Faster mesh sorting.

This commit is contained in:
Leonardo Zide 2017-03-19 22:59:55 -07:00
parent 8023f868cd
commit 50b9ab1984
4 changed files with 57 additions and 42 deletions

View file

@ -20,42 +20,51 @@
lcProgram lcContext::mPrograms[LC_NUM_MATERIALS]; lcProgram lcContext::mPrograms[LC_NUM_MATERIALS];
static int lcOpaqueRenderMeshCompare(const void* Elem1, const void* Elem2) struct lcOpaqueMeshSorter
{ {
lcRenderMesh* Mesh1 = (lcRenderMesh*)Elem1; lcOpaqueMeshSorter(lcScene* Scene)
lcRenderMesh* Mesh2 = (lcRenderMesh*)Elem2; : mScene(Scene)
{
}
if (Mesh1->Mesh < Mesh2->Mesh) bool operator() (int Index1, int Index2)
return -1; {
lcRenderMesh& Mesh1 = mScene->mRenderMeshes[Index1];
lcRenderMesh& Mesh2 = mScene->mRenderMeshes[Index2];
if (Mesh1->Mesh > Mesh2->Mesh) return Mesh1.Mesh < Mesh2.Mesh;
return 1; }
return 0; lcScene* mScene;
} };
static int lcTranslucentRenderMeshCompare(const void* Elem1, const void* Elem2) struct lcTranslucentMeshSorter
{ {
lcRenderMesh* Mesh1 = (lcRenderMesh*)Elem1; lcTranslucentMeshSorter(lcScene* Scene)
lcRenderMesh* Mesh2 = (lcRenderMesh*)Elem2; : mScene(Scene)
{
}
if (Mesh1->Distance < Mesh2->Distance) bool operator() (int Index1, int Index2)
return 1; {
lcRenderMesh& Mesh1 = mScene->mRenderMeshes[Index1];
lcRenderMesh& Mesh2 = mScene->mRenderMeshes[Index2];
if (Mesh1->Distance > Mesh2->Distance) return Mesh1.Distance < Mesh2.Distance;
return -1; }
return 0; lcScene* mScene;
} };
lcScene::lcScene() lcScene::lcScene()
: mOpaqueMeshes(0, 1024), mTranslucentMeshes(0, 1024), mInterfaceObjects(0, 1024) : mRenderMeshes(0, 1024), mOpaqueMeshes(0, 1024), mTranslucentMeshes(0, 1024), mInterfaceObjects(0, 1024)
{ {
} }
void lcScene::Begin(const lcMatrix44& ViewMatrix) void lcScene::Begin(const lcMatrix44& ViewMatrix)
{ {
mViewMatrix = ViewMatrix; mViewMatrix = ViewMatrix;
mRenderMeshes.RemoveAll();
mOpaqueMeshes.RemoveAll(); mOpaqueMeshes.RemoveAll();
mTranslucentMeshes.RemoveAll(); mTranslucentMeshes.RemoveAll();
mInterfaceObjects.RemoveAll(); mInterfaceObjects.RemoveAll();
@ -63,8 +72,8 @@ void lcScene::Begin(const lcMatrix44& ViewMatrix)
void lcScene::End() void lcScene::End()
{ {
qsort(&mOpaqueMeshes[0], mOpaqueMeshes.GetSize(), sizeof(mOpaqueMeshes[0]), lcOpaqueRenderMeshCompare); std::sort(&mOpaqueMeshes[0], &mOpaqueMeshes[0] + mOpaqueMeshes.GetSize(), lcOpaqueMeshSorter(this));
qsort(&mTranslucentMeshes[0], mTranslucentMeshes.GetSize(), sizeof(mTranslucentMeshes[0]), lcTranslucentRenderMeshCompare); std::sort(&mTranslucentMeshes[0], &mTranslucentMeshes[0] + mTranslucentMeshes.GetSize(), lcTranslucentMeshSorter(this));
} }
lcContext::lcContext() lcContext::lcContext()
@ -1218,15 +1227,15 @@ void lcContext::DrawMeshSection(lcMesh* Mesh, lcMeshSection* Section)
} }
} }
void lcContext::DrawOpaqueMeshes(const lcArray<lcRenderMesh>& OpaqueMeshes) void lcContext::DrawOpaqueMeshes(const lcScene& Scene)
{ {
bool DrawLines = lcGetPreferences().mDrawEdgeLines; bool DrawLines = lcGetPreferences().mDrawEdgeLines;
const lcArray<lcRenderMesh>& RenderMeshes = Scene.mRenderMeshes;
lcGetPiecesLibrary()->UpdateBuffers(this); // TODO: find a better place for this update const lcArray<int>& OpaqueMeshes = Scene.mOpaqueMeshes;
for (int MeshIdx = 0; MeshIdx < OpaqueMeshes.GetSize(); MeshIdx++) for (int MeshIdx = 0; MeshIdx < OpaqueMeshes.GetSize(); MeshIdx++)
{ {
const lcRenderMesh& RenderMesh = OpaqueMeshes[MeshIdx]; const lcRenderMesh& RenderMesh = RenderMeshes[OpaqueMeshes[MeshIdx]];
lcMesh* Mesh = RenderMesh.Mesh; lcMesh* Mesh = RenderMesh.Mesh;
int LodIndex = RenderMesh.LodIndex; int LodIndex = RenderMesh.LodIndex;
@ -1311,8 +1320,11 @@ void lcContext::DrawOpaqueMeshes(const lcArray<lcRenderMesh>& OpaqueMeshes)
} }
} }
void lcContext::DrawTranslucentMeshes(const lcArray<lcRenderMesh>& TranslucentMeshes) void lcContext::DrawTranslucentMeshes(const lcScene& Scene)
{ {
const lcArray<lcRenderMesh>& RenderMeshes = Scene.mRenderMeshes;
const lcArray<int>& TranslucentMeshes = Scene.mTranslucentMeshes;
if (TranslucentMeshes.IsEmpty()) if (TranslucentMeshes.IsEmpty())
return; return;
@ -1322,7 +1334,7 @@ void lcContext::DrawTranslucentMeshes(const lcArray<lcRenderMesh>& TranslucentMe
for (int MeshIdx = 0; MeshIdx < TranslucentMeshes.GetSize(); MeshIdx++) for (int MeshIdx = 0; MeshIdx < TranslucentMeshes.GetSize(); MeshIdx++)
{ {
const lcRenderMesh& RenderMesh = TranslucentMeshes[MeshIdx]; const lcRenderMesh& RenderMesh = RenderMeshes[TranslucentMeshes[MeshIdx]];
lcMesh* Mesh = RenderMesh.Mesh; lcMesh* Mesh = RenderMesh.Mesh;
int LodIndex = RenderMesh.LodIndex; int LodIndex = RenderMesh.LodIndex;
@ -1368,8 +1380,10 @@ void lcContext::DrawTranslucentMeshes(const lcArray<lcRenderMesh>& TranslucentMe
void lcContext::DrawScene(const lcScene& Scene) void lcContext::DrawScene(const lcScene& Scene)
{ {
DrawOpaqueMeshes(Scene.mOpaqueMeshes); lcGetPiecesLibrary()->UpdateBuffers(this); // TODO: find a better place for this update
DrawTranslucentMeshes(Scene.mTranslucentMeshes);
DrawOpaqueMeshes(Scene);
DrawTranslucentMeshes(Scene);
} }
void lcContext::DrawInterfaceObjects(const lcArray<const lcObject*>& InterfaceObjects) void lcContext::DrawInterfaceObjects(const lcArray<const lcObject*>& InterfaceObjects)

View file

@ -15,8 +15,9 @@ public:
void End(); void End();
lcMatrix44 mViewMatrix; lcMatrix44 mViewMatrix;
lcArray<lcRenderMesh> mOpaqueMeshes; lcArray<lcRenderMesh> mRenderMeshes;
lcArray<lcRenderMesh> mTranslucentMeshes; lcArray<int> mOpaqueMeshes;
lcArray<int> mTranslucentMeshes;
lcArray<const lcObject*> mInterfaceObjects; lcArray<const lcObject*> mInterfaceObjects;
}; };
@ -176,8 +177,8 @@ protected:
void FlushState(); void FlushState();
void DrawMeshSection(lcMesh* Mesh, lcMeshSection* Section); void DrawMeshSection(lcMesh* Mesh, lcMeshSection* Section);
void DrawOpaqueMeshes(const lcArray<lcRenderMesh>& OpaqueMeshes); void DrawOpaqueMeshes(const lcScene& Scene);
void DrawTranslucentMeshes(const lcArray<lcRenderMesh>& TranslucentMeshes); void DrawTranslucentMeshes(const lcScene& Scene);
GLuint mVertexBufferObject; GLuint mVertexBufferObject;
GLuint mIndexBufferObject; GLuint mIndexBufferObject;

View file

@ -644,7 +644,7 @@ void lcPiece::AddRenderMeshes(lcScene& Scene, bool DrawInterface) const
mPieceInfo->AddRenderMeshes(Scene, mModelWorld, mColorIndex, Focused, Selected); mPieceInfo->AddRenderMeshes(Scene, mModelWorld, mColorIndex, Focused, Selected);
else else
{ {
lcRenderMesh RenderMesh; lcRenderMesh& RenderMesh = Scene.mRenderMeshes.Add();
RenderMesh.WorldMatrix = mModelWorld; RenderMesh.WorldMatrix = mModelWorld;
RenderMesh.Mesh = mMesh; RenderMesh.Mesh = mMesh;
@ -656,10 +656,10 @@ void lcPiece::AddRenderMeshes(lcScene& Scene, bool DrawInterface) const
bool Translucent = lcIsColorTranslucent(mColorIndex); bool Translucent = lcIsColorTranslucent(mColorIndex);
if ((mPieceInfo->mFlags & (LC_PIECE_HAS_SOLID | LC_PIECE_HAS_LINES)) || ((mPieceInfo->mFlags & LC_PIECE_HAS_DEFAULT) && !Translucent)) if ((mPieceInfo->mFlags & (LC_PIECE_HAS_SOLID | LC_PIECE_HAS_LINES)) || ((mPieceInfo->mFlags & LC_PIECE_HAS_DEFAULT) && !Translucent))
Scene.mOpaqueMeshes.Add(RenderMesh); Scene.mOpaqueMeshes.Add(Scene.mRenderMeshes.GetSize() - 1);
if ((mPieceInfo->mFlags & LC_PIECE_HAS_TRANSLUCENT) || ((mPieceInfo->mFlags & LC_PIECE_HAS_DEFAULT) && Translucent)) if ((mPieceInfo->mFlags & LC_PIECE_HAS_TRANSLUCENT) || ((mPieceInfo->mFlags & LC_PIECE_HAS_DEFAULT) && Translucent))
Scene.mTranslucentMeshes.Add(RenderMesh); Scene.mTranslucentMeshes.Add(Scene.mRenderMeshes.GetSize() - 1);
} }
if (Selected) if (Selected)

View file

@ -313,7 +313,7 @@ void PieceInfo::AddRenderMesh(lcScene& Scene)
if (!mMesh) if (!mMesh)
return; return;
lcRenderMesh RenderMesh; lcRenderMesh& RenderMesh = Scene.mRenderMeshes.Add();
RenderMesh.WorldMatrix = lcMatrix44Identity(); RenderMesh.WorldMatrix = lcMatrix44Identity();
RenderMesh.Mesh = mMesh; RenderMesh.Mesh = mMesh;
@ -323,17 +323,17 @@ void PieceInfo::AddRenderMesh(lcScene& Scene)
RenderMesh.LodIndex = mMesh->GetLodIndex(RenderMesh.Distance); RenderMesh.LodIndex = mMesh->GetLodIndex(RenderMesh.Distance);
if (mFlags & (LC_PIECE_HAS_SOLID | LC_PIECE_HAS_DEFAULT | LC_PIECE_HAS_LINES)) if (mFlags & (LC_PIECE_HAS_SOLID | LC_PIECE_HAS_DEFAULT | LC_PIECE_HAS_LINES))
Scene.mOpaqueMeshes.Add(RenderMesh); Scene.mOpaqueMeshes.Add(Scene.mRenderMeshes.GetSize() - 1);
if (mFlags & LC_PIECE_HAS_TRANSLUCENT) if (mFlags & LC_PIECE_HAS_TRANSLUCENT)
Scene.mTranslucentMeshes.Add(RenderMesh); Scene.mTranslucentMeshes.Add(Scene.mRenderMeshes.GetSize() - 1);
} }
void PieceInfo::AddRenderMeshes(lcScene& Scene, const lcMatrix44& WorldMatrix, int ColorIndex, bool Focused, bool Selected) const void PieceInfo::AddRenderMeshes(lcScene& Scene, const lcMatrix44& WorldMatrix, int ColorIndex, bool Focused, bool Selected) const
{ {
if (mMesh || (mFlags & LC_PIECE_PLACEHOLDER)) if (mMesh || (mFlags & LC_PIECE_PLACEHOLDER))
{ {
lcRenderMesh RenderMesh; lcRenderMesh& RenderMesh = Scene.mRenderMeshes.Add();
RenderMesh.WorldMatrix = WorldMatrix; RenderMesh.WorldMatrix = WorldMatrix;
RenderMesh.Mesh = (mFlags & LC_PIECE_PLACEHOLDER) ? gPlaceholderMesh : mMesh; RenderMesh.Mesh = (mFlags & LC_PIECE_PLACEHOLDER) ? gPlaceholderMesh : mMesh;
@ -345,10 +345,10 @@ void PieceInfo::AddRenderMeshes(lcScene& Scene, const lcMatrix44& WorldMatrix, i
bool Translucent = lcIsColorTranslucent(ColorIndex); bool Translucent = lcIsColorTranslucent(ColorIndex);
if ((mFlags & (LC_PIECE_HAS_SOLID | LC_PIECE_HAS_LINES)) || ((mFlags & LC_PIECE_HAS_DEFAULT) && !Translucent)) if ((mFlags & (LC_PIECE_HAS_SOLID | LC_PIECE_HAS_LINES)) || ((mFlags & LC_PIECE_HAS_DEFAULT) && !Translucent))
Scene.mOpaqueMeshes.Add(RenderMesh); Scene.mOpaqueMeshes.Add(Scene.mRenderMeshes.GetSize() - 1);
if ((mFlags & LC_PIECE_HAS_TRANSLUCENT) || ((mFlags & LC_PIECE_HAS_DEFAULT) && Translucent)) if ((mFlags & LC_PIECE_HAS_TRANSLUCENT) || ((mFlags & LC_PIECE_HAS_DEFAULT) && Translucent))
Scene.mTranslucentMeshes.Add(RenderMesh); Scene.mTranslucentMeshes.Add(Scene.mRenderMeshes.GetSize() - 1);
} }
if (mFlags & LC_PIECE_MODEL) if (mFlags & LC_PIECE_MODEL)