From e78ef29a593857d87b0c35c211d082c8caa80f7b Mon Sep 17 00:00:00 2001 From: Kester Maddock Date: Fri, 21 May 2004 08:55:12 +0000 Subject: Depth sorting for alpha mesh objects. - Mesh Objects are sorted by depth (based on object centre.) Using object centre means the user has control over the sort. - Polygons are not sorted. - Polygons are not split. - O(nlog(n)) --- source/gameengine/Rasterizer/RAS_BucketManager.cpp | 62 +++++--- source/gameengine/Rasterizer/RAS_BucketManager.h | 33 +++- .../gameengine/Rasterizer/RAS_MaterialBucket.cpp | 167 ++++++++++++--------- source/gameengine/Rasterizer/RAS_MaterialBucket.h | 25 ++- 4 files changed, 187 insertions(+), 100 deletions(-) diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.cpp b/source/gameengine/Rasterizer/RAS_BucketManager.cpp index 9b8f455d518..8a4ffb3a668 100644 --- a/source/gameengine/Rasterizer/RAS_BucketManager.cpp +++ b/source/gameengine/Rasterizer/RAS_BucketManager.cpp @@ -48,7 +48,7 @@ #include "RAS_BucketManager.h" - +#include RAS_BucketManager::RAS_BucketManager() { @@ -61,10 +61,45 @@ RAS_BucketManager::~RAS_BucketManager() } + +void RAS_BucketManager::RenderAlphaBuckets( + const MT_Transform& cameratrans, RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools) +{ + BucketList::iterator bit; + std::multiset alphameshset; + RAS_MaterialBucket::T_MeshSlotList::iterator mit; + + for (bit = m_AlphaBuckets.begin(); bit != m_AlphaBuckets.end(); ++bit) + { + (*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(cameratrans.getBasis()[2], pos) + cameratrans.getOrigin()[2], mit, *bit)); + } + } + } + + // It shouldn't be strictly necessary to disable depth writes; but + // it is needed for compatibility. + rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_DISABLED); + + std::multiset< alphamesh, backtofront>::iterator msit = alphameshset.begin(); + for (; msit != alphameshset.end(); ++msit) + { + (*msit).m_bucket->RenderMeshSlot(cameratrans, rasty, rendertools, *(*msit).m_ms, + (*msit).m_bucket->ActivateMaterial(cameratrans, rasty, rendertools)); + } + + rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED); +} + void RAS_BucketManager::Renderbuckets( const MT_Transform& cameratrans, RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools) { - std::vector::iterator bucket; + BucketList::iterator bucket; rasty->EnableTextures(false); rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED); @@ -73,33 +108,22 @@ void RAS_BucketManager::Renderbuckets( rasty->ClearCachingInfo(); RAS_MaterialBucket::StartFrame(); - for (bucket = m_MaterialBuckets.begin(); bucket != m_MaterialBuckets.end(); bucket++) + for (bucket = m_MaterialBuckets.begin(); bucket != m_MaterialBuckets.end(); ++bucket) { (*bucket)->ClearScheduledPolygons(); } - for (bucket = m_AlphaBuckets.begin(); bucket != m_AlphaBuckets.end(); bucket++) - { - (*bucket)->ClearScheduledPolygons(); - } - - for (bucket = m_MaterialBuckets.begin(); bucket != m_MaterialBuckets.end(); bucket++) - (*bucket)->Render(cameratrans,rasty,rendertools); - rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_DISABLED); - - for (bucket = m_AlphaBuckets.begin(); bucket != m_AlphaBuckets.end(); bucket++) - { + for (bucket = m_MaterialBuckets.begin(); bucket != m_MaterialBuckets.end(); ++bucket) (*bucket)->Render(cameratrans,rasty,rendertools); - } - - rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED); + + RenderAlphaBuckets(cameratrans, rasty, rendertools); RAS_MaterialBucket::EndFrame(); } RAS_MaterialBucket* RAS_BucketManager::RAS_BucketManagerFindBucket(RAS_IPolyMaterial * material) { - std::vector::iterator it; + BucketList::iterator it; for (it = m_MaterialBuckets.begin(); it != m_MaterialBuckets.end(); it++) { if (*(*it)->GetPolyMaterial() == *material) @@ -123,7 +147,7 @@ RAS_MaterialBucket* RAS_BucketManager::RAS_BucketManagerFindBucket(RAS_IPolyMate void RAS_BucketManager::RAS_BucketManagerClearAll() { - std::vector::iterator it; + BucketList::iterator it; for (it = m_MaterialBuckets.begin(); it != m_MaterialBuckets.end(); it++) { delete (*it); diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.h b/source/gameengine/Rasterizer/RAS_BucketManager.h index 834ae574bbc..9d7c5a4b05a 100644 --- a/source/gameengine/Rasterizer/RAS_BucketManager.h +++ b/source/gameengine/Rasterizer/RAS_BucketManager.h @@ -43,13 +43,42 @@ class RAS_BucketManager { //GEN_Map m_MaterialBuckets; - std::vector m_MaterialBuckets; - std::vector m_AlphaBuckets; + + typedef std::vector BucketList; + BucketList m_MaterialBuckets; + BucketList m_AlphaBuckets; + + /** + * struct alphamesh holds a mesh, (m_ms) it's depth, (m_z) and the bucket it came from (m_bucket.) + */ + struct 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) + {} + }; + + struct backtofront + { + bool operator()(const alphamesh &a, const alphamesh &b) + { + return a.m_z < b.m_z; + } + }; + public: RAS_BucketManager(); virtual ~RAS_BucketManager(); + void RenderAlphaBuckets(const MT_Transform& cameratrans, + RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools); void Renderbuckets(const MT_Transform & cameratrans, RAS_IRasterizer* rasty, class RAS_IRenderTools* rendertools); diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp index 5f1766be0e4..faaeafb0d05 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp @@ -154,28 +154,28 @@ void RAS_MaterialBucket::EndFrame() { } +unsigned int RAS_MaterialBucket::NumMeshSlots() +{ + return m_meshSlots.size(); +} +RAS_MaterialBucket::T_MeshSlotList::iterator RAS_MaterialBucket::msBegin() +{ + return m_meshSlots.begin(); +} -void RAS_MaterialBucket::Render(const MT_Transform& cameratrans, - RAS_IRasterizer* rasty, - RAS_IRenderTools* rendertools) +RAS_MaterialBucket::T_MeshSlotList::iterator RAS_MaterialBucket::msEnd() { + return m_meshSlots.end(); +} - if (m_meshSlots.begin()== m_meshSlots.end()) - return; - +int RAS_MaterialBucket::ActivateMaterial(const MT_Transform& cameratrans, RAS_IRasterizer* rasty, + RAS_IRenderTools *rendertools) +{ rendertools->SetViewMat(cameratrans); rasty->SetMaterial(*m_material); - if (m_meshSlots.size() >0) - { - - rendertools->SetClientObject((*m_meshSlots.begin()).m_clientObj); - } - - //printf("RAS_MatBucket::Render: %d m_meshSlots\n", m_meshSlots.size()); - bool dolights = m_material->GetDrawingMode()&16; if ((rasty->GetDrawingMode() <= RAS_IRasterizer::KX_SOLID) || !dolights) @@ -187,68 +187,91 @@ void RAS_MaterialBucket::Render(const MT_Transform& cameratrans, bool bUseLights = rendertools->ProcessLighting(m_material->GetLightLayer()); } - int drawmode = (rasty->GetDrawingMode() < RAS_IRasterizer::KX_SOLID ? + return (rasty->GetDrawingMode() < RAS_IRasterizer::KX_SOLID ? 1: (m_material->UsesTriangles() ? 0 : 2)); +} + +void RAS_MaterialBucket::RenderMeshSlot(const MT_Transform& cameratrans, RAS_IRasterizer* rasty, + RAS_IRenderTools* rendertools, const KX_MeshSlot &ms, int drawmode) +{ + if (!ms.m_bVisible) + return; + + rendertools->SetClientObject(ms.m_clientObj); + + /* __NLA Do the deformation */ + if (ms.m_pDeformer) + ms.m_pDeformer->Apply(m_material); + /* End __NLA */ + + rendertools->PushMatrix(); + rendertools->applyTransform(rasty,ms.m_OpenGLMatrix,m_material->GetDrawingMode()); + + // Use the text-specific IndexPrimitives for text faces + if (m_material->GetDrawingMode() & RAS_IRasterizer::RAS_RENDER_3DPOLYGON_TEXT) + { + rasty->IndexPrimitives_3DText( + ms.m_mesh->GetVertexCache(m_material), + ms.m_mesh->GetIndexCache(m_material), + drawmode, + m_material, + rendertools, // needed for textprinting on polys + ms.m_bObjectColor, + ms.m_RGBAcolor); + + } + // Use the (slower) IndexPrimitives_Ex which can recalc face normals & such + // for deformed objects - eventually should be extended to recalc ALL normals + else if (ms.m_pDeformer){ + rasty->IndexPrimitives_Ex( + ms.m_mesh->GetVertexCache(m_material), + ms.m_mesh->GetIndexCache(m_material), + drawmode, + m_material, + rendertools, // needed for textprinting on polys + ms.m_bObjectColor, + ms.m_RGBAcolor + ); + } + // Use the normal IndexPrimitives + else + { + rasty->IndexPrimitives( + ms.m_mesh->GetVertexCache(m_material), + ms.m_mesh->GetIndexCache(m_material), + drawmode, + m_material, + rendertools, // needed for textprinting on polys + ms.m_bObjectColor, + ms.m_RGBAcolor + ); + } + + rendertools->PopMatrix(); +} + +void RAS_MaterialBucket::Render(const MT_Transform& cameratrans, + RAS_IRasterizer* rasty, + RAS_IRenderTools* rendertools) +{ + if (m_meshSlots.begin()== m_meshSlots.end()) + return; + + rendertools->SetViewMat(cameratrans); + + rasty->SetMaterial(*m_material); + + if (m_meshSlots.size() >0) + { + rendertools->SetClientObject((*m_meshSlots.begin()).m_clientObj); + } + + int drawmode = ActivateMaterial(cameratrans, rasty, rendertools); for (T_MeshSlotList::const_iterator it = m_meshSlots.begin(); - ! (it == m_meshSlots.end());it++) + ! (it == m_meshSlots.end()); ++it) { - //printf("RAS_MatBucket::Render: (%p) %s MeshSlot %s\n", this, it->m_mesh->m_class?"Skin":"Mesh", (const char *)(*it).m_mesh->GetName()); - if ((*it).m_bVisible) - { - rendertools->SetClientObject((*it).m_clientObj); - - /* __NLA Do the deformation */ - if ((*it).m_pDeformer) - (*it).m_pDeformer->Apply(m_material); - /* End __NLA */ - - rendertools->PushMatrix(); - rendertools->applyTransform(rasty,(*it).m_OpenGLMatrix,m_material->GetDrawingMode()); - - // Use the text-specific IndexPrimitives for text faces - if (m_material->GetDrawingMode() & RAS_IRasterizer::RAS_RENDER_3DPOLYGON_TEXT) - { - rasty->IndexPrimitives_3DText( - (*it).m_mesh->GetVertexCache(m_material), - (*it).m_mesh->GetIndexCache(m_material), - drawmode, - m_material, - rendertools, // needed for textprinting on polys - (*it).m_bObjectColor, - (*it).m_RGBAcolor); - - } - // Use the (slower) IndexPrimitives_Ex which can recalc face normals & such - // for deformed objects - eventually should be extended to recalc ALL normals - else if ((*it).m_pDeformer){ - rasty->IndexPrimitives_Ex( - (*it).m_mesh->GetVertexCache(m_material), - (*it).m_mesh->GetIndexCache(m_material), - drawmode, - m_material, - rendertools, // needed for textprinting on polys - (*it).m_bObjectColor, - (*it).m_RGBAcolor - ); - } - // Use the normal IndexPrimitives - else - { - rasty->IndexPrimitives( - (*it).m_mesh->GetVertexCache(m_material), - (*it).m_mesh->GetIndexCache(m_material), - drawmode, - m_material, - rendertools, // needed for textprinting on polys - (*it).m_bObjectColor, - (*it).m_RGBAcolor - ); - } - - rendertools->PopMatrix(); - } - //printf("gets here\n"); + RenderMeshSlot(cameratrans, rasty, rendertools, *it, drawmode); } } diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.h b/source/gameengine/Rasterizer/RAS_MaterialBucket.h index 51174c12335..28185dabca6 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.h +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.h @@ -95,15 +95,9 @@ inline bool operator <( const KX_MeshSlot& rhs,const KX_MeshSlot& lhs) */ class RAS_MaterialBucket { +public: typedef std::set T_MeshSlotList; - T_MeshSlotList m_meshSlots; - bool m_bScheduled; - bool m_bModified; - RAS_IPolyMaterial* m_material; - double* m_pOGLMatrix; - -public: RAS_MaterialBucket(RAS_IPolyMaterial* mat); virtual ~RAS_MaterialBucket() {} @@ -127,6 +121,15 @@ public: bool color, const MT_Vector4& rgbavec); + void RenderMeshSlot(const MT_Transform& cameratrans, RAS_IRasterizer* rasty, + RAS_IRenderTools* rendertools, const KX_MeshSlot &ms, int drawmode); + int ActivateMaterial(const MT_Transform& cameratrans, RAS_IRasterizer* rasty, + RAS_IRenderTools *rendertools); + + unsigned int NumMeshSlots(); + T_MeshSlotList::iterator msBegin(); + T_MeshSlotList::iterator msEnd(); + struct less { bool operator()(const RAS_MaterialBucket* x, const RAS_MaterialBucket* y) const @@ -136,6 +139,14 @@ public: }; typedef set Set; +private: + + T_MeshSlotList m_meshSlots; + bool m_bScheduled; + bool m_bModified; + RAS_IPolyMaterial* m_material; + double* m_pOGLMatrix; + }; #endif //__KX_BUCKET -- cgit v1.2.3