pull/4170/head
Kim Kulling 2021-11-10 20:37:27 +01:00
parent 791cb195be
commit 8ed18621db
15 changed files with 741 additions and 708 deletions

View File

@ -75,7 +75,7 @@ bool X3DImporter::isNodeEmpty(XmlNode &node) {
} }
void X3DImporter::checkNodeMustBeEmpty(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) { void X3DImporter::skipUnsupportedNode(const std::string &pParentNodeName, XmlNode &node) {
@ -321,7 +321,7 @@ void X3DImporter::readHead(XmlNode &node) {
for (auto currentNode : node.children()) { for (auto currentNode : node.children()) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
if (currentName == "meta") { if (currentName == "meta") {
checkNodeMustBeEmpty(node); //checkNodeMustBeEmpty(node);
meta_entry entry; meta_entry entry;
if (XmlParser::getStdStrAttribute(currentNode, "name", entry.name)) { if (XmlParser::getStdStrAttribute(currentNode, "name", entry.name)) {
XmlParser::getStdStrAttribute(currentNode, "content", entry.value); XmlParser::getStdStrAttribute(currentNode, "content", entry.value);
@ -339,6 +339,9 @@ void X3DImporter::readHead(XmlNode &node) {
} }
void X3DImporter::readChildNodes(XmlNode &node, const std::string &pParentNodeName) { void X3DImporter::readChildNodes(XmlNode &node, const std::string &pParentNodeName) {
if (node.empty()) {
return;
}
for (auto currentNode : node.children()) { for (auto currentNode : node.children()) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
if (currentName == "Shape") if (currentName == "Shape")
@ -463,6 +466,8 @@ void X3DImporter::ParseHelper_Group_Begin(const bool pStatic) {
} }
void X3DImporter::ParseHelper_Node_Enter(X3DNodeElementBase *pNode) { 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->Children.push_back(pNode); // add new element to current element child list.
mNodeElementCur = pNode; // switch current element to new one. mNodeElementCur = pNode; // switch current element to new one.
} }
@ -471,6 +476,9 @@ void X3DImporter::ParseHelper_Node_Exit() {
// check if we can walk up. // check if we can walk up.
if (mNodeElementCur != nullptr) { if (mNodeElementCur != nullptr) {
mNodeElementCur = mNodeElementCur->Parent; mNodeElementCur = mNodeElementCur->Parent;
} else {
int i = 0;
++i;
} }
} }

View File

@ -270,6 +270,7 @@ public:
void Clear(); void Clear();
private: private:
X3DNodeElementBase *MACRO_USE_CHECKANDAPPLY(XmlNode &node, std::string pDEF, std::string pUSE, X3DElemType pType, X3DNodeElementBase *pNE);
bool isNodeEmpty(XmlNode &node); bool isNodeEmpty(XmlNode &node);
void checkNodeMustBeEmpty(XmlNode &node); void checkNodeMustBeEmpty(XmlNode &node);
void skipUnsupportedNode(const std::string &pParentNodeName, XmlNode &node); void skipUnsupportedNode(const std::string &pParentNodeName, XmlNode &node);

View File

@ -78,7 +78,7 @@ void X3DImporter::readArc2D(XmlNode &node) {
// if "USE" defined then find already defined element. // if "USE" defined then find already defined element.
if (!use.empty()) { if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Arc2D, ne); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Arc2D, ne);
} else { } else {
// create and if needed - define new geometry object. // create and if needed - define new geometry object.
ne = new X3DNodeElementGeometry2D(X3DElemType::ENET_Arc2D, mNodeElementCur); 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" defined then find already defined element.
if (!use.empty()) { if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_ArcClose2D, ne); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_ArcClose2D, ne);
} else { } else {
// create and if needed - define new geometry object. // create and if needed - define new geometry object.
ne = new X3DNodeElementGeometry2D(X3DElemType::ENET_ArcClose2D, mNodeElementCur); 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" defined then find already defined element.
if (!use.empty()) { if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Circle2D, ne); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Circle2D, ne);
} else { } else {
// create and if needed - define new geometry object. // create and if needed - define new geometry object.
ne = new X3DNodeElementGeometry2D(X3DElemType::ENET_Circle2D, mNodeElementCur); 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" defined then find already defined element.
if (!use.empty()) { if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Disk2D, ne); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Disk2D, ne);
} else { } else {
std::list<aiVector3D> tlist_o, tlist_i; std::list<aiVector3D> tlist_o, tlist_i;
@ -308,7 +308,7 @@ void X3DImporter::readPolyline2D(XmlNode &node) {
// if "USE" defined then find already defined element. // if "USE" defined then find already defined element.
if (!use.empty()) { if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Polyline2D, ne); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Polyline2D, ne);
} else { } else {
// create and if needed - define new geometry object. // create and if needed - define new geometry object.
ne = new X3DNodeElementGeometry2D(X3DElemType::ENET_Polyline2D, mNodeElementCur); 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" defined then find already defined element.
if (!use.empty()) { if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Polypoint2D, ne); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Polypoint2D, ne);
} else { } else {
// create and if needed - define new geometry object. // create and if needed - define new geometry object.
ne = new X3DNodeElementGeometry2D(X3DElemType::ENET_Polypoint2D, mNodeElementCur); 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" defined then find already defined element.
if (!use.empty()) { if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Rectangle2D, ne); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Rectangle2D, ne);
} else { } else {
// create and if needed - define new geometry object. // create and if needed - define new geometry object.
ne = new X3DNodeElementGeometry2D(X3DElemType::ENET_Rectangle2D, mNodeElementCur); 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" defined then find already defined element.
if (!use.empty()) { if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TriangleSet2D, ne); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TriangleSet2D, ne);
} else { } else {
if (vertices.size() % 3) throw DeadlyImportError("TriangleSet2D. Not enough points for defining triangle."); if (vertices.size() % 3) throw DeadlyImportError("TriangleSet2D. Not enough points for defining triangle.");

View File

@ -46,16 +46,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER #ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
#include "X3DGeoHelper.h"
#include "X3DImporter.hpp" #include "X3DImporter.hpp"
#include "X3DImporter_Macro.hpp" #include "X3DImporter_Macro.hpp"
#include "X3DXmlHelper.h" #include "X3DXmlHelper.h"
#include "X3DGeoHelper.h"
// Header files, Assimp. // Header files, Assimp.
#include <assimp/StandardShapes.h> #include <assimp/StandardShapes.h>
namespace Assimp namespace Assimp {
{
// <Box // <Box
// DEF="" ID // DEF="" ID
@ -70,34 +69,31 @@ void X3DImporter::readBox(XmlNode &node) {
std::string def, use; std::string def, use;
bool solid = true; bool solid = true;
aiVector3D size(2, 2, 2); aiVector3D size(2, 2, 2);
X3DNodeElementBase* ne( nullptr ); X3DNodeElementBase *ne(nullptr);
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use); MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
X3DXmlHelper::getVector3DAttribute(node, "size", size); X3DXmlHelper::getVector3DAttribute(node, "size", size);
XmlParser::getBoolAttribute(node, "solid", solid); XmlParser::getBoolAttribute(node, "solid", solid);
// if "USE" defined then find already defined element. // if "USE" defined then find already defined element.
if(!use.empty()) if (!use.empty()) {
{ ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Box, ne);
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Box, ne); } else {
}
else
{
// create and if needed - define new geometry object. // create and if needed - define new geometry object.
ne = new X3DNodeElementGeometry3D(X3DElemType::ENET_Box, mNodeElementCur); ne = new X3DNodeElementGeometry3D(X3DElemType::ENET_Box, mNodeElementCur);
if(!def.empty()) ne->ID = def; 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)->Solid = solid;
((X3DNodeElementGeometry3D *)ne)->NumIndices = 4; ((X3DNodeElementGeometry3D *)ne)->NumIndices = 4;
// check for X3DMetadataObject childs. // check for X3DMetadataObject childs.
if(!isNodeEmpty(node)) if (!isNodeEmpty(node))
childrenReadMetadata(node, ne, "Box"); childrenReadMetadata(node, ne, "Box");
else else
mNodeElementCur->Children.push_back(ne);// add made object as child to current element 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 NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
}// if(!use.empty()) else } // if(!use.empty()) else
} }
// <Cone // <Cone
@ -116,7 +112,7 @@ void X3DImporter::readCone(XmlNode &node) {
float height = 2; float height = 2;
bool side = true; bool side = true;
bool solid = true; bool solid = true;
X3DNodeElementBase* ne( nullptr ); X3DNodeElementBase *ne(nullptr);
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use); MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
XmlParser::getBoolAttribute(node, "solid", solid); XmlParser::getBoolAttribute(node, "solid", solid);
@ -126,46 +122,41 @@ void X3DImporter::readCone(XmlNode &node) {
XmlParser::getFloatAttribute(node, "bottomRadius", bottomRadius); XmlParser::getFloatAttribute(node, "bottomRadius", bottomRadius);
// if "USE" defined then find already defined element. // if "USE" defined then find already defined element.
if(!use.empty()) if (!use.empty()) {
{ ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Cone, ne);
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Cone, ne); } else {
} const unsigned int tess = 30; ///TODO: IME tessellation factor through ai_property
else
{
const unsigned int tess = 30;///TODO: IME tessellation factor through ai_property
std::vector<aiVector3D> tvec;// temp array for vertices. std::vector<aiVector3D> tvec; // temp array for vertices.
// create and if needed - define new geometry object. // create and if needed - define new geometry object.
ne = new X3DNodeElementGeometry3D(X3DElemType::ENET_Cone, mNodeElementCur); ne = new X3DNodeElementGeometry3D(X3DElemType::ENET_Cone, mNodeElementCur);
if(!def.empty()) ne->ID = def; if (!def.empty()) ne->ID = def;
// make cone or parts according to flags. // make cone or parts according to flags.
if(side) if (side) {
{
StandardShapes::MakeCone(height, 0, bottomRadius, tess, tvec, !bottom); StandardShapes::MakeCone(height, 0, bottomRadius, tess, tvec, !bottom);
} } else if (bottom) {
else if(bottom)
{
StandardShapes::MakeCircle(bottomRadius, tess, tvec); StandardShapes::MakeCircle(bottomRadius, tess, tvec);
height = -(height / 2); height = -(height / 2);
for(std::vector<aiVector3D>::iterator it = tvec.begin(); it != tvec.end(); ++it) it->y = height;// y - because circle made in oXZ. for (std::vector<aiVector3D>::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<aiVector3D>::iterator it = tvec.begin(); it != tvec.end(); ++it) for (std::vector<aiVector3D>::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; ((X3DNodeElementGeometry3D *)ne)->NumIndices = 3;
// check for X3DMetadataObject childs. // check for X3DMetadataObject childs.
if(!isNodeEmpty(node)) if (!isNodeEmpty(node))
childrenReadMetadata(node, ne, "Cone"); childrenReadMetadata(node, ne, "Cone");
else else
mNodeElementCur->Children.push_back(ne);// add made object as child to current element 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 NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
}// if(!use.empty()) else } // if(!use.empty()) else
} }
// <Cylinder // <Cylinder
@ -186,7 +177,7 @@ void X3DImporter::readCylinder(XmlNode &node) {
bool side = true; bool side = true;
bool solid = true; bool solid = true;
bool top = true; bool top = true;
X3DNodeElementBase* ne( nullptr ); X3DNodeElementBase *ne(nullptr);
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use); MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
XmlParser::getFloatAttribute(node, "radius", radius); XmlParser::getFloatAttribute(node, "radius", radius);
@ -197,59 +188,53 @@ void X3DImporter::readCylinder(XmlNode &node) {
XmlParser::getFloatAttribute(node, "height", height); XmlParser::getFloatAttribute(node, "height", height);
// if "USE" defined then find already defined element. // if "USE" defined then find already defined element.
if(!use.empty()) if (!use.empty()) {
{ ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Cylinder, ne);
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Cylinder, ne); } else {
} const unsigned int tess = 30; ///TODO: IME tessellation factor through ai_property
else
{
const unsigned int tess = 30;///TODO: IME tessellation factor through ai_property
std::vector<aiVector3D> tside;// temp array for vertices of side. std::vector<aiVector3D> tside; // temp array for vertices of side.
std::vector<aiVector3D> tcir;// temp array for vertices of circle. std::vector<aiVector3D> tcir; // temp array for vertices of circle.
// create and if needed - define new geometry object. // create and if needed - define new geometry object.
ne = new X3DNodeElementGeometry3D(X3DElemType::ENET_Cylinder, mNodeElementCur); ne = new X3DNodeElementGeometry3D(X3DElemType::ENET_Cylinder, mNodeElementCur);
if(!def.empty()) ne->ID = def; if (!def.empty()) ne->ID = def;
// make cilynder or parts according to flags. // make cilynder or parts according to flags.
if(side) StandardShapes::MakeCone(height, radius, radius, tess, tside, true); 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. 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); if (top || bottom) StandardShapes::MakeCircle(radius, tess, tcir);
// copy data from temp arrays // copy data from temp arrays
std::list<aiVector3D> &vlist = ((X3DNodeElementGeometry3D *)ne)->Vertices; // just short alias. std::list<aiVector3D> &vlist = ((X3DNodeElementGeometry3D *)ne)->Vertices; // just short alias.
for(std::vector<aiVector3D>::iterator it = tside.begin(); it != tside.end(); ++it) vlist.push_back(*it); for (std::vector<aiVector3D>::iterator it = tside.begin(); it != tside.end(); ++it)
vlist.push_back(*it);
if(top) if (top) {
{ for (std::vector<aiVector3D>::iterator it = tcir.begin(); it != tcir.end(); ++it) {
for(std::vector<aiVector3D>::iterator it = tcir.begin(); it != tcir.end(); ++it) (*it).y = height; // y - because circle made in oXZ.
{
(*it).y = height;// y - because circle made in oXZ.
vlist.push_back(*it); vlist.push_back(*it);
} }
}// if(top) } // if(top)
if(bottom) if (bottom) {
{ for (std::vector<aiVector3D>::iterator it = tcir.begin(); it != tcir.end(); ++it) {
for(std::vector<aiVector3D>::iterator it = tcir.begin(); it != tcir.end(); ++it) (*it).y = -height; // y - because circle made in oXZ.
{
(*it).y = -height;// y - because circle made in oXZ.
vlist.push_back(*it); vlist.push_back(*it);
} }
}// if(top) } // if(top)
((X3DNodeElementGeometry3D *)ne)->Solid = solid; ((X3DNodeElementGeometry3D *)ne)->Solid = solid;
((X3DNodeElementGeometry3D *)ne)->NumIndices = 3; ((X3DNodeElementGeometry3D *)ne)->NumIndices = 3;
// check for X3DMetadataObject childs. // check for X3DMetadataObject childs.
if(!isNodeEmpty(node)) if (!isNodeEmpty(node))
childrenReadMetadata(node, ne, "Cylinder"); childrenReadMetadata(node, ne, "Cylinder");
else else
mNodeElementCur->Children.push_back(ne);// add made object as child to current element 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 NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
}// if(!use.empty()) else } // if(!use.empty()) else
} }
// <ElevationGrid // <ElevationGrid
@ -286,7 +271,7 @@ void X3DImporter::readElevationGrid(XmlNode &node) {
float xSpacing = 1; float xSpacing = 1;
int32_t zDimension = 0; int32_t zDimension = 0;
float zSpacing = 1; float zSpacing = 1;
X3DNodeElementBase* ne( nullptr ); X3DNodeElementBase *ne(nullptr);
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use); MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
XmlParser::getBoolAttribute(node, "solid", solid); XmlParser::getBoolAttribute(node, "solid", solid);
@ -301,28 +286,25 @@ void X3DImporter::readElevationGrid(XmlNode &node) {
XmlParser::getFloatAttribute(node, "zSpacing", zSpacing); XmlParser::getFloatAttribute(node, "zSpacing", zSpacing);
// if "USE" defined then find already defined element. // if "USE" defined then find already defined element.
if(!use.empty()) if (!use.empty()) {
{ ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_ElevationGrid, ne);
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_ElevationGrid, ne); } else {
} if ((xSpacing == 0.0f) || (zSpacing == 0.0f)) throw DeadlyImportError("Spacing in <ElevationGrid> must be grater than zero.");
else if ((xDimension <= 0) || (zDimension <= 0)) throw DeadlyImportError("Dimension in <ElevationGrid> must be grater than zero.");
{
if((xSpacing == 0.0f) || (zSpacing == 0.0f)) throw DeadlyImportError("Spacing in <ElevationGrid> must be grater than zero.");
if((xDimension <= 0) || (zDimension <= 0)) throw DeadlyImportError("Dimension in <ElevationGrid> must be grater than zero.");
if ((size_t)(xDimension * zDimension) != height.size()) DeadlyImportError("Heights count must be equal to \"xDimension * zDimension\" in <ElevationGrid>"); if ((size_t)(xDimension * zDimension) != height.size()) DeadlyImportError("Heights count must be equal to \"xDimension * zDimension\" in <ElevationGrid>");
// create and if needed - define new geometry object. // create and if needed - define new geometry object.
ne = new X3DNodeElementElevationGrid(X3DElemType::ENET_ElevationGrid, mNodeElementCur); ne = new X3DNodeElementElevationGrid(X3DElemType::ENET_ElevationGrid, mNodeElementCur);
if(!def.empty()) ne->ID = def; 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 { // create grid vertices list
std::vector<float>::const_iterator he_it = height.begin(); std::vector<float>::const_iterator he_it = height.begin();
for(int32_t zi = 0; zi < zDimension; zi++)// rows for (int32_t zi = 0; zi < zDimension; zi++) // rows
{ {
for(int32_t xi = 0; xi < xDimension; xi++)// columns for (int32_t xi = 0; xi < xDimension; xi++) // columns
{ {
aiVector3D tvec(xSpacing * xi, *he_it, zSpacing * zi); aiVector3D tvec(xSpacing * xi, *he_it, zSpacing * zi);
@ -330,31 +312,28 @@ void X3DImporter::readElevationGrid(XmlNode &node) {
++he_it; ++he_it;
} }
} }
}// END: create grid vertices list } // END: create grid vertices list
// //
// create faces list. In "coordIdx" format // create faces list. In "coordIdx" format
// //
// check if we have quads // check if we have quads
if((xDimension < 2) || (zDimension < 2))// only one element in dimension is set, create line set. 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. ((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++) for (size_t i = 0, i_e = (grid_alias.Vertices.size() - 1); i < i_e; i++) {
{
grid_alias.CoordIdx.push_back(static_cast<int32_t>(i)); grid_alias.CoordIdx.push_back(static_cast<int32_t>(i));
grid_alias.CoordIdx.push_back(static_cast<int32_t>(i + 1)); grid_alias.CoordIdx.push_back(static_cast<int32_t>(i + 1));
grid_alias.CoordIdx.push_back(-1); grid_alias.CoordIdx.push_back(-1);
} }
} } else // two or more elements in every dimension is set. create quad set.
else// two or more elements in every dimension is set. create quad set.
{ {
((X3DNodeElementElevationGrid *)ne)->NumIndices = 4; ((X3DNodeElementElevationGrid *)ne)->NumIndices = 4;
for(int32_t fzi = 0, fzi_e = (zDimension - 1); fzi < fzi_e; fzi++)// rows 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 for (int32_t fxi = 0, fxi_e = (xDimension - 1); fxi < fxi_e; fxi++) // columns
{ {
// points direction in face. // points direction in face.
if(ccw) if (ccw) {
{
// CCW: // CCW:
// 3 2 // 3 2
// 0 1 // 0 1
@ -362,9 +341,7 @@ void X3DImporter::readElevationGrid(XmlNode &node) {
grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + (fxi + 1)); 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 + 1));
grid_alias.CoordIdx.push_back(fzi * xDimension + fxi); grid_alias.CoordIdx.push_back(fzi * xDimension + fxi);
} } else {
else
{
// CW: // CW:
// 0 1 // 0 1
// 3 2 // 3 2
@ -372,178 +349,159 @@ void X3DImporter::readElevationGrid(XmlNode &node) {
grid_alias.CoordIdx.push_back(fzi * xDimension + (fxi + 1)); 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 + 1));
grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + fxi); grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + fxi);
}// if(ccw) else } // if(ccw) else
grid_alias.CoordIdx.push_back(-1); grid_alias.CoordIdx.push_back(-1);
}// for(int32_t fxi = 0, fxi_e = (xDimension - 1); fxi < fxi_e; fxi++) } // 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++) } // for(int32_t fzi = 0, fzi_e = (zDimension - 1); fzi < fzi_e; fzi++)
}// if((xDimension < 2) || (zDimension < 2)) else } // if((xDimension < 2) || (zDimension < 2)) else
grid_alias.ColorPerVertex = colorPerVertex; grid_alias.ColorPerVertex = colorPerVertex;
grid_alias.NormalPerVertex = normalPerVertex; grid_alias.NormalPerVertex = normalPerVertex;
grid_alias.CreaseAngle = creaseAngle; grid_alias.CreaseAngle = creaseAngle;
grid_alias.Solid = solid; grid_alias.Solid = solid;
// check for child nodes // check for child nodes
if(!isNodeEmpty(node)) if (!isNodeEmpty(node)) {
{
ParseHelper_Node_Enter(ne); ParseHelper_Node_Enter(ne);
for (auto currentChildNode : node.children()) { for (auto currentChildNode : node.children()) {
const std::string &currentChildName = currentChildNode.name(); const std::string &currentChildName = currentChildNode.name();
// check for X3DComposedGeometryNodes // check for X3DComposedGeometryNodes
if (currentChildName == "Color") readColor(currentChildNode); if (currentChildName == "Color")
else if (currentChildName == "ColorRGBA") readColorRGBA(currentChildNode); readColor(currentChildNode);
else if (currentChildName == "Normal") readNormal(currentChildNode); else if (currentChildName == "ColorRGBA")
else if (currentChildName == "TextureCoordinate") readTextureCoordinate(currentChildNode); readColorRGBA(currentChildNode);
else if (currentChildName == "Normal")
readNormal(currentChildNode);
else if (currentChildName == "TextureCoordinate")
readTextureCoordinate(currentChildNode);
// check for X3DMetadataObject // check for X3DMetadataObject
else if (!checkForMetadataNode(currentChildNode)) skipUnsupportedNode("ElevationGrid", currentChildNode); else if (!checkForMetadataNode(currentChildNode))
skipUnsupportedNode("ElevationGrid", currentChildNode);
} }
ParseHelper_Node_Exit(); ParseHelper_Node_Exit();
}// if(!mReader->isEmptyElement()) } // if(!mReader->isEmptyElement())
else else {
{ mNodeElementCur->Children.push_back(ne); // add made object as child to current element
mNodeElementCur->Children.push_back(ne);// add made object as child to current element } // if(!mReader->isEmptyElement()) else
}// if(!mReader->isEmptyElement()) else
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
}// if(!use.empty()) else } // if(!use.empty()) else
} }
template<typename TVector> template <typename TVector>
static void GeometryHelper_Extrusion_CurveIsClosed(std::vector<TVector>& pCurve, const bool pDropTail, const bool pRemoveLastPoint, bool& pCurveIsClosed) static void GeometryHelper_Extrusion_CurveIsClosed(std::vector<TVector> &pCurve, const bool pDropTail, const bool pRemoveLastPoint, bool &pCurveIsClosed) {
{
size_t cur_sz = pCurve.size(); size_t cur_sz = pCurve.size();
pCurveIsClosed = false; pCurveIsClosed = false;
// for curve with less than four points checking is have no sense, // for curve with less than four points checking is have no sense,
if(cur_sz < 4) return; if (cur_sz < 4) return;
for(size_t s = 3, s_e = cur_sz; s < s_e; s++) for (size_t s = 3, s_e = cur_sz; s < s_e; s++) {
{
// search for first point of duplicated part. // search for first point of duplicated part.
if(pCurve[0] == pCurve[s]) if (pCurve[0] == pCurve[s]) {
{
bool found = true; bool found = true;
// check if tail(indexed by b2) is duplicate of head(indexed by b1). // 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++) 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.
if(pCurve[b1] != pCurve[b2])
{// points not match: clear flag and break loop.
found = false; found = false;
break; break;
} }
}// for(size_t b1 = 1, b2 = (s + 1); b2 < cur_sz; b1++, b2++) } // 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 duplicate tail is found then drop or not it depending on flags.
if(found) if (found) {
{
pCurveIsClosed = true; pCurveIsClosed = true;
if(pDropTail) if (pDropTail) {
{ if (!pRemoveLastPoint) s++; // prepare value for iterator's arithmetics.
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; break;
}// if(found) } // if(found)
}// if(pCurve[0] == pCurve[s]) } // if(pCurve[0] == pCurve[s])
}// for(size_t s = 3, s_e = (cur_sz - 1); s < s_e; 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<aiVector3D>& pSpine, const bool pSpine_Closed) static aiVector3D GeometryHelper_Extrusion_GetNextY(const size_t pSpine_PointIdx, const std::vector<aiVector3D> &pSpine, const bool pSpine_Closed) {
{
const size_t spine_idx_last = pSpine.size() - 1; const size_t spine_idx_last = pSpine.size() - 1;
aiVector3D tvec; aiVector3D tvec;
if((pSpine_PointIdx == 0) || (pSpine_PointIdx == spine_idx_last))// at first special cases if ((pSpine_PointIdx == 0) || (pSpine_PointIdx == spine_idx_last)) // at first special cases
{ {
if(pSpine_Closed) 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.
{// 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]) // 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. // in tail are removed.
// So, last point in pSpine is a spine[n - 2] // So, last point in pSpine is a spine[n - 2]
tvec = pSpine[1] - pSpine[spine_idx_last]; 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]
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]; 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
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]. // the spine[0].
tvec = pSpine[spine_idx_last] - pSpine[spine_idx_last - 1]; tvec = pSpine[spine_idx_last] - pSpine[spine_idx_last - 1];
} }
}// if((pSpine_PointIdx == 0) || (pSpine_PointIdx == spine_idx_last)) } // if((pSpine_PointIdx == 0) || (pSpine_PointIdx == spine_idx_last))
else 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]).
{// 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]; 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)) else
return tvec.Normalize(); return tvec.Normalize();
} }
static aiVector3D GeometryHelper_Extrusion_GetNextZ(const size_t pSpine_PointIdx, const std::vector<aiVector3D>& pSpine, const bool pSpine_Closed, static aiVector3D GeometryHelper_Extrusion_GetNextZ(const size_t pSpine_PointIdx, const std::vector<aiVector3D> &pSpine, const bool pSpine_Closed,
const aiVector3D pVecZ_Prev) const aiVector3D pVecZ_Prev) {
{
const aiVector3D zero_vec(0); const aiVector3D zero_vec(0);
const size_t spine_idx_last = pSpine.size() - 1; const size_t spine_idx_last = pSpine.size() - 1;
aiVector3D tvec; aiVector3D tvec;
// at first special cases // at first special cases
if(pSpine.size() < 3)// spine have not enough points for vector calculations. if (pSpine.size() < 3) // spine have not enough points for vector calculations.
{ {
tvec.Set(0, 0, 1); tvec.Set(0, 0, 1);
} } else if (pSpine_PointIdx == 0) // special case: first point
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. 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]); 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.
else // for not closed curve first and next point(s[0] and s[1]) has the same vector Z.
{ {
bool found = false; 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) // 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." // then the Z-axis for the first spine point with a defined Z-axis is used."
// Walk through spine and find Z. // Walk through spine and find Z.
for(size_t next_point = 2; (next_point <= spine_idx_last) && !found; next_point++) for (size_t next_point = 2; (next_point <= spine_idx_last) && !found; next_point++) {
{
// (pSpine[2] - pSpine[1]) ^ (pSpine[0] - pSpine[1]) // (pSpine[2] - pSpine[1]) ^ (pSpine[0] - pSpine[1])
tvec = (pSpine[next_point] - pSpine[next_point - 1]) ^ (pSpine[next_point - 2] - pSpine[next_point - 1]); tvec = (pSpine[next_point] - pSpine[next_point - 1]) ^ (pSpine[next_point - 2] - pSpine[next_point - 1]);
found = !tvec.Equal(zero_vec); found = !tvec.Equal(zero_vec);
} }
// if entire spine are collinear then use OZ axis. // if entire spine are collinear then use OZ axis.
if(!found) tvec.Set(0, 0, 1); if (!found) tvec.Set(0, 0, 1);
}// if(pSpine_Closed) else } // if(pSpine_Closed) else
}// else if(pSpine_PointIdx == 0) } // else if(pSpine_PointIdx == 0)
else if(pSpine_PointIdx == spine_idx_last)// special case: last point else if (pSpine_PointIdx == spine_idx_last) // special case: last point
{ {
if(pSpine_Closed) 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].
{// 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]); 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 taken spine vectors are collinear then use previous vector Z.
if(tvec.Equal(zero_vec)) tvec = pVecZ_Prev; if (tvec.Equal(zero_vec)) tvec = pVecZ_Prev;
} } else { // vector Z for last point of not closed curve is previous vector Z.
else
{// vector Z for last point of not closed curve is previous vector Z.
tvec = pVecZ_Prev; tvec = pVecZ_Prev;
} }
} } else // regular point
else// regular point
{ {
tvec = (pSpine[pSpine_PointIdx + 1] - pSpine[pSpine_PointIdx]) ^ (pSpine[pSpine_PointIdx - 1] - pSpine[pSpine_PointIdx]); 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 taken spine vectors are collinear then use previous vector Z.
if(tvec.Equal(zero_vec)) tvec = pVecZ_Prev; 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 // 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). // is flipped (multiplied by -1).
if((tvec * pVecZ_Prev) < 0) tvec = -tvec; if ((tvec * pVecZ_Prev) < 0) tvec = -tvec;
return tvec.Normalize(); return tvec.Normalize();
} }
@ -574,7 +532,7 @@ void X3DImporter::readExtrusion(XmlNode &node) {
std::vector<aiVector2D> scale; std::vector<aiVector2D> scale;
bool solid = true; bool solid = true;
std::vector<aiVector3D> spine; std::vector<aiVector3D> spine;
X3DNodeElementBase* ne( nullptr ); X3DNodeElementBase *ne(nullptr);
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use); MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
XmlParser::getBoolAttribute(node, "beginCap", beginCap); XmlParser::getBoolAttribute(node, "beginCap", beginCap);
@ -589,74 +547,65 @@ void X3DImporter::readExtrusion(XmlNode &node) {
X3DXmlHelper::getVector3DArrayAttribute(node, "spine", spine); X3DXmlHelper::getVector3DArrayAttribute(node, "spine", spine);
// if "USE" defined then find already defined element. // if "USE" defined then find already defined element.
if(!use.empty()) if (!use.empty()) {
{ ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Extrusion, ne);
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Extrusion, ne); } else {
}
else
{
// //
// check if default values must be assigned // check if default values must be assigned
// //
if(spine.size() == 0) if (spine.size() == 0) {
{
spine.resize(2); spine.resize(2);
spine[0].Set(0, 0, 0), spine[1].Set(0, 1, 0); spine[0].Set(0, 0, 0), spine[1].Set(0, 1, 0);
} } else if (spine.size() == 1) {
else if(spine.size() == 1)
{
throw DeadlyImportError("ParseNode_Geometry3D_Extrusion. Spine must have at least two points."); throw DeadlyImportError("ParseNode_Geometry3D_Extrusion. Spine must have at least two points.");
} }
if(crossSection.size() == 0) if (crossSection.size() == 0) {
{
crossSection.resize(5); 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); 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 { // orientation
size_t ori_size = orientation.size() / 4; size_t ori_size = orientation.size() / 4;
if(ori_size < spine.size()) if (ori_size < spine.size()) {
{ float add_ori[4]; // values that will be added
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. 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]; 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
else// else - use default values
{ {
add_ori[0] = 0, add_ori[1] = 0, add_ori[2] = 1, add_ori[3] = 0; add_ori[0] = 0, add_ori[1] = 0, add_ori[2] = 1, add_ori[3] = 0;
} }
orientation.reserve(spine.size() * 4); orientation.reserve(spine.size() * 4);
for(size_t i = 0, i_e = (spine.size() - ori_size); i < i_e; i++) 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.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 <Extrusion> must has multiple four quantity of numbers."); if (orientation.size() % 4) throw DeadlyImportError("Attribute \"orientation\" in <Extrusion> must has multiple four quantity of numbers.");
}// END: orientation } // END: orientation
{// scale { // scale
if(scale.size() < spine.size()) if (scale.size() < spine.size()) {
{
aiVector2D add_sc; aiVector2D add_sc;
if(scale.size() == 1)// if "scale" has one element then use it value for all spine points. if (scale.size() == 1) // if "scale" has one element then use it value for all spine points.
add_sc = scale[0]; add_sc = scale[0];
else// else - use default values else // else - use default values
add_sc.Set(1, 1); add_sc.Set(1, 1);
scale.reserve(spine.size()); scale.reserve(spine.size());
for(size_t i = 0, i_e = (spine.size() - scale.size()); i < i_e; i++) scale.push_back(add_sc); for (size_t i = 0, i_e = (spine.size() - scale.size()); i < i_e; i++)
scale.push_back(add_sc);
} }
}// END: scale } // END: scale
// //
// create and if needed - define new geometry object. // create and if needed - define new geometry object.
// //
ne = new X3DNodeElementIndexedSet(X3DElemType::ENET_Extrusion, mNodeElementCur); ne = new X3DNodeElementIndexedSet(X3DElemType::ENET_Extrusion, mNodeElementCur);
if(!def.empty()) ne->ID = def; if (!def.empty()) ne->ID = def;
X3DNodeElementIndexedSet &ext_alias = *((X3DNodeElementIndexedSet *)ne); // create alias for conveience X3DNodeElementIndexedSet &ext_alias = *((X3DNodeElementIndexedSet *)ne); // create alias for conveience
// assign part of input data // assign part of input data
@ -675,28 +624,26 @@ void X3DImporter::readExtrusion(XmlNode &node) {
// needed. While createing CootdIdx is taking in account CCW flag. // needed. While createing CootdIdx is taking in account CCW flag.
// 4. The last step: create Vertices list. // 4. The last step: create Vertices list.
// //
bool spine_closed;// flag: true if spine curve is closed. bool spine_closed; // flag: true if spine curve is closed.
bool cross_closed;// flag: true if cross curve is closed. bool cross_closed; // flag: true if cross curve is closed.
std::vector<aiMatrix3x3> basis_arr;// array of basises. ROW_a - X, ROW_b - Y, ROW_c - Z. std::vector<aiMatrix3x3> basis_arr; // array of basises. ROW_a - X, ROW_b - Y, ROW_c - Z.
std::vector<std::vector<aiVector3D> > pointset_arr;// array of point sets: cross curves. std::vector<std::vector<aiVector3D>> pointset_arr; // array of point sets: cross curves.
// detect closed curves // detect closed curves
GeometryHelper_Extrusion_CurveIsClosed(crossSection, true, true, cross_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. 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 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) if (spine_closed) {
{
beginCap |= endCap; beginCap |= endCap;
endCap = false; endCap = false;
} }
{// 1. Calculate array of basises. { // 1. Calculate array of basises.
aiMatrix4x4 rotmat; aiMatrix4x4 rotmat;
aiVector3D vecX(0), vecY(0), vecZ(0); aiVector3D vecX(0), vecY(0), vecZ(0);
basis_arr.resize(spine.size()); basis_arr.resize(spine.size());
for(size_t i = 0, i_e = spine.size(); i < i_e; i++) for (size_t i = 0, i_e = spine.size(); i < i_e; i++) {
{
aiVector3D tvec; aiVector3D tvec;
// get axises of basis. // get axises of basis.
@ -708,22 +655,20 @@ void X3DImporter::readExtrusion(XmlNode &node) {
tvec = vecX, tvec *= rotmat, basis_arr[i].a1 = tvec.x, basis_arr[i].a2 = tvec.y, basis_arr[i].a3 = tvec.z; 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 = 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; 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++) } // for(size_t i = 0, i_e = spine.size(); i < i_e; i++)
}// END: 1. Calculate array of basises } // END: 1. Calculate array of basises
{// 2. Create array of point sets. { // 2. Create array of point sets.
aiMatrix4x4 scmat; aiMatrix4x4 scmat;
std::vector<aiVector3D> tcross(crossSection.size()); std::vector<aiVector3D> tcross(crossSection.size());
pointset_arr.resize(spine.size()); pointset_arr.resize(spine.size());
for(size_t spi = 0, spi_e = spine.size(); spi < spi_e; spi++) for (size_t spi = 0, spi_e = spine.size(); spi < spi_e; spi++) {
{
aiVector3D tc23vec; aiVector3D tc23vec;
tc23vec.Set(scale[spi].x, 0, scale[spi].y); tc23vec.Set(scale[spi].x, 0, scale[spi].y);
aiMatrix4x4::Scaling(tc23vec, scmat); aiMatrix4x4::Scaling(tc23vec, scmat);
for(size_t cri = 0, cri_e = crossSection.size(); cri < cri_e; cri++) for (size_t cri = 0, cri_e = crossSection.size(); cri < cri_e; cri++) {
{
aiVector3D tvecX, tvecY, tvecZ; aiVector3D tvecX, tvecY, tvecZ;
tc23vec.Set(crossSection[cri].x, 0, crossSection[cri].y); tc23vec.Set(crossSection[cri].x, 0, crossSection[cri].y);
@ -737,53 +682,50 @@ void X3DImporter::readExtrusion(XmlNode &node) {
tvecZ.Set(basis_arr[spi].c1, basis_arr[spi].c2, basis_arr[spi].c3), tvecZ *= tcross[cri].z; 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. // apply new coordinates and translate it to spine point.
tcross[cri] = tvecX + tvecY + tvecZ + spine[spi]; tcross[cri] = tvecX + tvecY + tvecZ + spine[spi];
}// for(size_t cri = 0, cri_e = crossSection.size(); cri < cri_e; i++) } // for(size_t cri = 0, cri_e = crossSection.size(); cri < cri_e; i++)
pointset_arr[spi] = tcross;// store transferred point set pointset_arr[spi] = tcross; // store transferred point set
}// for(size_t spi = 0, spi_e = spine.size(); spi < spi_e; i++) } // for(size_t spi = 0, spi_e = spine.size(); spi < spi_e; i++)
}// END: 2. Create array of point sets. } // END: 2. Create array of point sets.
{// 3. Create CoordIdx. { // 3. Create CoordIdx.
// add caps if needed // add caps if needed
if(beginCap) if (beginCap) {
{
// add cap as polygon. vertices of cap are places at begin, so just add numbers from zero. // 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<int32_t>(i)); for (size_t i = 0, i_e = crossSection.size(); i < i_e; i++)
ext_alias.CoordIndex.push_back(static_cast<int32_t>(i));
// add delimiter // add delimiter
ext_alias.CoordIndex.push_back(-1); ext_alias.CoordIndex.push_back(-1);
}// if(beginCap) } // if(beginCap)
if(endCap) if (endCap) {
{
// add cap as polygon. vertices of cap are places at end, as for beginCap use just sequence of numbers but with offset. // 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(); 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<int32_t>(i)); for (size_t i = beg, i_e = (beg + crossSection.size()); i < i_e; i++)
ext_alias.CoordIndex.push_back(static_cast<int32_t>(i));
// add delimiter // add delimiter
ext_alias.CoordIndex.push_back(-1); ext_alias.CoordIndex.push_back(-1);
}// if(beginCap) } // if(beginCap)
// add quads // add quads
for(size_t spi = 0, spi_e = (spine.size() - 1); spi <= spi_e; spi++) 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_sz = crossSection.size();
const size_t cr_last = crossSection.size() - 1; 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) if (spi != spi_e)
right_col = spi + 1; 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. 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; right_col = 0;
else else
break;// if spine curve is not closed then break the loop, because spi is out of range for that type of spine. 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++) for (size_t cri = 0; cri < cr_sz; cri++) {
{ if (cri != cr_last) {
if(cri != cr_last)
{
MACRO_FACE_ADD_QUAD(ccw, ext_alias.CoordIndex, MACRO_FACE_ADD_QUAD(ccw, ext_alias.CoordIndex,
static_cast<int32_t>(spi * cr_sz + cri), static_cast<int32_t>(spi * cr_sz + cri),
static_cast<int32_t>(right_col * cr_sz + cri), static_cast<int32_t>(right_col * cr_sz + cri),
@ -791,8 +733,7 @@ void X3DImporter::readExtrusion(XmlNode &node) {
static_cast<int32_t>(spi * cr_sz + cri + 1)); static_cast<int32_t>(spi * cr_sz + cri + 1));
// add delimiter // add delimiter
ext_alias.CoordIndex.push_back(-1); 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.
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, MACRO_FACE_ADD_QUAD(ccw, ext_alias.CoordIndex,
static_cast<int32_t>(spi * cr_sz + cri), static_cast<int32_t>(spi * cr_sz + cri),
@ -802,30 +743,28 @@ void X3DImporter::readExtrusion(XmlNode &node) {
// add delimiter // add delimiter
ext_alias.CoordIndex.push_back(-1); ext_alias.CoordIndex.push_back(-1);
} }
}// for(size_t cri = 0; cri < cr_sz; cri++) } // for(size_t cri = 0; cri < cr_sz; cri++)
}// for(size_t spi = 0, spi_e = (spine.size() - 2); spi < spi_e; spi++) } // for(size_t spi = 0, spi_e = (spine.size() - 2); spi < spi_e; spi++)
}// END: 3. Create CoordIdx. } // END: 3. Create CoordIdx.
{// 4. Create vertices list. { // 4. Create vertices list.
// just copy all vertices // just copy all vertices
for(size_t spi = 0, spi_e = spine.size(); spi < spi_e; spi++) 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++) {
for(size_t cri = 0, cri_e = crossSection.size(); cri < cri_e; cri++)
{
ext_alias.Vertices.emplace_back(pointset_arr[spi][cri]); ext_alias.Vertices.emplace_back(pointset_arr[spi][cri]);
} }
} }
}// END: 4. Create vertices list. } // END: 4. Create vertices list.
//PrintVectorSet("Ext. CoordIdx", ext_alias.CoordIndex); //PrintVectorSet("Ext. CoordIdx", ext_alias.CoordIndex);
//PrintVectorSet("Ext. Vertices", ext_alias.Vertices); //PrintVectorSet("Ext. Vertices", ext_alias.Vertices);
// check for child nodes // check for child nodes
if(!isNodeEmpty(node)) if (!isNodeEmpty(node))
childrenReadMetadata(node, ne, "Extrusion"); childrenReadMetadata(node, ne, "Extrusion");
else else
mNodeElementCur->Children.push_back(ne);// add made object as child to current element 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 NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
}// if(!use.empty()) else } // if(!use.empty()) else
} }
// <IndexedFaceSet // <IndexedFaceSet
@ -860,7 +799,7 @@ void X3DImporter::readIndexedFaceSet(XmlNode &node) {
bool normalPerVertex = true; bool normalPerVertex = true;
bool solid = true; bool solid = true;
std::vector<int32_t> texCoordIndex; std::vector<int32_t> texCoordIndex;
X3DNodeElementBase* ne( nullptr ); X3DNodeElementBase *ne(nullptr);
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use); MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
XmlParser::getBoolAttribute(node, "ccw", ccw); XmlParser::getBoolAttribute(node, "ccw", ccw);
@ -875,18 +814,15 @@ void X3DImporter::readIndexedFaceSet(XmlNode &node) {
X3DXmlHelper::getInt32ArrayAttribute(node, "texCoordIndex", texCoordIndex); X3DXmlHelper::getInt32ArrayAttribute(node, "texCoordIndex", texCoordIndex);
// if "USE" defined then find already defined element. // if "USE" defined then find already defined element.
if(!use.empty()) if (!use.empty()) {
{ ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedFaceSet, ne);
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedFaceSet, ne); } else {
}
else
{
// check data // check data
if(coordIndex.size() == 0) throw DeadlyImportError("IndexedFaceSet must contain not empty \"coordIndex\" attribute."); if (coordIndex.size() == 0) throw DeadlyImportError("IndexedFaceSet must contain not empty \"coordIndex\" attribute.");
// create and if needed - define new geometry object. // create and if needed - define new geometry object.
ne = new X3DNodeElementIndexedSet(X3DElemType::ENET_IndexedFaceSet, mNodeElementCur); ne = new X3DNodeElementIndexedSet(X3DElemType::ENET_IndexedFaceSet, mNodeElementCur);
if(!def.empty()) ne->ID = def; if (!def.empty()) ne->ID = def;
X3DNodeElementIndexedSet &ne_alias = *((X3DNodeElementIndexedSet *)ne); X3DNodeElementIndexedSet &ne_alias = *((X3DNodeElementIndexedSet *)ne);
@ -901,29 +837,33 @@ void X3DImporter::readIndexedFaceSet(XmlNode &node) {
ne_alias.Solid = solid; ne_alias.Solid = solid;
ne_alias.TexCoordIndex = texCoordIndex; ne_alias.TexCoordIndex = texCoordIndex;
// check for child nodes // check for child nodes
if(!isNodeEmpty(node)) if (!isNodeEmpty(node)) {
{
ParseHelper_Node_Enter(ne); ParseHelper_Node_Enter(ne);
for (auto currentChildNode : node.children()) { for (auto currentChildNode : node.children()) {
const std::string &currentChildName = currentChildNode.name(); const std::string &currentChildName = currentChildNode.name();
// check for X3DComposedGeometryNodes // check for X3DComposedGeometryNodes
if (currentChildName == "Color") readColor(currentChildNode); if (currentChildName == "Color")
else if (currentChildName == "ColorRGBA") readColorRGBA(currentChildNode); readColor(currentChildNode);
else if (currentChildName == "Coordinate") readCoordinate(currentChildNode); else if (currentChildName == "ColorRGBA")
else if (currentChildName == "Normal") readNormal(currentChildNode); readColorRGBA(currentChildNode);
else if (currentChildName == "TextureCoordinate") readTextureCoordinate(currentChildNode); else if (currentChildName == "Coordinate")
readCoordinate(currentChildNode);
else if (currentChildName == "Normal")
readNormal(currentChildNode);
else if (currentChildName == "TextureCoordinate")
readTextureCoordinate(currentChildNode);
// check for X3DMetadataObject // check for X3DMetadataObject
else if (!checkForMetadataNode(currentChildNode)) skipUnsupportedNode("IndexedFaceSet", currentChildNode); else if (!checkForMetadataNode(currentChildNode))
skipUnsupportedNode("IndexedFaceSet", currentChildNode);
} }
ParseHelper_Node_Exit(); ParseHelper_Node_Exit();
}// if(!isNodeEmpty(node)) } // if(!isNodeEmpty(node))
else else {
{ mNodeElementCur->Children.push_back(ne); // add made object as child to current element
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 NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
}// if(!use.empty()) else } // if(!use.empty()) else
} }
// <Sphere // <Sphere
@ -936,46 +876,42 @@ void X3DImporter::readSphere(XmlNode &node) {
std::string use, def; std::string use, def;
ai_real radius = 1; ai_real radius = 1;
bool solid = true; bool solid = true;
X3DNodeElementBase* ne( nullptr ); X3DNodeElementBase *ne(nullptr);
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use); MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
XmlParser::getFloatAttribute(node, "radius", radius); XmlParser::getFloatAttribute(node, "radius", radius);
XmlParser::getBoolAttribute(node, "solid", solid); XmlParser::getBoolAttribute(node, "solid", solid);
// if "USE" defined then find already defined element. // if "USE" defined then find already defined element.
if(!use.empty()) if (!use.empty()) {
{ ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Sphere, ne);
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Sphere, ne); } else {
} const unsigned int tess = 3; ///TODO: IME tessellation factor through ai_property
else
{
const unsigned int tess = 3;///TODO: IME tessellation factor through ai_property
std::vector<aiVector3D> tlist; std::vector<aiVector3D> tlist;
// create and if needed - define new geometry object. // create and if needed - define new geometry object.
ne = new X3DNodeElementGeometry3D(X3DElemType::ENET_Sphere, mNodeElementCur); ne = new X3DNodeElementGeometry3D(X3DElemType::ENET_Sphere, mNodeElementCur);
if(!def.empty()) ne->ID = def; if (!def.empty()) ne->ID = def;
StandardShapes::MakeSphere(tess, tlist); StandardShapes::MakeSphere(tess, tlist);
// copy data from temp array and apply scale // copy data from temp array and apply scale
for(std::vector<aiVector3D>::iterator it = tlist.begin(); it != tlist.end(); ++it) for (std::vector<aiVector3D>::iterator it = tlist.begin(); it != tlist.end(); ++it) {
{
((X3DNodeElementGeometry3D *)ne)->Vertices.push_back(*it * radius); ((X3DNodeElementGeometry3D *)ne)->Vertices.push_back(*it * radius);
} }
((X3DNodeElementGeometry3D *)ne)->Solid = solid; ((X3DNodeElementGeometry3D *)ne)->Solid = solid;
((X3DNodeElementGeometry3D *)ne)->NumIndices = 3; ((X3DNodeElementGeometry3D *)ne)->NumIndices = 3;
// check for X3DMetadataObject childs. // check for X3DMetadataObject childs.
if(!isNodeEmpty(node)) if (!isNodeEmpty(node))
childrenReadMetadata(node, ne, "Sphere"); childrenReadMetadata(node, ne, "Sphere");
else else
mNodeElementCur->Children.push_back(ne);// add made object as child to current element 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 NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
}// if(!use.empty()) else } // if(!use.empty()) else
} }
}// namespace Assimp } // namespace Assimp
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER #endif // !ASSIMP_BUILD_NO_X3D_IMPORTER

View File

@ -72,9 +72,8 @@ void X3DImporter::startReadGroup(XmlNode &node) {
// if "USE" defined then find already defined element. // if "USE" defined then find already defined element.
if (!use.empty()) { if (!use.empty()) {
X3DNodeElementBase *ne; X3DNodeElementBase *ne = nullptr;
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Group, ne);
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Group, ne);
} else { } else {
ParseHelper_Group_Begin(); // create new grouping element and go deeper if node has children. 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. // 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" defined then find already defined element.
if (!use.empty()) { 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 { } else {
ParseHelper_Group_Begin(true); // create new grouping element and go deeper if node has children. 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. // 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" defined then find already defined element.
if (!use.empty()) { 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 { } else {
ParseHelper_Group_Begin(); // create new grouping element and go deeper if node has children. 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. // 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()) { if (!use.empty()) {
X3DNodeElementBase *ne(nullptr); X3DNodeElementBase *ne(nullptr);
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Group, ne); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Group, ne);
} else { } else {
ParseHelper_Group_Begin(); // create new grouping element and go deeper if node has children. 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. // at this place new group mode created and made current, so we can name it.

View File

@ -83,7 +83,7 @@ void X3DImporter::readDirectionalLight(XmlNode &node) {
// if "USE" defined then find already defined element. // if "USE" defined then find already defined element.
if (!use.empty()) { if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_DirectionalLight, ne); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_DirectionalLight, ne);
} else { } else {
if (on) { if (on) {
// create and if needed - define new geometry object. // 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" defined then find already defined element.
if (!use.empty()) { if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_PointLight, ne); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_PointLight, ne);
} else { } else {
if (on) { if (on) {
// create and if needed - define new geometry object. // 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" defined then find already defined element.
if (!use.empty()) { if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_SpotLight, ne); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_SpotLight, ne);
} else { } else {
if (on) { if (on) {
// create and if needed - define new geometry object. // create and if needed - define new geometry object.

View File

@ -47,20 +47,36 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef X3DIMPORTER_MACRO_HPP_INCLUDED #ifndef X3DIMPORTER_MACRO_HPP_INCLUDED
#define X3DIMPORTER_MACRO_HPP_INCLUDED #define X3DIMPORTER_MACRO_HPP_INCLUDED
/// \def MACRO_USE_CHECKANDAPPLY(pDEF, pUSE, pNE) #include <assimp/XmlParser.h>
#include "X3DImporter.hpp"
#include <string>
namespace Assimp {
/// Used for regular checking while attribute "USE" is defined. /// Used for regular checking while attribute "USE" is defined.
/// \param [in] pNode - pugi xml node to read. /// \param [in] pNode - pugi xml node to read.
/// \param [in] pDEF - string holding "DEF" value. /// \param [in] pDEF - string holding "DEF" value.
/// \param [in] pUSE - string holding "USE" value. /// \param [in] pUSE - string holding "USE" value.
/// \param [in] pType - type of element to find. /// \param [in] pType - type of element to find.
/// \param [out] pNE - pointer to found node element. /// \param [out] pNE - pointer to found node element.
#define MACRO_USE_CHECKANDAPPLY(pNode, pDEF, pUSE, pType, pNE) \ inline X3DNodeElementBase *X3DImporter::MACRO_USE_CHECKANDAPPLY(XmlNode &node, std::string pDEF, std::string pUSE, X3DElemType pType, X3DNodeElementBase *pNE) {
do { \ if (nullptr == mNodeElementCur) {
checkNodeMustBeEmpty(pNode); \ printf("here\n");
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 */ \ //do {
} while (false) 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 /// \def MACRO_ATTRREAD_CHECKUSEDEF_RET
/// Compact variant for checking "USE" and "DEF". /// Compact variant for checking "USE" and "DEF".

View File

@ -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) \ #define MACRO_METADATA_FINDCREATE(pNode, pDEF_Var, pUSE_Var, pReference, pValue, pNE, pMetaClass, pMetaName, pType) \
/* if "USE" defined then find already defined element. */ \ /* if "USE" defined then find already defined element. */ \
if (!pUSE_Var.empty()) { \ 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 { \ } else { \
pNE = new pMetaClass(mNodeElementCur); \ pNE = new pMetaClass(mNodeElementCur); \
if (!pDEF_Var.empty()) pNE->ID = pDEF_Var; \ 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" defined then find already defined element.
if (!use.empty()) { if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_MetaSet, ne); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_MetaSet, ne);
} else { } else {
ne = new X3DNodeElementMetaSet(mNodeElementCur); ne = new X3DNodeElementMetaSet(mNodeElementCur);
if (!def.empty()) ne->ID = def; if (!def.empty()) ne->ID = def;
((X3DNodeElementMetaSet *)ne)->Reference = reference; ((X3DNodeElementMetaSet *)ne)->Reference = reference;
// also metadata node can contain childs // also metadata node can contain children
if (!isNodeEmpty(node)) if (!isNodeEmpty(node))
childrenReadMetadata(node, ne, "MetadataSet"); childrenReadMetadata(node, ne, "MetadataSet");
else else

View File

@ -78,10 +78,9 @@ void X3DImporter::readInline(XmlNode &node) {
X3DXmlHelper::getStringListAttribute(node, "url", url); X3DXmlHelper::getStringListAttribute(node, "url", url);
// if "USE" defined then find already defined element. // if "USE" defined then find already defined element.
X3DNodeElementBase *ne = nullptr;
if (!use.empty()) { if (!use.empty()) {
X3DNodeElementBase *ne; ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Group, ne);
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Group, ne);
} else { } else {
ParseHelper_Group_Begin(true); // create new grouping element and go deeper if node has children. 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. // at this place new group mode created and made current, so we can name it.

View File

@ -67,7 +67,7 @@ void X3DImporter::readColor(XmlNode &node) {
// if "USE" defined then find already defined element. // if "USE" defined then find already defined element.
if (!use.empty()) { if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Color, ne); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Color, ne);
} else { } else {
// create and if needed - define new geometry object. // create and if needed - define new geometry object.
ne = new X3DNodeElementColor(mNodeElementCur); ne = new X3DNodeElementColor(mNodeElementCur);
@ -99,7 +99,7 @@ void X3DImporter::readColorRGBA(XmlNode &node) {
// if "USE" defined then find already defined element. // if "USE" defined then find already defined element.
if (!use.empty()) { if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_ColorRGBA, ne); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_ColorRGBA, ne);
} else { } else {
// create and if needed - define new geometry object. // create and if needed - define new geometry object.
ne = new X3DNodeElementColorRGBA(mNodeElementCur); ne = new X3DNodeElementColorRGBA(mNodeElementCur);
@ -131,7 +131,7 @@ void X3DImporter::readCoordinate(XmlNode &node) {
// if "USE" defined then find already defined element. // if "USE" defined then find already defined element.
if (!use.empty()) { if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Coordinate, ne); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Coordinate, ne);
} else { } else {
// create and if needed - define new geometry object. // create and if needed - define new geometry object.
ne = new X3DNodeElementCoordinate(mNodeElementCur); ne = new X3DNodeElementCoordinate(mNodeElementCur);
@ -174,7 +174,7 @@ void X3DImporter::readIndexedLineSet(XmlNode &node) {
// if "USE" defined then find already defined element. // if "USE" defined then find already defined element.
if (!use.empty()) { if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedLineSet, ne); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedLineSet, ne);
} else { } else {
// check data // check data
if ((coordIndex.size() < 2) || ((coordIndex.back() == (-1)) && (coordIndex.size() < 3))) 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" defined then find already defined element.
if (!use.empty()) { if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedTriangleFanSet, ne); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedTriangleFanSet, ne);
} else { } else {
// check data // check data
if (index.size() == 0) throw DeadlyImportError("IndexedTriangleFanSet must contain not empty \"index\" attribute."); 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" defined then find already defined element.
if (!use.empty()) { if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedTriangleSet, ne); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedTriangleSet, ne);
} else { } else {
// check data // check data
if (index.size() == 0) throw DeadlyImportError("IndexedTriangleSet must contain not empty \"index\" attribute."); 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" defined then find already defined element.
if (!use.empty()) { if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedTriangleStripSet, ne); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedTriangleStripSet, ne);
} else { } else {
// check data // 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. // create and if needed - define new geometry object.
ne = new X3DNodeElementIndexedSet(X3DElemType::ENET_IndexedTriangleStripSet, mNodeElementCur); 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" defined then find already defined element.
if (!use.empty()) { if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_LineSet, ne); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_LineSet, ne);
} else { } else {
// check data // 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. // create and if needed - define new geometry object.
ne = new X3DNodeElementSet(X3DElemType::ENET_LineSet, mNodeElementCur); 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" defined then find already defined element.
if (!use.empty()) { if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_PointSet, ne); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_PointSet, ne);
} else { } else {
// create and if needed - define new geometry object. // create and if needed - define new geometry object.
ne = new X3DNodeElementIndexedSet(X3DElemType::ENET_PointSet, mNodeElementCur); 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" defined then find already defined element.
if (!use.empty()) { if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TriangleFanSet, ne); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TriangleFanSet, ne);
} else { } else {
// check data // 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. // create and if needed - define new geometry object.
ne = new X3DNodeElementSet(X3DElemType::ENET_TriangleFanSet, mNodeElementCur); 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" defined then find already defined element.
if (!use.empty()) { if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TriangleSet, ne); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TriangleSet, ne);
} else { } else {
// create and if needed - define new geometry object. // create and if needed - define new geometry object.
ne = new X3DNodeElementIndexedSet(X3DElemType::ENET_TriangleSet, mNodeElementCur); 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" defined then find already defined element.
if (!use.empty()) { if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TriangleStripSet, ne); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TriangleStripSet, ne);
} else { } else {
// check data // check data
if (stripCount.size() == 0) throw DeadlyImportError("TriangleStripSet must contain not empty \"stripCount\" attribute."); 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) { void X3DImporter::readNormal(XmlNode &node) {
std::string use, def; std::string use, def;
std::list<aiVector3D> vector; std::list<aiVector3D> vector;
X3DNodeElementBase *ne; X3DNodeElementBase *ne=nullptr;
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use); MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
X3DXmlHelper::getVector3DListAttribute(node, "vector", vector); X3DXmlHelper::getVector3DListAttribute(node, "vector", vector);
// if "USE" defined then find already defined element. // if "USE" defined then find already defined element.
if (!use.empty()) { if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Normal, ne); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Normal, ne);
} else { } else {
// create and if needed - define new geometry object. // create and if needed - define new geometry object.
ne = new X3DNodeElementNormal(mNodeElementCur); ne = new X3DNodeElementNormal(mNodeElementCur);

View File

@ -60,7 +60,7 @@ void X3DImporter::readShape(XmlNode &node) {
// if "USE" defined then find already defined element. // if "USE" defined then find already defined element.
if (!use.empty()) { if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Shape, ne); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Shape, ne);
} else { } else {
// create and if needed - define new geometry object. // create and if needed - define new geometry object.
ne = new X3DNodeElementShape(mNodeElementCur); ne = new X3DNodeElementShape(mNodeElementCur);
@ -74,31 +74,55 @@ void X3DImporter::readShape(XmlNode &node) {
// check for appearance node // check for appearance node
if (currentChildName == "Appearance") readAppearance(currentChildNode); if (currentChildName == "Appearance") readAppearance(currentChildNode);
// check for X3DGeometryNodes // check for X3DGeometryNodes
else if (currentChildName == "Arc2D") readArc2D(currentChildNode); else if (currentChildName == "Arc2D")
else if (currentChildName == "ArcClose2D") readArcClose2D(currentChildNode); readArc2D(currentChildNode);
else if (currentChildName == "Circle2D") readCircle2D(currentChildNode); else if (currentChildName == "ArcClose2D")
else if (currentChildName == "Disk2D") readDisk2D(currentChildNode); readArcClose2D(currentChildNode);
else if (currentChildName == "Polyline2D") readPolyline2D(currentChildNode); else if (currentChildName == "Circle2D")
else if (currentChildName == "Polypoint2D") readPolypoint2D(currentChildNode); readCircle2D(currentChildNode);
else if (currentChildName == "Rectangle2D") readRectangle2D(currentChildNode); else if (currentChildName == "Disk2D")
else if (currentChildName == "TriangleSet2D") readTriangleSet2D(currentChildNode); readDisk2D(currentChildNode);
else if (currentChildName == "Box") readBox(currentChildNode); else if (currentChildName == "Polyline2D")
else if (currentChildName == "Cone") readCone(currentChildNode); readPolyline2D(currentChildNode);
else if (currentChildName == "Cylinder") readCylinder(currentChildNode); else if (currentChildName == "Polypoint2D")
else if (currentChildName == "ElevationGrid") readElevationGrid(currentChildNode); readPolypoint2D(currentChildNode);
else if (currentChildName == "Extrusion") readExtrusion(currentChildNode); else if (currentChildName == "Rectangle2D")
else if (currentChildName == "IndexedFaceSet") readIndexedFaceSet(currentChildNode); readRectangle2D(currentChildNode);
else if (currentChildName == "Sphere") readSphere(currentChildNode); else if (currentChildName == "TriangleSet2D")
else if (currentChildName == "IndexedLineSet") readIndexedLineSet(currentChildNode); readTriangleSet2D(currentChildNode);
else if (currentChildName == "LineSet") readLineSet(currentChildNode); else if (currentChildName == "Box")
else if (currentChildName == "PointSet") readPointSet(currentChildNode); readBox(currentChildNode);
else if (currentChildName == "IndexedTriangleFanSet") readIndexedTriangleFanSet(currentChildNode); else if (currentChildName == "Cone")
else if (currentChildName == "IndexedTriangleSet") readIndexedTriangleSet(currentChildNode); readCone(currentChildNode);
else if (currentChildName == "IndexedTriangleStripSet") readIndexedTriangleStripSet(currentChildNode); else if (currentChildName == "Cylinder")
else if (currentChildName == "TriangleFanSet") readTriangleFanSet(currentChildNode); readCylinder(currentChildNode);
else if (currentChildName == "TriangleSet") readTriangleSet(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 // check for X3DMetadataObject
else if (!checkForMetadataNode(currentChildNode)) skipUnsupportedNode("Shape", currentChildNode); else if (!checkForMetadataNode(currentChildNode))
skipUnsupportedNode("Shape", currentChildNode);
} }
ParseHelper_Node_Exit(); ParseHelper_Node_Exit();
@ -123,42 +147,41 @@ void X3DImporter::readShape(XmlNode &node) {
// </Appearance> // </Appearance>
void X3DImporter::readAppearance(XmlNode &node) { void X3DImporter::readAppearance(XmlNode &node) {
std::string use, def; std::string use, def;
X3DNodeElementBase* ne( nullptr ); X3DNodeElementBase *ne(nullptr);
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use); MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
// if "USE" defined then find already defined element. // if "USE" defined then find already defined element.
if (!use.empty()) if (!use.empty()) {
{ ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Appearance, ne);
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Appearance, ne); } else {
}
else
{
// create and if needed - define new geometry object. // create and if needed - define new geometry object.
ne = new X3DNodeElementAppearance(mNodeElementCur); ne = new X3DNodeElementAppearance(mNodeElementCur);
if(!def.empty()) ne->ID = def; if (!def.empty()) ne->ID = def;
// check for child nodes // check for child nodes
if(!isNodeEmpty(node)) if (!isNodeEmpty(node)) {
{
ParseHelper_Node_Enter(ne); ParseHelper_Node_Enter(ne);
for (auto currentChildNode : node.children()) { for (auto currentChildNode : node.children()) {
const std::string &currentChildName = currentChildNode.name(); const std::string &currentChildName = currentChildNode.name();
if (currentChildName == "Material") readMaterial(currentChildNode); if (currentChildName == "Material")
else if (currentChildName == "ImageTexture") readImageTexture(currentChildNode); readMaterial(currentChildNode);
else if (currentChildName == "TextureTransform") readTextureTransform(currentChildNode); else if (currentChildName == "ImageTexture")
readImageTexture(currentChildNode);
else if (currentChildName == "TextureTransform")
readTextureTransform(currentChildNode);
// check for X3DMetadataObject // check for X3DMetadataObject
else if (!checkForMetadataNode(currentChildNode)) skipUnsupportedNode("Appearance", currentChildNode); else if (!checkForMetadataNode(currentChildNode))
skipUnsupportedNode("Appearance", currentChildNode);
} }
ParseHelper_Node_Exit(); ParseHelper_Node_Exit();
}// if(!isNodeEmpty(node)) } // if(!isNodeEmpty(node))
else else {
{ mNodeElementCur->Children.push_back(ne); // add made object as child to current element
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 NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
}// if(!use.empty()) else } // if(!use.empty()) else
} }
// <Material // <Material
@ -179,7 +202,7 @@ void X3DImporter::readMaterial(XmlNode &node) {
aiColor3D diffuseColor(0.8f, 0.8f, 0.8f); aiColor3D diffuseColor(0.8f, 0.8f, 0.8f);
aiColor3D emissiveColor(0, 0, 0); aiColor3D emissiveColor(0, 0, 0);
aiColor3D specularColor(0, 0, 0); aiColor3D specularColor(0, 0, 0);
X3DNodeElementBase* ne( nullptr ); X3DNodeElementBase *ne(nullptr);
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use); MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
XmlParser::getFloatAttribute(node, "ambientIntensity", ambientIntensity); XmlParser::getFloatAttribute(node, "ambientIntensity", ambientIntensity);
@ -190,15 +213,12 @@ void X3DImporter::readMaterial(XmlNode &node) {
X3DXmlHelper::getColor3DAttribute(node, "specularColor", specularColor); X3DXmlHelper::getColor3DAttribute(node, "specularColor", specularColor);
// if "USE" defined then find already defined element. // if "USE" defined then find already defined element.
if(!use.empty()) if (!use.empty()) {
{ ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Material, ne);
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Material, ne); } else {
}
else
{
// create and if needed - define new geometry object. // create and if needed - define new geometry object.
ne = new X3DNodeElementMaterial(mNodeElementCur); ne = new X3DNodeElementMaterial(mNodeElementCur);
if(!def.empty()) ne->ID = def; if (!def.empty()) ne->ID = def;
((X3DNodeElementMaterial *)ne)->AmbientIntensity = ambientIntensity; ((X3DNodeElementMaterial *)ne)->AmbientIntensity = ambientIntensity;
((X3DNodeElementMaterial *)ne)->Shininess = shininess; ((X3DNodeElementMaterial *)ne)->Shininess = shininess;
@ -207,15 +227,15 @@ void X3DImporter::readMaterial(XmlNode &node) {
((X3DNodeElementMaterial *)ne)->EmissiveColor = emissiveColor; ((X3DNodeElementMaterial *)ne)->EmissiveColor = emissiveColor;
((X3DNodeElementMaterial *)ne)->SpecularColor = specularColor; ((X3DNodeElementMaterial *)ne)->SpecularColor = specularColor;
// check for child nodes // check for child nodes
if(!isNodeEmpty(node)) if (!isNodeEmpty(node))
childrenReadMetadata(node, ne, "Material"); childrenReadMetadata(node, ne, "Material");
else else
mNodeElementCur->Children.push_back(ne); // add made object as child to current element 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 NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
}// if(!use.empty()) else } // if(!use.empty()) else
} }
}// namespace Assimp } // namespace Assimp
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER #endif // !ASSIMP_BUILD_NO_X3D_IMPORTER

View File

@ -74,7 +74,7 @@ void X3DImporter::readImageTexture(XmlNode &node) {
// if "USE" defined then find already defined element. // if "USE" defined then find already defined element.
if (!use.empty()) { if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_ImageTexture, ne); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_ImageTexture, ne);
} else { } else {
// create and if needed - define new geometry object. // create and if needed - define new geometry object.
ne = new X3DNodeElementImageTexture(mNodeElementCur); ne = new X3DNodeElementImageTexture(mNodeElementCur);
@ -113,7 +113,7 @@ void X3DImporter::readTextureCoordinate(XmlNode &node) {
// if "USE" defined then find already defined element. // if "USE" defined then find already defined element.
if (!use.empty()) { if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TextureCoordinate, ne); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TextureCoordinate, ne);
} else { } else {
// create and if needed - define new geometry object. // create and if needed - define new geometry object.
ne = new X3DNodeElementTextureCoordinate(mNodeElementCur); ne = new X3DNodeElementTextureCoordinate(mNodeElementCur);
@ -154,7 +154,7 @@ void X3DImporter::readTextureTransform(XmlNode &node) {
// if "USE" defined then find already defined element. // if "USE" defined then find already defined element.
if (!use.empty()) { if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TextureTransform, ne); ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TextureTransform, ne);
} else { } else {
// create and if needed - define new geometry object. // create and if needed - define new geometry object.
ne = new X3DNodeElementTextureTransform(mNodeElementCur); ne = new X3DNodeElementTextureTransform(mNodeElementCur);

View File

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN" "https://www.web3d.org/specifications/x3d-3.0.dtd">
<X3D profile='Immersive' version='3.0' xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance' xsd:noNamespaceSchemaLocation='https://www.web3d.org/specifications/x3d-3.0.xsd'>
<!-- X3D&#8482; is a trademark of the Web3D Consortium Incorporated, standing for Extensible 3D Graphics (X3D). -->
<head>
<meta content='HelloX3dTrademark.x3d' name='title'/>
<meta content='Don Brutzman' name='creator'/>
<meta content='6 June 2001' name='created'/>
<meta content='20 October 2019' name='modified'/>
<meta content='Simple example showing spinning globe and X3D&amp;#8482; trademark text. X3D (tm) is a trademark of the Web3D Consortium Inc. X3D stands for Extensible 3D Graphics (X3D), an encoding of VRML using XML. X3D has been defined since 1998. Trademark registration pending. VRML is the Virtual Reality Modeling Language (VRML), International Standard ISO/IEC 14772-1:1997. XML is the Extensible Markup Language (XML), a Recommendation of the World Wide Web Consortium (W3C).' name='description'/>
<meta content='HelloX3dTrademark.png' name='Image'/>
<meta content='https://www.web3d.org' name='reference'/>
<meta content='https://www.web3d.org/x3d' name='reference'/>
<meta content='https://www.web3d.org/Specifications/VRML97' name='reference'/>
<meta content='http://www.w3.org/XML' name='reference'/>
<meta content='https://www.web3d.org/x3d/content/examples/Basic/development/HelloX3dTrademark.x3d' name='identifier'/>
<meta content='X3D-Edit 3.3, https://savage.nps.edu/X3D-Edit' name='generator'/>
<meta content='../license.html' name='license'/>
</head>
<Scene>
<WorldInfo info='"an introductory scene"' title='Hello X3D&amp;#8482; Trademark (tm)'/>
<Viewpoint description='Hello, world' orientation='0 1 0 3.14159' position='0 0 -8'/>
<Transform DEF='EarthCoordinateSystem'>
<Group DEF='MiniWorld'>
<Shape>
<Appearance>
<ImageTexture url='"earth-topo.png" "earth-topo.gif" "earth-topo-small.gif" "https://www.web3d.org/x3d/content/examples/Basic/development/earth-topo.png" "https://www.web3d.org/x3d/content/examples/Basic/development/earth-topo.gif" "https://www.web3d.org/x3d/content/examples/Basic/development/earth-topo-small.gif"'/>
</Appearance>
<Sphere DEF='GlobeNotToScale'/>
</Shape>
</Group>
<Transform DEF='SimpleGeoStationarySatellite' scale='0.1 0.3 0.1' translation='0 0 4'>
<Shape>
<Appearance>
<Material diffuseColor='0.9 0.1 0.1'/>
</Appearance>
<Text string='"Hello" "X3D Trademark (tm)"'>
<FontStyle justify='"MIDDLE" "MIDDLE"' size='3'/>
</Text>
</Shape>
</Transform>
</Transform>
<TimeSensor DEF='OrbitalTimeInterval' cycleInterval='12.0' loop='true'/>
<OrientationInterpolator DEF='SpinThoseThings' key='0.00 0.25 0.50 0.75 1.00' keyValue='0 1 0 0 0 1 0 1.57079 0 1 0 3.14159 0 1 0 4.7123889 0 1 0 6.2831852'/>
<ROUTE fromField='fraction_changed' fromNode='OrbitalTimeInterval' toField='set_fraction' toNode='SpinThoseThings'/>
<ROUTE fromField='value_changed' fromNode='SpinThoseThings' toField='rotation' toNode='EarthCoordinateSystem'/>
</Scene>
</X3D>

Binary file not shown.

View File

@ -49,7 +49,7 @@ using namespace Assimp;
class utX3DImportExport : public AbstractImportExportBase { class utX3DImportExport : public AbstractImportExportBase {
public: public:
virtual bool importerTest() { bool importerTest() override {
Assimp::Importer importer; Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/X3D/ComputerKeyboard.x3d", aiProcess_ValidateDataStructure); const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/X3D/ComputerKeyboard.x3d", aiProcess_ValidateDataStructure);
return nullptr != scene; return nullptr != scene;