Support exporting flexible parts. Fixes #157.

This commit is contained in:
Leonardo Zide 2019-05-26 11:08:47 -07:00
parent 602dfeb8b6
commit 3070d25663
9 changed files with 149 additions and 104 deletions

View file

@ -10,6 +10,7 @@
#include <QtGui>
#include <QPrinter>
#include <array>
#include <set>
#ifndef Q_FALLTHROUGH
#define Q_FALLTHROUGH(); // fall through

View file

@ -3124,17 +3124,7 @@ void lcModel::GetPartsListForStep(lcStep Step, int DefaultColorIndex, lcPartsLis
void lcModel::GetModelParts(const lcMatrix44& WorldMatrix, int DefaultColorIndex, lcArray<lcModelPartsEntry>& ModelParts) const
{
for (lcPiece* Piece : mPieces)
{
if (!Piece->IsVisibleInSubModel())
continue;
int ColorIndex = Piece->mColorIndex;
if (ColorIndex == gDefaultColor)
ColorIndex = DefaultColorIndex;
Piece->mPieceInfo->GetModelParts(lcMul(Piece->mModelWorld, WorldMatrix), ColorIndex, ModelParts);
}
Piece->GetModelParts(WorldMatrix, DefaultColorIndex, ModelParts);
}
void lcModel::GetSelectionInformation(int* Flags, lcArray<lcObject*>& Selection, lcObject** Focus) const

View file

@ -91,13 +91,6 @@ struct lcModelHistoryEntry
QString Description;
};
struct lcModelPartsEntry
{
lcMatrix44 WorldMatrix;
PieceInfo* Info;
int ColorIndex;
};
class lcModel
{
public:

View file

@ -863,6 +863,28 @@ bool lcPiece::IsVisibleInSubModel() const
return (mStepHide == LC_STEP_MAX) && !(mState & LC_PIECE_HIDDEN);
}
void lcPiece::GetModelParts(const lcMatrix44& WorldMatrix, int DefaultColorIndex, lcArray<lcModelPartsEntry>& ModelParts) const
{
if (!IsVisibleInSubModel())
return;
int ColorIndex = mColorIndex;
if (ColorIndex == gDefaultColor)
ColorIndex = DefaultColorIndex;
if (!mMesh)
mPieceInfo->GetModelParts(lcMul(mModelWorld, WorldMatrix), ColorIndex, ModelParts);
else
{
lcModelPartsEntry& ModelPartsEntry = ModelParts.Add();
ModelPartsEntry.WorldMatrix = WorldMatrix;
ModelPartsEntry.ColorIndex = DefaultColorIndex;
ModelPartsEntry.Info = const_cast<PieceInfo*>(mPieceInfo);
ModelPartsEntry.Mesh = mMesh;
}
}
const lcBoundingBox& lcPiece::GetBoundingBox() const
{
if (!mMesh)

View file

@ -396,6 +396,7 @@ public:
const char* GetName() const override;
bool IsVisible(lcStep Step) const;
bool IsVisibleInSubModel() const;
void GetModelParts(const lcMatrix44& WorldMatrix, int DefaultColorIndex, lcArray<lcModelPartsEntry>& ModelParts) const;
void Initialize(const lcMatrix44& WorldMatrix, lcStep Step);
const lcBoundingBox& GetBoundingBox() const;
void CompareBoundingBox(lcVector3& Min, lcVector3& Max) const;

View file

@ -354,6 +354,7 @@ void PieceInfo::GetModelParts(const lcMatrix44& WorldMatrix, int DefaultColorInd
ModelPartsEntry.WorldMatrix = WorldMatrix;
ModelPartsEntry.ColorIndex = DefaultColorIndex;
ModelPartsEntry.Info = const_cast<PieceInfo*>(this);
ModelPartsEntry.Mesh = nullptr;
}
void PieceInfo::UpdateBoundingBox(std::vector<lcModel*>& UpdatedModels)

View file

@ -22,6 +22,14 @@ enum lcPieceInfoState
LC_PIECEINFO_LOADED
};
struct lcModelPartsEntry
{
lcMatrix44 WorldMatrix;
PieceInfo* Info;
lcMesh* Mesh;
int ColorIndex;
};
class lcSynthInfo;
class PieceInfo

View file

@ -615,8 +615,8 @@ void Project::GetModelParts(lcArray<lcModelPartsEntry>& ModelParts)
if (mModels.IsEmpty())
return;
for (int ModelIdx = 0; ModelIdx < mModels.GetSize(); ModelIdx++)
mModels[ModelIdx]->CalculateStep(LC_STEP_MAX);
for (lcModel* Model : mModels)
Model->CalculateStep(LC_STEP_MAX);
mModels[0]->GetModelParts(lcMatrix44Identity(), gDefaultColor, ModelParts);
@ -958,10 +958,9 @@ void Project::Export3DStudio(const QString& FileName)
}
int NumPieces = 0;
for (int PartIdx = 0; PartIdx < ModelParts.GetSize(); PartIdx++)
for (const lcModelPartsEntry& ModelPart : ModelParts)
{
PieceInfo* Info = ModelParts[PartIdx].Info;
lcMesh* Mesh = Info->GetMesh();
lcMesh* Mesh = !ModelPart.Mesh ? ModelPart.Info->GetMesh() : ModelPart.Mesh;
if (!Mesh || Mesh->mIndexType == GL_UNSIGNED_INT)
continue;
@ -985,7 +984,7 @@ void Project::Export3DStudio(const QString& FileName)
File.WriteU16(Mesh->mNumVertices);
lcVertex* Verts = (lcVertex*)Mesh->mVertexData;
const lcMatrix44& ModelWorld = ModelParts[PartIdx].WorldMatrix;
const lcMatrix44& ModelWorld = ModelPart.WorldMatrix;
for (int VertexIdx = 0; VertexIdx < Mesh->mNumVertices; VertexIdx++)
{
@ -1054,7 +1053,7 @@ void Project::Export3DStudio(const QString& FileName)
if (Section->PrimitiveType != LC_MESH_TRIANGLES && Section->PrimitiveType != LC_MESH_TEXTURED_TRIANGLES)
continue;
int MaterialIndex = Section->ColorIndex == gDefaultColor ? ModelParts[PartIdx].ColorIndex : Section->ColorIndex;
int MaterialIndex = Section->ColorIndex == gDefaultColor ? ModelPart.ColorIndex : Section->ColorIndex;
File.WriteU16(0x4130); // CHK_MSH_MAT_GROUP
File.WriteU32(6 + MaterialNameLength + 1 + 2 + 2 * Section->NumIndices / 3);
@ -1266,18 +1265,27 @@ void Project::ExportCOLLADA(const QString& FileName)
Stream << "</library_materials>\r\n";
Stream << "<library_geometries>\r\n";
QSet<PieceInfo*> AddedPieces;
std::set<lcMesh*> AddedMeshes;
for (const lcModelPartsEntry& Entry : ModelParts)
auto GetMeshID = [](const lcModelPartsEntry& ModelPart)
{
PieceInfo* Info = Entry.Info;
if (AddedPieces.contains(Info))
continue;
AddedPieces.insert(Info);
PieceInfo* Info = ModelPart.Info;
QString ID = QString(Info->mFileName).replace('.', '_');
lcMesh* Mesh = Info->GetMesh();
if (ModelPart.Mesh)
ID += "_" + QString::number((quintptr)ModelPart.Mesh, 16);
return ID;
};
for (const lcModelPartsEntry& ModelPart : ModelParts)
{
lcMesh* Mesh = !ModelPart.Mesh ? ModelPart.Info->GetMesh() : ModelPart.Mesh;
if (!AddedMeshes.insert(Mesh).second)
continue;
QString ID = GetMeshID(ModelPart);
if (!Mesh)
Mesh = gPlaceholderMesh;
@ -1387,15 +1395,14 @@ void Project::ExportCOLLADA(const QString& FileName)
Stream << "<library_visual_scenes>\r\n";
Stream << "\t<visual_scene id=\"DefaultScene\">\r\n";
for (const lcModelPartsEntry& Entry : ModelParts)
for (const lcModelPartsEntry& ModelPart : ModelParts)
{
PieceInfo* Info = Entry.Info;
QString ID = QString(Info->mFileName).replace('.', '_');
QString ID = GetMeshID(ModelPart);
Stream << "\t\t<node>\r\n";
Stream << "\t\t\t<matrix>\r\n";
const lcMatrix44& Matrix = Entry.WorldMatrix;
const lcMatrix44& Matrix = ModelPart.WorldMatrix;
Stream << QString("\t\t\t\t%1 %2 %3 %4\r\n").arg(QString::number(Matrix[0][0]), QString::number(Matrix[1][0]), QString::number(Matrix[2][0]), QString::number(Matrix[3][0]));
Stream << QString("\t\t\t\t%1 %2 %3 %4\r\n").arg(QString::number(Matrix[0][1]), QString::number(Matrix[1][1]), QString::number(Matrix[2][1]), QString::number(Matrix[3][1]));
Stream << QString("\t\t\t\t%1 %2 %3 %4\r\n").arg(QString::number(Matrix[0][2]), QString::number(Matrix[1][2]), QString::number(Matrix[2][2]), QString::number(Matrix[3][2]));
@ -1406,7 +1413,7 @@ void Project::ExportCOLLADA(const QString& FileName)
Stream << "\t\t\t\t<bind_material>\r\n";
Stream << "\t\t\t\t\t<technique_common>\r\n";
lcMesh* Mesh = Info->GetMesh();
lcMesh* Mesh = !ModelPart.Mesh ? ModelPart.Info->GetMesh() : ModelPart.Mesh;
if (!Mesh)
Mesh = gPlaceholderMesh;
@ -1421,7 +1428,7 @@ void Project::ExportCOLLADA(const QString& FileName)
const char* SourceColorName = gColorList[Section->ColorIndex].SafeName;
const char* TargetColorName;
if (Section->ColorIndex == gDefaultColor)
TargetColorName = gColorList[Entry.ColorIndex].SafeName;
TargetColorName = gColorList[ModelPart.ColorIndex].SafeName;
else
TargetColorName = gColorList[Section->ColorIndex].SafeName;
@ -2155,35 +2162,34 @@ bool Project::ExportPOVRay(const QString& FileName)
}
}
std::set<lcMesh*> AddedMeshes;
if (!LGEOPath.isEmpty())
{
POVFile.WriteLine("#include \"lg_defs.inc\"\n#include \"lg_color.inc\"\n\n");
for (int PartIdx = 0; PartIdx < ModelParts.GetSize(); PartIdx++)
for (const lcModelPartsEntry& ModelPart : ModelParts)
{
PieceInfo* Info = ModelParts[PartIdx].Info;
if (ModelPart.Mesh)
continue;
for (int CheckIdx = 0; CheckIdx < ModelParts.GetSize(); CheckIdx++)
auto Search = PieceTable.find(ModelPart.Info);
if (Search == PieceTable.end())
continue;
lcMesh* Mesh = ModelPart.Info->GetMesh();
if (!Mesh)
continue;
if (!AddedMeshes.insert(Mesh).second)
continue;
const std::pair<char[LC_PIECE_NAME_LEN], int>& Entry = Search->second;
if (Entry.first[0])
{
if (ModelParts[CheckIdx].Info != Info)
continue;
if (CheckIdx != PartIdx)
break;
auto Search = PieceTable.find(Info);
if (Search != PieceTable.end())
{
const std::pair<char[LC_PIECE_NAME_LEN], int>& Entry = Search->second;
if (Entry.first[0])
{
sprintf(Line, "#include \"%s.inc\"\n", Entry.first);
POVFile.WriteLine(Line);
}
}
break;
sprintf(Line, "#include \"%s.inc\"\n", Entry.first);
POVFile.WriteLine(Line);
}
}
@ -2218,25 +2224,40 @@ bool Project::ExportPOVRay(const QString& FileName)
for (int ColorIdx = 0; ColorIdx < NumColors; ColorIdx++)
ColorTablePointer[ColorIdx] = ColorTable[ColorIdx].data();
for (int PartIdx = 0; PartIdx < ModelParts.GetSize(); PartIdx++)
auto GetMeshName = [](const lcModelPartsEntry& ModelPart, char* Name)
{
PieceInfo* Info = ModelParts[PartIdx].Info;
lcMesh* Mesh = Info->GetMesh();
std::pair<char[LC_PIECE_NAME_LEN], int>& Entry = PieceTable[Info];
strcpy(Name, ModelPart.Info->mFileName);
if (!Mesh || Entry.first[0])
for (char* c = Name; *c; c++)
if (*c == '-' || *c == '.')
*c = '_';
if (ModelPart.Mesh)
{
char Suffix[32];
sprintf(Suffix, "_%p", ModelPart.Mesh);
strcat(Name, Suffix);
}
};
for (const lcModelPartsEntry& ModelPart : ModelParts)
{
lcMesh* Mesh = !ModelPart.Mesh ? ModelPart.Info->GetMesh() : ModelPart.Mesh;
if (!AddedMeshes.insert(Mesh).second)
continue;
if (!Mesh)
continue;
char Name[LC_PIECE_NAME_LEN];
char* Ptr;
GetMeshName(ModelPart, Name);
strcpy(Name, Info->mFileName);
while ((Ptr = strchr(Name, '-')))
*Ptr = '_';
while ((Ptr = strchr(Name, '.')))
*Ptr = '_';
sprintf(Entry.first, "lc_%s", Name);
if (!ModelPart.Mesh)
{
std::pair<char[LC_PIECE_NAME_LEN], int>& Entry = PieceTable[ModelPart.Info];
sprintf(Entry.first, "lc_%s", Name);
}
Mesh->ExportPOVRay(POVFile, Name, &ColorTablePointer[0]);
@ -2287,32 +2308,41 @@ bool Project::ExportPOVRay(const QString& FileName)
sprintf(Line, "light_source{ <%f, %f, %f>\n color rgb 0.5\n area_light 200, 200, 10, 10\n jitter\n}\n\n", 2.0f * Radius + Center.x, 0.0f * Radius + Center.y, -2.0f * Radius + Center.z);
POVFile.WriteLine(Line);
for (int PartIdx = 0; PartIdx < ModelParts.GetSize(); PartIdx++)
for (const lcModelPartsEntry& ModelPart : ModelParts)
{
PieceInfo* Info = ModelParts[PartIdx].Info;
std::pair<char[LC_PIECE_NAME_LEN], int>& Entry = PieceTable[Info];
int Color;
Color = ModelParts[PartIdx].ColorIndex;
int Color = ModelPart.ColorIndex;
const char* Suffix = lcIsColorTranslucent(Color) ? "_clear" : "";
const float* f = ModelPart.WorldMatrix;
const float* f = ModelParts[PartIdx].WorldMatrix;
if (Entry.second & LGEO_PIECE_SLOPE)
if (!ModelPart.Mesh)
{
sprintf(Line, "merge {\n object {\n %s%s\n texture { %s }\n }\n"
" object {\n %s_slope\n texture { %s normal { bumps 0.3 scale 0.02 } }\n }\n"
" matrix <%.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f>\n}\n",
Entry.first, Suffix, ColorTable[Color].data(), Entry.first, ColorTable[Color].data(),
-f[5], -f[4], -f[6], -f[1], -f[0], -f[2], f[9], f[8], f[10], f[13] / 25.0f, f[12] / 25.0f, f[14] / 25.0f);
std::pair<char[LC_PIECE_NAME_LEN], int>& Entry = PieceTable[ModelPart.Info];
if (Entry.second & LGEO_PIECE_SLOPE)
{
sprintf(Line, "merge {\n object {\n %s%s\n texture { %s }\n }\n"
" object {\n %s_slope\n texture { %s normal { bumps 0.3 scale 0.02 } }\n }\n"
" matrix <%.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f>\n}\n",
Entry.first, Suffix, ColorTable[Color].data(), Entry.first, ColorTable[Color].data(),
-f[5], -f[4], -f[6], -f[1], -f[0], -f[2], f[9], f[8], f[10], f[13] / 25.0f, f[12] / 25.0f, f[14] / 25.0f);
}
else
{
if (!ModelPart.Info || !ModelPart.Info->GetMesh())
continue;
sprintf(Line, "object {\n %s%s\n texture { %s }\n matrix <%.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f>\n}\n",
Entry.first, Suffix, ColorTable[Color].data(), -f[5], -f[4], -f[6], -f[1], -f[0], -f[2], f[9], f[8], f[10], f[13] / 25.0f, f[12] / 25.0f, f[14] / 25.0f);
}
}
else
{
if (!Info || !Info->GetMesh())
continue;
char Name[LC_PIECE_NAME_LEN];
GetMeshName(ModelPart, Name);
sprintf(Line, "object {\n %s%s\n texture { %s }\n matrix <%.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f>\n}\n",
Entry.first, Suffix, ColorTable[Color].data(), -f[5], -f[4], -f[6], -f[1], -f[0], -f[2], f[9], f[8], f[10], f[13] / 25.0f, f[12] / 25.0f, f[14] / 25.0f);
sprintf(Line, "object {\n lc_%s%s\n texture { %s }\n matrix <%.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f>\n}\n",
Name, Suffix, ColorTable[Color].data(), -f[5], -f[4], -f[6], -f[1], -f[0], -f[2], f[9], f[8], f[10], f[13] / 25.0f, f[12] / 25.0f, f[14] / 25.0f);
}
POVFile.WriteLine(Line);
@ -2377,14 +2407,14 @@ void Project::ExportWavefront(const QString& FileName)
MaterialFile.WriteLine(Line);
}
for (int PartIdx = 0; PartIdx < ModelParts.GetSize(); PartIdx++)
for (const lcModelPartsEntry& ModelPart : ModelParts)
{
lcMesh* Mesh = ModelParts[PartIdx].Info->GetMesh();
lcMesh* Mesh = !ModelPart.Mesh ? ModelPart.Info->GetMesh() : ModelPart.Mesh;
if (!Mesh)
continue;
const lcMatrix44& ModelWorld = ModelParts[PartIdx].WorldMatrix;
const lcMatrix44& ModelWorld = ModelPart.WorldMatrix;
lcVertex* Verts = (lcVertex*)Mesh->mVertexData;
for (int VertexIdx = 0; VertexIdx < Mesh->mNumVertices; VertexIdx++)
@ -2397,14 +2427,14 @@ void Project::ExportWavefront(const QString& FileName)
OBJFile.WriteLine("#\n\n");
}
for (int PartIdx = 0; PartIdx < ModelParts.GetSize(); PartIdx++)
for (const lcModelPartsEntry& ModelPart : ModelParts)
{
lcMesh* Mesh = ModelParts[PartIdx].Info->GetMesh();
lcMesh* Mesh = !ModelPart.Mesh ? ModelPart.Info->GetMesh() : ModelPart.Mesh;
if (!Mesh)
continue;
const lcMatrix44& ModelWorld = ModelParts[PartIdx].WorldMatrix;
const lcMatrix44& ModelWorld = ModelPart.WorldMatrix;
lcVertex* Verts = (lcVertex*)Mesh->mVertexData;
for (int VertexIdx = 0; VertexIdx < Mesh->mNumVertices; VertexIdx++)
@ -2419,16 +2449,15 @@ void Project::ExportWavefront(const QString& FileName)
for (int PartIdx = 0; PartIdx < ModelParts.GetSize(); PartIdx++)
{
PieceInfo* Info = ModelParts[PartIdx].Info;
sprintf(Line, "g Piece%.3d\n", PartIdx);
OBJFile.WriteLine(Line);
lcMesh* Mesh = Info->GetMesh();
const lcModelPartsEntry& ModelPart = ModelParts[PartIdx];
lcMesh* Mesh = !ModelPart.Mesh ? ModelPart.Info->GetMesh() : ModelPart.Mesh;
if (Mesh)
{
Mesh->ExportWavefrontIndices(OBJFile, ModelParts[PartIdx].ColorIndex, vert);
Mesh->ExportWavefrontIndices(OBJFile, ModelPart.ColorIndex, vert);
vert += Mesh->mNumVertices;
}
}

View file

@ -14,7 +14,7 @@ equals(QT_MAJOR_VERSION, 5) {
}
INCLUDEPATH += qt common
CONFIG += precompile_header incremental c++11
CONFIG += precompile_header incremental c++11 force_debug_info
win32 {
RC_FILE = qt/leocad.rc