mirror of
https://github.com/leozide/leocad
synced 2024-12-25 21:58:23 +01:00
200 lines
6.9 KiB
C++
200 lines
6.9 KiB
C++
#include "lc_global.h"
|
|
#include "lc_lxf.h"
|
|
#include "lc_library.h"
|
|
#include "lc_application.h"
|
|
#include "lc_mainwindow.h"
|
|
#include "piece.h"
|
|
#include "lc_file.h"
|
|
#include <QDomDocument>
|
|
|
|
static bool lcLoadLDrawXML(std::map<int, int>& MaterialTable, std::map<int, std::string>& BrickTable, std::map<std::string, std::pair<lcVector3, lcVector4>>& TransformTable)
|
|
{
|
|
QFile File(lcGetPiecesLibrary()->mLibraryDir.absoluteFilePath(QLatin1String("ldraw.xml")));
|
|
QByteArray Data;
|
|
|
|
if (File.open(QIODevice::ReadOnly))
|
|
Data = File.readAll();
|
|
else
|
|
{
|
|
QFile DefaultFile(":/resources/ldraw.xml");
|
|
|
|
if (DefaultFile.open(QIODevice::ReadOnly))
|
|
Data = DefaultFile.readAll();
|
|
}
|
|
|
|
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"));
|
|
int LegoID = Element.attribute(QLatin1String("lego")).toInt();
|
|
|
|
BrickTable.insert(std::make_pair(LegoID, LDrawID.toStdString()));
|
|
}
|
|
else if (ElementName == QLatin1String("Transformation"))
|
|
{
|
|
QString LDrawID = Element.attribute(QLatin1String("ldraw"));
|
|
|
|
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.insert(std::make_pair(LDrawID.toStdString(), std::make_pair(Translation, AxisAngle)));
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool lcImportLXFMLFile(const QString& FileData, std::vector<lcPiece*>& Pieces, std::vector<std::vector<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() + ".dat", 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() + ".dat"));
|
|
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, QString(), false);
|
|
Piece->Initialize(lcMatrix44LDrawToLeoCAD(WorldMatrix), 1);
|
|
Piece->SetColorCode(ColorCode);
|
|
Pieces.push_back(Piece);
|
|
NumBrickPieces++;
|
|
}
|
|
|
|
if (NumBrickPieces > 1)
|
|
{
|
|
std::vector<lcPiece*> Group;
|
|
for (size_t PieceIdx = Pieces.size() - NumBrickPieces; PieceIdx < Pieces.size(); PieceIdx++)
|
|
Group.push_back(Pieces[PieceIdx]);
|
|
Groups.push_back(Group);
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|