diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2008-11-13 00:16:53 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2008-11-13 00:16:53 +0300 |
commit | bdfe7d89e2f1292644577972c716931b4ce3c6c3 (patch) | |
tree | d00eb50b749cb001e2b08272c91791e66740b05d /source/gameengine/Rasterizer/RAS_BucketManager.cpp | |
parent | 78a1c27c4a6abe0ed31ca93ad21910f3df04da56 (diff) | |
parent | 7e4db234cee71ead34ee81a12e27da4bd548eb4b (diff) |
Merge of trunk into blender 2.5:
svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r12987:17416
Issues:
* GHOST/X11 had conflicting changes. Some code was added in 2.5, which was
later added in trunk also, but reverted partially, specifically revision
16683. I have left out this reversion in the 2.5 branch since I think it is
needed there.
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=16683
* Scons had various conflicting changes, I decided to go with trunk version
for everything except priorities and some library renaming.
* In creator.c, there were various fixes and fixes for fixes related to the -w
-W and -p options. In 2.5 -w and -W is not coded yet, and -p is done
differently. Since this is changed so much, and I don't think those fixes
would be needed in 2.5, I've left them out.
* Also in creator.c: there was code for a python bugfix where the screen was not
initialized when running with -P. The code that initializes the screen there
I had to disable, that can't work in 2.5 anymore but left it commented as a
reminder.
Further I had to disable some new function calls. using src/ and python/, as
was done already in this branch, disabled function calls:
* bpath.c: error reporting
* BME_conversions.c: editmesh conversion functions.
* SHD_dynamic: disabled almost completely, there is no python/.
* KX_PythonInit.cpp and Ketsji/ build files: Mathutils is not there, disabled.
* text.c: clipboard copy call.
* object.c: OB_SUPPORT_MATERIAL.
* DerivedMesh.c and subsurf_ccg, stipple_quarttone.
Still to be done:
* Go over files and functions that were moved to a different location but could
still use changes that were done in trunk.
Diffstat (limited to 'source/gameengine/Rasterizer/RAS_BucketManager.cpp')
-rw-r--r-- | source/gameengine/Rasterizer/RAS_BucketManager.cpp | 268 |
1 files changed, 172 insertions, 96 deletions
diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.cpp b/source/gameengine/Rasterizer/RAS_BucketManager.cpp index 48e761cfc5a..f7938bb62e6 100644 --- a/source/gameengine/Rasterizer/RAS_BucketManager.cpp +++ b/source/gameengine/Rasterizer/RAS_BucketManager.cpp @@ -26,10 +26,6 @@ * ***** END GPL LICENSE BLOCK ***** */ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - #ifdef WIN32 // don't show these anoying STL warnings #pragma warning (disable:4786) @@ -39,156 +35,236 @@ #include "RAS_MaterialBucket.h" #include "STR_HashedString.h" #include "RAS_MeshObject.h" -#define KX_NUM_MATERIALBUCKETS 100 #include "RAS_IRasterizer.h" #include "RAS_IRenderTools.h" #include "RAS_BucketManager.h" +#include <algorithm> #include <set> -RAS_BucketManager::RAS_BucketManager() +/* sorting */ + +struct RAS_BucketManager::sortedmeshslot { +public: + MT_Scalar m_z; /* depth */ + RAS_MeshSlot *m_ms; /* mesh slot */ + RAS_MaterialBucket *m_bucket; /* buck mesh slot came from */ -} + sortedmeshslot() {} -RAS_BucketManager::~RAS_BucketManager() -{ - RAS_BucketManagerClearAll(); -} + void set(RAS_MeshSlot *ms, RAS_MaterialBucket *bucket, const MT_Vector3& pnorm) + { + // would be good to use the actual bounding box center instead + MT_Point3 pos(ms->m_OpenGLMatrix[12], ms->m_OpenGLMatrix[13], ms->m_OpenGLMatrix[14]); -/** - * struct alphamesh holds a mesh, (m_ms) it's depth, (m_z) and the bucket it came from (m_bucket.) - */ -struct RAS_BucketManager::alphamesh -{ -public: - MT_Scalar m_z; - RAS_MaterialBucket::T_MeshSlotList::iterator m_ms; - RAS_MaterialBucket *m_bucket; - alphamesh(MT_Scalar z, RAS_MaterialBucket::T_MeshSlotList::iterator &ms, RAS_MaterialBucket *bucket) : - m_z(z), - m_ms(ms), - m_bucket(bucket) - {} + m_z = MT_dot(pnorm, pos); + m_ms = ms; + m_bucket = bucket; + } }; struct RAS_BucketManager::backtofront { - bool operator()(const alphamesh &a, const alphamesh &b) + bool operator()(const sortedmeshslot &a, const sortedmeshslot &b) { - return a.m_z < b.m_z; + return (a.m_z < b.m_z) || (a.m_z == b.m_z && a.m_ms < b.m_ms); } }; - -void RAS_BucketManager::RenderAlphaBuckets( - const MT_Transform& cameratrans, RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools) +struct RAS_BucketManager::fronttoback { - BucketList::iterator bit; - std::multiset<alphamesh, backtofront> alphameshset; - RAS_MaterialBucket::T_MeshSlotList::iterator mit; - - /* Camera's near plane equation: cam_norm.dot(point) + cam_origin */ - const MT_Vector3 cam_norm(cameratrans.getBasis()[2]); - const MT_Scalar cam_origin = cameratrans.getOrigin()[2]; - for (bit = m_AlphaBuckets.begin(); bit != m_AlphaBuckets.end(); ++bit) + bool operator()(const sortedmeshslot &a, const sortedmeshslot &b) { - (*bit)->ClearScheduledPolygons(); - for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) - { - if ((*mit).m_bVisible) - { - MT_Point3 pos((*mit).m_OpenGLMatrix[12], (*mit).m_OpenGLMatrix[13], (*mit).m_OpenGLMatrix[14]); - alphameshset.insert(alphamesh(MT_dot(cam_norm, pos) + cam_origin, mit, *bit)); - } - } + return (a.m_z > b.m_z) || (a.m_z == b.m_z && a.m_ms > b.m_ms); } +}; + +/* bucket manager */ + +RAS_BucketManager::RAS_BucketManager() +{ + +} + +RAS_BucketManager::~RAS_BucketManager() +{ + BucketList::iterator it; + + for (it = m_SolidBuckets.begin(); it != m_SolidBuckets.end(); it++) + delete (*it); + + for (it = m_AlphaBuckets.begin(); it != m_AlphaBuckets.end(); it++) + delete(*it); - // It shouldn't be strictly necessary to disable depth writes; but - // it is needed for compatibility. + m_SolidBuckets.clear(); + m_AlphaBuckets.clear(); +} + +void RAS_BucketManager::OrderBuckets(const MT_Transform& cameratrans, BucketList& buckets, vector<sortedmeshslot>& slots, bool alpha) +{ + BucketList::iterator bit; + list<RAS_MeshSlot>::iterator mit; + size_t size = 0, i = 0; + + /* Camera's near plane equation: pnorm.dot(point) + pval, + * but we leave out pval since it's constant anyway */ + const MT_Vector3 pnorm(cameratrans.getBasis()[2]); + + for (bit = buckets.begin(); bit != buckets.end(); ++bit) + for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) + if (!mit->IsCulled()) + size++; + + slots.resize(size); + + for (bit = buckets.begin(); bit != buckets.end(); ++bit) + for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) + if (!mit->IsCulled()) + slots[i++].set(&*mit, *bit, pnorm); + + if(alpha) + sort(slots.begin(), slots.end(), backtofront()); + else + sort(slots.begin(), slots.end(), fronttoback()); +} + +void RAS_BucketManager::RenderAlphaBuckets( + const MT_Transform& cameratrans, RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools) +{ + vector<sortedmeshslot> slots; + vector<sortedmeshslot>::iterator sit; + + // Having depth masks disabled/enabled gives different artifacts in + // case no sorting is done or is done inexact. For compatibility, we + // disable it. rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_DISABLED); - int drawingmode; - std::multiset< alphamesh, backtofront>::iterator msit = alphameshset.begin(); - for (; msit != alphameshset.end(); ++msit) - { - while ((*msit).m_bucket->ActivateMaterial(cameratrans, rasty, rendertools, drawingmode)) - (*msit).m_bucket->RenderMeshSlot(cameratrans, rasty, rendertools, *(*msit).m_ms, drawingmode); - } + OrderBuckets(cameratrans, m_AlphaBuckets, slots, true); + for(sit=slots.begin(); sit!=slots.end(); ++sit) { + rendertools->SetClientObject(rasty, sit->m_ms->m_clientObj); + + while(sit->m_bucket->ActivateMaterial(cameratrans, rasty, rendertools)) + sit->m_bucket->RenderMeshSlot(cameratrans, rasty, rendertools, *(sit->m_ms)); + } + rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED); } -void RAS_BucketManager::Renderbuckets( +void RAS_BucketManager::RenderSolidBuckets( const MT_Transform& cameratrans, RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools) { - BucketList::iterator bucket; - - rasty->EnableTextures(false); + BucketList::iterator bit; + list<RAS_MeshSlot>::iterator mit; + rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED); - - // beginning each frame, clear (texture/material) caching information - rasty->ClearCachingInfo(); - RAS_MaterialBucket::StartFrame(); - for (bucket = m_MaterialBuckets.begin(); bucket != m_MaterialBuckets.end(); ++bucket) - { - (*bucket)->ClearScheduledPolygons(); + for (bit = m_SolidBuckets.begin(); bit != m_SolidBuckets.end(); ++bit) { + for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) { + if (mit->IsCulled()) + continue; + + rendertools->SetClientObject(rasty, mit->m_clientObj); + + while ((*bit)->ActivateMaterial(cameratrans, rasty, rendertools)) + (*bit)->RenderMeshSlot(cameratrans, rasty, rendertools, *mit); + } } - for (bucket = m_MaterialBuckets.begin(); bucket != m_MaterialBuckets.end(); ++bucket) - { - RAS_IPolyMaterial *tmp = (*bucket)->GetPolyMaterial(); - if(tmp->IsZSort() || tmp->GetFlag() &RAS_FORCEALPHA ) - rasty->SetAlphaTest(true); - else - rasty->SetAlphaTest(false); + /* this code draws meshes order front-to-back instead to reduce overdraw. + * it turned out slower due to much material state switching, a more clever + * algorithm might do better. */ +#if 0 + vector<sortedmeshslot> slots; + vector<sortedmeshslot>::iterator sit; + + OrderBuckets(cameratrans, m_SolidBuckets, slots, false); + + for(sit=slots.begin(); sit!=slots.end(); ++sit) { + rendertools->SetClientObject(rasty, sit->m_ms->m_clientObj); - (*bucket)->Render(cameratrans,rasty,rendertools); + while(sit->m_bucket->ActivateMaterial(cameratrans, rasty, rendertools)) + sit->m_bucket->RenderMeshSlot(cameratrans, rasty, rendertools, *(sit->m_ms)); } - rasty->SetAlphaTest(false); +#endif +} + +void RAS_BucketManager::Renderbuckets( + const MT_Transform& cameratrans, RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools) +{ + /* beginning each frame, clear (texture/material) caching information */ + rasty->ClearCachingInfo(); + RenderSolidBuckets(cameratrans, rasty, rendertools); RenderAlphaBuckets(cameratrans, rasty, rendertools); - RAS_MaterialBucket::EndFrame(); + + rendertools->SetClientObject(rasty, NULL); } -RAS_MaterialBucket* RAS_BucketManager::RAS_BucketManagerFindBucket(RAS_IPolyMaterial * material) +RAS_MaterialBucket* RAS_BucketManager::FindBucket(RAS_IPolyMaterial * material, bool &bucketCreated) { BucketList::iterator it; - for (it = m_MaterialBuckets.begin(); it != m_MaterialBuckets.end(); it++) - { + + bucketCreated = false; + + for (it = m_SolidBuckets.begin(); it != m_SolidBuckets.end(); it++) if (*(*it)->GetPolyMaterial() == *material) return *it; - } for (it = m_AlphaBuckets.begin(); it != m_AlphaBuckets.end(); it++) - { if (*(*it)->GetPolyMaterial() == *material) return *it; - } RAS_MaterialBucket *bucket = new RAS_MaterialBucket(material); - if (bucket->IsTransparant()) + bucketCreated = true; + + if (bucket->IsAlpha()) m_AlphaBuckets.push_back(bucket); else - m_MaterialBuckets.push_back(bucket); + m_SolidBuckets.push_back(bucket); return bucket; } -void RAS_BucketManager::RAS_BucketManagerClearAll() +void RAS_BucketManager::OptimizeBuckets(MT_Scalar distance) { - BucketList::iterator it; - for (it = m_MaterialBuckets.begin(); it != m_MaterialBuckets.end(); it++) - { - delete (*it); - } - for (it = m_AlphaBuckets.begin(); it != m_AlphaBuckets.end(); it++) - { - delete(*it); + BucketList::iterator bit; + + distance = 10.0; + + for (bit = m_SolidBuckets.begin(); bit != m_SolidBuckets.end(); ++bit) + (*bit)->Optimize(distance); + for (bit = m_AlphaBuckets.begin(); bit != m_AlphaBuckets.end(); ++bit) + (*bit)->Optimize(distance); +} + +void RAS_BucketManager::ReleaseDisplayLists(RAS_IPolyMaterial *mat) +{ + BucketList::iterator bit; + list<RAS_MeshSlot>::iterator mit; + + for (bit = m_SolidBuckets.begin(); bit != m_SolidBuckets.end(); ++bit) { + if (mat == NULL || (mat == (*bit)->GetPolyMaterial())) { + for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) { + if(mit->m_DisplayList) { + mit->m_DisplayList->Release(); + mit->m_DisplayList = NULL; + } + } + } } - m_MaterialBuckets.clear(); - m_AlphaBuckets.clear(); + for (bit = m_AlphaBuckets.begin(); bit != m_AlphaBuckets.end(); ++bit) { + if (mat == NULL || (mat == (*bit)->GetPolyMaterial())) { + for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) { + if(mit->m_DisplayList) { + mit->m_DisplayList->Release(); + mit->m_DisplayList = NULL; + } + } + } + } } + |