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))
This commit is contained in:
Kester Maddock 2004-05-21 08:55:12 +00:00
parent 2a622e35d4
commit e78ef29a59
4 changed files with 189 additions and 102 deletions

@ -48,7 +48,7 @@
#include "RAS_BucketManager.h" #include "RAS_BucketManager.h"
#include <set>
RAS_BucketManager::RAS_BucketManager() 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<alphamesh, backtofront> 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( void RAS_BucketManager::Renderbuckets(
const MT_Transform& cameratrans, RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools) const MT_Transform& cameratrans, RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools)
{ {
std::vector<RAS_MaterialBucket*>::iterator bucket; BucketList::iterator bucket;
rasty->EnableTextures(false); rasty->EnableTextures(false);
rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED); rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED);
@ -73,33 +108,22 @@ void RAS_BucketManager::Renderbuckets(
rasty->ClearCachingInfo(); rasty->ClearCachingInfo();
RAS_MaterialBucket::StartFrame(); 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(); (*bucket)->ClearScheduledPolygons();
} }
for (bucket = m_AlphaBuckets.begin(); bucket != m_AlphaBuckets.end(); bucket++)
{ for (bucket = m_MaterialBuckets.begin(); bucket != m_MaterialBuckets.end(); ++bucket)
(*bucket)->ClearScheduledPolygons();
}
for (bucket = m_MaterialBuckets.begin(); bucket != m_MaterialBuckets.end(); bucket++)
(*bucket)->Render(cameratrans,rasty,rendertools); (*bucket)->Render(cameratrans,rasty,rendertools);
rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_DISABLED); RenderAlphaBuckets(cameratrans, rasty, rendertools);
for (bucket = m_AlphaBuckets.begin(); bucket != m_AlphaBuckets.end(); bucket++)
{
(*bucket)->Render(cameratrans,rasty,rendertools);
}
rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED);
RAS_MaterialBucket::EndFrame(); RAS_MaterialBucket::EndFrame();
} }
RAS_MaterialBucket* RAS_BucketManager::RAS_BucketManagerFindBucket(RAS_IPolyMaterial * material) RAS_MaterialBucket* RAS_BucketManager::RAS_BucketManagerFindBucket(RAS_IPolyMaterial * material)
{ {
std::vector<RAS_MaterialBucket*>::iterator it; BucketList::iterator it;
for (it = m_MaterialBuckets.begin(); it != m_MaterialBuckets.end(); it++) for (it = m_MaterialBuckets.begin(); it != m_MaterialBuckets.end(); it++)
{ {
if (*(*it)->GetPolyMaterial() == *material) if (*(*it)->GetPolyMaterial() == *material)
@ -123,7 +147,7 @@ RAS_MaterialBucket* RAS_BucketManager::RAS_BucketManagerFindBucket(RAS_IPolyMate
void RAS_BucketManager::RAS_BucketManagerClearAll() void RAS_BucketManager::RAS_BucketManagerClearAll()
{ {
std::vector<RAS_MaterialBucket*>::iterator it; BucketList::iterator it;
for (it = m_MaterialBuckets.begin(); it != m_MaterialBuckets.end(); it++) for (it = m_MaterialBuckets.begin(); it != m_MaterialBuckets.end(); it++)
{ {
delete (*it); delete (*it);

@ -43,13 +43,42 @@
class RAS_BucketManager class RAS_BucketManager
{ {
//GEN_Map<class RAS_IPolyMaterial,class RAS_MaterialBucket*> m_MaterialBuckets; //GEN_Map<class RAS_IPolyMaterial,class RAS_MaterialBucket*> m_MaterialBuckets;
std::vector<class RAS_MaterialBucket*> m_MaterialBuckets;
std::vector<class RAS_MaterialBucket*> m_AlphaBuckets; typedef std::vector<class RAS_MaterialBucket*> 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: public:
RAS_BucketManager(); RAS_BucketManager();
virtual ~RAS_BucketManager(); virtual ~RAS_BucketManager();
void RenderAlphaBuckets(const MT_Transform& cameratrans,
RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools);
void Renderbuckets(const MT_Transform & cameratrans, void Renderbuckets(const MT_Transform & cameratrans,
RAS_IRasterizer* rasty, RAS_IRasterizer* rasty,
class RAS_IRenderTools* rendertools); class RAS_IRenderTools* rendertools);

@ -154,28 +154,28 @@ void RAS_MaterialBucket::EndFrame()
{ {
} }
unsigned int RAS_MaterialBucket::NumMeshSlots()
void RAS_MaterialBucket::Render(const MT_Transform& cameratrans,
RAS_IRasterizer* rasty,
RAS_IRenderTools* rendertools)
{ {
return m_meshSlots.size();
}
if (m_meshSlots.begin()== m_meshSlots.end()) RAS_MaterialBucket::T_MeshSlotList::iterator RAS_MaterialBucket::msBegin()
return; {
return m_meshSlots.begin();
}
RAS_MaterialBucket::T_MeshSlotList::iterator RAS_MaterialBucket::msEnd()
{
return m_meshSlots.end();
}
int RAS_MaterialBucket::ActivateMaterial(const MT_Transform& cameratrans, RAS_IRasterizer* rasty,
RAS_IRenderTools *rendertools)
{
rendertools->SetViewMat(cameratrans); rendertools->SetViewMat(cameratrans);
rasty->SetMaterial(*m_material); 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; bool dolights = m_material->GetDrawingMode()&16;
if ((rasty->GetDrawingMode() <= RAS_IRasterizer::KX_SOLID) || !dolights) 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()); 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)); 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(); 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()); RenderMeshSlot(cameratrans, rasty, rendertools, *it, drawmode);
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");
} }
} }

@ -95,15 +95,9 @@ inline bool operator <( const KX_MeshSlot& rhs,const KX_MeshSlot& lhs)
*/ */
class RAS_MaterialBucket class RAS_MaterialBucket
{ {
public:
typedef std::set<KX_MeshSlot> T_MeshSlotList; typedef std::set<KX_MeshSlot> 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); RAS_MaterialBucket(RAS_IPolyMaterial* mat);
virtual ~RAS_MaterialBucket() {} virtual ~RAS_MaterialBucket() {}
@ -127,6 +121,15 @@ public:
bool color, bool color,
const MT_Vector4& rgbavec); 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 struct less
{ {
bool operator()(const RAS_MaterialBucket* x, const RAS_MaterialBucket* y) const bool operator()(const RAS_MaterialBucket* x, const RAS_MaterialBucket* y) const
@ -136,6 +139,14 @@ public:
}; };
typedef set<RAS_MaterialBucket*, less> Set; typedef set<RAS_MaterialBucket*, less> Set;
private:
T_MeshSlotList m_meshSlots;
bool m_bScheduled;
bool m_bModified;
RAS_IPolyMaterial* m_material;
double* m_pOGLMatrix;
}; };
#endif //__KX_BUCKET #endif //__KX_BUCKET