Added mesh LOD.

This commit is contained in:
leo 2015-05-24 04:36:25 +00:00
parent 77424ccf16
commit 307ed62ceb
8 changed files with 684 additions and 389 deletions

View file

@ -78,6 +78,11 @@ public:
mLength = NewSize;
}
void SetGrow(int Grow)
{
mGrow = Grow;
}
void AllocGrow(int Grow)
{
if ((mLength + Grow) > mAlloc)

View file

@ -29,10 +29,10 @@ static int lcTranslucentRenderMeshCompare(const void* Elem1, const void* Elem2)
lcRenderMesh* Mesh2 = (lcRenderMesh*)Elem2;
if (Mesh1->Distance < Mesh2->Distance)
return -1;
return 1;
if (Mesh1->Distance > Mesh2->Distance)
return 1;
return -1;
return 0;
}
@ -44,6 +44,7 @@ lcScene::lcScene()
void lcScene::Begin(const lcMatrix44& ViewMatrix)
{
mViewMatrix = ViewMatrix;
mOpaqueMeshes.RemoveAll();
mTranslucentMeshes.RemoveAll();
mInterfaceObjects.RemoveAll();
@ -962,13 +963,14 @@ void lcContext::DrawOpaqueMeshes(const lcArray<lcRenderMesh>& OpaqueMeshes)
{
lcRenderMesh& RenderMesh = OpaqueMeshes[MeshIdx];
lcMesh* Mesh = RenderMesh.Mesh;
int LodIndex = RenderMesh.LodIndex;
BindMesh(Mesh);
SetWorldMatrix(RenderMesh.WorldMatrix);
for (int SectionIdx = 0; SectionIdx < Mesh->mNumSections; SectionIdx++)
for (int SectionIdx = 0; SectionIdx < Mesh->mLods[LodIndex].NumSections; SectionIdx++)
{
lcMeshSection* Section = &Mesh->mSections[SectionIdx];
lcMeshSection* Section = &Mesh->mLods[LodIndex].Sections[SectionIdx];
int ColorIndex = Section->ColorIndex;
if (Section->PrimitiveType == GL_TRIANGLES)
@ -1038,13 +1040,14 @@ void lcContext::DrawTranslucentMeshes(const lcArray<lcRenderMesh>& TranslucentMe
{
lcRenderMesh& RenderMesh = TranslucentMeshes[MeshIdx];
lcMesh* Mesh = RenderMesh.Mesh;
int LodIndex = RenderMesh.LodIndex;
BindMesh(Mesh);
SetWorldMatrix(RenderMesh.WorldMatrix);
for (int SectionIdx = 0; SectionIdx < Mesh->mNumSections; SectionIdx++)
for (int SectionIdx = 0; SectionIdx < Mesh->mLods[LodIndex].NumSections; SectionIdx++)
{
lcMeshSection* Section = &Mesh->mSections[SectionIdx];
lcMeshSection* Section = &Mesh->mLods[LodIndex].Sections[SectionIdx];
int ColorIndex = Section->ColorIndex;
if (Section->PrimitiveType != GL_TRIANGLES)

File diff suppressed because it is too large Load diff

View file

@ -55,30 +55,39 @@ struct lcLibraryTextureMap
bool Next;
};
enum lcMeshDataType
{
LC_MESHDATA_HIGH,
LC_MESHDATA_LOW,
LC_MESHDATA_SHARED,
LC_NUM_MESHDATA_TYPES
};
class lcLibraryMeshData
{
public:
lcLibraryMeshData()
: mVertices(1024, 1024)
{
for (int MeshDataIdx = 0; MeshDataIdx < LC_NUM_MESHDATA_TYPES; MeshDataIdx++)
mVertices[MeshDataIdx].SetGrow(1024);
}
~lcLibraryMeshData()
{
for (int SectionIdx = 0; SectionIdx < mSections.GetSize(); SectionIdx++)
delete mSections[SectionIdx];
for (int MeshDataIdx = 0; MeshDataIdx < LC_NUM_MESHDATA_TYPES; MeshDataIdx++)
mSections[MeshDataIdx].DeleteAll();
}
void AddLine(int LineType, lcuint32 ColorCode, const lcVector3* Vertices);
void AddTexturedLine(int LineType, lcuint32 ColorCode, const lcLibraryTextureMap& Map, const lcVector3* Vertices);
void AddMeshData(const lcLibraryMeshData& Data, const lcMatrix44& Transform, lcuint32 CurrentColorCode, lcLibraryTextureMap* TextureMap);
void AddMeshDataNoDuplicateCheck(const lcLibraryMeshData& Data, const lcMatrix44& Transform, lcuint32 CurrentColorCode, lcLibraryTextureMap* TextureMap);
void AddLine(lcMeshDataType MeshDataType, int LineType, lcuint32 ColorCode, const lcVector3* Vertices);
void AddTexturedLine(lcMeshDataType MeshDataType, int LineType, lcuint32 ColorCode, const lcLibraryTextureMap& Map, const lcVector3* Vertices);
void AddMeshData(const lcLibraryMeshData& Data, const lcMatrix44& Transform, lcuint32 CurrentColorCode, lcLibraryTextureMap* TextureMap, lcMeshDataType OverrideDestIndex);
void AddMeshDataNoDuplicateCheck(const lcLibraryMeshData& Data, const lcMatrix44& Transform, lcuint32 CurrentColorCode, lcLibraryTextureMap* TextureMap, lcMeshDataType OverrideDestIndex);
void TestQuad(int* QuadIndices, const lcVector3* Vertices);
void ResequenceQuad(int* QuadIndices, int a, int b, int c, int d);
lcArray<lcLibraryMeshSection*> mSections;
lcArray<lcVertex> mVertices;
lcArray<lcVertexTextured> mTexturedVertices;
lcArray<lcLibraryMeshSection*> mSections[LC_NUM_MESHDATA_TYPES];
lcArray<lcVertex> mVertices[LC_NUM_MESHDATA_TYPES];
lcArray<lcVertexTextured> mTexturedVertices[LC_NUM_MESHDATA_TYPES];
};
class lcLibraryPrimitive
@ -149,7 +158,7 @@ public:
mNumOfficialPieces = mPieces.GetSize();
}
bool ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransform, lcuint32 CurrentColorCode, lcArray<lcLibraryTextureMap>& TextureStack, lcLibraryMeshData& MeshData);
bool ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransform, lcuint32 CurrentColorCode, lcArray<lcLibraryTextureMap>& TextureStack, lcLibraryMeshData& MeshData, lcMeshDataType MeshDataType);
void CreateMesh(PieceInfo* Info, lcLibraryMeshData& MeshData);
void UpdateBuffers(lcContext* Context);

View file

@ -11,8 +11,12 @@ lcMesh* gPlaceholderMesh;
lcMesh::lcMesh()
{
mSections = NULL;
mNumSections = 0;
for (int LodIdx = 0; LodIdx < LC_NUM_MESH_LODS; LodIdx++)
{
mLods[LodIdx].Sections = NULL;
mLods[LodIdx].NumSections = 0;
}
mNumVertices = 0;
mNumTexturedVertices = 0;
mIndexType = 0;
@ -28,13 +32,18 @@ lcMesh::~lcMesh()
{
free(mVertexData);
free(mIndexData);
delete[] mSections;
for (int LodIdx = 0; LodIdx < LC_NUM_MESH_LODS; LodIdx++)
delete[] mLods[LodIdx].Sections;
}
void lcMesh::Create(int NumSections, int NumVertices, int NumTexturedVertices, int NumIndices)
void lcMesh::Create(lcuint16 NumSections[LC_NUM_MESH_LODS], int NumVertices, int NumTexturedVertices, int NumIndices)
{
mSections = new lcMeshSection[NumSections];
mNumSections = NumSections;
for (int LodIdx = 0; LodIdx < LC_NUM_MESH_LODS; LodIdx++)
{
if (NumSections[LodIdx])
mLods[LodIdx].Sections = new lcMeshSection[NumSections[LodIdx]];
mLods[LodIdx].NumSections = NumSections[LodIdx];
}
mNumVertices = NumVertices;
mNumTexturedVertices = NumTexturedVertices;
@ -57,10 +66,15 @@ void lcMesh::Create(int NumSections, int NumVertices, int NumTexturedVertices, i
void lcMesh::CreateBox()
{
Create(2, 8, 0, 36 + 24);
lcuint16 NumSections[LC_NUM_MESH_LODS];
memset(NumSections, 0, sizeof(NumSections));
NumSections[LC_MESH_LOD_HIGH] = 2;
Create(NumSections, 8, 0, 36 + 24);
lcVector3 Min(-10.0f, -10.0f, -24.0f);
lcVector3 Max(10.0f, 10.0f, 4.0f);
mRadius = lcLength((Max - Min) / 2.0f);
float* Verts = (float*)mVertexData;
lcuint16* Indices = (lcuint16*)mIndexData;
@ -74,7 +88,7 @@ void lcMesh::CreateBox()
*Verts++ = Max[0]; *Verts++ = Max[1]; *Verts++ = Max[2];
*Verts++ = Max[0]; *Verts++ = Min[1]; *Verts++ = Max[2];
lcMeshSection* Section = &mSections[0];
lcMeshSection* Section = &mLods[LC_MESH_LOD_HIGH].Sections[0];
Section->ColorIndex = gDefaultColor;
Section->IndexOffset = 0;
Section->NumIndices = 36;
@ -99,7 +113,7 @@ void lcMesh::CreateBox()
*Indices++ = 1; *Indices++ = 2; *Indices++ = 6;
*Indices++ = 1; *Indices++ = 6; *Indices++ = 5;
Section = &mSections[1];
Section = &mLods[LC_MESH_LOD_HIGH].Sections[1];
Section->ColorIndex = gEdgeColor;
Section->IndexOffset = 36 * 2;
Section->NumIndices = 24;
@ -122,9 +136,9 @@ bool lcMesh::MinIntersectDist(const lcVector3& Start, const lcVector3& End, floa
float* Verts = (float*)mVertexData;
bool Hit = false;
for (int SectionIdx = 0; SectionIdx < mNumSections; SectionIdx++)
for (int SectionIdx = 0; SectionIdx < mLods[LC_MESH_LOD_HIGH].NumSections; SectionIdx++)
{
lcMeshSection* Section = &mSections[SectionIdx];
lcMeshSection* Section = &mLods[LC_MESH_LOD_HIGH].Sections[SectionIdx];
if (Section->PrimitiveType != GL_TRIANGLES)
continue;
@ -161,9 +175,9 @@ bool lcMesh::IntersectsPlanes(const lcVector4 Planes[6])
{
float* Verts = (float*)mVertexData;
for (int SectionIdx = 0; SectionIdx < mNumSections; SectionIdx++)
for (int SectionIdx = 0; SectionIdx < mLods[LC_MESH_LOD_HIGH].NumSections; SectionIdx++)
{
lcMeshSection* Section = &mSections[SectionIdx];
lcMeshSection* Section = &mLods[LC_MESH_LOD_HIGH].Sections[SectionIdx];
if (Section->PrimitiveType != GL_TRIANGLES)
continue;
@ -196,9 +210,9 @@ void lcMesh::ExportPOVRay(lcFile& File, const char* MeshName, const char* ColorT
float* Verts = (float*)mVertexData;
for (int SectionIdx = 0; SectionIdx < mNumSections; SectionIdx++)
for (int SectionIdx = 0; SectionIdx < mLods[LC_MESH_LOD_HIGH].NumSections; SectionIdx++)
{
lcMeshSection* Section = &mSections[SectionIdx];
lcMeshSection* Section = &mLods[LC_MESH_LOD_HIGH].Sections[SectionIdx];
if (Section->PrimitiveType != GL_TRIANGLES)
continue;
@ -239,9 +253,9 @@ void lcMesh::ExportWavefrontIndices(lcFile& File, int DefaultColorIndex, int Ver
{
char Line[1024];
for (int SectionIdx = 0; SectionIdx < mNumSections; SectionIdx++)
for (int SectionIdx = 0; SectionIdx < mLods[LC_MESH_LOD_HIGH].NumSections; SectionIdx++)
{
lcMeshSection* Section = &mSections[SectionIdx];
lcMeshSection* Section = &mLods[LC_MESH_LOD_HIGH].Sections[SectionIdx];
if (Section->PrimitiveType != GL_TRIANGLES)
continue;
@ -283,45 +297,51 @@ bool lcMesh::FileLoad(lcFile& File)
return false;
lcuint32 NumVertices, NumTexturedVertices, NumIndices;
lcuint16 NumSections;
lcuint16 NumLods, NumSections[LC_NUM_MESH_LODS];
if (!File.ReadU16(&NumSections, 1) || !File.ReadU32(&NumVertices, 1) || !File.ReadU32(&NumTexturedVertices, 1) || !File.ReadU32(&NumIndices, 1))
if (!File.ReadU32(&NumVertices, 1) || !File.ReadU32(&NumTexturedVertices, 1) || !File.ReadU32(&NumIndices, 1))
return false;
if (!File.ReadU16(&NumLods, 1) || NumLods != LC_NUM_MESH_LODS || !File.ReadU16(NumSections, LC_NUM_MESH_LODS))
return false;
Create(NumSections, NumVertices, NumTexturedVertices, NumIndices);
for (int SectionIdx = 0; SectionIdx < mNumSections; SectionIdx++)
for (int LodIdx = 0; LodIdx < LC_NUM_MESH_LODS; LodIdx++)
{
lcMeshSection& Section = mSections[SectionIdx];
lcuint32 ColorCode, IndexOffset;
lcuint16 Triangles, Length;
if (!File.ReadU32(&ColorCode, 1) || !File.ReadU32(&IndexOffset, 1) || !File.ReadU32(&NumIndices, 1) || !File.ReadU16(&Triangles, 1))
return false;
Section.ColorIndex = lcGetColorIndex(ColorCode);
Section.IndexOffset = IndexOffset;
Section.NumIndices = NumIndices;
Section.PrimitiveType = Triangles ? GL_TRIANGLES : GL_LINES;
if (!File.ReadU16(&Length, 1))
return false;
if (Length)
for (int SectionIdx = 0; SectionIdx < mLods[LodIdx].NumSections; SectionIdx++)
{
if (Length >= LC_TEXTURE_NAME_LEN)
lcMeshSection& Section = mLods[LodIdx].Sections[SectionIdx];
lcuint32 ColorCode, IndexOffset;
lcuint16 Triangles, Length;
if (!File.ReadU32(&ColorCode, 1) || !File.ReadU32(&IndexOffset, 1) || !File.ReadU32(&NumIndices, 1) || !File.ReadU16(&Triangles, 1))
return false;
char FileName[LC_TEXTURE_NAME_LEN];
Section.ColorIndex = lcGetColorIndex(ColorCode);
Section.IndexOffset = IndexOffset;
Section.NumIndices = NumIndices;
Section.PrimitiveType = Triangles ? GL_TRIANGLES : GL_LINES;
File.ReadBuffer(FileName, Length);
FileName[Length] = 0;
if (!File.ReadU16(&Length, 1))
return false;
Section.Texture = lcGetPiecesLibrary()->FindTexture(FileName);
if (Length)
{
if (Length >= LC_TEXTURE_NAME_LEN)
return false;
char FileName[LC_TEXTURE_NAME_LEN];
File.ReadBuffer(FileName, Length);
FileName[Length] = 0;
Section.Texture = lcGetPiecesLibrary()->FindTexture(FileName);
}
else
Section.Texture = NULL;
}
else
Section.Texture = NULL;
}
File.ReadFloats((float*)mVertexData, 3 * mNumVertices + 5 * mNumTexturedVertices);
@ -339,28 +359,34 @@ void lcMesh::FileSave(lcFile& File)
File.WriteU32(LC_MESH_FILE_ID);
File.WriteU32(LC_MESH_FILE_VERSION);
File.WriteU16(mNumSections);
File.WriteU32(mNumVertices);
File.WriteU32(mNumTexturedVertices);
File.WriteU32(mIndexDataSize / (mIndexType == GL_UNSIGNED_SHORT ? 2 : 4));
for (int SectionIdx = 0; SectionIdx < mNumSections; SectionIdx++)
File.WriteU16(LC_NUM_MESH_LODS);
for (int LodIdx = 0; LodIdx < LC_NUM_MESH_LODS; LodIdx++)
File.WriteU16(mLods[LodIdx].NumSections);
for (int LodIdx = 0; LodIdx < LC_NUM_MESH_LODS; LodIdx++)
{
lcMeshSection& Section = mSections[SectionIdx];
File.WriteU32(lcGetColorCode(Section.ColorIndex));
File.WriteU32(Section.IndexOffset);
File.WriteU32(Section.NumIndices);
File.WriteU16(Section.PrimitiveType == GL_TRIANGLES ? 1 : 0);
if (Section.Texture)
for (int SectionIdx = 0; SectionIdx < mLods[LodIdx].NumSections; SectionIdx++)
{
int Length = strlen(Section.Texture->mName);
File.WriteU16(Length);
File.WriteBuffer(Section.Texture->mName, Length);
lcMeshSection& Section = mLods[LodIdx].Sections[SectionIdx];
File.WriteU32(lcGetColorCode(Section.ColorIndex));
File.WriteU32(Section.IndexOffset);
File.WriteU32(Section.NumIndices);
File.WriteU16(Section.PrimitiveType == GL_TRIANGLES ? 1 : 0);
if (Section.Texture)
{
int Length = strlen(Section.Texture->mName);
File.WriteU16(Length);
File.WriteBuffer(Section.Texture->mName, Length);
}
else
File.WriteU16(0);
}
else
File.WriteU16(0);
}
File.WriteFloats((float*)mVertexData, 3 * mNumVertices + 5 * mNumTexturedVertices);
@ -369,3 +395,11 @@ void lcMesh::FileSave(lcFile& File)
else
File.WriteU32((lcuint32*)mIndexData, mIndexDataSize / 4);
}
int lcMesh::GetLodIndex(float Distance) const
{
if (mLods[LC_MESH_LOD_LOW].NumSections && (Distance - mRadius) > 250.0f)
return LC_MESH_LOD_LOW;
else
return LC_MESH_LOD_HIGH;
}

View file

@ -5,7 +5,7 @@
#include "lc_math.h"
#define LC_MESH_FILE_ID LC_FOURCC('M', 'E', 'S', 'H')
#define LC_MESH_FILE_VERSION 0x0100
#define LC_MESH_FILE_VERSION 0x0110
struct lcVertex
{
@ -27,13 +27,26 @@ struct lcMeshSection
lcTexture* Texture;
};
struct lcMeshLod
{
lcMeshSection* Sections;
int NumSections;
};
enum
{
LC_MESH_LOD_HIGH,
LC_MESH_LOD_LOW,
LC_NUM_MESH_LODS
};
class lcMesh
{
public:
lcMesh();
~lcMesh();
void Create(int NumSections, int NumVertices, int NumTexturedVertices, int NumIndices);
void Create(lcuint16 NumSections[LC_NUM_MESH_LODS], int NumVertices, int NumTexturedVertices, int NumIndices);
void CreateBox();
bool FileLoad(lcFile& File);
@ -55,8 +68,10 @@ public:
bool IntersectsPlanes(const lcVector4 Planes[6]);
bool IntersectsPlanes(const lcVector4 Planes[6]);
lcMeshSection* mSections;
int mNumSections;
int GetLodIndex(float Distance) const;
lcMeshLod mLods[LC_NUM_MESH_LODS];
float mRadius;
void* mVertexData;
int mVertexDataSize;
@ -83,6 +98,7 @@ struct lcRenderMesh
lcMesh* Mesh;
float Distance;
int ColorIndex;
int LodIndex;
lcRenderMeshState State;
};

View file

@ -82,7 +82,7 @@ void PieceInfo::SetModel(lcModel* Model, bool UpdateMesh)
PieceFile.Seek(0, SEEK_SET);
const char* OldLocale = setlocale(LC_NUMERIC, "C");
bool Ret = lcGetPiecesLibrary()->ReadMeshData(PieceFile, lcMatrix44Identity(), 16, TextureStack, MeshData);
bool Ret = lcGetPiecesLibrary()->ReadMeshData(PieceFile, lcMatrix44Identity(), 16, TextureStack, MeshData, LC_MESHDATA_SHARED);
setlocale(LC_NUMERIC, OldLocale);
if (Ret)
@ -127,12 +127,15 @@ void PieceInfo::Unload()
{
if (mMesh)
{
for (int SectionIdx = 0; SectionIdx < mMesh->mNumSections; SectionIdx++)
for (int LodIdx = 0; LodIdx < LC_NUM_MESH_LODS; LodIdx++)
{
lcMeshSection& Section = mMesh->mSections[SectionIdx];
for (int SectionIdx = 0; SectionIdx < mMesh->mLods[LodIdx].NumSections; SectionIdx++)
{
lcMeshSection& Section = mMesh->mLods[LodIdx].Sections[SectionIdx];
if (Section.Texture)
Section.Texture->Release();
if (Section.Texture)
Section.Texture->Release();
}
}
delete mMesh;
@ -287,16 +290,14 @@ void PieceInfo::AddRenderMesh(lcScene& Scene)
RenderMesh.Mesh = mMesh;
RenderMesh.ColorIndex = gDefaultColor;
RenderMesh.State = LC_RENDERMESH_NONE;
RenderMesh.Distance = fabsf(Scene.mViewMatrix.r[3].z);
RenderMesh.LodIndex = mMesh->GetLodIndex(RenderMesh.Distance);
if (mFlags & (LC_PIECE_HAS_SOLID | LC_PIECE_HAS_DEFAULT | LC_PIECE_HAS_LINES))
Scene.mOpaqueMeshes.Add(RenderMesh);
if (mFlags & LC_PIECE_HAS_TRANSLUCENT)
{
RenderMesh.Distance = Scene.mViewMatrix.r[3].z;
Scene.mTranslucentMeshes.Add(RenderMesh);
}
}
void PieceInfo::AddRenderMeshes(lcScene& Scene, const lcMatrix44& WorldMatrix, int ColorIndex, bool Focused, bool Selected)
@ -309,6 +310,8 @@ void PieceInfo::AddRenderMeshes(lcScene& Scene, const lcMatrix44& WorldMatrix, i
RenderMesh.Mesh = (mFlags & LC_PIECE_PLACEHOLDER) ? gPlaceholderMesh : mMesh;
RenderMesh.ColorIndex = ColorIndex;
RenderMesh.State = Focused ? LC_RENDERMESH_FOCUSED : (Selected ? LC_RENDERMESH_SELECTED : LC_RENDERMESH_NONE);
RenderMesh.Distance = fabsf(lcMul31(WorldMatrix[3], Scene.mViewMatrix).z);
RenderMesh.LodIndex = mMesh->GetLodIndex(RenderMesh.Distance);
bool Translucent = lcIsColorTranslucent(ColorIndex);
@ -316,13 +319,7 @@ void PieceInfo::AddRenderMeshes(lcScene& Scene, const lcMatrix44& WorldMatrix, i
Scene.mOpaqueMeshes.Add(RenderMesh);
if ((mFlags & LC_PIECE_HAS_TRANSLUCENT) || ((mFlags & LC_PIECE_HAS_DEFAULT) && Translucent))
{
lcVector3 Pos = lcMul31(WorldMatrix[3], Scene.mViewMatrix);
RenderMesh.Distance = Pos[2];
Scene.mTranslucentMeshes.Add(RenderMesh);
}
}
if (mFlags & LC_PIECE_MODEL)

View file

@ -765,9 +765,9 @@ void Project::Export3DStudio(const QString& FileName)
int NumTriangles = 0;
for (int SectionIdx = 0; SectionIdx < Mesh->mNumSections; SectionIdx++)
for (int SectionIdx = 0; SectionIdx < Mesh->mLods[LC_MESH_LOD_HIGH].NumSections; SectionIdx++)
{
lcMeshSection* Section = &Mesh->mSections[SectionIdx];
lcMeshSection* Section = &Mesh->mLods[LC_MESH_LOD_HIGH].Sections[SectionIdx];
if (Section->PrimitiveType != GL_TRIANGLES)
continue;
@ -777,9 +777,9 @@ void Project::Export3DStudio(const QString& FileName)
File.WriteU16(NumTriangles);
for (int SectionIdx = 0; SectionIdx < Mesh->mNumSections; SectionIdx++)
for (int SectionIdx = 0; SectionIdx < Mesh->mLods[LC_MESH_LOD_HIGH].NumSections; SectionIdx++)
{
lcMeshSection* Section = &Mesh->mSections[SectionIdx];
lcMeshSection* Section = &Mesh->mLods[LC_MESH_LOD_HIGH].Sections[SectionIdx];
if (Section->PrimitiveType != GL_TRIANGLES)
continue;
@ -797,9 +797,9 @@ void Project::Export3DStudio(const QString& FileName)
NumTriangles = 0;
for (int SectionIdx = 0; SectionIdx < Mesh->mNumSections; SectionIdx++)
for (int SectionIdx = 0; SectionIdx < Mesh->mLods[LC_MESH_LOD_HIGH].NumSections; SectionIdx++)
{
lcMeshSection* Section = &Mesh->mSections[SectionIdx];
lcMeshSection* Section = &Mesh->mLods[LC_MESH_LOD_HIGH].Sections[SectionIdx];
if (Section->PrimitiveType != GL_TRIANGLES)
continue;