Store texture projection as part of the section while loading meshes.

This commit is contained in:
Leonardo Zide 2021-06-12 19:29:13 -07:00
parent d84d8f1f3c
commit bf7a382dcc
2 changed files with 281 additions and 206 deletions

View file

@ -10,10 +10,13 @@ static lcVector2 lcCalculateTexCoord(const lcVector3& Position, const lcMeshLoad
{ {
switch (TextureMap->Type) switch (TextureMap->Type)
{ {
case lcMeshLoaderTextureMapType::Planar: case lcMeshLoaderMaterialType::Solid:
break;
case lcMeshLoaderMaterialType::Planar:
return lcVector2(lcDot3(Position, TextureMap->Params.Planar.Planes[0]) + TextureMap->Params.Planar.Planes[0].w, lcDot3(Position, TextureMap->Params.Planar.Planes[1]) + TextureMap->Params.Planar.Planes[1].w); return lcVector2(lcDot3(Position, TextureMap->Params.Planar.Planes[0]) + TextureMap->Params.Planar.Planes[0].w, lcDot3(Position, TextureMap->Params.Planar.Planes[1]) + TextureMap->Params.Planar.Planes[1].w);
case lcMeshLoaderTextureMapType::Cylindrical: case lcMeshLoaderMaterialType::Cylindrical:
{ {
const lcVector4& FrontPlane = TextureMap->Params.Cylindrical.FrontPlane; const lcVector4& FrontPlane = TextureMap->Params.Cylindrical.FrontPlane;
const lcVector4& Plane1 = TextureMap->Params.Cylindrical.Plane1; const lcVector4& Plane1 = TextureMap->Params.Cylindrical.Plane1;
@ -33,7 +36,7 @@ static lcVector2 lcCalculateTexCoord(const lcVector3& Position, const lcMeshLoad
return TexCoord; return TexCoord;
} }
case lcMeshLoaderTextureMapType::Spherical: case lcMeshLoaderMaterialType::Spherical:
{ {
const lcVector4& FrontPlane = TextureMap->Params.Spherical.FrontPlane; const lcVector4& FrontPlane = TextureMap->Params.Spherical.FrontPlane;
const lcVector3& Center = TextureMap->Params.Spherical.Center; const lcVector3& Center = TextureMap->Params.Spherical.Center;
@ -113,13 +116,13 @@ static bool lcCompareVertices(const lcVector3& Position1, const lcVector2& TexCo
return lcCompareVertices(Position1, Position2) && fabsf(TexCoord1.x - TexCoord2.x) < lcTexCoordEpsilon && fabsf(TexCoord1.y - TexCoord2.y) < lcTexCoordEpsilon; return lcCompareVertices(Position1, Position2) && fabsf(TexCoord1.x - TexCoord2.x) < lcTexCoordEpsilon && fabsf(TexCoord1.y - TexCoord2.y) < lcTexCoordEpsilon;
} }
lcMeshLoaderSection* lcMeshLoaderTypeData::AddSection(lcMeshPrimitiveType PrimitiveType, quint32 ColorCode, lcTexture* Texture) lcMeshLoaderSection* lcMeshLoaderTypeData::AddSection(lcMeshPrimitiveType PrimitiveType, lcMeshLoaderMaterial* Material)
{ {
for (std::unique_ptr<lcMeshLoaderSection>& Section : mSections) for (std::unique_ptr<lcMeshLoaderSection>& Section : mSections)
if (Section->mColor == ColorCode && Section->mPrimitiveType == PrimitiveType && Section->mTexture == Texture) if (Section->mMaterial == Material && Section->mPrimitiveType == PrimitiveType)
return Section.get(); return Section.get();
mSections.emplace_back(new lcMeshLoaderSection(PrimitiveType, ColorCode, Texture)); mSections.emplace_back(new lcMeshLoaderSection(PrimitiveType, Material));
return mSections.back().get(); return mSections.back().get();
} }
@ -300,11 +303,11 @@ quint32 lcMeshLoaderTypeData::AddConditionalVertex(const lcVector3(&Position)[4]
return mConditionalVertices.GetSize() - 1; return mConditionalVertices.GetSize() - 1;
} }
void lcMeshLoaderTypeData::ProcessLine(int LineType, quint32 ColorCode, bool WindingCCW, lcVector3 (&Vertices)[4], bool Optimize) void lcMeshLoaderTypeData::ProcessLine(int LineType, lcMeshLoaderMaterial* Material, bool WindingCCW, lcVector3 (&Vertices)[4], bool Optimize)
{ {
lcMeshPrimitiveType PrimitiveTypes[4] = { LC_MESH_LINES, LC_MESH_TRIANGLES, LC_MESH_TRIANGLES, LC_MESH_CONDITIONAL_LINES }; lcMeshPrimitiveType PrimitiveTypes[4] = { LC_MESH_LINES, LC_MESH_TRIANGLES, LC_MESH_TRIANGLES, LC_MESH_CONDITIONAL_LINES };
lcMeshPrimitiveType PrimitiveType = PrimitiveTypes[LineType - 2]; lcMeshPrimitiveType PrimitiveType = PrimitiveTypes[LineType - 2];
lcMeshLoaderSection* Section = AddSection(PrimitiveType, ColorCode, nullptr); lcMeshLoaderSection* Section = AddSection(PrimitiveType, Material);
int QuadIndices[4] = { 0, 1, 2, 3 }; int QuadIndices[4] = { 0, 1, 2, 3 };
int Indices[4] = { -1, -1, -1, -1 }; int Indices[4] = { -1, -1, -1, -1 };
@ -396,10 +399,10 @@ void lcMeshLoaderTypeData::ProcessLine(int LineType, quint32 ColorCode, bool Win
} }
} }
void lcMeshLoaderTypeData::ProcessTexturedLine(int LineType, quint32 ColorCode, bool WindingCCW, const lcMeshLoaderTextureMap& TextureMap, const lcVector3* Vertices, bool Optimize) void lcMeshLoaderTypeData::ProcessTexturedLine(int LineType, lcMeshLoaderMaterial* Material, bool WindingCCW, const lcMeshLoaderTextureMap& TextureMap, const lcVector3* Vertices, bool Optimize)
{ {
lcMeshPrimitiveType PrimitiveType = LC_MESH_TEXTURED_TRIANGLES; lcMeshPrimitiveType PrimitiveType = LC_MESH_TEXTURED_TRIANGLES;
lcMeshLoaderSection* Section = AddSection(PrimitiveType, ColorCode, TextureMap.Texture); lcMeshLoaderSection* Section = AddSection(PrimitiveType, Material);
int QuadIndices[4] = { 0, 1, 2, 3 }; int QuadIndices[4] = { 0, 1, 2, 3 };
int Indices[4] = { -1, -1, -1, -1 }; int Indices[4] = { -1, -1, -1, -1 };
@ -420,7 +423,7 @@ void lcMeshLoaderTypeData::ProcessTexturedLine(int LineType, quint32 ColorCode,
TexCoords[QuadIndices[IndexIdx]] = lcCalculateTexCoord(Position, &TextureMap); TexCoords[QuadIndices[IndexIdx]] = lcCalculateTexCoord(Position, &TextureMap);
} }
if (TextureMap.Type == lcMeshLoaderTextureMapType::Cylindrical || TextureMap.Type == lcMeshLoaderTextureMapType::Spherical) if (TextureMap.Type == lcMeshLoaderMaterialType::Cylindrical || TextureMap.Type == lcMeshLoaderMaterialType::Spherical)
{ {
auto CheckTexCoordsWrap = [&TexCoords, &Vertices, &TextureMap](int Index1, int Index2, int Index3) auto CheckTexCoordsWrap = [&TexCoords, &Vertices, &TextureMap](int Index1, int Index2, int Index3)
{ {
@ -431,7 +434,7 @@ void lcMeshLoaderTypeData::ProcessTexturedLine(int LineType, quint32 ColorCode,
if (u12 < 0.5f && u13 < 0.5f && u23 < 0.5f) if (u12 < 0.5f && u13 < 0.5f && u23 < 0.5f)
return; return;
const lcVector4& Plane2 = (TextureMap.Type == lcMeshLoaderTextureMapType::Cylindrical) ? TextureMap.Params.Cylindrical.Plane2 : TextureMap.Params.Spherical.Plane2; const lcVector4& Plane2 = (TextureMap.Type == lcMeshLoaderMaterialType::Cylindrical) ? TextureMap.Params.Cylindrical.Plane2 : TextureMap.Params.Spherical.Plane2;
float Dot1 = fabsf(lcDot(Plane2, lcVector4(Vertices[Index1], 1.0f))); float Dot1 = fabsf(lcDot(Plane2, lcVector4(Vertices[Index1], 1.0f)));
float Dot2 = fabsf(lcDot(Plane2, lcVector4(Vertices[Index2], 1.0f))); float Dot2 = fabsf(lcDot(Plane2, lcVector4(Vertices[Index2], 1.0f)));
float Dot3 = fabsf(lcDot(Plane2, lcVector4(Vertices[Index3], 1.0f))); float Dot3 = fabsf(lcDot(Plane2, lcVector4(Vertices[Index3], 1.0f)));
@ -482,7 +485,7 @@ void lcMeshLoaderTypeData::ProcessTexturedLine(int LineType, quint32 ColorCode,
CheckTexCoordsWrap(QuadIndices[2], QuadIndices[3], QuadIndices[0]); CheckTexCoordsWrap(QuadIndices[2], QuadIndices[3], QuadIndices[0]);
} }
if (TextureMap.Type == lcMeshLoaderTextureMapType::Spherical) if (TextureMap.Type == lcMeshLoaderMaterialType::Spherical)
{ {
auto CheckTexCoordsPole = [&TexCoords, &Vertices, &TextureMap](int Index1, int Index2, int Index3) auto CheckTexCoordsPole = [&TexCoords, &Vertices, &TextureMap](int Index1, int Index2, int Index3)
{ {
@ -654,21 +657,30 @@ void lcMeshLoaderTypeData::AddMeshData(const lcMeshLoaderTypeData& Data, const l
for (const std::unique_ptr<lcMeshLoaderSection>& SrcSection : Data.mSections) for (const std::unique_ptr<lcMeshLoaderSection>& SrcSection : Data.mSections)
{ {
quint32 ColorCode = SrcSection->mColor == 16 ? CurrentColorCode : SrcSection->mColor; const quint32 ColorCode = SrcSection->mMaterial->Color == 16 ? CurrentColorCode : SrcSection->mMaterial->Color;
lcTexture* Texture;
lcMeshPrimitiveType PrimitiveType = SrcSection->mPrimitiveType; lcMeshPrimitiveType PrimitiveType = SrcSection->mPrimitiveType;
lcMeshLoaderSection* DstSection;
if (SrcSection->mTexture) if (SrcSection->mMaterial->Type != lcMeshLoaderMaterialType::Solid)
Texture = SrcSection->mTexture; {
lcMeshLoaderTextureMap DstTextureMap = *TextureMap;
for (lcVector3& Point : DstTextureMap.Points)
Point = lcMul31(Point, Transform);
DstSection = AddSection(PrimitiveType, mMeshData->GetTexturedMaterial(ColorCode, DstTextureMap));
}
else if (TextureMap && SrcSection->mPrimitiveType == LC_MESH_TRIANGLES) else if (TextureMap && SrcSection->mPrimitiveType == LC_MESH_TRIANGLES)
{ {
Texture = TextureMap->Texture;
PrimitiveType = LC_MESH_TEXTURED_TRIANGLES; PrimitiveType = LC_MESH_TEXTURED_TRIANGLES;
DstSection = AddSection(PrimitiveType, mMeshData->GetTexturedMaterial(ColorCode, *TextureMap));
} }
else else
Texture = nullptr; {
DstSection = AddSection(PrimitiveType, mMeshData->GetMaterial(ColorCode));
}
lcMeshLoaderSection* DstSection = AddSection(PrimitiveType, ColorCode, Texture);
DstSection->mIndices.AllocGrow(SrcSection->mIndices.GetSize()); DstSection->mIndices.AllocGrow(SrcSection->mIndices.GetSize());
if (PrimitiveType == LC_MESH_CONDITIONAL_LINES) if (PrimitiveType == LC_MESH_CONDITIONAL_LINES)
@ -758,21 +770,30 @@ void lcMeshLoaderTypeData::AddMeshDataNoDuplicateCheck(const lcMeshLoaderTypeDat
for (const std::unique_ptr<lcMeshLoaderSection>& SrcSection : Data.mSections) for (const std::unique_ptr<lcMeshLoaderSection>& SrcSection : Data.mSections)
{ {
quint32 ColorCode = SrcSection->mColor == 16 ? CurrentColorCode : SrcSection->mColor; const quint32 ColorCode = SrcSection->mMaterial->Color == 16 ? CurrentColorCode : SrcSection->mMaterial->Color;
lcTexture* Texture;
lcMeshPrimitiveType PrimitiveType = SrcSection->mPrimitiveType; lcMeshPrimitiveType PrimitiveType = SrcSection->mPrimitiveType;
lcMeshLoaderSection* DstSection;
if (SrcSection->mTexture) if (SrcSection->mMaterial->Type != lcMeshLoaderMaterialType::Solid)
Texture = SrcSection->mTexture; {
lcMeshLoaderTextureMap DstTextureMap = *TextureMap;
for (lcVector3& Point : DstTextureMap.Points)
Point = lcMul31(Point, Transform);
DstSection = AddSection(PrimitiveType, mMeshData->GetTexturedMaterial(ColorCode, DstTextureMap));
}
else if (TextureMap && SrcSection->mPrimitiveType == LC_MESH_TRIANGLES) else if (TextureMap && SrcSection->mPrimitiveType == LC_MESH_TRIANGLES)
{ {
Texture = TextureMap->Texture;
PrimitiveType = LC_MESH_TEXTURED_TRIANGLES; PrimitiveType = LC_MESH_TEXTURED_TRIANGLES;
DstSection = AddSection(PrimitiveType, mMeshData->GetTexturedMaterial(ColorCode, *TextureMap));
} }
else else
Texture = nullptr; {
DstSection = AddSection(PrimitiveType, mMeshData->GetMaterial(ColorCode));
}
lcMeshLoaderSection* DstSection = AddSection(SrcSection->mPrimitiveType, ColorCode, Texture);
DstSection->mIndices.SetGrow(lcMin(DstSection->mIndices.GetSize(), 8 * 1024 * 1024)); DstSection->mIndices.SetGrow(lcMin(DstSection->mIndices.GetSize(), 8 * 1024 * 1024));
DstSection->mIndices.AllocGrow(SrcSection->mIndices.GetSize()); DstSection->mIndices.AllocGrow(SrcSection->mIndices.GetSize());
@ -811,7 +832,7 @@ void lcLibraryMeshData::AddVertices(lcMeshDataType MeshDataType, int VertexCount
void lcLibraryMeshData::AddIndices(lcMeshDataType MeshDataType, lcMeshPrimitiveType PrimitiveType, quint32 ColorCode, int IndexCount, quint32** IndexBuffer) void lcLibraryMeshData::AddIndices(lcMeshDataType MeshDataType, lcMeshPrimitiveType PrimitiveType, quint32 ColorCode, int IndexCount, quint32** IndexBuffer)
{ {
lcMeshLoaderSection* Section = mData[MeshDataType].AddSection(PrimitiveType, ColorCode, nullptr); lcMeshLoaderSection* Section = mData[MeshDataType].AddSection(PrimitiveType, GetMaterial(ColorCode));
lcArray<quint32>& Indices = Section->mIndices; lcArray<quint32>& Indices = Section->mIndices;
int CurrentSize = Indices.GetSize(); int CurrentSize = Indices.GetSize();
@ -842,12 +863,66 @@ void lcLibraryMeshData::AddMeshDataNoDuplicateCheck(const lcLibraryMeshData& Dat
mHasTextures |= (Data.mHasTextures || TextureMap); mHasTextures |= (Data.mHasTextures || TextureMap);
} }
static bool lcLibraryMeshSectionCompare(const lcMergeSection& First, const lcMergeSection& Second) lcMeshLoaderMaterial* lcLibraryMeshData::GetMaterial(quint32 ColorCode)
{ {
lcMeshLoaderSection* a = First.Lod ? First.Lod : First.Shared; for (std::unique_ptr<lcMeshLoaderMaterial>& Material : mMaterials)
lcMeshLoaderSection* b = Second.Lod ? Second.Lod : Second.Shared; if (Material->Type == lcMeshLoaderMaterialType::Solid && Material->Color == ColorCode)
return Material.get();
if (a->mPrimitiveType != b->mPrimitiveType) lcMeshLoaderMaterial* Material = new lcMeshLoaderMaterial();
mMaterials.emplace_back(Material);
Material->Type = lcMeshLoaderMaterialType::Solid;
Material->Color = ColorCode;
return Material;
}
lcMeshLoaderMaterial* lcLibraryMeshData::GetTexturedMaterial(quint32 ColorCode, const lcMeshLoaderTextureMap& TextureMap)
{
for (std::unique_ptr<lcMeshLoaderMaterial>& Material : mMaterials)
{
if (Material->Type != TextureMap.Type || Material->Color != ColorCode)
continue;
if (strcmp(Material->Name, TextureMap.Name))
continue;
if (Material->Points[0] != TextureMap.Points[0] || Material->Points[1] != TextureMap.Points[1] || Material->Points[2] != TextureMap.Points[2])
continue;
if (Material->Type == lcMeshLoaderMaterialType::Cylindrical)
{
if (Material->Angles[0] != TextureMap.Angles[0])
continue;
}
else if (Material->Type == lcMeshLoaderMaterialType::Spherical)
{
if (Material->Angles[0] != TextureMap.Angles[0] || Material->Angles[1] != TextureMap.Angles[1])
continue;
}
return Material.get();
}
lcMeshLoaderMaterial* Material = new lcMeshLoaderMaterial();
mMaterials.emplace_back(Material);
Material->Type = TextureMap.Type;
Material->Color = ColorCode;
Material->Points[0] = TextureMap.Points[0];
Material->Points[1] = TextureMap.Points[1];
Material->Points[2] = TextureMap.Points[2];
Material->Angles[0] = TextureMap.Angles[0];
Material->Angles[1] = TextureMap.Angles[1];
strcpy(Material->Name, TextureMap.Name);
return Material;
}
static bool lcMeshLoaderFinalSectionCompare(const lcMeshLoaderFinalSection& a, const lcMeshLoaderFinalSection& b)
{
if (a.PrimitiveType != b.PrimitiveType)
{ {
int PrimitiveOrder[LC_MESH_NUM_PRIMITIVE_TYPES] = int PrimitiveOrder[LC_MESH_NUM_PRIMITIVE_TYPES] =
{ {
@ -861,21 +936,21 @@ static bool lcLibraryMeshSectionCompare(const lcMergeSection& First, const lcMer
{ {
int Primitive = PrimitiveOrder[PrimitiveType]; int Primitive = PrimitiveOrder[PrimitiveType];
if (a->mPrimitiveType == Primitive) if (a.PrimitiveType == Primitive)
return true; return true;
if (b->mPrimitiveType == Primitive) if (b.PrimitiveType == Primitive)
return false; return false;
} }
} }
bool TranslucentA = lcIsColorTranslucent(a->mColor); bool TranslucentA = lcIsColorTranslucent(a.Color);
bool TranslucentB = lcIsColorTranslucent(b->mColor); bool TranslucentB = lcIsColorTranslucent(b.Color);
if (TranslucentA != TranslucentB) if (TranslucentA != TranslucentB)
return !TranslucentA; return !TranslucentA;
return a->mColor > b->mColor; return a.Color > b.Color;
} }
lcMesh* lcLibraryMeshData::CreateMesh() lcMesh* lcLibraryMeshData::CreateMesh()
@ -891,15 +966,14 @@ lcMesh* lcLibraryMeshData::CreateMesh()
std::vector<quint32> IndexRemap[LC_NUM_MESHDATA_TYPES]; std::vector<quint32> IndexRemap[LC_NUM_MESHDATA_TYPES];
std::vector<quint32> TexturedIndexRemap[LC_NUM_MESHDATA_TYPES]; std::vector<quint32> TexturedIndexRemap[LC_NUM_MESHDATA_TYPES];
// todo: I don't think we should be converting to color index here because it gets saved to the cache
for (const std::unique_ptr<lcMeshLoaderMaterial>& Material : mMaterials)
Material->Color = lcGetColorIndex(Material->Color);
if (!mHasTextures) if (!mHasTextures)
{ {
for (int MeshDataIdx = 0; MeshDataIdx < LC_NUM_MESHDATA_TYPES; MeshDataIdx++) for (int MeshDataIdx = 0; MeshDataIdx < LC_NUM_MESHDATA_TYPES; MeshDataIdx++)
{ {
std::vector<std::unique_ptr<lcMeshLoaderSection>>& Sections = mData[MeshDataIdx].mSections;
for (const std::unique_ptr<lcMeshLoaderSection>& Section : Sections)
Section->mColor = lcGetColorIndex(Section->mColor);
BaseVertices[MeshDataIdx] = NumVertices; BaseVertices[MeshDataIdx] = NumVertices;
NumVertices += mData[MeshDataIdx].mVertices.GetSize(); NumVertices += mData[MeshDataIdx].mVertices.GetSize();
BaseConditionalVertices[MeshDataIdx] = ConditionalVertexCount; BaseConditionalVertices[MeshDataIdx] = ConditionalVertexCount;
@ -910,11 +984,6 @@ lcMesh* lcLibraryMeshData::CreateMesh()
{ {
for (int MeshDataIdx = 0; MeshDataIdx < LC_NUM_MESHDATA_TYPES; MeshDataIdx++) for (int MeshDataIdx = 0; MeshDataIdx < LC_NUM_MESHDATA_TYPES; MeshDataIdx++)
{ {
std::vector<std::unique_ptr<lcMeshLoaderSection>>& Sections = mData[MeshDataIdx].mSections;
for (const std::unique_ptr<lcMeshLoaderSection>& Section : Sections)
Section->mColor = lcGetColorIndex(Section->mColor);
BaseVertices[MeshDataIdx] = NumVertices; BaseVertices[MeshDataIdx] = NumVertices;
BaseTexturedVertices[MeshDataIdx] = NumTexturedVertices; BaseTexturedVertices[MeshDataIdx] = NumTexturedVertices;
@ -947,51 +1016,39 @@ lcMesh* lcLibraryMeshData::CreateMesh()
quint16 NumSections[LC_NUM_MESH_LODS]; quint16 NumSections[LC_NUM_MESH_LODS];
int NumIndices = 0; int NumIndices = 0;
lcArray<lcMergeSection> MergeSections[LC_NUM_MESH_LODS]; lcArray<lcMeshLoaderFinalSection> FinalSections[LC_NUM_MESH_LODS];
for (int LodIdx = 0; LodIdx < LC_NUM_MESH_LODS; LodIdx++) for (int LodIdx = 0; LodIdx < LC_NUM_MESH_LODS; LodIdx++)
{ {
std::vector<std::unique_ptr<lcMeshLoaderSection>>& SharedSections = mData[LC_MESHDATA_SHARED].mSections; auto AddFinalSection = [](lcMeshLoaderSection* Section, lcArray<lcMeshLoaderFinalSection>& FinalSections)
std::vector<std::unique_ptr<lcMeshLoaderSection>>& Sections = mData[LodIdx].mSections;
for (std::unique_ptr<lcMeshLoaderSection>& SharedSection : SharedSections)
{ {
NumIndices += SharedSection->mIndices.GetSize(); for (const lcMeshLoaderFinalSection& FinalSection : FinalSections)
if (FinalSection.PrimitiveType == Section->mPrimitiveType && FinalSection.Color == Section->mMaterial->Color && !strcmp(FinalSection.Name, Section->mMaterial->Name))
return;
lcMergeSection& MergeSection = MergeSections[LodIdx].Add(); lcMeshLoaderFinalSection& FinalSection = FinalSections.Add();
MergeSection.Shared = SharedSection.get();
MergeSection.Lod = nullptr;
}
for (std::unique_ptr<lcMeshLoaderSection>& Section : Sections) FinalSection.PrimitiveType = Section->mPrimitiveType;
FinalSection.Color = Section->mMaterial->Color;
strcpy(FinalSection.Name, Section->mMaterial->Name);
};
for (std::unique_ptr<lcMeshLoaderSection>& Section : mData[LC_MESHDATA_SHARED].mSections)
{ {
bool Found = false;
NumIndices += Section->mIndices.GetSize(); NumIndices += Section->mIndices.GetSize();
for (int SharedSectionIdx = 0; SharedSectionIdx < (int)SharedSections.size(); SharedSectionIdx++) AddFinalSection(Section.get(), FinalSections[LodIdx]);
{
lcMeshLoaderSection* SharedSection = SharedSections[SharedSectionIdx].get();
if (SharedSection->mColor == Section->mColor && SharedSection->mPrimitiveType == Section->mPrimitiveType && SharedSection->mTexture == Section->mTexture)
{
lcMergeSection& MergeSection = MergeSections[LodIdx][SharedSectionIdx];
MergeSection.Lod = Section.get();
Found = true;
break;
}
}
if (!Found)
{
lcMergeSection& MergeSection = MergeSections[LodIdx].Add();
MergeSection.Shared = nullptr;
MergeSection.Lod = Section.get();
}
} }
NumSections[LodIdx] = MergeSections[LodIdx].GetSize(); for (std::unique_ptr<lcMeshLoaderSection>& Section : mData[LodIdx].mSections)
std::sort(MergeSections[LodIdx].begin(), MergeSections[LodIdx].end(), lcLibraryMeshSectionCompare); {
NumIndices += Section->mIndices.GetSize();
AddFinalSection(Section.get(), FinalSections[LodIdx]);
}
NumSections[LodIdx] = FinalSections[LodIdx].GetSize();
std::sort(FinalSections[LodIdx].begin(), FinalSections[LodIdx].end(), lcMeshLoaderFinalSectionCompare);
} }
Mesh->Create(NumSections, NumVertices, NumTexturedVertices, ConditionalVertexCount, NumIndices); Mesh->Create(NumSections, NumVertices, NumTexturedVertices, ConditionalVertexCount, NumIndices);
@ -1070,7 +1127,7 @@ lcMesh* lcLibraryMeshData::CreateMesh()
} }
else if (Section->mPrimitiveType != LC_MESH_CONDITIONAL_LINES) else if (Section->mPrimitiveType != LC_MESH_CONDITIONAL_LINES)
{ {
if (!Section->mTexture) if (Section->mMaterial->Type == lcMeshLoaderMaterialType::Solid)
{ {
for (quint32& Index : Section->mIndices) for (quint32& Index : Section->mIndices)
Index = IndexRemap[MeshDataIdx][Index]; Index = IndexRemap[MeshDataIdx][Index];
@ -1101,9 +1158,9 @@ lcMesh* lcLibraryMeshData::CreateMesh()
} }
if (Mesh->mIndexType == GL_UNSIGNED_SHORT) if (Mesh->mIndexType == GL_UNSIGNED_SHORT)
WriteSections<quint16>(Mesh, MergeSections, BaseVertices, BaseTexturedVertices, BaseConditionalVertices); WriteSections<quint16>(Mesh, FinalSections, BaseVertices, BaseTexturedVertices, BaseConditionalVertices);
else else
WriteSections<quint32>(Mesh, MergeSections, BaseVertices, BaseTexturedVertices, BaseConditionalVertices); WriteSections<quint32>(Mesh, FinalSections, BaseVertices, BaseTexturedVertices, BaseConditionalVertices);
if (mHasStyleStud) if (mHasStyleStud)
Mesh->mFlags |= lcMeshFlag::HasStyleStud; Mesh->mFlags |= lcMeshFlag::HasStyleStud;
@ -1114,40 +1171,45 @@ lcMesh* lcLibraryMeshData::CreateMesh()
} }
template<typename IndexType> template<typename IndexType>
void lcLibraryMeshData::WriteSections(lcMesh* Mesh, const lcArray<lcMergeSection> (&MergeSections)[LC_NUM_MESH_LODS], int(&BaseVertices)[LC_NUM_MESHDATA_TYPES], int(&BaseTexturedVertices)[LC_NUM_MESHDATA_TYPES], int(&BaseConditionalVertices)[LC_NUM_MESHDATA_TYPES]) void lcLibraryMeshData::WriteSections(lcMesh* Mesh, const lcArray<lcMeshLoaderFinalSection> (&FinalSections)[LC_NUM_MESH_LODS], int(&BaseVertices)[LC_NUM_MESHDATA_TYPES], int(&BaseTexturedVertices)[LC_NUM_MESHDATA_TYPES], int(&BaseConditionalVertices)[LC_NUM_MESHDATA_TYPES])
{ {
int NumIndices = 0; int NumIndices = 0;
for (int LodIdx = 0; LodIdx < LC_NUM_MESH_LODS; LodIdx++) for (int LodIdx = 0; LodIdx < LC_NUM_MESH_LODS; LodIdx++)
{ {
for (int SectionIdx = 0; SectionIdx < MergeSections[LodIdx].GetSize(); SectionIdx++) for (int SectionIdx = 0; SectionIdx < FinalSections[LodIdx].GetSize(); SectionIdx++)
{ {
const lcMergeSection& MergeSection = MergeSections[LodIdx][SectionIdx]; const lcMeshLoaderFinalSection& FinalSection = FinalSections[LodIdx][SectionIdx];
lcMeshSection& DstSection = Mesh->mLods[LodIdx].Sections[SectionIdx]; lcMeshSection& DstSection = Mesh->mLods[LodIdx].Sections[SectionIdx];
lcMeshLoaderSection* SetupSection = MergeSection.Shared ? MergeSection.Shared : MergeSection.Lod; DstSection.ColorIndex = FinalSection.Color;
DstSection.PrimitiveType = FinalSection.PrimitiveType;
DstSection.ColorIndex = SetupSection->mColor;
DstSection.PrimitiveType = SetupSection->mPrimitiveType;
DstSection.NumIndices = 0; DstSection.NumIndices = 0;
DstSection.Texture = SetupSection->mTexture;
if (DstSection.Texture) if (!FinalSection.Name[0])
DstSection.Texture->AddRef(); DstSection.Texture = nullptr;
else
{
if (mMeshLoader)
DstSection.Texture = lcGetPiecesLibrary()->FindTexture(FinalSection.Name, mMeshLoader->mCurrentProject, mMeshLoader->mSearchProjectFolder);
else
DstSection.Texture = lcGetPiecesLibrary()->FindTexture(FinalSection.Name, nullptr, false);
if (DstSection.Texture)
DstSection.Texture->AddRef();
}
DstSection.IndexOffset = NumIndices * sizeof(IndexType); DstSection.IndexOffset = NumIndices * sizeof(IndexType);
IndexType* Index = (IndexType*)Mesh->mIndexData + NumIndices; IndexType* Index = (IndexType*)Mesh->mIndexData + NumIndices;
if (MergeSection.Shared) auto AddSection = [this, &DstSection, &Index, &BaseVertices, &BaseTexturedVertices, &BaseConditionalVertices](lcMeshLoaderSection* SrcSection, lcMeshDataType SrcDataType)
{ {
lcMeshLoaderSection* SrcSection = MergeSection.Shared;
if (DstSection.PrimitiveType != LC_MESH_CONDITIONAL_LINES) if (DstSection.PrimitiveType != LC_MESH_CONDITIONAL_LINES)
{ {
if (!mHasTextures) if (!mHasTextures)
{ {
IndexType BaseVertex = DstSection.Texture ? BaseTexturedVertices[LC_MESHDATA_SHARED] : BaseVertices[LC_MESHDATA_SHARED]; IndexType BaseVertex = DstSection.Texture ? BaseTexturedVertices[SrcDataType] : BaseVertices[SrcDataType];
for (int IndexIdx = 0; IndexIdx < SrcSection->mIndices.GetSize(); IndexIdx++) for (int IndexIdx = 0; IndexIdx < SrcSection->mIndices.GetSize(); IndexIdx++)
*Index++ = BaseVertex + SrcSection->mIndices[IndexIdx]; *Index++ = BaseVertex + SrcSection->mIndices[IndexIdx];
@ -1158,42 +1220,24 @@ void lcLibraryMeshData::WriteSections(lcMesh* Mesh, const lcArray<lcMergeSection
} }
else else
{ {
IndexType BaseVertex = BaseConditionalVertices[LC_MESHDATA_SHARED]; IndexType BaseVertex = BaseConditionalVertices[SrcDataType];
for (int IndexIdx = 0; IndexIdx < SrcSection->mIndices.GetSize(); IndexIdx++) for (int IndexIdx = 0; IndexIdx < SrcSection->mIndices.GetSize(); IndexIdx++)
*Index++ = BaseVertex + SrcSection->mIndices[IndexIdx]; *Index++ = BaseVertex + SrcSection->mIndices[IndexIdx];
} }
DstSection.NumIndices += SrcSection->mIndices.GetSize(); DstSection.NumIndices += SrcSection->mIndices.GetSize();
} };
if (MergeSection.Lod) for (std::unique_ptr<lcMeshLoaderSection>& Section : mData[LC_MESHDATA_SHARED].mSections)
{ if (FinalSection.PrimitiveType == Section->mPrimitiveType && FinalSection.Color == Section->mMaterial->Color && !strcmp(FinalSection.Name, Section->mMaterial->Name))
lcMeshLoaderSection* SrcSection = MergeSection.Lod; AddSection(Section.get(), LC_MESHDATA_SHARED);
if (DstSection.PrimitiveType != LC_MESH_CONDITIONAL_LINES) const lcMeshDataType MeshDataType = (LodIdx == LC_MESH_LOD_LOW) ? LC_MESHDATA_LOW : LC_MESHDATA_HIGH;
{
if (!mHasTextures)
{
IndexType BaseVertex = DstSection.Texture ? BaseTexturedVertices[LodIdx] : BaseVertices[LodIdx];
for (int IndexIdx = 0; IndexIdx < SrcSection->mIndices.GetSize(); IndexIdx++) for (std::unique_ptr<lcMeshLoaderSection>& Section : mData[MeshDataType].mSections)
*Index++ = BaseVertex + SrcSection->mIndices[IndexIdx]; if (FinalSection.PrimitiveType == Section->mPrimitiveType && FinalSection.Color == Section->mMaterial->Color && !strcmp(FinalSection.Name, Section->mMaterial->Name))
} AddSection(Section.get(), MeshDataType);
else
for (int IndexIdx = 0; IndexIdx < SrcSection->mIndices.GetSize(); IndexIdx++)
*Index++ = SrcSection->mIndices[IndexIdx];
}
else
{
IndexType BaseVertex = BaseConditionalVertices[LodIdx];
for (int IndexIdx = 0; IndexIdx < SrcSection->mIndices.GetSize(); IndexIdx++)
*Index++ = BaseVertex + SrcSection->mIndices[IndexIdx];
}
DstSection.NumIndices += SrcSection->mIndices.GetSize();
}
if (DstSection.PrimitiveType == LC_MESH_TRIANGLES || DstSection.PrimitiveType == LC_MESH_TEXTURED_TRIANGLES) if (DstSection.PrimitiveType == LC_MESH_TRIANGLES || DstSection.PrimitiveType == LC_MESH_TEXTURED_TRIANGLES)
{ {
@ -1304,6 +1348,7 @@ void lcLibraryMeshData::UpdateMeshSectionBoundingBox(lcMesh* Mesh, lcMeshSection
lcMeshLoader::lcMeshLoader(lcLibraryMeshData& MeshData, bool Optimize, Project* CurrentProject, bool SearchProjectFolder) lcMeshLoader::lcMeshLoader(lcLibraryMeshData& MeshData, bool Optimize, Project* CurrentProject, bool SearchProjectFolder)
: mMeshData(MeshData), mOptimize(Optimize), mCurrentProject(CurrentProject), mSearchProjectFolder(SearchProjectFolder) : mMeshData(MeshData), mOptimize(Optimize), mCurrentProject(CurrentProject), mSearchProjectFolder(SearchProjectFolder)
{ {
MeshData.SetMeshLoader(this);
} }
bool lcMeshLoader::LoadMesh(lcFile& File, lcMeshDataType MeshDataType) bool lcMeshLoader::LoadMesh(lcFile& File, lcMeshDataType MeshDataType)
@ -1411,22 +1456,19 @@ bool lcMeshLoader::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransform
{ {
Token += 7; Token += 7;
char FileName[LC_MAXPATH]; lcMeshLoaderTextureMap& Map = mTextureStack.Add();
lcVector3 Points[3]; lcVector3 (&Points)[3] = Map.Points;
sscanf(Token, "%f %f %f %f %f %f %f %f %f %s", &Points[0].x, &Points[0].y, &Points[0].z, &Points[1].x, &Points[1].y, &Points[1].z, &Points[2].x, &Points[2].y, &Points[2].z, FileName); sscanf(Token, "%f %f %f %f %f %f %f %f %f %s", &Points[0].x, &Points[0].y, &Points[0].z, &Points[1].x, &Points[1].y, &Points[1].z, &Points[2].x, &Points[2].y, &Points[2].z, Map.Name);
Points[0] = lcMul31(Points[0], CurrentTransform); Points[0] = lcMul31(Points[0], CurrentTransform);
Points[1] = lcMul31(Points[1], CurrentTransform); Points[1] = lcMul31(Points[1], CurrentTransform);
Points[2] = lcMul31(Points[2], CurrentTransform); Points[2] = lcMul31(Points[2], CurrentTransform);
CleanTextureName(FileName); CleanTextureName(Map.Name);
lcMeshLoaderTextureMap& Map = mTextureStack.Add(); // Map.Texture = Library->FindTexture(Map.Name, mCurrentProject, mSearchProjectFolder);
Map.Next = false; Map.Type = lcMeshLoaderMaterialType::Planar;
Map.Fallback = false;
Map.Texture = Library->FindTexture(FileName, mCurrentProject, mSearchProjectFolder);
Map.Type = lcMeshLoaderTextureMapType::Planar;
for (int EdgeIdx = 0; EdgeIdx < 2; EdgeIdx++) for (int EdgeIdx = 0; EdgeIdx < 2; EdgeIdx++)
{ {
@ -1444,24 +1486,21 @@ bool lcMeshLoader::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransform
{ {
Token += 12; Token += 12;
char FileName[LC_MAXPATH]; lcMeshLoaderTextureMap& Map = mTextureStack.Add();
lcVector3 Points[3]; lcVector3 (&Points)[3] = Map.Points;
float Angle; float& Angle = Map.Angles[0];
sscanf(Token, "%f %f %f %f %f %f %f %f %f %f %s", &Points[0].x, &Points[0].y, &Points[0].z, &Points[1].x, &Points[1].y, &Points[1].z, &Points[2].x, &Points[2].y, &Points[2].z, &Angle, FileName); sscanf(Token, "%f %f %f %f %f %f %f %f %f %f %s", &Points[0].x, &Points[0].y, &Points[0].z, &Points[1].x, &Points[1].y, &Points[1].z, &Points[2].x, &Points[2].y, &Points[2].z, &Angle, Map.Name);
Points[0] = lcMul31(Points[0], CurrentTransform); Points[0] = lcMul31(Points[0], CurrentTransform);
Points[1] = lcMul31(Points[1], CurrentTransform); Points[1] = lcMul31(Points[1], CurrentTransform);
Points[2] = lcMul31(Points[2], CurrentTransform); Points[2] = lcMul31(Points[2], CurrentTransform);
CleanTextureName(FileName); CleanTextureName(Map.Name);
lcMeshLoaderTextureMap& Map = mTextureStack.Add(); // Map.Texture = Library->FindTexture(Map.Name, mCurrentProject, mSearchProjectFolder);
Map.Next = false; Map.Type = lcMeshLoaderMaterialType::Cylindrical;
Map.Fallback = false;
Map.Texture = Library->FindTexture(FileName, mCurrentProject, mSearchProjectFolder);
Map.Type = lcMeshLoaderTextureMapType::Cylindrical;
lcVector3 Up = Points[0] - Points[1]; lcVector3 Up = Points[0] - Points[1];
float UpLength = lcLength(Up); float UpLength = lcLength(Up);
lcVector3 Front = lcNormalize(Points[2] - Points[1]); lcVector3 Front = lcNormalize(Points[2] - Points[1]);
@ -1477,23 +1516,21 @@ bool lcMeshLoader::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransform
{ {
Token += 10; Token += 10;
char FileName[LC_MAXPATH]; lcMeshLoaderTextureMap& Map = mTextureStack.Add();
lcVector3 Points[3]; lcVector3(&Points)[3] = Map.Points;
float Angle1, Angle2; float& Angle1 = Map.Angles[0];
float& Angle2 = Map.Angles[1];
sscanf(Token, "%f %f %f %f %f %f %f %f %f %f %f %s", &Points[0].x, &Points[0].y, &Points[0].z, &Points[1].x, &Points[1].y, &Points[1].z, &Points[2].x, &Points[2].y, &Points[2].z, &Angle1, &Angle2, FileName); sscanf(Token, "%f %f %f %f %f %f %f %f %f %f %f %s", &Points[0].x, &Points[0].y, &Points[0].z, &Points[1].x, &Points[1].y, &Points[1].z, &Points[2].x, &Points[2].y, &Points[2].z, &Angle1, &Angle2, Map.Name);
Points[0] = lcMul31(Points[0], CurrentTransform); Points[0] = lcMul31(Points[0], CurrentTransform);
Points[1] = lcMul31(Points[1], CurrentTransform); Points[1] = lcMul31(Points[1], CurrentTransform);
Points[2] = lcMul31(Points[2], CurrentTransform); Points[2] = lcMul31(Points[2], CurrentTransform);
CleanTextureName(FileName); CleanTextureName(Map.Name);
lcMeshLoaderTextureMap& Map = mTextureStack.Add(); // Map.Texture = Library->FindTexture(Map.Name, mCurrentProject, mSearchProjectFolder);
Map.Next = false; Map.Type = lcMeshLoaderMaterialType::Spherical;
Map.Fallback = false;
Map.Texture = Library->FindTexture(FileName, mCurrentProject, mSearchProjectFolder);
Map.Type = lcMeshLoaderTextureMapType::Spherical;
lcVector3 Front = lcNormalize(Points[1] - Points[0]); lcVector3 Front = lcNormalize(Points[1] - Points[0]);
lcVector3 Plane1Normal = lcNormalize(lcCross(Front, Points[2] - Points[0])); lcVector3 Plane1Normal = lcNormalize(lcCross(Front, Points[2] - Points[0]));
@ -1579,18 +1616,18 @@ bool lcMeshLoader::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransform
{ {
TextureMap = &mTextureStack[mTextureStack.GetSize() - 1]; TextureMap = &mTextureStack[mTextureStack.GetSize() - 1];
if (TextureMap->Texture) // if (TextureMap->Texture)
{ {
if (TextureMap->Fallback) if (TextureMap->Fallback)
continue; continue;
} }
else // else
{ // {
if (!TextureMap->Fallback) // if (!TextureMap->Fallback)
continue; // continue;
//
TextureMap = nullptr; // TextureMap = nullptr;
} // }
} }
int Dummy; int Dummy;
@ -1656,7 +1693,7 @@ bool lcMeshLoader::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransform
Points[0] = lcMul31(Points[0], CurrentTransform); Points[0] = lcMul31(Points[0], CurrentTransform);
Points[1] = lcMul31(Points[1], CurrentTransform); Points[1] = lcMul31(Points[1], CurrentTransform);
mMeshData.mData[MeshDataType].ProcessLine(LineType, ColorCode, WindingCCW, Points, mOptimize); mMeshData.mData[MeshDataType].ProcessLine(LineType, mMeshData.GetMaterial(ColorCode), WindingCCW, Points, mOptimize);
break; break;
case 3: case 3:
@ -1667,16 +1704,16 @@ bool lcMeshLoader::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransform
Points[1] = lcMul31(Points[1], CurrentTransform); Points[1] = lcMul31(Points[1], CurrentTransform);
Points[2] = lcMul31(Points[2], CurrentTransform); Points[2] = lcMul31(Points[2], CurrentTransform);
if (TextureMap) if (!TextureMap)
mMeshData.mData[MeshDataType].ProcessLine(LineType, mMeshData.GetMaterial(ColorCode), WindingCCW, Points, mOptimize);
else
{ {
mMeshData.mHasTextures = true; mMeshData.mHasTextures = true;
mMeshData.mData[MeshDataType].ProcessTexturedLine(LineType, ColorCode, WindingCCW, *TextureMap, Points, mOptimize); mMeshData.mData[MeshDataType].ProcessTexturedLine(LineType, mMeshData.GetTexturedMaterial(ColorCode, *TextureMap), WindingCCW, *TextureMap, Points, mOptimize);
if (TextureMap->Next) if (TextureMap->Next)
mTextureStack.RemoveIndex(mTextureStack.GetSize() - 1); mTextureStack.RemoveIndex(mTextureStack.GetSize() - 1);
} }
else
mMeshData.mData[MeshDataType].ProcessLine(LineType, ColorCode, WindingCCW, Points, mOptimize);
break; break;
case 4: case 4:
@ -1688,16 +1725,16 @@ bool lcMeshLoader::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransform
Points[2] = lcMul31(Points[2], CurrentTransform); Points[2] = lcMul31(Points[2], CurrentTransform);
Points[3] = lcMul31(Points[3], CurrentTransform); Points[3] = lcMul31(Points[3], CurrentTransform);
if (TextureMap) if (!TextureMap)
mMeshData.mData[MeshDataType].ProcessLine(LineType, mMeshData.GetMaterial(ColorCode), WindingCCW, Points, mOptimize);
else
{ {
mMeshData.mHasTextures = true; mMeshData.mHasTextures = true;
mMeshData.mData[MeshDataType].ProcessTexturedLine(LineType, ColorCode, WindingCCW, *TextureMap, Points, mOptimize); mMeshData.mData[MeshDataType].ProcessTexturedLine(LineType, mMeshData.GetTexturedMaterial(ColorCode, *TextureMap), WindingCCW, *TextureMap, Points, mOptimize);
if (TextureMap->Next) if (TextureMap->Next)
mTextureStack.RemoveIndex(mTextureStack.GetSize() - 1); mTextureStack.RemoveIndex(mTextureStack.GetSize() - 1);
} }
else
mMeshData.mData[MeshDataType].ProcessLine(LineType, ColorCode, WindingCCW, Points, mOptimize);
break; break;
case 5: case 5:
@ -1709,7 +1746,7 @@ bool lcMeshLoader::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransform
Points[2] = lcMul31(Points[2], CurrentTransform); Points[2] = lcMul31(Points[2], CurrentTransform);
Points[3] = lcMul31(Points[3], CurrentTransform); Points[3] = lcMul31(Points[3], CurrentTransform);
mMeshData.mData[MeshDataType].ProcessLine(LineType, ColorCode, WindingCCW, Points, mOptimize); mMeshData.mData[MeshDataType].ProcessLine(LineType, mMeshData.GetMaterial(ColorCode), WindingCCW, Points, mOptimize);
break; break;
} }

View file

@ -4,6 +4,9 @@
#include "lc_math.h" #include "lc_math.h"
#include "lc_mesh.h" #include "lc_mesh.h"
class lcLibraryMeshData;
class lcMeshLoader;
#define LC_LIBRARY_VERTEX_UNTEXTURED 0x1 #define LC_LIBRARY_VERTEX_UNTEXTURED 0x1
#define LC_LIBRARY_VERTEX_TEXTURED 0x2 #define LC_LIBRARY_VERTEX_TEXTURED 0x2
@ -29,39 +32,46 @@ struct lcMeshLoaderConditionalVertex
lcVector3 Position[4]; lcVector3 Position[4];
}; };
class lcMeshLoaderSection enum class lcMeshLoaderMaterialType
{
public:
lcMeshLoaderSection(lcMeshPrimitiveType PrimitiveType, quint32 Color, lcTexture* Texture)
: mIndices(1024, 1024)
{
mPrimitiveType = PrimitiveType;
mColor = Color;
mTexture = Texture;
}
lcMeshPrimitiveType mPrimitiveType;
quint32 mColor;
lcTexture* mTexture;
lcArray<quint32> mIndices;
};
struct lcMergeSection
{
lcMeshLoaderSection* Shared;
lcMeshLoaderSection* Lod;
};
enum class lcMeshLoaderTextureMapType
{ {
Solid,
Planar, Planar,
Cylindrical, Cylindrical,
Spherical Spherical
}; };
struct lcMeshLoaderMaterial
{
lcMeshLoaderMaterialType Type = lcMeshLoaderMaterialType::Solid;
quint32 Color = 16;
lcVector3 Points[3] = {};
float Angles[2] = {};
char Name[256] = {};
};
class lcMeshLoaderSection
{
public:
lcMeshLoaderSection(lcMeshPrimitiveType PrimitiveType, lcMeshLoaderMaterial* Material)
: mMaterial(Material), mPrimitiveType(PrimitiveType), mIndices(1024, 1024)
{
}
lcMeshLoaderMaterial* mMaterial;
lcMeshPrimitiveType mPrimitiveType;
lcArray<quint32> mIndices;
};
struct lcMeshLoaderFinalSection
{
quint32 Color;
lcMeshPrimitiveType PrimitiveType;
char Name[256];
};
struct lcMeshLoaderTextureMap struct lcMeshLoaderTextureMap
{ {
lcTexture* Texture; // lcTexture* Texture;
union lcTextureMapParams union lcTextureMapParams
{ {
@ -94,9 +104,13 @@ struct lcMeshLoaderTextureMap
} Spherical; } Spherical;
} Params; } Params;
lcMeshLoaderTextureMapType Type; lcMeshLoaderMaterialType Type;
bool Fallback; lcVector3 Points[3];
bool Next; float Angles[2];
char Name[LC_MAXPATH];
bool Fallback = false;
bool Next = false;
}; };
class lcMeshLoaderTypeData class lcMeshLoaderTypeData
@ -123,7 +137,12 @@ public:
mConditionalVertices.RemoveAll(); mConditionalVertices.RemoveAll();
} }
lcMeshLoaderSection* AddSection(lcMeshPrimitiveType PrimitiveType, quint32 ColorCode, lcTexture* Texture); void SetMeshData(lcLibraryMeshData* MeshData)
{
mMeshData = MeshData;
}
lcMeshLoaderSection* AddSection(lcMeshPrimitiveType PrimitiveType, lcMeshLoaderMaterial* Material);
quint32 AddVertex(const lcVector3& Position, bool Optimize); quint32 AddVertex(const lcVector3& Position, bool Optimize);
quint32 AddVertex(const lcVector3& Position, const lcVector3& Normal, bool Optimize); quint32 AddVertex(const lcVector3& Position, const lcVector3& Normal, bool Optimize);
@ -131,8 +150,8 @@ public:
quint32 AddTexturedVertex(const lcVector3& Position, const lcVector3& Normal, const lcVector2& TexCoord, bool Optimize); quint32 AddTexturedVertex(const lcVector3& Position, const lcVector3& Normal, const lcVector2& TexCoord, bool Optimize);
quint32 AddConditionalVertex(const lcVector3 (&Position)[4]); quint32 AddConditionalVertex(const lcVector3 (&Position)[4]);
void ProcessLine(int LineType, quint32 ColorCode, bool WindingCCW, lcVector3 (&Vertices)[4], bool Optimize); void ProcessLine(int LineType, lcMeshLoaderMaterial* Material, bool WindingCCW, lcVector3 (&Vertices)[4], bool Optimize);
void ProcessTexturedLine(int LineType, quint32 ColorCode, bool WindingCCW, const lcMeshLoaderTextureMap& Map, const lcVector3* Vertices, bool Optimize); void ProcessTexturedLine(int LineType, lcMeshLoaderMaterial* Material, bool WindingCCW, const lcMeshLoaderTextureMap& Map, const lcVector3* Vertices, bool Optimize);
void AddMeshData(const lcMeshLoaderTypeData& Data, const lcMatrix44& Transform, quint32 CurrentColorCode, bool InvertWinding, bool InvertNormals, lcMeshLoaderTextureMap* TextureMap); void AddMeshData(const lcMeshLoaderTypeData& Data, const lcMatrix44& Transform, quint32 CurrentColorCode, bool InvertWinding, bool InvertNormals, lcMeshLoaderTextureMap* TextureMap);
void AddMeshDataNoDuplicateCheck(const lcMeshLoaderTypeData& Data, const lcMatrix44& Transform, quint32 CurrentColorCode, bool InvertWinding, bool InvertNormals, lcMeshLoaderTextureMap* TextureMap); void AddMeshDataNoDuplicateCheck(const lcMeshLoaderTypeData& Data, const lcMatrix44& Transform, quint32 CurrentColorCode, bool InvertWinding, bool InvertNormals, lcMeshLoaderTextureMap* TextureMap);
@ -140,6 +159,9 @@ public:
std::vector<std::unique_ptr<lcMeshLoaderSection>> mSections; std::vector<std::unique_ptr<lcMeshLoaderSection>> mSections;
lcArray<lcMeshLoaderVertex> mVertices; lcArray<lcMeshLoaderVertex> mVertices;
lcArray<lcMeshLoaderConditionalVertex> mConditionalVertices; lcArray<lcMeshLoaderConditionalVertex> mConditionalVertices;
protected:
lcLibraryMeshData* mMeshData;
}; };
class lcLibraryMeshData class lcLibraryMeshData
@ -149,6 +171,9 @@ public:
{ {
mHasTextures = false; mHasTextures = false;
mHasStyleStud = false; mHasStyleStud = false;
for (lcMeshLoaderTypeData& Data : mData)
Data.SetMeshData(this);
} }
lcLibraryMeshData(const lcLibraryMeshData&) = delete; lcLibraryMeshData(const lcLibraryMeshData&) = delete;
@ -172,19 +197,30 @@ public:
mHasStyleStud = false; mHasStyleStud = false;
} }
void SetMeshLoader(lcMeshLoader* MeshLoader)
{
mMeshLoader = MeshLoader;
}
lcMesh* CreateMesh(); lcMesh* CreateMesh();
void AddVertices(lcMeshDataType MeshDataType, int VertexCount, int* BaseVertex, lcMeshLoaderVertex** VertexBuffer); void AddVertices(lcMeshDataType MeshDataType, int VertexCount, int* BaseVertex, lcMeshLoaderVertex** VertexBuffer);
void AddIndices(lcMeshDataType MeshDataType, lcMeshPrimitiveType PrimitiveType, quint32 ColorCode, int IndexCount, quint32** IndexBuffer); void AddIndices(lcMeshDataType MeshDataType, lcMeshPrimitiveType PrimitiveType, quint32 ColorCode, int IndexCount, quint32** IndexBuffer);
void AddMeshData(const lcLibraryMeshData& Data, const lcMatrix44& Transform, quint32 CurrentColorCode, bool InvertWinding, bool InvertNormals, lcMeshLoaderTextureMap* TextureMap, lcMeshDataType OverrideDestIndex); void AddMeshData(const lcLibraryMeshData& Data, const lcMatrix44& Transform, quint32 CurrentColorCode, bool InvertWinding, bool InvertNormals, lcMeshLoaderTextureMap* TextureMap, lcMeshDataType OverrideDestIndex);
void AddMeshDataNoDuplicateCheck(const lcLibraryMeshData& Data, const lcMatrix44& Transform, quint32 CurrentColorCode, bool InvertWinding, bool InvertNormals, lcMeshLoaderTextureMap* TextureMap, lcMeshDataType OverrideDestIndex); void AddMeshDataNoDuplicateCheck(const lcLibraryMeshData& Data, const lcMatrix44& Transform, quint32 CurrentColorCode, bool InvertWinding, bool InvertNormals, lcMeshLoaderTextureMap* TextureMap, lcMeshDataType OverrideDestIndex);
lcMeshLoaderMaterial* GetMaterial(quint32 ColorCode);
lcMeshLoaderMaterial* GetTexturedMaterial(quint32 ColorCode, const lcMeshLoaderTextureMap& TextureMap);
std::array<lcMeshLoaderTypeData, LC_NUM_MESHDATA_TYPES> mData; std::array<lcMeshLoaderTypeData, LC_NUM_MESHDATA_TYPES> mData;
bool mHasTextures; bool mHasTextures;
bool mHasStyleStud; bool mHasStyleStud;
protected: protected:
lcMeshLoader* mMeshLoader = nullptr;
std::vector<std::unique_ptr<lcMeshLoaderMaterial>> mMaterials;
template<typename IndexType> template<typename IndexType>
void WriteSections(lcMesh* Mesh, const lcArray<lcMergeSection> (&MergeSections)[LC_NUM_MESH_LODS], int (&BaseVertices)[LC_NUM_MESHDATA_TYPES], int (&BaseTexturedVertices)[LC_NUM_MESHDATA_TYPES], int (&BaseConditionalVertices)[LC_NUM_MESHDATA_TYPES]); void WriteSections(lcMesh* Mesh, const lcArray<lcMeshLoaderFinalSection> (&FinalSections)[LC_NUM_MESH_LODS], int (&BaseVertices)[LC_NUM_MESHDATA_TYPES], int (&BaseTexturedVertices)[LC_NUM_MESHDATA_TYPES], int (&BaseConditionalVertices)[LC_NUM_MESHDATA_TYPES]);
static void UpdateMeshBoundingBox(lcMesh* Mesh); static void UpdateMeshBoundingBox(lcMesh* Mesh);
template<typename IndexType> template<typename IndexType>
@ -198,12 +234,14 @@ public:
bool LoadMesh(lcFile& File, lcMeshDataType MeshDataType); bool LoadMesh(lcFile& File, lcMeshDataType MeshDataType);
Project* mCurrentProject;
bool mSearchProjectFolder;
protected: protected:
bool ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransform, quint32 CurrentColorCode, bool InvertWinding, lcMeshDataType MeshDataType); bool ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransform, quint32 CurrentColorCode, bool InvertWinding, lcMeshDataType MeshDataType);
lcArray<lcMeshLoaderTextureMap> mTextureStack; lcArray<lcMeshLoaderTextureMap> mTextureStack;
lcLibraryMeshData& mMeshData; lcLibraryMeshData& mMeshData;
bool mOptimize; bool mOptimize;
Project* mCurrentProject;
bool mSearchProjectFolder;
}; };