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

View File

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

View File

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

View File

@ -46,16 +46,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
#include "X3DGeoHelper.h"
#include "X3DImporter.hpp"
#include "X3DImporter_Macro.hpp"
#include "X3DXmlHelper.h"
#include "X3DGeoHelper.h"
// Header files, Assimp.
#include <assimp/StandardShapes.h>
namespace Assimp
{
namespace Assimp {
// <Box
// DEF="" ID
@ -77,12 +76,9 @@ void X3DImporter::readBox(XmlNode &node) {
XmlParser::getBoolAttribute(node, "solid", solid);
// if "USE" defined then find already defined element.
if(!use.empty())
{
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Box, ne);
}
else
{
if (!use.empty()) {
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Box, ne);
} else {
// create and if needed - define new geometry object.
ne = new X3DNodeElementGeometry3D(X3DElemType::ENET_Box, mNodeElementCur);
if (!def.empty()) ne->ID = def;
@ -126,12 +122,9 @@ void X3DImporter::readCone(XmlNode &node) {
XmlParser::getFloatAttribute(node, "bottomRadius", bottomRadius);
// if "USE" defined then find already defined element.
if(!use.empty())
{
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Cone, ne);
}
else
{
if (!use.empty()) {
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Cone, ne);
} else {
const unsigned int tess = 30; ///TODO: IME tessellation factor through ai_property
std::vector<aiVector3D> tvec; // temp array for vertices.
@ -141,15 +134,13 @@ void X3DImporter::readCone(XmlNode &node) {
if (!def.empty()) ne->ID = def;
// make cone or parts according to flags.
if(side)
{
if (side) {
StandardShapes::MakeCone(height, 0, bottomRadius, tess, tvec, !bottom);
}
else if(bottom)
{
} else if (bottom) {
StandardShapes::MakeCircle(bottomRadius, tess, tvec);
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
@ -197,12 +188,9 @@ void X3DImporter::readCylinder(XmlNode &node) {
XmlParser::getFloatAttribute(node, "height", height);
// if "USE" defined then find already defined element.
if(!use.empty())
{
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Cylinder, ne);
}
else
{
if (!use.empty()) {
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Cylinder, ne);
} else {
const unsigned int tess = 30; ///TODO: IME tessellation factor through ai_property
std::vector<aiVector3D> tside; // temp array for vertices of side.
@ -220,21 +208,18 @@ void X3DImporter::readCylinder(XmlNode &node) {
// copy data from temp arrays
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)
{
for(std::vector<aiVector3D>::iterator it = tcir.begin(); it != tcir.end(); ++it)
{
if (top) {
for (std::vector<aiVector3D>::iterator it = tcir.begin(); it != tcir.end(); ++it) {
(*it).y = height; // y - because circle made in oXZ.
vlist.push_back(*it);
}
} // if(top)
if(bottom)
{
for(std::vector<aiVector3D>::iterator it = tcir.begin(); it != tcir.end(); ++it)
{
if (bottom) {
for (std::vector<aiVector3D>::iterator it = tcir.begin(); it != tcir.end(); ++it) {
(*it).y = -height; // y - because circle made in oXZ.
vlist.push_back(*it);
}
@ -301,12 +286,9 @@ void X3DImporter::readElevationGrid(XmlNode &node) {
XmlParser::getFloatAttribute(node, "zSpacing", zSpacing);
// if "USE" defined then find already defined element.
if(!use.empty())
{
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_ElevationGrid, ne);
}
else
{
if (!use.empty()) {
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_ElevationGrid, ne);
} else {
if ((xSpacing == 0.0f) || (zSpacing == 0.0f)) throw DeadlyImportError("Spacing in <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>");
@ -338,14 +320,12 @@ void X3DImporter::readElevationGrid(XmlNode &node) {
if ((xDimension < 2) || (zDimension < 2)) // only one element in dimension is set, create line set.
{
((X3DNodeElementElevationGrid *)ne)->NumIndices = 2; // will be holded as line set.
for(size_t i = 0, i_e = (grid_alias.Vertices.size() - 1); i < i_e; i++)
{
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 + 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;
for (int32_t fzi = 0, fzi_e = (zDimension - 1); fzi < fzi_e; fzi++) // rows
@ -353,8 +333,7 @@ void X3DImporter::readElevationGrid(XmlNode &node) {
for (int32_t fxi = 0, fxi_e = (xDimension - 1); fxi < fxi_e; fxi++) // columns
{
// points direction in face.
if(ccw)
{
if (ccw) {
// CCW:
// 3 2
// 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 * xDimension + (fxi + 1));
grid_alias.CoordIdx.push_back(fzi * xDimension + fxi);
}
else
{
} else {
// CW:
// 0 1
// 3 2
@ -384,23 +361,26 @@ void X3DImporter::readElevationGrid(XmlNode &node) {
grid_alias.CreaseAngle = creaseAngle;
grid_alias.Solid = solid;
// check for child nodes
if(!isNodeEmpty(node))
{
if (!isNodeEmpty(node)) {
ParseHelper_Node_Enter(ne);
for (auto currentChildNode : node.children()) {
const std::string &currentChildName = currentChildNode.name();
// check for X3DComposedGeometryNodes
if (currentChildName == "Color") readColor(currentChildNode);
else if (currentChildName == "ColorRGBA") readColorRGBA(currentChildNode);
else if (currentChildName == "Normal") readNormal(currentChildNode);
else if (currentChildName == "TextureCoordinate") readTextureCoordinate(currentChildNode);
if (currentChildName == "Color")
readColor(currentChildNode);
else if (currentChildName == "ColorRGBA")
readColorRGBA(currentChildNode);
else if (currentChildName == "Normal")
readNormal(currentChildNode);
else if (currentChildName == "TextureCoordinate")
readTextureCoordinate(currentChildNode);
// check for X3DMetadataObject
else if (!checkForMetadataNode(currentChildNode)) skipUnsupportedNode("ElevationGrid", currentChildNode);
else if (!checkForMetadataNode(currentChildNode))
skipUnsupportedNode("ElevationGrid", currentChildNode);
}
ParseHelper_Node_Exit();
} // if(!mReader->isEmptyElement())
else
{
else {
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
} // if(!mReader->isEmptyElement()) else
@ -409,26 +389,21 @@ void X3DImporter::readElevationGrid(XmlNode &node) {
}
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();
pCurveIsClosed = false;
// for curve with less than four points checking is have no sense,
if (cur_sz < 4) return;
for(size_t s = 3, s_e = cur_sz; s < s_e; s++)
{
for (size_t s = 3, s_e = cur_sz; s < s_e; s++) {
// search for first point of duplicated part.
if(pCurve[0] == pCurve[s])
{
if (pCurve[0] == pCurve[s]) {
bool found = true;
// check if tail(indexed by b2) is duplicate of head(indexed by b1).
for(size_t b1 = 1, b2 = (s + 1); b2 < cur_sz; b1++, b2++)
{
if(pCurve[b1] != pCurve[b2])
{// points not match: clear flag and break loop.
for (size_t b1 = 1, b2 = (s + 1); b2 < cur_sz; b1++, b2++) {
if (pCurve[b1] != pCurve[b2]) { // points not match: clear flag and break loop.
found = false;
break;
@ -436,11 +411,9 @@ static void GeometryHelper_Extrusion_CurveIsClosed(std::vector<TVector>& pCurve,
} // for(size_t b1 = 1, b2 = (s + 1); b2 < cur_sz; b1++, b2++)
// if duplicate tail is found then drop or not it depending on flags.
if(found)
{
if (found) {
pCurveIsClosed = true;
if(pDropTail)
{
if (pDropTail) {
if (!pRemoveLastPoint) s++; // prepare value for iterator's arithmetics.
pCurve.erase(pCurve.begin() + s, pCurve.end()); // remove tail
@ -452,32 +425,25 @@ static void GeometryHelper_Extrusion_CurveIsClosed(std::vector<TVector>& pCurve,
} // 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;
aiVector3D tvec;
if ((pSpine_PointIdx == 0) || (pSpine_PointIdx == spine_idx_last)) // at first special cases
{
if(pSpine_Closed)
{// If the spine curve is closed: The SCP for the first and last points is the same and is found using (spine[1] - spine[n - 2]) to compute the Y-axis.
if (pSpine_Closed) { // If the spine curve is closed: The SCP for the first and last points is the same and is found using (spine[1] - spine[n - 2]) to compute the Y-axis.
// As we even for closed spine curve last and first point in pSpine are not the same: duplicates(spine[n - 1] which are equivalent to spine[0])
// in tail are removed.
// So, last point in pSpine is a spine[n - 2]
tvec = pSpine[1] - pSpine[spine_idx_last];
}
else if(pSpine_PointIdx == 0)
{// The Y-axis used for the first point is the vector from spine[0] to spine[1]
} else if (pSpine_PointIdx == 0) { // The Y-axis used for the first point is the vector from spine[0] to spine[1]
tvec = pSpine[1] - pSpine[0];
}
else
{// The Y-axis used for the last point it is the vector from spine[n-2] to spine[n-1]. In our case(see above about dropping tail) spine[n - 1] is
} else { // The Y-axis used for the last point it is the vector from spine[n-2] to spine[n-1]. In our case(see above about dropping tail) spine[n - 1] is
// the spine[0].
tvec = pSpine[spine_idx_last] - pSpine[spine_idx_last - 1];
}
} // if((pSpine_PointIdx == 0) || (pSpine_PointIdx == spine_idx_last))
else
{// For all points other than the first or last: The Y-axis for spine[i] is found by normalizing the vector defined by (spine[i+1] - spine[i-1]).
else { // For all points other than the first or last: The Y-axis for spine[i] is found by normalizing the vector defined by (spine[i+1] - spine[i-1]).
tvec = pSpine[pSpine_PointIdx + 1] - pSpine[pSpine_PointIdx - 1];
} // if((pSpine_PointIdx == 0) || (pSpine_PointIdx == spine_idx_last)) else
@ -485,8 +451,7 @@ static aiVector3D GeometryHelper_Extrusion_GetNextY(const size_t pSpine_PointIdx
}
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 size_t spine_idx_last = pSpine.size() - 1;
@ -496,22 +461,19 @@ static aiVector3D GeometryHelper_Extrusion_GetNextZ(const size_t pSpine_PointIdx
if (pSpine.size() < 3) // spine have not enough points for vector calculations.
{
tvec.Set(0, 0, 1);
}
else if(pSpine_PointIdx == 0)// special case: first point
} else if (pSpine_PointIdx == 0) // special case: first point
{
if (pSpine_Closed) // for calculating use previous point in curve s[n - 2]. In list it's a last point, because point s[n - 1] was removed as duplicate.
{
tvec = (pSpine[1] - pSpine[0]) ^ (pSpine[spine_idx_last] - pSpine[0]);
}
else // for not closed curve first and next point(s[0] and s[1]) has the same vector Z.
} else // for not closed curve first and next point(s[0] and s[1]) has the same vector Z.
{
bool found = false;
// As said: "If the Z-axis of the first point is undefined (because the spine is not closed and the first two spine segments are collinear)
// then the Z-axis for the first spine point with a defined Z-axis is used."
// Walk through spine and find Z.
for(size_t next_point = 2; (next_point <= spine_idx_last) && !found; next_point++)
{
for (size_t next_point = 2; (next_point <= spine_idx_last) && !found; next_point++) {
// (pSpine[2] - pSpine[1]) ^ (pSpine[0] - pSpine[1])
tvec = (pSpine[next_point] - pSpine[next_point - 1]) ^ (pSpine[next_point - 2] - pSpine[next_point - 1]);
found = !tvec.Equal(zero_vec);
@ -523,18 +485,14 @@ static aiVector3D GeometryHelper_Extrusion_GetNextZ(const size_t pSpine_PointIdx
} // else if(pSpine_PointIdx == 0)
else if (pSpine_PointIdx == spine_idx_last) // special case: last point
{
if(pSpine_Closed)
{// do not forget that real last point s[n - 1] is removed as duplicated. And in this case we are calculating vector Z for point s[n - 2].
if (pSpine_Closed) { // do not forget that real last point s[n - 1] is removed as duplicated. And in this case we are calculating vector Z for point s[n - 2].
tvec = (pSpine[0] - pSpine[pSpine_PointIdx]) ^ (pSpine[pSpine_PointIdx - 1] - pSpine[pSpine_PointIdx]);
// if taken spine vectors are collinear then use previous vector Z.
if (tvec.Equal(zero_vec)) tvec = pVecZ_Prev;
}
else
{// vector Z for last point of not closed curve is previous vector Z.
} else { // vector Z for last point of not closed curve is previous vector Z.
tvec = pVecZ_Prev;
}
}
else// regular point
} else // regular point
{
tvec = (pSpine[pSpine_PointIdx + 1] - pSpine[pSpine_PointIdx]) ^ (pSpine[pSpine_PointIdx - 1] - pSpine[pSpine_PointIdx]);
// if taken spine vectors are collinear then use previous vector Z.
@ -589,27 +547,20 @@ void X3DImporter::readExtrusion(XmlNode &node) {
X3DXmlHelper::getVector3DArrayAttribute(node, "spine", spine);
// if "USE" defined then find already defined element.
if(!use.empty())
{
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Extrusion, ne);
}
else
{
if (!use.empty()) {
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Extrusion, ne);
} else {
//
// check if default values must be assigned
//
if(spine.size() == 0)
{
if (spine.size() == 0) {
spine.resize(2);
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.");
}
if(crossSection.size() == 0)
{
if (crossSection.size() == 0) {
crossSection.resize(5);
crossSection[0].Set(1, 1), crossSection[1].Set(1, -1), crossSection[2].Set(-1, -1), crossSection[3].Set(-1, 1), crossSection[4].Set(1, 1);
}
@ -617,15 +568,13 @@ void X3DImporter::readExtrusion(XmlNode &node) {
{ // orientation
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
if (ori_size == 1) // if "orientation" has one element(means one MFRotation with four components) then use it value for all spine points.
{
add_ori[0] = orientation[0], add_ori[1] = orientation[1], add_ori[2] = orientation[2], add_ori[3] = orientation[3];
}
else// else - use default values
} else // else - use default values
{
add_ori[0] = 0, add_ori[1] = 0, add_ori[2] = 1, add_ori[3] = 0;
}
@ -639,8 +588,7 @@ void X3DImporter::readExtrusion(XmlNode &node) {
} // END: orientation
{ // scale
if(scale.size() < spine.size())
{
if (scale.size() < spine.size()) {
aiVector2D add_sc;
if (scale.size() == 1) // if "scale" has one element then use it value for all spine points.
@ -649,7 +597,8 @@ void X3DImporter::readExtrusion(XmlNode &node) {
add_sc.Set(1, 1);
scale.reserve(spine.size());
for(size_t i = 0, i_e = (spine.size() - scale.size()); i < i_e; i++) scale.push_back(add_sc);
for (size_t i = 0, i_e = (spine.size() - scale.size()); i < i_e; i++)
scale.push_back(add_sc);
}
} // END: scale
//
@ -684,8 +633,7 @@ void X3DImporter::readExtrusion(XmlNode &node) {
GeometryHelper_Extrusion_CurveIsClosed(crossSection, true, true, cross_closed); // true - drop tail, true - remove duplicate end.
GeometryHelper_Extrusion_CurveIsClosed(spine, true, true, spine_closed); // true - drop tail, true - remove duplicate end.
// If both cap are requested and spine curve is closed then we can make only one cap. Because second cap will be the same surface.
if(spine_closed)
{
if (spine_closed) {
beginCap |= endCap;
endCap = false;
}
@ -695,8 +643,7 @@ void X3DImporter::readExtrusion(XmlNode &node) {
aiVector3D vecX(0), vecY(0), vecZ(0);
basis_arr.resize(spine.size());
for(size_t i = 0, i_e = spine.size(); i < i_e; i++)
{
for (size_t i = 0, i_e = spine.size(); i < i_e; i++) {
aiVector3D tvec;
// get axises of basis.
@ -716,14 +663,12 @@ void X3DImporter::readExtrusion(XmlNode &node) {
std::vector<aiVector3D> tcross(crossSection.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;
tc23vec.Set(scale[spi].x, 0, scale[spi].y);
aiMatrix4x4::Scaling(tc23vec, scmat);
for(size_t cri = 0, cri_e = crossSection.size(); cri < cri_e; cri++)
{
for (size_t cri = 0, cri_e = crossSection.size(); cri < cri_e; cri++) {
aiVector3D tvecX, tvecY, tvecZ;
tc23vec.Set(crossSection[cri].x, 0, crossSection[cri].y);
@ -745,29 +690,28 @@ void X3DImporter::readExtrusion(XmlNode &node) {
{ // 3. Create CoordIdx.
// 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.
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
ext_alias.CoordIndex.push_back(-1);
} // 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.
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
ext_alias.CoordIndex.push_back(-1);
} // if(beginCap)
// 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_last = crossSection.size() - 1;
@ -780,10 +724,8 @@ void X3DImporter::readExtrusion(XmlNode &node) {
else
break; // if spine curve is not closed then break the loop, because spi is out of range for that type of spine.
for(size_t cri = 0; cri < cr_sz; cri++)
{
if(cri != cr_last)
{
for (size_t cri = 0; cri < cr_sz; cri++) {
if (cri != cr_last) {
MACRO_FACE_ADD_QUAD(ccw, ext_alias.CoordIndex,
static_cast<int32_t>(spi * 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));
// add delimiter
ext_alias.CoordIndex.push_back(-1);
}
else if(cross_closed)// if cross curve is closed then one more quad is needed: between first and last points of curve.
} else if (cross_closed) // if cross curve is closed then one more quad is needed: between first and last points of curve.
{
MACRO_FACE_ADD_QUAD(ccw, ext_alias.CoordIndex,
static_cast<int32_t>(spi * cr_sz + cri),
@ -808,10 +749,8 @@ void X3DImporter::readExtrusion(XmlNode &node) {
{ // 4. Create vertices list.
// just copy all vertices
for(size_t spi = 0, spi_e = spine.size(); spi < spi_e; spi++)
{
for(size_t cri = 0, cri_e = crossSection.size(); cri < cri_e; cri++)
{
for (size_t spi = 0, spi_e = spine.size(); spi < spi_e; spi++) {
for (size_t cri = 0, cri_e = crossSection.size(); cri < cri_e; cri++) {
ext_alias.Vertices.emplace_back(pointset_arr[spi][cri]);
}
}
@ -875,12 +814,9 @@ void X3DImporter::readIndexedFaceSet(XmlNode &node) {
X3DXmlHelper::getInt32ArrayAttribute(node, "texCoordIndex", texCoordIndex);
// if "USE" defined then find already defined element.
if(!use.empty())
{
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedFaceSet, ne);
}
else
{
if (!use.empty()) {
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedFaceSet, ne);
} else {
// check data
if (coordIndex.size() == 0) throw DeadlyImportError("IndexedFaceSet must contain not empty \"coordIndex\" attribute.");
@ -901,24 +837,28 @@ void X3DImporter::readIndexedFaceSet(XmlNode &node) {
ne_alias.Solid = solid;
ne_alias.TexCoordIndex = texCoordIndex;
// check for child nodes
if(!isNodeEmpty(node))
{
if (!isNodeEmpty(node)) {
ParseHelper_Node_Enter(ne);
for (auto currentChildNode : node.children()) {
const std::string &currentChildName = currentChildNode.name();
// check for X3DComposedGeometryNodes
if (currentChildName == "Color") readColor(currentChildNode);
else if (currentChildName == "ColorRGBA") readColorRGBA(currentChildNode);
else if (currentChildName == "Coordinate") readCoordinate(currentChildNode);
else if (currentChildName == "Normal") readNormal(currentChildNode);
else if (currentChildName == "TextureCoordinate") readTextureCoordinate(currentChildNode);
if (currentChildName == "Color")
readColor(currentChildNode);
else if (currentChildName == "ColorRGBA")
readColorRGBA(currentChildNode);
else if (currentChildName == "Coordinate")
readCoordinate(currentChildNode);
else if (currentChildName == "Normal")
readNormal(currentChildNode);
else if (currentChildName == "TextureCoordinate")
readTextureCoordinate(currentChildNode);
// check for X3DMetadataObject
else if (!checkForMetadataNode(currentChildNode)) skipUnsupportedNode("IndexedFaceSet", currentChildNode);
else if (!checkForMetadataNode(currentChildNode))
skipUnsupportedNode("IndexedFaceSet", currentChildNode);
}
ParseHelper_Node_Exit();
} // if(!isNodeEmpty(node))
else
{
else {
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
}
@ -943,12 +883,9 @@ void X3DImporter::readSphere(XmlNode &node) {
XmlParser::getBoolAttribute(node, "solid", solid);
// if "USE" defined then find already defined element.
if(!use.empty())
{
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Sphere, ne);
}
else
{
if (!use.empty()) {
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Sphere, ne);
} else {
const unsigned int tess = 3; ///TODO: IME tessellation factor through ai_property
std::vector<aiVector3D> tlist;
@ -959,8 +896,7 @@ void X3DImporter::readSphere(XmlNode &node) {
StandardShapes::MakeSphere(tess, tlist);
// 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);
}

View File

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

View File

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

View File

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

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) \
/* if "USE" defined then find already defined element. */ \
if (!pUSE_Var.empty()) { \
MACRO_USE_CHECKANDAPPLY(pNode, pDEF_Var, pUSE_Var, pType, pNE); \
ne = MACRO_USE_CHECKANDAPPLY(pNode, pDEF_Var, pUSE_Var, pType, pNE); \
} else { \
pNE = new pMetaClass(mNodeElementCur); \
if (!pDEF_Var.empty()) pNE->ID = pDEF_Var; \
@ -213,13 +213,13 @@ void X3DImporter::readMetadataSet(XmlNode &node) {
// if "USE" defined then find already defined element.
if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_MetaSet, ne);
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_MetaSet, ne);
} else {
ne = new X3DNodeElementMetaSet(mNodeElementCur);
if (!def.empty()) ne->ID = def;
((X3DNodeElementMetaSet *)ne)->Reference = reference;
// also metadata node can contain childs
// also metadata node can contain children
if (!isNodeEmpty(node))
childrenReadMetadata(node, ne, "MetadataSet");
else

View File

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

View File

@ -67,7 +67,7 @@ void X3DImporter::readColor(XmlNode &node) {
// if "USE" defined then find already defined element.
if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Color, ne);
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Color, ne);
} else {
// create and if needed - define new geometry object.
ne = new X3DNodeElementColor(mNodeElementCur);
@ -99,7 +99,7 @@ void X3DImporter::readColorRGBA(XmlNode &node) {
// if "USE" defined then find already defined element.
if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_ColorRGBA, ne);
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_ColorRGBA, ne);
} else {
// create and if needed - define new geometry object.
ne = new X3DNodeElementColorRGBA(mNodeElementCur);
@ -131,7 +131,7 @@ void X3DImporter::readCoordinate(XmlNode &node) {
// if "USE" defined then find already defined element.
if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Coordinate, ne);
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Coordinate, ne);
} else {
// create and if needed - define new geometry object.
ne = new X3DNodeElementCoordinate(mNodeElementCur);
@ -174,7 +174,7 @@ void X3DImporter::readIndexedLineSet(XmlNode &node) {
// if "USE" defined then find already defined element.
if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedLineSet, ne);
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedLineSet, ne);
} else {
// check data
if ((coordIndex.size() < 2) || ((coordIndex.back() == (-1)) && (coordIndex.size() < 3)))
@ -248,7 +248,7 @@ void X3DImporter::readIndexedTriangleFanSet(XmlNode &node) {
// if "USE" defined then find already defined element.
if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedTriangleFanSet, ne);
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedTriangleFanSet, ne);
} else {
// check data
if (index.size() == 0) throw DeadlyImportError("IndexedTriangleFanSet must contain not empty \"index\" attribute.");
@ -354,7 +354,7 @@ void X3DImporter::readIndexedTriangleSet(XmlNode &node) {
// if "USE" defined then find already defined element.
if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedTriangleSet, ne);
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedTriangleSet, ne);
} else {
// check data
if (index.size() == 0) throw DeadlyImportError("IndexedTriangleSet must contain not empty \"index\" attribute.");
@ -453,10 +453,12 @@ void X3DImporter::readIndexedTriangleStripSet(XmlNode &node) {
// if "USE" defined then find already defined element.
if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedTriangleStripSet, ne);
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedTriangleStripSet, ne);
} else {
// check data
if (index.size() == 0) throw DeadlyImportError("IndexedTriangleStripSet must contain not empty \"index\" attribute.");
if (index.empty()) {
throw DeadlyImportError("IndexedTriangleStripSet must contain not empty \"index\" attribute.");
}
// create and if needed - define new geometry object.
ne = new X3DNodeElementIndexedSet(X3DElemType::ENET_IndexedTriangleStripSet, mNodeElementCur);
@ -544,10 +546,12 @@ void X3DImporter::readLineSet(XmlNode &node) {
// if "USE" defined then find already defined element.
if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_LineSet, ne);
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_LineSet, ne);
} else {
// check data
if (vertexCount.size() == 0) throw DeadlyImportError("LineSet must contain not empty \"vertexCount\" attribute.");
if (vertexCount.empty()) {
throw DeadlyImportError("LineSet must contain not empty \"vertexCount\" attribute.");
}
// create and if needed - define new geometry object.
ne = new X3DNodeElementSet(X3DElemType::ENET_LineSet, mNodeElementCur);
@ -612,7 +616,7 @@ void X3DImporter::readPointSet(XmlNode &node) {
// if "USE" defined then find already defined element.
if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_PointSet, ne);
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_PointSet, ne);
} else {
// create and if needed - define new geometry object.
ne = new X3DNodeElementIndexedSet(X3DElemType::ENET_PointSet, mNodeElementCur);
@ -677,10 +681,12 @@ void X3DImporter::readTriangleFanSet(XmlNode &node) {
// if "USE" defined then find already defined element.
if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TriangleFanSet, ne);
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TriangleFanSet, ne);
} else {
// check data
if (fanCount.size() == 0) throw DeadlyImportError("TriangleFanSet must contain not empty \"fanCount\" attribute.");
if (fanCount.empty()) {
throw DeadlyImportError("TriangleFanSet must contain not empty \"fanCount\" attribute.");
}
// create and if needed - define new geometry object.
ne = new X3DNodeElementSet(X3DElemType::ENET_TriangleFanSet, mNodeElementCur);
@ -784,7 +790,7 @@ void X3DImporter::readTriangleSet(XmlNode &node) {
// if "USE" defined then find already defined element.
if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TriangleSet, ne);
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TriangleSet, ne);
} else {
// create and if needed - define new geometry object.
ne = new X3DNodeElementIndexedSet(X3DElemType::ENET_TriangleSet, mNodeElementCur);
@ -859,7 +865,7 @@ void X3DImporter::readTriangleStripSet(XmlNode &node) {
// if "USE" defined then find already defined element.
if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TriangleStripSet, ne);
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TriangleStripSet, ne);
} else {
// check data
if (stripCount.size() == 0) throw DeadlyImportError("TriangleStripSet must contain not empty \"stripCount\" attribute.");
@ -958,14 +964,14 @@ void X3DImporter::readTriangleStripSet(XmlNode &node) {
void X3DImporter::readNormal(XmlNode &node) {
std::string use, def;
std::list<aiVector3D> vector;
X3DNodeElementBase *ne;
X3DNodeElementBase *ne=nullptr;
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
X3DXmlHelper::getVector3DListAttribute(node, "vector", vector);
// if "USE" defined then find already defined element.
if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Normal, ne);
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Normal, ne);
} else {
// create and if needed - define new geometry object.
ne = new X3DNodeElementNormal(mNodeElementCur);

View File

@ -60,7 +60,7 @@ void X3DImporter::readShape(XmlNode &node) {
// if "USE" defined then find already defined element.
if (!use.empty()) {
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Shape, ne);
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Shape, ne);
} else {
// create and if needed - define new geometry object.
ne = new X3DNodeElementShape(mNodeElementCur);
@ -74,31 +74,55 @@ void X3DImporter::readShape(XmlNode &node) {
// check for appearance node
if (currentChildName == "Appearance") readAppearance(currentChildNode);
// check for X3DGeometryNodes
else if (currentChildName == "Arc2D") readArc2D(currentChildNode);
else if (currentChildName == "ArcClose2D") readArcClose2D(currentChildNode);
else if (currentChildName == "Circle2D") readCircle2D(currentChildNode);
else if (currentChildName == "Disk2D") readDisk2D(currentChildNode);
else if (currentChildName == "Polyline2D") readPolyline2D(currentChildNode);
else if (currentChildName == "Polypoint2D") readPolypoint2D(currentChildNode);
else if (currentChildName == "Rectangle2D") readRectangle2D(currentChildNode);
else if (currentChildName == "TriangleSet2D") readTriangleSet2D(currentChildNode);
else if (currentChildName == "Box") readBox(currentChildNode);
else if (currentChildName == "Cone") readCone(currentChildNode);
else if (currentChildName == "Cylinder") readCylinder(currentChildNode);
else if (currentChildName == "ElevationGrid") readElevationGrid(currentChildNode);
else if (currentChildName == "Extrusion") readExtrusion(currentChildNode);
else if (currentChildName == "IndexedFaceSet") readIndexedFaceSet(currentChildNode);
else if (currentChildName == "Sphere") readSphere(currentChildNode);
else if (currentChildName == "IndexedLineSet") readIndexedLineSet(currentChildNode);
else if (currentChildName == "LineSet") readLineSet(currentChildNode);
else if (currentChildName == "PointSet") readPointSet(currentChildNode);
else if (currentChildName == "IndexedTriangleFanSet") readIndexedTriangleFanSet(currentChildNode);
else if (currentChildName == "IndexedTriangleSet") readIndexedTriangleSet(currentChildNode);
else if (currentChildName == "IndexedTriangleStripSet") readIndexedTriangleStripSet(currentChildNode);
else if (currentChildName == "TriangleFanSet") readTriangleFanSet(currentChildNode);
else if (currentChildName == "TriangleSet") readTriangleSet(currentChildNode);
else if (currentChildName == "Arc2D")
readArc2D(currentChildNode);
else if (currentChildName == "ArcClose2D")
readArcClose2D(currentChildNode);
else if (currentChildName == "Circle2D")
readCircle2D(currentChildNode);
else if (currentChildName == "Disk2D")
readDisk2D(currentChildNode);
else if (currentChildName == "Polyline2D")
readPolyline2D(currentChildNode);
else if (currentChildName == "Polypoint2D")
readPolypoint2D(currentChildNode);
else if (currentChildName == "Rectangle2D")
readRectangle2D(currentChildNode);
else if (currentChildName == "TriangleSet2D")
readTriangleSet2D(currentChildNode);
else if (currentChildName == "Box")
readBox(currentChildNode);
else if (currentChildName == "Cone")
readCone(currentChildNode);
else if (currentChildName == "Cylinder")
readCylinder(currentChildNode);
else if (currentChildName == "ElevationGrid")
readElevationGrid(currentChildNode);
else if (currentChildName == "Extrusion")
readExtrusion(currentChildNode);
else if (currentChildName == "IndexedFaceSet")
readIndexedFaceSet(currentChildNode);
else if (currentChildName == "Sphere")
readSphere(currentChildNode);
else if (currentChildName == "IndexedLineSet")
readIndexedLineSet(currentChildNode);
else if (currentChildName == "LineSet")
readLineSet(currentChildNode);
else if (currentChildName == "PointSet")
readPointSet(currentChildNode);
else if (currentChildName == "IndexedTriangleFanSet")
readIndexedTriangleFanSet(currentChildNode);
else if (currentChildName == "IndexedTriangleSet")
readIndexedTriangleSet(currentChildNode);
else if (currentChildName == "IndexedTriangleStripSet")
readIndexedTriangleStripSet(currentChildNode);
else if (currentChildName == "TriangleFanSet")
readTriangleFanSet(currentChildNode);
else if (currentChildName == "TriangleSet")
readTriangleSet(currentChildNode);
// check for X3DMetadataObject
else if (!checkForMetadataNode(currentChildNode)) skipUnsupportedNode("Shape", currentChildNode);
else if (!checkForMetadataNode(currentChildNode))
skipUnsupportedNode("Shape", currentChildNode);
}
ParseHelper_Node_Exit();
@ -128,32 +152,31 @@ void X3DImporter::readAppearance(XmlNode &node) {
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
// if "USE" defined then find already defined element.
if (!use.empty())
{
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Appearance, ne);
}
else
{
if (!use.empty()) {
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Appearance, ne);
} else {
// create and if needed - define new geometry object.
ne = new X3DNodeElementAppearance(mNodeElementCur);
if (!def.empty()) ne->ID = def;
// check for child nodes
if(!isNodeEmpty(node))
{
if (!isNodeEmpty(node)) {
ParseHelper_Node_Enter(ne);
for (auto currentChildNode : node.children()) {
const std::string &currentChildName = currentChildNode.name();
if (currentChildName == "Material") readMaterial(currentChildNode);
else if (currentChildName == "ImageTexture") readImageTexture(currentChildNode);
else if (currentChildName == "TextureTransform") readTextureTransform(currentChildNode);
if (currentChildName == "Material")
readMaterial(currentChildNode);
else if (currentChildName == "ImageTexture")
readImageTexture(currentChildNode);
else if (currentChildName == "TextureTransform")
readTextureTransform(currentChildNode);
// check for X3DMetadataObject
else if (!checkForMetadataNode(currentChildNode)) skipUnsupportedNode("Appearance", currentChildNode);
else if (!checkForMetadataNode(currentChildNode))
skipUnsupportedNode("Appearance", currentChildNode);
}
ParseHelper_Node_Exit();
} // if(!isNodeEmpty(node))
else
{
else {
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
}
@ -190,12 +213,9 @@ void X3DImporter::readMaterial(XmlNode &node) {
X3DXmlHelper::getColor3DAttribute(node, "specularColor", specularColor);
// if "USE" defined then find already defined element.
if(!use.empty())
{
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Material, ne);
}
else
{
if (!use.empty()) {
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Material, ne);
} else {
// create and if needed - define new geometry object.
ne = new X3DNodeElementMaterial(mNodeElementCur);
if (!def.empty()) ne->ID = def;

View File

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

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 {
public:
virtual bool importerTest() {
bool importerTest() override {
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/X3D/ComputerKeyboard.x3d", aiProcess_ValidateDataStructure);
return nullptr != scene;