migrated x3d importer to pugixml reader
parent
3001d88172
commit
3f6a371b64
|
@ -116,7 +116,7 @@ void X3DGeoHelper::polylineIdx_to_lineIdx(const std::list<int32_t> &pPolylineCoo
|
||||||
vert_set[6].Set(x1, y2, z1); \
|
vert_set[6].Set(x1, y2, z1); \
|
||||||
vert_set[7].Set(x1, y1, z1)
|
vert_set[7].Set(x1, y1, z1)
|
||||||
|
|
||||||
void X3DGeoHelper::rect_parallele_piped(const aiVector3D &pSize, std::list<aiVector3D> &pVertices) {
|
void X3DGeoHelper::rect_parallel_epiped(const aiVector3D &pSize, std::list<aiVector3D> &pVertices) {
|
||||||
MESH_RectParallelepiped_CREATE_VERT;
|
MESH_RectParallelepiped_CREATE_VERT;
|
||||||
MACRO_FACE_ADD_QUAD_FA(true, pVertices, vert_set, 3, 2, 1, 0); // front
|
MACRO_FACE_ADD_QUAD_FA(true, pVertices, vert_set, 3, 2, 1, 0); // front
|
||||||
MACRO_FACE_ADD_QUAD_FA(true, pVertices, vert_set, 6, 7, 4, 5); // back
|
MACRO_FACE_ADD_QUAD_FA(true, pVertices, vert_set, 6, 7, 4, 5); // back
|
||||||
|
|
|
@ -19,7 +19,7 @@ public:
|
||||||
static void make_arc2D(float pStartAngle, float pEndAngle, float pRadius, size_t numSegments, std::list<aiVector3D> &pVertices);
|
static void make_arc2D(float pStartAngle, float pEndAngle, float pRadius, size_t numSegments, std::list<aiVector3D> &pVertices);
|
||||||
static void extend_point_to_line(const std::list<aiVector3D> &pPoint, std::list<aiVector3D> &pLine);
|
static void extend_point_to_line(const std::list<aiVector3D> &pPoint, std::list<aiVector3D> &pLine);
|
||||||
static void polylineIdx_to_lineIdx(const std::list<int32_t> &pPolylineCoordIdx, std::list<int32_t> &pLineCoordIdx);
|
static void polylineIdx_to_lineIdx(const std::list<int32_t> &pPolylineCoordIdx, std::list<int32_t> &pLineCoordIdx);
|
||||||
static void rect_parallele_piped(const aiVector3D &pSize, std::list<aiVector3D> &pVertices);
|
static void rect_parallel_epiped(const aiVector3D &pSize, std::list<aiVector3D> &pVertices);
|
||||||
static void coordIdx_str2faces_arr(const std::vector<int32_t> &pCoordIdx, std::vector<aiFace> &pFaces, unsigned int &pPrimitiveTypes);
|
static void coordIdx_str2faces_arr(const std::vector<int32_t> &pCoordIdx, std::vector<aiFace> &pFaces, unsigned int &pPrimitiveTypes);
|
||||||
static void add_color(aiMesh &pMesh, const std::list<aiColor3D> &pColors, const bool pColorPerVertex);
|
static void add_color(aiMesh &pMesh, const std::list<aiColor3D> &pColors, const bool pColorPerVertex);
|
||||||
static void add_color(aiMesh &pMesh, const std::list<aiColor4D> &pColors, const bool pColorPerVertex);
|
static void add_color(aiMesh &pMesh, const std::list<aiColor4D> &pColors, const bool pColorPerVertex);
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -41,6 +41,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#ifndef INCLUDED_AI_X3D_IMPORTER_H
|
#ifndef INCLUDED_AI_X3D_IMPORTER_H
|
||||||
#define INCLUDED_AI_X3D_IMPORTER_H
|
#define INCLUDED_AI_X3D_IMPORTER_H
|
||||||
|
|
||||||
|
#include "X3DImporter_Node.hpp"
|
||||||
|
|
||||||
#include <assimp/BaseImporter.h>
|
#include <assimp/BaseImporter.h>
|
||||||
#include <assimp/XmlParser.h>
|
#include <assimp/XmlParser.h>
|
||||||
#include <assimp/importerdesc.h>
|
#include <assimp/importerdesc.h>
|
||||||
|
@ -51,7 +53,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
|
|
||||||
|
@ -68,6 +69,21 @@ inline void Throw_ConvertFail_Str2ArrF(const std::string &nodeName, const std::s
|
||||||
"\" from string to array of floats.");
|
"\" from string to array of floats.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void Throw_ConvertFail_Str2ArrD(const std::string &nodeName, const std::string &pAttrValue) {
|
||||||
|
throw DeadlyImportError("In <" + nodeName + "> failed to convert attribute value \"" + pAttrValue +
|
||||||
|
"\" from string to array of doubles.");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Throw_ConvertFail_Str2ArrB(const std::string &nodeName, const std::string &pAttrValue) {
|
||||||
|
throw DeadlyImportError("In <" + nodeName + "> failed to convert attribute value \"" + pAttrValue +
|
||||||
|
"\" from string to array of booleans.");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Throw_ConvertFail_Str2ArrI(const std::string &nodeName, const std::string &pAttrValue) {
|
||||||
|
throw DeadlyImportError("In <" + nodeName + "> failed to convert attribute value \"" + pAttrValue +
|
||||||
|
"\" from string to array of integers.");
|
||||||
|
}
|
||||||
|
|
||||||
inline void Throw_DEF_And_USE(const std::string &nodeName) {
|
inline void Throw_DEF_And_USE(const std::string &nodeName) {
|
||||||
throw DeadlyImportError("\"DEF\" and \"USE\" can not be defined both in <" + nodeName + ">.");
|
throw DeadlyImportError("\"DEF\" and \"USE\" can not be defined both in <" + nodeName + ">.");
|
||||||
}
|
}
|
||||||
|
@ -225,410 +241,8 @@ inline void LogInfo(const std::string &message) {
|
||||||
///
|
///
|
||||||
/// That's all for now. Enjoy
|
/// That's all for now. Enjoy
|
||||||
///
|
///
|
||||||
enum class X3DElemType {
|
|
||||||
ENET_Group, ///< Element has type "Group".
|
|
||||||
ENET_MetaBoolean, ///< Element has type "Metadata boolean".
|
|
||||||
ENET_MetaDouble, ///< Element has type "Metadata double".
|
|
||||||
ENET_MetaFloat, ///< Element has type "Metadata float".
|
|
||||||
ENET_MetaInteger, ///< Element has type "Metadata integer".
|
|
||||||
ENET_MetaSet, ///< Element has type "Metadata set".
|
|
||||||
ENET_MetaString, ///< Element has type "Metadata string".
|
|
||||||
ENET_Arc2D, ///< Element has type "Arc2D".
|
|
||||||
ENET_ArcClose2D, ///< Element has type "ArcClose2D".
|
|
||||||
ENET_Circle2D, ///< Element has type "Circle2D".
|
|
||||||
ENET_Disk2D, ///< Element has type "Disk2D".
|
|
||||||
ENET_Polyline2D, ///< Element has type "Polyline2D".
|
|
||||||
ENET_Polypoint2D, ///< Element has type "Polypoint2D".
|
|
||||||
ENET_Rectangle2D, ///< Element has type "Rectangle2D".
|
|
||||||
ENET_TriangleSet2D, ///< Element has type "TriangleSet2D".
|
|
||||||
ENET_Box, ///< Element has type "Box".
|
|
||||||
ENET_Cone, ///< Element has type "Cone".
|
|
||||||
ENET_Cylinder, ///< Element has type "Cylinder".
|
|
||||||
ENET_Sphere, ///< Element has type "Sphere".
|
|
||||||
ENET_ElevationGrid, ///< Element has type "ElevationGrid".
|
|
||||||
ENET_Extrusion, ///< Element has type "Extrusion".
|
|
||||||
ENET_Coordinate, ///< Element has type "Coordinate".
|
|
||||||
ENET_Normal, ///< Element has type "Normal".
|
|
||||||
ENET_TextureCoordinate, ///< Element has type "TextureCoordinate".
|
|
||||||
ENET_IndexedFaceSet, ///< Element has type "IndexedFaceSet".
|
|
||||||
ENET_IndexedLineSet, ///< Element has type "IndexedLineSet".
|
|
||||||
ENET_IndexedTriangleSet, ///< Element has type "IndexedTriangleSet".
|
|
||||||
ENET_IndexedTriangleFanSet, ///< Element has type "IndexedTriangleFanSet".
|
|
||||||
ENET_IndexedTriangleStripSet, ///< Element has type "IndexedTriangleStripSet".
|
|
||||||
ENET_LineSet, ///< Element has type "LineSet".
|
|
||||||
ENET_PointSet, ///< Element has type "PointSet".
|
|
||||||
ENET_TriangleSet, ///< Element has type "TriangleSet".
|
|
||||||
ENET_TriangleFanSet, ///< Element has type "TriangleFanSet".
|
|
||||||
ENET_TriangleStripSet, ///< Element has type "TriangleStripSet".
|
|
||||||
ENET_Color, ///< Element has type "Color".
|
|
||||||
ENET_ColorRGBA, ///< Element has type "ColorRGBA".
|
|
||||||
ENET_Shape, ///< Element has type "Shape".
|
|
||||||
ENET_Appearance, ///< Element has type "Appearance".
|
|
||||||
ENET_Material, ///< Element has type "Material".
|
|
||||||
ENET_ImageTexture, ///< Element has type "ImageTexture".
|
|
||||||
ENET_TextureTransform, ///< Element has type "TextureTransform".
|
|
||||||
ENET_DirectionalLight, ///< Element has type "DirectionalLight".
|
|
||||||
ENET_PointLight, ///< Element has type "PointLight".
|
|
||||||
ENET_SpotLight, ///< Element has type "SpotLight".
|
|
||||||
|
|
||||||
ENET_Invalid ///< Element has invalid type and possible contain invalid data.
|
using X3DElementList = std::list<X3DNodeElementBase *>;
|
||||||
};
|
|
||||||
|
|
||||||
struct X3DNodeElementBase {
|
|
||||||
X3DNodeElementBase *Parent;
|
|
||||||
std::string ID;
|
|
||||||
std::list<X3DNodeElementBase *> Children;
|
|
||||||
X3DElemType Type;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
X3DNodeElementBase(X3DElemType type, X3DNodeElementBase *pParent) :
|
|
||||||
Type(type), Parent(pParent) {
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// This struct hold <Color> value.
|
|
||||||
struct CX3DImporter_NodeElement_Color : X3DNodeElementBase {
|
|
||||||
std::list<aiColor3D> Value; ///< Stored value.
|
|
||||||
|
|
||||||
/// Constructor
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
CX3DImporter_NodeElement_Color(X3DNodeElementBase *pParent) :
|
|
||||||
X3DNodeElementBase(X3DElemType::ENET_Color, pParent) {}
|
|
||||||
|
|
||||||
}; // struct CX3DImporter_NodeElement_Color
|
|
||||||
|
|
||||||
/// This struct hold <ColorRGBA> value.
|
|
||||||
struct CX3DImporter_NodeElement_ColorRGBA : X3DNodeElementBase {
|
|
||||||
std::list<aiColor4D> Value; ///< Stored value.
|
|
||||||
|
|
||||||
/// Constructor
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
CX3DImporter_NodeElement_ColorRGBA(X3DNodeElementBase *pParent) :
|
|
||||||
X3DNodeElementBase(X3DElemType::ENET_ColorRGBA, pParent) {}
|
|
||||||
|
|
||||||
}; // struct CX3DImporter_NodeElement_ColorRGBA
|
|
||||||
|
|
||||||
/// This struct hold <Coordinate> value.
|
|
||||||
struct CX3DImporter_NodeElement_Coordinate : public X3DNodeElementBase {
|
|
||||||
std::list<aiVector3D> Value; ///< Stored value.
|
|
||||||
|
|
||||||
/// Constructor
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
CX3DImporter_NodeElement_Coordinate(X3DNodeElementBase *pParent) :
|
|
||||||
X3DNodeElementBase(X3DElemType::ENET_Coordinate, pParent) {}
|
|
||||||
|
|
||||||
}; // struct CX3DImporter_NodeElement_Coordinate
|
|
||||||
|
|
||||||
/// This struct hold <Normal> value.
|
|
||||||
struct CX3DImporter_NodeElement_Normal : X3DNodeElementBase {
|
|
||||||
std::list<aiVector3D> Value; ///< Stored value.
|
|
||||||
|
|
||||||
/// Constructor
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
CX3DImporter_NodeElement_Normal(X3DNodeElementBase *pParent) :
|
|
||||||
X3DNodeElementBase(X3DElemType::ENET_Normal, pParent) {}
|
|
||||||
|
|
||||||
}; // struct CX3DImporter_NodeElement_Normal
|
|
||||||
|
|
||||||
/// This struct hold <TextureCoordinate> value.
|
|
||||||
struct CX3DImporter_NodeElement_TextureCoordinate : X3DNodeElementBase {
|
|
||||||
std::list<aiVector2D> Value; ///< Stored value.
|
|
||||||
|
|
||||||
/// Constructor
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
CX3DImporter_NodeElement_TextureCoordinate(X3DNodeElementBase *pParent) :
|
|
||||||
X3DNodeElementBase(X3DElemType::ENET_TextureCoordinate, pParent) {}
|
|
||||||
|
|
||||||
}; // struct CX3DImporter_NodeElement_TextureCoordinate
|
|
||||||
|
|
||||||
/// Two-dimensional figure.
|
|
||||||
struct CX3DImporter_NodeElement_Geometry2D : X3DNodeElementBase {
|
|
||||||
std::list<aiVector3D> Vertices; ///< Vertices list.
|
|
||||||
size_t NumIndices; ///< Number of indices in one face.
|
|
||||||
bool Solid; ///< Flag: if true then render must use back-face culling, else render must draw both sides of object.
|
|
||||||
|
|
||||||
/// Constructor.
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
/// \param [in] pType - type of geometry object.
|
|
||||||
CX3DImporter_NodeElement_Geometry2D(X3DElemType pType, X3DNodeElementBase *pParent) :
|
|
||||||
X3DNodeElementBase(pType, pParent), Solid(true) {}
|
|
||||||
|
|
||||||
}; // class CX3DImporter_NodeElement_Geometry2D
|
|
||||||
|
|
||||||
/// Three-dimensional body.
|
|
||||||
struct CX3DImporter_NodeElement_Geometry3D : X3DNodeElementBase {
|
|
||||||
std::list<aiVector3D> Vertices; ///< Vertices list.
|
|
||||||
size_t NumIndices; ///< Number of indices in one face.
|
|
||||||
bool Solid; ///< Flag: if true then render must use back-face culling, else render must draw both sides of object.
|
|
||||||
|
|
||||||
/// Constructor.
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
/// \param [in] pType - type of geometry object.
|
|
||||||
CX3DImporter_NodeElement_Geometry3D(X3DElemType pType, X3DNodeElementBase *pParent) :
|
|
||||||
X3DNodeElementBase(pType, pParent), Vertices(), NumIndices(0), Solid(true) {
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
}; // class CX3DImporter_NodeElement_Geometry3D
|
|
||||||
|
|
||||||
/// Uniform rectangular grid of varying height.
|
|
||||||
struct CX3DImporter_NodeElement_ElevationGrid : CX3DImporter_NodeElement_Geometry3D {
|
|
||||||
bool NormalPerVertex; ///< If true then normals are defined for every vertex, else for every face(line).
|
|
||||||
bool ColorPerVertex; ///< If true then colors are defined for every vertex, else for every face(line).
|
|
||||||
/// If the angle between the geometric normals of two adjacent faces is less than the crease angle, normals shall be calculated so that the faces are
|
|
||||||
/// shaded smoothly across the edge; otherwise, normals shall be calculated so that a lighting discontinuity across the edge is produced.
|
|
||||||
float CreaseAngle;
|
|
||||||
std::vector<int32_t> CoordIdx; ///< Coordinates list by faces. In X3D format: "-1" - delimiter for faces.
|
|
||||||
|
|
||||||
/// Constructor.
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
/// \param [in] pType - type of geometry object.
|
|
||||||
CX3DImporter_NodeElement_ElevationGrid(X3DElemType pType, X3DNodeElementBase *pParent) :
|
|
||||||
CX3DImporter_NodeElement_Geometry3D(pType, pParent) {}
|
|
||||||
}; // class CX3DImporter_NodeElement_IndexedSet
|
|
||||||
|
|
||||||
/// Shape with indexed vertices.
|
|
||||||
struct CX3DImporter_NodeElement_IndexedSet : public CX3DImporter_NodeElement_Geometry3D {
|
|
||||||
/// The ccw field defines the ordering of the vertex coordinates of the geometry with respect to user-given or automatically generated normal vectors
|
|
||||||
/// used in the lighting model equations. If ccw is TRUE, the normals shall follow the right hand rule; the orientation of each normal with respect to
|
|
||||||
/// the vertices (taken in order) shall be such that the vertices appear to be oriented in a counterclockwise order when the vertices are viewed (in the
|
|
||||||
/// local coordinate system of the Shape) from the opposite direction as the normal. If ccw is FALSE, the normals shall be oriented in the opposite
|
|
||||||
/// direction. If normals are not generated but are supplied using a Normal node, and the orientation of the normals does not match the setting of the
|
|
||||||
/// ccw field, results are undefined.
|
|
||||||
bool CCW;
|
|
||||||
std::vector<int32_t> ColorIndex; ///< Field to specify the polygonal faces by indexing into the <Color> or <ColorRGBA>.
|
|
||||||
bool ColorPerVertex; ///< If true then colors are defined for every vertex, else for every face(line).
|
|
||||||
/// The convex field indicates whether all polygons in the shape are convex (TRUE). A polygon is convex if it is planar, does not intersect itself,
|
|
||||||
/// and all of the interior angles at its vertices are less than 180 degrees. Non planar and self intersecting polygons may produce undefined results
|
|
||||||
/// even if the convex field is FALSE.
|
|
||||||
bool Convex;
|
|
||||||
std::vector<int32_t> CoordIndex; ///< Field to specify the polygonal faces by indexing into the <Coordinate>.
|
|
||||||
/// If the angle between the geometric normals of two adjacent faces is less than the crease angle, normals shall be calculated so that the faces are
|
|
||||||
/// shaded smoothly across the edge; otherwise, normals shall be calculated so that a lighting discontinuity across the edge is produced.
|
|
||||||
float CreaseAngle;
|
|
||||||
std::vector<int32_t> NormalIndex; ///< Field to specify the polygonal faces by indexing into the <Normal>.
|
|
||||||
bool NormalPerVertex; ///< If true then normals are defined for every vertex, else for every face(line).
|
|
||||||
std::vector<int32_t> TexCoordIndex; ///< Field to specify the polygonal faces by indexing into the <TextureCoordinate>.
|
|
||||||
|
|
||||||
/// Constructor.
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
/// \param [in] pType - type of geometry object.
|
|
||||||
CX3DImporter_NodeElement_IndexedSet(X3DElemType pType, X3DNodeElementBase *pParent) :
|
|
||||||
CX3DImporter_NodeElement_Geometry3D(pType, pParent) {}
|
|
||||||
}; // class CX3DImporter_NodeElement_IndexedSet
|
|
||||||
|
|
||||||
/// Shape with set of vertices.
|
|
||||||
struct CX3DImporter_NodeElement_Set : CX3DImporter_NodeElement_Geometry3D {
|
|
||||||
/// The ccw field defines the ordering of the vertex coordinates of the geometry with respect to user-given or automatically generated normal vectors
|
|
||||||
/// used in the lighting model equations. If ccw is TRUE, the normals shall follow the right hand rule; the orientation of each normal with respect to
|
|
||||||
/// the vertices (taken in order) shall be such that the vertices appear to be oriented in a counterclockwise order when the vertices are viewed (in the
|
|
||||||
/// local coordinate system of the Shape) from the opposite direction as the normal. If ccw is FALSE, the normals shall be oriented in the opposite
|
|
||||||
/// direction. If normals are not generated but are supplied using a Normal node, and the orientation of the normals does not match the setting of the
|
|
||||||
/// ccw field, results are undefined.
|
|
||||||
bool CCW;
|
|
||||||
bool ColorPerVertex; ///< If true then colors are defined for every vertex, else for every face(line).
|
|
||||||
bool NormalPerVertex; ///< If true then normals are defined for every vertex, else for every face(line).
|
|
||||||
std::vector<int32_t> CoordIndex; ///< Field to specify the polygonal faces by indexing into the <Coordinate>.
|
|
||||||
std::vector<int32_t> NormalIndex; ///< Field to specify the polygonal faces by indexing into the <Normal>.
|
|
||||||
std::vector<int32_t> TexCoordIndex; ///< Field to specify the polygonal faces by indexing into the <TextureCoordinate>.
|
|
||||||
std::vector<int32_t> VertexCount; ///< Field describes how many vertices are to be used in each polyline(polygon) from the <Coordinate> field.
|
|
||||||
|
|
||||||
/// Constructor.
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
/// \param [in] pType - type of geometry object.
|
|
||||||
CX3DImporter_NodeElement_Set(X3DElemType type, X3DNodeElementBase *pParent) :
|
|
||||||
CX3DImporter_NodeElement_Geometry3D(type, pParent) {}
|
|
||||||
|
|
||||||
}; // class CX3DImporter_NodeElement_Set
|
|
||||||
|
|
||||||
/// This struct hold <Shape> value.
|
|
||||||
struct CX3DImporter_NodeElement_Shape : X3DNodeElementBase {
|
|
||||||
|
|
||||||
/// Constructor
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
CX3DImporter_NodeElement_Shape(X3DNodeElementBase *pParent) :
|
|
||||||
X3DNodeElementBase(X3DElemType::ENET_Shape, pParent) {}
|
|
||||||
}; // struct CX3DImporter_NodeElement_Shape
|
|
||||||
|
|
||||||
/// This struct hold <Appearance> value.
|
|
||||||
struct CX3DImporter_NodeElement_Appearance : public X3DNodeElementBase {
|
|
||||||
|
|
||||||
/// Constructor
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
CX3DImporter_NodeElement_Appearance(X3DNodeElementBase *pParent) :
|
|
||||||
X3DNodeElementBase(X3DElemType::ENET_Appearance, pParent) {}
|
|
||||||
|
|
||||||
}; // struct CX3DImporter_NodeElement_Appearance
|
|
||||||
|
|
||||||
struct CX3DImporter_NodeElement_Material : public X3DNodeElementBase {
|
|
||||||
float AmbientIntensity; ///< Specifies how much ambient light from light sources this surface shall reflect.
|
|
||||||
aiColor3D DiffuseColor; ///< Reflects all X3D light sources depending on the angle of the surface with respect to the light source.
|
|
||||||
aiColor3D EmissiveColor; ///< Models "glowing" objects. This can be useful for displaying pre-lit models.
|
|
||||||
float Shininess; ///< Lower shininess values produce soft glows, while higher values result in sharper, smaller highlights.
|
|
||||||
aiColor3D SpecularColor; ///< The specularColor and shininess fields determine the specular highlights.
|
|
||||||
float Transparency; ///< Specifies how "clear" an object is, with 1.0 being completely transparent, and 0.0 completely opaque.
|
|
||||||
|
|
||||||
/// Constructor.
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
/// \param [in] pType - type of geometry object.
|
|
||||||
CX3DImporter_NodeElement_Material(X3DNodeElementBase *pParent) :
|
|
||||||
X3DNodeElementBase(X3DElemType::ENET_Material, pParent),
|
|
||||||
AmbientIntensity(0.0f),
|
|
||||||
DiffuseColor(),
|
|
||||||
EmissiveColor(),
|
|
||||||
Shininess(0.0f),
|
|
||||||
SpecularColor(),
|
|
||||||
Transparency(1.0f) {
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
}; // class CX3DImporter_NodeElement_Material
|
|
||||||
|
|
||||||
/// This struct hold <ImageTexture> value.
|
|
||||||
struct CX3DImporter_NodeElement_ImageTexture : X3DNodeElementBase {
|
|
||||||
/// RepeatS and RepeatT, that specify how the texture wraps in the S and T directions. If repeatS is TRUE (the default), the texture map is repeated
|
|
||||||
/// outside the [0.0, 1.0] texture coordinate range in the S direction so that it fills the shape. If repeatS is FALSE, the texture coordinates are
|
|
||||||
/// clamped in the S direction to lie within the [0.0, 1.0] range. The repeatT field is analogous to the repeatS field.
|
|
||||||
bool RepeatS;
|
|
||||||
bool RepeatT; ///< See \ref RepeatS.
|
|
||||||
std::string URL; ///< URL of the texture.
|
|
||||||
|
|
||||||
/// Constructor
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
CX3DImporter_NodeElement_ImageTexture(X3DNodeElementBase *pParent) :
|
|
||||||
X3DNodeElementBase(X3DElemType::ENET_ImageTexture, pParent) {}
|
|
||||||
|
|
||||||
}; // struct CX3DImporter_NodeElement_ImageTexture
|
|
||||||
|
|
||||||
/// This struct hold <TextureTransform> value.
|
|
||||||
struct CX3DImporter_NodeElement_TextureTransform : X3DNodeElementBase {
|
|
||||||
aiVector2D Center; ///< Specifies a translation offset in texture coordinate space about which the rotation and scale fields are applied.
|
|
||||||
float Rotation; ///< Specifies a rotation in angle base units of the texture coordinates about the center point after the scale has been applied.
|
|
||||||
aiVector2D Scale; ///< Specifies a scaling factor in S and T of the texture coordinates about the center point.
|
|
||||||
aiVector2D Translation; ///< Specifies a translation of the texture coordinates.
|
|
||||||
|
|
||||||
/// Constructor
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
CX3DImporter_NodeElement_TextureTransform(X3DNodeElementBase *pParent) :
|
|
||||||
X3DNodeElementBase(X3DElemType::ENET_TextureTransform, pParent) {}
|
|
||||||
|
|
||||||
}; // struct CX3DImporter_NodeElement_TextureTransform
|
|
||||||
|
|
||||||
struct CX3DNodeElementGroup : X3DNodeElementBase {
|
|
||||||
aiMatrix4x4 Transformation; ///< Transformation matrix.
|
|
||||||
|
|
||||||
/// As you know node elements can use already defined node elements when attribute "USE" is defined.
|
|
||||||
/// Standard search when looking for an element in the whole scene graph, existing at this moment.
|
|
||||||
/// If a node is marked as static, the children(or lower) can not search for elements in the nodes upper then static.
|
|
||||||
bool Static;
|
|
||||||
|
|
||||||
bool UseChoice; ///< Flag: if true then use number from \ref Choice to choose what the child will be kept.
|
|
||||||
int32_t Choice; ///< Number of the child which will be kept.
|
|
||||||
|
|
||||||
/// Constructor.
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
/// \param [in] pStatic - static node flag.
|
|
||||||
CX3DNodeElementGroup(X3DNodeElementBase *pParent, const bool pStatic = false) :
|
|
||||||
X3DNodeElementBase(X3DElemType::ENET_Group, pParent), Static(pStatic), UseChoice(false) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct X3DNodeElementMeta : X3DNodeElementBase {
|
|
||||||
std::string Name; ///< Name of metadata object.
|
|
||||||
std::string Reference;
|
|
||||||
|
|
||||||
virtual ~X3DNodeElementMeta() {
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
X3DNodeElementMeta(X3DElemType type, X3DNodeElementBase *parent) :
|
|
||||||
X3DNodeElementBase(type, parent) {
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct X3DNodeElementMetaBoolean : X3DNodeElementMeta {
|
|
||||||
std::vector<bool> Value; ///< Stored value.
|
|
||||||
|
|
||||||
explicit X3DNodeElementMetaBoolean(X3DNodeElementBase *pParent) :
|
|
||||||
X3DNodeElementMeta(X3DElemType::ENET_MetaBoolean, pParent) {
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct X3DNodeElementMetaDouble : X3DNodeElementMeta {
|
|
||||||
std::vector<double> Value; ///< Stored value.
|
|
||||||
|
|
||||||
explicit X3DNodeElementMetaDouble(X3DNodeElementBase *pParent) :
|
|
||||||
X3DNodeElementMeta(X3DElemType::ENET_MetaDouble, pParent) {
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct X3DNodeElementMetaFloat : public X3DNodeElementMeta {
|
|
||||||
std::vector<float> Value; ///< Stored value.
|
|
||||||
|
|
||||||
explicit X3DNodeElementMetaFloat(X3DNodeElementBase *pParent) :
|
|
||||||
X3DNodeElementMeta(X3DElemType::ENET_MetaFloat, pParent) {
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct X3DNodeElementMetaInt : public X3DNodeElementMeta {
|
|
||||||
std::vector<int32_t> Value; ///< Stored value.
|
|
||||||
|
|
||||||
explicit X3DNodeElementMetaInt(X3DNodeElementBase *pParent) :
|
|
||||||
X3DNodeElementMeta(X3DElemType::ENET_MetaInteger, pParent) {
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct X3DNodeElementMetaSet : public X3DNodeElementMeta {
|
|
||||||
std::list<X3DNodeElementMeta> Value; ///< Stored value.
|
|
||||||
|
|
||||||
explicit X3DNodeElementMetaSet(X3DNodeElementBase *pParent) :
|
|
||||||
X3DNodeElementMeta(X3DElemType::ENET_MetaSet, pParent) {
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct X3DNodeElementMetaString : X3DNodeElementMeta {
|
|
||||||
std::list<std::string> Value; ///< Stored value.
|
|
||||||
|
|
||||||
explicit X3DNodeElementMetaString(X3DNodeElementBase *pParent) :
|
|
||||||
X3DNodeElementMeta(X3DElemType::ENET_MetaString, pParent) {
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// \struct CX3DImporter_NodeElement_Light
|
|
||||||
/// This struct hold <TextureTransform> value.
|
|
||||||
struct X3DNodeNodeElementLight : X3DNodeElementBase {
|
|
||||||
float AmbientIntensity; ///< Specifies the intensity of the ambient emission from the light.
|
|
||||||
aiColor3D Color; ///< specifies the spectral colour properties of both the direct and ambient light emission as an RGB value.
|
|
||||||
aiVector3D Direction; ///< Specifies the direction vector of the illumination emanating from the light source in the local coordinate system.
|
|
||||||
/// \var Global
|
|
||||||
/// Field that determines whether the light is global or scoped. Global lights illuminate all objects that fall within their volume of lighting influence.
|
|
||||||
/// Scoped lights only illuminate objects that are in the same transformation hierarchy as the light.
|
|
||||||
bool Global;
|
|
||||||
float Intensity; ///< Specifies the brightness of the direct emission from the light.
|
|
||||||
/// \var Attenuation
|
|
||||||
/// PointLight node's illumination falls off with distance as specified by three attenuation coefficients. The attenuation factor
|
|
||||||
/// is: "1 / max(attenuation[0] + attenuation[1] * r + attenuation[2] * r2, 1)", where r is the distance from the light to the surface being illuminated.
|
|
||||||
aiVector3D Attenuation;
|
|
||||||
aiVector3D Location; ///< Specifies a translation offset of the centre point of the light source from the light's local coordinate system origin.
|
|
||||||
float Radius; ///< Specifies the radial extent of the solid angle and the maximum distance from location that may be illuminated by the light source.
|
|
||||||
float BeamWidth; ///< Specifies an inner solid angle in which the light source emits light at uniform full intensity.
|
|
||||||
float CutOffAngle; ///< The light source's emission intensity drops off from the inner solid angle (beamWidth) to the outer solid angle (cutOffAngle).
|
|
||||||
|
|
||||||
/// Constructor
|
|
||||||
/// \param [in] pParent - pointer to parent node.
|
|
||||||
/// \param [in] pLightType - type of the light source.
|
|
||||||
X3DNodeNodeElementLight(X3DElemType pLightType, X3DNodeElementBase *pParent) :
|
|
||||||
X3DNodeElementBase(pLightType, pParent) {}
|
|
||||||
|
|
||||||
}; // struct CX3DImporter_NodeElement_Light
|
|
||||||
|
|
||||||
using X3DElementList = std::list<X3DNodeElementBase*>;
|
|
||||||
|
|
||||||
class X3DImporter : public BaseImporter {
|
class X3DImporter : public BaseImporter {
|
||||||
public:
|
public:
|
||||||
|
@ -654,18 +268,113 @@ public:
|
||||||
void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler);
|
void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler);
|
||||||
const aiImporterDesc *GetInfo() const;
|
const aiImporterDesc *GetInfo() const;
|
||||||
void Clear();
|
void Clear();
|
||||||
void readMetadata(XmlNode &node);
|
|
||||||
void readScene(XmlNode &node);
|
|
||||||
void readViewpoint(XmlNode &node);
|
|
||||||
void readMetadataObject(XmlNode &node);
|
|
||||||
void ParseDirectionalLight(XmlNode &node);
|
|
||||||
void Postprocess_BuildNode(const X3DNodeElementBase &pNodeElement, aiNode &pSceneNode, std::list<aiMesh *> &pSceneMeshList,
|
|
||||||
std::list<aiMaterial *> &pSceneMaterialList, std::list<aiLight *> &pSceneLightList) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool isNodeEmpty(XmlNode &node);
|
||||||
|
void checkNodeMustBeEmpty(XmlNode &node);
|
||||||
|
void skipUnsupportedNode(const std::string &pParentNodeName, XmlNode &node);
|
||||||
|
void readHead(XmlNode &node);
|
||||||
|
void readChildNodes(XmlNode &node, const std::string &pParentNodeName);
|
||||||
|
void readScene(XmlNode &node);
|
||||||
|
|
||||||
|
bool FindNodeElement_FromRoot(const std::string &pID, const X3DElemType pType, X3DNodeElementBase **pElement);
|
||||||
|
bool FindNodeElement_FromNode(X3DNodeElementBase *pStartNode, const std::string &pID,
|
||||||
|
const X3DElemType pType, X3DNodeElementBase **pElement);
|
||||||
|
bool FindNodeElement(const std::string &pID, const X3DElemType pType, X3DNodeElementBase **pElement);
|
||||||
|
void ParseHelper_Group_Begin(const bool pStatic = false);
|
||||||
|
void ParseHelper_Node_Enter(X3DNodeElementBase *pNode);
|
||||||
|
void ParseHelper_Node_Exit();
|
||||||
|
|
||||||
|
// 2D geometry
|
||||||
|
void readArc2D(XmlNode &node);
|
||||||
|
void readArcClose2D(XmlNode &node);
|
||||||
|
void readCircle2D(XmlNode &node);
|
||||||
|
void readDisk2D(XmlNode &node);
|
||||||
|
void readPolyline2D(XmlNode &node);
|
||||||
|
void readPolypoint2D(XmlNode &node);
|
||||||
|
void readRectangle2D(XmlNode &node);
|
||||||
|
void readTriangleSet2D(XmlNode &node);
|
||||||
|
|
||||||
|
// 3D geometry
|
||||||
|
void readBox(XmlNode &node);
|
||||||
|
void readCone(XmlNode &node);
|
||||||
|
void readCylinder(XmlNode &node);
|
||||||
|
void readElevationGrid(XmlNode &node);
|
||||||
|
void readExtrusion(XmlNode &node);
|
||||||
|
void readIndexedFaceSet(XmlNode &node);
|
||||||
|
void readSphere(XmlNode &node);
|
||||||
|
|
||||||
|
// group
|
||||||
|
void startReadGroup(XmlNode &node);
|
||||||
|
void endReadGroup();
|
||||||
|
void startReadStaticGroup(XmlNode &node);
|
||||||
|
void endReadStaticGroup();
|
||||||
|
void startReadSwitch(XmlNode &node);
|
||||||
|
void endReadSwitch();
|
||||||
|
void startReadTransform(XmlNode &node);
|
||||||
|
void endReadTransform();
|
||||||
|
|
||||||
|
// light
|
||||||
|
void readDirectionalLight(XmlNode &node);
|
||||||
|
void readPointLight(XmlNode &node);
|
||||||
|
void readSpotLight(XmlNode &node);
|
||||||
|
|
||||||
|
// metadata
|
||||||
|
bool checkForMetadataNode(XmlNode &node);
|
||||||
|
void childrenReadMetadata(XmlNode &node, X3DNodeElementBase *pParentElement, const std::string &pNodeName);
|
||||||
|
void readMetadataBoolean(XmlNode &node);
|
||||||
|
void readMetadataDouble(XmlNode &node);
|
||||||
|
void readMetadataFloat(XmlNode &node);
|
||||||
|
void readMetadataInteger(XmlNode &node);
|
||||||
|
void readMetadataSet(XmlNode &node);
|
||||||
|
void readMetadataString(XmlNode &node);
|
||||||
|
|
||||||
|
// networking
|
||||||
|
void readInline(XmlNode &node);
|
||||||
|
|
||||||
|
// postprocessing
|
||||||
|
aiMatrix4x4 PostprocessHelper_Matrix_GlobalToCurrent() const;
|
||||||
|
void PostprocessHelper_CollectMetadata(const X3DNodeElementBase &pNodeElement, std::list<X3DNodeElementBase *> &pList) const;
|
||||||
|
bool PostprocessHelper_ElementIsMetadata(const X3DElemType pType) const;
|
||||||
|
bool PostprocessHelper_ElementIsMesh(const X3DElemType pType) const;
|
||||||
|
void Postprocess_BuildLight(const X3DNodeElementBase &pNodeElement, std::list<aiLight *> &pSceneLightList) const;
|
||||||
|
void Postprocess_BuildMaterial(const X3DNodeElementBase &pNodeElement, aiMaterial **pMaterial) const;
|
||||||
|
void Postprocess_BuildMesh(const X3DNodeElementBase &pNodeElement, aiMesh **pMesh) const;
|
||||||
|
void Postprocess_BuildNode(const X3DNodeElementBase &pNodeElement, aiNode &pSceneNode, std::list<aiMesh *> &pSceneMeshList,
|
||||||
|
std::list<aiMaterial *> &pSceneMaterialList, std::list<aiLight *> &pSceneLightList) const;
|
||||||
|
void Postprocess_BuildShape(const X3DNodeElementShape &pShapeNodeElement, std::list<unsigned int> &pNodeMeshInd,
|
||||||
|
std::list<aiMesh *> &pSceneMeshList, std::list<aiMaterial *> &pSceneMaterialList) const;
|
||||||
|
void Postprocess_CollectMetadata(const X3DNodeElementBase &pNodeElement, aiNode &pSceneNode) const;
|
||||||
|
|
||||||
|
// rendering
|
||||||
|
void readColor(XmlNode &node);
|
||||||
|
void readColorRGBA(XmlNode &node);
|
||||||
|
void readCoordinate(XmlNode &node);
|
||||||
|
void readIndexedLineSet(XmlNode &node);
|
||||||
|
void readIndexedTriangleFanSet(XmlNode &node);
|
||||||
|
void readIndexedTriangleSet(XmlNode &node);
|
||||||
|
void readIndexedTriangleStripSet(XmlNode &node);
|
||||||
|
void readLineSet(XmlNode &node);
|
||||||
|
void readPointSet(XmlNode &node);
|
||||||
|
void readTriangleFanSet(XmlNode &node);
|
||||||
|
void readTriangleSet(XmlNode &node);
|
||||||
|
void readTriangleStripSet(XmlNode &node);
|
||||||
|
void readNormal(XmlNode &node);
|
||||||
|
|
||||||
|
// shape
|
||||||
|
void readShape(XmlNode &node);
|
||||||
|
void readAppearance(XmlNode &node);
|
||||||
|
void readMaterial(XmlNode &node);
|
||||||
|
|
||||||
|
// texturing
|
||||||
|
void readImageTexture(XmlNode &node);
|
||||||
|
void readTextureCoordinate(XmlNode &node);
|
||||||
|
void readTextureTransform(XmlNode &node);
|
||||||
|
|
||||||
static const aiImporterDesc Description;
|
static const aiImporterDesc Description;
|
||||||
X3DNodeElementBase *mNodeElementCur;
|
X3DNodeElementBase *mNodeElementCur;
|
||||||
aiScene *mScene;
|
aiScene *mScene;
|
||||||
|
IOSystem *mpIOHandler;
|
||||||
}; // class X3DImporter
|
}; // class X3DImporter
|
||||||
|
|
||||||
} // namespace Assimp
|
} // namespace Assimp
|
||||||
|
|
|
@ -0,0 +1,467 @@
|
||||||
|
/*
|
||||||
|
Open Asset Import Library (assimp)
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2019, assimp team
|
||||||
|
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
with or without modification, are permitted provided that the
|
||||||
|
following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer in the documentation and/or other
|
||||||
|
materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of the assimp team, nor the names of its
|
||||||
|
contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior
|
||||||
|
written permission of the assimp team.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
/// \file X3DImporter_Geometry2D.cpp
|
||||||
|
/// \brief Parsing data from nodes of "Geometry2D" set of X3D.
|
||||||
|
/// date 2015-2016
|
||||||
|
/// author smal.root@gmail.com
|
||||||
|
|
||||||
|
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||||
|
|
||||||
|
#include "X3DImporter.hpp"
|
||||||
|
#include "X3DImporter_Macro.hpp"
|
||||||
|
#include "X3DXmlHelper.h"
|
||||||
|
#include "X3DGeoHelper.h"
|
||||||
|
|
||||||
|
namespace Assimp {
|
||||||
|
|
||||||
|
// <Arc2D
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// endAngle="1.570796" SFFloat [initializeOnly]
|
||||||
|
// radius="1" SFFloat [initializeOnly]
|
||||||
|
// startAngle="0" SFFloat [initializeOnly]
|
||||||
|
// />
|
||||||
|
// The Arc2D node specifies a linear circular arc whose center is at (0,0) and whose angles are measured starting at the positive x-axis and sweeping
|
||||||
|
// towards the positive y-axis. The radius field specifies the radius of the circle of which the arc is a portion. The arc extends from the startAngle
|
||||||
|
// counterclockwise to the endAngle. The values of startAngle and endAngle shall be in the range [-2pi, 2pi] radians (or the equivalent if a different
|
||||||
|
// angle base unit has been specified). If startAngle and endAngle have the same value, a circle is specified.
|
||||||
|
void X3DImporter::readArc2D(XmlNode &node) {
|
||||||
|
std::string def, use;
|
||||||
|
float endAngle = AI_MATH_HALF_PI_F;
|
||||||
|
float radius = 1;
|
||||||
|
float startAngle = 0;
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
XmlParser::getFloatAttribute(node, "endAngle", endAngle);
|
||||||
|
XmlParser::getFloatAttribute(node, "radius", radius);
|
||||||
|
XmlParser::getFloatAttribute(node, "startAngle", startAngle);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty()) {
|
||||||
|
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);
|
||||||
|
if (!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
// create point list of geometry object and convert it to line set.
|
||||||
|
std::list<aiVector3D> tlist;
|
||||||
|
|
||||||
|
X3DGeoHelper::make_arc2D(startAngle, endAngle, radius, 10, tlist); ///TODO: IME - AI_CONFIG for NumSeg
|
||||||
|
X3DGeoHelper::extend_point_to_line(tlist, ((X3DNodeElementGeometry2D *)ne)->Vertices);
|
||||||
|
((X3DNodeElementGeometry2D *)ne)->NumIndices = 2;
|
||||||
|
// check for X3DMetadataObject childs.
|
||||||
|
if (!isNodeEmpty(node))
|
||||||
|
childrenReadMetadata(node, ne, "Arc2D");
|
||||||
|
else
|
||||||
|
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
// <ArcClose2D
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// closureType="PIE" SFString [initializeOnly], {"PIE", "CHORD"}
|
||||||
|
// endAngle="1.570796" SFFloat [initializeOnly]
|
||||||
|
// radius="1" SFFloat [initializeOnly]
|
||||||
|
// solid="false" SFBool [initializeOnly]
|
||||||
|
// startAngle="0" SFFloat [initializeOnly]
|
||||||
|
// />
|
||||||
|
// The ArcClose node specifies a portion of a circle whose center is at (0,0) and whose angles are measured starting at the positive x-axis and sweeping
|
||||||
|
// towards the positive y-axis. The end points of the arc specified are connected as defined by the closureType field. The radius field specifies the radius
|
||||||
|
// of the circle of which the arc is a portion. The arc extends from the startAngle counterclockwise to the endAngle. The value of radius shall be greater
|
||||||
|
// than zero. The values of startAngle and endAngle shall be in the range [-2pi, 2pi] radians (or the equivalent if a different default angle base unit has
|
||||||
|
// been specified). If startAngle and endAngle have the same value, a circle is specified and closureType is ignored. If the absolute difference between
|
||||||
|
// startAngle and endAngle is greater than or equal to 2pi, a complete circle is produced with no chord or radial line(s) drawn from the center.
|
||||||
|
// A closureType of "PIE" connects the end point to the start point by defining two straight line segments first from the end point to the center and then
|
||||||
|
// the center to the start point. A closureType of "CHORD" connects the end point to the start point by defining a straight line segment from the end point
|
||||||
|
// to the start point. Textures are applied individually to each face of the ArcClose2D. On the front (+Z) and back (-Z) faces of the ArcClose2D, when
|
||||||
|
// viewed from the +Z-axis, the texture is mapped onto each face with the same orientation as if the image were displayed normally in 2D.
|
||||||
|
void X3DImporter::readArcClose2D(XmlNode &node) {
|
||||||
|
std::string def, use;
|
||||||
|
std::string closureType("PIE");
|
||||||
|
float endAngle = AI_MATH_HALF_PI_F;
|
||||||
|
float radius = 1;
|
||||||
|
bool solid = false;
|
||||||
|
float startAngle = 0;
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
XmlParser::getStdStrAttribute(node, "closureType", closureType);
|
||||||
|
XmlParser::getFloatAttribute(node, "endAngle", endAngle);
|
||||||
|
XmlParser::getFloatAttribute(node, "endAngle", endAngle);
|
||||||
|
XmlParser::getFloatAttribute(node, "radius", radius);
|
||||||
|
XmlParser::getBoolAttribute(node, "solid", solid);
|
||||||
|
XmlParser::getFloatAttribute(node, "startAngle", startAngle);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty()) {
|
||||||
|
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);
|
||||||
|
if (!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
((X3DNodeElementGeometry2D *)ne)->Solid = solid;
|
||||||
|
// create point list of geometry object.
|
||||||
|
X3DGeoHelper::make_arc2D(startAngle, endAngle, radius, 10, ((X3DNodeElementGeometry2D *)ne)->Vertices); ///TODO: IME - AI_CONFIG for NumSeg
|
||||||
|
// add chord or two radiuses only if not a circle was defined
|
||||||
|
if (!((std::fabs(endAngle - startAngle) >= AI_MATH_TWO_PI_F) || (endAngle == startAngle))) {
|
||||||
|
std::list<aiVector3D> &vlist = ((X3DNodeElementGeometry2D *)ne)->Vertices; // just short alias.
|
||||||
|
|
||||||
|
if ((closureType == "PIE") || (closureType == "\"PIE\""))
|
||||||
|
vlist.push_back(aiVector3D(0, 0, 0)); // center point - first radial line
|
||||||
|
else if ((closureType != "CHORD") && (closureType != "\"CHORD\""))
|
||||||
|
Throw_IncorrectAttrValue("ArcClose2D", "closureType");
|
||||||
|
|
||||||
|
vlist.push_back(*vlist.begin()); // arc first point - chord from first to last point of arc(if CHORD) or second radial line(if PIE).
|
||||||
|
}
|
||||||
|
|
||||||
|
((X3DNodeElementGeometry2D *)ne)->NumIndices = ((X3DNodeElementGeometry2D *)ne)->Vertices.size();
|
||||||
|
// check for X3DMetadataObject childs.
|
||||||
|
if (!isNodeEmpty(node))
|
||||||
|
childrenReadMetadata(node, ne, "ArcClose2D");
|
||||||
|
else
|
||||||
|
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
// <Circle2D
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// radius="1" SFFloat [initializeOnly]
|
||||||
|
// />
|
||||||
|
void X3DImporter::readCircle2D(XmlNode &node) {
|
||||||
|
std::string def, use;
|
||||||
|
float radius = 1;
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
XmlParser::getFloatAttribute(node, "radius", radius);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty()) {
|
||||||
|
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);
|
||||||
|
if (!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
// create point list of geometry object and convert it to line set.
|
||||||
|
std::list<aiVector3D> tlist;
|
||||||
|
|
||||||
|
X3DGeoHelper::make_arc2D(0, 0, radius, 10, tlist); ///TODO: IME - AI_CONFIG for NumSeg
|
||||||
|
X3DGeoHelper::extend_point_to_line(tlist, ((X3DNodeElementGeometry2D *)ne)->Vertices);
|
||||||
|
((X3DNodeElementGeometry2D *)ne)->NumIndices = 2;
|
||||||
|
// check for X3DMetadataObject childs.
|
||||||
|
if (!isNodeEmpty(node))
|
||||||
|
childrenReadMetadata(node, ne, "Circle2D");
|
||||||
|
else
|
||||||
|
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
// <Disk2D
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// innerRadius="0" SFFloat [initializeOnly]
|
||||||
|
// outerRadius="1" SFFloat [initializeOnly]
|
||||||
|
// solid="false" SFBool [initializeOnly]
|
||||||
|
// />
|
||||||
|
// The Disk2D node specifies a circular disk which is centred at (0, 0) in the local coordinate system. The outerRadius field specifies the radius of the
|
||||||
|
// outer dimension of the Disk2D. The innerRadius field specifies the inner dimension of the Disk2D. The value of outerRadius shall be greater than zero.
|
||||||
|
// The value of innerRadius shall be greater than or equal to zero and less than or equal to outerRadius. If innerRadius is zero, the Disk2D is completely
|
||||||
|
// filled. Otherwise, the area within the innerRadius forms a hole in the Disk2D. If innerRadius is equal to outerRadius, a solid circular line shall
|
||||||
|
// be drawn using the current line properties. Textures are applied individually to each face of the Disk2D. On the front (+Z) and back (-Z) faces of
|
||||||
|
// the Disk2D, when viewed from the +Z-axis, the texture is mapped onto each face with the same orientation as if the image were displayed normally in 2D.
|
||||||
|
void X3DImporter::readDisk2D(XmlNode &node) {
|
||||||
|
std::string def, use;
|
||||||
|
float innerRadius = 0;
|
||||||
|
float outerRadius = 1;
|
||||||
|
bool solid = false;
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
XmlParser::getFloatAttribute(node, "innerRadius", innerRadius);
|
||||||
|
XmlParser::getFloatAttribute(node, "outerRadius", outerRadius);
|
||||||
|
XmlParser::getBoolAttribute(node, "solid", solid);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty()) {
|
||||||
|
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Disk2D, ne);
|
||||||
|
} else {
|
||||||
|
std::list<aiVector3D> tlist_o, tlist_i;
|
||||||
|
|
||||||
|
if (innerRadius > outerRadius) Throw_IncorrectAttrValue("Disk2D", "innerRadius");
|
||||||
|
|
||||||
|
// create and if needed - define new geometry object.
|
||||||
|
ne = new X3DNodeElementGeometry2D(X3DElemType::ENET_Disk2D, mNodeElementCur);
|
||||||
|
if (!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
// create point list of geometry object.
|
||||||
|
///TODO: IME - AI_CONFIG for NumSeg
|
||||||
|
X3DGeoHelper::make_arc2D(0, 0, outerRadius, 10, tlist_o); // outer circle
|
||||||
|
if (innerRadius == 0.0f) { // make filled disk
|
||||||
|
// in tlist_o we already have points of circle. just copy it and sign as polygon.
|
||||||
|
((X3DNodeElementGeometry2D *)ne)->Vertices = tlist_o;
|
||||||
|
((X3DNodeElementGeometry2D *)ne)->NumIndices = tlist_o.size();
|
||||||
|
} else if (innerRadius == outerRadius) { // make circle
|
||||||
|
// in tlist_o we already have points of circle. convert it to line set.
|
||||||
|
X3DGeoHelper::extend_point_to_line(tlist_o, ((X3DNodeElementGeometry2D *)ne)->Vertices);
|
||||||
|
((X3DNodeElementGeometry2D *)ne)->NumIndices = 2;
|
||||||
|
} else { // make disk
|
||||||
|
std::list<aiVector3D> &vlist = ((X3DNodeElementGeometry2D *)ne)->Vertices; // just short alias.
|
||||||
|
|
||||||
|
X3DGeoHelper::make_arc2D(0, 0, innerRadius, 10, tlist_i); // inner circle
|
||||||
|
//
|
||||||
|
// create quad list from two point lists
|
||||||
|
//
|
||||||
|
if (tlist_i.size() < 2) throw DeadlyImportError("Disk2D. Not enough points for creating quad list."); // tlist_i and tlist_o has equal size.
|
||||||
|
|
||||||
|
// add all quads except last
|
||||||
|
for (std::list<aiVector3D>::iterator it_i = tlist_i.begin(), it_o = tlist_o.begin(); it_i != tlist_i.end();) {
|
||||||
|
// do not forget - CCW direction
|
||||||
|
vlist.push_back(*it_i++); // 1st point
|
||||||
|
vlist.push_back(*it_o++); // 2nd point
|
||||||
|
vlist.push_back(*it_o); // 3rd point
|
||||||
|
vlist.push_back(*it_i); // 4th point
|
||||||
|
}
|
||||||
|
|
||||||
|
// add last quad
|
||||||
|
vlist.push_back(*tlist_i.end()); // 1st point
|
||||||
|
vlist.push_back(*tlist_o.end()); // 2nd point
|
||||||
|
vlist.push_back(*tlist_o.begin()); // 3rd point
|
||||||
|
vlist.push_back(*tlist_o.begin()); // 4th point
|
||||||
|
|
||||||
|
((X3DNodeElementGeometry2D *)ne)->NumIndices = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
((X3DNodeElementGeometry2D *)ne)->Solid = solid;
|
||||||
|
// check for X3DMetadataObject childs.
|
||||||
|
if (!isNodeEmpty(node))
|
||||||
|
childrenReadMetadata(node, ne, "Disk2D");
|
||||||
|
else
|
||||||
|
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
// <Polyline2D
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// lineSegments="" MFVec2F [intializeOnly]
|
||||||
|
// />
|
||||||
|
void X3DImporter::readPolyline2D(XmlNode &node) {
|
||||||
|
std::string def, use;
|
||||||
|
std::list<aiVector2D> lineSegments;
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
X3DXmlHelper::getVector2DListAttribute(node, "lineSegments", lineSegments);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty()) {
|
||||||
|
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);
|
||||||
|
if (!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
//
|
||||||
|
// convert read point list of geometry object to line set.
|
||||||
|
//
|
||||||
|
std::list<aiVector3D> tlist;
|
||||||
|
|
||||||
|
// convert vec2 to vec3
|
||||||
|
for (std::list<aiVector2D>::iterator it2 = lineSegments.begin(); it2 != lineSegments.end(); ++it2)
|
||||||
|
tlist.push_back(aiVector3D(it2->x, it2->y, 0));
|
||||||
|
|
||||||
|
// convert point set to line set
|
||||||
|
X3DGeoHelper::extend_point_to_line(tlist, ((X3DNodeElementGeometry2D *)ne)->Vertices);
|
||||||
|
((X3DNodeElementGeometry2D *)ne)->NumIndices = 2;
|
||||||
|
// check for X3DMetadataObject childs.
|
||||||
|
if (!isNodeEmpty(node))
|
||||||
|
childrenReadMetadata(node, ne, "Polyline2D");
|
||||||
|
else
|
||||||
|
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
// <Polypoint2D
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// point="" MFVec2F [inputOutput]
|
||||||
|
// />
|
||||||
|
void X3DImporter::readPolypoint2D(XmlNode &node) {
|
||||||
|
std::string def, use;
|
||||||
|
std::list<aiVector2D> point;
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
X3DXmlHelper::getVector2DListAttribute(node, "point", point);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty()) {
|
||||||
|
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);
|
||||||
|
if (!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
// convert vec2 to vec3
|
||||||
|
for (std::list<aiVector2D>::iterator it2 = point.begin(); it2 != point.end(); ++it2) {
|
||||||
|
((X3DNodeElementGeometry2D *)ne)->Vertices.push_back(aiVector3D(it2->x, it2->y, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
((X3DNodeElementGeometry2D *)ne)->NumIndices = 1;
|
||||||
|
// check for X3DMetadataObject childs.
|
||||||
|
if (!isNodeEmpty(node))
|
||||||
|
childrenReadMetadata(node, ne, "Polypoint2D");
|
||||||
|
else
|
||||||
|
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
// <Rectangle2D
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// size="2 2" SFVec2f [initializeOnly]
|
||||||
|
// solid="false" SFBool [initializeOnly]
|
||||||
|
// />
|
||||||
|
void X3DImporter::readRectangle2D(XmlNode &node) {
|
||||||
|
std::string def, use;
|
||||||
|
aiVector2D size(2, 2);
|
||||||
|
bool solid = false;
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
X3DXmlHelper::getVector2DAttribute(node, "size", size);
|
||||||
|
XmlParser::getBoolAttribute(node, "solid", solid);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty()) {
|
||||||
|
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);
|
||||||
|
if (!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
float x1 = -size.x / 2.0f;
|
||||||
|
float x2 = size.x / 2.0f;
|
||||||
|
float y1 = -size.y / 2.0f;
|
||||||
|
float y2 = size.y / 2.0f;
|
||||||
|
std::list<aiVector3D> &vlist = ((X3DNodeElementGeometry2D *)ne)->Vertices; // just short alias.
|
||||||
|
|
||||||
|
vlist.push_back(aiVector3D(x2, y1, 0)); // 1st point
|
||||||
|
vlist.push_back(aiVector3D(x2, y2, 0)); // 2nd point
|
||||||
|
vlist.push_back(aiVector3D(x1, y2, 0)); // 3rd point
|
||||||
|
vlist.push_back(aiVector3D(x1, y1, 0)); // 4th point
|
||||||
|
((X3DNodeElementGeometry2D *)ne)->Solid = solid;
|
||||||
|
((X3DNodeElementGeometry2D *)ne)->NumIndices = 4;
|
||||||
|
// check for X3DMetadataObject childs.
|
||||||
|
if (!isNodeEmpty(node))
|
||||||
|
childrenReadMetadata(node, ne, "Rectangle2D");
|
||||||
|
else
|
||||||
|
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
// <TriangleSet2D
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// solid="false" SFBool [initializeOnly]
|
||||||
|
// vertices="" MFVec2F [inputOutput]
|
||||||
|
// />
|
||||||
|
void X3DImporter::readTriangleSet2D(XmlNode &node) {
|
||||||
|
std::string def, use;
|
||||||
|
bool solid = false;
|
||||||
|
std::list<aiVector2D> vertices;
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
X3DXmlHelper::getVector2DListAttribute(node, "vertices", vertices);
|
||||||
|
XmlParser::getBoolAttribute(node, "solid", solid);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty()) {
|
||||||
|
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TriangleSet2D, ne);
|
||||||
|
} else {
|
||||||
|
if (vertices.size() % 3) throw DeadlyImportError("TriangleSet2D. Not enough points for defining triangle.");
|
||||||
|
|
||||||
|
// create and if needed - define new geometry object.
|
||||||
|
ne = new X3DNodeElementGeometry2D(X3DElemType::ENET_TriangleSet2D, mNodeElementCur);
|
||||||
|
if (!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
// convert vec2 to vec3
|
||||||
|
for (std::list<aiVector2D>::iterator it2 = vertices.begin(); it2 != vertices.end(); ++it2) {
|
||||||
|
((X3DNodeElementGeometry2D *)ne)->Vertices.push_back(aiVector3D(it2->x, it2->y, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
((X3DNodeElementGeometry2D *)ne)->Solid = solid;
|
||||||
|
((X3DNodeElementGeometry2D *)ne)->NumIndices = 3;
|
||||||
|
// check for X3DMetadataObject childs.
|
||||||
|
if (!isNodeEmpty(node))
|
||||||
|
childrenReadMetadata(node, ne, "TriangleSet2D");
|
||||||
|
else
|
||||||
|
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Assimp
|
||||||
|
|
||||||
|
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
@ -0,0 +1,981 @@
|
||||||
|
/*
|
||||||
|
Open Asset Import Library (assimp)
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2019, assimp team
|
||||||
|
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
with or without modification, are permitted provided that the
|
||||||
|
following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer in the documentation and/or other
|
||||||
|
materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of the assimp team, nor the names of its
|
||||||
|
contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior
|
||||||
|
written permission of the assimp team.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
/// \file X3DImporter_Geometry3D.cpp
|
||||||
|
/// \brief Parsing data from nodes of "Geometry3D" set of X3D.
|
||||||
|
/// \date 2015-2016
|
||||||
|
/// \author smal.root@gmail.com
|
||||||
|
|
||||||
|
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||||
|
|
||||||
|
#include "X3DImporter.hpp"
|
||||||
|
#include "X3DImporter_Macro.hpp"
|
||||||
|
#include "X3DXmlHelper.h"
|
||||||
|
#include "X3DGeoHelper.h"
|
||||||
|
|
||||||
|
// Header files, Assimp.
|
||||||
|
#include <assimp/StandardShapes.h>
|
||||||
|
|
||||||
|
namespace Assimp
|
||||||
|
{
|
||||||
|
|
||||||
|
// <Box
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// size="2 2 2" SFVec3f [initializeOnly]
|
||||||
|
// solid="true" SFBool [initializeOnly]
|
||||||
|
// />
|
||||||
|
// The Box node specifies a rectangular parallelepiped box centred at (0, 0, 0) in the local coordinate system and aligned with the local coordinate axes.
|
||||||
|
// By default, the box measures 2 units in each dimension, from -1 to +1. The size field specifies the extents of the box along the X-, Y-, and Z-axes
|
||||||
|
// respectively and each component value shall be greater than zero.
|
||||||
|
void X3DImporter::readBox(XmlNode &node) {
|
||||||
|
std::string def, use;
|
||||||
|
bool solid = true;
|
||||||
|
aiVector3D size(2, 2, 2);
|
||||||
|
X3DNodeElementBase* ne( nullptr );
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
X3DXmlHelper::getVector3DAttribute(node, "size", size);
|
||||||
|
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
|
||||||
|
{
|
||||||
|
// create and if needed - define new geometry object.
|
||||||
|
ne = new X3DNodeElementGeometry3D(X3DElemType::ENET_Box, mNodeElementCur);
|
||||||
|
if(!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
X3DGeoHelper::rect_parallel_epiped(size, ((X3DNodeElementGeometry3D *)ne)->Vertices); // get quad list
|
||||||
|
((X3DNodeElementGeometry3D *)ne)->Solid = solid;
|
||||||
|
((X3DNodeElementGeometry3D *)ne)->NumIndices = 4;
|
||||||
|
// check for X3DMetadataObject childs.
|
||||||
|
if(!isNodeEmpty(node))
|
||||||
|
childrenReadMetadata(node, ne, "Box");
|
||||||
|
else
|
||||||
|
mNodeElementCur->Children.push_back(ne);// add made object as child to current element
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
|
||||||
|
}// if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
// <Cone
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// bottom="true" SFBool [initializeOnly]
|
||||||
|
// bottomRadius="1" SFloat [initializeOnly]
|
||||||
|
// height="2" SFloat [initializeOnly]
|
||||||
|
// side="true" SFBool [initializeOnly]
|
||||||
|
// solid="true" SFBool [initializeOnly]
|
||||||
|
// />
|
||||||
|
void X3DImporter::readCone(XmlNode &node) {
|
||||||
|
std::string use, def;
|
||||||
|
bool bottom = true;
|
||||||
|
float bottomRadius = 1;
|
||||||
|
float height = 2;
|
||||||
|
bool side = true;
|
||||||
|
bool solid = true;
|
||||||
|
X3DNodeElementBase* ne( nullptr );
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
XmlParser::getBoolAttribute(node, "solid", solid);
|
||||||
|
XmlParser::getBoolAttribute(node, "side", side);
|
||||||
|
XmlParser::getBoolAttribute(node, "bottom", bottom);
|
||||||
|
XmlParser::getFloatAttribute(node, "height", height);
|
||||||
|
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
|
||||||
|
{
|
||||||
|
const unsigned int tess = 30;///TODO: IME tessellation factor through ai_property
|
||||||
|
|
||||||
|
std::vector<aiVector3D> tvec;// temp array for vertices.
|
||||||
|
|
||||||
|
// create and if needed - define new geometry object.
|
||||||
|
ne = new X3DNodeElementGeometry3D(X3DElemType::ENET_Cone, mNodeElementCur);
|
||||||
|
if(!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
// make cone or parts according to flags.
|
||||||
|
if(side)
|
||||||
|
{
|
||||||
|
StandardShapes::MakeCone(height, 0, bottomRadius, tess, tvec, !bottom);
|
||||||
|
}
|
||||||
|
else if(bottom)
|
||||||
|
{
|
||||||
|
StandardShapes::MakeCircle(bottomRadius, tess, tvec);
|
||||||
|
height = -(height / 2);
|
||||||
|
for(std::vector<aiVector3D>::iterator it = tvec.begin(); it != tvec.end(); ++it) it->y = height;// y - because circle made in oXZ.
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy data from temp array
|
||||||
|
for (std::vector<aiVector3D>::iterator it = tvec.begin(); it != tvec.end(); ++it)
|
||||||
|
((X3DNodeElementGeometry3D*)ne)->Vertices.push_back(*it);
|
||||||
|
|
||||||
|
((X3DNodeElementGeometry3D *)ne)->Solid = solid;
|
||||||
|
((X3DNodeElementGeometry3D *)ne)->NumIndices = 3;
|
||||||
|
// check for X3DMetadataObject childs.
|
||||||
|
if(!isNodeEmpty(node))
|
||||||
|
childrenReadMetadata(node, ne, "Cone");
|
||||||
|
else
|
||||||
|
mNodeElementCur->Children.push_back(ne);// add made object as child to current element
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
|
||||||
|
}// if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
// <Cylinder
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// bottom="true" SFBool [initializeOnly]
|
||||||
|
// height="2" SFloat [initializeOnly]
|
||||||
|
// radius="1" SFloat [initializeOnly]
|
||||||
|
// side="true" SFBool [initializeOnly]
|
||||||
|
// solid="true" SFBool [initializeOnly]
|
||||||
|
// top="true" SFBool [initializeOnly]
|
||||||
|
// />
|
||||||
|
void X3DImporter::readCylinder(XmlNode &node) {
|
||||||
|
std::string use, def;
|
||||||
|
bool bottom = true;
|
||||||
|
float height = 2;
|
||||||
|
float radius = 1;
|
||||||
|
bool side = true;
|
||||||
|
bool solid = true;
|
||||||
|
bool top = true;
|
||||||
|
X3DNodeElementBase* ne( nullptr );
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
XmlParser::getFloatAttribute(node, "radius", radius);
|
||||||
|
XmlParser::getBoolAttribute(node, "solid", solid);
|
||||||
|
XmlParser::getBoolAttribute(node, "bottom", bottom);
|
||||||
|
XmlParser::getBoolAttribute(node, "top", top);
|
||||||
|
XmlParser::getBoolAttribute(node, "side", side);
|
||||||
|
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
|
||||||
|
{
|
||||||
|
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> tcir;// temp array for vertices of circle.
|
||||||
|
|
||||||
|
// create and if needed - define new geometry object.
|
||||||
|
ne = new X3DNodeElementGeometry3D(X3DElemType::ENET_Cylinder, mNodeElementCur);
|
||||||
|
if(!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
// make cilynder or parts according to flags.
|
||||||
|
if(side) StandardShapes::MakeCone(height, radius, radius, tess, tside, true);
|
||||||
|
|
||||||
|
height /= 2;// height defined for whole cylinder, when creating top and bottom circle we are using just half of height.
|
||||||
|
if(top || bottom) StandardShapes::MakeCircle(radius, tess, tcir);
|
||||||
|
// copy data from temp arrays
|
||||||
|
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);
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
(*it).y = -height;// y - because circle made in oXZ.
|
||||||
|
vlist.push_back(*it);
|
||||||
|
}
|
||||||
|
}// if(top)
|
||||||
|
|
||||||
|
((X3DNodeElementGeometry3D *)ne)->Solid = solid;
|
||||||
|
((X3DNodeElementGeometry3D *)ne)->NumIndices = 3;
|
||||||
|
// check for X3DMetadataObject childs.
|
||||||
|
if(!isNodeEmpty(node))
|
||||||
|
childrenReadMetadata(node, ne, "Cylinder");
|
||||||
|
else
|
||||||
|
mNodeElementCur->Children.push_back(ne);// add made object as child to current element
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
|
||||||
|
}// if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
// <ElevationGrid
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// ccw="true" SFBool [initializeOnly]
|
||||||
|
// colorPerVertex="true" SFBool [initializeOnly]
|
||||||
|
// creaseAngle="0" SFloat [initializeOnly]
|
||||||
|
// height="" MFloat [initializeOnly]
|
||||||
|
// normalPerVertex="true" SFBool [initializeOnly]
|
||||||
|
// solid="true" SFBool [initializeOnly]
|
||||||
|
// xDimension="0" SFInt32 [initializeOnly]
|
||||||
|
// xSpacing="1.0" SFloat [initializeOnly]
|
||||||
|
// zDimension="0" SFInt32 [initializeOnly]
|
||||||
|
// zSpacing="1.0" SFloat [initializeOnly]
|
||||||
|
// >
|
||||||
|
// <!-- ColorNormalTexCoordContentModel -->
|
||||||
|
// ColorNormalTexCoordContentModel can contain Color (or ColorRGBA), Normal and TextureCoordinate, in any order. No more than one instance of any single
|
||||||
|
// node type is allowed. A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
||||||
|
// </ElevationGrid>
|
||||||
|
// The ElevationGrid node specifies a uniform rectangular grid of varying height in the Y=0 plane of the local coordinate system. The geometry is described
|
||||||
|
// by a scalar array of height values that specify the height of a surface above each point of the grid. The xDimension and zDimension fields indicate
|
||||||
|
// the number of elements of the grid height array in the X and Z directions. Both xDimension and zDimension shall be greater than or equal to zero.
|
||||||
|
// If either the xDimension or the zDimension is less than two, the ElevationGrid contains no quadrilaterals.
|
||||||
|
void X3DImporter::readElevationGrid(XmlNode &node) {
|
||||||
|
std::string use, def;
|
||||||
|
bool ccw = true;
|
||||||
|
bool colorPerVertex = true;
|
||||||
|
float creaseAngle = 0;
|
||||||
|
std::vector<float> height;
|
||||||
|
bool normalPerVertex = true;
|
||||||
|
bool solid = true;
|
||||||
|
int32_t xDimension = 0;
|
||||||
|
float xSpacing = 1;
|
||||||
|
int32_t zDimension = 0;
|
||||||
|
float zSpacing = 1;
|
||||||
|
X3DNodeElementBase* ne( nullptr );
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
XmlParser::getBoolAttribute(node, "solid", solid);
|
||||||
|
XmlParser::getBoolAttribute(node, "ccw", ccw);
|
||||||
|
XmlParser::getBoolAttribute(node, "colorPerVertex", colorPerVertex);
|
||||||
|
XmlParser::getBoolAttribute(node, "normalPerVertex", normalPerVertex);
|
||||||
|
XmlParser::getFloatAttribute(node, "creaseAngle", creaseAngle);
|
||||||
|
X3DXmlHelper::getFloatArrayAttribute(node, "height", height);
|
||||||
|
XmlParser::getIntAttribute(node, "xDimension", xDimension);
|
||||||
|
XmlParser::getFloatAttribute(node, "xSpacing", xSpacing);
|
||||||
|
XmlParser::getIntAttribute(node, "zDimension", zDimension);
|
||||||
|
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((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>");
|
||||||
|
|
||||||
|
// create and if needed - define new geometry object.
|
||||||
|
ne = new X3DNodeElementElevationGrid(X3DElemType::ENET_ElevationGrid, mNodeElementCur);
|
||||||
|
if(!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
X3DNodeElementElevationGrid &grid_alias = *((X3DNodeElementElevationGrid *)ne); // create alias for conveience
|
||||||
|
|
||||||
|
{// create grid vertices list
|
||||||
|
std::vector<float>::const_iterator he_it = height.begin();
|
||||||
|
|
||||||
|
for(int32_t zi = 0; zi < zDimension; zi++)// rows
|
||||||
|
{
|
||||||
|
for(int32_t xi = 0; xi < xDimension; xi++)// columns
|
||||||
|
{
|
||||||
|
aiVector3D tvec(xSpacing * xi, *he_it, zSpacing * zi);
|
||||||
|
|
||||||
|
grid_alias.Vertices.push_back(tvec);
|
||||||
|
++he_it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}// END: create grid vertices list
|
||||||
|
//
|
||||||
|
// create faces list. In "coordIdx" format
|
||||||
|
//
|
||||||
|
// check if we have quads
|
||||||
|
if((xDimension < 2) || (zDimension < 2))// only one element in dimension is set, create line set.
|
||||||
|
{
|
||||||
|
((X3DNodeElementElevationGrid *)ne)->NumIndices = 2; // will be holded as line set.
|
||||||
|
for(size_t i = 0, i_e = (grid_alias.Vertices.size() - 1); i < i_e; i++)
|
||||||
|
{
|
||||||
|
grid_alias.CoordIdx.push_back(static_cast<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.
|
||||||
|
{
|
||||||
|
((X3DNodeElementElevationGrid *)ne)->NumIndices = 4;
|
||||||
|
for(int32_t fzi = 0, fzi_e = (zDimension - 1); fzi < fzi_e; fzi++)// rows
|
||||||
|
{
|
||||||
|
for(int32_t fxi = 0, fxi_e = (xDimension - 1); fxi < fxi_e; fxi++)// columns
|
||||||
|
{
|
||||||
|
// points direction in face.
|
||||||
|
if(ccw)
|
||||||
|
{
|
||||||
|
// CCW:
|
||||||
|
// 3 2
|
||||||
|
// 0 1
|
||||||
|
grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + fxi);
|
||||||
|
grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + (fxi + 1));
|
||||||
|
grid_alias.CoordIdx.push_back(fzi * xDimension + (fxi + 1));
|
||||||
|
grid_alias.CoordIdx.push_back(fzi * xDimension + fxi);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// CW:
|
||||||
|
// 0 1
|
||||||
|
// 3 2
|
||||||
|
grid_alias.CoordIdx.push_back(fzi * xDimension + fxi);
|
||||||
|
grid_alias.CoordIdx.push_back(fzi * xDimension + (fxi + 1));
|
||||||
|
grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + (fxi + 1));
|
||||||
|
grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + fxi);
|
||||||
|
}// if(ccw) else
|
||||||
|
|
||||||
|
grid_alias.CoordIdx.push_back(-1);
|
||||||
|
}// for(int32_t fxi = 0, fxi_e = (xDimension - 1); fxi < fxi_e; fxi++)
|
||||||
|
}// for(int32_t fzi = 0, fzi_e = (zDimension - 1); fzi < fzi_e; fzi++)
|
||||||
|
}// if((xDimension < 2) || (zDimension < 2)) else
|
||||||
|
|
||||||
|
grid_alias.ColorPerVertex = colorPerVertex;
|
||||||
|
grid_alias.NormalPerVertex = normalPerVertex;
|
||||||
|
grid_alias.CreaseAngle = creaseAngle;
|
||||||
|
grid_alias.Solid = solid;
|
||||||
|
// check for child nodes
|
||||||
|
if(!isNodeEmpty(node))
|
||||||
|
{
|
||||||
|
ParseHelper_Node_Enter(ne);
|
||||||
|
for (auto currentChildNode : node.children()) {
|
||||||
|
const std::string ¤tChildName = currentChildNode.name();
|
||||||
|
// check for X3DComposedGeometryNodes
|
||||||
|
if (currentChildName == "Color") readColor(currentChildNode);
|
||||||
|
else if (currentChildName == "ColorRGBA") readColorRGBA(currentChildNode);
|
||||||
|
else if (currentChildName == "Normal") readNormal(currentChildNode);
|
||||||
|
else if (currentChildName == "TextureCoordinate") readTextureCoordinate(currentChildNode);
|
||||||
|
// check for X3DMetadataObject
|
||||||
|
else if (!checkForMetadataNode(currentChildNode)) skipUnsupportedNode("ElevationGrid", currentChildNode);
|
||||||
|
}
|
||||||
|
ParseHelper_Node_Exit();
|
||||||
|
}// if(!mReader->isEmptyElement())
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mNodeElementCur->Children.push_back(ne);// add made object as child to current element
|
||||||
|
}// if(!mReader->isEmptyElement()) else
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
|
||||||
|
}// if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename TVector>
|
||||||
|
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++)
|
||||||
|
{
|
||||||
|
// search for first point of duplicated part.
|
||||||
|
if(pCurve[0] == pCurve[s])
|
||||||
|
{
|
||||||
|
bool found = true;
|
||||||
|
|
||||||
|
// check if tail(indexed by b2) is duplicate of head(indexed by b1).
|
||||||
|
for(size_t b1 = 1, b2 = (s + 1); b2 < cur_sz; b1++, b2++)
|
||||||
|
{
|
||||||
|
if(pCurve[b1] != pCurve[b2])
|
||||||
|
{// points not match: clear flag and break loop.
|
||||||
|
found = false;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}// for(size_t b1 = 1, b2 = (s + 1); b2 < cur_sz; b1++, b2++)
|
||||||
|
|
||||||
|
// if duplicate tail is found then drop or not it depending on flags.
|
||||||
|
if(found)
|
||||||
|
{
|
||||||
|
pCurveIsClosed = true;
|
||||||
|
if(pDropTail)
|
||||||
|
{
|
||||||
|
if(!pRemoveLastPoint) s++;// prepare value for iterator's arithmetics.
|
||||||
|
|
||||||
|
pCurve.erase(pCurve.begin() + s, pCurve.end());// remove tail
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}// if(found)
|
||||||
|
}// if(pCurve[0] == pCurve[s])
|
||||||
|
}// for(size_t s = 3, s_e = (cur_sz - 1); s < s_e; s++)
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
|
// As we even for closed spine curve last and first point in pSpine are not the same: duplicates(spine[n - 1] which are equivalent to spine[0])
|
||||||
|
// in tail are removed.
|
||||||
|
// So, last point in pSpine is a spine[n - 2]
|
||||||
|
tvec = pSpine[1] - pSpine[spine_idx_last];
|
||||||
|
}
|
||||||
|
else if(pSpine_PointIdx == 0)
|
||||||
|
{// The Y-axis used for the first point is the vector from spine[0] to spine[1]
|
||||||
|
tvec = pSpine[1] - pSpine[0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{// The Y-axis used for the last point it is the vector from spine[n-2] to spine[n-1]. In our case(see above about dropping tail) spine[n - 1] is
|
||||||
|
// the spine[0].
|
||||||
|
tvec = pSpine[spine_idx_last] - pSpine[spine_idx_last - 1];
|
||||||
|
}
|
||||||
|
}// if((pSpine_PointIdx == 0) || (pSpine_PointIdx == spine_idx_last))
|
||||||
|
else
|
||||||
|
{// For all points other than the first or last: The Y-axis for spine[i] is found by normalizing the vector defined by (spine[i+1] - spine[i-1]).
|
||||||
|
tvec = pSpine[pSpine_PointIdx + 1] - pSpine[pSpine_PointIdx - 1];
|
||||||
|
}// if((pSpine_PointIdx == 0) || (pSpine_PointIdx == spine_idx_last)) else
|
||||||
|
|
||||||
|
return tvec.Normalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
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 zero_vec(0);
|
||||||
|
const size_t spine_idx_last = pSpine.size() - 1;
|
||||||
|
|
||||||
|
aiVector3D tvec;
|
||||||
|
|
||||||
|
// at first special cases
|
||||||
|
if(pSpine.size() < 3)// spine have not enough points for vector calculations.
|
||||||
|
{
|
||||||
|
tvec.Set(0, 0, 1);
|
||||||
|
}
|
||||||
|
else if(pSpine_PointIdx == 0)// special case: first point
|
||||||
|
{
|
||||||
|
if(pSpine_Closed)// for calculating use previous point in curve s[n - 2]. In list it's a last point, because point s[n - 1] was removed as duplicate.
|
||||||
|
{
|
||||||
|
tvec = (pSpine[1] - pSpine[0]) ^ (pSpine[spine_idx_last] - pSpine[0]);
|
||||||
|
}
|
||||||
|
else // for not closed curve first and next point(s[0] and s[1]) has the same vector Z.
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
// As said: "If the Z-axis of the first point is undefined (because the spine is not closed and the first two spine segments are collinear)
|
||||||
|
// then the Z-axis for the first spine point with a defined Z-axis is used."
|
||||||
|
// Walk through spine and find Z.
|
||||||
|
for(size_t next_point = 2; (next_point <= spine_idx_last) && !found; next_point++)
|
||||||
|
{
|
||||||
|
// (pSpine[2] - pSpine[1]) ^ (pSpine[0] - pSpine[1])
|
||||||
|
tvec = (pSpine[next_point] - pSpine[next_point - 1]) ^ (pSpine[next_point - 2] - pSpine[next_point - 1]);
|
||||||
|
found = !tvec.Equal(zero_vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if entire spine are collinear then use OZ axis.
|
||||||
|
if(!found) tvec.Set(0, 0, 1);
|
||||||
|
}// if(pSpine_Closed) else
|
||||||
|
}// else if(pSpine_PointIdx == 0)
|
||||||
|
else if(pSpine_PointIdx == spine_idx_last)// special case: last point
|
||||||
|
{
|
||||||
|
if(pSpine_Closed)
|
||||||
|
{// do not forget that real last point s[n - 1] is removed as duplicated. And in this case we are calculating vector Z for point s[n - 2].
|
||||||
|
tvec = (pSpine[0] - pSpine[pSpine_PointIdx]) ^ (pSpine[pSpine_PointIdx - 1] - pSpine[pSpine_PointIdx]);
|
||||||
|
// if taken spine vectors are collinear then use previous vector Z.
|
||||||
|
if(tvec.Equal(zero_vec)) tvec = pVecZ_Prev;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{// vector Z for last point of not closed curve is previous vector Z.
|
||||||
|
tvec = pVecZ_Prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else// regular point
|
||||||
|
{
|
||||||
|
tvec = (pSpine[pSpine_PointIdx + 1] - pSpine[pSpine_PointIdx]) ^ (pSpine[pSpine_PointIdx - 1] - pSpine[pSpine_PointIdx]);
|
||||||
|
// if taken spine vectors are collinear then use previous vector Z.
|
||||||
|
if(tvec.Equal(zero_vec)) tvec = pVecZ_Prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
// After determining the Z-axis, its dot product with the Z-axis of the previous spine point is computed. If this value is negative, the Z-axis
|
||||||
|
// is flipped (multiplied by -1).
|
||||||
|
if((tvec * pVecZ_Prev) < 0) tvec = -tvec;
|
||||||
|
|
||||||
|
return tvec.Normalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
// <Extrusion
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// beginCap="true" SFBool [initializeOnly]
|
||||||
|
// ccw="true" SFBool [initializeOnly]
|
||||||
|
// convex="true" SFBool [initializeOnly]
|
||||||
|
// creaseAngle="0.0" SFloat [initializeOnly]
|
||||||
|
// crossSection="1 1 1 -1 -1 -1 -1 1 1 1" MFVec2f [initializeOnly]
|
||||||
|
// endCap="true" SFBool [initializeOnly]
|
||||||
|
// orientation="0 0 1 0" MFRotation [initializeOnly]
|
||||||
|
// scale="1 1" MFVec2f [initializeOnly]
|
||||||
|
// solid="true" SFBool [initializeOnly]
|
||||||
|
// spine="0 0 0 0 1 0" MFVec3f [initializeOnly]
|
||||||
|
// />
|
||||||
|
void X3DImporter::readExtrusion(XmlNode &node) {
|
||||||
|
std::string use, def;
|
||||||
|
bool beginCap = true;
|
||||||
|
bool ccw = true;
|
||||||
|
bool convex = true;
|
||||||
|
float creaseAngle = 0;
|
||||||
|
std::vector<aiVector2D> crossSection;
|
||||||
|
bool endCap = true;
|
||||||
|
std::vector<float> orientation;
|
||||||
|
std::vector<aiVector2D> scale;
|
||||||
|
bool solid = true;
|
||||||
|
std::vector<aiVector3D> spine;
|
||||||
|
X3DNodeElementBase* ne( nullptr );
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
XmlParser::getBoolAttribute(node, "beginCap", beginCap);
|
||||||
|
XmlParser::getBoolAttribute(node, "ccw", ccw);
|
||||||
|
XmlParser::getBoolAttribute(node, "convex", convex);
|
||||||
|
XmlParser::getFloatAttribute(node, "creaseAngle", creaseAngle);
|
||||||
|
X3DXmlHelper::getVector2DArrayAttribute(node, "crossSection", crossSection);
|
||||||
|
XmlParser::getBoolAttribute(node, "endCap", endCap);
|
||||||
|
X3DXmlHelper::getFloatArrayAttribute(node, "orientation", orientation);
|
||||||
|
X3DXmlHelper::getVector2DArrayAttribute(node, "scale", scale);
|
||||||
|
XmlParser::getBoolAttribute(node, "solid", solid);
|
||||||
|
X3DXmlHelper::getVector3DArrayAttribute(node, "spine", spine);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if(!use.empty())
|
||||||
|
{
|
||||||
|
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Extrusion, ne);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// check if default values must be assigned
|
||||||
|
//
|
||||||
|
if(spine.size() == 0)
|
||||||
|
{
|
||||||
|
spine.resize(2);
|
||||||
|
spine[0].Set(0, 0, 0), spine[1].Set(0, 1, 0);
|
||||||
|
}
|
||||||
|
else if(spine.size() == 1)
|
||||||
|
{
|
||||||
|
throw DeadlyImportError("ParseNode_Geometry3D_Extrusion. Spine must have at least two points.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(crossSection.size() == 0)
|
||||||
|
{
|
||||||
|
crossSection.resize(5);
|
||||||
|
crossSection[0].Set(1, 1), crossSection[1].Set(1, -1), crossSection[2].Set(-1, -1), crossSection[3].Set(-1, 1), crossSection[4].Set(1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
{// orientation
|
||||||
|
size_t ori_size = orientation.size() / 4;
|
||||||
|
|
||||||
|
if(ori_size < spine.size())
|
||||||
|
{
|
||||||
|
float add_ori[4];// values that will be added
|
||||||
|
|
||||||
|
if(ori_size == 1)// if "orientation" has one element(means one MFRotation with four components) then use it value for all spine points.
|
||||||
|
{
|
||||||
|
add_ori[0] = orientation[0], add_ori[1] = orientation[1], add_ori[2] = orientation[2], add_ori[3] = orientation[3];
|
||||||
|
}
|
||||||
|
else// else - use default values
|
||||||
|
{
|
||||||
|
add_ori[0] = 0, add_ori[1] = 0, add_ori[2] = 1, add_ori[3] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
orientation.reserve(spine.size() * 4);
|
||||||
|
for(size_t i = 0, i_e = (spine.size() - ori_size); i < i_e; i++)
|
||||||
|
orientation.push_back(add_ori[0]), orientation.push_back(add_ori[1]), orientation.push_back(add_ori[2]), orientation.push_back(add_ori[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(orientation.size() % 4) throw DeadlyImportError("Attribute \"orientation\" in <Extrusion> must has multiple four quantity of numbers.");
|
||||||
|
}// END: orientation
|
||||||
|
|
||||||
|
{// scale
|
||||||
|
if(scale.size() < spine.size())
|
||||||
|
{
|
||||||
|
aiVector2D add_sc;
|
||||||
|
|
||||||
|
if(scale.size() == 1)// if "scale" has one element then use it value for all spine points.
|
||||||
|
add_sc = scale[0];
|
||||||
|
else// else - use default values
|
||||||
|
add_sc.Set(1, 1);
|
||||||
|
|
||||||
|
scale.reserve(spine.size());
|
||||||
|
for(size_t i = 0, i_e = (spine.size() - scale.size()); i < i_e; i++) scale.push_back(add_sc);
|
||||||
|
}
|
||||||
|
}// END: scale
|
||||||
|
//
|
||||||
|
// create and if needed - define new geometry object.
|
||||||
|
//
|
||||||
|
ne = new X3DNodeElementIndexedSet(X3DElemType::ENET_Extrusion, mNodeElementCur);
|
||||||
|
if(!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
X3DNodeElementIndexedSet &ext_alias = *((X3DNodeElementIndexedSet *)ne); // create alias for conveience
|
||||||
|
// assign part of input data
|
||||||
|
ext_alias.CCW = ccw;
|
||||||
|
ext_alias.Convex = convex;
|
||||||
|
ext_alias.CreaseAngle = creaseAngle;
|
||||||
|
ext_alias.Solid = solid;
|
||||||
|
|
||||||
|
//
|
||||||
|
// How we done it at all?
|
||||||
|
// 1. At first we will calculate array of basises for every point in spine(look SCP in ISO-dic). Also "orientation" vector
|
||||||
|
// are applied vor every basis.
|
||||||
|
// 2. After that we can create array of point sets: which are scaled, transferred to basis of relative basis and at final translated to real position
|
||||||
|
// using relative spine point.
|
||||||
|
// 3. Next step is creating CoordIdx array(do not forget "-1" delimiter). While creating CoordIdx also created faces for begin and end caps, if
|
||||||
|
// needed. While createing CootdIdx is taking in account CCW flag.
|
||||||
|
// 4. The last step: create Vertices list.
|
||||||
|
//
|
||||||
|
bool spine_closed;// flag: true if spine curve is closed.
|
||||||
|
bool cross_closed;// flag: true if cross curve is closed.
|
||||||
|
std::vector<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.
|
||||||
|
|
||||||
|
// detect closed curves
|
||||||
|
GeometryHelper_Extrusion_CurveIsClosed(crossSection, true, true, cross_closed);// true - drop tail, true - remove duplicate end.
|
||||||
|
GeometryHelper_Extrusion_CurveIsClosed(spine, true, true, spine_closed);// true - drop tail, true - remove duplicate end.
|
||||||
|
// If both cap are requested and spine curve is closed then we can make only one cap. Because second cap will be the same surface.
|
||||||
|
if(spine_closed)
|
||||||
|
{
|
||||||
|
beginCap |= endCap;
|
||||||
|
endCap = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
{// 1. Calculate array of basises.
|
||||||
|
aiMatrix4x4 rotmat;
|
||||||
|
aiVector3D vecX(0), vecY(0), vecZ(0);
|
||||||
|
|
||||||
|
basis_arr.resize(spine.size());
|
||||||
|
for(size_t i = 0, i_e = spine.size(); i < i_e; i++)
|
||||||
|
{
|
||||||
|
aiVector3D tvec;
|
||||||
|
|
||||||
|
// get axises of basis.
|
||||||
|
vecY = GeometryHelper_Extrusion_GetNextY(i, spine, spine_closed);
|
||||||
|
vecZ = GeometryHelper_Extrusion_GetNextZ(i, spine, spine_closed, vecZ);
|
||||||
|
vecX = (vecY ^ vecZ).Normalize();
|
||||||
|
// get rotation matrix and apply "orientation" to basis
|
||||||
|
aiMatrix4x4::Rotation(orientation[i * 4 + 3], aiVector3D(orientation[i * 4], orientation[i * 4 + 1], orientation[i * 4 + 2]), rotmat);
|
||||||
|
tvec = vecX, tvec *= rotmat, basis_arr[i].a1 = tvec.x, basis_arr[i].a2 = tvec.y, basis_arr[i].a3 = tvec.z;
|
||||||
|
tvec = vecY, tvec *= rotmat, basis_arr[i].b1 = tvec.x, basis_arr[i].b2 = tvec.y, basis_arr[i].b3 = tvec.z;
|
||||||
|
tvec = vecZ, tvec *= rotmat, basis_arr[i].c1 = tvec.x, basis_arr[i].c2 = tvec.y, basis_arr[i].c3 = tvec.z;
|
||||||
|
}// for(size_t i = 0, i_e = spine.size(); i < i_e; i++)
|
||||||
|
}// END: 1. Calculate array of basises
|
||||||
|
|
||||||
|
{// 2. Create array of point sets.
|
||||||
|
aiMatrix4x4 scmat;
|
||||||
|
std::vector<aiVector3D> tcross(crossSection.size());
|
||||||
|
|
||||||
|
pointset_arr.resize(spine.size());
|
||||||
|
for(size_t spi = 0, spi_e = spine.size(); spi < spi_e; spi++)
|
||||||
|
{
|
||||||
|
aiVector3D tc23vec;
|
||||||
|
|
||||||
|
tc23vec.Set(scale[spi].x, 0, scale[spi].y);
|
||||||
|
aiMatrix4x4::Scaling(tc23vec, scmat);
|
||||||
|
for(size_t cri = 0, cri_e = crossSection.size(); cri < cri_e; cri++)
|
||||||
|
{
|
||||||
|
aiVector3D tvecX, tvecY, tvecZ;
|
||||||
|
|
||||||
|
tc23vec.Set(crossSection[cri].x, 0, crossSection[cri].y);
|
||||||
|
// apply scaling to point
|
||||||
|
tcross[cri] = scmat * tc23vec;
|
||||||
|
//
|
||||||
|
// transfer point to new basis
|
||||||
|
// calculate coordinate in new basis
|
||||||
|
tvecX.Set(basis_arr[spi].a1, basis_arr[spi].a2, basis_arr[spi].a3), tvecX *= tcross[cri].x;
|
||||||
|
tvecY.Set(basis_arr[spi].b1, basis_arr[spi].b2, basis_arr[spi].b3), tvecY *= tcross[cri].y;
|
||||||
|
tvecZ.Set(basis_arr[spi].c1, basis_arr[spi].c2, basis_arr[spi].c3), tvecZ *= tcross[cri].z;
|
||||||
|
// apply new coordinates and translate it to spine point.
|
||||||
|
tcross[cri] = tvecX + tvecY + tvecZ + spine[spi];
|
||||||
|
}// for(size_t cri = 0, cri_e = crossSection.size(); cri < cri_e; i++)
|
||||||
|
|
||||||
|
pointset_arr[spi] = tcross;// store transferred point set
|
||||||
|
}// for(size_t spi = 0, spi_e = spine.size(); spi < spi_e; i++)
|
||||||
|
}// END: 2. Create array of point sets.
|
||||||
|
|
||||||
|
{// 3. Create CoordIdx.
|
||||||
|
// add caps if needed
|
||||||
|
if(beginCap)
|
||||||
|
{
|
||||||
|
// add cap as polygon. vertices of cap are places at begin, so just add numbers from zero.
|
||||||
|
for(size_t i = 0, i_e = crossSection.size(); i < i_e; i++) ext_alias.CoordIndex.push_back(static_cast<int32_t>(i));
|
||||||
|
|
||||||
|
// add delimiter
|
||||||
|
ext_alias.CoordIndex.push_back(-1);
|
||||||
|
}// if(beginCap)
|
||||||
|
|
||||||
|
if(endCap)
|
||||||
|
{
|
||||||
|
// add cap as polygon. vertices of cap are places at end, as for beginCap use just sequence of numbers but with offset.
|
||||||
|
size_t beg = (pointset_arr.size() - 1) * crossSection.size();
|
||||||
|
|
||||||
|
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++)
|
||||||
|
{
|
||||||
|
const size_t cr_sz = crossSection.size();
|
||||||
|
const size_t cr_last = crossSection.size() - 1;
|
||||||
|
|
||||||
|
size_t right_col;// hold index basis for points of quad placed in right column;
|
||||||
|
|
||||||
|
if(spi != spi_e)
|
||||||
|
right_col = spi + 1;
|
||||||
|
else if(spine_closed)// if spine curve is closed then one more quad is needed: between first and last points of curve.
|
||||||
|
right_col = 0;
|
||||||
|
else
|
||||||
|
break;// if spine curve is not closed then break the loop, because spi is out of range for that type of spine.
|
||||||
|
|
||||||
|
for(size_t cri = 0; cri < cr_sz; cri++)
|
||||||
|
{
|
||||||
|
if(cri != cr_last)
|
||||||
|
{
|
||||||
|
MACRO_FACE_ADD_QUAD(ccw, ext_alias.CoordIndex,
|
||||||
|
static_cast<int32_t>(spi * cr_sz + cri),
|
||||||
|
static_cast<int32_t>(right_col * cr_sz + cri),
|
||||||
|
static_cast<int32_t>(right_col * cr_sz + cri + 1),
|
||||||
|
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.
|
||||||
|
{
|
||||||
|
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),
|
||||||
|
static_cast<int32_t>(right_col * cr_sz + 0),
|
||||||
|
static_cast<int32_t>(spi * cr_sz + 0));
|
||||||
|
// add delimiter
|
||||||
|
ext_alias.CoordIndex.push_back(-1);
|
||||||
|
}
|
||||||
|
}// for(size_t cri = 0; cri < cr_sz; cri++)
|
||||||
|
}// for(size_t spi = 0, spi_e = (spine.size() - 2); spi < spi_e; spi++)
|
||||||
|
}// END: 3. Create CoordIdx.
|
||||||
|
|
||||||
|
{// 4. Create vertices list.
|
||||||
|
// just copy all vertices
|
||||||
|
for(size_t spi = 0, spi_e = spine.size(); spi < spi_e; spi++)
|
||||||
|
{
|
||||||
|
for(size_t cri = 0, cri_e = crossSection.size(); cri < cri_e; cri++)
|
||||||
|
{
|
||||||
|
ext_alias.Vertices.push_back(pointset_arr[spi][cri]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}// END: 4. Create vertices list.
|
||||||
|
//PrintVectorSet("Ext. CoordIdx", ext_alias.CoordIndex);
|
||||||
|
//PrintVectorSet("Ext. Vertices", ext_alias.Vertices);
|
||||||
|
// check for child nodes
|
||||||
|
if(!isNodeEmpty(node))
|
||||||
|
childrenReadMetadata(node, ne, "Extrusion");
|
||||||
|
else
|
||||||
|
mNodeElementCur->Children.push_back(ne);// add made object as child to current element
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
|
||||||
|
}// if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
// <IndexedFaceSet
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// ccw="true" SFBool [initializeOnly]
|
||||||
|
// colorIndex="" MFInt32 [initializeOnly]
|
||||||
|
// colorPerVertex="true" SFBool [initializeOnly]
|
||||||
|
// convex="true" SFBool [initializeOnly]
|
||||||
|
// coordIndex="" MFInt32 [initializeOnly]
|
||||||
|
// creaseAngle="0" SFFloat [initializeOnly]
|
||||||
|
// normalIndex="" MFInt32 [initializeOnly]
|
||||||
|
// normalPerVertex="true" SFBool [initializeOnly]
|
||||||
|
// solid="true" SFBool [initializeOnly]
|
||||||
|
// texCoordIndex="" MFInt32 [initializeOnly]
|
||||||
|
// >
|
||||||
|
// <!-- ComposedGeometryContentModel -->
|
||||||
|
// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
|
||||||
|
// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
|
||||||
|
// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
|
||||||
|
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
||||||
|
// </IndexedFaceSet>
|
||||||
|
void X3DImporter::readIndexedFaceSet(XmlNode &node) {
|
||||||
|
std::string use, def;
|
||||||
|
bool ccw = true;
|
||||||
|
std::vector<int32_t> colorIndex;
|
||||||
|
bool colorPerVertex = true;
|
||||||
|
bool convex = true;
|
||||||
|
std::vector<int32_t> coordIndex;
|
||||||
|
float creaseAngle = 0;
|
||||||
|
std::vector<int32_t> normalIndex;
|
||||||
|
bool normalPerVertex = true;
|
||||||
|
bool solid = true;
|
||||||
|
std::vector<int32_t> texCoordIndex;
|
||||||
|
X3DNodeElementBase* ne( nullptr );
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
XmlParser::getBoolAttribute(node, "ccw", ccw);
|
||||||
|
X3DXmlHelper::getInt32ArrayAttribute(node, "colorIndex", colorIndex);
|
||||||
|
XmlParser::getBoolAttribute(node, "colorPerVertex", colorPerVertex);
|
||||||
|
XmlParser::getBoolAttribute(node, "convex", convex);
|
||||||
|
X3DXmlHelper::getInt32ArrayAttribute(node, "coordIndex", coordIndex);
|
||||||
|
XmlParser::getFloatAttribute(node, "creaseAngle", creaseAngle);
|
||||||
|
X3DXmlHelper::getInt32ArrayAttribute(node, "normalIndex", normalIndex);
|
||||||
|
XmlParser::getBoolAttribute(node, "normalPerVertex", normalPerVertex);
|
||||||
|
XmlParser::getBoolAttribute(node, "solid", solid);
|
||||||
|
X3DXmlHelper::getInt32ArrayAttribute(node, "texCoordIndex", texCoordIndex);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if(!use.empty())
|
||||||
|
{
|
||||||
|
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedFaceSet, ne);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// check data
|
||||||
|
if(coordIndex.size() == 0) throw DeadlyImportError("IndexedFaceSet must contain not empty \"coordIndex\" attribute.");
|
||||||
|
|
||||||
|
// create and if needed - define new geometry object.
|
||||||
|
ne = new X3DNodeElementIndexedSet(X3DElemType::ENET_IndexedFaceSet, mNodeElementCur);
|
||||||
|
if(!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
X3DNodeElementIndexedSet &ne_alias = *((X3DNodeElementIndexedSet *)ne);
|
||||||
|
|
||||||
|
ne_alias.CCW = ccw;
|
||||||
|
ne_alias.ColorIndex = colorIndex;
|
||||||
|
ne_alias.ColorPerVertex = colorPerVertex;
|
||||||
|
ne_alias.Convex = convex;
|
||||||
|
ne_alias.CoordIndex = coordIndex;
|
||||||
|
ne_alias.CreaseAngle = creaseAngle;
|
||||||
|
ne_alias.NormalIndex = normalIndex;
|
||||||
|
ne_alias.NormalPerVertex = normalPerVertex;
|
||||||
|
ne_alias.Solid = solid;
|
||||||
|
ne_alias.TexCoordIndex = texCoordIndex;
|
||||||
|
// check for child nodes
|
||||||
|
if(!isNodeEmpty(node))
|
||||||
|
{
|
||||||
|
ParseHelper_Node_Enter(ne);
|
||||||
|
for (auto currentChildNode : node.children()) {
|
||||||
|
const std::string ¤tChildName = currentChildNode.name();
|
||||||
|
// check for X3DComposedGeometryNodes
|
||||||
|
if (currentChildName == "Color") readColor(currentChildNode);
|
||||||
|
else if (currentChildName == "ColorRGBA") readColorRGBA(currentChildNode);
|
||||||
|
else if (currentChildName == "Coordinate") readCoordinate(currentChildNode);
|
||||||
|
else if (currentChildName == "Normal") readNormal(currentChildNode);
|
||||||
|
else if (currentChildName == "TextureCoordinate") readTextureCoordinate(currentChildNode);
|
||||||
|
// check for X3DMetadataObject
|
||||||
|
else if (!checkForMetadataNode(currentChildNode)) skipUnsupportedNode("IndexedFaceSet", currentChildNode);
|
||||||
|
}
|
||||||
|
ParseHelper_Node_Exit();
|
||||||
|
}// if(!isNodeEmpty(node))
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mNodeElementCur->Children.push_back(ne);// add made object as child to current element
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
|
||||||
|
}// if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
// <Sphere
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// radius="1" SFloat [initializeOnly]
|
||||||
|
// solid="true" SFBool [initializeOnly]
|
||||||
|
// />
|
||||||
|
void X3DImporter::readSphere(XmlNode &node) {
|
||||||
|
std::string use, def;
|
||||||
|
ai_real radius = 1;
|
||||||
|
bool solid = true;
|
||||||
|
X3DNodeElementBase* ne( nullptr );
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
XmlParser::getFloatAttribute(node, "radius", radius);
|
||||||
|
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
|
||||||
|
{
|
||||||
|
const unsigned int tess = 3;///TODO: IME tessellation factor through ai_property
|
||||||
|
|
||||||
|
std::vector<aiVector3D> tlist;
|
||||||
|
|
||||||
|
// create and if needed - define new geometry object.
|
||||||
|
ne = new X3DNodeElementGeometry3D(X3DElemType::ENET_Sphere, mNodeElementCur);
|
||||||
|
if(!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
StandardShapes::MakeSphere(tess, tlist);
|
||||||
|
// copy data from temp array and apply scale
|
||||||
|
for(std::vector<aiVector3D>::iterator it = tlist.begin(); it != tlist.end(); ++it)
|
||||||
|
{
|
||||||
|
((X3DNodeElementGeometry3D *)ne)->Vertices.push_back(*it * radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
((X3DNodeElementGeometry3D *)ne)->Solid = solid;
|
||||||
|
((X3DNodeElementGeometry3D *)ne)->NumIndices = 3;
|
||||||
|
// check for X3DMetadataObject childs.
|
||||||
|
if(!isNodeEmpty(node))
|
||||||
|
childrenReadMetadata(node, ne, "Sphere");
|
||||||
|
else
|
||||||
|
mNodeElementCur->Children.push_back(ne);// add made object as child to current element
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
|
||||||
|
}// if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
}// namespace Assimp
|
||||||
|
|
||||||
|
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
@ -0,0 +1,273 @@
|
||||||
|
/*
|
||||||
|
Open Asset Import Library (assimp)
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2019, assimp team
|
||||||
|
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
with or without modification, are permitted provided that the
|
||||||
|
following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer in the documentation and/or other
|
||||||
|
materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of the assimp team, nor the names of its
|
||||||
|
contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior
|
||||||
|
written permission of the assimp team.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
/// \file X3DImporter_Group.cpp
|
||||||
|
/// \brief Parsing data from nodes of "Grouping" set of X3D.
|
||||||
|
/// date 2015-2016
|
||||||
|
/// author smal.root@gmail.com
|
||||||
|
|
||||||
|
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||||
|
|
||||||
|
#include "X3DImporter.hpp"
|
||||||
|
#include "X3DImporter_Macro.hpp"
|
||||||
|
#include "X3DXmlHelper.h"
|
||||||
|
|
||||||
|
namespace Assimp {
|
||||||
|
|
||||||
|
// <Group
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// bboxCenter="0 0 0" SFVec3f [initializeOnly]
|
||||||
|
// bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
|
||||||
|
// >
|
||||||
|
// <\!-- ChildContentModel -->
|
||||||
|
// ChildContentModel is the child-node content model corresponding to X3DChildNode, combining all profiles. ChildContentModel can contain most nodes,
|
||||||
|
// other Grouping nodes, Prototype declarations and ProtoInstances in any order and any combination. When the assigned profile is less than Full, the
|
||||||
|
// precise palette of legal nodes that are available depends on assigned profile and components.
|
||||||
|
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
||||||
|
// </Group>
|
||||||
|
// A Group node contains children nodes without introducing a new transformation. It is equivalent to a Transform node containing an identity transform.
|
||||||
|
void X3DImporter::startReadGroup(XmlNode &node) {
|
||||||
|
std::string def, use;
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty()) {
|
||||||
|
X3DNodeElementBase *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.
|
||||||
|
if (!def.empty()) mNodeElementCur->ID = def;
|
||||||
|
// in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
|
||||||
|
|
||||||
|
// for empty element exit from node in that place
|
||||||
|
if (isNodeEmpty(node)) ParseHelper_Node_Exit();
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
void X3DImporter::endReadGroup() {
|
||||||
|
ParseHelper_Node_Exit(); // go up in scene graph
|
||||||
|
}
|
||||||
|
|
||||||
|
// <StaticGroup
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// bboxCenter="0 0 0" SFVec3f [initializeOnly]
|
||||||
|
// bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
|
||||||
|
// >
|
||||||
|
// <\!-- ChildContentModel -->
|
||||||
|
// ChildContentModel is the child-node content model corresponding to X3DChildNode, combining all profiles. ChildContentModel can contain most nodes,
|
||||||
|
// other Grouping nodes, Prototype declarations and ProtoInstances in any order and any combination. When the assigned profile is less than Full, the
|
||||||
|
// precise palette of legal nodes that are available depends on assigned profile and components.
|
||||||
|
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
||||||
|
// </StaticGroup>
|
||||||
|
// The StaticGroup node contains children nodes which cannot be modified. StaticGroup children are guaranteed to not change, send events, receive events or
|
||||||
|
// contain any USE references outside the StaticGroup.
|
||||||
|
void X3DImporter::startReadStaticGroup(XmlNode &node) {
|
||||||
|
std::string def, use;
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty()) {
|
||||||
|
X3DNodeElementBase *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.
|
||||||
|
if (!def.empty()) mNodeElementCur->ID = def;
|
||||||
|
// in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
|
||||||
|
|
||||||
|
// for empty element exit from node in that place
|
||||||
|
if (isNodeEmpty(node)) ParseHelper_Node_Exit();
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
void X3DImporter::endReadStaticGroup() {
|
||||||
|
ParseHelper_Node_Exit(); // go up in scene graph
|
||||||
|
}
|
||||||
|
|
||||||
|
// <Switch
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// bboxCenter="0 0 0" SFVec3f [initializeOnly]
|
||||||
|
// bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
|
||||||
|
// whichChoice="-1" SFInt32 [inputOutput]
|
||||||
|
// >
|
||||||
|
// <\!-- ChildContentModel -->
|
||||||
|
// ChildContentModel is the child-node content model corresponding to X3DChildNode, combining all profiles. ChildContentModel can contain most nodes,
|
||||||
|
// other Grouping nodes, Prototype declarations and ProtoInstances in any order and any combination. When the assigned profile is less than Full, the
|
||||||
|
// precise palette of legal nodes that are available depends on assigned profile and components.
|
||||||
|
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
||||||
|
// </Switch>
|
||||||
|
// The Switch grouping node traverses zero or one of the nodes specified in the children field. The whichChoice field specifies the index of the child
|
||||||
|
// to traverse, with the first child having index 0. If whichChoice is less than zero or greater than the number of nodes in the children field, nothing
|
||||||
|
// is chosen.
|
||||||
|
void X3DImporter::startReadSwitch(XmlNode &node) {
|
||||||
|
std::string def, use;
|
||||||
|
int32_t whichChoice = -1;
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
XmlParser::getIntAttribute(node, "whichChoice", whichChoice);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty()) {
|
||||||
|
X3DNodeElementBase *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.
|
||||||
|
if (!def.empty()) mNodeElementCur->ID = def;
|
||||||
|
|
||||||
|
// also set values specific to this type of group
|
||||||
|
((X3DNodeElementGroup *)mNodeElementCur)->UseChoice = true;
|
||||||
|
((X3DNodeElementGroup *)mNodeElementCur)->Choice = whichChoice;
|
||||||
|
// in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
|
||||||
|
|
||||||
|
// for empty element exit from node in that place
|
||||||
|
if (isNodeEmpty(node)) ParseHelper_Node_Exit();
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
void X3DImporter::endReadSwitch() {
|
||||||
|
// just exit from node. Defined choice will be accepted at postprocessing stage.
|
||||||
|
ParseHelper_Node_Exit(); // go up in scene graph
|
||||||
|
}
|
||||||
|
|
||||||
|
// <Transform
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// bboxCenter="0 0 0" SFVec3f [initializeOnly]
|
||||||
|
// bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
|
||||||
|
// center="0 0 0" SFVec3f [inputOutput]
|
||||||
|
// rotation="0 0 1 0" SFRotation [inputOutput]
|
||||||
|
// scale="1 1 1" SFVec3f [inputOutput]
|
||||||
|
// scaleOrientation="0 0 1 0" SFRotation [inputOutput]
|
||||||
|
// translation="0 0 0" SFVec3f [inputOutput]
|
||||||
|
// >
|
||||||
|
// <\!-- ChildContentModel -->
|
||||||
|
// ChildContentModel is the child-node content model corresponding to X3DChildNode, combining all profiles. ChildContentModel can contain most nodes,
|
||||||
|
// other Grouping nodes, Prototype declarations and ProtoInstances in any order and any combination. When the assigned profile is less than Full, the
|
||||||
|
// precise palette of legal nodes that are available depends on assigned profile and components.
|
||||||
|
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
||||||
|
// </Transform>
|
||||||
|
// The Transform node is a grouping node that defines a coordinate system for its children that is relative to the coordinate systems of its ancestors.
|
||||||
|
// Given a 3-dimensional point P and Transform node, P is transformed into point P' in its parent's coordinate system by a series of intermediate
|
||||||
|
// transformations. In matrix transformation notation, where C (center), SR (scaleOrientation), T (translation), R (rotation), and S (scale) are the
|
||||||
|
// equivalent transformation matrices,
|
||||||
|
// P' = T * C * R * SR * S * -SR * -C * P
|
||||||
|
void X3DImporter::startReadTransform(XmlNode &node) {
|
||||||
|
aiVector3D center(0, 0, 0);
|
||||||
|
float rotation[4] = { 0, 0, 1, 0 };
|
||||||
|
aiVector3D scale(1, 1, 1); // A value of zero indicates that any child geometry shall not be displayed
|
||||||
|
float scale_orientation[4] = { 0, 0, 1, 0 };
|
||||||
|
aiVector3D translation(0, 0, 0);
|
||||||
|
aiMatrix4x4 matr, tmatr;
|
||||||
|
std::string use, def;
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
X3DXmlHelper::getVector3DAttribute(node, "center", center);
|
||||||
|
X3DXmlHelper::getVector3DAttribute(node, "scale", scale);
|
||||||
|
X3DXmlHelper::getVector3DAttribute(node, "translation", translation);
|
||||||
|
std::vector<float> tvec;
|
||||||
|
if (X3DXmlHelper::getFloatArrayAttribute(node, "rotation", tvec)) {
|
||||||
|
if (tvec.size() != 4) throw DeadlyImportError("<Transform>: rotation vector must have 4 elements.");
|
||||||
|
memcpy(rotation, tvec.data(), sizeof(rotation));
|
||||||
|
tvec.clear();
|
||||||
|
}
|
||||||
|
if (X3DXmlHelper::getFloatArrayAttribute(node, "scaleOrientation", tvec)) {
|
||||||
|
if (tvec.size() != 4) throw DeadlyImportError("<Transform>: scaleOrientation vector must have 4 elements.");
|
||||||
|
memcpy(scale_orientation, tvec.data(), sizeof(scale_orientation));
|
||||||
|
tvec.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty()) {
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
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.
|
||||||
|
if (!def.empty()) {
|
||||||
|
mNodeElementCur->ID = def;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// also set values specific to this type of group
|
||||||
|
//
|
||||||
|
// calculate transformation matrix
|
||||||
|
aiMatrix4x4::Translation(translation, matr); // T
|
||||||
|
aiMatrix4x4::Translation(center, tmatr); // C
|
||||||
|
matr *= tmatr;
|
||||||
|
aiMatrix4x4::Rotation(rotation[3], aiVector3D(rotation[0], rotation[1], rotation[2]), tmatr); // R
|
||||||
|
matr *= tmatr;
|
||||||
|
aiMatrix4x4::Rotation(scale_orientation[3], aiVector3D(scale_orientation[0], scale_orientation[1], scale_orientation[2]), tmatr); // SR
|
||||||
|
matr *= tmatr;
|
||||||
|
aiMatrix4x4::Scaling(scale, tmatr); // S
|
||||||
|
matr *= tmatr;
|
||||||
|
aiMatrix4x4::Rotation(-scale_orientation[3], aiVector3D(scale_orientation[0], scale_orientation[1], scale_orientation[2]), tmatr); // -SR
|
||||||
|
matr *= tmatr;
|
||||||
|
aiMatrix4x4::Translation(-center, tmatr); // -C
|
||||||
|
matr *= tmatr;
|
||||||
|
// and assign it
|
||||||
|
((X3DNodeElementGroup *)mNodeElementCur)->Transformation = matr;
|
||||||
|
// in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
|
||||||
|
|
||||||
|
// for empty element exit from node in that place
|
||||||
|
if (isNodeEmpty(node)) {
|
||||||
|
ParseHelper_Node_Exit();
|
||||||
|
}
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
void X3DImporter::endReadTransform() {
|
||||||
|
ParseHelper_Node_Exit(); // go up in scene graph
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Assimp
|
||||||
|
|
||||||
|
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
@ -0,0 +1,270 @@
|
||||||
|
/*
|
||||||
|
Open Asset Import Library (assimp)
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2019, assimp team
|
||||||
|
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
with or without modification, are permitted provided that the
|
||||||
|
following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer in the documentation and/or other
|
||||||
|
materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of the assimp team, nor the names of its
|
||||||
|
contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior
|
||||||
|
written permission of the assimp team.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
/// \file X3DImporter_Light.cpp
|
||||||
|
/// \brief Parsing data from nodes of "Lighting" set of X3D.
|
||||||
|
/// date 2015-2016
|
||||||
|
/// author smal.root@gmail.com
|
||||||
|
|
||||||
|
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||||
|
|
||||||
|
#include "X3DImporter.hpp"
|
||||||
|
#include "X3DImporter_Macro.hpp"
|
||||||
|
#include "X3DXmlHelper.h"
|
||||||
|
#include <assimp/StringUtils.h>
|
||||||
|
|
||||||
|
namespace Assimp {
|
||||||
|
|
||||||
|
// <DirectionalLight
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// ambientIntensity="0" SFFloat [inputOutput]
|
||||||
|
// color="1 1 1" SFColor [inputOutput]
|
||||||
|
// direction="0 0 -1" SFVec3f [inputOutput]
|
||||||
|
// global="false" SFBool [inputOutput]
|
||||||
|
// intensity="1" SFFloat [inputOutput]
|
||||||
|
// on="true" SFBool [inputOutput]
|
||||||
|
// />
|
||||||
|
void X3DImporter::readDirectionalLight(XmlNode &node) {
|
||||||
|
std::string def, use;
|
||||||
|
float ambientIntensity = 0;
|
||||||
|
aiColor3D color(1, 1, 1);
|
||||||
|
aiVector3D direction(0, 0, -1);
|
||||||
|
bool global = false;
|
||||||
|
float intensity = 1;
|
||||||
|
bool on = true;
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
XmlParser::getFloatAttribute(node, "ambientIntensity", ambientIntensity);
|
||||||
|
X3DXmlHelper::getColor3DAttribute(node, "color", color);
|
||||||
|
X3DXmlHelper::getVector3DAttribute(node, "direction", direction);
|
||||||
|
XmlParser::getBoolAttribute(node, "global", global);
|
||||||
|
XmlParser::getFloatAttribute(node, "intensity", intensity);
|
||||||
|
XmlParser::getBoolAttribute(node, "on", on);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty()) {
|
||||||
|
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_DirectionalLight, ne);
|
||||||
|
} else {
|
||||||
|
if (on) {
|
||||||
|
// create and if needed - define new geometry object.
|
||||||
|
ne = new X3DNodeElementLight(X3DElemType::ENET_DirectionalLight, mNodeElementCur);
|
||||||
|
if (!def.empty())
|
||||||
|
ne->ID = def;
|
||||||
|
else
|
||||||
|
ne->ID = "DirectionalLight_" + ai_to_string((size_t)ne); // make random name
|
||||||
|
|
||||||
|
((X3DNodeElementLight *)ne)->AmbientIntensity = ambientIntensity;
|
||||||
|
((X3DNodeElementLight *)ne)->Color = color;
|
||||||
|
((X3DNodeElementLight *)ne)->Direction = direction;
|
||||||
|
((X3DNodeElementLight *)ne)->Global = global;
|
||||||
|
((X3DNodeElementLight *)ne)->Intensity = intensity;
|
||||||
|
// Assimp want a node with name similar to a light. "Why? I don't no." )
|
||||||
|
ParseHelper_Group_Begin(false);
|
||||||
|
|
||||||
|
mNodeElementCur->ID = ne->ID; // assign name to node and return to light element.
|
||||||
|
ParseHelper_Node_Exit();
|
||||||
|
// check for child nodes
|
||||||
|
if (!isNodeEmpty(node))
|
||||||
|
childrenReadMetadata(node, ne, "DirectionalLight");
|
||||||
|
else
|
||||||
|
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||||
|
} // if(on)
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
// <PointLight
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// ambientIntensity="0" SFFloat [inputOutput]
|
||||||
|
// attenuation="1 0 0" SFVec3f [inputOutput]
|
||||||
|
// color="1 1 1" SFColor [inputOutput]
|
||||||
|
// global="true" SFBool [inputOutput]
|
||||||
|
// intensity="1" SFFloat [inputOutput]
|
||||||
|
// location="0 0 0" SFVec3f [inputOutput]
|
||||||
|
// on="true" SFBool [inputOutput]
|
||||||
|
// radius="100" SFFloat [inputOutput]
|
||||||
|
// />
|
||||||
|
void X3DImporter::readPointLight(XmlNode &node) {
|
||||||
|
std::string def, use;
|
||||||
|
float ambientIntensity = 0;
|
||||||
|
aiVector3D attenuation(1, 0, 0);
|
||||||
|
aiColor3D color(1, 1, 1);
|
||||||
|
bool global = true;
|
||||||
|
float intensity = 1;
|
||||||
|
aiVector3D location(0, 0, 0);
|
||||||
|
bool on = true;
|
||||||
|
float radius = 100;
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
XmlParser::getFloatAttribute(node, "ambientIntensity", ambientIntensity);
|
||||||
|
X3DXmlHelper::getVector3DAttribute(node, "attenuation", attenuation);
|
||||||
|
X3DXmlHelper::getColor3DAttribute(node, "color", color);
|
||||||
|
XmlParser::getBoolAttribute(node, "global", global);
|
||||||
|
XmlParser::getFloatAttribute(node, "intensity", intensity);
|
||||||
|
X3DXmlHelper::getVector3DAttribute(node, "location", location);
|
||||||
|
XmlParser::getBoolAttribute(node, "on", on);
|
||||||
|
XmlParser::getFloatAttribute(node, "radius", radius);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty()) {
|
||||||
|
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_PointLight, ne);
|
||||||
|
} else {
|
||||||
|
if (on) {
|
||||||
|
// create and if needed - define new geometry object.
|
||||||
|
ne = new X3DNodeElementLight(X3DElemType::ENET_PointLight, mNodeElementCur);
|
||||||
|
if (!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
((X3DNodeElementLight *)ne)->AmbientIntensity = ambientIntensity;
|
||||||
|
((X3DNodeElementLight *)ne)->Attenuation = attenuation;
|
||||||
|
((X3DNodeElementLight *)ne)->Color = color;
|
||||||
|
((X3DNodeElementLight *)ne)->Global = global;
|
||||||
|
((X3DNodeElementLight *)ne)->Intensity = intensity;
|
||||||
|
((X3DNodeElementLight *)ne)->Location = location;
|
||||||
|
((X3DNodeElementLight *)ne)->Radius = radius;
|
||||||
|
// Assimp want a node with name similar to a light. "Why? I don't no." )
|
||||||
|
ParseHelper_Group_Begin(false);
|
||||||
|
// make random name
|
||||||
|
if (ne->ID.empty()) ne->ID = "PointLight_" + ai_to_string((size_t)ne);
|
||||||
|
|
||||||
|
mNodeElementCur->ID = ne->ID; // assign name to node and return to light element.
|
||||||
|
ParseHelper_Node_Exit();
|
||||||
|
// check for child nodes
|
||||||
|
if (!isNodeEmpty(node))
|
||||||
|
childrenReadMetadata(node, ne, "PointLight");
|
||||||
|
else
|
||||||
|
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||||
|
} // if(on)
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
// <SpotLight
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// ambientIntensity="0" SFFloat [inputOutput]
|
||||||
|
// attenuation="1 0 0" SFVec3f [inputOutput]
|
||||||
|
// beamWidth="0.7854" SFFloat [inputOutput]
|
||||||
|
// color="1 1 1" SFColor [inputOutput]
|
||||||
|
// cutOffAngle="1.570796" SFFloat [inputOutput]
|
||||||
|
// direction="0 0 -1" SFVec3f [inputOutput]
|
||||||
|
// global="true" SFBool [inputOutput]
|
||||||
|
// intensity="1" SFFloat [inputOutput]
|
||||||
|
// location="0 0 0" SFVec3f [inputOutput]
|
||||||
|
// on="true" SFBool [inputOutput]
|
||||||
|
// radius="100" SFFloat [inputOutput]
|
||||||
|
// />
|
||||||
|
void X3DImporter::readSpotLight(XmlNode &node) {
|
||||||
|
std::string def, use;
|
||||||
|
float ambientIntensity = 0;
|
||||||
|
aiVector3D attenuation(1, 0, 0);
|
||||||
|
float beamWidth = 0.7854f;
|
||||||
|
aiColor3D color(1, 1, 1);
|
||||||
|
float cutOffAngle = 1.570796f;
|
||||||
|
aiVector3D direction(0, 0, -1);
|
||||||
|
bool global = true;
|
||||||
|
float intensity = 1;
|
||||||
|
aiVector3D location(0, 0, 0);
|
||||||
|
bool on = true;
|
||||||
|
float radius = 100;
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
XmlParser::getFloatAttribute(node, "ambientIntensity", ambientIntensity);
|
||||||
|
X3DXmlHelper::getVector3DAttribute(node, "attenuation", attenuation);
|
||||||
|
XmlParser::getFloatAttribute(node, "beamWidth", beamWidth);
|
||||||
|
X3DXmlHelper::getColor3DAttribute(node, "color", color);
|
||||||
|
XmlParser::getFloatAttribute(node, "cutOffAngle", cutOffAngle);
|
||||||
|
X3DXmlHelper::getVector3DAttribute(node, "direction", direction);
|
||||||
|
XmlParser::getBoolAttribute(node, "global", global);
|
||||||
|
XmlParser::getFloatAttribute(node, "intensity", intensity);
|
||||||
|
X3DXmlHelper::getVector3DAttribute(node, "location", location);
|
||||||
|
XmlParser::getBoolAttribute(node, "on", on);
|
||||||
|
XmlParser::getFloatAttribute(node, "radius", radius);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty()) {
|
||||||
|
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_SpotLight, ne);
|
||||||
|
} else {
|
||||||
|
if (on) {
|
||||||
|
// create and if needed - define new geometry object.
|
||||||
|
ne = new X3DNodeElementLight(X3DElemType::ENET_SpotLight, mNodeElementCur);
|
||||||
|
if (!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
if (beamWidth > cutOffAngle) beamWidth = cutOffAngle;
|
||||||
|
|
||||||
|
((X3DNodeElementLight *)ne)->AmbientIntensity = ambientIntensity;
|
||||||
|
((X3DNodeElementLight *)ne)->Attenuation = attenuation;
|
||||||
|
((X3DNodeElementLight *)ne)->BeamWidth = beamWidth;
|
||||||
|
((X3DNodeElementLight *)ne)->Color = color;
|
||||||
|
((X3DNodeElementLight *)ne)->CutOffAngle = cutOffAngle;
|
||||||
|
((X3DNodeElementLight *)ne)->Direction = direction;
|
||||||
|
((X3DNodeElementLight *)ne)->Global = global;
|
||||||
|
((X3DNodeElementLight *)ne)->Intensity = intensity;
|
||||||
|
((X3DNodeElementLight *)ne)->Location = location;
|
||||||
|
((X3DNodeElementLight *)ne)->Radius = radius;
|
||||||
|
|
||||||
|
// Assimp want a node with name similar to a light. "Why? I don't no." )
|
||||||
|
ParseHelper_Group_Begin(false);
|
||||||
|
// make random name
|
||||||
|
if (ne->ID.empty()) ne->ID = "SpotLight_" + ai_to_string((size_t)ne);
|
||||||
|
|
||||||
|
mNodeElementCur->ID = ne->ID; // assign name to node and return to light element.
|
||||||
|
ParseHelper_Node_Exit();
|
||||||
|
// check for child nodes
|
||||||
|
if (!isNodeEmpty(node))
|
||||||
|
childrenReadMetadata(node, ne, "SpotLight");
|
||||||
|
else
|
||||||
|
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||||
|
} // if(on)
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Assimp
|
||||||
|
|
||||||
|
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
@ -0,0 +1,110 @@
|
||||||
|
/*
|
||||||
|
Open Asset Import Library (assimp)
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2019, assimp team
|
||||||
|
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
with or without modification, are permitted provided that the
|
||||||
|
following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer in the documentation and/or other
|
||||||
|
materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of the assimp team, nor the names of its
|
||||||
|
contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior
|
||||||
|
written permission of the assimp team.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
/// \file X3DImporter_Macro.hpp
|
||||||
|
/// \brief Useful macrodefines.
|
||||||
|
/// \date 2015-2016
|
||||||
|
/// \author smal.root@gmail.com
|
||||||
|
|
||||||
|
#ifndef X3DIMPORTER_MACRO_HPP_INCLUDED
|
||||||
|
#define X3DIMPORTER_MACRO_HPP_INCLUDED
|
||||||
|
|
||||||
|
/// \def MACRO_USE_CHECKANDAPPLY(pDEF, pUSE, pNE)
|
||||||
|
/// 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)
|
||||||
|
|
||||||
|
/// \def MACRO_ATTRREAD_CHECKUSEDEF_RET
|
||||||
|
/// Compact variant for checking "USE" and "DEF".
|
||||||
|
/// \param [in] pNode - pugi xml node to read.
|
||||||
|
/// \param [out] pDEF_Var - output variable name for "DEF" value.
|
||||||
|
/// \param [out] pUSE_Var - output variable name for "USE" value.
|
||||||
|
#define MACRO_ATTRREAD_CHECKUSEDEF_RET(pNode, pDEF_Var, pUSE_Var) \
|
||||||
|
do { \
|
||||||
|
XmlParser::getStdStrAttribute(pNode, "def", pDEF_Var); \
|
||||||
|
XmlParser::getStdStrAttribute(pNode, "use", pUSE_Var); \
|
||||||
|
} while (false)
|
||||||
|
|
||||||
|
/// \def MACRO_FACE_ADD_QUAD_FA(pCCW, pOut, pIn, pP1, pP2, pP3, pP4)
|
||||||
|
/// Add points as quad. Means that pP1..pP4 set in CCW order.
|
||||||
|
#define MACRO_FACE_ADD_QUAD_FA(pCCW, pOut, pIn, pP1, pP2, pP3, pP4) \
|
||||||
|
do { \
|
||||||
|
if (pCCW) { \
|
||||||
|
pOut.push_back(pIn[pP1]); \
|
||||||
|
pOut.push_back(pIn[pP2]); \
|
||||||
|
pOut.push_back(pIn[pP3]); \
|
||||||
|
pOut.push_back(pIn[pP4]); \
|
||||||
|
} else { \
|
||||||
|
pOut.push_back(pIn[pP4]); \
|
||||||
|
pOut.push_back(pIn[pP3]); \
|
||||||
|
pOut.push_back(pIn[pP2]); \
|
||||||
|
pOut.push_back(pIn[pP1]); \
|
||||||
|
} \
|
||||||
|
} while (false)
|
||||||
|
|
||||||
|
/// \def MACRO_FACE_ADD_QUAD(pCCW, pOut, pP1, pP2, pP3, pP4)
|
||||||
|
/// Add points as quad. Means that pP1..pP4 set in CCW order.
|
||||||
|
#define MACRO_FACE_ADD_QUAD(pCCW, pOut, pP1, pP2, pP3, pP4) \
|
||||||
|
do { \
|
||||||
|
if (pCCW) { \
|
||||||
|
pOut.push_back(pP1); \
|
||||||
|
pOut.push_back(pP2); \
|
||||||
|
pOut.push_back(pP3); \
|
||||||
|
pOut.push_back(pP4); \
|
||||||
|
} else { \
|
||||||
|
pOut.push_back(pP4); \
|
||||||
|
pOut.push_back(pP3); \
|
||||||
|
pOut.push_back(pP2); \
|
||||||
|
pOut.push_back(pP1); \
|
||||||
|
} \
|
||||||
|
} while (false)
|
||||||
|
|
||||||
|
#endif // X3DIMPORTER_MACRO_HPP_INCLUDED
|
|
@ -0,0 +1,255 @@
|
||||||
|
/*
|
||||||
|
Open Asset Import Library (assimp)
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2019, assimp team
|
||||||
|
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
with or without modification, are permitted provided that the
|
||||||
|
following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer in the documentation and/or other
|
||||||
|
materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of the assimp team, nor the names of its
|
||||||
|
contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior
|
||||||
|
written permission of the assimp team.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
/// \file X3DImporter_Metadata.cpp
|
||||||
|
/// \brief Parsing data from nodes of "Metadata" set of X3D.
|
||||||
|
/// \date 2015-2016
|
||||||
|
/// \author smal.root@gmail.com
|
||||||
|
|
||||||
|
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||||
|
|
||||||
|
#include "X3DImporter.hpp"
|
||||||
|
#include "X3DImporter_Macro.hpp"
|
||||||
|
#include "X3DXmlHelper.h"
|
||||||
|
|
||||||
|
namespace Assimp {
|
||||||
|
|
||||||
|
bool X3DImporter::checkForMetadataNode(XmlNode &node) {
|
||||||
|
const std::string &name = node.name();
|
||||||
|
if (name == "MetadataBoolean") {
|
||||||
|
readMetadataBoolean(node);
|
||||||
|
} else if (name == "MetadataDouble") {
|
||||||
|
readMetadataDouble(node);
|
||||||
|
} else if (name == "MetadataFloat") {
|
||||||
|
readMetadataFloat(node);
|
||||||
|
} else if (name == "MetadataInteger") {
|
||||||
|
readMetadataInteger(node);
|
||||||
|
} else if (name == "MetadataSet") {
|
||||||
|
readMetadataSet(node);
|
||||||
|
} else if (name == "MetadataString") {
|
||||||
|
readMetadataString(node);
|
||||||
|
} else
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void X3DImporter::childrenReadMetadata(XmlNode &node, X3DNodeElementBase *pParentElement, const std::string &pNodeName) {
|
||||||
|
ParseHelper_Node_Enter(pParentElement);
|
||||||
|
for (auto childNode : node.children()) {
|
||||||
|
if (!checkForMetadataNode(childNode)) skipUnsupportedNode(pNodeName, childNode);
|
||||||
|
}
|
||||||
|
ParseHelper_Node_Exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \def MACRO_METADATA_FINDCREATE(pDEF_Var, pUSE_Var, pReference, pValue, pNE, pMetaName)
|
||||||
|
/// Find element by "USE" or create new one.
|
||||||
|
/// \param [in] pNode - pugi xml node to read.
|
||||||
|
/// \param [in] pDEF_Var - variable name with "DEF" value.
|
||||||
|
/// \param [in] pUSE_Var - variable name with "USE" value.
|
||||||
|
/// \param [in] pReference - variable name with "reference" value.
|
||||||
|
/// \param [in] pValue - variable name with "value" value.
|
||||||
|
/// \param [in, out] pNE - pointer to node element.
|
||||||
|
/// \param [in] pMetaClass - Class of node.
|
||||||
|
/// \param [in] pMetaName - Name of node.
|
||||||
|
/// \param [in] pType - type of element to find.
|
||||||
|
#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); \
|
||||||
|
} else { \
|
||||||
|
pNE = new pMetaClass(mNodeElementCur); \
|
||||||
|
if (!pDEF_Var.empty()) pNE->ID = pDEF_Var; \
|
||||||
|
\
|
||||||
|
((pMetaClass *)pNE)->Reference = pReference; \
|
||||||
|
((pMetaClass *)pNE)->Value = pValue; \
|
||||||
|
/* also metadata node can contain childs */ \
|
||||||
|
if (!isNodeEmpty(pNode)) \
|
||||||
|
childrenReadMetadata(pNode, pNE, pMetaName); /* in that case node element will be added to child elements list of current node. */ \
|
||||||
|
else \
|
||||||
|
mNodeElementCur->Children.push_back(pNE); /* else - add element to child list manually */ \
|
||||||
|
\
|
||||||
|
NodeElement_List.push_back(pNE); /* add new element to elements list. */ \
|
||||||
|
} /* if(!pUSE_Var.empty()) else */ \
|
||||||
|
\
|
||||||
|
do { \
|
||||||
|
} while (false)
|
||||||
|
|
||||||
|
// <MetadataBoolean
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// name="" SFString [inputOutput]
|
||||||
|
// reference="" SFString [inputOutput]
|
||||||
|
// value="" MFBool [inputOutput]
|
||||||
|
// />
|
||||||
|
void X3DImporter::readMetadataBoolean(XmlNode &node) {
|
||||||
|
std::string def, use;
|
||||||
|
std::string name, reference;
|
||||||
|
std::vector<bool> value;
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
XmlParser::getStdStrAttribute(node, "name", name);
|
||||||
|
XmlParser::getStdStrAttribute(node, "reference", reference);
|
||||||
|
X3DXmlHelper::getBooleanArrayAttribute(node, "value", value);
|
||||||
|
|
||||||
|
MACRO_METADATA_FINDCREATE(node, def, use, reference, value, ne, X3DNodeElementMetaBoolean, "MetadataBoolean", ENET_MetaBoolean);
|
||||||
|
}
|
||||||
|
|
||||||
|
// <MetadataDouble
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// name="" SFString [inputOutput]
|
||||||
|
// reference="" SFString [inputOutput]
|
||||||
|
// value="" MFDouble [inputOutput]
|
||||||
|
// />
|
||||||
|
void X3DImporter::readMetadataDouble(XmlNode &node) {
|
||||||
|
std::string def, use;
|
||||||
|
std::string name, reference;
|
||||||
|
std::vector<double> value;
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
XmlParser::getStdStrAttribute(node, "name", name);
|
||||||
|
XmlParser::getStdStrAttribute(node, "reference", reference);
|
||||||
|
X3DXmlHelper::getDoubleArrayAttribute(node, "value", value);
|
||||||
|
|
||||||
|
MACRO_METADATA_FINDCREATE(node, def, use, reference, value, ne, X3DNodeElementMetaDouble, "MetadataDouble", ENET_MetaDouble);
|
||||||
|
}
|
||||||
|
|
||||||
|
// <MetadataFloat
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// name="" SFString [inputOutput]
|
||||||
|
// reference="" SFString [inputOutput]
|
||||||
|
// value="" MFFloat [inputOutput]
|
||||||
|
// />
|
||||||
|
void X3DImporter::readMetadataFloat(XmlNode &node) {
|
||||||
|
std::string def, use;
|
||||||
|
std::string name, reference;
|
||||||
|
std::vector<float> value;
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
XmlParser::getStdStrAttribute(node, "name", name);
|
||||||
|
XmlParser::getStdStrAttribute(node, "reference", reference);
|
||||||
|
X3DXmlHelper::getFloatArrayAttribute(node, "value", value);
|
||||||
|
|
||||||
|
MACRO_METADATA_FINDCREATE(node, def, use, reference, value, ne, X3DNodeElementMetaFloat, "MetadataFloat", ENET_MetaFloat);
|
||||||
|
}
|
||||||
|
|
||||||
|
// <MetadataInteger
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// name="" SFString [inputOutput]
|
||||||
|
// reference="" SFString [inputOutput]
|
||||||
|
// value="" MFInteger [inputOutput]
|
||||||
|
// />
|
||||||
|
void X3DImporter::readMetadataInteger(XmlNode &node) {
|
||||||
|
std::string def, use;
|
||||||
|
std::string name, reference;
|
||||||
|
std::vector<int32_t> value;
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
XmlParser::getStdStrAttribute(node, "name", name);
|
||||||
|
XmlParser::getStdStrAttribute(node, "reference", reference);
|
||||||
|
X3DXmlHelper::getInt32ArrayAttribute(node, "value", value);
|
||||||
|
|
||||||
|
MACRO_METADATA_FINDCREATE(node, def, use, reference, value, ne, X3DNodeElementMetaInt, "MetadataInteger", ENET_MetaInteger);
|
||||||
|
}
|
||||||
|
|
||||||
|
// <MetadataSet
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// name="" SFString [inputOutput]
|
||||||
|
// reference="" SFString [inputOutput]
|
||||||
|
// />
|
||||||
|
void X3DImporter::readMetadataSet(XmlNode &node) {
|
||||||
|
std::string def, use;
|
||||||
|
std::string name, reference;
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
XmlParser::getStdStrAttribute(node, "name", name);
|
||||||
|
XmlParser::getStdStrAttribute(node, "reference", reference);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty()) {
|
||||||
|
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
|
||||||
|
if (!isNodeEmpty(node))
|
||||||
|
childrenReadMetadata(node, ne, "MetadataSet");
|
||||||
|
else
|
||||||
|
mNodeElementCur->Children.push_back(ne); // made object as child to current element
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne); // add new element to elements list.
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
// <MetadataString
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// name="" SFString [inputOutput]
|
||||||
|
// reference="" SFString [inputOutput]
|
||||||
|
// value="" MFString [inputOutput]
|
||||||
|
// />
|
||||||
|
void X3DImporter::readMetadataString(XmlNode &node) {
|
||||||
|
std::string def, use;
|
||||||
|
std::string name, reference;
|
||||||
|
std::vector<std::string> value;
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
XmlParser::getStdStrAttribute(node, "name", name);
|
||||||
|
XmlParser::getStdStrAttribute(node, "reference", reference);
|
||||||
|
X3DXmlHelper::getStringArrayAttribute(node, "value", value);
|
||||||
|
|
||||||
|
MACRO_METADATA_FINDCREATE(node, def, use, reference, value, ne, X3DNodeElementMetaString, "MetadataString", ENET_MetaString);
|
||||||
|
}
|
||||||
|
|
||||||
|
}// namespace Assimp
|
||||||
|
|
||||||
|
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
@ -0,0 +1,125 @@
|
||||||
|
/*
|
||||||
|
Open Asset Import Library (assimp)
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2019, assimp team
|
||||||
|
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
with or without modification, are permitted provided that the
|
||||||
|
following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer in the documentation and/or other
|
||||||
|
materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of the assimp team, nor the names of its
|
||||||
|
contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior
|
||||||
|
written permission of the assimp team.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
/// \file X3DImporter_Networking.cpp
|
||||||
|
/// \brief Parsing data from nodes of "Networking" set of X3D.
|
||||||
|
/// date 2015-2016
|
||||||
|
/// author smal.root@gmail.com
|
||||||
|
|
||||||
|
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||||
|
|
||||||
|
#include "X3DImporter.hpp"
|
||||||
|
#include "X3DImporter_Macro.hpp"
|
||||||
|
#include "X3DXmlHelper.h"
|
||||||
|
|
||||||
|
// Header files, Assimp.
|
||||||
|
#include <assimp/DefaultIOSystem.h>
|
||||||
|
|
||||||
|
//#include <regex>
|
||||||
|
|
||||||
|
namespace Assimp {
|
||||||
|
|
||||||
|
//static std::regex pattern_parentDir(R"((^|/)[^/]+/../)");
|
||||||
|
static std::string parentDir("/../");
|
||||||
|
|
||||||
|
// <Inline
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// bboxCenter="0 0 0" SFVec3f [initializeOnly]
|
||||||
|
// bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
|
||||||
|
// load="true" SFBool [inputOutput]
|
||||||
|
// url="" MFString [inputOutput]
|
||||||
|
// />
|
||||||
|
void X3DImporter::readInline(XmlNode &node) {
|
||||||
|
std::string def, use;
|
||||||
|
bool load = true;
|
||||||
|
std::list<std::string> url;
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
XmlParser::getBoolAttribute(node, "load", load);
|
||||||
|
X3DXmlHelper::getStringListAttribute(node, "url", url);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty()) {
|
||||||
|
X3DNodeElementBase *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.
|
||||||
|
if (!def.empty()) mNodeElementCur->ID = def;
|
||||||
|
|
||||||
|
if (load && !url.empty()) {
|
||||||
|
std::string full_path = mpIOHandler->CurrentDirectory() + url.front();
|
||||||
|
|
||||||
|
//full_path = std::regex_replace(full_path, pattern_parentDir, "$1");
|
||||||
|
for (std::string::size_type pos = full_path.find(parentDir); pos != std::string::npos; pos = full_path.find(parentDir, pos)) {
|
||||||
|
if (pos > 0) {
|
||||||
|
std::string::size_type pos2 = full_path.rfind('/', pos - 1);
|
||||||
|
if (pos2 != std::string::npos) {
|
||||||
|
full_path.erase(pos2, pos - pos2 + 3);
|
||||||
|
pos = pos2;
|
||||||
|
} else {
|
||||||
|
full_path.erase(0, pos + 4);
|
||||||
|
pos = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pos += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Attribute "url" can contain list of strings. But we need only one - first.
|
||||||
|
std::string::size_type slashPos = full_path.find_last_of("\\/");
|
||||||
|
mpIOHandler->PushDirectory(slashPos == std::string::npos ? std::string() : full_path.substr(0, slashPos + 1));
|
||||||
|
ParseFile(full_path, mpIOHandler);
|
||||||
|
mpIOHandler->PopDirectory();
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for X3DMetadataObject childs.
|
||||||
|
if (!isNodeEmpty(node)) childrenReadMetadata(node, mNodeElementCur, "Inline");
|
||||||
|
|
||||||
|
// exit from node in that place
|
||||||
|
ParseHelper_Node_Exit();
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Assimp
|
||||||
|
|
||||||
|
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
@ -0,0 +1,459 @@
|
||||||
|
/*
|
||||||
|
Open Asset Import Library (assimp)
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2019, assimp team
|
||||||
|
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
with or without modification, are permitted provided that the
|
||||||
|
following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer in the documentation and/or other
|
||||||
|
materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of the assimp team, nor the names of its
|
||||||
|
contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior
|
||||||
|
written permission of the assimp team.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
/// \file X3DImporter_Node.hpp
|
||||||
|
/// \brief Elements of scene graph.
|
||||||
|
/// \date 2015-2016
|
||||||
|
/// \author smal.root@gmail.com
|
||||||
|
|
||||||
|
#ifndef INCLUDED_AI_X3D_IMPORTER_NODE_H
|
||||||
|
#define INCLUDED_AI_X3D_IMPORTER_NODE_H
|
||||||
|
|
||||||
|
// Header files, Assimp.
|
||||||
|
#include <assimp/types.h>
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
enum X3DElemType {
|
||||||
|
ENET_Group, ///< Element has type "Group".
|
||||||
|
ENET_MetaBoolean, ///< Element has type "Metadata boolean".
|
||||||
|
ENET_MetaDouble, ///< Element has type "Metadata double".
|
||||||
|
ENET_MetaFloat, ///< Element has type "Metadata float".
|
||||||
|
ENET_MetaInteger, ///< Element has type "Metadata integer".
|
||||||
|
ENET_MetaSet, ///< Element has type "Metadata set".
|
||||||
|
ENET_MetaString, ///< Element has type "Metadata string".
|
||||||
|
ENET_Arc2D, ///< Element has type "Arc2D".
|
||||||
|
ENET_ArcClose2D, ///< Element has type "ArcClose2D".
|
||||||
|
ENET_Circle2D, ///< Element has type "Circle2D".
|
||||||
|
ENET_Disk2D, ///< Element has type "Disk2D".
|
||||||
|
ENET_Polyline2D, ///< Element has type "Polyline2D".
|
||||||
|
ENET_Polypoint2D, ///< Element has type "Polypoint2D".
|
||||||
|
ENET_Rectangle2D, ///< Element has type "Rectangle2D".
|
||||||
|
ENET_TriangleSet2D, ///< Element has type "TriangleSet2D".
|
||||||
|
ENET_Box, ///< Element has type "Box".
|
||||||
|
ENET_Cone, ///< Element has type "Cone".
|
||||||
|
ENET_Cylinder, ///< Element has type "Cylinder".
|
||||||
|
ENET_Sphere, ///< Element has type "Sphere".
|
||||||
|
ENET_ElevationGrid, ///< Element has type "ElevationGrid".
|
||||||
|
ENET_Extrusion, ///< Element has type "Extrusion".
|
||||||
|
ENET_Coordinate, ///< Element has type "Coordinate".
|
||||||
|
ENET_Normal, ///< Element has type "Normal".
|
||||||
|
ENET_TextureCoordinate, ///< Element has type "TextureCoordinate".
|
||||||
|
ENET_IndexedFaceSet, ///< Element has type "IndexedFaceSet".
|
||||||
|
ENET_IndexedLineSet, ///< Element has type "IndexedLineSet".
|
||||||
|
ENET_IndexedTriangleSet, ///< Element has type "IndexedTriangleSet".
|
||||||
|
ENET_IndexedTriangleFanSet, ///< Element has type "IndexedTriangleFanSet".
|
||||||
|
ENET_IndexedTriangleStripSet, ///< Element has type "IndexedTriangleStripSet".
|
||||||
|
ENET_LineSet, ///< Element has type "LineSet".
|
||||||
|
ENET_PointSet, ///< Element has type "PointSet".
|
||||||
|
ENET_TriangleSet, ///< Element has type "TriangleSet".
|
||||||
|
ENET_TriangleFanSet, ///< Element has type "TriangleFanSet".
|
||||||
|
ENET_TriangleStripSet, ///< Element has type "TriangleStripSet".
|
||||||
|
ENET_Color, ///< Element has type "Color".
|
||||||
|
ENET_ColorRGBA, ///< Element has type "ColorRGBA".
|
||||||
|
ENET_Shape, ///< Element has type "Shape".
|
||||||
|
ENET_Appearance, ///< Element has type "Appearance".
|
||||||
|
ENET_Material, ///< Element has type "Material".
|
||||||
|
ENET_ImageTexture, ///< Element has type "ImageTexture".
|
||||||
|
ENET_TextureTransform, ///< Element has type "TextureTransform".
|
||||||
|
ENET_DirectionalLight, ///< Element has type "DirectionalLight".
|
||||||
|
ENET_PointLight, ///< Element has type "PointLight".
|
||||||
|
ENET_SpotLight, ///< Element has type "SpotLight".
|
||||||
|
|
||||||
|
ENET_Invalid ///< Element has invalid type and possible contain invalid data.
|
||||||
|
};
|
||||||
|
|
||||||
|
struct X3DNodeElementBase {
|
||||||
|
X3DNodeElementBase *Parent;
|
||||||
|
std::string ID;
|
||||||
|
std::list<X3DNodeElementBase *> Children;
|
||||||
|
X3DElemType Type;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
X3DNodeElementBase(X3DElemType type, X3DNodeElementBase *pParent) :
|
||||||
|
Type(type), Parent(pParent) {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// This struct hold <Color> value.
|
||||||
|
struct X3DNodeElementColor : X3DNodeElementBase {
|
||||||
|
std::list<aiColor3D> Value; ///< Stored value.
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
/// \param [in] pParent - pointer to parent node.
|
||||||
|
X3DNodeElementColor(X3DNodeElementBase *pParent) :
|
||||||
|
X3DNodeElementBase(X3DElemType::ENET_Color, pParent) {}
|
||||||
|
|
||||||
|
}; // struct X3DNodeElementColor
|
||||||
|
|
||||||
|
/// This struct hold <ColorRGBA> value.
|
||||||
|
struct X3DNodeElementColorRGBA : X3DNodeElementBase {
|
||||||
|
std::list<aiColor4D> Value; ///< Stored value.
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
/// \param [in] pParent - pointer to parent node.
|
||||||
|
X3DNodeElementColorRGBA(X3DNodeElementBase *pParent) :
|
||||||
|
X3DNodeElementBase(X3DElemType::ENET_ColorRGBA, pParent) {}
|
||||||
|
|
||||||
|
}; // struct X3DNodeElementColorRGBA
|
||||||
|
|
||||||
|
/// This struct hold <Coordinate> value.
|
||||||
|
struct X3DNodeElementCoordinate : public X3DNodeElementBase {
|
||||||
|
std::list<aiVector3D> Value; ///< Stored value.
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
/// \param [in] pParent - pointer to parent node.
|
||||||
|
X3DNodeElementCoordinate(X3DNodeElementBase *pParent) :
|
||||||
|
X3DNodeElementBase(X3DElemType::ENET_Coordinate, pParent) {}
|
||||||
|
|
||||||
|
}; // struct X3DNodeElementCoordinate
|
||||||
|
|
||||||
|
/// This struct hold <Normal> value.
|
||||||
|
struct X3DNodeElementNormal : X3DNodeElementBase {
|
||||||
|
std::list<aiVector3D> Value; ///< Stored value.
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
/// \param [in] pParent - pointer to parent node.
|
||||||
|
X3DNodeElementNormal(X3DNodeElementBase *pParent) :
|
||||||
|
X3DNodeElementBase(X3DElemType::ENET_Normal, pParent) {}
|
||||||
|
|
||||||
|
}; // struct X3DNodeElementNormal
|
||||||
|
|
||||||
|
/// This struct hold <TextureCoordinate> value.
|
||||||
|
struct X3DNodeElementTextureCoordinate : X3DNodeElementBase {
|
||||||
|
std::list<aiVector2D> Value; ///< Stored value.
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
/// \param [in] pParent - pointer to parent node.
|
||||||
|
X3DNodeElementTextureCoordinate(X3DNodeElementBase *pParent) :
|
||||||
|
X3DNodeElementBase(X3DElemType::ENET_TextureCoordinate, pParent) {}
|
||||||
|
|
||||||
|
}; // struct X3DNodeElementTextureCoordinate
|
||||||
|
|
||||||
|
/// Two-dimensional figure.
|
||||||
|
struct X3DNodeElementGeometry2D : X3DNodeElementBase {
|
||||||
|
std::list<aiVector3D> Vertices; ///< Vertices list.
|
||||||
|
size_t NumIndices; ///< Number of indices in one face.
|
||||||
|
bool Solid; ///< Flag: if true then render must use back-face culling, else render must draw both sides of object.
|
||||||
|
|
||||||
|
/// Constructor.
|
||||||
|
/// \param [in] pParent - pointer to parent node.
|
||||||
|
/// \param [in] pType - type of geometry object.
|
||||||
|
X3DNodeElementGeometry2D(X3DElemType pType, X3DNodeElementBase *pParent) :
|
||||||
|
X3DNodeElementBase(pType, pParent), Solid(true) {}
|
||||||
|
|
||||||
|
}; // class X3DNodeElementGeometry2D
|
||||||
|
|
||||||
|
/// Three-dimensional body.
|
||||||
|
struct X3DNodeElementGeometry3D : X3DNodeElementBase {
|
||||||
|
std::list<aiVector3D> Vertices; ///< Vertices list.
|
||||||
|
size_t NumIndices; ///< Number of indices in one face.
|
||||||
|
bool Solid; ///< Flag: if true then render must use back-face culling, else render must draw both sides of object.
|
||||||
|
|
||||||
|
/// Constructor.
|
||||||
|
/// \param [in] pParent - pointer to parent node.
|
||||||
|
/// \param [in] pType - type of geometry object.
|
||||||
|
X3DNodeElementGeometry3D(X3DElemType pType, X3DNodeElementBase *pParent) :
|
||||||
|
X3DNodeElementBase(pType, pParent), Vertices(), NumIndices(0), Solid(true) {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
}; // class X3DNodeElementGeometry3D
|
||||||
|
|
||||||
|
/// Uniform rectangular grid of varying height.
|
||||||
|
struct X3DNodeElementElevationGrid : X3DNodeElementGeometry3D {
|
||||||
|
bool NormalPerVertex; ///< If true then normals are defined for every vertex, else for every face(line).
|
||||||
|
bool ColorPerVertex; ///< If true then colors are defined for every vertex, else for every face(line).
|
||||||
|
/// If the angle between the geometric normals of two adjacent faces is less than the crease angle, normals shall be calculated so that the faces are
|
||||||
|
/// shaded smoothly across the edge; otherwise, normals shall be calculated so that a lighting discontinuity across the edge is produced.
|
||||||
|
float CreaseAngle;
|
||||||
|
std::vector<int32_t> CoordIdx; ///< Coordinates list by faces. In X3D format: "-1" - delimiter for faces.
|
||||||
|
|
||||||
|
/// Constructor.
|
||||||
|
/// \param [in] pParent - pointer to parent node.
|
||||||
|
/// \param [in] pType - type of geometry object.
|
||||||
|
X3DNodeElementElevationGrid(X3DElemType pType, X3DNodeElementBase *pParent) :
|
||||||
|
X3DNodeElementGeometry3D(pType, pParent) {}
|
||||||
|
}; // class X3DNodeElementIndexedSet
|
||||||
|
|
||||||
|
/// Shape with indexed vertices.
|
||||||
|
struct X3DNodeElementIndexedSet : public X3DNodeElementGeometry3D {
|
||||||
|
/// The ccw field defines the ordering of the vertex coordinates of the geometry with respect to user-given or automatically generated normal vectors
|
||||||
|
/// used in the lighting model equations. If ccw is TRUE, the normals shall follow the right hand rule; the orientation of each normal with respect to
|
||||||
|
/// the vertices (taken in order) shall be such that the vertices appear to be oriented in a counterclockwise order when the vertices are viewed (in the
|
||||||
|
/// local coordinate system of the Shape) from the opposite direction as the normal. If ccw is FALSE, the normals shall be oriented in the opposite
|
||||||
|
/// direction. If normals are not generated but are supplied using a Normal node, and the orientation of the normals does not match the setting of the
|
||||||
|
/// ccw field, results are undefined.
|
||||||
|
bool CCW;
|
||||||
|
std::vector<int32_t> ColorIndex; ///< Field to specify the polygonal faces by indexing into the <Color> or <ColorRGBA>.
|
||||||
|
bool ColorPerVertex; ///< If true then colors are defined for every vertex, else for every face(line).
|
||||||
|
/// The convex field indicates whether all polygons in the shape are convex (TRUE). A polygon is convex if it is planar, does not intersect itself,
|
||||||
|
/// and all of the interior angles at its vertices are less than 180 degrees. Non planar and self intersecting polygons may produce undefined results
|
||||||
|
/// even if the convex field is FALSE.
|
||||||
|
bool Convex;
|
||||||
|
std::vector<int32_t> CoordIndex; ///< Field to specify the polygonal faces by indexing into the <Coordinate>.
|
||||||
|
/// If the angle between the geometric normals of two adjacent faces is less than the crease angle, normals shall be calculated so that the faces are
|
||||||
|
/// shaded smoothly across the edge; otherwise, normals shall be calculated so that a lighting discontinuity across the edge is produced.
|
||||||
|
float CreaseAngle;
|
||||||
|
std::vector<int32_t> NormalIndex; ///< Field to specify the polygonal faces by indexing into the <Normal>.
|
||||||
|
bool NormalPerVertex; ///< If true then normals are defined for every vertex, else for every face(line).
|
||||||
|
std::vector<int32_t> TexCoordIndex; ///< Field to specify the polygonal faces by indexing into the <TextureCoordinate>.
|
||||||
|
|
||||||
|
/// Constructor.
|
||||||
|
/// \param [in] pParent - pointer to parent node.
|
||||||
|
/// \param [in] pType - type of geometry object.
|
||||||
|
X3DNodeElementIndexedSet(X3DElemType pType, X3DNodeElementBase *pParent) :
|
||||||
|
X3DNodeElementGeometry3D(pType, pParent) {}
|
||||||
|
}; // class X3DNodeElementIndexedSet
|
||||||
|
|
||||||
|
/// Shape with set of vertices.
|
||||||
|
struct X3DNodeElementSet : X3DNodeElementGeometry3D {
|
||||||
|
/// The ccw field defines the ordering of the vertex coordinates of the geometry with respect to user-given or automatically generated normal vectors
|
||||||
|
/// used in the lighting model equations. If ccw is TRUE, the normals shall follow the right hand rule; the orientation of each normal with respect to
|
||||||
|
/// the vertices (taken in order) shall be such that the vertices appear to be oriented in a counterclockwise order when the vertices are viewed (in the
|
||||||
|
/// local coordinate system of the Shape) from the opposite direction as the normal. If ccw is FALSE, the normals shall be oriented in the opposite
|
||||||
|
/// direction. If normals are not generated but are supplied using a Normal node, and the orientation of the normals does not match the setting of the
|
||||||
|
/// ccw field, results are undefined.
|
||||||
|
bool CCW;
|
||||||
|
bool ColorPerVertex; ///< If true then colors are defined for every vertex, else for every face(line).
|
||||||
|
bool NormalPerVertex; ///< If true then normals are defined for every vertex, else for every face(line).
|
||||||
|
std::vector<int32_t> CoordIndex; ///< Field to specify the polygonal faces by indexing into the <Coordinate>.
|
||||||
|
std::vector<int32_t> NormalIndex; ///< Field to specify the polygonal faces by indexing into the <Normal>.
|
||||||
|
std::vector<int32_t> TexCoordIndex; ///< Field to specify the polygonal faces by indexing into the <TextureCoordinate>.
|
||||||
|
std::vector<int32_t> VertexCount; ///< Field describes how many vertices are to be used in each polyline(polygon) from the <Coordinate> field.
|
||||||
|
|
||||||
|
/// Constructor.
|
||||||
|
/// \param [in] pParent - pointer to parent node.
|
||||||
|
/// \param [in] pType - type of geometry object.
|
||||||
|
X3DNodeElementSet(X3DElemType type, X3DNodeElementBase *pParent) :
|
||||||
|
X3DNodeElementGeometry3D(type, pParent) {}
|
||||||
|
|
||||||
|
}; // class X3DNodeElementSet
|
||||||
|
|
||||||
|
/// This struct hold <Shape> value.
|
||||||
|
struct X3DNodeElementShape : X3DNodeElementBase {
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
/// \param [in] pParent - pointer to parent node.
|
||||||
|
X3DNodeElementShape(X3DNodeElementBase *pParent) :
|
||||||
|
X3DNodeElementBase(X3DElemType::ENET_Shape, pParent) {}
|
||||||
|
}; // struct X3DNodeElementShape
|
||||||
|
|
||||||
|
/// This struct hold <Appearance> value.
|
||||||
|
struct X3DNodeElementAppearance : public X3DNodeElementBase {
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
/// \param [in] pParent - pointer to parent node.
|
||||||
|
X3DNodeElementAppearance(X3DNodeElementBase *pParent) :
|
||||||
|
X3DNodeElementBase(X3DElemType::ENET_Appearance, pParent) {}
|
||||||
|
|
||||||
|
}; // struct X3DNodeElementAppearance
|
||||||
|
|
||||||
|
struct X3DNodeElementMaterial : public X3DNodeElementBase {
|
||||||
|
float AmbientIntensity; ///< Specifies how much ambient light from light sources this surface shall reflect.
|
||||||
|
aiColor3D DiffuseColor; ///< Reflects all X3D light sources depending on the angle of the surface with respect to the light source.
|
||||||
|
aiColor3D EmissiveColor; ///< Models "glowing" objects. This can be useful for displaying pre-lit models.
|
||||||
|
float Shininess; ///< Lower shininess values produce soft glows, while higher values result in sharper, smaller highlights.
|
||||||
|
aiColor3D SpecularColor; ///< The specularColor and shininess fields determine the specular highlights.
|
||||||
|
float Transparency; ///< Specifies how "clear" an object is, with 1.0 being completely transparent, and 0.0 completely opaque.
|
||||||
|
|
||||||
|
/// Constructor.
|
||||||
|
/// \param [in] pParent - pointer to parent node.
|
||||||
|
/// \param [in] pType - type of geometry object.
|
||||||
|
X3DNodeElementMaterial(X3DNodeElementBase *pParent) :
|
||||||
|
X3DNodeElementBase(X3DElemType::ENET_Material, pParent),
|
||||||
|
AmbientIntensity(0.0f),
|
||||||
|
DiffuseColor(),
|
||||||
|
EmissiveColor(),
|
||||||
|
Shininess(0.0f),
|
||||||
|
SpecularColor(),
|
||||||
|
Transparency(1.0f) {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
}; // class X3DNodeElementMaterial
|
||||||
|
|
||||||
|
/// This struct hold <ImageTexture> value.
|
||||||
|
struct X3DNodeElementImageTexture : X3DNodeElementBase {
|
||||||
|
/// RepeatS and RepeatT, that specify how the texture wraps in the S and T directions. If repeatS is TRUE (the default), the texture map is repeated
|
||||||
|
/// outside the [0.0, 1.0] texture coordinate range in the S direction so that it fills the shape. If repeatS is FALSE, the texture coordinates are
|
||||||
|
/// clamped in the S direction to lie within the [0.0, 1.0] range. The repeatT field is analogous to the repeatS field.
|
||||||
|
bool RepeatS;
|
||||||
|
bool RepeatT; ///< See \ref RepeatS.
|
||||||
|
std::string URL; ///< URL of the texture.
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
/// \param [in] pParent - pointer to parent node.
|
||||||
|
X3DNodeElementImageTexture(X3DNodeElementBase *pParent) :
|
||||||
|
X3DNodeElementBase(X3DElemType::ENET_ImageTexture, pParent) {}
|
||||||
|
|
||||||
|
}; // struct X3DNodeElementImageTexture
|
||||||
|
|
||||||
|
/// This struct hold <TextureTransform> value.
|
||||||
|
struct X3DNodeElementTextureTransform : X3DNodeElementBase {
|
||||||
|
aiVector2D Center; ///< Specifies a translation offset in texture coordinate space about which the rotation and scale fields are applied.
|
||||||
|
float Rotation; ///< Specifies a rotation in angle base units of the texture coordinates about the center point after the scale has been applied.
|
||||||
|
aiVector2D Scale; ///< Specifies a scaling factor in S and T of the texture coordinates about the center point.
|
||||||
|
aiVector2D Translation; ///< Specifies a translation of the texture coordinates.
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
/// \param [in] pParent - pointer to parent node.
|
||||||
|
X3DNodeElementTextureTransform(X3DNodeElementBase *pParent) :
|
||||||
|
X3DNodeElementBase(X3DElemType::ENET_TextureTransform, pParent) {}
|
||||||
|
|
||||||
|
}; // struct X3DNodeElementTextureTransform
|
||||||
|
|
||||||
|
struct X3DNodeElementGroup : X3DNodeElementBase {
|
||||||
|
aiMatrix4x4 Transformation; ///< Transformation matrix.
|
||||||
|
|
||||||
|
/// As you know node elements can use already defined node elements when attribute "USE" is defined.
|
||||||
|
/// Standard search when looking for an element in the whole scene graph, existing at this moment.
|
||||||
|
/// If a node is marked as static, the children(or lower) can not search for elements in the nodes upper then static.
|
||||||
|
bool Static;
|
||||||
|
|
||||||
|
bool UseChoice; ///< Flag: if true then use number from \ref Choice to choose what the child will be kept.
|
||||||
|
int32_t Choice; ///< Number of the child which will be kept.
|
||||||
|
|
||||||
|
/// Constructor.
|
||||||
|
/// \param [in] pParent - pointer to parent node.
|
||||||
|
/// \param [in] pStatic - static node flag.
|
||||||
|
X3DNodeElementGroup(X3DNodeElementBase *pParent, const bool pStatic = false) :
|
||||||
|
X3DNodeElementBase(X3DElemType::ENET_Group, pParent), Static(pStatic), UseChoice(false) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct X3DNodeElementMeta : X3DNodeElementBase {
|
||||||
|
std::string Name; ///< Name of metadata object.
|
||||||
|
std::string Reference;
|
||||||
|
|
||||||
|
virtual ~X3DNodeElementMeta() {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
X3DNodeElementMeta(X3DElemType type, X3DNodeElementBase *parent) :
|
||||||
|
X3DNodeElementBase(type, parent) {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct X3DNodeElementMetaBoolean : X3DNodeElementMeta {
|
||||||
|
std::vector<bool> Value; ///< Stored value.
|
||||||
|
|
||||||
|
explicit X3DNodeElementMetaBoolean(X3DNodeElementBase *pParent) :
|
||||||
|
X3DNodeElementMeta(X3DElemType::ENET_MetaBoolean, pParent) {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct X3DNodeElementMetaDouble : X3DNodeElementMeta {
|
||||||
|
std::vector<double> Value; ///< Stored value.
|
||||||
|
|
||||||
|
explicit X3DNodeElementMetaDouble(X3DNodeElementBase *pParent) :
|
||||||
|
X3DNodeElementMeta(X3DElemType::ENET_MetaDouble, pParent) {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct X3DNodeElementMetaFloat : public X3DNodeElementMeta {
|
||||||
|
std::vector<float> Value; ///< Stored value.
|
||||||
|
|
||||||
|
explicit X3DNodeElementMetaFloat(X3DNodeElementBase *pParent) :
|
||||||
|
X3DNodeElementMeta(X3DElemType::ENET_MetaFloat, pParent) {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct X3DNodeElementMetaInt : public X3DNodeElementMeta {
|
||||||
|
std::vector<int32_t> Value; ///< Stored value.
|
||||||
|
|
||||||
|
explicit X3DNodeElementMetaInt(X3DNodeElementBase *pParent) :
|
||||||
|
X3DNodeElementMeta(X3DElemType::ENET_MetaInteger, pParent) {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct X3DNodeElementMetaSet : public X3DNodeElementMeta {
|
||||||
|
std::list<X3DNodeElementMeta> Value; ///< Stored value.
|
||||||
|
|
||||||
|
explicit X3DNodeElementMetaSet(X3DNodeElementBase *pParent) :
|
||||||
|
X3DNodeElementMeta(X3DElemType::ENET_MetaSet, pParent) {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct X3DNodeElementMetaString : X3DNodeElementMeta {
|
||||||
|
std::vector<std::string> Value; ///< Stored value.
|
||||||
|
|
||||||
|
explicit X3DNodeElementMetaString(X3DNodeElementBase *pParent) :
|
||||||
|
X3DNodeElementMeta(X3DElemType::ENET_MetaString, pParent) {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// \struct X3DNodeElementLight
|
||||||
|
/// This struct hold <TextureTransform> value.
|
||||||
|
struct X3DNodeElementLight : X3DNodeElementBase {
|
||||||
|
float AmbientIntensity; ///< Specifies the intensity of the ambient emission from the light.
|
||||||
|
aiColor3D Color; ///< specifies the spectral colour properties of both the direct and ambient light emission as an RGB value.
|
||||||
|
aiVector3D Direction; ///< Specifies the direction vector of the illumination emanating from the light source in the local coordinate system.
|
||||||
|
/// \var Global
|
||||||
|
/// Field that determines whether the light is global or scoped. Global lights illuminate all objects that fall within their volume of lighting influence.
|
||||||
|
/// Scoped lights only illuminate objects that are in the same transformation hierarchy as the light.
|
||||||
|
bool Global;
|
||||||
|
float Intensity; ///< Specifies the brightness of the direct emission from the light.
|
||||||
|
/// \var Attenuation
|
||||||
|
/// PointLight node's illumination falls off with distance as specified by three attenuation coefficients. The attenuation factor
|
||||||
|
/// is: "1 / max(attenuation[0] + attenuation[1] * r + attenuation[2] * r2, 1)", where r is the distance from the light to the surface being illuminated.
|
||||||
|
aiVector3D Attenuation;
|
||||||
|
aiVector3D Location; ///< Specifies a translation offset of the centre point of the light source from the light's local coordinate system origin.
|
||||||
|
float Radius; ///< Specifies the radial extent of the solid angle and the maximum distance from location that may be illuminated by the light source.
|
||||||
|
float BeamWidth; ///< Specifies an inner solid angle in which the light source emits light at uniform full intensity.
|
||||||
|
float CutOffAngle; ///< The light source's emission intensity drops off from the inner solid angle (beamWidth) to the outer solid angle (cutOffAngle).
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
/// \param [in] pParent - pointer to parent node.
|
||||||
|
/// \param [in] pLightType - type of the light source.
|
||||||
|
X3DNodeElementLight(X3DElemType pLightType, X3DNodeElementBase *pParent) :
|
||||||
|
X3DNodeElementBase(pLightType, pParent) {}
|
||||||
|
|
||||||
|
}; // struct X3DNodeElementLight
|
||||||
|
|
||||||
|
#endif // INCLUDED_AI_X3D_IMPORTER_NODE_H
|
|
@ -0,0 +1,731 @@
|
||||||
|
/*
|
||||||
|
Open Asset Import Library (assimp)
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2019, assimp team
|
||||||
|
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
with or without modification, are permitted provided that the
|
||||||
|
following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer in the documentation and/or other
|
||||||
|
materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of the assimp team, nor the names of its
|
||||||
|
contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior
|
||||||
|
written permission of the assimp team.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
/// \file X3DImporter_Postprocess.cpp
|
||||||
|
/// \brief Convert built scenegraph and objects to Assimp scenegraph.
|
||||||
|
/// \date 2015-2016
|
||||||
|
/// \author smal.root@gmail.com
|
||||||
|
|
||||||
|
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||||
|
|
||||||
|
#include "X3DGeoHelper.h"
|
||||||
|
#include "X3DImporter.hpp"
|
||||||
|
|
||||||
|
// Header files, Assimp.
|
||||||
|
#include <assimp/StandardShapes.h>
|
||||||
|
#include <assimp/StringUtils.h>
|
||||||
|
#include <assimp/ai_assert.h>
|
||||||
|
|
||||||
|
// Header files, stdlib.
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iterator>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace Assimp {
|
||||||
|
|
||||||
|
aiMatrix4x4 X3DImporter::PostprocessHelper_Matrix_GlobalToCurrent() const {
|
||||||
|
X3DNodeElementBase *cur_node;
|
||||||
|
std::list<aiMatrix4x4> matr;
|
||||||
|
aiMatrix4x4 out_matr;
|
||||||
|
|
||||||
|
// starting walk from current element to root
|
||||||
|
cur_node = mNodeElementCur;
|
||||||
|
if (cur_node != nullptr) {
|
||||||
|
do {
|
||||||
|
// if cur_node is group then store group transformation matrix in list.
|
||||||
|
if (cur_node->Type == X3DElemType::ENET_Group) matr.push_back(((X3DNodeElementGroup *)cur_node)->Transformation);
|
||||||
|
|
||||||
|
cur_node = cur_node->Parent;
|
||||||
|
} while (cur_node != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// multiplicate all matrices in reverse order
|
||||||
|
for (std::list<aiMatrix4x4>::reverse_iterator rit = matr.rbegin(); rit != matr.rend(); ++rit)
|
||||||
|
out_matr = out_matr * (*rit);
|
||||||
|
|
||||||
|
return out_matr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void X3DImporter::PostprocessHelper_CollectMetadata(const X3DNodeElementBase &pNodeElement, std::list<X3DNodeElementBase *> &pList) const {
|
||||||
|
// walk through childs and find for metadata.
|
||||||
|
for (std::list<X3DNodeElementBase *>::const_iterator el_it = pNodeElement.Children.begin(); el_it != pNodeElement.Children.end(); ++el_it) {
|
||||||
|
if (((*el_it)->Type == X3DElemType::ENET_MetaBoolean) || ((*el_it)->Type == X3DElemType::ENET_MetaDouble) ||
|
||||||
|
((*el_it)->Type == X3DElemType::ENET_MetaFloat) || ((*el_it)->Type == X3DElemType::ENET_MetaInteger) ||
|
||||||
|
((*el_it)->Type == X3DElemType::ENET_MetaString)) {
|
||||||
|
pList.push_back(*el_it);
|
||||||
|
} else if ((*el_it)->Type == X3DElemType::ENET_MetaSet) {
|
||||||
|
PostprocessHelper_CollectMetadata(**el_it, pList);
|
||||||
|
}
|
||||||
|
} // for(std::list<X3DNodeElementBase*>::const_iterator el_it = pNodeElement.Children.begin(); el_it != pNodeElement.Children.end(); el_it++)
|
||||||
|
}
|
||||||
|
|
||||||
|
bool X3DImporter::PostprocessHelper_ElementIsMetadata(const X3DElemType pType) const {
|
||||||
|
if ((pType == X3DElemType::ENET_MetaBoolean) || (pType == X3DElemType::ENET_MetaDouble) ||
|
||||||
|
(pType == X3DElemType::ENET_MetaFloat) || (pType == X3DElemType::ENET_MetaInteger) ||
|
||||||
|
(pType == X3DElemType::ENET_MetaString) || (pType == X3DElemType::ENET_MetaSet)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool X3DImporter::PostprocessHelper_ElementIsMesh(const X3DElemType pType) const {
|
||||||
|
if ((pType == X3DElemType::ENET_Arc2D) || (pType == X3DElemType::ENET_ArcClose2D) ||
|
||||||
|
(pType == X3DElemType::ENET_Box) || (pType == X3DElemType::ENET_Circle2D) ||
|
||||||
|
(pType == X3DElemType::ENET_Cone) || (pType == X3DElemType::ENET_Cylinder) ||
|
||||||
|
(pType == X3DElemType::ENET_Disk2D) || (pType == X3DElemType::ENET_ElevationGrid) ||
|
||||||
|
(pType == X3DElemType::ENET_Extrusion) || (pType == X3DElemType::ENET_IndexedFaceSet) ||
|
||||||
|
(pType == X3DElemType::ENET_IndexedLineSet) || (pType == X3DElemType::ENET_IndexedTriangleFanSet) ||
|
||||||
|
(pType == X3DElemType::ENET_IndexedTriangleSet) || (pType == X3DElemType::ENET_IndexedTriangleStripSet) ||
|
||||||
|
(pType == X3DElemType::ENET_PointSet) || (pType == X3DElemType::ENET_LineSet) ||
|
||||||
|
(pType == X3DElemType::ENET_Polyline2D) || (pType == X3DElemType::ENET_Polypoint2D) ||
|
||||||
|
(pType == X3DElemType::ENET_Rectangle2D) || (pType == X3DElemType::ENET_Sphere) ||
|
||||||
|
(pType == X3DElemType::ENET_TriangleFanSet) || (pType == X3DElemType::ENET_TriangleSet) ||
|
||||||
|
(pType == X3DElemType::ENET_TriangleSet2D) || (pType == X3DElemType::ENET_TriangleStripSet)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void X3DImporter::Postprocess_BuildLight(const X3DNodeElementBase &pNodeElement, std::list<aiLight *> &pSceneLightList) const {
|
||||||
|
const X3DNodeElementLight &ne = *((X3DNodeElementLight *)&pNodeElement);
|
||||||
|
aiMatrix4x4 transform_matr = PostprocessHelper_Matrix_GlobalToCurrent();
|
||||||
|
aiLight *new_light = new aiLight;
|
||||||
|
|
||||||
|
new_light->mName = ne.ID;
|
||||||
|
new_light->mColorAmbient = ne.Color * ne.AmbientIntensity;
|
||||||
|
new_light->mColorDiffuse = ne.Color * ne.Intensity;
|
||||||
|
new_light->mColorSpecular = ne.Color * ne.Intensity;
|
||||||
|
switch (pNodeElement.Type) {
|
||||||
|
case X3DElemType::ENET_DirectionalLight:
|
||||||
|
new_light->mType = aiLightSource_DIRECTIONAL;
|
||||||
|
new_light->mDirection = ne.Direction, new_light->mDirection *= transform_matr;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case X3DElemType::ENET_PointLight:
|
||||||
|
new_light->mType = aiLightSource_POINT;
|
||||||
|
new_light->mPosition = ne.Location, new_light->mPosition *= transform_matr;
|
||||||
|
new_light->mAttenuationConstant = ne.Attenuation.x;
|
||||||
|
new_light->mAttenuationLinear = ne.Attenuation.y;
|
||||||
|
new_light->mAttenuationQuadratic = ne.Attenuation.z;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case X3DElemType::ENET_SpotLight:
|
||||||
|
new_light->mType = aiLightSource_SPOT;
|
||||||
|
new_light->mPosition = ne.Location, new_light->mPosition *= transform_matr;
|
||||||
|
new_light->mDirection = ne.Direction, new_light->mDirection *= transform_matr;
|
||||||
|
new_light->mAttenuationConstant = ne.Attenuation.x;
|
||||||
|
new_light->mAttenuationLinear = ne.Attenuation.y;
|
||||||
|
new_light->mAttenuationQuadratic = ne.Attenuation.z;
|
||||||
|
new_light->mAngleInnerCone = ne.BeamWidth;
|
||||||
|
new_light->mAngleOuterCone = ne.CutOffAngle;
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw DeadlyImportError("Postprocess_BuildLight. Unknown type of light: " + ai_to_string(pNodeElement.Type) + ".");
|
||||||
|
}
|
||||||
|
|
||||||
|
pSceneLightList.push_back(new_light);
|
||||||
|
}
|
||||||
|
|
||||||
|
void X3DImporter::Postprocess_BuildMaterial(const X3DNodeElementBase &pNodeElement, aiMaterial **pMaterial) const {
|
||||||
|
// check argument
|
||||||
|
if (pMaterial == nullptr) throw DeadlyImportError("Postprocess_BuildMaterial. pMaterial is nullptr.");
|
||||||
|
if (*pMaterial != nullptr) throw DeadlyImportError("Postprocess_BuildMaterial. *pMaterial must be nullptr.");
|
||||||
|
|
||||||
|
*pMaterial = new aiMaterial;
|
||||||
|
aiMaterial &taimat = **pMaterial; // creating alias for convenience.
|
||||||
|
|
||||||
|
// at this point pNodeElement point to <Appearance> node. Walk through childs and add all stored data.
|
||||||
|
for (std::list<X3DNodeElementBase *>::const_iterator el_it = pNodeElement.Children.begin(); el_it != pNodeElement.Children.end(); ++el_it) {
|
||||||
|
if ((*el_it)->Type == X3DElemType::ENET_Material) {
|
||||||
|
aiColor3D tcol3;
|
||||||
|
float tvalf;
|
||||||
|
X3DNodeElementMaterial &tnemat = *((X3DNodeElementMaterial *)*el_it);
|
||||||
|
|
||||||
|
tcol3.r = tnemat.AmbientIntensity, tcol3.g = tnemat.AmbientIntensity, tcol3.b = tnemat.AmbientIntensity;
|
||||||
|
taimat.AddProperty(&tcol3, 1, AI_MATKEY_COLOR_AMBIENT);
|
||||||
|
taimat.AddProperty(&tnemat.DiffuseColor, 1, AI_MATKEY_COLOR_DIFFUSE);
|
||||||
|
taimat.AddProperty(&tnemat.EmissiveColor, 1, AI_MATKEY_COLOR_EMISSIVE);
|
||||||
|
taimat.AddProperty(&tnemat.SpecularColor, 1, AI_MATKEY_COLOR_SPECULAR);
|
||||||
|
tvalf = 1;
|
||||||
|
taimat.AddProperty(&tvalf, 1, AI_MATKEY_SHININESS_STRENGTH);
|
||||||
|
taimat.AddProperty(&tnemat.Shininess, 1, AI_MATKEY_SHININESS);
|
||||||
|
tvalf = 1.0f - tnemat.Transparency;
|
||||||
|
taimat.AddProperty(&tvalf, 1, AI_MATKEY_OPACITY);
|
||||||
|
} // if((*el_it)->Type == X3DElemType::ENET_Material)
|
||||||
|
else if ((*el_it)->Type == X3DElemType::ENET_ImageTexture) {
|
||||||
|
X3DNodeElementImageTexture &tnetex = *((X3DNodeElementImageTexture *)*el_it);
|
||||||
|
aiString url_str(tnetex.URL.c_str());
|
||||||
|
int mode = aiTextureOp_Multiply;
|
||||||
|
|
||||||
|
taimat.AddProperty(&url_str, AI_MATKEY_TEXTURE_DIFFUSE(0));
|
||||||
|
taimat.AddProperty(&tnetex.RepeatS, 1, AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0));
|
||||||
|
taimat.AddProperty(&tnetex.RepeatT, 1, AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0));
|
||||||
|
taimat.AddProperty(&mode, 1, AI_MATKEY_TEXOP_DIFFUSE(0));
|
||||||
|
} // else if((*el_it)->Type == X3DElemType::ENET_ImageTexture)
|
||||||
|
else if ((*el_it)->Type == X3DElemType::ENET_TextureTransform) {
|
||||||
|
aiUVTransform trans;
|
||||||
|
X3DNodeElementTextureTransform &tnetextr = *((X3DNodeElementTextureTransform *)*el_it);
|
||||||
|
|
||||||
|
trans.mTranslation = tnetextr.Translation - tnetextr.Center;
|
||||||
|
trans.mScaling = tnetextr.Scale;
|
||||||
|
trans.mRotation = tnetextr.Rotation;
|
||||||
|
taimat.AddProperty(&trans, 1, AI_MATKEY_UVTRANSFORM_DIFFUSE(0));
|
||||||
|
} // else if((*el_it)->Type == X3DElemType::ENET_TextureTransform)
|
||||||
|
} // for(std::list<X3DNodeElementBase*>::const_iterator el_it = pNodeElement.Children.begin(); el_it != pNodeElement.Children.end(); el_it++)
|
||||||
|
}
|
||||||
|
|
||||||
|
void X3DImporter::Postprocess_BuildMesh(const X3DNodeElementBase &pNodeElement, aiMesh **pMesh) const {
|
||||||
|
// check argument
|
||||||
|
if (pMesh == nullptr) throw DeadlyImportError("Postprocess_BuildMesh. pMesh is nullptr.");
|
||||||
|
if (*pMesh != nullptr) throw DeadlyImportError("Postprocess_BuildMesh. *pMesh must be nullptr.");
|
||||||
|
|
||||||
|
/************************************************************************************************************************************/
|
||||||
|
/************************************************************ Geometry2D ************************************************************/
|
||||||
|
/************************************************************************************************************************************/
|
||||||
|
if ((pNodeElement.Type == X3DElemType::ENET_Arc2D) || (pNodeElement.Type == X3DElemType::ENET_ArcClose2D) ||
|
||||||
|
(pNodeElement.Type == X3DElemType::ENET_Circle2D) || (pNodeElement.Type == X3DElemType::ENET_Disk2D) ||
|
||||||
|
(pNodeElement.Type == X3DElemType::ENET_Polyline2D) || (pNodeElement.Type == X3DElemType::ENET_Polypoint2D) ||
|
||||||
|
(pNodeElement.Type == X3DElemType::ENET_Rectangle2D) || (pNodeElement.Type == X3DElemType::ENET_TriangleSet2D)) {
|
||||||
|
X3DNodeElementGeometry2D &tnemesh = *((X3DNodeElementGeometry2D *)&pNodeElement); // create alias for convenience
|
||||||
|
std::vector<aiVector3D> tarr;
|
||||||
|
|
||||||
|
tarr.reserve(tnemesh.Vertices.size());
|
||||||
|
for (std::list<aiVector3D>::iterator it = tnemesh.Vertices.begin(); it != tnemesh.Vertices.end(); ++it)
|
||||||
|
tarr.push_back(*it);
|
||||||
|
*pMesh = StandardShapes::MakeMesh(tarr, static_cast<unsigned int>(tnemesh.NumIndices)); // create mesh from vertices using Assimp help.
|
||||||
|
|
||||||
|
return; // mesh is build, nothing to do anymore.
|
||||||
|
}
|
||||||
|
/************************************************************************************************************************************/
|
||||||
|
/************************************************************ Geometry3D ************************************************************/
|
||||||
|
/************************************************************************************************************************************/
|
||||||
|
//
|
||||||
|
// Predefined figures
|
||||||
|
//
|
||||||
|
if ((pNodeElement.Type == X3DElemType::ENET_Box) || (pNodeElement.Type == X3DElemType::ENET_Cone) ||
|
||||||
|
(pNodeElement.Type == X3DElemType::ENET_Cylinder) || (pNodeElement.Type == X3DElemType::ENET_Sphere)) {
|
||||||
|
X3DNodeElementGeometry3D &tnemesh = *((X3DNodeElementGeometry3D *)&pNodeElement); // create alias for convenience
|
||||||
|
std::vector<aiVector3D> tarr;
|
||||||
|
|
||||||
|
tarr.reserve(tnemesh.Vertices.size());
|
||||||
|
for (std::list<aiVector3D>::iterator it = tnemesh.Vertices.begin(); it != tnemesh.Vertices.end(); ++it)
|
||||||
|
tarr.push_back(*it);
|
||||||
|
|
||||||
|
*pMesh = StandardShapes::MakeMesh(tarr, static_cast<unsigned int>(tnemesh.NumIndices)); // create mesh from vertices using Assimp help.
|
||||||
|
|
||||||
|
return; // mesh is build, nothing to do anymore.
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Parametric figures
|
||||||
|
//
|
||||||
|
if (pNodeElement.Type == X3DElemType::ENET_ElevationGrid) {
|
||||||
|
X3DNodeElementElevationGrid &tnemesh = *((X3DNodeElementElevationGrid *)&pNodeElement); // create alias for convenience
|
||||||
|
|
||||||
|
// at first create mesh from existing vertices.
|
||||||
|
*pMesh = X3DGeoHelper::make_mesh(tnemesh.CoordIdx, tnemesh.Vertices);
|
||||||
|
// copy additional information from children
|
||||||
|
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||||
|
if ((*ch_it)->Type == X3DElemType::ENET_Color)
|
||||||
|
X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColor *)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||||
|
else if ((*ch_it)->Type == X3DElemType::ENET_ColorRGBA)
|
||||||
|
X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColorRGBA *)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||||
|
else if ((*ch_it)->Type == X3DElemType::ENET_Normal)
|
||||||
|
X3DGeoHelper::add_normal(**pMesh, ((X3DNodeElementNormal *)*ch_it)->Value, tnemesh.NormalPerVertex);
|
||||||
|
else if ((*ch_it)->Type == X3DElemType::ENET_TextureCoordinate)
|
||||||
|
X3DGeoHelper::add_tex_coord(**pMesh, ((X3DNodeElementTextureCoordinate *)*ch_it)->Value);
|
||||||
|
else
|
||||||
|
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of ElevationGrid: " + ai_to_string((*ch_it)->Type) + ".");
|
||||||
|
} // for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it)
|
||||||
|
|
||||||
|
return; // mesh is build, nothing to do anymore.
|
||||||
|
} // if(pNodeElement.Type == X3DElemType::ENET_ElevationGrid)
|
||||||
|
//
|
||||||
|
// Indexed primitives sets
|
||||||
|
//
|
||||||
|
if (pNodeElement.Type == X3DElemType::ENET_IndexedFaceSet) {
|
||||||
|
X3DNodeElementIndexedSet &tnemesh = *((X3DNodeElementIndexedSet *)&pNodeElement); // create alias for convenience
|
||||||
|
|
||||||
|
// at first search for <Coordinate> node and create mesh.
|
||||||
|
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||||
|
if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
|
||||||
|
*pMesh = X3DGeoHelper::make_mesh(tnemesh.CoordIndex, ((X3DNodeElementCoordinate *)*ch_it)->Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy additional information from children
|
||||||
|
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||||
|
if ((*ch_it)->Type == X3DElemType::ENET_Color)
|
||||||
|
X3DGeoHelper::add_color(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((X3DNodeElementColor *)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||||
|
else if ((*ch_it)->Type == X3DElemType::ENET_ColorRGBA)
|
||||||
|
X3DGeoHelper::add_color(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((X3DNodeElementColorRGBA *)*ch_it)->Value,
|
||||||
|
tnemesh.ColorPerVertex);
|
||||||
|
else if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
|
||||||
|
} // skip because already read when mesh created.
|
||||||
|
else if ((*ch_it)->Type == X3DElemType::ENET_Normal)
|
||||||
|
X3DGeoHelper::add_normal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((X3DNodeElementNormal *)*ch_it)->Value,
|
||||||
|
tnemesh.NormalPerVertex);
|
||||||
|
else if ((*ch_it)->Type == X3DElemType::ENET_TextureCoordinate)
|
||||||
|
X3DGeoHelper::add_tex_coord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((X3DNodeElementTextureCoordinate *)*ch_it)->Value);
|
||||||
|
else
|
||||||
|
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedFaceSet: " + ai_to_string((*ch_it)->Type) + ".");
|
||||||
|
} // for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it)
|
||||||
|
|
||||||
|
return; // mesh is build, nothing to do anymore.
|
||||||
|
} // if(pNodeElement.Type == X3DElemType::ENET_IndexedFaceSet)
|
||||||
|
|
||||||
|
if (pNodeElement.Type == X3DElemType::ENET_IndexedLineSet) {
|
||||||
|
X3DNodeElementIndexedSet &tnemesh = *((X3DNodeElementIndexedSet *)&pNodeElement); // create alias for convenience
|
||||||
|
|
||||||
|
// at first search for <Coordinate> node and create mesh.
|
||||||
|
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||||
|
if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
|
||||||
|
*pMesh = X3DGeoHelper::make_mesh(tnemesh.CoordIndex, ((X3DNodeElementCoordinate *)*ch_it)->Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy additional information from children
|
||||||
|
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||||
|
ai_assert(*pMesh);
|
||||||
|
if ((*ch_it)->Type == X3DElemType::ENET_Color)
|
||||||
|
X3DGeoHelper::add_color(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((X3DNodeElementColor *)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||||
|
else if ((*ch_it)->Type == X3DElemType::ENET_ColorRGBA)
|
||||||
|
X3DGeoHelper::add_color(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((X3DNodeElementColorRGBA *)*ch_it)->Value,
|
||||||
|
tnemesh.ColorPerVertex);
|
||||||
|
else if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
|
||||||
|
} // skip because already read when mesh created.
|
||||||
|
else
|
||||||
|
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedLineSet: " + ai_to_string((*ch_it)->Type) + ".");
|
||||||
|
} // for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it)
|
||||||
|
|
||||||
|
return; // mesh is build, nothing to do anymore.
|
||||||
|
} // if(pNodeElement.Type == X3DElemType::ENET_IndexedLineSet)
|
||||||
|
|
||||||
|
if ((pNodeElement.Type == X3DElemType::ENET_IndexedTriangleSet) ||
|
||||||
|
(pNodeElement.Type == X3DElemType::ENET_IndexedTriangleFanSet) ||
|
||||||
|
(pNodeElement.Type == X3DElemType::ENET_IndexedTriangleStripSet)) {
|
||||||
|
X3DNodeElementIndexedSet &tnemesh = *((X3DNodeElementIndexedSet *)&pNodeElement); // create alias for convenience
|
||||||
|
|
||||||
|
// at first search for <Coordinate> node and create mesh.
|
||||||
|
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||||
|
if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
|
||||||
|
*pMesh = X3DGeoHelper::make_mesh(tnemesh.CoordIndex, ((X3DNodeElementCoordinate *)*ch_it)->Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy additional information from children
|
||||||
|
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||||
|
ai_assert(*pMesh);
|
||||||
|
if ((*ch_it)->Type == X3DElemType::ENET_Color)
|
||||||
|
X3DGeoHelper::add_color(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((X3DNodeElementColor *)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||||
|
else if ((*ch_it)->Type == X3DElemType::ENET_ColorRGBA)
|
||||||
|
X3DGeoHelper::add_color(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((X3DNodeElementColorRGBA *)*ch_it)->Value,
|
||||||
|
tnemesh.ColorPerVertex);
|
||||||
|
else if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
|
||||||
|
} // skip because already read when mesh created.
|
||||||
|
else if ((*ch_it)->Type == X3DElemType::ENET_Normal)
|
||||||
|
X3DGeoHelper::add_normal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((X3DNodeElementNormal *)*ch_it)->Value,
|
||||||
|
tnemesh.NormalPerVertex);
|
||||||
|
else if ((*ch_it)->Type == X3DElemType::ENET_TextureCoordinate)
|
||||||
|
X3DGeoHelper::add_tex_coord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((X3DNodeElementTextureCoordinate *)*ch_it)->Value);
|
||||||
|
else
|
||||||
|
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedTriangleSet or IndexedTriangleFanSet, or \
|
||||||
|
IndexedTriangleStripSet: " +
|
||||||
|
ai_to_string((*ch_it)->Type) + ".");
|
||||||
|
} // for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it)
|
||||||
|
|
||||||
|
return; // mesh is build, nothing to do anymore.
|
||||||
|
} // if((pNodeElement.Type == X3DElemType::ENET_IndexedTriangleFanSet) || (pNodeElement.Type == X3DElemType::ENET_IndexedTriangleStripSet))
|
||||||
|
|
||||||
|
if (pNodeElement.Type == X3DElemType::ENET_Extrusion) {
|
||||||
|
X3DNodeElementIndexedSet &tnemesh = *((X3DNodeElementIndexedSet *)&pNodeElement); // create alias for convenience
|
||||||
|
|
||||||
|
*pMesh = X3DGeoHelper::make_mesh(tnemesh.CoordIndex, tnemesh.Vertices);
|
||||||
|
|
||||||
|
return; // mesh is build, nothing to do anymore.
|
||||||
|
} // if(pNodeElement.Type == X3DElemType::ENET_Extrusion)
|
||||||
|
|
||||||
|
//
|
||||||
|
// Primitives sets
|
||||||
|
//
|
||||||
|
if (pNodeElement.Type == X3DElemType::ENET_PointSet) {
|
||||||
|
X3DNodeElementSet &tnemesh = *((X3DNodeElementSet *)&pNodeElement); // create alias for convenience
|
||||||
|
|
||||||
|
// at first search for <Coordinate> node and create mesh.
|
||||||
|
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||||
|
if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
|
||||||
|
std::vector<aiVector3D> vec_copy;
|
||||||
|
|
||||||
|
vec_copy.reserve(((X3DNodeElementCoordinate *)*ch_it)->Value.size());
|
||||||
|
for (std::list<aiVector3D>::const_iterator it = ((X3DNodeElementCoordinate *)*ch_it)->Value.begin();
|
||||||
|
it != ((X3DNodeElementCoordinate *)*ch_it)->Value.end(); ++it) {
|
||||||
|
vec_copy.push_back(*it);
|
||||||
|
}
|
||||||
|
|
||||||
|
*pMesh = StandardShapes::MakeMesh(vec_copy, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy additional information from children
|
||||||
|
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||||
|
ai_assert(*pMesh);
|
||||||
|
if ((*ch_it)->Type == X3DElemType::ENET_Color)
|
||||||
|
X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColor *)*ch_it)->Value, true);
|
||||||
|
else if ((*ch_it)->Type == X3DElemType::ENET_ColorRGBA)
|
||||||
|
X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColorRGBA *)*ch_it)->Value, true);
|
||||||
|
else if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
|
||||||
|
} // skip because already read when mesh created.
|
||||||
|
else
|
||||||
|
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of PointSet: " + ai_to_string((*ch_it)->Type) + ".");
|
||||||
|
} // for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it)
|
||||||
|
|
||||||
|
return; // mesh is build, nothing to do anymore.
|
||||||
|
} // if(pNodeElement.Type == X3DElemType::ENET_PointSet)
|
||||||
|
|
||||||
|
if (pNodeElement.Type == X3DElemType::ENET_LineSet) {
|
||||||
|
X3DNodeElementSet &tnemesh = *((X3DNodeElementSet *)&pNodeElement); // create alias for convenience
|
||||||
|
|
||||||
|
// at first search for <Coordinate> node and create mesh.
|
||||||
|
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||||
|
if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
|
||||||
|
*pMesh = X3DGeoHelper::make_mesh(tnemesh.CoordIndex, ((X3DNodeElementCoordinate *)*ch_it)->Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy additional information from children
|
||||||
|
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||||
|
ai_assert(*pMesh);
|
||||||
|
if ((*ch_it)->Type == X3DElemType::ENET_Color)
|
||||||
|
X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColor *)*ch_it)->Value, true);
|
||||||
|
else if ((*ch_it)->Type == X3DElemType::ENET_ColorRGBA)
|
||||||
|
X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColorRGBA *)*ch_it)->Value, true);
|
||||||
|
else if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
|
||||||
|
} // skip because already read when mesh created.
|
||||||
|
else
|
||||||
|
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of LineSet: " + ai_to_string((*ch_it)->Type) + ".");
|
||||||
|
} // for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it)
|
||||||
|
|
||||||
|
return; // mesh is build, nothing to do anymore.
|
||||||
|
} // if(pNodeElement.Type == X3DElemType::ENET_LineSet)
|
||||||
|
|
||||||
|
if (pNodeElement.Type == X3DElemType::ENET_TriangleFanSet) {
|
||||||
|
X3DNodeElementSet &tnemesh = *((X3DNodeElementSet *)&pNodeElement); // create alias for convenience
|
||||||
|
|
||||||
|
// at first search for <Coordinate> node and create mesh.
|
||||||
|
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||||
|
if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
|
||||||
|
*pMesh = X3DGeoHelper::make_mesh(tnemesh.CoordIndex, ((X3DNodeElementCoordinate *)*ch_it)->Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy additional information from children
|
||||||
|
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||||
|
if (nullptr == *pMesh) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((*ch_it)->Type == X3DElemType::ENET_Color)
|
||||||
|
X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColor *)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||||
|
else if ((*ch_it)->Type == X3DElemType::ENET_ColorRGBA)
|
||||||
|
X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColorRGBA *)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||||
|
else if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
|
||||||
|
} // skip because already read when mesh created.
|
||||||
|
else if ((*ch_it)->Type == X3DElemType::ENET_Normal)
|
||||||
|
X3DGeoHelper::add_normal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((X3DNodeElementNormal *)*ch_it)->Value,
|
||||||
|
tnemesh.NormalPerVertex);
|
||||||
|
else if ((*ch_it)->Type == X3DElemType::ENET_TextureCoordinate)
|
||||||
|
X3DGeoHelper::add_tex_coord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((X3DNodeElementTextureCoordinate *)*ch_it)->Value);
|
||||||
|
else
|
||||||
|
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TrianlgeFanSet: " + ai_to_string((*ch_it)->Type) + ".");
|
||||||
|
} // for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it)
|
||||||
|
|
||||||
|
return; // mesh is build, nothing to do anymore.
|
||||||
|
} // if(pNodeElement.Type == X3DElemType::ENET_TriangleFanSet)
|
||||||
|
|
||||||
|
if (pNodeElement.Type == X3DElemType::ENET_TriangleSet) {
|
||||||
|
X3DNodeElementSet &tnemesh = *((X3DNodeElementSet *)&pNodeElement); // create alias for convenience
|
||||||
|
|
||||||
|
// at first search for <Coordinate> node and create mesh.
|
||||||
|
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||||
|
if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
|
||||||
|
std::vector<aiVector3D> vec_copy;
|
||||||
|
|
||||||
|
vec_copy.reserve(((X3DNodeElementCoordinate *)*ch_it)->Value.size());
|
||||||
|
for (std::list<aiVector3D>::const_iterator it = ((X3DNodeElementCoordinate *)*ch_it)->Value.begin();
|
||||||
|
it != ((X3DNodeElementCoordinate *)*ch_it)->Value.end(); ++it) {
|
||||||
|
vec_copy.push_back(*it);
|
||||||
|
}
|
||||||
|
|
||||||
|
*pMesh = StandardShapes::MakeMesh(vec_copy, 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy additional information from children
|
||||||
|
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||||
|
ai_assert(*pMesh);
|
||||||
|
if ((*ch_it)->Type == X3DElemType::ENET_Color)
|
||||||
|
X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColor *)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||||
|
else if ((*ch_it)->Type == X3DElemType::ENET_ColorRGBA)
|
||||||
|
X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColorRGBA *)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||||
|
else if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
|
||||||
|
} // skip because already read when mesh created.
|
||||||
|
else if ((*ch_it)->Type == X3DElemType::ENET_Normal)
|
||||||
|
X3DGeoHelper::add_normal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((X3DNodeElementNormal *)*ch_it)->Value,
|
||||||
|
tnemesh.NormalPerVertex);
|
||||||
|
else if ((*ch_it)->Type == X3DElemType::ENET_TextureCoordinate)
|
||||||
|
X3DGeoHelper::add_tex_coord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((X3DNodeElementTextureCoordinate *)*ch_it)->Value);
|
||||||
|
else
|
||||||
|
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TrianlgeSet: " + ai_to_string((*ch_it)->Type) + ".");
|
||||||
|
} // for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it)
|
||||||
|
|
||||||
|
return; // mesh is build, nothing to do anymore.
|
||||||
|
} // if(pNodeElement.Type == X3DElemType::ENET_TriangleSet)
|
||||||
|
|
||||||
|
if (pNodeElement.Type == X3DElemType::ENET_TriangleStripSet) {
|
||||||
|
X3DNodeElementSet &tnemesh = *((X3DNodeElementSet *)&pNodeElement); // create alias for convenience
|
||||||
|
|
||||||
|
// at first search for <Coordinate> node and create mesh.
|
||||||
|
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||||
|
if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
|
||||||
|
*pMesh = X3DGeoHelper::make_mesh(tnemesh.CoordIndex, ((X3DNodeElementCoordinate *)*ch_it)->Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy additional information from children
|
||||||
|
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||||
|
ai_assert(*pMesh);
|
||||||
|
if ((*ch_it)->Type == X3DElemType::ENET_Color)
|
||||||
|
X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColor *)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||||
|
else if ((*ch_it)->Type == X3DElemType::ENET_ColorRGBA)
|
||||||
|
X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColorRGBA *)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||||
|
else if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
|
||||||
|
} // skip because already read when mesh created.
|
||||||
|
else if ((*ch_it)->Type == X3DElemType::ENET_Normal)
|
||||||
|
X3DGeoHelper::add_normal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((X3DNodeElementNormal *)*ch_it)->Value,
|
||||||
|
tnemesh.NormalPerVertex);
|
||||||
|
else if ((*ch_it)->Type == X3DElemType::ENET_TextureCoordinate)
|
||||||
|
X3DGeoHelper::add_tex_coord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((X3DNodeElementTextureCoordinate *)*ch_it)->Value);
|
||||||
|
else
|
||||||
|
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TriangleStripSet: " + ai_to_string((*ch_it)->Type) + ".");
|
||||||
|
} // for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it)
|
||||||
|
|
||||||
|
return; // mesh is build, nothing to do anymore.
|
||||||
|
} // if(pNodeElement.Type == X3DElemType::ENET_TriangleStripSet)
|
||||||
|
|
||||||
|
throw DeadlyImportError("Postprocess_BuildMesh. Unknown mesh type: " + ai_to_string(pNodeElement.Type) + ".");
|
||||||
|
}
|
||||||
|
|
||||||
|
void X3DImporter::Postprocess_BuildNode(const X3DNodeElementBase &pNodeElement, aiNode &pSceneNode, std::list<aiMesh *> &pSceneMeshList,
|
||||||
|
std::list<aiMaterial *> &pSceneMaterialList, std::list<aiLight *> &pSceneLightList) const {
|
||||||
|
std::list<X3DNodeElementBase *>::const_iterator chit_begin = pNodeElement.Children.begin();
|
||||||
|
std::list<X3DNodeElementBase *>::const_iterator chit_end = pNodeElement.Children.end();
|
||||||
|
std::list<aiNode *> SceneNode_Child;
|
||||||
|
std::list<unsigned int> SceneNode_Mesh;
|
||||||
|
|
||||||
|
// At first read all metadata
|
||||||
|
Postprocess_CollectMetadata(pNodeElement, pSceneNode);
|
||||||
|
// check if we have deal with grouping node. Which can contain transformation or switch
|
||||||
|
if (pNodeElement.Type == X3DElemType::ENET_Group) {
|
||||||
|
const X3DNodeElementGroup &tne_group = *((X3DNodeElementGroup *)&pNodeElement); // create alias for convenience
|
||||||
|
|
||||||
|
pSceneNode.mTransformation = tne_group.Transformation;
|
||||||
|
if (tne_group.UseChoice) {
|
||||||
|
// If Choice is less than zero or greater than the number of nodes in the children field, nothing is chosen.
|
||||||
|
if ((tne_group.Choice < 0) || ((size_t)tne_group.Choice >= pNodeElement.Children.size())) {
|
||||||
|
chit_begin = pNodeElement.Children.end();
|
||||||
|
chit_end = pNodeElement.Children.end();
|
||||||
|
} else {
|
||||||
|
for (size_t i = 0; i < (size_t)tne_group.Choice; i++)
|
||||||
|
++chit_begin; // forward iterator to chosen node.
|
||||||
|
|
||||||
|
chit_end = chit_begin;
|
||||||
|
++chit_end; // point end iterator to next element after chosen node.
|
||||||
|
}
|
||||||
|
} // if(tne_group.UseChoice)
|
||||||
|
} // if(pNodeElement.Type == X3DElemType::ENET_Group)
|
||||||
|
|
||||||
|
// Reserve memory for fast access and check children.
|
||||||
|
for (std::list<X3DNodeElementBase *>::const_iterator it = chit_begin; it != chit_end; ++it) { // in this loop we do not read metadata because it's already read at begin.
|
||||||
|
if ((*it)->Type == X3DElemType::ENET_Group) {
|
||||||
|
// if child is group then create new node and do recursive call.
|
||||||
|
aiNode *new_node = new aiNode;
|
||||||
|
|
||||||
|
new_node->mName = (*it)->ID;
|
||||||
|
new_node->mParent = &pSceneNode;
|
||||||
|
SceneNode_Child.push_back(new_node);
|
||||||
|
Postprocess_BuildNode(**it, *new_node, pSceneMeshList, pSceneMaterialList, pSceneLightList);
|
||||||
|
} else if ((*it)->Type == X3DElemType::ENET_Shape) {
|
||||||
|
// shape can contain only one geometry and one appearance nodes.
|
||||||
|
Postprocess_BuildShape(*((X3DNodeElementShape *)*it), SceneNode_Mesh, pSceneMeshList, pSceneMaterialList);
|
||||||
|
} else if (((*it)->Type == X3DElemType::ENET_DirectionalLight) || ((*it)->Type == X3DElemType::ENET_PointLight) ||
|
||||||
|
((*it)->Type == X3DElemType::ENET_SpotLight)) {
|
||||||
|
Postprocess_BuildLight(*((X3DNodeElementLight *)*it), pSceneLightList);
|
||||||
|
} else if (!PostprocessHelper_ElementIsMetadata((*it)->Type)) // skip metadata
|
||||||
|
{
|
||||||
|
throw DeadlyImportError("Postprocess_BuildNode. Unknown type: " + ai_to_string((*it)->Type) + ".");
|
||||||
|
}
|
||||||
|
} // for(std::list<X3DNodeElementBase*>::const_iterator it = chit_begin; it != chit_end; it++)
|
||||||
|
|
||||||
|
// copy data about children and meshes to aiNode.
|
||||||
|
if (!SceneNode_Child.empty()) {
|
||||||
|
std::list<aiNode *>::const_iterator it = SceneNode_Child.begin();
|
||||||
|
|
||||||
|
pSceneNode.mNumChildren = static_cast<unsigned int>(SceneNode_Child.size());
|
||||||
|
pSceneNode.mChildren = new aiNode *[pSceneNode.mNumChildren];
|
||||||
|
for (size_t i = 0; i < pSceneNode.mNumChildren; i++)
|
||||||
|
pSceneNode.mChildren[i] = *it++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SceneNode_Mesh.empty()) {
|
||||||
|
std::list<unsigned int>::const_iterator it = SceneNode_Mesh.begin();
|
||||||
|
|
||||||
|
pSceneNode.mNumMeshes = static_cast<unsigned int>(SceneNode_Mesh.size());
|
||||||
|
pSceneNode.mMeshes = new unsigned int[pSceneNode.mNumMeshes];
|
||||||
|
for (size_t i = 0; i < pSceneNode.mNumMeshes; i++)
|
||||||
|
pSceneNode.mMeshes[i] = *it++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// that's all. return to previous deals
|
||||||
|
}
|
||||||
|
|
||||||
|
void X3DImporter::Postprocess_BuildShape(const X3DNodeElementShape &pShapeNodeElement, std::list<unsigned int> &pNodeMeshInd,
|
||||||
|
std::list<aiMesh *> &pSceneMeshList, std::list<aiMaterial *> &pSceneMaterialList) const {
|
||||||
|
aiMaterial *tmat = nullptr;
|
||||||
|
aiMesh *tmesh = nullptr;
|
||||||
|
X3DElemType mesh_type = X3DElemType::ENET_Invalid;
|
||||||
|
unsigned int mat_ind = 0;
|
||||||
|
|
||||||
|
for (std::list<X3DNodeElementBase *>::const_iterator it = pShapeNodeElement.Children.begin(); it != pShapeNodeElement.Children.end(); ++it) {
|
||||||
|
if (PostprocessHelper_ElementIsMesh((*it)->Type)) {
|
||||||
|
Postprocess_BuildMesh(**it, &tmesh);
|
||||||
|
if (tmesh != nullptr) {
|
||||||
|
// if mesh successfully built then add data about it to arrays
|
||||||
|
pNodeMeshInd.push_back(static_cast<unsigned int>(pSceneMeshList.size()));
|
||||||
|
pSceneMeshList.push_back(tmesh);
|
||||||
|
// keep mesh type. Need above for texture coordinate generation.
|
||||||
|
mesh_type = (*it)->Type;
|
||||||
|
}
|
||||||
|
} else if ((*it)->Type == X3DElemType::ENET_Appearance) {
|
||||||
|
Postprocess_BuildMaterial(**it, &tmat);
|
||||||
|
if (tmat != nullptr) {
|
||||||
|
// if material successfully built then add data about it to array
|
||||||
|
mat_ind = static_cast<unsigned int>(pSceneMaterialList.size());
|
||||||
|
pSceneMaterialList.push_back(tmat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // for(std::list<X3DNodeElementBase*>::const_iterator it = pShapeNodeElement.Children.begin(); it != pShapeNodeElement.Children.end(); it++)
|
||||||
|
|
||||||
|
// associate read material with read mesh.
|
||||||
|
if ((tmesh != nullptr) && (tmat != nullptr)) {
|
||||||
|
tmesh->mMaterialIndex = mat_ind;
|
||||||
|
// Check texture mapping. If material has texture but mesh has no texture coordinate then try to ask Assimp to generate texture coordinates.
|
||||||
|
if ((tmat->GetTextureCount(aiTextureType_DIFFUSE) != 0) && !tmesh->HasTextureCoords(0)) {
|
||||||
|
int32_t tm;
|
||||||
|
aiVector3D tvec3;
|
||||||
|
|
||||||
|
switch (mesh_type) {
|
||||||
|
case X3DElemType::ENET_Box:
|
||||||
|
tm = aiTextureMapping_BOX;
|
||||||
|
break;
|
||||||
|
case X3DElemType::ENET_Cone:
|
||||||
|
case X3DElemType::ENET_Cylinder:
|
||||||
|
tm = aiTextureMapping_CYLINDER;
|
||||||
|
break;
|
||||||
|
case X3DElemType::ENET_Sphere:
|
||||||
|
tm = aiTextureMapping_SPHERE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
tm = aiTextureMapping_PLANE;
|
||||||
|
break;
|
||||||
|
} // switch(mesh_type)
|
||||||
|
|
||||||
|
tmat->AddProperty(&tm, 1, AI_MATKEY_MAPPING_DIFFUSE(0));
|
||||||
|
} // if((tmat->GetTextureCount(aiTextureType_DIFFUSE) != 0) && !tmesh->HasTextureCoords(0))
|
||||||
|
} // if((tmesh != nullptr) && (tmat != nullptr))
|
||||||
|
}
|
||||||
|
|
||||||
|
void X3DImporter::Postprocess_CollectMetadata(const X3DNodeElementBase &pNodeElement, aiNode &pSceneNode) const {
|
||||||
|
std::list<X3DNodeElementBase *> meta_list;
|
||||||
|
size_t meta_idx;
|
||||||
|
|
||||||
|
PostprocessHelper_CollectMetadata(pNodeElement, meta_list); // find metadata in current node element.
|
||||||
|
if (!meta_list.empty()) {
|
||||||
|
if (pSceneNode.mMetaData != nullptr) {
|
||||||
|
throw DeadlyImportError("Postprocess. MetaData member in node are not nullptr. Something went wrong.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy collected metadata to output node.
|
||||||
|
pSceneNode.mMetaData = aiMetadata::Alloc(static_cast<unsigned int>(meta_list.size()));
|
||||||
|
meta_idx = 0;
|
||||||
|
for (std::list<X3DNodeElementBase *>::const_iterator it = meta_list.begin(); it != meta_list.end(); ++it, ++meta_idx) {
|
||||||
|
X3DNodeElementMeta *cur_meta = (X3DNodeElementMeta *)*it;
|
||||||
|
|
||||||
|
// due to limitations we can add only first element of value list.
|
||||||
|
// Add an element according to its type.
|
||||||
|
if ((*it)->Type == X3DElemType::ENET_MetaBoolean) {
|
||||||
|
if (((X3DNodeElementMetaBoolean *)cur_meta)->Value.size() > 0)
|
||||||
|
pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, *(((X3DNodeElementMetaBoolean *)cur_meta)->Value.begin()));
|
||||||
|
} else if ((*it)->Type == X3DElemType::ENET_MetaDouble) {
|
||||||
|
if (((X3DNodeElementMetaDouble *)cur_meta)->Value.size() > 0)
|
||||||
|
pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, (float)*(((X3DNodeElementMetaDouble *)cur_meta)->Value.begin()));
|
||||||
|
} else if ((*it)->Type == X3DElemType::ENET_MetaFloat) {
|
||||||
|
if (((X3DNodeElementMetaFloat *)cur_meta)->Value.size() > 0)
|
||||||
|
pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, *(((X3DNodeElementMetaFloat *)cur_meta)->Value.begin()));
|
||||||
|
} else if ((*it)->Type == X3DElemType::ENET_MetaInteger) {
|
||||||
|
if (((X3DNodeElementMetaInt *)cur_meta)->Value.size() > 0)
|
||||||
|
pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, *(((X3DNodeElementMetaInt *)cur_meta)->Value.begin()));
|
||||||
|
} else if ((*it)->Type == X3DElemType::ENET_MetaString) {
|
||||||
|
if (((X3DNodeElementMetaString *)cur_meta)->Value.size() > 0) {
|
||||||
|
aiString tstr(((X3DNodeElementMetaString *)cur_meta)->Value.begin()->data());
|
||||||
|
|
||||||
|
pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, tstr);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw DeadlyImportError("Postprocess. Unknown metadata type.");
|
||||||
|
} // if((*it)->Type == X3DElemType::ENET_Meta*) else
|
||||||
|
} // for(std::list<X3DNodeElementBase*>::const_iterator it = meta_list.begin(); it != meta_list.end(); it++)
|
||||||
|
} // if( !meta_list.empty() )
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Assimp
|
||||||
|
|
||||||
|
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
@ -0,0 +1,987 @@
|
||||||
|
/*
|
||||||
|
Open Asset Import Library (assimp)
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2019, assimp team
|
||||||
|
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
with or without modification, are permitted provided that the
|
||||||
|
following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer in the documentation and/or other
|
||||||
|
materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of the assimp team, nor the names of its
|
||||||
|
contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior
|
||||||
|
written permission of the assimp team.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
/// \file X3DImporter_Rendering.cpp
|
||||||
|
/// \brief Parsing data from nodes of "Rendering" set of X3D.
|
||||||
|
/// \date 2015-2016
|
||||||
|
/// \author smal.root@gmail.com
|
||||||
|
|
||||||
|
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||||
|
|
||||||
|
#include "X3DImporter.hpp"
|
||||||
|
#include "X3DImporter_Macro.hpp"
|
||||||
|
#include "X3DXmlHelper.h"
|
||||||
|
|
||||||
|
namespace Assimp {
|
||||||
|
|
||||||
|
// <Color
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// color="" MFColor [inputOutput]
|
||||||
|
// />
|
||||||
|
void X3DImporter::readColor(XmlNode &node) {
|
||||||
|
std::string use, def;
|
||||||
|
std::list<aiColor3D> color;
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
X3DXmlHelper::getColor3DListAttribute(node, "color", color);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty()) {
|
||||||
|
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Color, ne);
|
||||||
|
} else {
|
||||||
|
// create and if needed - define new geometry object.
|
||||||
|
ne = new X3DNodeElementColor(mNodeElementCur);
|
||||||
|
if (!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
((X3DNodeElementColor *)ne)->Value = color;
|
||||||
|
// check for X3DMetadataObject childs.
|
||||||
|
if (!isNodeEmpty(node))
|
||||||
|
childrenReadMetadata(node, ne, "Color");
|
||||||
|
else
|
||||||
|
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
// <ColorRGBA
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// color="" MFColorRGBA [inputOutput]
|
||||||
|
// />
|
||||||
|
void X3DImporter::readColorRGBA(XmlNode &node) {
|
||||||
|
std::string use, def;
|
||||||
|
std::list<aiColor4D> color;
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
X3DXmlHelper::getColor4DListAttribute(node, "color", color);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty()) {
|
||||||
|
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_ColorRGBA, ne);
|
||||||
|
} else {
|
||||||
|
// create and if needed - define new geometry object.
|
||||||
|
ne = new X3DNodeElementColorRGBA(mNodeElementCur);
|
||||||
|
if (!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
((X3DNodeElementColorRGBA *)ne)->Value = color;
|
||||||
|
// check for X3DMetadataObject childs.
|
||||||
|
if (!isNodeEmpty(node))
|
||||||
|
childrenReadMetadata(node, ne, "ColorRGBA");
|
||||||
|
else
|
||||||
|
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
// <Coordinate
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// point="" MFVec3f [inputOutput]
|
||||||
|
// />
|
||||||
|
void X3DImporter::readCoordinate(XmlNode &node) {
|
||||||
|
std::string use, def;
|
||||||
|
std::list<aiVector3D> point;
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
X3DXmlHelper::getVector3DListAttribute(node, "point", point);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty()) {
|
||||||
|
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Coordinate, ne);
|
||||||
|
} else {
|
||||||
|
// create and if needed - define new geometry object.
|
||||||
|
ne = new X3DNodeElementCoordinate(mNodeElementCur);
|
||||||
|
if (!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
((X3DNodeElementCoordinate *)ne)->Value = point;
|
||||||
|
// check for X3DMetadataObject childs.
|
||||||
|
if (!isNodeEmpty(node))
|
||||||
|
childrenReadMetadata(node, ne, "Coordinate");
|
||||||
|
else
|
||||||
|
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
// <IndexedLineSet
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// colorIndex="" MFInt32 [initializeOnly]
|
||||||
|
// colorPerVertex="true" SFBool [initializeOnly]
|
||||||
|
// coordIndex="" MFInt32 [initializeOnly]
|
||||||
|
// >
|
||||||
|
// <!-- ColorCoordinateContentModel -->
|
||||||
|
// ColorCoordinateContentModel is the child-node content model corresponding to IndexedLineSet, LineSet and PointSet. ColorCoordinateContentModel can
|
||||||
|
// contain any-order Coordinate node with Color (or ColorRGBA) node. No more than one instance of any single node type is allowed.
|
||||||
|
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
||||||
|
// </IndexedLineSet>
|
||||||
|
void X3DImporter::readIndexedLineSet(XmlNode &node) {
|
||||||
|
std::string use, def;
|
||||||
|
std::vector<int32_t> colorIndex;
|
||||||
|
bool colorPerVertex = true;
|
||||||
|
std::vector<int32_t> coordIndex;
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
X3DXmlHelper::getInt32ArrayAttribute(node, "colorIndex", colorIndex);
|
||||||
|
XmlParser::getBoolAttribute(node, "colorPerVertex", colorPerVertex);
|
||||||
|
X3DXmlHelper::getInt32ArrayAttribute(node, "coordIndex", coordIndex);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty()) {
|
||||||
|
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedLineSet, ne);
|
||||||
|
} else {
|
||||||
|
// check data
|
||||||
|
if ((coordIndex.size() < 2) || ((coordIndex.back() == (-1)) && (coordIndex.size() < 3)))
|
||||||
|
throw DeadlyImportError("IndexedLineSet must contain not empty \"coordIndex\" attribute.");
|
||||||
|
|
||||||
|
// create and if needed - define new geometry object.
|
||||||
|
ne = new X3DNodeElementIndexedSet(X3DElemType::ENET_IndexedLineSet, mNodeElementCur);
|
||||||
|
if (!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
X3DNodeElementIndexedSet &ne_alias = *((X3DNodeElementIndexedSet *)ne);
|
||||||
|
|
||||||
|
ne_alias.ColorIndex = colorIndex;
|
||||||
|
ne_alias.ColorPerVertex = colorPerVertex;
|
||||||
|
ne_alias.CoordIndex = coordIndex;
|
||||||
|
// check for child nodes
|
||||||
|
if (!isNodeEmpty(node)) {
|
||||||
|
ParseHelper_Node_Enter(ne);
|
||||||
|
for (auto currentChildNode : node.children()) {
|
||||||
|
const std::string ¤tChildName = currentChildNode.name();
|
||||||
|
// check for Color and Coordinate nodes
|
||||||
|
if (currentChildName == "Color")
|
||||||
|
readColor(currentChildNode);
|
||||||
|
else if (currentChildName == "ColorRGBA")
|
||||||
|
readColorRGBA(currentChildNode);
|
||||||
|
else if (currentChildName == "Coordinate")
|
||||||
|
readCoordinate(currentChildNode);
|
||||||
|
// check for X3DMetadataObject
|
||||||
|
else if (!checkForMetadataNode(currentChildNode))
|
||||||
|
skipUnsupportedNode("IndexedLineSet", currentChildNode);
|
||||||
|
}
|
||||||
|
ParseHelper_Node_Exit();
|
||||||
|
} // if(!isNodeEmpty(node))
|
||||||
|
else {
|
||||||
|
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
// <IndexedTriangleFanSet
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// ccw="true" SFBool [initializeOnly]
|
||||||
|
// colorPerVertex="true" SFBool [initializeOnly]
|
||||||
|
// index="" MFInt32 [initializeOnly]
|
||||||
|
// normalPerVertex="true" SFBool [initializeOnly]
|
||||||
|
// solid="true" SFBool [initializeOnly]
|
||||||
|
// >
|
||||||
|
// <!-- ComposedGeometryContentModel -->
|
||||||
|
// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
|
||||||
|
// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
|
||||||
|
// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
|
||||||
|
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
||||||
|
// </IndexedTriangleFanSet>
|
||||||
|
void X3DImporter::readIndexedTriangleFanSet(XmlNode &node) {
|
||||||
|
std::string use, def;
|
||||||
|
bool ccw = true;
|
||||||
|
bool colorPerVertex = true;
|
||||||
|
std::vector<int32_t> index;
|
||||||
|
bool normalPerVertex = true;
|
||||||
|
bool solid = true;
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
XmlParser::getBoolAttribute(node, "ccw", ccw);
|
||||||
|
XmlParser::getBoolAttribute(node, "colorPerVertex", colorPerVertex);
|
||||||
|
X3DXmlHelper::getInt32ArrayAttribute(node, "index", index);
|
||||||
|
XmlParser::getBoolAttribute(node, "normalPerVertex", normalPerVertex);
|
||||||
|
XmlParser::getBoolAttribute(node, "solid", solid);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty()) {
|
||||||
|
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.");
|
||||||
|
|
||||||
|
// create and if needed - define new geometry object.
|
||||||
|
ne = new X3DNodeElementIndexedSet(X3DElemType::ENET_IndexedTriangleFanSet, mNodeElementCur);
|
||||||
|
if (!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
X3DNodeElementIndexedSet &ne_alias = *((X3DNodeElementIndexedSet *)ne);
|
||||||
|
|
||||||
|
ne_alias.CCW = ccw;
|
||||||
|
ne_alias.ColorPerVertex = colorPerVertex;
|
||||||
|
ne_alias.NormalPerVertex = normalPerVertex;
|
||||||
|
ne_alias.Solid = solid;
|
||||||
|
|
||||||
|
ne_alias.CoordIndex.clear();
|
||||||
|
int counter = 0;
|
||||||
|
int32_t idx[3];
|
||||||
|
for (std::vector<int32_t>::const_iterator idx_it = index.begin(); idx_it != index.end(); ++idx_it) {
|
||||||
|
idx[2] = *idx_it;
|
||||||
|
if (idx[2] < 0) {
|
||||||
|
counter = 0;
|
||||||
|
} else {
|
||||||
|
if (counter >= 2) {
|
||||||
|
if (ccw) {
|
||||||
|
ne_alias.CoordIndex.push_back(idx[0]);
|
||||||
|
ne_alias.CoordIndex.push_back(idx[1]);
|
||||||
|
ne_alias.CoordIndex.push_back(idx[2]);
|
||||||
|
} else {
|
||||||
|
ne_alias.CoordIndex.push_back(idx[0]);
|
||||||
|
ne_alias.CoordIndex.push_back(idx[2]);
|
||||||
|
ne_alias.CoordIndex.push_back(idx[1]);
|
||||||
|
}
|
||||||
|
ne_alias.CoordIndex.push_back(-1);
|
||||||
|
idx[1] = idx[2];
|
||||||
|
} else {
|
||||||
|
idx[counter] = idx[2];
|
||||||
|
}
|
||||||
|
++counter;
|
||||||
|
}
|
||||||
|
} // for(std::list<int32_t>::const_iterator idx_it = index.begin(); idx_it != ne_alias.index.end(); idx_it++)
|
||||||
|
|
||||||
|
// check for child nodes
|
||||||
|
if (!isNodeEmpty(node)) {
|
||||||
|
ParseHelper_Node_Enter(ne);
|
||||||
|
for (auto currentChildNode : node.children()) {
|
||||||
|
const std::string ¤tChildName = currentChildNode.name();
|
||||||
|
// check for X3DComposedGeometryNodes
|
||||||
|
if (currentChildName == "Color")
|
||||||
|
readColor(currentChildNode);
|
||||||
|
else if (currentChildName == "ColorRGBA")
|
||||||
|
readColorRGBA(currentChildNode);
|
||||||
|
else if (currentChildName == "Coordinate")
|
||||||
|
readCoordinate(currentChildNode);
|
||||||
|
else if (currentChildName == "Normal")
|
||||||
|
readNormal(currentChildNode);
|
||||||
|
else if (currentChildName == "TextureCoordinate")
|
||||||
|
readTextureCoordinate(currentChildNode);
|
||||||
|
// check for X3DMetadataObject
|
||||||
|
else if (!checkForMetadataNode(currentChildNode))
|
||||||
|
skipUnsupportedNode("IndexedTriangleFanSet", currentChildNode);
|
||||||
|
}
|
||||||
|
ParseHelper_Node_Exit();
|
||||||
|
} // if(!isNodeEmpty(node))
|
||||||
|
else {
|
||||||
|
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
// <IndexedTriangleSet
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// ccw="true" SFBool [initializeOnly]
|
||||||
|
// colorPerVertex="true" SFBool [initializeOnly]
|
||||||
|
// index="" MFInt32 [initializeOnly]
|
||||||
|
// normalPerVertex="true" SFBool [initializeOnly]
|
||||||
|
// solid="true" SFBool [initializeOnly]
|
||||||
|
// >
|
||||||
|
// <!-- ComposedGeometryContentModel -->
|
||||||
|
// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
|
||||||
|
// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
|
||||||
|
// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
|
||||||
|
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
||||||
|
// </IndexedTriangleSet>
|
||||||
|
void X3DImporter::readIndexedTriangleSet(XmlNode &node) {
|
||||||
|
std::string use, def;
|
||||||
|
bool ccw = true;
|
||||||
|
bool colorPerVertex = true;
|
||||||
|
std::vector<int32_t> index;
|
||||||
|
bool normalPerVertex = true;
|
||||||
|
bool solid = true;
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
XmlParser::getBoolAttribute(node, "ccw", ccw);
|
||||||
|
XmlParser::getBoolAttribute(node, "colorPerVertex", colorPerVertex);
|
||||||
|
X3DXmlHelper::getInt32ArrayAttribute(node, "index", index);
|
||||||
|
XmlParser::getBoolAttribute(node, "normalPerVertex", normalPerVertex);
|
||||||
|
XmlParser::getBoolAttribute(node, "solid", solid);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty()) {
|
||||||
|
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.");
|
||||||
|
|
||||||
|
// create and if needed - define new geometry object.
|
||||||
|
ne = new X3DNodeElementIndexedSet(X3DElemType::ENET_IndexedTriangleSet, mNodeElementCur);
|
||||||
|
if (!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
X3DNodeElementIndexedSet &ne_alias = *((X3DNodeElementIndexedSet *)ne);
|
||||||
|
|
||||||
|
ne_alias.CCW = ccw;
|
||||||
|
ne_alias.ColorPerVertex = colorPerVertex;
|
||||||
|
ne_alias.NormalPerVertex = normalPerVertex;
|
||||||
|
ne_alias.Solid = solid;
|
||||||
|
|
||||||
|
ne_alias.CoordIndex.clear();
|
||||||
|
int counter = 0;
|
||||||
|
int32_t idx[3];
|
||||||
|
for (std::vector<int32_t>::const_iterator idx_it = index.begin(); idx_it != index.end(); ++idx_it) {
|
||||||
|
idx[counter++] = *idx_it;
|
||||||
|
if (counter > 2) {
|
||||||
|
counter = 0;
|
||||||
|
if (ccw) {
|
||||||
|
ne_alias.CoordIndex.push_back(idx[0]);
|
||||||
|
ne_alias.CoordIndex.push_back(idx[1]);
|
||||||
|
ne_alias.CoordIndex.push_back(idx[2]);
|
||||||
|
} else {
|
||||||
|
ne_alias.CoordIndex.push_back(idx[0]);
|
||||||
|
ne_alias.CoordIndex.push_back(idx[2]);
|
||||||
|
ne_alias.CoordIndex.push_back(idx[1]);
|
||||||
|
}
|
||||||
|
ne_alias.CoordIndex.push_back(-1);
|
||||||
|
}
|
||||||
|
} // for(std::list<int32_t>::const_iterator idx_it = index.begin(); idx_it != ne_alias.index.end(); idx_it++)
|
||||||
|
|
||||||
|
// check for child nodes
|
||||||
|
if (!isNodeEmpty(node)) {
|
||||||
|
ParseHelper_Node_Enter(ne);
|
||||||
|
for (auto currentChildNode : node.children()) {
|
||||||
|
const std::string ¤tChildName = currentChildNode.name();
|
||||||
|
// check for X3DComposedGeometryNodes
|
||||||
|
if (currentChildName == "Color")
|
||||||
|
readColor(currentChildNode);
|
||||||
|
else if (currentChildName == "ColorRGBA")
|
||||||
|
readColorRGBA(currentChildNode);
|
||||||
|
else if (currentChildName == "Coordinate")
|
||||||
|
readCoordinate(currentChildNode);
|
||||||
|
else if (currentChildName == "Normal")
|
||||||
|
readNormal(currentChildNode);
|
||||||
|
else if (currentChildName == "TextureCoordinate")
|
||||||
|
readTextureCoordinate(currentChildNode);
|
||||||
|
// check for X3DMetadataObject
|
||||||
|
else if (!checkForMetadataNode(currentChildNode))
|
||||||
|
skipUnsupportedNode("IndexedTriangleSet", currentChildNode);
|
||||||
|
}
|
||||||
|
ParseHelper_Node_Exit();
|
||||||
|
} // if(!isNodeEmpty(node))
|
||||||
|
else {
|
||||||
|
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
// <IndexedTriangleStripSet
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// ccw="true" SFBool [initializeOnly]
|
||||||
|
// colorPerVertex="true" SFBool [initializeOnly]
|
||||||
|
// index="" MFInt32 [initializeOnly]
|
||||||
|
// normalPerVertex="true" SFBool [initializeOnly]
|
||||||
|
// solid="true" SFBool [initializeOnly]
|
||||||
|
// >
|
||||||
|
// <!-- ComposedGeometryContentModel -->
|
||||||
|
// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
|
||||||
|
// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
|
||||||
|
// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
|
||||||
|
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
||||||
|
// </IndexedTriangleStripSet>
|
||||||
|
void X3DImporter::readIndexedTriangleStripSet(XmlNode &node) {
|
||||||
|
std::string use, def;
|
||||||
|
bool ccw = true;
|
||||||
|
bool colorPerVertex = true;
|
||||||
|
std::vector<int32_t> index;
|
||||||
|
bool normalPerVertex = true;
|
||||||
|
bool solid = true;
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
XmlParser::getBoolAttribute(node, "ccw", ccw);
|
||||||
|
XmlParser::getBoolAttribute(node, "colorPerVertex", colorPerVertex);
|
||||||
|
X3DXmlHelper::getInt32ArrayAttribute(node, "index", index);
|
||||||
|
XmlParser::getBoolAttribute(node, "normalPerVertex", normalPerVertex);
|
||||||
|
XmlParser::getBoolAttribute(node, "solid", solid);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty()) {
|
||||||
|
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.");
|
||||||
|
|
||||||
|
// create and if needed - define new geometry object.
|
||||||
|
ne = new X3DNodeElementIndexedSet(X3DElemType::ENET_IndexedTriangleStripSet, mNodeElementCur);
|
||||||
|
if (!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
X3DNodeElementIndexedSet &ne_alias = *((X3DNodeElementIndexedSet *)ne);
|
||||||
|
|
||||||
|
ne_alias.CCW = ccw;
|
||||||
|
ne_alias.ColorPerVertex = colorPerVertex;
|
||||||
|
ne_alias.NormalPerVertex = normalPerVertex;
|
||||||
|
ne_alias.Solid = solid;
|
||||||
|
|
||||||
|
ne_alias.CoordIndex.clear();
|
||||||
|
int counter = 0;
|
||||||
|
int32_t idx[3];
|
||||||
|
for (std::vector<int32_t>::const_iterator idx_it = index.begin(); idx_it != index.end(); ++idx_it) {
|
||||||
|
idx[2] = *idx_it;
|
||||||
|
if (idx[2] < 0) {
|
||||||
|
counter = 0;
|
||||||
|
} else {
|
||||||
|
if (counter >= 2) {
|
||||||
|
if (ccw) {
|
||||||
|
ne_alias.CoordIndex.push_back(idx[0]);
|
||||||
|
ne_alias.CoordIndex.push_back(idx[1]);
|
||||||
|
ne_alias.CoordIndex.push_back(idx[2]);
|
||||||
|
} else {
|
||||||
|
ne_alias.CoordIndex.push_back(idx[0]);
|
||||||
|
ne_alias.CoordIndex.push_back(idx[2]);
|
||||||
|
ne_alias.CoordIndex.push_back(idx[1]);
|
||||||
|
}
|
||||||
|
ne_alias.CoordIndex.push_back(-1);
|
||||||
|
}
|
||||||
|
idx[counter & 1] = idx[2];
|
||||||
|
++counter;
|
||||||
|
}
|
||||||
|
} // for(std::list<int32_t>::const_iterator idx_it = index.begin(); idx_it != ne_alias.index.end(); idx_it++)
|
||||||
|
|
||||||
|
// check for child nodes
|
||||||
|
if (!isNodeEmpty(node)) {
|
||||||
|
ParseHelper_Node_Enter(ne);
|
||||||
|
for (auto currentChildNode : node.children()) {
|
||||||
|
const std::string ¤tChildName = currentChildNode.name();
|
||||||
|
// check for X3DComposedGeometryNodes
|
||||||
|
if (currentChildName == "Color")
|
||||||
|
readColor(currentChildNode);
|
||||||
|
else if (currentChildName == "ColorRGBA")
|
||||||
|
readColorRGBA(currentChildNode);
|
||||||
|
else if (currentChildName == "Coordinate")
|
||||||
|
readCoordinate(currentChildNode);
|
||||||
|
else if (currentChildName == "Normal")
|
||||||
|
readNormal(currentChildNode);
|
||||||
|
else if (currentChildName == "TextureCoordinate")
|
||||||
|
readTextureCoordinate(currentChildNode);
|
||||||
|
// check for X3DMetadataObject
|
||||||
|
else if (!checkForMetadataNode(currentChildNode))
|
||||||
|
skipUnsupportedNode("IndexedTriangleStripSet", currentChildNode);
|
||||||
|
}
|
||||||
|
ParseHelper_Node_Exit();
|
||||||
|
} // if(!isNodeEmpty(node))
|
||||||
|
else {
|
||||||
|
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
// <LineSet
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// vertexCount="" MFInt32 [initializeOnly]
|
||||||
|
// >
|
||||||
|
// <!-- ColorCoordinateContentModel -->
|
||||||
|
// ColorCoordinateContentModel is the child-node content model corresponding to IndexedLineSet, LineSet and PointSet. ColorCoordinateContentModel can
|
||||||
|
// contain any-order Coordinate node with Color (or ColorRGBA) node. No more than one instance of any single node type is allowed.
|
||||||
|
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
||||||
|
// </LineSet>
|
||||||
|
void X3DImporter::readLineSet(XmlNode &node) {
|
||||||
|
std::string use, def;
|
||||||
|
std::vector<int32_t> vertexCount;
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
X3DXmlHelper::getInt32ArrayAttribute(node, "vertexCount", vertexCount);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty()) {
|
||||||
|
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.");
|
||||||
|
|
||||||
|
// create and if needed - define new geometry object.
|
||||||
|
ne = new X3DNodeElementSet(X3DElemType::ENET_LineSet, mNodeElementCur);
|
||||||
|
if (!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
X3DNodeElementSet &ne_alias = *((X3DNodeElementSet *)ne);
|
||||||
|
|
||||||
|
ne_alias.VertexCount = vertexCount;
|
||||||
|
// create CoordIdx
|
||||||
|
size_t coord_num = 0;
|
||||||
|
|
||||||
|
ne_alias.CoordIndex.clear();
|
||||||
|
for (std::vector<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); ++vc_it) {
|
||||||
|
if (*vc_it < 2) throw DeadlyImportError("LineSet. vertexCount shall be greater than or equal to two.");
|
||||||
|
|
||||||
|
for (int32_t i = 0; i < *vc_it; i++)
|
||||||
|
ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num++)); // add vertices indices
|
||||||
|
|
||||||
|
ne_alias.CoordIndex.push_back(-1); // add face delimiter.
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for child nodes
|
||||||
|
if (!isNodeEmpty(node)) {
|
||||||
|
ParseHelper_Node_Enter(ne);
|
||||||
|
for (auto currentChildNode : node.children()) {
|
||||||
|
const std::string ¤tChildName = currentChildNode.name();
|
||||||
|
// check for X3DComposedGeometryNodes
|
||||||
|
if (currentChildName == "Color")
|
||||||
|
readColor(currentChildNode);
|
||||||
|
else if (currentChildName == "ColorRGBA")
|
||||||
|
readColorRGBA(currentChildNode);
|
||||||
|
else if (currentChildName == "Coordinate")
|
||||||
|
readCoordinate(currentChildNode);
|
||||||
|
// check for X3DMetadataObject
|
||||||
|
else if (!checkForMetadataNode(currentChildNode))
|
||||||
|
skipUnsupportedNode("LineSet", currentChildNode);
|
||||||
|
}
|
||||||
|
ParseHelper_Node_Exit();
|
||||||
|
} // if(!isNodeEmpty(node))
|
||||||
|
else {
|
||||||
|
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
// <PointSet
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// >
|
||||||
|
// <!-- ColorCoordinateContentModel -->
|
||||||
|
// ColorCoordinateContentModel is the child-node content model corresponding to IndexedLineSet, LineSet and PointSet. ColorCoordinateContentModel can
|
||||||
|
// contain any-order Coordinate node with Color (or ColorRGBA) node. No more than one instance of any single node type is allowed.
|
||||||
|
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
||||||
|
// </PointSet>
|
||||||
|
void X3DImporter::readPointSet(XmlNode &node) {
|
||||||
|
std::string use, def;
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty()) {
|
||||||
|
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_PointSet, ne);
|
||||||
|
} else {
|
||||||
|
// create and if needed - define new geometry object.
|
||||||
|
ne = new X3DNodeElementIndexedSet(X3DElemType::ENET_PointSet, mNodeElementCur);
|
||||||
|
if (!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
// check for child nodes
|
||||||
|
if (!isNodeEmpty(node)) {
|
||||||
|
ParseHelper_Node_Enter(ne);
|
||||||
|
for (auto currentChildNode : node.children()) {
|
||||||
|
const std::string ¤tChildName = currentChildNode.name();
|
||||||
|
// check for X3DComposedGeometryNodes
|
||||||
|
if (currentChildName == "Color")
|
||||||
|
readColor(currentChildNode);
|
||||||
|
else if (currentChildName == "ColorRGBA")
|
||||||
|
readColorRGBA(currentChildNode);
|
||||||
|
else if (currentChildName == "Coordinate")
|
||||||
|
readCoordinate(currentChildNode);
|
||||||
|
// check for X3DMetadataObject
|
||||||
|
else if (!checkForMetadataNode(currentChildNode))
|
||||||
|
skipUnsupportedNode("PointSet", currentChildNode);
|
||||||
|
}
|
||||||
|
ParseHelper_Node_Exit();
|
||||||
|
} // if(!isNodeEmpty(node))
|
||||||
|
else {
|
||||||
|
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
// <TriangleFanSet
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// ccw="true" SFBool [initializeOnly]
|
||||||
|
// colorPerVertex="true" SFBool [initializeOnly]
|
||||||
|
// fanCount="" MFInt32 [inputOutput]
|
||||||
|
// normalPerVertex="true" SFBool [initializeOnly]
|
||||||
|
// solid="true" SFBool [initializeOnly]
|
||||||
|
// >
|
||||||
|
// <!-- ComposedGeometryContentModel -->
|
||||||
|
// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
|
||||||
|
// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
|
||||||
|
// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
|
||||||
|
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
||||||
|
// </TriangleFanSet>
|
||||||
|
void X3DImporter::readTriangleFanSet(XmlNode &node) {
|
||||||
|
std::string use, def;
|
||||||
|
bool ccw = true;
|
||||||
|
bool colorPerVertex = true;
|
||||||
|
std::vector<int32_t> fanCount;
|
||||||
|
bool normalPerVertex = true;
|
||||||
|
bool solid = true;
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
XmlParser::getBoolAttribute(node, "ccw", ccw);
|
||||||
|
XmlParser::getBoolAttribute(node, "colorPerVertex", colorPerVertex);
|
||||||
|
X3DXmlHelper::getInt32ArrayAttribute(node, "fanCount", fanCount);
|
||||||
|
XmlParser::getBoolAttribute(node, "normalPerVertex", normalPerVertex);
|
||||||
|
XmlParser::getBoolAttribute(node, "solid", solid);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty()) {
|
||||||
|
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.");
|
||||||
|
|
||||||
|
// create and if needed - define new geometry object.
|
||||||
|
ne = new X3DNodeElementSet(X3DElemType::ENET_TriangleFanSet, mNodeElementCur);
|
||||||
|
if (!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
X3DNodeElementSet &ne_alias = *((X3DNodeElementSet *)ne);
|
||||||
|
|
||||||
|
ne_alias.CCW = ccw;
|
||||||
|
ne_alias.ColorPerVertex = colorPerVertex;
|
||||||
|
ne_alias.VertexCount = fanCount;
|
||||||
|
ne_alias.NormalPerVertex = normalPerVertex;
|
||||||
|
ne_alias.Solid = solid;
|
||||||
|
// create CoordIdx
|
||||||
|
size_t coord_num_first, coord_num_prev;
|
||||||
|
|
||||||
|
ne_alias.CoordIndex.clear();
|
||||||
|
// assign indices for first triangle
|
||||||
|
coord_num_first = 0;
|
||||||
|
coord_num_prev = 1;
|
||||||
|
for (std::vector<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); ++vc_it) {
|
||||||
|
if (*vc_it < 3) throw DeadlyImportError("TriangleFanSet. fanCount shall be greater than or equal to three.");
|
||||||
|
|
||||||
|
for (int32_t vc = 2; vc < *vc_it; vc++) {
|
||||||
|
if (ccw) {
|
||||||
|
// 2 1
|
||||||
|
// 0
|
||||||
|
ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num_first)); // first vertex is a center and always is [0].
|
||||||
|
ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num_prev++));
|
||||||
|
ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num_prev));
|
||||||
|
} else {
|
||||||
|
// 1 2
|
||||||
|
// 0
|
||||||
|
ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num_first)); // first vertex is a center and always is [0].
|
||||||
|
ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num_prev + 1));
|
||||||
|
ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num_prev++));
|
||||||
|
} // if(ccw) else
|
||||||
|
|
||||||
|
ne_alias.CoordIndex.push_back(-1); // add face delimiter.
|
||||||
|
} // for(int32_t vc = 2; vc < *vc_it; vc++)
|
||||||
|
|
||||||
|
coord_num_prev++; // that index will be center of next fan
|
||||||
|
coord_num_first = coord_num_prev++; // forward to next point - second point of fan
|
||||||
|
} // for(std::list<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); vc_it++)
|
||||||
|
// check for child nodes
|
||||||
|
if (!isNodeEmpty(node)) {
|
||||||
|
ParseHelper_Node_Enter(ne);
|
||||||
|
for (auto currentChildNode : node.children()) {
|
||||||
|
const std::string ¤tChildName = currentChildNode.name();
|
||||||
|
// check for X3DComposedGeometryNodes
|
||||||
|
if (currentChildName == "Color")
|
||||||
|
readColor(currentChildNode);
|
||||||
|
else if (currentChildName == "ColorRGBA")
|
||||||
|
readColorRGBA(currentChildNode);
|
||||||
|
else if (currentChildName == "Coordinate")
|
||||||
|
readCoordinate(currentChildNode);
|
||||||
|
else if (currentChildName == "Normal")
|
||||||
|
readNormal(currentChildNode);
|
||||||
|
else if (currentChildName == "TextureCoordinate")
|
||||||
|
readTextureCoordinate(currentChildNode);
|
||||||
|
// check for X3DMetadataObject
|
||||||
|
else if (!checkForMetadataNode(currentChildNode))
|
||||||
|
skipUnsupportedNode("TriangleFanSet", currentChildNode);
|
||||||
|
}
|
||||||
|
ParseHelper_Node_Exit();
|
||||||
|
} // if(!isNodeEmpty(node))
|
||||||
|
else {
|
||||||
|
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
// <TriangleSet
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// ccw="true" SFBool [initializeOnly]
|
||||||
|
// colorPerVertex="true" SFBool [initializeOnly]
|
||||||
|
// normalPerVertex="true" SFBool [initializeOnly]
|
||||||
|
// solid="true" SFBool [initializeOnly]
|
||||||
|
// >
|
||||||
|
// <!-- ComposedGeometryContentModel -->
|
||||||
|
// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
|
||||||
|
// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
|
||||||
|
// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
|
||||||
|
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
||||||
|
// </TriangleSet>
|
||||||
|
void X3DImporter::readTriangleSet(XmlNode &node) {
|
||||||
|
std::string use, def;
|
||||||
|
bool ccw = true;
|
||||||
|
bool colorPerVertex = true;
|
||||||
|
bool normalPerVertex = true;
|
||||||
|
bool solid = true;
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
XmlParser::getBoolAttribute(node, "ccw", ccw);
|
||||||
|
XmlParser::getBoolAttribute(node, "colorPerVertex", colorPerVertex);
|
||||||
|
XmlParser::getBoolAttribute(node, "normalPerVertex", normalPerVertex);
|
||||||
|
XmlParser::getBoolAttribute(node, "solid", solid);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty()) {
|
||||||
|
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);
|
||||||
|
if (!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
X3DNodeElementSet &ne_alias = *((X3DNodeElementSet *)ne);
|
||||||
|
|
||||||
|
ne_alias.CCW = ccw;
|
||||||
|
ne_alias.ColorPerVertex = colorPerVertex;
|
||||||
|
ne_alias.NormalPerVertex = normalPerVertex;
|
||||||
|
ne_alias.Solid = solid;
|
||||||
|
// check for child nodes
|
||||||
|
if (!isNodeEmpty(node)) {
|
||||||
|
ParseHelper_Node_Enter(ne);
|
||||||
|
for (auto currentChildNode : node.children()) {
|
||||||
|
const std::string ¤tChildName = currentChildNode.name();
|
||||||
|
// check for X3DComposedGeometryNodes
|
||||||
|
if (currentChildName == "Color")
|
||||||
|
readColor(currentChildNode);
|
||||||
|
else if (currentChildName == "ColorRGBA")
|
||||||
|
readColorRGBA(currentChildNode);
|
||||||
|
else if (currentChildName == "Coordinate")
|
||||||
|
readCoordinate(currentChildNode);
|
||||||
|
else if (currentChildName == "Normal")
|
||||||
|
readNormal(currentChildNode);
|
||||||
|
else if (currentChildName == "TextureCoordinate")
|
||||||
|
readTextureCoordinate(currentChildNode);
|
||||||
|
// check for X3DMetadataObject
|
||||||
|
else if (!checkForMetadataNode(currentChildNode))
|
||||||
|
skipUnsupportedNode("TriangleSet", currentChildNode);
|
||||||
|
}
|
||||||
|
ParseHelper_Node_Exit();
|
||||||
|
} // if(!isNodeEmpty(node))
|
||||||
|
else {
|
||||||
|
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
// <TriangleStripSet
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// ccw="true" SFBool [initializeOnly]
|
||||||
|
// colorPerVertex="true" SFBool [initializeOnly]
|
||||||
|
// normalPerVertex="true" SFBool [initializeOnly]
|
||||||
|
// solid="true" SFBool [initializeOnly]
|
||||||
|
// stripCount="" MFInt32 [inputOutput]
|
||||||
|
// >
|
||||||
|
// <!-- ComposedGeometryContentModel -->
|
||||||
|
// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
|
||||||
|
// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
|
||||||
|
// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
|
||||||
|
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
||||||
|
// </TriangleStripSet>
|
||||||
|
void X3DImporter::readTriangleStripSet(XmlNode &node) {
|
||||||
|
std::string use, def;
|
||||||
|
bool ccw = true;
|
||||||
|
bool colorPerVertex = true;
|
||||||
|
std::vector<int32_t> stripCount;
|
||||||
|
bool normalPerVertex = true;
|
||||||
|
bool solid = true;
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
XmlParser::getBoolAttribute(node, "ccw", ccw);
|
||||||
|
XmlParser::getBoolAttribute(node, "colorPerVertex", colorPerVertex);
|
||||||
|
X3DXmlHelper::getInt32ArrayAttribute(node, "stripCount", stripCount);
|
||||||
|
XmlParser::getBoolAttribute(node, "normalPerVertex", normalPerVertex);
|
||||||
|
XmlParser::getBoolAttribute(node, "solid", solid);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty()) {
|
||||||
|
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.");
|
||||||
|
|
||||||
|
// create and if needed - define new geometry object.
|
||||||
|
ne = new X3DNodeElementSet(X3DElemType::ENET_TriangleStripSet, mNodeElementCur);
|
||||||
|
if (!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
X3DNodeElementSet &ne_alias = *((X3DNodeElementSet *)ne);
|
||||||
|
|
||||||
|
ne_alias.CCW = ccw;
|
||||||
|
ne_alias.ColorPerVertex = colorPerVertex;
|
||||||
|
ne_alias.VertexCount = stripCount;
|
||||||
|
ne_alias.NormalPerVertex = normalPerVertex;
|
||||||
|
ne_alias.Solid = solid;
|
||||||
|
// create CoordIdx
|
||||||
|
size_t coord_num0, coord_num1, coord_num2; // indices of current triangle
|
||||||
|
bool odd_tri; // sequence of current triangle
|
||||||
|
size_t coord_num_sb; // index of first point of strip
|
||||||
|
|
||||||
|
ne_alias.CoordIndex.clear();
|
||||||
|
coord_num_sb = 0;
|
||||||
|
for (std::vector<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); ++vc_it) {
|
||||||
|
if (*vc_it < 3) throw DeadlyImportError("TriangleStripSet. stripCount shall be greater than or equal to three.");
|
||||||
|
|
||||||
|
// set initial values for first triangle
|
||||||
|
coord_num0 = coord_num_sb;
|
||||||
|
coord_num1 = coord_num_sb + 1;
|
||||||
|
coord_num2 = coord_num_sb + 2;
|
||||||
|
odd_tri = true;
|
||||||
|
|
||||||
|
for (int32_t vc = 2; vc < *vc_it; vc++) {
|
||||||
|
if (ccw) {
|
||||||
|
// 0 2
|
||||||
|
// 1
|
||||||
|
ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num0));
|
||||||
|
ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num1));
|
||||||
|
ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num2));
|
||||||
|
} else {
|
||||||
|
// 0 1
|
||||||
|
// 2
|
||||||
|
ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num0));
|
||||||
|
ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num2));
|
||||||
|
ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num1));
|
||||||
|
} // if(ccw) else
|
||||||
|
|
||||||
|
ne_alias.CoordIndex.push_back(-1); // add face delimiter.
|
||||||
|
// prepare values for next triangle
|
||||||
|
if (odd_tri) {
|
||||||
|
coord_num0 = coord_num2;
|
||||||
|
coord_num2++;
|
||||||
|
} else {
|
||||||
|
coord_num1 = coord_num2;
|
||||||
|
coord_num2 = coord_num1 + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
odd_tri = !odd_tri;
|
||||||
|
coord_num_sb = coord_num2; // that index will be start of next strip
|
||||||
|
} // for(int32_t vc = 2; vc < *vc_it; vc++)
|
||||||
|
} // for(std::list<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); vc_it++)
|
||||||
|
// check for child nodes
|
||||||
|
if (!isNodeEmpty(node)) {
|
||||||
|
ParseHelper_Node_Enter(ne);
|
||||||
|
for (auto currentChildNode : node.children()) {
|
||||||
|
const std::string ¤tChildName = currentChildNode.name();
|
||||||
|
// check for X3DComposedGeometryNodes
|
||||||
|
if (currentChildName == "Color")
|
||||||
|
readColor(currentChildNode);
|
||||||
|
else if (currentChildName == "ColorRGBA")
|
||||||
|
readColorRGBA(currentChildNode);
|
||||||
|
else if (currentChildName == "Coordinate")
|
||||||
|
readCoordinate(currentChildNode);
|
||||||
|
else if (currentChildName == "Normal")
|
||||||
|
readNormal(currentChildNode);
|
||||||
|
else if (currentChildName == "TextureCoordinate")
|
||||||
|
readTextureCoordinate(currentChildNode);
|
||||||
|
// check for X3DMetadataObject
|
||||||
|
else if (!checkForMetadataNode(currentChildNode))
|
||||||
|
skipUnsupportedNode("TriangleStripSet", currentChildNode);
|
||||||
|
}
|
||||||
|
ParseHelper_Node_Exit();
|
||||||
|
} // if(!isNodeEmpty(node))
|
||||||
|
else {
|
||||||
|
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
// <Normal
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// vector="" MFVec3f [inputOutput]
|
||||||
|
// />
|
||||||
|
void X3DImporter::readNormal(XmlNode &node) {
|
||||||
|
std::string use, def;
|
||||||
|
std::list<aiVector3D> vector;
|
||||||
|
X3DNodeElementBase *ne;
|
||||||
|
|
||||||
|
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);
|
||||||
|
} else {
|
||||||
|
// create and if needed - define new geometry object.
|
||||||
|
ne = new X3DNodeElementNormal(mNodeElementCur);
|
||||||
|
if (!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
((X3DNodeElementNormal *)ne)->Value = vector;
|
||||||
|
// check for X3DMetadataObject childs.
|
||||||
|
if (!isNodeEmpty(node))
|
||||||
|
childrenReadMetadata(node, ne, "Normal");
|
||||||
|
else
|
||||||
|
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Assimp
|
||||||
|
|
||||||
|
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
@ -0,0 +1,221 @@
|
||||||
|
/*
|
||||||
|
Open Asset Import Library (assimp)
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2019, assimp team
|
||||||
|
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
with or without modification, are permitted provided that the
|
||||||
|
following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer in the documentation and/or other
|
||||||
|
materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of the assimp team, nor the names of its
|
||||||
|
contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior
|
||||||
|
written permission of the assimp team.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
/// \file X3DImporter_Shape.cpp
|
||||||
|
/// \brief Parsing data from nodes of "Shape" set of X3D.
|
||||||
|
/// \date 2015-2016
|
||||||
|
/// \author smal.root@gmail.com
|
||||||
|
|
||||||
|
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||||
|
|
||||||
|
#include "X3DImporter.hpp"
|
||||||
|
#include "X3DImporter_Macro.hpp"
|
||||||
|
#include "X3DXmlHelper.h"
|
||||||
|
|
||||||
|
namespace Assimp {
|
||||||
|
|
||||||
|
void X3DImporter::readShape(XmlNode &node) {
|
||||||
|
std::string use, def;
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty()) {
|
||||||
|
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Shape, ne);
|
||||||
|
} else {
|
||||||
|
// create and if needed - define new geometry object.
|
||||||
|
ne = new X3DNodeElementShape(mNodeElementCur);
|
||||||
|
if (!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
// check for child nodes
|
||||||
|
if (!isNodeEmpty(node)) {
|
||||||
|
ParseHelper_Node_Enter(ne);
|
||||||
|
for (auto currentChildNode : node.children()) {
|
||||||
|
const std::string ¤tChildName = currentChildNode.name();
|
||||||
|
// 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);
|
||||||
|
// check for X3DMetadataObject
|
||||||
|
else if (!checkForMetadataNode(currentChildNode)) skipUnsupportedNode("Shape", currentChildNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
ParseHelper_Node_Exit();
|
||||||
|
} // if (!isNodeEmpty(node))
|
||||||
|
else {
|
||||||
|
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
// <Appearance
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// >
|
||||||
|
// <!-- AppearanceChildContentModel -->
|
||||||
|
// "Child-node content model corresponding to X3DAppearanceChildNode. Appearance can contain FillProperties, LineProperties, Material, any Texture node and
|
||||||
|
// any TextureTransform node, in any order. No more than one instance of these nodes is allowed. Appearance may also contain multiple shaders (ComposedShader,
|
||||||
|
// PackagedShader, ProgramShader).
|
||||||
|
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model."
|
||||||
|
// </Appearance>
|
||||||
|
void X3DImporter::readAppearance(XmlNode &node) {
|
||||||
|
std::string use, def;
|
||||||
|
X3DNodeElementBase* ne( nullptr );
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty())
|
||||||
|
{
|
||||||
|
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Appearance, ne);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// create and if needed - define new geometry object.
|
||||||
|
ne = new X3DNodeElementAppearance(mNodeElementCur);
|
||||||
|
if(!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
// check for child nodes
|
||||||
|
if(!isNodeEmpty(node))
|
||||||
|
{
|
||||||
|
ParseHelper_Node_Enter(ne);
|
||||||
|
for (auto currentChildNode : node.children()) {
|
||||||
|
const std::string ¤tChildName = currentChildNode.name();
|
||||||
|
if (currentChildName == "Material") readMaterial(currentChildNode);
|
||||||
|
else if (currentChildName == "ImageTexture") readImageTexture(currentChildNode);
|
||||||
|
else if (currentChildName == "TextureTransform") readTextureTransform(currentChildNode);
|
||||||
|
// check for X3DMetadataObject
|
||||||
|
else if (!checkForMetadataNode(currentChildNode)) skipUnsupportedNode("Appearance", currentChildNode);
|
||||||
|
}
|
||||||
|
ParseHelper_Node_Exit();
|
||||||
|
}// if(!isNodeEmpty(node))
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mNodeElementCur->Children.push_back(ne);// add made object as child to current element
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
|
||||||
|
}// if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
// <Material
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// ambientIntensity="0.2" SFFloat [inputOutput]
|
||||||
|
// diffuseColor="0.8 0.8 0.8" SFColor [inputOutput]
|
||||||
|
// emissiveColor="0 0 0" SFColor [inputOutput]
|
||||||
|
// shininess="0.2" SFFloat [inputOutput]
|
||||||
|
// specularColor="0 0 0" SFColor [inputOutput]
|
||||||
|
// transparency="0" SFFloat [inputOutput]
|
||||||
|
// />
|
||||||
|
void X3DImporter::readMaterial(XmlNode &node) {
|
||||||
|
std::string use, def;
|
||||||
|
float ambientIntensity = 0.2f;
|
||||||
|
float shininess = 0.2f;
|
||||||
|
float transparency = 0;
|
||||||
|
aiColor3D diffuseColor(0.8f, 0.8f, 0.8f);
|
||||||
|
aiColor3D emissiveColor(0, 0, 0);
|
||||||
|
aiColor3D specularColor(0, 0, 0);
|
||||||
|
X3DNodeElementBase* ne( nullptr );
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
XmlParser::getFloatAttribute(node, "ambientIntensity", ambientIntensity);
|
||||||
|
XmlParser::getFloatAttribute(node, "shininess", shininess);
|
||||||
|
XmlParser::getFloatAttribute(node, "transparency", transparency);
|
||||||
|
X3DXmlHelper::getColor3DAttribute(node, "diffuseColor", diffuseColor);
|
||||||
|
X3DXmlHelper::getColor3DAttribute(node, "emissiveColor", emissiveColor);
|
||||||
|
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
|
||||||
|
{
|
||||||
|
// create and if needed - define new geometry object.
|
||||||
|
ne = new X3DNodeElementMaterial(mNodeElementCur);
|
||||||
|
if(!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
((X3DNodeElementMaterial *)ne)->AmbientIntensity = ambientIntensity;
|
||||||
|
((X3DNodeElementMaterial *)ne)->Shininess = shininess;
|
||||||
|
((X3DNodeElementMaterial *)ne)->Transparency = transparency;
|
||||||
|
((X3DNodeElementMaterial *)ne)->DiffuseColor = diffuseColor;
|
||||||
|
((X3DNodeElementMaterial *)ne)->EmissiveColor = emissiveColor;
|
||||||
|
((X3DNodeElementMaterial *)ne)->SpecularColor = specularColor;
|
||||||
|
// check for child nodes
|
||||||
|
if(!isNodeEmpty(node))
|
||||||
|
childrenReadMetadata(node, ne, "Material");
|
||||||
|
else
|
||||||
|
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
|
||||||
|
}// if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
}// namespace Assimp
|
||||||
|
|
||||||
|
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
@ -0,0 +1,179 @@
|
||||||
|
/*
|
||||||
|
Open Asset Import Library (assimp)
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2019, assimp team
|
||||||
|
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
with or without modification, are permitted provided that the
|
||||||
|
following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer in the documentation and/or other
|
||||||
|
materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of the assimp team, nor the names of its
|
||||||
|
contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior
|
||||||
|
written permission of the assimp team.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
/// \file X3DImporter_Texturing.cpp
|
||||||
|
/// \brief Parsing data from nodes of "Texturing" set of X3D.
|
||||||
|
/// \date 2015-2016
|
||||||
|
/// \author smal.root@gmail.com
|
||||||
|
|
||||||
|
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||||
|
|
||||||
|
#include "X3DImporter.hpp"
|
||||||
|
#include "X3DImporter_Macro.hpp"
|
||||||
|
#include "X3DXmlHelper.h"
|
||||||
|
|
||||||
|
namespace Assimp {
|
||||||
|
|
||||||
|
// <ImageTexture
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// repeatS="true" SFBool
|
||||||
|
// repeatT="true" SFBool
|
||||||
|
// url="" MFString
|
||||||
|
// />
|
||||||
|
// When the url field contains no values ([]), texturing is disabled.
|
||||||
|
void X3DImporter::readImageTexture(XmlNode &node) {
|
||||||
|
std::string use, def;
|
||||||
|
bool repeatS = true;
|
||||||
|
bool repeatT = true;
|
||||||
|
std::list<std::string> url;
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
XmlParser::getBoolAttribute(node, "repeatS", repeatS);
|
||||||
|
XmlParser::getBoolAttribute(node, "repeatT", repeatT);
|
||||||
|
X3DXmlHelper::getStringListAttribute(node, "url", url);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty()) {
|
||||||
|
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_ImageTexture, ne);
|
||||||
|
} else {
|
||||||
|
// create and if needed - define new geometry object.
|
||||||
|
ne = new X3DNodeElementImageTexture(mNodeElementCur);
|
||||||
|
if (!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
((X3DNodeElementImageTexture *)ne)->RepeatS = repeatS;
|
||||||
|
((X3DNodeElementImageTexture *)ne)->RepeatT = repeatT;
|
||||||
|
// Attribute "url" can contain list of strings. But we need only one - first.
|
||||||
|
if (!url.empty())
|
||||||
|
((X3DNodeElementImageTexture *)ne)->URL = url.front();
|
||||||
|
else
|
||||||
|
((X3DNodeElementImageTexture *)ne)->URL = "";
|
||||||
|
|
||||||
|
// check for X3DMetadataObject childs.
|
||||||
|
if (!isNodeEmpty(node))
|
||||||
|
childrenReadMetadata(node, ne, "ImageTexture");
|
||||||
|
else
|
||||||
|
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
// <TextureCoordinate
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// point="" MFVec3f [inputOutput]
|
||||||
|
// />
|
||||||
|
void X3DImporter::readTextureCoordinate(XmlNode &node) {
|
||||||
|
std::string use, def;
|
||||||
|
std::list<aiVector2D> point;
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
X3DXmlHelper::getVector2DListAttribute(node, "point", point);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty()) {
|
||||||
|
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TextureCoordinate, ne);
|
||||||
|
} else {
|
||||||
|
// create and if needed - define new geometry object.
|
||||||
|
ne = new X3DNodeElementTextureCoordinate(mNodeElementCur);
|
||||||
|
if (!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
((X3DNodeElementTextureCoordinate *)ne)->Value = point;
|
||||||
|
// check for X3DMetadataObject childs.
|
||||||
|
if (!isNodeEmpty(node))
|
||||||
|
childrenReadMetadata(node, ne, "TextureCoordinate");
|
||||||
|
else
|
||||||
|
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
// <TextureTransform
|
||||||
|
// DEF="" ID
|
||||||
|
// USE="" IDREF
|
||||||
|
// center="0 0" SFVec2f [inputOutput]
|
||||||
|
// rotation="0" SFFloat [inputOutput]
|
||||||
|
// scale="1 1" SFVec2f [inputOutput]
|
||||||
|
// translation="0 0" SFVec2f [inputOutput]
|
||||||
|
// />
|
||||||
|
void X3DImporter::readTextureTransform(XmlNode &node) {
|
||||||
|
std::string use, def;
|
||||||
|
aiVector2D center(0, 0);
|
||||||
|
float rotation = 0;
|
||||||
|
aiVector2D scale(1, 1);
|
||||||
|
aiVector2D translation(0, 0);
|
||||||
|
X3DNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||||
|
X3DXmlHelper::getVector2DAttribute(node, "center", center);
|
||||||
|
XmlParser::getFloatAttribute(node, "rotation", rotation);
|
||||||
|
X3DXmlHelper::getVector2DAttribute(node, "scale", scale);
|
||||||
|
X3DXmlHelper::getVector2DAttribute(node, "translation", translation);
|
||||||
|
|
||||||
|
// if "USE" defined then find already defined element.
|
||||||
|
if (!use.empty()) {
|
||||||
|
MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TextureTransform, ne);
|
||||||
|
} else {
|
||||||
|
// create and if needed - define new geometry object.
|
||||||
|
ne = new X3DNodeElementTextureTransform(mNodeElementCur);
|
||||||
|
if (!def.empty()) ne->ID = def;
|
||||||
|
|
||||||
|
((X3DNodeElementTextureTransform *)ne)->Center = center;
|
||||||
|
((X3DNodeElementTextureTransform *)ne)->Rotation = rotation;
|
||||||
|
((X3DNodeElementTextureTransform *)ne)->Scale = scale;
|
||||||
|
((X3DNodeElementTextureTransform *)ne)->Translation = translation;
|
||||||
|
// check for X3DMetadataObject childs.
|
||||||
|
if (!isNodeEmpty(node))
|
||||||
|
childrenReadMetadata(node, ne, "TextureTransform");
|
||||||
|
else
|
||||||
|
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||||
|
|
||||||
|
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||||
|
} // if(!use.empty()) else
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Assimp
|
||||||
|
|
||||||
|
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
@ -0,0 +1,294 @@
|
||||||
|
#include "X3DXmlHelper.h"
|
||||||
|
#include "X3DImporter.hpp"
|
||||||
|
|
||||||
|
#include <assimp/ParsingUtils.h>
|
||||||
|
|
||||||
|
namespace Assimp {
|
||||||
|
|
||||||
|
bool X3DXmlHelper::getColor3DAttribute(XmlNode &node, const char *attributeName, aiColor3D &color) {
|
||||||
|
std::string val;
|
||||||
|
if (XmlParser::getStdStrAttribute(node, attributeName, val)) {
|
||||||
|
std::vector<std::string> values;
|
||||||
|
tokenize<std::string>(val, values, " ");
|
||||||
|
if (values.size() != 3) {
|
||||||
|
Throw_ConvertFail_Str2ArrF(node.name(), attributeName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto it = values.begin();
|
||||||
|
color.r = stof(*it++);
|
||||||
|
color.g = stof(*it++);
|
||||||
|
color.b = stof(*it);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool X3DXmlHelper::getVector2DAttribute(XmlNode &node, const char *attributeName, aiVector2D &color) {
|
||||||
|
std::string val;
|
||||||
|
if (XmlParser::getStdStrAttribute(node, attributeName, val)) {
|
||||||
|
std::vector<std::string> values;
|
||||||
|
tokenize<std::string>(val, values, " ");
|
||||||
|
if (values.size() != 2) {
|
||||||
|
Throw_ConvertFail_Str2ArrF(node.name(), attributeName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto it = values.begin();
|
||||||
|
color.x = stof(*it++);
|
||||||
|
color.y = stof(*it);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool X3DXmlHelper::getVector3DAttribute(XmlNode &node, const char *attributeName, aiVector3D &color) {
|
||||||
|
std::string val;
|
||||||
|
if (XmlParser::getStdStrAttribute(node, attributeName, val)) {
|
||||||
|
std::vector<std::string> values;
|
||||||
|
tokenize<std::string>(val, values, " ");
|
||||||
|
if (values.size() != 3) {
|
||||||
|
Throw_ConvertFail_Str2ArrF(node.name(), attributeName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto it = values.begin();
|
||||||
|
color.x = stof(*it++);
|
||||||
|
color.y = stof(*it++);
|
||||||
|
color.z = stof(*it);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool X3DXmlHelper::getBooleanArrayAttribute(XmlNode &node, const char *attributeName, std::vector<bool> &boolArray) {
|
||||||
|
std::string val;
|
||||||
|
if (XmlParser::getStdStrAttribute(node, attributeName, val)) {
|
||||||
|
std::vector<std::string> values;
|
||||||
|
tokenize<std::string>(val, values, " ");
|
||||||
|
auto it = values.begin();
|
||||||
|
while (it != values.end()) {
|
||||||
|
auto s = *it++;
|
||||||
|
if (!s.empty())
|
||||||
|
boolArray.push_back(s[0] == 't' || s[0] == '1');
|
||||||
|
else
|
||||||
|
Throw_ConvertFail_Str2ArrB(node.name(), attributeName);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool X3DXmlHelper::getDoubleArrayAttribute(XmlNode &node, const char *attributeName, std::vector<double> &doubleArray) {
|
||||||
|
std::string val;
|
||||||
|
if (XmlParser::getStdStrAttribute(node, attributeName, val)) {
|
||||||
|
std::vector<std::string> values;
|
||||||
|
tokenize<std::string>(val, values, " ");
|
||||||
|
auto it = values.begin();
|
||||||
|
while (it != values.end()) {
|
||||||
|
auto s = *it++;
|
||||||
|
if (!s.empty())
|
||||||
|
doubleArray.push_back(atof(s.c_str()));
|
||||||
|
else
|
||||||
|
Throw_ConvertFail_Str2ArrD(node.name(), attributeName);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool X3DXmlHelper::getFloatArrayAttribute(XmlNode &node, const char *attributeName, std::vector<float> &floatArray) {
|
||||||
|
std::string val;
|
||||||
|
if (XmlParser::getStdStrAttribute(node, attributeName, val)) {
|
||||||
|
std::vector<std::string> values;
|
||||||
|
tokenize<std::string>(val, values, " ");
|
||||||
|
auto it = values.begin();
|
||||||
|
while (it != values.end()) {
|
||||||
|
auto s = *it++;
|
||||||
|
if (!s.empty())
|
||||||
|
floatArray.push_back((float)atof(s.c_str()));
|
||||||
|
else
|
||||||
|
Throw_ConvertFail_Str2ArrF(node.name(), attributeName);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool X3DXmlHelper::getInt32ArrayAttribute(XmlNode &node, const char *attributeName, std::vector<int32_t> &intArray) {
|
||||||
|
std::string val;
|
||||||
|
if (XmlParser::getStdStrAttribute(node, attributeName, val)) {
|
||||||
|
std::vector<std::string> values;
|
||||||
|
tokenize<std::string>(val, values, " ");
|
||||||
|
auto it = values.begin();
|
||||||
|
while (it != values.end()) {
|
||||||
|
auto s = *it++;
|
||||||
|
if (!s.empty())
|
||||||
|
intArray.push_back((int32_t)atof(s.c_str()));
|
||||||
|
else
|
||||||
|
Throw_ConvertFail_Str2ArrI(node.name(), attributeName);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool X3DXmlHelper::getStringListAttribute(XmlNode &node, const char *attributeName, std::list<std::string> &stringList) {
|
||||||
|
std::string val;
|
||||||
|
if (XmlParser::getStdStrAttribute(node, attributeName, val)) {
|
||||||
|
std::vector<std::string> values;
|
||||||
|
tokenize<std::string>(val, values, " ");
|
||||||
|
auto it = values.begin();
|
||||||
|
std::string currentConcat = "";
|
||||||
|
bool inQuotes = false;
|
||||||
|
while (it != values.end()) {
|
||||||
|
auto s = *it++;
|
||||||
|
if (!s.empty()) {
|
||||||
|
if (inQuotes) {
|
||||||
|
if (*(s.rbegin()) == '"') {
|
||||||
|
stringList.push_back(currentConcat + s.substr(0, s.length() - 1));
|
||||||
|
currentConcat = "";
|
||||||
|
inQuotes = false;
|
||||||
|
} else {
|
||||||
|
currentConcat += " " + s;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (s[0] == '"') {
|
||||||
|
currentConcat = s.substr(1);
|
||||||
|
inQuotes = true;
|
||||||
|
} else {
|
||||||
|
stringList.push_back(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (!inQuotes)
|
||||||
|
Throw_ConvertFail_Str2ArrI(node.name(), attributeName);
|
||||||
|
}
|
||||||
|
if (inQuotes) Throw_ConvertFail_Str2ArrI(node.name(), attributeName);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool X3DXmlHelper::getStringArrayAttribute(XmlNode &node, const char *attributeName, std::vector<std::string> &stringArray) {
|
||||||
|
std::list<std::string> tlist;
|
||||||
|
|
||||||
|
if (getStringListAttribute(node, attributeName, tlist)) {
|
||||||
|
if (!tlist.empty()) {
|
||||||
|
stringArray.reserve(tlist.size());
|
||||||
|
for (std::list<std::string>::iterator it = tlist.begin(); it != tlist.end(); ++it) {
|
||||||
|
stringArray.push_back(*it);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool X3DXmlHelper::getVector2DListAttribute(XmlNode &node, const char *attributeName, std::list<aiVector2D> &vectorList) {
|
||||||
|
std::string val;
|
||||||
|
if (XmlParser::getStdStrAttribute(node, attributeName, val)) {
|
||||||
|
std::vector<std::string> values;
|
||||||
|
tokenize<std::string>(val, values, " ");
|
||||||
|
if (values.size() % 2) Throw_ConvertFail_Str2ArrF(node.name(), attributeName);
|
||||||
|
auto it = values.begin();
|
||||||
|
while (it != values.end()) {
|
||||||
|
aiVector2D tvec;
|
||||||
|
|
||||||
|
tvec.x = (float)atof((*it++).c_str());
|
||||||
|
tvec.y = (float)atof((*it++).c_str());
|
||||||
|
vectorList.push_back(tvec);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool X3DXmlHelper::getVector2DArrayAttribute(XmlNode &node, const char *attributeName, std::vector<aiVector2D> &vectorArray) {
|
||||||
|
std::list<aiVector2D> tlist;
|
||||||
|
|
||||||
|
if (getVector2DListAttribute(node, attributeName, tlist)) {
|
||||||
|
if (!tlist.empty()) {
|
||||||
|
vectorArray.reserve(tlist.size());
|
||||||
|
for (std::list<aiVector2D>::iterator it = tlist.begin(); it != tlist.end(); ++it) {
|
||||||
|
vectorArray.push_back(*it);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool X3DXmlHelper::getVector3DListAttribute(XmlNode &node, const char *attributeName, std::list<aiVector3D> &vectorList) {
|
||||||
|
std::string val;
|
||||||
|
if (XmlParser::getStdStrAttribute(node, attributeName, val)) {
|
||||||
|
std::vector<std::string> values;
|
||||||
|
tokenize<std::string>(val, values, " ");
|
||||||
|
if (values.size() % 3 != 0) Throw_ConvertFail_Str2ArrF(node.name(), attributeName);
|
||||||
|
auto it = values.begin();
|
||||||
|
while (it != values.end()) {
|
||||||
|
aiVector3D tvec;
|
||||||
|
|
||||||
|
tvec.x = (float)atof((*it++).c_str());
|
||||||
|
tvec.y = (float)atof((*it++).c_str());
|
||||||
|
tvec.z = (float)atof((*it++).c_str());
|
||||||
|
vectorList.push_back(tvec);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool X3DXmlHelper::getVector3DArrayAttribute(XmlNode &node, const char *attributeName, std::vector<aiVector3D> &vectorArray) {
|
||||||
|
std::list<aiVector3D> tlist;
|
||||||
|
|
||||||
|
if (getVector3DListAttribute(node, attributeName, tlist)) {
|
||||||
|
if (!tlist.empty()) {
|
||||||
|
vectorArray.reserve(tlist.size());
|
||||||
|
for (std::list<aiVector3D>::iterator it = tlist.begin(); it != tlist.end(); ++it) {
|
||||||
|
vectorArray.push_back(*it);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool X3DXmlHelper::getColor3DListAttribute(XmlNode &node, const char *attributeName, std::list<aiColor3D> &colorList) {
|
||||||
|
std::string val;
|
||||||
|
if (XmlParser::getStdStrAttribute(node, attributeName, val)) {
|
||||||
|
std::vector<std::string> values;
|
||||||
|
tokenize<std::string>(val, values, " ");
|
||||||
|
if (values.size() % 3 != 0) Throw_ConvertFail_Str2ArrF(node.name(), attributeName);
|
||||||
|
auto it = values.begin();
|
||||||
|
while (it != values.end()) {
|
||||||
|
aiColor3D tvec;
|
||||||
|
|
||||||
|
tvec.r = (float)atof((*it++).c_str());
|
||||||
|
tvec.g = (float)atof((*it++).c_str());
|
||||||
|
tvec.b = (float)atof((*it++).c_str());
|
||||||
|
colorList.push_back(tvec);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool X3DXmlHelper::getColor4DListAttribute(XmlNode &node, const char *attributeName, std::list<aiColor4D> &colorList) {
|
||||||
|
std::string val;
|
||||||
|
if (XmlParser::getStdStrAttribute(node, attributeName, val)) {
|
||||||
|
std::vector<std::string> values;
|
||||||
|
tokenize<std::string>(val, values, " ");
|
||||||
|
if (values.size() % 4 != 0) Throw_ConvertFail_Str2ArrF(node.name(), attributeName);
|
||||||
|
auto it = values.begin();
|
||||||
|
while (it != values.end()) {
|
||||||
|
aiColor4D tvec;
|
||||||
|
|
||||||
|
tvec.r = (float)atof((*it++).c_str());
|
||||||
|
tvec.g = (float)atof((*it++).c_str());
|
||||||
|
tvec.b = (float)atof((*it++).c_str());
|
||||||
|
tvec.a = (float)atof((*it++).c_str());
|
||||||
|
colorList.push_back(tvec);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Assimp
|
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <assimp/XmlParser.h>
|
||||||
|
#include <assimp/types.h>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
namespace Assimp {
|
||||||
|
|
||||||
|
class X3DXmlHelper {
|
||||||
|
public:
|
||||||
|
static bool getColor3DAttribute(XmlNode &node, const char *attributeName, aiColor3D &color);
|
||||||
|
static bool getVector2DAttribute(XmlNode &node, const char *attributeName, aiVector2D &vector);
|
||||||
|
static bool getVector3DAttribute(XmlNode &node, const char *attributeName, aiVector3D &vector);
|
||||||
|
|
||||||
|
static bool getBooleanArrayAttribute(XmlNode &node, const char *attributeName, std::vector<bool> &boolArray);
|
||||||
|
static bool getDoubleArrayAttribute(XmlNode &node, const char *attributeName, std::vector<double> &doubleArray);
|
||||||
|
static bool getFloatArrayAttribute(XmlNode &node, const char *attributeName, std::vector<float> &floatArray);
|
||||||
|
static bool getInt32ArrayAttribute(XmlNode &node, const char *attributeName, std::vector<int32_t> &intArray);
|
||||||
|
static bool getStringListAttribute(XmlNode &node, const char *attributeName, std::list<std::string> &stringArray);
|
||||||
|
static bool getStringArrayAttribute(XmlNode &node, const char *attributeName, std::vector<std::string> &stringArray);
|
||||||
|
|
||||||
|
static bool getVector2DListAttribute(XmlNode &node, const char *attributeName, std::list<aiVector2D> &vectorList);
|
||||||
|
static bool getVector2DArrayAttribute(XmlNode &node, const char *attributeName, std::vector<aiVector2D> &vectorArray);
|
||||||
|
static bool getVector3DListAttribute(XmlNode &node, const char *attributeName, std::list<aiVector3D> &vectorList);
|
||||||
|
static bool getVector3DArrayAttribute(XmlNode &node, const char *attributeName, std::vector<aiVector3D> &vectorArray);
|
||||||
|
static bool getColor3DListAttribute(XmlNode &node, const char *attributeName, std::list<aiColor3D> &colorList);
|
||||||
|
static bool getColor4DListAttribute(XmlNode &node, const char *attributeName, std::list<aiColor4D> &colorList);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Assimp
|
|
@ -800,9 +800,23 @@ ADD_ASSIMP_IMPORTER( X
|
||||||
|
|
||||||
ADD_ASSIMP_IMPORTER( X3D
|
ADD_ASSIMP_IMPORTER( X3D
|
||||||
AssetLib/X3D/X3DImporter.cpp
|
AssetLib/X3D/X3DImporter.cpp
|
||||||
|
AssetLib/X3D/X3DImporter_Geometry2D.cpp
|
||||||
|
AssetLib/X3D/X3DImporter_Geometry3D.cpp
|
||||||
|
AssetLib/X3D/X3DImporter_Group.cpp
|
||||||
|
AssetLib/X3D/X3DImporter_Light.cpp
|
||||||
|
AssetLib/X3D/X3DImporter_Metadata.cpp
|
||||||
|
AssetLib/X3D/X3DImporter_Networking.cpp
|
||||||
|
AssetLib/X3D/X3DImporter_Postprocess.cpp
|
||||||
|
AssetLib/X3D/X3DImporter_Rendering.cpp
|
||||||
|
AssetLib/X3D/X3DImporter_Shape.cpp
|
||||||
|
AssetLib/X3D/X3DImporter_Texturing.cpp
|
||||||
AssetLib/X3D/X3DImporter.hpp
|
AssetLib/X3D/X3DImporter.hpp
|
||||||
|
AssetLib/X3D/X3DImporter_Macro.hpp
|
||||||
|
AssetLib/X3D/X3DImporter_Node.hpp
|
||||||
AssetLib/X3D/X3DGeoHelper.cpp
|
AssetLib/X3D/X3DGeoHelper.cpp
|
||||||
AssetLib/X3D/X3DGeoHelper.h
|
AssetLib/X3D/X3DGeoHelper.h
|
||||||
|
AssetLib/X3D/X3DXmlHelper.cpp
|
||||||
|
AssetLib/X3D/X3DXmlHelper.h
|
||||||
)
|
)
|
||||||
|
|
||||||
ADD_ASSIMP_IMPORTER( GLTF
|
ADD_ASSIMP_IMPORTER( GLTF
|
||||||
|
|
|
@ -365,9 +365,7 @@ void GetImporterInstanceList(std::vector<BaseImporter *> &out) {
|
||||||
out.push_back(new D3MFImporter());
|
out.push_back(new D3MFImporter());
|
||||||
#endif
|
#endif
|
||||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||||
if (devImportersEnabled) { // https://github.com/assimp/assimp/issues/3647
|
out.push_back(new X3DImporter());
|
||||||
out.push_back(new X3DImporter());
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
#ifndef ASSIMP_BUILD_NO_MMD_IMPORTER
|
#ifndef ASSIMP_BUILD_NO_MMD_IMPORTER
|
||||||
out.push_back(new MMDImporter());
|
out.push_back(new MMDImporter());
|
||||||
|
|
Loading…
Reference in New Issue