New LDD importer.

This commit is contained in:
Leonardo Zide
2017-07-08 09:29:35 -07:00
parent 91fa2ec9dd
commit 3d7bfdafb0
7 changed files with 7517 additions and 9 deletions
+198 -3
View File
@@ -5,8 +5,203 @@
#include "lc_mainwindow.h"
#include "piece.h"
#include "lc_file.h"
#include <QDomDocument>
bool lcImportLDDFile(const QString& FileData, lcArray<lcPiece*>& Pieces, lcArray<lcArray<lcPiece*>>& Groups)
static bool lcLoadLDrawXML(std::map<int, int>& MaterialTable, std::map<int, std::string>& BrickTable, std::map<std::string, std::pair<lcVector3, lcVector4>>& TransformTable)
{
return false;
}
QFile File(lcGetPiecesLibrary()->mLibraryDir.absoluteFilePath(QLatin1String("ldraw.xml")));
QByteArray Data;
if (File.open(QIODevice::ReadOnly))
Data = File.readAll();
else
{
QResource Resource(":/resources/ldraw.xml");
if (Resource.isValid())
{
if (Resource.isCompressed())
Data = qUncompress(Resource.data(), Resource.size());
else
Data = QByteArray::fromRawData((const char*)Resource.data(), Resource.size());
}
}
if (Data.isEmpty())
return false;
QDomDocument Document;
Document.setContent(QString::fromUtf8(Data));
QDomElement Root = Document.documentElement();
if (Root.tagName() != QLatin1String("LDrawMapping"))
return false;
for (QDomNode Node = Root.firstChild(); !Node.isNull(); Node = Node.nextSibling())
{
QDomElement Element = Node.toElement();
QString ElementName = Element.tagName();
if (ElementName == QLatin1String("Material"))
{
int LDrawColor = Element.attribute(QLatin1String("ldraw")).toInt();
int LegoColor = Element.attribute(QLatin1String("lego")).toInt();
MaterialTable[LegoColor] = LDrawColor;
}
else if (ElementName == QLatin1String("Brick"))
{
QString LDrawID = Element.attribute(QLatin1String("ldraw")).toUpper();
LDrawID.chop(4);
int LegoID = Element.attribute(QLatin1String("lego")).toInt();
BrickTable.emplace(std::make_pair(LegoID, std::move(LDrawID.toStdString())));
}
else if (ElementName == QLatin1String("Transformation"))
{
QString LDrawID = Element.attribute(QLatin1String("ldraw")).toUpper();
LDrawID.chop(4);
lcVector3 Translation;
lcVector4 AxisAngle;
Translation[0] = Element.attribute(QLatin1String("tx")).toFloat();
Translation[1] = Element.attribute(QLatin1String("ty")).toFloat();
Translation[2] = Element.attribute(QLatin1String("tz")).toFloat();
AxisAngle[0] = Element.attribute(QLatin1String("ax")).toFloat();
AxisAngle[1] = Element.attribute(QLatin1String("ay")).toFloat();
AxisAngle[2] = Element.attribute(QLatin1String("az")).toFloat();
AxisAngle[3] = Element.attribute(QLatin1String("angle")).toFloat();
TransformTable.emplace(std::make_pair(std::move(LDrawID.toStdString()), std::make_pair(Translation, AxisAngle)));
}
}
return true;
}
bool lcImportLXFMLFile(const QString& FileData, lcArray<lcPiece*>& Pieces, lcArray<lcArray<lcPiece*>>& Groups)
{
std::map<int, int> MaterialTable;
std::map<int, std::string> BrickTable;
std::map<std::string, std::pair<lcVector3, lcVector4>> TransformTable;
if (!lcLoadLDrawXML(MaterialTable, BrickTable, TransformTable))
return false;
QDomDocument Document;
Document.setContent(FileData);
QDomElement Root = Document.documentElement();
if (Root.tagName() != QLatin1String("LXFML"))
return false;
for (QDomNode SectionNode = Root.firstChild(); !SectionNode.isNull(); SectionNode = SectionNode.nextSibling())
{
QDomElement SectionElement = SectionNode.toElement();
if (SectionElement.tagName() != QLatin1String("Bricks"))
continue;
for (QDomNode BrickNode = SectionElement.firstChild(); !BrickNode.isNull(); BrickNode = BrickNode.nextSibling())
{
QDomElement BrickElement = BrickNode.toElement();
if (BrickElement.tagName() != QLatin1String("Brick"))
continue;
int NumBrickPieces = 0;
for (QDomNode PartNode = BrickElement.firstChild(); !PartNode.isNull(); PartNode = PartNode.nextSibling())
{
QDomElement PartElement = PartNode.toElement();
if (PartElement.tagName() != QLatin1String("Part"))
continue;
bool BoneFound = false;
lcMatrix44 WorldMatrix;
for (QDomNode BoneNode = PartElement.firstChild(); !BoneNode.isNull(); BoneNode = BoneNode.nextSibling())
{
QDomElement BoneElement = BoneNode.toElement();
if (BoneElement.tagName() != QLatin1String("Bone"))
continue;
QString BoneTransform = BoneElement.attribute(QLatin1String("transformation"));
QStringList BoneElements = BoneTransform.split(',');
if (BoneElements.size() != 12)
continue;
WorldMatrix[0][0] = BoneElements[0].toFloat();
WorldMatrix[0][1] = BoneElements[1].toFloat();
WorldMatrix[0][2] = BoneElements[2].toFloat();
WorldMatrix[0][3] = 0.0f;
WorldMatrix[1][0] = BoneElements[3].toFloat();
WorldMatrix[1][1] = BoneElements[4].toFloat();
WorldMatrix[1][2] = BoneElements[5].toFloat();
WorldMatrix[1][3] = 0.0f;
WorldMatrix[2][0] = BoneElements[6].toFloat();
WorldMatrix[2][1] = BoneElements[7].toFloat();
WorldMatrix[2][2] = BoneElements[8].toFloat();
WorldMatrix[3][3] = 0.0f;
WorldMatrix[3][0] = BoneElements[9].toFloat();
WorldMatrix[3][1] = BoneElements[10].toFloat();
WorldMatrix[3][2] = BoneElements[11].toFloat();
WorldMatrix[3][3] = 1.0f;
BoneFound = true;
break;
}
if (!BoneFound)
continue;
QString LegoID = PartElement.attribute(QLatin1String("designID"));
int Material = PartElement.attribute(QLatin1String("materials")).split(',').first().toInt();
PieceInfo* Info = nullptr;
const auto BrickIt = BrickTable.find(LegoID.toInt());
if (BrickIt != BrickTable.end())
Info = lcGetPiecesLibrary()->FindPiece(BrickIt->second.c_str(), nullptr, true, false);
else
Info = lcGetPiecesLibrary()->FindPiece(LegoID.toLatin1(), nullptr, true, false);
const auto ColorIt = MaterialTable.find(Material);
int ColorCode = 16;
if (ColorIt != MaterialTable.end())
ColorCode = ColorIt->second;
const auto TransformIt = TransformTable.find(BrickIt != BrickTable.end() ? BrickIt->second : LegoID.toStdString());
if (TransformIt != TransformTable.end())
{
const lcVector4& AxisAngle = TransformIt->second.second;
const lcVector3& TransformTranslation = TransformIt->second.first;
lcMatrix44 Transform = lcMatrix44FromAxisAngle(lcVector3(AxisAngle[0], AxisAngle[1], AxisAngle[2]), -AxisAngle[3]);
Transform.SetTranslation(lcMul30(-TransformTranslation, Transform));
WorldMatrix = lcMul(Transform, WorldMatrix);
}
WorldMatrix = lcMatrix44(lcVector4(WorldMatrix[0][0], -WorldMatrix[0][1], -WorldMatrix[0][2], 0.0f), lcVector4(-WorldMatrix[1][0], WorldMatrix[1][1], WorldMatrix[1][2], 0.0f),
lcVector4(-WorldMatrix[2][0], WorldMatrix[2][1], WorldMatrix[2][2], 0.0f), lcVector4(WorldMatrix[3][0] * 25.0f, -WorldMatrix[3][1] * 25.0f, -WorldMatrix[3][2] * 25.0f, 1.0f));
lcPiece* Piece = new lcPiece(nullptr);
Piece->SetPieceInfo(Info, false);
Piece->Initialize(lcMatrix44LDrawToLeoCAD(WorldMatrix), 1);
Piece->SetColorCode(ColorCode);
Pieces.Add(Piece);
NumBrickPieces++;
}
if (NumBrickPieces > 1)
{
lcArray<lcPiece*> Group;
for (int PieceIdx = Pieces.GetSize() - NumBrickPieces; PieceIdx < Pieces.GetSize(); PieceIdx++)
Group.Add(Pieces[PieceIdx]);
Groups.Add(Group);
}
}
}
return true;
}
+1 -1
View File
@@ -2,5 +2,5 @@
#include "lc_array.h"
bool lcImportLDDFile(const QString& FileData, lcArray<lcPiece*>& Pieces, lcArray<lcArray<lcPiece*>>& Groups);
bool lcImportLXFMLFile(const QString& FileData, lcArray<lcPiece*>& Pieces, lcArray<lcArray<lcPiece*>>& Groups);
+14 -3
View File
@@ -755,6 +755,17 @@ inline lcMatrix33 lcMatrix33FromAxisAngle(const lcVector3& Axis, const float Rad
return m;
}
inline lcMatrix33 lcMatrix33Transpose(const lcMatrix33& m)
{
lcMatrix33 t;
t.r[0] = lcVector3(m[0][0], m[1][0], m[2][0]);
t.r[1] = lcVector3(m[0][1], m[1][1], m[2][1]);
t.r[2] = lcVector3(m[0][2], m[1][2], m[2][2]);
return t;
}
inline lcMatrix33 lcMatrix33AffineInverse(const lcMatrix33& m)
{
lcMatrix33 Inv;
@@ -1309,9 +1320,9 @@ inline lcMatrix44 lcMatrix44LDrawToLeoCAD(const lcMatrix44& Matrix)
{
lcMatrix44 m;
m.r[0] = lcVector4(Matrix[0][0], Matrix[2][0], -Matrix[1][0], 0.0f);
m.r[1] = lcVector4(Matrix[0][2], Matrix[2][2], -Matrix[1][2], 0.0f);
m.r[2] = lcVector4(-Matrix[0][1], -Matrix[2][1], Matrix[1][1], 0.0f);
m.r[0] = lcVector4(Matrix[0][0], Matrix[0][2], -Matrix[0][1], 0.0f);
m.r[1] = lcVector4(Matrix[2][0], Matrix[2][2], -Matrix[2][1], 0.0f);
m.r[2] = lcVector4(-Matrix[1][0], -Matrix[1][2], Matrix[1][1], 0.0f);
m.r[3] = lcVector4(Matrix[3][0], Matrix[3][2], -Matrix[3][1], 1.0f);
return m;
+1 -1
View File
@@ -950,7 +950,7 @@ bool lcModel::LoadLDD(const QString& FileData)
lcArray<lcPiece*> Pieces;
lcArray<lcArray<lcPiece*>> Groups;
if (!lcImportLDDFile(FileData, Pieces, Groups))
if (!lcImportLXFMLFile(FileData, Pieces, Groups))
return false;
for (lcPiece* Piece : Pieces)
+1 -1
View File
@@ -3,7 +3,7 @@ TEMPLATE = app
greaterThan(QT_MAJOR_VERSION, 4) {
QT *= printsupport
QT += concurrent
QT += concurrent xml
}
INCLUDEPATH += qt common
+1
View File
@@ -93,6 +93,7 @@
<file>resources/library.zip</file>
<file>resources/ldconfig.ldr</file>
<file>resources/minifig.ini</file>
<file>resources/ldraw.xml</file>
<file>resources/leocad_fr.qm</file>
<file>resources/leocad_pt.qm</file>
</qresource>
+7301
View File
File diff suppressed because it is too large Load Diff