From 8ed18621dbb7d906ddbb79a366d1f987f826c5b4 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 10 Nov 2021 20:37:27 +0100 Subject: [PATCH] Fixes --- code/AssetLib/X3D/X3DImporter.cpp | 12 +- code/AssetLib/X3D/X3DImporter.hpp | 1 + code/AssetLib/X3D/X3DImporter_Geometry2D.cpp | 16 +- code/AssetLib/X3D/X3DImporter_Geometry3D.cpp | 1102 +++++++++--------- code/AssetLib/X3D/X3DImporter_Group.cpp | 15 +- code/AssetLib/X3D/X3DImporter_Light.cpp | 6 +- code/AssetLib/X3D/X3DImporter_Macro.hpp | 32 +- code/AssetLib/X3D/X3DImporter_Metadata.cpp | 6 +- code/AssetLib/X3D/X3DImporter_Networking.cpp | 5 +- code/AssetLib/X3D/X3DImporter_Rendering.cpp | 40 +- code/AssetLib/X3D/X3DImporter_Shape.cpp | 158 +-- code/AssetLib/X3D/X3DImporter_Texturing.cpp | 6 +- test/models/X3D/HelloX3dTrademark.x3d | 48 + test/test.3mf | Bin 1143 -> 1143 bytes test/unit/utX3DImportExport.cpp | 2 +- 15 files changed, 741 insertions(+), 708 deletions(-) create mode 100644 test/models/X3D/HelloX3dTrademark.x3d diff --git a/code/AssetLib/X3D/X3DImporter.cpp b/code/AssetLib/X3D/X3DImporter.cpp index bfe83a49f..e33782785 100644 --- a/code/AssetLib/X3D/X3DImporter.cpp +++ b/code/AssetLib/X3D/X3DImporter.cpp @@ -75,7 +75,7 @@ bool X3DImporter::isNodeEmpty(XmlNode &node) { } void X3DImporter::checkNodeMustBeEmpty(XmlNode &node) { - if (isNodeEmpty(node)) throw DeadlyImportError(std::string("Node <") + node.name() + "> must be empty."); + if (!isNodeEmpty(node)) throw DeadlyImportError(std::string("Node <") + node.name() + "> must be empty."); } void X3DImporter::skipUnsupportedNode(const std::string &pParentNodeName, XmlNode &node) { @@ -321,7 +321,7 @@ void X3DImporter::readHead(XmlNode &node) { for (auto currentNode : node.children()) { const std::string ¤tName = currentNode.name(); if (currentName == "meta") { - checkNodeMustBeEmpty(node); + //checkNodeMustBeEmpty(node); meta_entry entry; if (XmlParser::getStdStrAttribute(currentNode, "name", entry.name)) { XmlParser::getStdStrAttribute(currentNode, "content", entry.value); @@ -339,6 +339,9 @@ void X3DImporter::readHead(XmlNode &node) { } void X3DImporter::readChildNodes(XmlNode &node, const std::string &pParentNodeName) { + if (node.empty()) { + return; + } for (auto currentNode : node.children()) { const std::string ¤tName = currentNode.name(); if (currentName == "Shape") @@ -463,6 +466,8 @@ void X3DImporter::ParseHelper_Group_Begin(const bool pStatic) { } void X3DImporter::ParseHelper_Node_Enter(X3DNodeElementBase *pNode) { + ai_assert(nullptr != pNode); + mNodeElementCur->Children.push_back(pNode); // add new element to current element child list. mNodeElementCur = pNode; // switch current element to new one. } @@ -471,6 +476,9 @@ void X3DImporter::ParseHelper_Node_Exit() { // check if we can walk up. if (mNodeElementCur != nullptr) { mNodeElementCur = mNodeElementCur->Parent; + } else { + int i = 0; + ++i; } } diff --git a/code/AssetLib/X3D/X3DImporter.hpp b/code/AssetLib/X3D/X3DImporter.hpp index c9509a035..adb73e6f8 100644 --- a/code/AssetLib/X3D/X3DImporter.hpp +++ b/code/AssetLib/X3D/X3DImporter.hpp @@ -270,6 +270,7 @@ public: void Clear(); private: + X3DNodeElementBase *MACRO_USE_CHECKANDAPPLY(XmlNode &node, std::string pDEF, std::string pUSE, X3DElemType pType, X3DNodeElementBase *pNE); bool isNodeEmpty(XmlNode &node); void checkNodeMustBeEmpty(XmlNode &node); void skipUnsupportedNode(const std::string &pParentNodeName, XmlNode &node); diff --git a/code/AssetLib/X3D/X3DImporter_Geometry2D.cpp b/code/AssetLib/X3D/X3DImporter_Geometry2D.cpp index 171075556..8d0f5bad9 100644 --- a/code/AssetLib/X3D/X3DImporter_Geometry2D.cpp +++ b/code/AssetLib/X3D/X3DImporter_Geometry2D.cpp @@ -78,7 +78,7 @@ void X3DImporter::readArc2D(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Arc2D, ne); + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Arc2D, ne); } else { // create and if needed - define new geometry object. ne = new X3DNodeElementGeometry2D(X3DElemType::ENET_Arc2D, mNodeElementCur); @@ -138,7 +138,7 @@ void X3DImporter::readArcClose2D(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_ArcClose2D, ne); + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_ArcClose2D, ne); } else { // create and if needed - define new geometry object. ne = new X3DNodeElementGeometry2D(X3DElemType::ENET_ArcClose2D, mNodeElementCur); @@ -185,7 +185,7 @@ void X3DImporter::readCircle2D(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Circle2D, ne); + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Circle2D, ne); } else { // create and if needed - define new geometry object. ne = new X3DNodeElementGeometry2D(X3DElemType::ENET_Circle2D, mNodeElementCur); @@ -234,7 +234,7 @@ void X3DImporter::readDisk2D(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Disk2D, ne); + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Disk2D, ne); } else { std::list tlist_o, tlist_i; @@ -308,7 +308,7 @@ void X3DImporter::readPolyline2D(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Polyline2D, ne); + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Polyline2D, ne); } else { // create and if needed - define new geometry object. ne = new X3DNodeElementGeometry2D(X3DElemType::ENET_Polyline2D, mNodeElementCur); @@ -351,7 +351,7 @@ void X3DImporter::readPolypoint2D(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Polypoint2D, ne); + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Polypoint2D, ne); } else { // create and if needed - define new geometry object. ne = new X3DNodeElementGeometry2D(X3DElemType::ENET_Polypoint2D, mNodeElementCur); @@ -391,7 +391,7 @@ void X3DImporter::readRectangle2D(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Rectangle2D, ne); + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Rectangle2D, ne); } else { // create and if needed - define new geometry object. ne = new X3DNodeElementGeometry2D(X3DElemType::ENET_Rectangle2D, mNodeElementCur); @@ -437,7 +437,7 @@ void X3DImporter::readTriangleSet2D(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TriangleSet2D, ne); + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TriangleSet2D, ne); } else { if (vertices.size() % 3) throw DeadlyImportError("TriangleSet2D. Not enough points for defining triangle."); diff --git a/code/AssetLib/X3D/X3DImporter_Geometry3D.cpp b/code/AssetLib/X3D/X3DImporter_Geometry3D.cpp index 53f5b27bb..edde34281 100644 --- a/code/AssetLib/X3D/X3DImporter_Geometry3D.cpp +++ b/code/AssetLib/X3D/X3DImporter_Geometry3D.cpp @@ -46,16 +46,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_X3D_IMPORTER +#include "X3DGeoHelper.h" #include "X3DImporter.hpp" #include "X3DImporter_Macro.hpp" #include "X3DXmlHelper.h" -#include "X3DGeoHelper.h" // Header files, Assimp. #include -namespace Assimp -{ +namespace Assimp { // ID = def; + // if "USE" defined then find already defined element. + if (!use.empty()) { + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Box, ne); + } else { + // create and if needed - define new geometry object. + ne = new X3DNodeElementGeometry3D(X3DElemType::ENET_Box, mNodeElementCur); + if (!def.empty()) ne->ID = def; - X3DGeoHelper::rect_parallel_epiped(size, ((X3DNodeElementGeometry3D *)ne)->Vertices); // get quad list + X3DGeoHelper::rect_parallel_epiped(size, ((X3DNodeElementGeometry3D *)ne)->Vertices); // get quad list ((X3DNodeElementGeometry3D *)ne)->Solid = solid; ((X3DNodeElementGeometry3D *)ne)->NumIndices = 4; - // check for X3DMetadataObject childs. - if(!isNodeEmpty(node)) - childrenReadMetadata(node, ne, "Box"); - else - mNodeElementCur->Children.push_back(ne);// add made object as child to current element + // check for X3DMetadataObject childs. + if (!isNodeEmpty(node)) + childrenReadMetadata(node, ne, "Box"); + else + mNodeElementCur->Children.push_back(ne); // add made object as child to current element - NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph - }// if(!use.empty()) else + NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph + } // if(!use.empty()) else } // tvec;// temp array for vertices. + std::vector tvec; // temp array for vertices. - // create and if needed - define new geometry object. - ne = new X3DNodeElementGeometry3D(X3DElemType::ENET_Cone, mNodeElementCur); - if(!def.empty()) ne->ID = def; + // create and if needed - define new geometry object. + ne = new X3DNodeElementGeometry3D(X3DElemType::ENET_Cone, mNodeElementCur); + if (!def.empty()) ne->ID = def; - // make cone or parts according to flags. - if(side) - { - StandardShapes::MakeCone(height, 0, bottomRadius, tess, tvec, !bottom); - } - else if(bottom) - { - StandardShapes::MakeCircle(bottomRadius, tess, tvec); - height = -(height / 2); - for(std::vector::iterator it = tvec.begin(); it != tvec.end(); ++it) it->y = height;// y - because circle made in oXZ. - } + // make cone or parts according to flags. + if (side) { + StandardShapes::MakeCone(height, 0, bottomRadius, tess, tvec, !bottom); + } else if (bottom) { + StandardShapes::MakeCircle(bottomRadius, tess, tvec); + height = -(height / 2); + for (std::vector::iterator it = tvec.begin(); it != tvec.end(); ++it) + it->y = height; // y - because circle made in oXZ. + } - // copy data from temp array + // copy data from temp array for (std::vector::iterator it = tvec.begin(); it != tvec.end(); ++it) - ((X3DNodeElementGeometry3D*)ne)->Vertices.push_back(*it); + ((X3DNodeElementGeometry3D *)ne)->Vertices.push_back(*it); - ((X3DNodeElementGeometry3D *)ne)->Solid = solid; + ((X3DNodeElementGeometry3D *)ne)->Solid = solid; ((X3DNodeElementGeometry3D *)ne)->NumIndices = 3; - // check for X3DMetadataObject childs. - if(!isNodeEmpty(node)) - childrenReadMetadata(node, ne, "Cone"); - else - mNodeElementCur->Children.push_back(ne);// add made object as child to current element + // check for X3DMetadataObject childs. + if (!isNodeEmpty(node)) + childrenReadMetadata(node, ne, "Cone"); + else + mNodeElementCur->Children.push_back(ne); // add made object as child to current element - NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph - }// if(!use.empty()) else + NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph + } // if(!use.empty()) else } // tside;// temp array for vertices of side. - std::vector tcir;// temp array for vertices of circle. + std::vector tside; // temp array for vertices of side. + std::vector tcir; // temp array for vertices of circle. - // create and if needed - define new geometry object. - ne = new X3DNodeElementGeometry3D(X3DElemType::ENET_Cylinder, mNodeElementCur); - if(!def.empty()) ne->ID = def; + // create and if needed - define new geometry object. + ne = new X3DNodeElementGeometry3D(X3DElemType::ENET_Cylinder, mNodeElementCur); + if (!def.empty()) ne->ID = def; - // make cilynder or parts according to flags. - if(side) StandardShapes::MakeCone(height, radius, radius, tess, tside, true); + // make cilynder or parts according to flags. + if (side) StandardShapes::MakeCone(height, radius, radius, tess, tside, true); - height /= 2;// height defined for whole cylinder, when creating top and bottom circle we are using just half of height. - if(top || bottom) StandardShapes::MakeCircle(radius, tess, tcir); - // copy data from temp arrays + height /= 2; // height defined for whole cylinder, when creating top and bottom circle we are using just half of height. + if (top || bottom) StandardShapes::MakeCircle(radius, tess, tcir); + // copy data from temp arrays std::list &vlist = ((X3DNodeElementGeometry3D *)ne)->Vertices; // just short alias. - for(std::vector::iterator it = tside.begin(); it != tside.end(); ++it) vlist.push_back(*it); + for (std::vector::iterator it = tside.begin(); it != tside.end(); ++it) + vlist.push_back(*it); - if(top) - { - for(std::vector::iterator it = tcir.begin(); it != tcir.end(); ++it) - { - (*it).y = height;// y - because circle made in oXZ. - vlist.push_back(*it); - } - }// if(top) + if (top) { + for (std::vector::iterator it = tcir.begin(); it != tcir.end(); ++it) { + (*it).y = height; // y - because circle made in oXZ. + vlist.push_back(*it); + } + } // if(top) - if(bottom) - { - for(std::vector::iterator it = tcir.begin(); it != tcir.end(); ++it) - { - (*it).y = -height;// y - because circle made in oXZ. - vlist.push_back(*it); - } - }// if(top) + if (bottom) { + for (std::vector::iterator it = tcir.begin(); it != tcir.end(); ++it) { + (*it).y = -height; // y - because circle made in oXZ. + vlist.push_back(*it); + } + } // if(top) - ((X3DNodeElementGeometry3D *)ne)->Solid = solid; + ((X3DNodeElementGeometry3D *)ne)->Solid = solid; ((X3DNodeElementGeometry3D *)ne)->NumIndices = 3; - // check for X3DMetadataObject childs. - if(!isNodeEmpty(node)) - childrenReadMetadata(node, ne, "Cylinder"); - else - mNodeElementCur->Children.push_back(ne);// add made object as child to current element + // check for X3DMetadataObject childs. + if (!isNodeEmpty(node)) + childrenReadMetadata(node, ne, "Cylinder"); + else + mNodeElementCur->Children.push_back(ne); // add made object as child to current element - NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph - }// if(!use.empty()) else + NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph + } // if(!use.empty()) else } // must be grater than zero."); - if((xDimension <= 0) || (zDimension <= 0)) throw DeadlyImportError("Dimension in must be grater than zero."); + // if "USE" defined then find already defined element. + if (!use.empty()) { + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_ElevationGrid, ne); + } else { + if ((xSpacing == 0.0f) || (zSpacing == 0.0f)) throw DeadlyImportError("Spacing in must be grater than zero."); + if ((xDimension <= 0) || (zDimension <= 0)) throw DeadlyImportError("Dimension in must be grater than zero."); if ((size_t)(xDimension * zDimension) != height.size()) DeadlyImportError("Heights count must be equal to \"xDimension * zDimension\" in "); - // create and if needed - define new geometry object. - ne = new X3DNodeElementElevationGrid(X3DElemType::ENET_ElevationGrid, mNodeElementCur); - if(!def.empty()) ne->ID = def; + // create and if needed - define new geometry object. + ne = new X3DNodeElementElevationGrid(X3DElemType::ENET_ElevationGrid, mNodeElementCur); + if (!def.empty()) ne->ID = def; - X3DNodeElementElevationGrid &grid_alias = *((X3DNodeElementElevationGrid *)ne); // create alias for conveience + X3DNodeElementElevationGrid &grid_alias = *((X3DNodeElementElevationGrid *)ne); // create alias for conveience - {// create grid vertices list - std::vector::const_iterator he_it = height.begin(); + { // create grid vertices list + std::vector::const_iterator he_it = height.begin(); - for(int32_t zi = 0; zi < zDimension; zi++)// rows - { - for(int32_t xi = 0; xi < xDimension; xi++)// columns - { - aiVector3D tvec(xSpacing * xi, *he_it, zSpacing * zi); + for (int32_t zi = 0; zi < zDimension; zi++) // rows + { + for (int32_t xi = 0; xi < xDimension; xi++) // columns + { + aiVector3D tvec(xSpacing * xi, *he_it, zSpacing * zi); - grid_alias.Vertices.push_back(tvec); - ++he_it; - } - } - }// END: create grid vertices list - // - // create faces list. In "coordIdx" format - // - // check if we have quads - if((xDimension < 2) || (zDimension < 2))// only one element in dimension is set, create line set. - { - ((X3DNodeElementElevationGrid *)ne)->NumIndices = 2; // will be holded as line set. - for(size_t i = 0, i_e = (grid_alias.Vertices.size() - 1); i < i_e; i++) - { - grid_alias.CoordIdx.push_back(static_cast(i)); - grid_alias.CoordIdx.push_back(static_cast(i + 1)); - grid_alias.CoordIdx.push_back(-1); - } - } - else// two or more elements in every dimension is set. create quad set. - { - ((X3DNodeElementElevationGrid *)ne)->NumIndices = 4; - for(int32_t fzi = 0, fzi_e = (zDimension - 1); fzi < fzi_e; fzi++)// rows - { - for(int32_t fxi = 0, fxi_e = (xDimension - 1); fxi < fxi_e; fxi++)// columns - { - // points direction in face. - if(ccw) - { - // CCW: - // 3 2 - // 0 1 - grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + fxi); - grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + (fxi + 1)); - grid_alias.CoordIdx.push_back(fzi * xDimension + (fxi + 1)); - grid_alias.CoordIdx.push_back(fzi * xDimension + fxi); - } - else - { - // CW: - // 0 1 - // 3 2 - grid_alias.CoordIdx.push_back(fzi * xDimension + fxi); - grid_alias.CoordIdx.push_back(fzi * xDimension + (fxi + 1)); - grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + (fxi + 1)); - grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + fxi); - }// if(ccw) else - - grid_alias.CoordIdx.push_back(-1); - }// for(int32_t fxi = 0, fxi_e = (xDimension - 1); fxi < fxi_e; fxi++) - }// for(int32_t fzi = 0, fzi_e = (zDimension - 1); fzi < fzi_e; fzi++) - }// if((xDimension < 2) || (zDimension < 2)) else - - grid_alias.ColorPerVertex = colorPerVertex; - grid_alias.NormalPerVertex = normalPerVertex; - grid_alias.CreaseAngle = creaseAngle; - grid_alias.Solid = solid; - // check for child nodes - if(!isNodeEmpty(node)) + grid_alias.Vertices.push_back(tvec); + ++he_it; + } + } + } // END: create grid vertices list + // + // create faces list. In "coordIdx" format + // + // check if we have quads + if ((xDimension < 2) || (zDimension < 2)) // only one element in dimension is set, create line set. { - ParseHelper_Node_Enter(ne); + ((X3DNodeElementElevationGrid *)ne)->NumIndices = 2; // will be holded as line set. + for (size_t i = 0, i_e = (grid_alias.Vertices.size() - 1); i < i_e; i++) { + grid_alias.CoordIdx.push_back(static_cast(i)); + grid_alias.CoordIdx.push_back(static_cast(i + 1)); + grid_alias.CoordIdx.push_back(-1); + } + } else // two or more elements in every dimension is set. create quad set. + { + ((X3DNodeElementElevationGrid *)ne)->NumIndices = 4; + for (int32_t fzi = 0, fzi_e = (zDimension - 1); fzi < fzi_e; fzi++) // rows + { + for (int32_t fxi = 0, fxi_e = (xDimension - 1); fxi < fxi_e; fxi++) // columns + { + // points direction in face. + if (ccw) { + // CCW: + // 3 2 + // 0 1 + grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + fxi); + grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + (fxi + 1)); + grid_alias.CoordIdx.push_back(fzi * xDimension + (fxi + 1)); + grid_alias.CoordIdx.push_back(fzi * xDimension + fxi); + } else { + // CW: + // 0 1 + // 3 2 + grid_alias.CoordIdx.push_back(fzi * xDimension + fxi); + grid_alias.CoordIdx.push_back(fzi * xDimension + (fxi + 1)); + grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + (fxi + 1)); + grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + fxi); + } // if(ccw) else + + grid_alias.CoordIdx.push_back(-1); + } // for(int32_t fxi = 0, fxi_e = (xDimension - 1); fxi < fxi_e; fxi++) + } // for(int32_t fzi = 0, fzi_e = (zDimension - 1); fzi < fzi_e; fzi++) + } // if((xDimension < 2) || (zDimension < 2)) else + + grid_alias.ColorPerVertex = colorPerVertex; + grid_alias.NormalPerVertex = normalPerVertex; + grid_alias.CreaseAngle = creaseAngle; + grid_alias.Solid = solid; + // check for child nodes + if (!isNodeEmpty(node)) { + ParseHelper_Node_Enter(ne); for (auto currentChildNode : node.children()) { const std::string ¤tChildName = currentChildNode.name(); - // check for X3DComposedGeometryNodes - if (currentChildName == "Color") readColor(currentChildNode); - else if (currentChildName == "ColorRGBA") readColorRGBA(currentChildNode); - else if (currentChildName == "Normal") readNormal(currentChildNode); - else if (currentChildName == "TextureCoordinate") readTextureCoordinate(currentChildNode); - // check for X3DMetadataObject - else if (!checkForMetadataNode(currentChildNode)) skipUnsupportedNode("ElevationGrid", currentChildNode); + // check for X3DComposedGeometryNodes + if (currentChildName == "Color") + readColor(currentChildNode); + else if (currentChildName == "ColorRGBA") + readColorRGBA(currentChildNode); + else if (currentChildName == "Normal") + readNormal(currentChildNode); + else if (currentChildName == "TextureCoordinate") + readTextureCoordinate(currentChildNode); + // check for X3DMetadataObject + else if (!checkForMetadataNode(currentChildNode)) + skipUnsupportedNode("ElevationGrid", currentChildNode); } ParseHelper_Node_Exit(); - }// if(!mReader->isEmptyElement()) - else - { - mNodeElementCur->Children.push_back(ne);// add made object as child to current element - }// if(!mReader->isEmptyElement()) else + } // if(!mReader->isEmptyElement()) + else { + mNodeElementCur->Children.push_back(ne); // add made object as child to current element + } // if(!mReader->isEmptyElement()) else - NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph - }// if(!use.empty()) else + NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph + } // if(!use.empty()) else } -template -static void GeometryHelper_Extrusion_CurveIsClosed(std::vector& pCurve, const bool pDropTail, const bool pRemoveLastPoint, bool& pCurveIsClosed) -{ +template +static void GeometryHelper_Extrusion_CurveIsClosed(std::vector &pCurve, const bool pDropTail, const bool pRemoveLastPoint, bool &pCurveIsClosed) { size_t cur_sz = pCurve.size(); - pCurveIsClosed = false; - // for curve with less than four points checking is have no sense, - if(cur_sz < 4) return; + pCurveIsClosed = false; + // for curve with less than four points checking is have no sense, + if (cur_sz < 4) return; - for(size_t s = 3, s_e = cur_sz; s < s_e; s++) - { - // search for first point of duplicated part. - if(pCurve[0] == pCurve[s]) - { - bool found = true; + for (size_t s = 3, s_e = cur_sz; s < s_e; s++) { + // search for first point of duplicated part. + if (pCurve[0] == pCurve[s]) { + bool found = true; - // check if tail(indexed by b2) is duplicate of head(indexed by b1). - for(size_t b1 = 1, b2 = (s + 1); b2 < cur_sz; b1++, b2++) - { - if(pCurve[b1] != pCurve[b2]) - {// points not match: clear flag and break loop. - found = false; + // check if tail(indexed by b2) is duplicate of head(indexed by b1). + for (size_t b1 = 1, b2 = (s + 1); b2 < cur_sz; b1++, b2++) { + if (pCurve[b1] != pCurve[b2]) { // points not match: clear flag and break loop. + found = false; - break; - } - }// for(size_t b1 = 1, b2 = (s + 1); b2 < cur_sz; b1++, b2++) + break; + } + } // for(size_t b1 = 1, b2 = (s + 1); b2 < cur_sz; b1++, b2++) - // if duplicate tail is found then drop or not it depending on flags. - if(found) - { - pCurveIsClosed = true; - if(pDropTail) - { - if(!pRemoveLastPoint) s++;// prepare value for iterator's arithmetics. + // if duplicate tail is found then drop or not it depending on flags. + if (found) { + pCurveIsClosed = true; + if (pDropTail) { + if (!pRemoveLastPoint) s++; // prepare value for iterator's arithmetics. - pCurve.erase(pCurve.begin() + s, pCurve.end());// remove tail - } + pCurve.erase(pCurve.begin() + s, pCurve.end()); // remove tail + } - break; - }// if(found) - }// if(pCurve[0] == pCurve[s]) - }// for(size_t s = 3, s_e = (cur_sz - 1); s < s_e; s++) + break; + } // if(found) + } // if(pCurve[0] == pCurve[s]) + } // for(size_t s = 3, s_e = (cur_sz - 1); s < s_e; s++) } -static aiVector3D GeometryHelper_Extrusion_GetNextY(const size_t pSpine_PointIdx, const std::vector& pSpine, const bool pSpine_Closed) -{ +static aiVector3D GeometryHelper_Extrusion_GetNextY(const size_t pSpine_PointIdx, const std::vector &pSpine, const bool pSpine_Closed) { const size_t spine_idx_last = pSpine.size() - 1; aiVector3D tvec; - if((pSpine_PointIdx == 0) || (pSpine_PointIdx == spine_idx_last))// at first special cases - { - if(pSpine_Closed) - {// If the spine curve is closed: The SCP for the first and last points is the same and is found using (spine[1] - spine[n - 2]) to compute the Y-axis. - // As we even for closed spine curve last and first point in pSpine are not the same: duplicates(spine[n - 1] which are equivalent to spine[0]) - // in tail are removed. - // So, last point in pSpine is a spine[n - 2] - tvec = pSpine[1] - pSpine[spine_idx_last]; - } - else if(pSpine_PointIdx == 0) - {// The Y-axis used for the first point is the vector from spine[0] to spine[1] - tvec = pSpine[1] - pSpine[0]; - } - else - {// The Y-axis used for the last point it is the vector from spine[n-2] to spine[n-1]. In our case(see above about dropping tail) spine[n - 1] is - // the spine[0]. - tvec = pSpine[spine_idx_last] - pSpine[spine_idx_last - 1]; - } - }// if((pSpine_PointIdx == 0) || (pSpine_PointIdx == spine_idx_last)) - else - {// For all points other than the first or last: The Y-axis for spine[i] is found by normalizing the vector defined by (spine[i+1] - spine[i-1]). - tvec = pSpine[pSpine_PointIdx + 1] - pSpine[pSpine_PointIdx - 1]; - }// if((pSpine_PointIdx == 0) || (pSpine_PointIdx == spine_idx_last)) else + if ((pSpine_PointIdx == 0) || (pSpine_PointIdx == spine_idx_last)) // at first special cases + { + if (pSpine_Closed) { // If the spine curve is closed: The SCP for the first and last points is the same and is found using (spine[1] - spine[n - 2]) to compute the Y-axis. + // As we even for closed spine curve last and first point in pSpine are not the same: duplicates(spine[n - 1] which are equivalent to spine[0]) + // in tail are removed. + // So, last point in pSpine is a spine[n - 2] + tvec = pSpine[1] - pSpine[spine_idx_last]; + } else if (pSpine_PointIdx == 0) { // The Y-axis used for the first point is the vector from spine[0] to spine[1] + tvec = pSpine[1] - pSpine[0]; + } else { // The Y-axis used for the last point it is the vector from spine[n-2] to spine[n-1]. In our case(see above about dropping tail) spine[n - 1] is + // the spine[0]. + tvec = pSpine[spine_idx_last] - pSpine[spine_idx_last - 1]; + } + } // if((pSpine_PointIdx == 0) || (pSpine_PointIdx == spine_idx_last)) + else { // For all points other than the first or last: The Y-axis for spine[i] is found by normalizing the vector defined by (spine[i+1] - spine[i-1]). + tvec = pSpine[pSpine_PointIdx + 1] - pSpine[pSpine_PointIdx - 1]; + } // if((pSpine_PointIdx == 0) || (pSpine_PointIdx == spine_idx_last)) else - return tvec.Normalize(); + return tvec.Normalize(); } -static aiVector3D GeometryHelper_Extrusion_GetNextZ(const size_t pSpine_PointIdx, const std::vector& pSpine, const bool pSpine_Closed, - const aiVector3D pVecZ_Prev) -{ +static aiVector3D GeometryHelper_Extrusion_GetNextZ(const size_t pSpine_PointIdx, const std::vector &pSpine, const bool pSpine_Closed, + const aiVector3D pVecZ_Prev) { const aiVector3D zero_vec(0); const size_t spine_idx_last = pSpine.size() - 1; aiVector3D tvec; - // at first special cases - if(pSpine.size() < 3)// spine have not enough points for vector calculations. - { - tvec.Set(0, 0, 1); - } - else if(pSpine_PointIdx == 0)// special case: first point - { - if(pSpine_Closed)// for calculating use previous point in curve s[n - 2]. In list it's a last point, because point s[n - 1] was removed as duplicate. - { - tvec = (pSpine[1] - pSpine[0]) ^ (pSpine[spine_idx_last] - pSpine[0]); - } - else // for not closed curve first and next point(s[0] and s[1]) has the same vector Z. - { - bool found = false; + // at first special cases + if (pSpine.size() < 3) // spine have not enough points for vector calculations. + { + tvec.Set(0, 0, 1); + } else if (pSpine_PointIdx == 0) // special case: first point + { + if (pSpine_Closed) // for calculating use previous point in curve s[n - 2]. In list it's a last point, because point s[n - 1] was removed as duplicate. + { + tvec = (pSpine[1] - pSpine[0]) ^ (pSpine[spine_idx_last] - pSpine[0]); + } else // for not closed curve first and next point(s[0] and s[1]) has the same vector Z. + { + bool found = false; - // As said: "If the Z-axis of the first point is undefined (because the spine is not closed and the first two spine segments are collinear) - // then the Z-axis for the first spine point with a defined Z-axis is used." - // Walk through spine and find Z. - for(size_t next_point = 2; (next_point <= spine_idx_last) && !found; next_point++) - { - // (pSpine[2] - pSpine[1]) ^ (pSpine[0] - pSpine[1]) - tvec = (pSpine[next_point] - pSpine[next_point - 1]) ^ (pSpine[next_point - 2] - pSpine[next_point - 1]); - found = !tvec.Equal(zero_vec); - } + // As said: "If the Z-axis of the first point is undefined (because the spine is not closed and the first two spine segments are collinear) + // then the Z-axis for the first spine point with a defined Z-axis is used." + // Walk through spine and find Z. + for (size_t next_point = 2; (next_point <= spine_idx_last) && !found; next_point++) { + // (pSpine[2] - pSpine[1]) ^ (pSpine[0] - pSpine[1]) + tvec = (pSpine[next_point] - pSpine[next_point - 1]) ^ (pSpine[next_point - 2] - pSpine[next_point - 1]); + found = !tvec.Equal(zero_vec); + } - // if entire spine are collinear then use OZ axis. - if(!found) tvec.Set(0, 0, 1); - }// if(pSpine_Closed) else - }// else if(pSpine_PointIdx == 0) - else if(pSpine_PointIdx == spine_idx_last)// special case: last point - { - if(pSpine_Closed) - {// do not forget that real last point s[n - 1] is removed as duplicated. And in this case we are calculating vector Z for point s[n - 2]. - tvec = (pSpine[0] - pSpine[pSpine_PointIdx]) ^ (pSpine[pSpine_PointIdx - 1] - pSpine[pSpine_PointIdx]); - // if taken spine vectors are collinear then use previous vector Z. - if(tvec.Equal(zero_vec)) tvec = pVecZ_Prev; - } - else - {// vector Z for last point of not closed curve is previous vector Z. - tvec = pVecZ_Prev; - } - } - else// regular point - { - tvec = (pSpine[pSpine_PointIdx + 1] - pSpine[pSpine_PointIdx]) ^ (pSpine[pSpine_PointIdx - 1] - pSpine[pSpine_PointIdx]); - // if taken spine vectors are collinear then use previous vector Z. - if(tvec.Equal(zero_vec)) tvec = pVecZ_Prev; - } + // if entire spine are collinear then use OZ axis. + if (!found) tvec.Set(0, 0, 1); + } // if(pSpine_Closed) else + } // else if(pSpine_PointIdx == 0) + else if (pSpine_PointIdx == spine_idx_last) // special case: last point + { + if (pSpine_Closed) { // do not forget that real last point s[n - 1] is removed as duplicated. And in this case we are calculating vector Z for point s[n - 2]. + tvec = (pSpine[0] - pSpine[pSpine_PointIdx]) ^ (pSpine[pSpine_PointIdx - 1] - pSpine[pSpine_PointIdx]); + // if taken spine vectors are collinear then use previous vector Z. + if (tvec.Equal(zero_vec)) tvec = pVecZ_Prev; + } else { // vector Z for last point of not closed curve is previous vector Z. + tvec = pVecZ_Prev; + } + } else // regular point + { + tvec = (pSpine[pSpine_PointIdx + 1] - pSpine[pSpine_PointIdx]) ^ (pSpine[pSpine_PointIdx - 1] - pSpine[pSpine_PointIdx]); + // if taken spine vectors are collinear then use previous vector Z. + if (tvec.Equal(zero_vec)) tvec = pVecZ_Prev; + } - // After determining the Z-axis, its dot product with the Z-axis of the previous spine point is computed. If this value is negative, the Z-axis - // is flipped (multiplied by -1). - if((tvec * pVecZ_Prev) < 0) tvec = -tvec; + // After determining the Z-axis, its dot product with the Z-axis of the previous spine point is computed. If this value is negative, the Z-axis + // is flipped (multiplied by -1). + if ((tvec * pVecZ_Prev) < 0) tvec = -tvec; - return tvec.Normalize(); + return tvec.Normalize(); } // scale; bool solid = true; std::vector spine; - X3DNodeElementBase* ne( nullptr ); + X3DNodeElementBase *ne(nullptr); MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use); XmlParser::getBoolAttribute(node, "beginCap", beginCap); @@ -588,244 +546,225 @@ void X3DImporter::readExtrusion(XmlNode &node) { XmlParser::getBoolAttribute(node, "solid", solid); X3DXmlHelper::getVector3DArrayAttribute(node, "spine", spine); - // if "USE" defined then find already defined element. - if(!use.empty()) - { - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Extrusion, ne); - } - else - { - // - // check if default values must be assigned - // - if(spine.size() == 0) - { - spine.resize(2); - spine[0].Set(0, 0, 0), spine[1].Set(0, 1, 0); - } - else if(spine.size() == 1) - { - throw DeadlyImportError("ParseNode_Geometry3D_Extrusion. Spine must have at least two points."); - } + // if "USE" defined then find already defined element. + if (!use.empty()) { + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Extrusion, ne); + } else { + // + // check if default values must be assigned + // + if (spine.size() == 0) { + spine.resize(2); + spine[0].Set(0, 0, 0), spine[1].Set(0, 1, 0); + } else if (spine.size() == 1) { + throw DeadlyImportError("ParseNode_Geometry3D_Extrusion. Spine must have at least two points."); + } - if(crossSection.size() == 0) - { - crossSection.resize(5); - crossSection[0].Set(1, 1), crossSection[1].Set(1, -1), crossSection[2].Set(-1, -1), crossSection[3].Set(-1, 1), crossSection[4].Set(1, 1); - } + if (crossSection.size() == 0) { + crossSection.resize(5); + crossSection[0].Set(1, 1), crossSection[1].Set(1, -1), crossSection[2].Set(-1, -1), crossSection[3].Set(-1, 1), crossSection[4].Set(1, 1); + } - {// orientation - size_t ori_size = orientation.size() / 4; + { // orientation + size_t ori_size = orientation.size() / 4; - if(ori_size < spine.size()) - { - float add_ori[4];// values that will be added + if (ori_size < spine.size()) { + float add_ori[4]; // values that will be added - if(ori_size == 1)// if "orientation" has one element(means one MFRotation with four components) then use it value for all spine points. - { - add_ori[0] = orientation[0], add_ori[1] = orientation[1], add_ori[2] = orientation[2], add_ori[3] = orientation[3]; - } - else// else - use default values - { - add_ori[0] = 0, add_ori[1] = 0, add_ori[2] = 1, add_ori[3] = 0; - } + if (ori_size == 1) // if "orientation" has one element(means one MFRotation with four components) then use it value for all spine points. + { + add_ori[0] = orientation[0], add_ori[1] = orientation[1], add_ori[2] = orientation[2], add_ori[3] = orientation[3]; + } else // else - use default values + { + add_ori[0] = 0, add_ori[1] = 0, add_ori[2] = 1, add_ori[3] = 0; + } - orientation.reserve(spine.size() * 4); - for(size_t i = 0, i_e = (spine.size() - ori_size); i < i_e; i++) - orientation.push_back(add_ori[0]), orientation.push_back(add_ori[1]), orientation.push_back(add_ori[2]), orientation.push_back(add_ori[3]); - } + orientation.reserve(spine.size() * 4); + for (size_t i = 0, i_e = (spine.size() - ori_size); i < i_e; i++) + orientation.push_back(add_ori[0]), orientation.push_back(add_ori[1]), orientation.push_back(add_ori[2]), orientation.push_back(add_ori[3]); + } - if(orientation.size() % 4) throw DeadlyImportError("Attribute \"orientation\" in must has multiple four quantity of numbers."); - }// END: orientation + if (orientation.size() % 4) throw DeadlyImportError("Attribute \"orientation\" in must has multiple four quantity of numbers."); + } // END: orientation - {// scale - if(scale.size() < spine.size()) - { - aiVector2D add_sc; + { // scale + if (scale.size() < spine.size()) { + aiVector2D add_sc; - if(scale.size() == 1)// if "scale" has one element then use it value for all spine points. - add_sc = scale[0]; - else// else - use default values - add_sc.Set(1, 1); + if (scale.size() == 1) // if "scale" has one element then use it value for all spine points. + add_sc = scale[0]; + else // else - use default values + add_sc.Set(1, 1); - scale.reserve(spine.size()); - for(size_t i = 0, i_e = (spine.size() - scale.size()); i < i_e; i++) scale.push_back(add_sc); - } - }// END: scale - // - // create and if needed - define new geometry object. - // - ne = new X3DNodeElementIndexedSet(X3DElemType::ENET_Extrusion, mNodeElementCur); - if(!def.empty()) ne->ID = def; + scale.reserve(spine.size()); + for (size_t i = 0, i_e = (spine.size() - scale.size()); i < i_e; i++) + scale.push_back(add_sc); + } + } // END: scale + // + // create and if needed - define new geometry object. + // + ne = new X3DNodeElementIndexedSet(X3DElemType::ENET_Extrusion, mNodeElementCur); + if (!def.empty()) ne->ID = def; - X3DNodeElementIndexedSet &ext_alias = *((X3DNodeElementIndexedSet *)ne); // create alias for conveience - // assign part of input data - ext_alias.CCW = ccw; - ext_alias.Convex = convex; - ext_alias.CreaseAngle = creaseAngle; - ext_alias.Solid = solid; + X3DNodeElementIndexedSet &ext_alias = *((X3DNodeElementIndexedSet *)ne); // create alias for conveience + // assign part of input data + ext_alias.CCW = ccw; + ext_alias.Convex = convex; + ext_alias.CreaseAngle = creaseAngle; + ext_alias.Solid = solid; - // - // How we done it at all? - // 1. At first we will calculate array of basises for every point in spine(look SCP in ISO-dic). Also "orientation" vector - // are applied vor every basis. - // 2. After that we can create array of point sets: which are scaled, transferred to basis of relative basis and at final translated to real position - // using relative spine point. - // 3. Next step is creating CoordIdx array(do not forget "-1" delimiter). While creating CoordIdx also created faces for begin and end caps, if - // needed. While createing CootdIdx is taking in account CCW flag. - // 4. The last step: create Vertices list. - // - bool spine_closed;// flag: true if spine curve is closed. - bool cross_closed;// flag: true if cross curve is closed. - std::vector basis_arr;// array of basises. ROW_a - X, ROW_b - Y, ROW_c - Z. - std::vector > pointset_arr;// array of point sets: cross curves. + // + // How we done it at all? + // 1. At first we will calculate array of basises for every point in spine(look SCP in ISO-dic). Also "orientation" vector + // are applied vor every basis. + // 2. After that we can create array of point sets: which are scaled, transferred to basis of relative basis and at final translated to real position + // using relative spine point. + // 3. Next step is creating CoordIdx array(do not forget "-1" delimiter). While creating CoordIdx also created faces for begin and end caps, if + // needed. While createing CootdIdx is taking in account CCW flag. + // 4. The last step: create Vertices list. + // + bool spine_closed; // flag: true if spine curve is closed. + bool cross_closed; // flag: true if cross curve is closed. + std::vector basis_arr; // array of basises. ROW_a - X, ROW_b - Y, ROW_c - Z. + std::vector> pointset_arr; // array of point sets: cross curves. // detect closed curves - GeometryHelper_Extrusion_CurveIsClosed(crossSection, true, true, cross_closed);// true - drop tail, true - remove duplicate end. - GeometryHelper_Extrusion_CurveIsClosed(spine, true, true, spine_closed);// true - drop tail, true - remove duplicate end. + GeometryHelper_Extrusion_CurveIsClosed(crossSection, true, true, cross_closed); // true - drop tail, true - remove duplicate end. + GeometryHelper_Extrusion_CurveIsClosed(spine, true, true, spine_closed); // true - drop tail, true - remove duplicate end. // If both cap are requested and spine curve is closed then we can make only one cap. Because second cap will be the same surface. - if(spine_closed) - { - beginCap |= endCap; - endCap = false; - } + if (spine_closed) { + beginCap |= endCap; + endCap = false; + } - {// 1. Calculate array of basises. - aiMatrix4x4 rotmat; - aiVector3D vecX(0), vecY(0), vecZ(0); + { // 1. Calculate array of basises. + aiMatrix4x4 rotmat; + aiVector3D vecX(0), vecY(0), vecZ(0); - basis_arr.resize(spine.size()); - for(size_t i = 0, i_e = spine.size(); i < i_e; i++) - { - aiVector3D tvec; + basis_arr.resize(spine.size()); + for (size_t i = 0, i_e = spine.size(); i < i_e; i++) { + aiVector3D tvec; - // get axises of basis. - vecY = GeometryHelper_Extrusion_GetNextY(i, spine, spine_closed); - vecZ = GeometryHelper_Extrusion_GetNextZ(i, spine, spine_closed, vecZ); - vecX = (vecY ^ vecZ).Normalize(); - // get rotation matrix and apply "orientation" to basis - aiMatrix4x4::Rotation(orientation[i * 4 + 3], aiVector3D(orientation[i * 4], orientation[i * 4 + 1], orientation[i * 4 + 2]), rotmat); - tvec = vecX, tvec *= rotmat, basis_arr[i].a1 = tvec.x, basis_arr[i].a2 = tvec.y, basis_arr[i].a3 = tvec.z; - tvec = vecY, tvec *= rotmat, basis_arr[i].b1 = tvec.x, basis_arr[i].b2 = tvec.y, basis_arr[i].b3 = tvec.z; - tvec = vecZ, tvec *= rotmat, basis_arr[i].c1 = tvec.x, basis_arr[i].c2 = tvec.y, basis_arr[i].c3 = tvec.z; - }// for(size_t i = 0, i_e = spine.size(); i < i_e; i++) - }// END: 1. Calculate array of basises + // get axises of basis. + vecY = GeometryHelper_Extrusion_GetNextY(i, spine, spine_closed); + vecZ = GeometryHelper_Extrusion_GetNextZ(i, spine, spine_closed, vecZ); + vecX = (vecY ^ vecZ).Normalize(); + // get rotation matrix and apply "orientation" to basis + aiMatrix4x4::Rotation(orientation[i * 4 + 3], aiVector3D(orientation[i * 4], orientation[i * 4 + 1], orientation[i * 4 + 2]), rotmat); + tvec = vecX, tvec *= rotmat, basis_arr[i].a1 = tvec.x, basis_arr[i].a2 = tvec.y, basis_arr[i].a3 = tvec.z; + tvec = vecY, tvec *= rotmat, basis_arr[i].b1 = tvec.x, basis_arr[i].b2 = tvec.y, basis_arr[i].b3 = tvec.z; + tvec = vecZ, tvec *= rotmat, basis_arr[i].c1 = tvec.x, basis_arr[i].c2 = tvec.y, basis_arr[i].c3 = tvec.z; + } // for(size_t i = 0, i_e = spine.size(); i < i_e; i++) + } // END: 1. Calculate array of basises - {// 2. Create array of point sets. - aiMatrix4x4 scmat; - std::vector tcross(crossSection.size()); + { // 2. Create array of point sets. + aiMatrix4x4 scmat; + std::vector tcross(crossSection.size()); - pointset_arr.resize(spine.size()); - for(size_t spi = 0, spi_e = spine.size(); spi < spi_e; spi++) - { - aiVector3D tc23vec; + pointset_arr.resize(spine.size()); + for (size_t spi = 0, spi_e = spine.size(); spi < spi_e; spi++) { + aiVector3D tc23vec; - tc23vec.Set(scale[spi].x, 0, scale[spi].y); - aiMatrix4x4::Scaling(tc23vec, scmat); - for(size_t cri = 0, cri_e = crossSection.size(); cri < cri_e; cri++) - { - aiVector3D tvecX, tvecY, tvecZ; + tc23vec.Set(scale[spi].x, 0, scale[spi].y); + aiMatrix4x4::Scaling(tc23vec, scmat); + for (size_t cri = 0, cri_e = crossSection.size(); cri < cri_e; cri++) { + aiVector3D tvecX, tvecY, tvecZ; - tc23vec.Set(crossSection[cri].x, 0, crossSection[cri].y); - // apply scaling to point - tcross[cri] = scmat * tc23vec; - // - // transfer point to new basis - // calculate coordinate in new basis - tvecX.Set(basis_arr[spi].a1, basis_arr[spi].a2, basis_arr[spi].a3), tvecX *= tcross[cri].x; - tvecY.Set(basis_arr[spi].b1, basis_arr[spi].b2, basis_arr[spi].b3), tvecY *= tcross[cri].y; - tvecZ.Set(basis_arr[spi].c1, basis_arr[spi].c2, basis_arr[spi].c3), tvecZ *= tcross[cri].z; - // apply new coordinates and translate it to spine point. - tcross[cri] = tvecX + tvecY + tvecZ + spine[spi]; - }// for(size_t cri = 0, cri_e = crossSection.size(); cri < cri_e; i++) + tc23vec.Set(crossSection[cri].x, 0, crossSection[cri].y); + // apply scaling to point + tcross[cri] = scmat * tc23vec; + // + // transfer point to new basis + // calculate coordinate in new basis + tvecX.Set(basis_arr[spi].a1, basis_arr[spi].a2, basis_arr[spi].a3), tvecX *= tcross[cri].x; + tvecY.Set(basis_arr[spi].b1, basis_arr[spi].b2, basis_arr[spi].b3), tvecY *= tcross[cri].y; + tvecZ.Set(basis_arr[spi].c1, basis_arr[spi].c2, basis_arr[spi].c3), tvecZ *= tcross[cri].z; + // apply new coordinates and translate it to spine point. + tcross[cri] = tvecX + tvecY + tvecZ + spine[spi]; + } // for(size_t cri = 0, cri_e = crossSection.size(); cri < cri_e; i++) - pointset_arr[spi] = tcross;// store transferred point set - }// for(size_t spi = 0, spi_e = spine.size(); spi < spi_e; i++) - }// END: 2. Create array of point sets. + pointset_arr[spi] = tcross; // store transferred point set + } // for(size_t spi = 0, spi_e = spine.size(); spi < spi_e; i++) + } // END: 2. Create array of point sets. - {// 3. Create CoordIdx. - // add caps if needed - if(beginCap) - { - // add cap as polygon. vertices of cap are places at begin, so just add numbers from zero. - for(size_t i = 0, i_e = crossSection.size(); i < i_e; i++) ext_alias.CoordIndex.push_back(static_cast(i)); + { // 3. Create CoordIdx. + // add caps if needed + if (beginCap) { + // add cap as polygon. vertices of cap are places at begin, so just add numbers from zero. + for (size_t i = 0, i_e = crossSection.size(); i < i_e; i++) + ext_alias.CoordIndex.push_back(static_cast(i)); - // add delimiter - ext_alias.CoordIndex.push_back(-1); - }// if(beginCap) + // add delimiter + ext_alias.CoordIndex.push_back(-1); + } // if(beginCap) - if(endCap) - { - // add cap as polygon. vertices of cap are places at end, as for beginCap use just sequence of numbers but with offset. - size_t beg = (pointset_arr.size() - 1) * crossSection.size(); + if (endCap) { + // add cap as polygon. vertices of cap are places at end, as for beginCap use just sequence of numbers but with offset. + size_t beg = (pointset_arr.size() - 1) * crossSection.size(); - for(size_t i = beg, i_e = (beg + crossSection.size()); i < i_e; i++) ext_alias.CoordIndex.push_back(static_cast(i)); + for (size_t i = beg, i_e = (beg + crossSection.size()); i < i_e; i++) + ext_alias.CoordIndex.push_back(static_cast(i)); - // add delimiter - ext_alias.CoordIndex.push_back(-1); - }// if(beginCap) + // add delimiter + ext_alias.CoordIndex.push_back(-1); + } // if(beginCap) - // add quads - for(size_t spi = 0, spi_e = (spine.size() - 1); spi <= spi_e; spi++) - { - const size_t cr_sz = crossSection.size(); - const size_t cr_last = crossSection.size() - 1; + // add quads + for (size_t spi = 0, spi_e = (spine.size() - 1); spi <= spi_e; spi++) { + const size_t cr_sz = crossSection.size(); + const size_t cr_last = crossSection.size() - 1; - size_t right_col;// hold index basis for points of quad placed in right column; + size_t right_col; // hold index basis for points of quad placed in right column; - if(spi != spi_e) - right_col = spi + 1; - else if(spine_closed)// if spine curve is closed then one more quad is needed: between first and last points of curve. - right_col = 0; - else - break;// if spine curve is not closed then break the loop, because spi is out of range for that type of spine. + if (spi != spi_e) + right_col = spi + 1; + else if (spine_closed) // if spine curve is closed then one more quad is needed: between first and last points of curve. + right_col = 0; + else + break; // if spine curve is not closed then break the loop, because spi is out of range for that type of spine. - for(size_t cri = 0; cri < cr_sz; cri++) - { - if(cri != cr_last) - { - MACRO_FACE_ADD_QUAD(ccw, ext_alias.CoordIndex, - static_cast(spi * cr_sz + cri), - static_cast(right_col * cr_sz + cri), - static_cast(right_col * cr_sz + cri + 1), - static_cast(spi * cr_sz + cri + 1)); - // add delimiter - ext_alias.CoordIndex.push_back(-1); - } - else if(cross_closed)// if cross curve is closed then one more quad is needed: between first and last points of curve. - { - MACRO_FACE_ADD_QUAD(ccw, ext_alias.CoordIndex, - static_cast(spi * cr_sz + cri), - static_cast(right_col * cr_sz + cri), - static_cast(right_col * cr_sz + 0), - static_cast(spi * cr_sz + 0)); - // add delimiter - ext_alias.CoordIndex.push_back(-1); - } - }// for(size_t cri = 0; cri < cr_sz; cri++) - }// for(size_t spi = 0, spi_e = (spine.size() - 2); spi < spi_e; spi++) - }// END: 3. Create CoordIdx. + for (size_t cri = 0; cri < cr_sz; cri++) { + if (cri != cr_last) { + MACRO_FACE_ADD_QUAD(ccw, ext_alias.CoordIndex, + static_cast(spi * cr_sz + cri), + static_cast(right_col * cr_sz + cri), + static_cast(right_col * cr_sz + cri + 1), + static_cast(spi * cr_sz + cri + 1)); + // add delimiter + ext_alias.CoordIndex.push_back(-1); + } else if (cross_closed) // if cross curve is closed then one more quad is needed: between first and last points of curve. + { + MACRO_FACE_ADD_QUAD(ccw, ext_alias.CoordIndex, + static_cast(spi * cr_sz + cri), + static_cast(right_col * cr_sz + cri), + static_cast(right_col * cr_sz + 0), + static_cast(spi * cr_sz + 0)); + // add delimiter + ext_alias.CoordIndex.push_back(-1); + } + } // for(size_t cri = 0; cri < cr_sz; cri++) + } // for(size_t spi = 0, spi_e = (spine.size() - 2); spi < spi_e; spi++) + } // END: 3. Create CoordIdx. - {// 4. Create vertices list. - // just copy all vertices - for(size_t spi = 0, spi_e = spine.size(); spi < spi_e; spi++) - { - for(size_t cri = 0, cri_e = crossSection.size(); cri < cri_e; cri++) - { - ext_alias.Vertices.emplace_back(pointset_arr[spi][cri]); - } - } - }// END: 4. Create vertices list. -//PrintVectorSet("Ext. CoordIdx", ext_alias.CoordIndex); -//PrintVectorSet("Ext. Vertices", ext_alias.Vertices); - // check for child nodes - if(!isNodeEmpty(node)) - childrenReadMetadata(node, ne, "Extrusion"); - else - mNodeElementCur->Children.push_back(ne);// add made object as child to current element + { // 4. Create vertices list. + // just copy all vertices + for (size_t spi = 0, spi_e = spine.size(); spi < spi_e; spi++) { + for (size_t cri = 0, cri_e = crossSection.size(); cri < cri_e; cri++) { + ext_alias.Vertices.emplace_back(pointset_arr[spi][cri]); + } + } + } // END: 4. Create vertices list. + //PrintVectorSet("Ext. CoordIdx", ext_alias.CoordIndex); + //PrintVectorSet("Ext. Vertices", ext_alias.Vertices); + // check for child nodes + if (!isNodeEmpty(node)) + childrenReadMetadata(node, ne, "Extrusion"); + else + mNodeElementCur->Children.push_back(ne); // add made object as child to current element - NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph - }// if(!use.empty()) else + NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph + } // if(!use.empty()) else } // texCoordIndex; - X3DNodeElementBase* ne( nullptr ); + X3DNodeElementBase *ne(nullptr); MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use); XmlParser::getBoolAttribute(node, "ccw", ccw); @@ -874,56 +813,57 @@ void X3DImporter::readIndexedFaceSet(XmlNode &node) { XmlParser::getBoolAttribute(node, "solid", solid); X3DXmlHelper::getInt32ArrayAttribute(node, "texCoordIndex", texCoordIndex); - // if "USE" defined then find already defined element. - if(!use.empty()) - { - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedFaceSet, ne); - } - else - { - // check data - if(coordIndex.size() == 0) throw DeadlyImportError("IndexedFaceSet must contain not empty \"coordIndex\" attribute."); + // if "USE" defined then find already defined element. + if (!use.empty()) { + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedFaceSet, ne); + } else { + // check data + if (coordIndex.size() == 0) throw DeadlyImportError("IndexedFaceSet must contain not empty \"coordIndex\" attribute."); - // create and if needed - define new geometry object. - ne = new X3DNodeElementIndexedSet(X3DElemType::ENET_IndexedFaceSet, mNodeElementCur); - if(!def.empty()) ne->ID = def; + // create and if needed - define new geometry object. + ne = new X3DNodeElementIndexedSet(X3DElemType::ENET_IndexedFaceSet, mNodeElementCur); + if (!def.empty()) ne->ID = def; - X3DNodeElementIndexedSet &ne_alias = *((X3DNodeElementIndexedSet *)ne); + X3DNodeElementIndexedSet &ne_alias = *((X3DNodeElementIndexedSet *)ne); - ne_alias.CCW = ccw; - ne_alias.ColorIndex = colorIndex; - ne_alias.ColorPerVertex = colorPerVertex; - ne_alias.Convex = convex; - ne_alias.CoordIndex = coordIndex; - ne_alias.CreaseAngle = creaseAngle; - ne_alias.NormalIndex = normalIndex; - ne_alias.NormalPerVertex = normalPerVertex; - ne_alias.Solid = solid; - ne_alias.TexCoordIndex = texCoordIndex; + ne_alias.CCW = ccw; + ne_alias.ColorIndex = colorIndex; + ne_alias.ColorPerVertex = colorPerVertex; + ne_alias.Convex = convex; + ne_alias.CoordIndex = coordIndex; + ne_alias.CreaseAngle = creaseAngle; + ne_alias.NormalIndex = normalIndex; + ne_alias.NormalPerVertex = normalPerVertex; + ne_alias.Solid = solid; + ne_alias.TexCoordIndex = texCoordIndex; // check for child nodes - if(!isNodeEmpty(node)) - { - ParseHelper_Node_Enter(ne); + if (!isNodeEmpty(node)) { + ParseHelper_Node_Enter(ne); for (auto currentChildNode : node.children()) { const std::string ¤tChildName = currentChildNode.name(); // check for X3DComposedGeometryNodes - if (currentChildName == "Color") readColor(currentChildNode); - else if (currentChildName == "ColorRGBA") readColorRGBA(currentChildNode); - else if (currentChildName == "Coordinate") readCoordinate(currentChildNode); - else if (currentChildName == "Normal") readNormal(currentChildNode); - else if (currentChildName == "TextureCoordinate") readTextureCoordinate(currentChildNode); + if (currentChildName == "Color") + readColor(currentChildNode); + else if (currentChildName == "ColorRGBA") + readColorRGBA(currentChildNode); + else if (currentChildName == "Coordinate") + readCoordinate(currentChildNode); + else if (currentChildName == "Normal") + readNormal(currentChildNode); + else if (currentChildName == "TextureCoordinate") + readTextureCoordinate(currentChildNode); // check for X3DMetadataObject - else if (!checkForMetadataNode(currentChildNode)) skipUnsupportedNode("IndexedFaceSet", currentChildNode); + else if (!checkForMetadataNode(currentChildNode)) + skipUnsupportedNode("IndexedFaceSet", currentChildNode); } - ParseHelper_Node_Exit(); - }// if(!isNodeEmpty(node)) - else - { - mNodeElementCur->Children.push_back(ne);// add made object as child to current element - } + ParseHelper_Node_Exit(); + } // if(!isNodeEmpty(node)) + else { + mNodeElementCur->Children.push_back(ne); // add made object as child to current element + } - NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph - }// if(!use.empty()) else + NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph + } // if(!use.empty()) else } // tlist; + std::vector tlist; - // create and if needed - define new geometry object. - ne = new X3DNodeElementGeometry3D(X3DElemType::ENET_Sphere, mNodeElementCur); - if(!def.empty()) ne->ID = def; + // create and if needed - define new geometry object. + ne = new X3DNodeElementGeometry3D(X3DElemType::ENET_Sphere, mNodeElementCur); + if (!def.empty()) ne->ID = def; - StandardShapes::MakeSphere(tess, tlist); - // copy data from temp array and apply scale - for(std::vector::iterator it = tlist.begin(); it != tlist.end(); ++it) - { + StandardShapes::MakeSphere(tess, tlist); + // copy data from temp array and apply scale + for (std::vector::iterator it = tlist.begin(); it != tlist.end(); ++it) { ((X3DNodeElementGeometry3D *)ne)->Vertices.push_back(*it * radius); - } + } - ((X3DNodeElementGeometry3D *)ne)->Solid = solid; + ((X3DNodeElementGeometry3D *)ne)->Solid = solid; ((X3DNodeElementGeometry3D *)ne)->NumIndices = 3; - // check for X3DMetadataObject childs. - if(!isNodeEmpty(node)) - childrenReadMetadata(node, ne, "Sphere"); - else - mNodeElementCur->Children.push_back(ne);// add made object as child to current element + // check for X3DMetadataObject childs. + if (!isNodeEmpty(node)) + childrenReadMetadata(node, ne, "Sphere"); + else + mNodeElementCur->Children.push_back(ne); // add made object as child to current element - NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph - }// if(!use.empty()) else + NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph + } // if(!use.empty()) else } -}// namespace Assimp +} // namespace Assimp #endif // !ASSIMP_BUILD_NO_X3D_IMPORTER diff --git a/code/AssetLib/X3D/X3DImporter_Group.cpp b/code/AssetLib/X3D/X3DImporter_Group.cpp index d672d741b..f579dc517 100644 --- a/code/AssetLib/X3D/X3DImporter_Group.cpp +++ b/code/AssetLib/X3D/X3DImporter_Group.cpp @@ -72,9 +72,8 @@ void X3DImporter::startReadGroup(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - X3DNodeElementBase *ne; - - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Group, ne); + X3DNodeElementBase *ne = nullptr; + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Group, ne); } else { ParseHelper_Group_Begin(); // create new grouping element and go deeper if node has children. // at this place new group mode created and made current, so we can name it. @@ -111,9 +110,9 @@ void X3DImporter::startReadStaticGroup(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - X3DNodeElementBase *ne; + X3DNodeElementBase *ne = nullptr; - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Group, ne); + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Group, ne); } else { ParseHelper_Group_Begin(true); // create new grouping element and go deeper if node has children. // at this place new group mode created and made current, so we can name it. @@ -154,9 +153,9 @@ void X3DImporter::startReadSwitch(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - X3DNodeElementBase *ne; + X3DNodeElementBase *ne=nullptr; - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Group, ne); + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Group, ne); } else { ParseHelper_Group_Begin(); // create new grouping element and go deeper if node has children. // at this place new group mode created and made current, so we can name it. @@ -228,7 +227,7 @@ void X3DImporter::startReadTransform(XmlNode &node) { if (!use.empty()) { X3DNodeElementBase *ne(nullptr); - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Group, ne); + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Group, ne); } else { ParseHelper_Group_Begin(); // create new grouping element and go deeper if node has children. // at this place new group mode created and made current, so we can name it. diff --git a/code/AssetLib/X3D/X3DImporter_Light.cpp b/code/AssetLib/X3D/X3DImporter_Light.cpp index b9bd17164..f1ed5e4cd 100644 --- a/code/AssetLib/X3D/X3DImporter_Light.cpp +++ b/code/AssetLib/X3D/X3DImporter_Light.cpp @@ -83,7 +83,7 @@ void X3DImporter::readDirectionalLight(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_DirectionalLight, ne); + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_DirectionalLight, ne); } else { if (on) { // create and if needed - define new geometry object. @@ -150,7 +150,7 @@ void X3DImporter::readPointLight(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_PointLight, ne); + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_PointLight, ne); } else { if (on) { // create and if needed - define new geometry object. @@ -227,7 +227,7 @@ void X3DImporter::readSpotLight(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_SpotLight, ne); + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_SpotLight, ne); } else { if (on) { // create and if needed - define new geometry object. diff --git a/code/AssetLib/X3D/X3DImporter_Macro.hpp b/code/AssetLib/X3D/X3DImporter_Macro.hpp index f493a86e9..08aac3da7 100644 --- a/code/AssetLib/X3D/X3DImporter_Macro.hpp +++ b/code/AssetLib/X3D/X3DImporter_Macro.hpp @@ -47,20 +47,36 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef X3DIMPORTER_MACRO_HPP_INCLUDED #define X3DIMPORTER_MACRO_HPP_INCLUDED -/// \def MACRO_USE_CHECKANDAPPLY(pDEF, pUSE, pNE) +#include +#include "X3DImporter.hpp" +#include + +namespace Assimp { + /// Used for regular checking while attribute "USE" is defined. /// \param [in] pNode - pugi xml node to read. /// \param [in] pDEF - string holding "DEF" value. /// \param [in] pUSE - string holding "USE" value. /// \param [in] pType - type of element to find. /// \param [out] pNE - pointer to found node element. -#define MACRO_USE_CHECKANDAPPLY(pNode, pDEF, pUSE, pType, pNE) \ - do { \ - checkNodeMustBeEmpty(pNode); \ - if (!pDEF.empty()) Throw_DEF_And_USE(pNode.name()); \ - if (!FindNodeElement(pUSE, X3DElemType::pType, &pNE)) Throw_USE_NotFound(pNode.name(), pUSE); \ - mNodeElementCur->Children.push_back(pNE); /* add found object as child to current element */ \ - } while (false) +inline X3DNodeElementBase *X3DImporter::MACRO_USE_CHECKANDAPPLY(XmlNode &node, std::string pDEF, std::string pUSE, X3DElemType pType, X3DNodeElementBase *pNE) { + if (nullptr == mNodeElementCur) { + printf("here\n"); + } + + //do { + checkNodeMustBeEmpty(node); + if (!pDEF.empty()) + Assimp::Throw_DEF_And_USE(node.name()); + if (!FindNodeElement(pUSE, pType, &pNE)) + Assimp::Throw_USE_NotFound(node.name(), pUSE); + mNodeElementCur->Children.push_back(pNE); /* add found object as child to current element */ + //} while (false); + + return pNE; +} + +} // namespace Assimp /// \def MACRO_ATTRREAD_CHECKUSEDEF_RET /// Compact variant for checking "USE" and "DEF". diff --git a/code/AssetLib/X3D/X3DImporter_Metadata.cpp b/code/AssetLib/X3D/X3DImporter_Metadata.cpp index bb1ba9a9d..8e07d8bb8 100644 --- a/code/AssetLib/X3D/X3DImporter_Metadata.cpp +++ b/code/AssetLib/X3D/X3DImporter_Metadata.cpp @@ -93,7 +93,7 @@ void X3DImporter::childrenReadMetadata(XmlNode &node, X3DNodeElementBase *pParen #define MACRO_METADATA_FINDCREATE(pNode, pDEF_Var, pUSE_Var, pReference, pValue, pNE, pMetaClass, pMetaName, pType) \ /* if "USE" defined then find already defined element. */ \ if (!pUSE_Var.empty()) { \ - MACRO_USE_CHECKANDAPPLY(pNode, pDEF_Var, pUSE_Var, pType, pNE); \ + ne = MACRO_USE_CHECKANDAPPLY(pNode, pDEF_Var, pUSE_Var, pType, pNE); \ } else { \ pNE = new pMetaClass(mNodeElementCur); \ if (!pDEF_Var.empty()) pNE->ID = pDEF_Var; \ @@ -213,13 +213,13 @@ void X3DImporter::readMetadataSet(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_MetaSet, ne); + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_MetaSet, ne); } else { ne = new X3DNodeElementMetaSet(mNodeElementCur); if (!def.empty()) ne->ID = def; ((X3DNodeElementMetaSet *)ne)->Reference = reference; - // also metadata node can contain childs + // also metadata node can contain children if (!isNodeEmpty(node)) childrenReadMetadata(node, ne, "MetadataSet"); else diff --git a/code/AssetLib/X3D/X3DImporter_Networking.cpp b/code/AssetLib/X3D/X3DImporter_Networking.cpp index d5ef58397..f2b471692 100644 --- a/code/AssetLib/X3D/X3DImporter_Networking.cpp +++ b/code/AssetLib/X3D/X3DImporter_Networking.cpp @@ -78,10 +78,9 @@ void X3DImporter::readInline(XmlNode &node) { X3DXmlHelper::getStringListAttribute(node, "url", url); // if "USE" defined then find already defined element. + X3DNodeElementBase *ne = nullptr; if (!use.empty()) { - X3DNodeElementBase *ne; - - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Group, ne); + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Group, ne); } else { ParseHelper_Group_Begin(true); // create new grouping element and go deeper if node has children. // at this place new group mode created and made current, so we can name it. diff --git a/code/AssetLib/X3D/X3DImporter_Rendering.cpp b/code/AssetLib/X3D/X3DImporter_Rendering.cpp index fe7e68081..66a30a916 100644 --- a/code/AssetLib/X3D/X3DImporter_Rendering.cpp +++ b/code/AssetLib/X3D/X3DImporter_Rendering.cpp @@ -67,7 +67,7 @@ void X3DImporter::readColor(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Color, ne); + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Color, ne); } else { // create and if needed - define new geometry object. ne = new X3DNodeElementColor(mNodeElementCur); @@ -99,7 +99,7 @@ void X3DImporter::readColorRGBA(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_ColorRGBA, ne); + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_ColorRGBA, ne); } else { // create and if needed - define new geometry object. ne = new X3DNodeElementColorRGBA(mNodeElementCur); @@ -131,7 +131,7 @@ void X3DImporter::readCoordinate(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Coordinate, ne); + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Coordinate, ne); } else { // create and if needed - define new geometry object. ne = new X3DNodeElementCoordinate(mNodeElementCur); @@ -174,7 +174,7 @@ void X3DImporter::readIndexedLineSet(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedLineSet, ne); + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedLineSet, ne); } else { // check data if ((coordIndex.size() < 2) || ((coordIndex.back() == (-1)) && (coordIndex.size() < 3))) @@ -248,7 +248,7 @@ void X3DImporter::readIndexedTriangleFanSet(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedTriangleFanSet, ne); + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedTriangleFanSet, ne); } else { // check data if (index.size() == 0) throw DeadlyImportError("IndexedTriangleFanSet must contain not empty \"index\" attribute."); @@ -354,7 +354,7 @@ void X3DImporter::readIndexedTriangleSet(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedTriangleSet, ne); + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedTriangleSet, ne); } else { // check data if (index.size() == 0) throw DeadlyImportError("IndexedTriangleSet must contain not empty \"index\" attribute."); @@ -453,10 +453,12 @@ void X3DImporter::readIndexedTriangleStripSet(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedTriangleStripSet, ne); + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedTriangleStripSet, ne); } else { // check data - if (index.size() == 0) throw DeadlyImportError("IndexedTriangleStripSet must contain not empty \"index\" attribute."); + if (index.empty()) { + throw DeadlyImportError("IndexedTriangleStripSet must contain not empty \"index\" attribute."); + } // create and if needed - define new geometry object. ne = new X3DNodeElementIndexedSet(X3DElemType::ENET_IndexedTriangleStripSet, mNodeElementCur); @@ -544,10 +546,12 @@ void X3DImporter::readLineSet(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_LineSet, ne); + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_LineSet, ne); } else { // check data - if (vertexCount.size() == 0) throw DeadlyImportError("LineSet must contain not empty \"vertexCount\" attribute."); + if (vertexCount.empty()) { + throw DeadlyImportError("LineSet must contain not empty \"vertexCount\" attribute."); + } // create and if needed - define new geometry object. ne = new X3DNodeElementSet(X3DElemType::ENET_LineSet, mNodeElementCur); @@ -612,7 +616,7 @@ void X3DImporter::readPointSet(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_PointSet, ne); + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_PointSet, ne); } else { // create and if needed - define new geometry object. ne = new X3DNodeElementIndexedSet(X3DElemType::ENET_PointSet, mNodeElementCur); @@ -677,10 +681,12 @@ void X3DImporter::readTriangleFanSet(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TriangleFanSet, ne); + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TriangleFanSet, ne); } else { // check data - if (fanCount.size() == 0) throw DeadlyImportError("TriangleFanSet must contain not empty \"fanCount\" attribute."); + if (fanCount.empty()) { + throw DeadlyImportError("TriangleFanSet must contain not empty \"fanCount\" attribute."); + } // create and if needed - define new geometry object. ne = new X3DNodeElementSet(X3DElemType::ENET_TriangleFanSet, mNodeElementCur); @@ -784,7 +790,7 @@ void X3DImporter::readTriangleSet(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TriangleSet, ne); + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TriangleSet, ne); } else { // create and if needed - define new geometry object. ne = new X3DNodeElementIndexedSet(X3DElemType::ENET_TriangleSet, mNodeElementCur); @@ -859,7 +865,7 @@ void X3DImporter::readTriangleStripSet(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TriangleStripSet, ne); + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TriangleStripSet, ne); } else { // check data if (stripCount.size() == 0) throw DeadlyImportError("TriangleStripSet must contain not empty \"stripCount\" attribute."); @@ -958,14 +964,14 @@ void X3DImporter::readTriangleStripSet(XmlNode &node) { void X3DImporter::readNormal(XmlNode &node) { std::string use, def; std::list vector; - X3DNodeElementBase *ne; + X3DNodeElementBase *ne=nullptr; MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use); X3DXmlHelper::getVector3DListAttribute(node, "vector", vector); // if "USE" defined then find already defined element. if (!use.empty()) { - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Normal, ne); + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Normal, ne); } else { // create and if needed - define new geometry object. ne = new X3DNodeElementNormal(mNodeElementCur); diff --git a/code/AssetLib/X3D/X3DImporter_Shape.cpp b/code/AssetLib/X3D/X3DImporter_Shape.cpp index 7a292be5c..1c472e14b 100644 --- a/code/AssetLib/X3D/X3DImporter_Shape.cpp +++ b/code/AssetLib/X3D/X3DImporter_Shape.cpp @@ -60,7 +60,7 @@ void X3DImporter::readShape(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Shape, ne); + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Shape, ne); } else { // create and if needed - define new geometry object. ne = new X3DNodeElementShape(mNodeElementCur); @@ -74,31 +74,55 @@ void X3DImporter::readShape(XmlNode &node) { // check for appearance node if (currentChildName == "Appearance") readAppearance(currentChildNode); // check for X3DGeometryNodes - else if (currentChildName == "Arc2D") readArc2D(currentChildNode); - else if (currentChildName == "ArcClose2D") readArcClose2D(currentChildNode); - else if (currentChildName == "Circle2D") readCircle2D(currentChildNode); - else if (currentChildName == "Disk2D") readDisk2D(currentChildNode); - else if (currentChildName == "Polyline2D") readPolyline2D(currentChildNode); - else if (currentChildName == "Polypoint2D") readPolypoint2D(currentChildNode); - else if (currentChildName == "Rectangle2D") readRectangle2D(currentChildNode); - else if (currentChildName == "TriangleSet2D") readTriangleSet2D(currentChildNode); - else if (currentChildName == "Box") readBox(currentChildNode); - else if (currentChildName == "Cone") readCone(currentChildNode); - else if (currentChildName == "Cylinder") readCylinder(currentChildNode); - else if (currentChildName == "ElevationGrid") readElevationGrid(currentChildNode); - else if (currentChildName == "Extrusion") readExtrusion(currentChildNode); - else if (currentChildName == "IndexedFaceSet") readIndexedFaceSet(currentChildNode); - else if (currentChildName == "Sphere") readSphere(currentChildNode); - else if (currentChildName == "IndexedLineSet") readIndexedLineSet(currentChildNode); - else if (currentChildName == "LineSet") readLineSet(currentChildNode); - else if (currentChildName == "PointSet") readPointSet(currentChildNode); - else if (currentChildName == "IndexedTriangleFanSet") readIndexedTriangleFanSet(currentChildNode); - else if (currentChildName == "IndexedTriangleSet") readIndexedTriangleSet(currentChildNode); - else if (currentChildName == "IndexedTriangleStripSet") readIndexedTriangleStripSet(currentChildNode); - else if (currentChildName == "TriangleFanSet") readTriangleFanSet(currentChildNode); - else if (currentChildName == "TriangleSet") readTriangleSet(currentChildNode); + else if (currentChildName == "Arc2D") + readArc2D(currentChildNode); + else if (currentChildName == "ArcClose2D") + readArcClose2D(currentChildNode); + else if (currentChildName == "Circle2D") + readCircle2D(currentChildNode); + else if (currentChildName == "Disk2D") + readDisk2D(currentChildNode); + else if (currentChildName == "Polyline2D") + readPolyline2D(currentChildNode); + else if (currentChildName == "Polypoint2D") + readPolypoint2D(currentChildNode); + else if (currentChildName == "Rectangle2D") + readRectangle2D(currentChildNode); + else if (currentChildName == "TriangleSet2D") + readTriangleSet2D(currentChildNode); + else if (currentChildName == "Box") + readBox(currentChildNode); + else if (currentChildName == "Cone") + readCone(currentChildNode); + else if (currentChildName == "Cylinder") + readCylinder(currentChildNode); + else if (currentChildName == "ElevationGrid") + readElevationGrid(currentChildNode); + else if (currentChildName == "Extrusion") + readExtrusion(currentChildNode); + else if (currentChildName == "IndexedFaceSet") + readIndexedFaceSet(currentChildNode); + else if (currentChildName == "Sphere") + readSphere(currentChildNode); + else if (currentChildName == "IndexedLineSet") + readIndexedLineSet(currentChildNode); + else if (currentChildName == "LineSet") + readLineSet(currentChildNode); + else if (currentChildName == "PointSet") + readPointSet(currentChildNode); + else if (currentChildName == "IndexedTriangleFanSet") + readIndexedTriangleFanSet(currentChildNode); + else if (currentChildName == "IndexedTriangleSet") + readIndexedTriangleSet(currentChildNode); + else if (currentChildName == "IndexedTriangleStripSet") + readIndexedTriangleStripSet(currentChildNode); + else if (currentChildName == "TriangleFanSet") + readTriangleFanSet(currentChildNode); + else if (currentChildName == "TriangleSet") + readTriangleSet(currentChildNode); // check for X3DMetadataObject - else if (!checkForMetadataNode(currentChildNode)) skipUnsupportedNode("Shape", currentChildNode); + else if (!checkForMetadataNode(currentChildNode)) + skipUnsupportedNode("Shape", currentChildNode); } ParseHelper_Node_Exit(); @@ -123,42 +147,41 @@ void X3DImporter::readShape(XmlNode &node) { // void X3DImporter::readAppearance(XmlNode &node) { std::string use, def; - X3DNodeElementBase* ne( nullptr ); + X3DNodeElementBase *ne(nullptr); MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use); - // if "USE" defined then find already defined element. - if (!use.empty()) - { - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Appearance, ne); - } - else - { - // create and if needed - define new geometry object. - ne = new X3DNodeElementAppearance(mNodeElementCur); - if(!def.empty()) ne->ID = def; + // if "USE" defined then find already defined element. + if (!use.empty()) { + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Appearance, ne); + } else { + // create and if needed - define new geometry object. + ne = new X3DNodeElementAppearance(mNodeElementCur); + if (!def.empty()) ne->ID = def; // check for child nodes - if(!isNodeEmpty(node)) - { - ParseHelper_Node_Enter(ne); + if (!isNodeEmpty(node)) { + ParseHelper_Node_Enter(ne); for (auto currentChildNode : node.children()) { const std::string ¤tChildName = currentChildNode.name(); - if (currentChildName == "Material") readMaterial(currentChildNode); - else if (currentChildName == "ImageTexture") readImageTexture(currentChildNode); - else if (currentChildName == "TextureTransform") readTextureTransform(currentChildNode); + if (currentChildName == "Material") + readMaterial(currentChildNode); + else if (currentChildName == "ImageTexture") + readImageTexture(currentChildNode); + else if (currentChildName == "TextureTransform") + readTextureTransform(currentChildNode); // check for X3DMetadataObject - else if (!checkForMetadataNode(currentChildNode)) skipUnsupportedNode("Appearance", currentChildNode); + else if (!checkForMetadataNode(currentChildNode)) + skipUnsupportedNode("Appearance", currentChildNode); } - ParseHelper_Node_Exit(); - }// if(!isNodeEmpty(node)) - else - { - mNodeElementCur->Children.push_back(ne);// add made object as child to current element - } + ParseHelper_Node_Exit(); + } // if(!isNodeEmpty(node)) + else { + mNodeElementCur->Children.push_back(ne); // add made object as child to current element + } - NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph - }// if(!use.empty()) else + NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph + } // if(!use.empty()) else } // ID = def; + // if "USE" defined then find already defined element. + if (!use.empty()) { + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Material, ne); + } else { + // create and if needed - define new geometry object. + ne = new X3DNodeElementMaterial(mNodeElementCur); + if (!def.empty()) ne->ID = def; - ((X3DNodeElementMaterial *)ne)->AmbientIntensity = ambientIntensity; + ((X3DNodeElementMaterial *)ne)->AmbientIntensity = ambientIntensity; ((X3DNodeElementMaterial *)ne)->Shininess = shininess; ((X3DNodeElementMaterial *)ne)->Transparency = transparency; ((X3DNodeElementMaterial *)ne)->DiffuseColor = diffuseColor; ((X3DNodeElementMaterial *)ne)->EmissiveColor = emissiveColor; ((X3DNodeElementMaterial *)ne)->SpecularColor = specularColor; // check for child nodes - if(!isNodeEmpty(node)) - childrenReadMetadata(node, ne, "Material"); - else + if (!isNodeEmpty(node)) + childrenReadMetadata(node, ne, "Material"); + else mNodeElementCur->Children.push_back(ne); // add made object as child to current element - NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph - }// if(!use.empty()) else + NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph + } // if(!use.empty()) else } -}// namespace Assimp +} // namespace Assimp #endif // !ASSIMP_BUILD_NO_X3D_IMPORTER diff --git a/code/AssetLib/X3D/X3DImporter_Texturing.cpp b/code/AssetLib/X3D/X3DImporter_Texturing.cpp index 6463e2808..32c1a90d7 100644 --- a/code/AssetLib/X3D/X3DImporter_Texturing.cpp +++ b/code/AssetLib/X3D/X3DImporter_Texturing.cpp @@ -74,7 +74,7 @@ void X3DImporter::readImageTexture(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_ImageTexture, ne); + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_ImageTexture, ne); } else { // create and if needed - define new geometry object. ne = new X3DNodeElementImageTexture(mNodeElementCur); @@ -113,7 +113,7 @@ void X3DImporter::readTextureCoordinate(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TextureCoordinate, ne); + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TextureCoordinate, ne); } else { // create and if needed - define new geometry object. ne = new X3DNodeElementTextureCoordinate(mNodeElementCur); @@ -154,7 +154,7 @@ void X3DImporter::readTextureTransform(XmlNode &node) { // if "USE" defined then find already defined element. if (!use.empty()) { - MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TextureTransform, ne); + ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TextureTransform, ne); } else { // create and if needed - define new geometry object. ne = new X3DNodeElementTextureTransform(mNodeElementCur); diff --git a/test/models/X3D/HelloX3dTrademark.x3d b/test/models/X3D/HelloX3dTrademark.x3d new file mode 100644 index 000000000..09aec075e --- /dev/null +++ b/test/models/X3D/HelloX3dTrademark.x3d @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/test.3mf b/test/test.3mf index eb1c49e1b1a6e71d1ce6c95fec699be6d1357051..72f6ae43766ddd789ed0f3fbc56917ccaacf577f 100644 GIT binary patch delta 68 zcmey)@tuP&z?+#xgn@y9gW>(;tl)`!Usyo&W;VtPj9}K}TTHhhjGfH35XLWND+t4a G#U21nG#VuU delta 68 zcmey)@tuP&z?+#xgn@y9gCV(eY0yNzFDxK>GaKUtMlfsgEvDNL#!hBi2;&#C6@+2I GVh;fNrx%3) diff --git a/test/unit/utX3DImportExport.cpp b/test/unit/utX3DImportExport.cpp index de3bfbc96..0d753c889 100644 --- a/test/unit/utX3DImportExport.cpp +++ b/test/unit/utX3DImportExport.cpp @@ -49,7 +49,7 @@ using namespace Assimp; class utX3DImportExport : public AbstractImportExportBase { public: - virtual bool importerTest() { + bool importerTest() override { Assimp::Importer importer; const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/X3D/ComputerKeyboard.x3d", aiProcess_ValidateDataStructure); return nullptr != scene;