Mesh: Improve 3MF format to support files from 'Make World'
This commit is contained in:
@@ -41,26 +41,21 @@
|
||||
|
||||
|
||||
using namespace MeshCore;
|
||||
#ifndef XERCES_CPP_NAMESPACE_BEGIN
|
||||
#define XERCES_CPP_NAMESPACE_QUALIFIER
|
||||
using namespace XERCES_CPP_NAMESPACE;
|
||||
#else
|
||||
XERCES_CPP_NAMESPACE_USE
|
||||
#endif
|
||||
|
||||
Reader3MF::Reader3MF(std::istream& str)
|
||||
{
|
||||
zipios::ZipHeader zipHeader(str);
|
||||
if (zipHeader.isValid()) {
|
||||
zip.reset(zipHeader.getInputStream("3D/3dmodel.model"));
|
||||
file = std::make_unique<zipios::ZipHeader>(str);
|
||||
if (file->isValid()) {
|
||||
zip.reset(file->getInputStream("3D/3dmodel.model"));
|
||||
}
|
||||
}
|
||||
|
||||
Reader3MF::Reader3MF(const std::string& filename)
|
||||
{
|
||||
zipios::ZipFile zipFile(filename);
|
||||
if (zipFile.isValid()) {
|
||||
zip.reset(zipFile.getInputStream("3D/3dmodel.model"));
|
||||
file = std::make_unique<zipios::ZipFile>(filename);
|
||||
if (file->isValid()) {
|
||||
zip.reset(file->getInputStream("3D/3dmodel.model"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,30 +73,36 @@ std::vector<int> Reader3MF::GetMeshIds() const
|
||||
bool Reader3MF::Load()
|
||||
{
|
||||
try {
|
||||
if (!zip) {
|
||||
return false;
|
||||
}
|
||||
return LoadModel(*zip);
|
||||
return TryLoad();
|
||||
}
|
||||
catch (const std::exception&) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Reader3MF::TryLoad()
|
||||
{
|
||||
if (!zip) {
|
||||
return false;
|
||||
}
|
||||
if (LoadModel(*zip)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return LoadMeshFromComponents();
|
||||
}
|
||||
|
||||
bool Reader3MF::LoadModel(std::istream& str)
|
||||
{
|
||||
try {
|
||||
std::unique_ptr<XercesDOMParser> parser(new XercesDOMParser);
|
||||
parser->setValidationScheme(XercesDOMParser::Val_Auto);
|
||||
parser->setDoNamespaces(false);
|
||||
parser->setDoSchema(false);
|
||||
parser->setValidationSchemaFullChecking(false);
|
||||
parser->setCreateEntityReferenceNodes(false);
|
||||
Component comp;
|
||||
comp.path = "3dmodel.model";
|
||||
return LoadModel(str, comp);
|
||||
}
|
||||
|
||||
Base::StdInputSource inputSource(str, "3dmodel.model");
|
||||
parser->parse(inputSource);
|
||||
std::unique_ptr<XERCES_CPP_NAMESPACE::DOMDocument> xmlDocument(parser->adoptDocument());
|
||||
return LoadModel(*xmlDocument);
|
||||
bool Reader3MF::LoadModel(std::istream& str, const Component& comp)
|
||||
{
|
||||
try {
|
||||
return TryLoadModel(str, comp);
|
||||
}
|
||||
catch (const XMLException&) {
|
||||
return false;
|
||||
@@ -111,24 +112,52 @@ bool Reader3MF::LoadModel(std::istream& str)
|
||||
}
|
||||
}
|
||||
|
||||
bool Reader3MF::LoadModel(XERCES_CPP_NAMESPACE::DOMDocument& xmlDocument)
|
||||
std::unique_ptr<XercesDOMParser> Reader3MF::makeDomParser()
|
||||
{
|
||||
std::unique_ptr<XercesDOMParser> parser(new XercesDOMParser);
|
||||
parser->setValidationScheme(XercesDOMParser::Val_Auto);
|
||||
parser->setDoNamespaces(false);
|
||||
parser->setDoSchema(false);
|
||||
parser->setValidationSchemaFullChecking(false);
|
||||
parser->setCreateEntityReferenceNodes(false);
|
||||
return parser;
|
||||
}
|
||||
|
||||
bool Reader3MF::TryLoadModel(std::istream& str, const Component& comp)
|
||||
{
|
||||
if (!str) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Base::StdInputSource inputSource(str, comp.path.c_str());
|
||||
std::unique_ptr<XercesDOMParser> parser = makeDomParser();
|
||||
parser->parse(inputSource);
|
||||
std::unique_ptr<DOMDocument> xmlDocument(parser->adoptDocument());
|
||||
return LoadModel(*xmlDocument, comp);
|
||||
}
|
||||
|
||||
bool Reader3MF::LoadModel(DOMDocument& xmlDocument, const Component& comp)
|
||||
{
|
||||
DOMNodeList* nodes = xmlDocument.getElementsByTagName(XStr("model").unicodeForm());
|
||||
for (XMLSize_t i = 0; i < nodes->getLength(); i++) {
|
||||
DOMNode* node = nodes->item(i);
|
||||
if (node->getNodeType() == DOMNode::ELEMENT_NODE) {
|
||||
bool resource = LoadResources(static_cast<DOMElement*>(node)->getElementsByTagName(
|
||||
XStr("resources").unicodeForm()));
|
||||
bool build = LoadBuild(
|
||||
static_cast<DOMElement*>(node)->getElementsByTagName(XStr("build").unicodeForm()));
|
||||
return (resource && build);
|
||||
return LoadResourcesAndBuild(static_cast<DOMElement*>(node), comp);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Reader3MF::LoadResources(DOMNodeList* nodes)
|
||||
bool Reader3MF::LoadResourcesAndBuild(DOMElement* node, const Component& comp)
|
||||
{
|
||||
bool resource =
|
||||
LoadResources(node->getElementsByTagName(XStr("resources").unicodeForm()), comp);
|
||||
bool build = LoadBuild(node->getElementsByTagName(XStr("build").unicodeForm()));
|
||||
return (resource && build);
|
||||
}
|
||||
|
||||
bool Reader3MF::LoadResources(DOMNodeList* nodes, const Component& comp)
|
||||
{
|
||||
if (!nodes) {
|
||||
return false;
|
||||
@@ -137,16 +166,16 @@ bool Reader3MF::LoadResources(DOMNodeList* nodes)
|
||||
for (XMLSize_t i = 0; i < nodes->getLength(); i++) {
|
||||
DOMNode* node = nodes->item(i);
|
||||
if (node->getNodeType() == DOMNode::ELEMENT_NODE) {
|
||||
DOMNodeList* objectList =
|
||||
static_cast<DOMElement*>(node)->getElementsByTagName(XStr("object").unicodeForm());
|
||||
return LoadObjects(objectList);
|
||||
auto elem = static_cast<DOMElement*>(node);
|
||||
DOMNodeList* objectList = elem->getElementsByTagName(XStr("object").unicodeForm());
|
||||
return LoadObject(objectList, comp);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Reader3MF::LoadBuild(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes)
|
||||
bool Reader3MF::LoadBuild(DOMNodeList* nodes)
|
||||
{
|
||||
if (!nodes) {
|
||||
return false;
|
||||
@@ -155,8 +184,8 @@ bool Reader3MF::LoadBuild(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes)
|
||||
for (XMLSize_t i = 0; i < nodes->getLength(); i++) {
|
||||
DOMNode* node = nodes->item(i);
|
||||
if (node->getNodeType() == DOMNode::ELEMENT_NODE) {
|
||||
DOMNodeList* objectList =
|
||||
static_cast<DOMElement*>(node)->getElementsByTagName(XStr("item").unicodeForm());
|
||||
auto elem = static_cast<DOMElement*>(node);
|
||||
DOMNodeList* objectList = elem->getElementsByTagName(XStr("item").unicodeForm());
|
||||
return LoadItems(objectList);
|
||||
}
|
||||
}
|
||||
@@ -164,57 +193,85 @@ bool Reader3MF::LoadBuild(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Reader3MF::LoadItems(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes)
|
||||
bool Reader3MF::LoadItems(DOMNodeList* nodes)
|
||||
{
|
||||
const std::size_t numEntries = 12;
|
||||
if (!nodes) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (XMLSize_t i = 0; i < nodes->getLength(); i++) {
|
||||
DOMNode* itemNode = nodes->item(i);
|
||||
DOMNode* idAttr = itemNode->getAttributes()->getNamedItem(XStr("objectid").unicodeForm());
|
||||
if (idAttr) {
|
||||
std::string id = StrX(idAttr->getNodeValue()).c_str();
|
||||
int idValue = std::stoi(id);
|
||||
Base::Matrix4D mat;
|
||||
|
||||
DOMNode* transformAttr =
|
||||
itemNode->getAttributes()->getNamedItem(XStr("transform").unicodeForm());
|
||||
if (transformAttr) {
|
||||
std::string transform = StrX(transformAttr->getNodeValue()).c_str();
|
||||
boost::char_separator<char> sep(" ,");
|
||||
boost::tokenizer<boost::char_separator<char>> tokens(transform, sep);
|
||||
std::vector<std::string> token_results;
|
||||
token_results.assign(tokens.begin(), tokens.end());
|
||||
if (token_results.size() == numEntries) {
|
||||
mat[0][0] = std::stod(token_results[0]);
|
||||
mat[1][0] = std::stod(token_results[1]);
|
||||
mat[2][0] = std::stod(token_results[2]);
|
||||
mat[0][1] = std::stod(token_results[3]);
|
||||
mat[1][1] = std::stod(token_results[4]);
|
||||
mat[2][1] = std::stod(token_results[5]);
|
||||
mat[0][2] = std::stod(token_results[6]);
|
||||
mat[1][2] = std::stod(token_results[7]);
|
||||
mat[2][2] = std::stod(token_results[8]);
|
||||
mat[0][3] = std::stod(token_results[9]);
|
||||
mat[1][3] = std::stod(token_results[10]);
|
||||
mat[2][3] = std::stod(token_results[11]);
|
||||
|
||||
try {
|
||||
meshes.at(idValue).second = mat;
|
||||
}
|
||||
catch (const std::exception&) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
DOMNamedNodeMap* nodeMap = itemNode->getAttributes();
|
||||
LoadItem(nodeMap);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Reader3MF::LoadObjects(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes)
|
||||
void Reader3MF::LoadItem(DOMNamedNodeMap* nodeMap)
|
||||
{
|
||||
DOMNode* idAttr = nodeMap->getNamedItem(XStr("objectid").unicodeForm());
|
||||
if (idAttr) {
|
||||
std::string id = StrX(idAttr->getNodeValue()).c_str();
|
||||
int idValue = std::stoi(id);
|
||||
|
||||
DOMNode* transformAttr = nodeMap->getNamedItem(XStr("transform").unicodeForm());
|
||||
if (transformAttr) {
|
||||
std::optional<Base::Matrix4D> mat = ReadTransform(transformAttr);
|
||||
if (mat) {
|
||||
auto it = meshes.find(idValue);
|
||||
if (it != meshes.end()) {
|
||||
it->second.second = mat.value();
|
||||
}
|
||||
|
||||
auto jt = std::find_if(components.begin(),
|
||||
components.end(),
|
||||
[idValue](const Component& comp) {
|
||||
return comp.id == idValue;
|
||||
});
|
||||
if (jt != components.end()) {
|
||||
jt->transform = mat.value();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<Base::Matrix4D> Reader3MF::ReadTransform(DOMNode* transformAttr)
|
||||
{
|
||||
constexpr const std::size_t numEntries = 12;
|
||||
using Pos2d = std::array<std::array<int, 2>, numEntries>;
|
||||
// clang-format off
|
||||
static Pos2d pos = {{
|
||||
{0, 0}, {1, 0}, {2, 0},
|
||||
{0, 1}, {1, 1}, {2, 1},
|
||||
{0, 2}, {1, 2}, {2, 2},
|
||||
{0, 3}, {1, 3}, {2, 3}
|
||||
}};
|
||||
// clang-format on
|
||||
|
||||
if (transformAttr) {
|
||||
std::string transform = StrX(transformAttr->getNodeValue()).c_str();
|
||||
boost::char_separator<char> sep(" ,");
|
||||
boost::tokenizer<boost::char_separator<char>> tokens(transform, sep);
|
||||
std::vector<std::string> token_results;
|
||||
token_results.assign(tokens.begin(), tokens.end());
|
||||
if (token_results.size() == numEntries) {
|
||||
Base::Matrix4D mat;
|
||||
// NOLINTBEGIN
|
||||
int index = 0;
|
||||
for (const auto& it : pos) {
|
||||
auto [r, c] = it;
|
||||
mat[r][c] = std::stod(token_results[index++]);
|
||||
}
|
||||
// NOLINTEND
|
||||
return mat;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
bool Reader3MF::LoadObject(DOMNodeList* nodes, const Component& comp)
|
||||
{
|
||||
if (!nodes) {
|
||||
return false;
|
||||
@@ -224,11 +281,18 @@ bool Reader3MF::LoadObjects(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes)
|
||||
DOMNode* objectNode = nodes->item(i);
|
||||
if (objectNode->getNodeType() == DOMNode::ELEMENT_NODE) {
|
||||
DOMNode* idAttr = objectNode->getAttributes()->getNamedItem(XStr("id").unicodeForm());
|
||||
auto elem = static_cast<DOMElement*>(objectNode);
|
||||
if (idAttr) {
|
||||
int id = std::stoi(StrX(idAttr->getNodeValue()).c_str());
|
||||
DOMNodeList* meshList = static_cast<DOMElement*>(objectNode)
|
||||
->getElementsByTagName(XStr("mesh").unicodeForm());
|
||||
LoadMesh(meshList, id);
|
||||
DOMNodeList* meshNode = elem->getElementsByTagName(XStr("mesh").unicodeForm());
|
||||
if (meshNode->getLength() > 0) {
|
||||
LoadMesh(meshNode, id, comp);
|
||||
}
|
||||
else {
|
||||
DOMNodeList* compNode =
|
||||
elem->getElementsByTagName(XStr("components").unicodeForm());
|
||||
LoadComponents(compNode, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -236,7 +300,77 @@ bool Reader3MF::LoadObjects(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes)
|
||||
return (!meshes.empty());
|
||||
}
|
||||
|
||||
void Reader3MF::LoadMesh(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes, int id)
|
||||
bool Reader3MF::LoadMeshFromComponents()
|
||||
{
|
||||
for (const auto& it : components) {
|
||||
std::string path = it.path.substr(1);
|
||||
zip.reset(file->getInputStream(path));
|
||||
LoadModel(*zip, it);
|
||||
}
|
||||
|
||||
return (!meshes.empty());
|
||||
}
|
||||
|
||||
void Reader3MF::LoadComponents(DOMNodeList* nodes, int id)
|
||||
{
|
||||
if (!nodes) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (XMLSize_t i = 0; i < nodes->getLength(); i++) {
|
||||
DOMNode* objectNode = nodes->item(i);
|
||||
if (objectNode->getNodeType() == DOMNode::ELEMENT_NODE) {
|
||||
auto elem = static_cast<DOMElement*>(objectNode);
|
||||
DOMNodeList* compNode = elem->getElementsByTagName(XStr("component").unicodeForm());
|
||||
if (compNode->getLength() > 0) {
|
||||
LoadComponent(compNode, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Reader3MF::LoadComponent(DOMNodeList* nodes, int id)
|
||||
{
|
||||
if (!nodes) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (XMLSize_t i = 0; i < nodes->getLength(); i++) {
|
||||
DOMNode* compNode = nodes->item(i);
|
||||
if (compNode->getNodeType() == DOMNode::ELEMENT_NODE) {
|
||||
if (DOMNamedNodeMap* attr = compNode->getAttributes()) {
|
||||
LoadComponent(attr, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Reader3MF::LoadComponent(DOMNamedNodeMap* attr, int id)
|
||||
{
|
||||
auto validComponent = [](const Component& comp) {
|
||||
return (comp.id > 0 && comp.objectId >= 0 && !comp.path.empty());
|
||||
};
|
||||
|
||||
Component component;
|
||||
component.id = id;
|
||||
if (DOMNode* pathAttr = attr->getNamedItem(XStr("p:path").unicodeForm())) {
|
||||
component.path = StrX(pathAttr->getNodeValue()).c_str();
|
||||
}
|
||||
if (DOMNode* idAttr = attr->getNamedItem(XStr("objectid").unicodeForm())) {
|
||||
component.objectId = std::stoi(StrX(idAttr->getNodeValue()).c_str());
|
||||
}
|
||||
if (DOMNode* transformAttr = attr->getNamedItem(XStr("transform").unicodeForm())) {
|
||||
std::optional<Base::Matrix4D> mat = ReadTransform(transformAttr);
|
||||
if (mat) {
|
||||
component.transform = mat.value();
|
||||
}
|
||||
}
|
||||
if (validComponent(component)) {
|
||||
components.push_back(component);
|
||||
}
|
||||
}
|
||||
|
||||
void Reader3MF::LoadMesh(DOMNodeList* nodes, int id, const Component& comp)
|
||||
{
|
||||
if (!nodes) {
|
||||
return;
|
||||
@@ -245,29 +379,26 @@ void Reader3MF::LoadMesh(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes, int
|
||||
for (XMLSize_t i = 0; i < nodes->getLength(); i++) {
|
||||
DOMNode* node = nodes->item(i);
|
||||
if (node->getNodeType() == DOMNode::ELEMENT_NODE) {
|
||||
auto elem = static_cast<DOMElement*>(node);
|
||||
MeshPointArray points;
|
||||
MeshFacetArray facets;
|
||||
LoadVertices(static_cast<DOMElement*>(node)->getElementsByTagName(
|
||||
XStr("vertices").unicodeForm()),
|
||||
points);
|
||||
LoadTriangles(static_cast<DOMElement*>(node)->getElementsByTagName(
|
||||
XStr("triangles").unicodeForm()),
|
||||
facets);
|
||||
LoadVertices(elem->getElementsByTagName(XStr("vertices").unicodeForm()), points);
|
||||
LoadTriangles(elem->getElementsByTagName(XStr("triangles").unicodeForm()), facets);
|
||||
|
||||
MeshCleanup meshCleanup(points, facets);
|
||||
meshCleanup.RemoveInvalids();
|
||||
MeshPointFacetAdjacency meshAdj(points.size(), facets);
|
||||
meshAdj.SetFacetNeighbourhood();
|
||||
|
||||
Base::Matrix4D mat = comp.transform;
|
||||
MeshKernel kernel;
|
||||
kernel.Adopt(points, facets);
|
||||
meshes.emplace(id, std::make_pair(kernel, Base::Matrix4D()));
|
||||
meshes.emplace(id, std::make_pair(kernel, mat));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Reader3MF::LoadVertices(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes,
|
||||
MeshPointArray& points)
|
||||
void Reader3MF::LoadVertices(DOMNodeList* nodes, MeshPointArray& points)
|
||||
{
|
||||
if (!nodes) {
|
||||
return;
|
||||
@@ -276,33 +407,39 @@ void Reader3MF::LoadVertices(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes,
|
||||
for (XMLSize_t i = 0; i < nodes->getLength(); i++) {
|
||||
DOMNode* node = nodes->item(i);
|
||||
if (node->getNodeType() == DOMNode::ELEMENT_NODE) {
|
||||
DOMNodeList* vertexList =
|
||||
static_cast<DOMElement*>(node)->getElementsByTagName(XStr("vertex").unicodeForm());
|
||||
auto elem = static_cast<DOMElement*>(node);
|
||||
DOMNodeList* vertexList = elem->getElementsByTagName(XStr("vertex").unicodeForm());
|
||||
if (vertexList) {
|
||||
XMLSize_t numVertices = vertexList->getLength();
|
||||
points.reserve(numVertices);
|
||||
for (XMLSize_t j = 0; j < numVertices; j++) {
|
||||
DOMNode* vertexNode = vertexList->item(j);
|
||||
DOMNamedNodeMap* attr = vertexNode->getAttributes();
|
||||
if (attr) {
|
||||
DOMNode* xAttr = attr->getNamedItem(XStr("x").unicodeForm());
|
||||
DOMNode* yAttr = attr->getNamedItem(XStr("y").unicodeForm());
|
||||
DOMNode* zAttr = attr->getNamedItem(XStr("z").unicodeForm());
|
||||
if (xAttr && yAttr && zAttr) {
|
||||
float x = std::stof(StrX(xAttr->getNodeValue()).c_str());
|
||||
float y = std::stof(StrX(yAttr->getNodeValue()).c_str());
|
||||
float z = std::stof(StrX(zAttr->getNodeValue()).c_str());
|
||||
points.emplace_back(x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
ReadVertices(vertexList, points);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Reader3MF::LoadTriangles(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes,
|
||||
MeshFacetArray& facets)
|
||||
void Reader3MF::ReadVertices(DOMNodeList* vertexList, MeshPointArray& points)
|
||||
{
|
||||
XMLSize_t numVertices = vertexList->getLength();
|
||||
points.reserve(numVertices);
|
||||
for (XMLSize_t j = 0; j < numVertices; j++) {
|
||||
DOMNode* vertexNode = vertexList->item(j);
|
||||
DOMNamedNodeMap* attr = vertexNode->getAttributes();
|
||||
if (attr) {
|
||||
DOMNode* xAttr = attr->getNamedItem(XStr("x").unicodeForm());
|
||||
DOMNode* yAttr = attr->getNamedItem(XStr("y").unicodeForm());
|
||||
DOMNode* zAttr = attr->getNamedItem(XStr("z").unicodeForm());
|
||||
if (xAttr && yAttr && zAttr) {
|
||||
// NOLINTBEGIN
|
||||
float x = std::stof(StrX(xAttr->getNodeValue()).c_str());
|
||||
float y = std::stof(StrX(yAttr->getNodeValue()).c_str());
|
||||
float z = std::stof(StrX(zAttr->getNodeValue()).c_str());
|
||||
points.emplace_back(x, y, z);
|
||||
// NOLINTEND
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Reader3MF::LoadTriangles(DOMNodeList* nodes, MeshFacetArray& facets)
|
||||
{
|
||||
if (!nodes) {
|
||||
return;
|
||||
@@ -311,26 +448,31 @@ void Reader3MF::LoadTriangles(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes,
|
||||
for (XMLSize_t i = 0; i < nodes->getLength(); i++) {
|
||||
DOMNode* node = nodes->item(i);
|
||||
if (node->getNodeType() == DOMNode::ELEMENT_NODE) {
|
||||
DOMNodeList* triangleList = static_cast<DOMElement*>(node)->getElementsByTagName(
|
||||
XStr("triangle").unicodeForm());
|
||||
auto elem = static_cast<DOMElement*>(node);
|
||||
DOMNodeList* triangleList = elem->getElementsByTagName(XStr("triangle").unicodeForm());
|
||||
if (triangleList) {
|
||||
XMLSize_t numTriangles = triangleList->getLength();
|
||||
facets.reserve(numTriangles);
|
||||
for (XMLSize_t j = 0; j < numTriangles; j++) {
|
||||
DOMNode* triangleNode = triangleList->item(j);
|
||||
DOMNamedNodeMap* attr = triangleNode->getAttributes();
|
||||
if (attr) {
|
||||
DOMNode* v1Attr = attr->getNamedItem(XStr("v1").unicodeForm());
|
||||
DOMNode* v2Attr = attr->getNamedItem(XStr("v2").unicodeForm());
|
||||
DOMNode* v3Attr = attr->getNamedItem(XStr("v3").unicodeForm());
|
||||
if (v1Attr && v2Attr && v3Attr) {
|
||||
PointIndex v1 = std::stoul(StrX(v1Attr->getNodeValue()).c_str());
|
||||
PointIndex v2 = std::stoul(StrX(v2Attr->getNodeValue()).c_str());
|
||||
PointIndex v3 = std::stoul(StrX(v3Attr->getNodeValue()).c_str());
|
||||
facets.emplace_back(v1, v2, v3);
|
||||
}
|
||||
}
|
||||
}
|
||||
ReadTriangles(triangleList, facets);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Reader3MF::ReadTriangles(DOMNodeList* triangleList, MeshFacetArray& facets)
|
||||
{
|
||||
XMLSize_t numTriangles = triangleList->getLength();
|
||||
facets.reserve(numTriangles);
|
||||
for (XMLSize_t j = 0; j < numTriangles; j++) {
|
||||
DOMNode* triangleNode = triangleList->item(j);
|
||||
DOMNamedNodeMap* attr = triangleNode->getAttributes();
|
||||
if (attr) {
|
||||
DOMNode* v1Attr = attr->getNamedItem(XStr("v1").unicodeForm());
|
||||
DOMNode* v2Attr = attr->getNamedItem(XStr("v2").unicodeForm());
|
||||
DOMNode* v3Attr = attr->getNamedItem(XStr("v3").unicodeForm());
|
||||
if (v1Attr && v2Attr && v3Attr) {
|
||||
PointIndex v1 = std::stoul(StrX(v1Attr->getNodeValue()).c_str());
|
||||
PointIndex v2 = std::stoul(StrX(v2Attr->getNodeValue()).c_str());
|
||||
PointIndex v3 = std::stoul(StrX(v3Attr->getNodeValue()).c_str());
|
||||
facets.emplace_back(v1, v2, v3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,23 +28,24 @@
|
||||
#include <Mod/Mesh/MeshGlobal.h>
|
||||
#include <iosfwd>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
#include <xercesc/util/XercesDefs.hpp>
|
||||
|
||||
#ifndef XERCES_CPP_NAMESPACE_BEGIN
|
||||
#define XERCES_CPP_NAMESPACE_QUALIFIER
|
||||
using namespace XERCES_CPP_NAMESPACE;
|
||||
namespace XERCES_CPP_NAMESPACE
|
||||
{
|
||||
class DOMDocument;
|
||||
class DOMElement;
|
||||
class DOMNode;
|
||||
class DOMNodeList;
|
||||
class DOMNamedNodeMap;
|
||||
class XercesDOMParser;
|
||||
} // namespace XERCES_CPP_NAMESPACE
|
||||
#else
|
||||
XERCES_CPP_NAMESPACE_BEGIN
|
||||
class DOMDocument;
|
||||
class DOMNodeList;
|
||||
XERCES_CPP_NAMESPACE_END
|
||||
#endif
|
||||
|
||||
namespace zipios
|
||||
{
|
||||
class FileCollection;
|
||||
}
|
||||
|
||||
namespace MeshCore
|
||||
{
|
||||
@@ -84,19 +85,41 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
struct Component
|
||||
{
|
||||
int id = -1;
|
||||
int objectId = -1;
|
||||
std::string path;
|
||||
Base::Matrix4D transform;
|
||||
};
|
||||
static std::unique_ptr<XERCES_CPP_NAMESPACE::XercesDOMParser> makeDomParser();
|
||||
bool TryLoad();
|
||||
bool LoadModel(std::istream&);
|
||||
bool LoadModel(XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument&);
|
||||
bool LoadResources(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList*);
|
||||
bool LoadBuild(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList*);
|
||||
bool LoadItems(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList*);
|
||||
bool LoadObjects(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList*);
|
||||
void LoadMesh(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList*, int id);
|
||||
void LoadVertices(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList*, MeshPointArray&);
|
||||
void LoadTriangles(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList*, MeshFacetArray&);
|
||||
bool LoadModel(std::istream&, const Component&);
|
||||
bool TryLoadModel(std::istream&, const Component&);
|
||||
bool LoadModel(XERCES_CPP_NAMESPACE::DOMDocument&, const Component&);
|
||||
bool LoadResourcesAndBuild(XERCES_CPP_NAMESPACE::DOMElement*, const Component&);
|
||||
bool LoadResources(XERCES_CPP_NAMESPACE::DOMNodeList*, const Component&);
|
||||
bool LoadBuild(XERCES_CPP_NAMESPACE::DOMNodeList*);
|
||||
bool LoadItems(XERCES_CPP_NAMESPACE::DOMNodeList*);
|
||||
void LoadItem(XERCES_CPP_NAMESPACE::DOMNamedNodeMap*);
|
||||
bool LoadObject(XERCES_CPP_NAMESPACE::DOMNodeList*, const Component&);
|
||||
void LoadComponents(XERCES_CPP_NAMESPACE::DOMNodeList*, int id);
|
||||
void LoadComponent(XERCES_CPP_NAMESPACE::DOMNodeList*, int id);
|
||||
void LoadComponent(XERCES_CPP_NAMESPACE::DOMNamedNodeMap*, int id);
|
||||
void LoadMesh(XERCES_CPP_NAMESPACE::DOMNodeList*, int id, const Component&);
|
||||
void LoadVertices(XERCES_CPP_NAMESPACE::DOMNodeList*, MeshPointArray&);
|
||||
void ReadVertices(XERCES_CPP_NAMESPACE::DOMNodeList*, MeshPointArray&);
|
||||
void LoadTriangles(XERCES_CPP_NAMESPACE::DOMNodeList*, MeshFacetArray&);
|
||||
void ReadTriangles(XERCES_CPP_NAMESPACE::DOMNodeList*, MeshFacetArray&);
|
||||
bool LoadMeshFromComponents();
|
||||
std::optional<Base::Matrix4D> ReadTransform(XERCES_CPP_NAMESPACE::DOMNode*);
|
||||
|
||||
private:
|
||||
std::vector<Component> components;
|
||||
using MeshKernelAndTransform = std::pair<MeshKernel, Base::Matrix4D>;
|
||||
std::unordered_map<int, MeshKernelAndTransform> meshes;
|
||||
std::unique_ptr<zipios::FileCollection> file;
|
||||
std::unique_ptr<std::istream> zip;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user