[+] X3D importer.
parent
e4cb388153
commit
3274951f2a
|
@ -610,6 +610,22 @@ ADD_ASSIMP_IMPORTER( X
|
|||
XFileExporter.cpp
|
||||
)
|
||||
|
||||
ADD_ASSIMP_IMPORTER(X3D
|
||||
X3DImporter.cpp
|
||||
X3DImporter.hpp
|
||||
X3DImporter_Geometry2D.cpp
|
||||
X3DImporter_Geometry3D.cpp
|
||||
X3DImporter_Group.cpp
|
||||
X3DImporter_Light.cpp
|
||||
X3DImporter_Metadata.cpp
|
||||
X3DImporter_Networking.cpp
|
||||
X3DImporter_Node.hpp
|
||||
X3DImporter_Postprocess.cpp
|
||||
X3DImporter_Rendering.cpp
|
||||
X3DImporter_Shape.cpp
|
||||
X3DImporter_Texturing.cpp
|
||||
)
|
||||
|
||||
ADD_ASSIMP_IMPORTER( GLTF
|
||||
glTFAsset.h
|
||||
glTFAsset.inl
|
||||
|
|
|
@ -185,6 +185,9 @@ corresponding preprocessor flag to selectively disable formats.
|
|||
#ifndef ASSIMP_BUILD_NO_3MF_IMPORTER
|
||||
# include "D3MFImporter.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
# include "X3DImporter.hpp"
|
||||
#endif
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
|
@ -331,6 +334,9 @@ void GetImporterInstanceList(std::vector< BaseImporter* >& out)
|
|||
#if ( !defined ASSIMP_BUILD_NO_3MF_IMPORTER )
|
||||
out.push_back(new D3MFImporter() );
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
out.push_back( new X3DImporter() );
|
||||
#endif
|
||||
}
|
||||
|
||||
/** will delete all registered importers. */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,954 @@
|
|||
/// \file X3DImporter.hpp
|
||||
/// \brief X3D-format files importer for Assimp.
|
||||
/// \date 2015-2016
|
||||
/// \author nevorek@gmail.com
|
||||
|
||||
#ifndef INCLUDED_AI_X3D_IMPORTER_H
|
||||
#define INCLUDED_AI_X3D_IMPORTER_H
|
||||
|
||||
// Pay attention - you must include some files from Assimp before including BaseImporter.h.
|
||||
// magic region begin
|
||||
#include <set>
|
||||
|
||||
#include "../include/assimp/DefaultLogger.hpp"
|
||||
#include "../include/assimp/importerdesc.h"
|
||||
#include "../include/assimp/ProgressHandler.hpp"
|
||||
#include "../include/assimp/types.h"
|
||||
// magic region end
|
||||
#include "BaseImporter.h"
|
||||
#include "irrXMLWrapper.h"
|
||||
|
||||
#include "X3DImporter_Node.hpp"
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
|
||||
/// \class X3DImporter
|
||||
/// Class that holding scene graph which include: groups, geometry, metadata etc.
|
||||
///
|
||||
/// Limitations.
|
||||
///
|
||||
/// Pay attention that X3D is format for interactive graphic and simulations for web browsers.
|
||||
/// So not all features can be imported using Assimp.
|
||||
///
|
||||
/// Unsupported nodes:
|
||||
/// CAD geometry component:
|
||||
/// "CADAssembly", "CADFace", "CADLayer", "CADPart", "IndexedQuadSet", "QuadSet"
|
||||
/// Core component:
|
||||
/// "ROUTE", "ExternProtoDeclare", "ProtoDeclare", "ProtoInstance", "ProtoInterface", "WorldInfo"
|
||||
/// Distributed interactive simulation (DIS) component:
|
||||
/// "DISEntityManager", "DISEntityTypeMapping", "EspduTransform", "ReceiverPdu", "SignalPdu", "TransmitterPdu"
|
||||
/// Cube map environmental texturing component:
|
||||
/// "ComposedCubeMapTexture", "GeneratedCubeMapTexture", "ImageCubeMapTexture"
|
||||
/// Environmental effects component:
|
||||
/// "Background", "Fog", "FogCoordinate", "LocalFog", "TextureBackground"
|
||||
/// Environmental sensor component:
|
||||
/// "ProximitySensor", "TransformSensor", "VisibilitySensor"
|
||||
/// Followers component:
|
||||
/// "ColorChaser", "ColorDamper", "CoordinateChaser", "CoordinateDamper", "OrientationChaser", "OrientationDamper", "PositionChaser",
|
||||
/// "PositionChaser2D", "PositionDamper", "PositionDamper2D", "ScalarChaser", "ScalarDamper", "TexCoordChaser2D", "TexCoordDamper2D"
|
||||
/// Geospatial component:
|
||||
/// "GeoCoordinate", "GeoElevationGrid", "GeoLocation", "GeoLOD", "GeoMetadata", "GeoOrigin", "GeoPositionInterpolator", "GeoProximitySensor",
|
||||
/// "GeoTouchSensor", "GeoTransform", "GeoViewpoint"
|
||||
/// Humanoid Animation (H-Anim) component:
|
||||
/// "HAnimDisplacer", "HAnimHumanoid", "HAnimJoint", "HAnimSegment", "HAnimSite"
|
||||
/// Interpolation component:
|
||||
/// "ColorInterpolator", "CoordinateInterpolator", "CoordinateInterpolator2D", "EaseInEaseOut", "NormalInterpolator", "OrientationInterpolator",
|
||||
/// "PositionInterpolator", "PositionInterpolator2D", "ScalarInterpolator", "SplinePositionInterpolator", "SplinePositionInterpolator2D",
|
||||
/// "SplineScalarInterpolator", "SquadOrientationInterpolator",
|
||||
/// Key device sensor component:
|
||||
/// "KeySensor", "StringSensor"
|
||||
/// Layering component:
|
||||
/// "Layer", "LayerSet", "Viewport"
|
||||
/// Layout component:
|
||||
/// "Layout", "LayoutGroup", "LayoutLayer", "ScreenFontStyle", "ScreenGroup"
|
||||
/// Navigation component:
|
||||
/// "Billboard", "Collision", "LOD", "NavigationInfo", "OrthoViewpoint", "Viewpoint", "ViewpointGroup"
|
||||
/// Networking component:
|
||||
/// "Anchor", "LoadSensor"
|
||||
/// NURBS component:
|
||||
/// "Contour2D", "ContourPolyline2D", "CoordinateDouble", "NurbsCurve", "NurbsCurve2D", "NurbsOrientationInterpolator", "NurbsPatchSurface",
|
||||
/// "NurbsPositionInterpolator", "NurbsSet", "NurbsSurfaceInterpolator", "NurbsSweptSurface", "NurbsSwungSurface", "NurbsTextureCoordinate",
|
||||
/// "NurbsTrimmedSurface"
|
||||
/// Particle systems component:
|
||||
/// "BoundedPhysicsModel", "ConeEmitter", "ExplosionEmitter", "ForcePhysicsModel", "ParticleSystem", "PointEmitter", "PolylineEmitter",
|
||||
/// "SurfaceEmitter", "VolumeEmitter", "WindPhysicsModel"
|
||||
/// Picking component:
|
||||
/// "LinePickSensor", "PickableGroup", "PointPickSensor", "PrimitivePickSensor", "VolumePickSensor"
|
||||
/// Pointing device sensor component:
|
||||
/// "CylinderSensor", "PlaneSensor", "SphereSensor", "TouchSensor"
|
||||
/// Rendering component:
|
||||
/// "ClipPlane"
|
||||
/// Rigid body physics:
|
||||
/// "BallJoint", "CollidableOffset", "CollidableShape", "CollisionCollection", "CollisionSensor", "CollisionSpace", "Contact", "DoubleAxisHingeJoint",
|
||||
/// "MotorJoint", "RigidBody", "RigidBodyCollection", "SingleAxisHingeJoint", "SliderJoint", "UniversalJoint"
|
||||
/// Scripting component:
|
||||
/// "Script"
|
||||
/// Programmable shaders component:
|
||||
/// "ComposedShader", "FloatVertexAttribute", "Matrix3VertexAttribute", "Matrix4VertexAttribute", "PackagedShader", "ProgramShader", "ShaderPart",
|
||||
/// "ShaderProgram",
|
||||
/// Shape component:
|
||||
/// "FillProperties", "LineProperties", "TwoSidedMaterial"
|
||||
/// Sound component:
|
||||
/// "AudioClip", "Sound"
|
||||
/// Text component:
|
||||
/// "FontStyle", "Text"
|
||||
/// Texturing3D Component:
|
||||
/// "ComposedTexture3D", "ImageTexture3D", "PixelTexture3D", "TextureCoordinate3D", "TextureCoordinate4D", "TextureTransformMatrix3D",
|
||||
/// "TextureTransform3D"
|
||||
/// Texturing component:
|
||||
/// "MovieTexture", "MultiTexture", "MultiTextureCoordinate", "MultiTextureTransform", "PixelTexture", "TextureCoordinateGenerator",
|
||||
/// "TextureProperties",
|
||||
/// Time component:
|
||||
/// "TimeSensor"
|
||||
/// Event Utilities component:
|
||||
/// "BooleanFilter", "BooleanSequencer", "BooleanToggle", "BooleanTrigger", "IntegerSequencer", "IntegerTrigger", "TimeTrigger",
|
||||
/// Volume rendering component:
|
||||
/// "BlendedVolumeStyle", "BoundaryEnhancementVolumeStyle", "CartoonVolumeStyle", "ComposedVolumeStyle", "EdgeEnhancementVolumeStyle",
|
||||
/// "IsoSurfaceVolumeData", "OpacityMapVolumeStyle", "ProjectionVolumeStyle", "SegmentedVolumeData", "ShadedVolumeStyle",
|
||||
/// "SilhouetteEnhancementVolumeStyle", "ToneMappedVolumeStyle", "VolumeData"
|
||||
///
|
||||
/// Supported nodes:
|
||||
/// Core component:
|
||||
/// "MetadataBoolean", "MetadataDouble", "MetadataFloat", "MetadataInteger", "MetadataSet", "MetadataString"
|
||||
/// Geometry2D component:
|
||||
/// "Arc2D", "ArcClose2D", "Circle2D", "Disk2D", "Polyline2D", "Polypoint2D", "Rectangle2D", "TriangleSet2D"
|
||||
/// Geometry3D component:
|
||||
/// "Box", "Cone", "Cylinder", "ElevationGrid", "Extrusion", "IndexedFaceSet", "Sphere"
|
||||
/// Grouping component:
|
||||
/// "Group", "StaticGroup", "Switch", "Transform"
|
||||
/// Lighting component:
|
||||
/// "DirectionalLight", "PointLight", "SpotLight"
|
||||
/// Networking component:
|
||||
/// "Inline"
|
||||
/// Rendering component:
|
||||
/// "Color", "ColorRGBA", "Coordinate", "IndexedLineSet", "IndexedTriangleFanSet", "IndexedTriangleSet", "IndexedTriangleStripSet", "LineSet",
|
||||
/// "PointSet", "TriangleFanSet", "TriangleSet", "TriangleStripSet", "Normal"
|
||||
/// Shape component:
|
||||
/// "Shape", "Appearance", "Material"
|
||||
/// Texturing component:
|
||||
/// "ImageTexture", "TextureCoordinate", "TextureTransform"
|
||||
///
|
||||
/// Limitations of attribute "USE".
|
||||
/// If "USE" is set then node must be empty, like that:
|
||||
/// <Node USE='name'/>
|
||||
/// not the
|
||||
/// <Node USE='name'><!-- something --> </Node>
|
||||
///
|
||||
/// Ignored attributes: "creaseAngle", "convex", "solid".
|
||||
///
|
||||
/// Texture coordinates generating: only for Sphere, Cone, Cylinder. In all other case used PLANE mapping.
|
||||
/// It's better that Assimp main code has powerfull texture coordinates generator. Then is not needed to
|
||||
/// duplicate this code in every importer.
|
||||
///
|
||||
/// Lighting limitations.
|
||||
/// If light source placed in some group with "DEF" set. And after that some node is use it group with "USE" attribute then
|
||||
/// you will get error about duplicate light sources. That's happening because Assimp require names for lights but do not like
|
||||
/// duplicates of it )).
|
||||
///
|
||||
/// Color for faces.
|
||||
/// That's happening when attribute "colorPerVertex" is set to "false". But Assimp do not hold how many colors has mesh and reuire
|
||||
/// equal length for mVertices and mColors. You will see the colors but vertices will use call which last used in "colorIdx".
|
||||
///
|
||||
/// That's all for now. Enjoy
|
||||
///
|
||||
class X3DImporter : public BaseImporter
|
||||
{
|
||||
/***********************************************/
|
||||
/******************** Types ********************/
|
||||
/***********************************************/
|
||||
|
||||
/***********************************************/
|
||||
/****************** Constants ******************/
|
||||
/***********************************************/
|
||||
|
||||
private:
|
||||
|
||||
static const aiImporterDesc Description;
|
||||
|
||||
/***********************************************/
|
||||
/****************** Variables ******************/
|
||||
/***********************************************/
|
||||
|
||||
private:
|
||||
|
||||
CX3DImporter_NodeElement* NodeElement_Cur;///< Current element.
|
||||
irr::io::IrrXMLReader* mReader;///< Pointer to XML-reader object
|
||||
std::string mFileDir;
|
||||
|
||||
public:
|
||||
|
||||
std::list<CX3DImporter_NodeElement*> NodeElement_List;///< All elements of scene graph.
|
||||
|
||||
/***********************************************/
|
||||
/****************** Functions ******************/
|
||||
/***********************************************/
|
||||
|
||||
private:
|
||||
|
||||
/// \fn X3DImporter(const X3DImporter& pScene)
|
||||
/// Disabled copy constructor.
|
||||
X3DImporter(const X3DImporter& pScene);
|
||||
|
||||
/// \fn X3DImporter& operator=(const X3DImporter& pScene)
|
||||
/// Disabled assign operator.
|
||||
X3DImporter& operator=(const X3DImporter& pScene);
|
||||
|
||||
/// \fn void Clear()
|
||||
/// Clear all temporary data.
|
||||
void Clear();
|
||||
|
||||
/***********************************************/
|
||||
/************* Functions: find set *************/
|
||||
/***********************************************/
|
||||
|
||||
/// \fn bool FindNodeElement_FromRoot(const std::string& pID, const CX3DImporter_NodeElement::EType pType, CX3DImporter_NodeElement** pElement)
|
||||
/// Find requested node element. Search will be made in all existing nodes.
|
||||
/// \param [in] pID - ID of requested element.
|
||||
/// \param [in] pType - type of requested element.
|
||||
/// \param [out] pElement - pointer to pointer to item found.
|
||||
/// \return true - if the element is found, else - false.
|
||||
bool FindNodeElement_FromRoot(const std::string& pID, const CX3DImporter_NodeElement::EType pType, CX3DImporter_NodeElement** pElement);
|
||||
|
||||
/// \fn bool FindNodeElement_FromNode(CX3DImporter_NodeElement* pStartNode, const std::string& pID, const CX3DImporter_NodeElement::EType pType, CX3DImporter_NodeElement** pElement)
|
||||
/// Find requested node element. Search will be made from pointed node down to childs.
|
||||
/// \param [in] pStartNode - pointer to start node.
|
||||
/// \param [in] pID - ID of requested element.
|
||||
/// \param [in] pType - type of requested element.
|
||||
/// \param [out] pElement - pointer to pointer to item found.
|
||||
/// \return true - if the element is found, else - false.
|
||||
bool FindNodeElement_FromNode(CX3DImporter_NodeElement* pStartNode, const std::string& pID, const CX3DImporter_NodeElement::EType pType,
|
||||
CX3DImporter_NodeElement** pElement);
|
||||
|
||||
/// \fn bool FindNodeElement(const std::string& pName, const CX3DImporter_NodeElement::EType pType, CX3DImporter_NodeElement** pElement)
|
||||
/// Find requested node element. For "Node"'s accounting flag "Static".
|
||||
/// \param [in] pName - name of requested element.
|
||||
/// \param [in] pType - type of requested element.
|
||||
/// \param [out] pElement - pointer to pointer to item found.
|
||||
/// \return true - if the element is found, else - false.
|
||||
bool FindNodeElement(const std::string& pName, const CX3DImporter_NodeElement::EType pType, CX3DImporter_NodeElement** pElement);
|
||||
|
||||
/***********************************************/
|
||||
/********* Functions: postprocess set **********/
|
||||
/***********************************************/
|
||||
|
||||
/// \fn aiMatrix4x4 PostprocessHelper_Matrix_GlobalToCurrent() const
|
||||
/// \return transformation matrix from global coordinate system to local.
|
||||
aiMatrix4x4 PostprocessHelper_Matrix_GlobalToCurrent() const;
|
||||
|
||||
/// \fn void PostprocessHelper_CollectMetadata(const CX3DImporter_NodeElement& pNodeElement, std::list<CX3DImporter_NodeElement*>& pList) const
|
||||
/// Check if child elements of node element is metadata and add it to temporary list.
|
||||
/// \param [in] pNodeElement - node element where metadata is searching.
|
||||
/// \param [out] pList - temporary list for collected metadata.
|
||||
void PostprocessHelper_CollectMetadata(const CX3DImporter_NodeElement& pNodeElement, std::list<CX3DImporter_NodeElement*>& pList) const;
|
||||
|
||||
/// \fn bool bool PostprocessHelper_ElementIsMetadata(const CX3DImporter_NodeElement::EType pType) const
|
||||
/// Check if type of node element is metadata. E.g. <MetadataSet>, <MetadataString>.
|
||||
/// \param [in] pType - checked type.
|
||||
/// \return true - if the type corresponds to the metadata.
|
||||
bool PostprocessHelper_ElementIsMetadata(const CX3DImporter_NodeElement::EType pType) const;
|
||||
|
||||
/// \fn bool PostprocessHelper_ElementIsMesh(const CX3DImporter_NodeElement::EType pType) const
|
||||
/// Check if type of node element is geometry object and can be used to build mesh. E.g. <Box>, <Arc2D>.
|
||||
/// \param [in] pType - checked type.
|
||||
/// \return true - if the type corresponds to the mesh.
|
||||
bool PostprocessHelper_ElementIsMesh(const CX3DImporter_NodeElement::EType pType) const;
|
||||
|
||||
/// \fn void Postprocess_BuildLight(const CX3DImporter_NodeElement& pNodeElement, std::list<aiLight*>& pSceneLightList) const
|
||||
/// Read CX3DImporter_NodeElement_Light, create aiLight and add it to list of the lights.
|
||||
/// \param [in] pNodeElement - reference to lisght element(<DirectionalLight>, <PointLight>, <SpotLight>).
|
||||
/// \param [out] pSceneLightList - reference to list of the lights.
|
||||
void Postprocess_BuildLight(const CX3DImporter_NodeElement& pNodeElement, std::list<aiLight*>& pSceneLightList) const;
|
||||
|
||||
/// \fn void Postprocess_BuildMaterial(const CX3DImporter_NodeElement& pNodeElement, aiMaterial** pMaterial) const
|
||||
/// Create filled structure with type \ref aiMaterial from \ref CX3DImporter_NodeElement. This function itseld extract
|
||||
/// all needed data from scene graph.
|
||||
/// \param [in] pNodeElement - reference to material element(<Appearance>).
|
||||
/// \param [out] pMaterial - pointer to pointer to created material. *pMaterial must be NULL.
|
||||
void Postprocess_BuildMaterial(const CX3DImporter_NodeElement& pNodeElement, aiMaterial** pMaterial) const;
|
||||
|
||||
/// \fn void Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeElement, aiMesh** pMesh) const
|
||||
/// Create filled structure with type \ref aiMaterial from \ref CX3DImporter_NodeElement. This function itseld extract
|
||||
/// all needed data from scene graph.
|
||||
/// \param [in] pNodeElement - reference to geometry object.
|
||||
/// \param [out] pMesh - pointer to pointer to created mesh. *pMesh must be NULL.
|
||||
void Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeElement, aiMesh** pMesh) const;
|
||||
|
||||
/// \fn void Postprocess_BuildNode(const CX3DImporter_NodeElement& pNodeElement, aiNode& pSceneNode, std::list<aiMesh*>& pSceneMeshList, std::list<aiMaterial*>& pSceneMaterialList, std::list<aiLight*>& pSceneLightList) const
|
||||
/// Create aiNode from CX3DImporter_NodeElement. Also function check children and make recursive call.
|
||||
/// \param [out] pNode - pointer to pointer to created node. *pNode must be NULL.
|
||||
/// \param [in] pNodeElement - CX3DImporter_NodeElement which read.
|
||||
/// \param [out] pSceneNode - aiNode for filling.
|
||||
/// \param [out] pSceneMeshList - list with aiMesh which belong to scene.
|
||||
/// \param [out] pSceneMaterialList - list with aiMaterial which belong to scene.
|
||||
/// \param [out] pSceneLightList - list with aiLight which belong to scene.
|
||||
void Postprocess_BuildNode(const CX3DImporter_NodeElement& pNodeElement, aiNode& pSceneNode, std::list<aiMesh*>& pSceneMeshList,
|
||||
std::list<aiMaterial*>& pSceneMaterialList, std::list<aiLight*>& pSceneLightList) const;
|
||||
|
||||
/// \fn void Postprocess_BuildShape(const CX3DImporter_NodeElement_Shape& pShapeNodeElement, std::list<unsigned int>& pNodeMeshInd, std::list<aiMesh*>& pSceneMeshList, std::list<aiMaterial*>& pSceneMaterialList) const
|
||||
/// To create mesh and material kept in <Schape>.
|
||||
/// \param pShapeNodeElement - reference to node element which kept <Shape> data.
|
||||
/// \param pNodeMeshInd - reference to list with mesh indices. When pShapeNodeElement will read new mesh index will be added to this list.
|
||||
/// \param pSceneMeshList - reference to list with meshes. When pShapeNodeElement will read new mesh will be added to this list.
|
||||
/// \param pSceneMaterialList - reference to list with materials. When pShapeNodeElement will read new material will be added to this list.
|
||||
void Postprocess_BuildShape(const CX3DImporter_NodeElement_Shape& pShapeNodeElement, std::list<unsigned int>& pNodeMeshInd,
|
||||
std::list<aiMesh*>& pSceneMeshList, std::list<aiMaterial*>& pSceneMaterialList) const;
|
||||
|
||||
/// \fn void Postprocess_CollectMetadata(aiNode& pSceneNode, const CX3DImporter_NodeElement& pNodeElement) const
|
||||
/// Check if child elements of node element is metadata and add it to scene node.
|
||||
/// \param [in] pNodeElement - node element where metadata is searching.
|
||||
/// \param [out] pSceneNode - scene node in which metadata will be added.
|
||||
void Postprocess_CollectMetadata(const CX3DImporter_NodeElement& pNodeElement, aiNode& pSceneNode) const;
|
||||
|
||||
/***********************************************/
|
||||
/************* Functions: throw set ************/
|
||||
/***********************************************/
|
||||
|
||||
/// \fn void Throw_ArgOutOfRange(const std::string& pArgument)
|
||||
/// Call that function when argument is out of range and exception must be raised.
|
||||
/// \throw DeadlyImportError.
|
||||
/// \param [in] pArgument - argument name.
|
||||
void Throw_ArgOutOfRange(const std::string& pArgument);
|
||||
|
||||
/// \fn void Throw_CloseNotFound(const std::string& pNode)
|
||||
/// Call that function when close tag of node not found and exception must be raised.
|
||||
/// E.g.:
|
||||
/// <Scene>
|
||||
/// <Shape>
|
||||
/// </Scene> <!--- shape not closed --->
|
||||
/// \throw DeadlyImportError.
|
||||
/// \param [in] pNode - node name in which exception happened.
|
||||
void Throw_CloseNotFound(const std::string& pNode);
|
||||
|
||||
/// \fn void Throw_ConvertFail_Str2ArrF(const std::string& pAttrValue)
|
||||
/// Call that function when string value can not be converted to floating point value and exception must be raised.
|
||||
/// \param [in] pAttrValue - attribute value.
|
||||
/// \throw DeadlyImportError.
|
||||
void Throw_ConvertFail_Str2ArrF(const std::string& pAttrValue);
|
||||
|
||||
/// \fn void Throw_DEF_And_USE()
|
||||
/// Call that function when in node defined attributes "DEF" and "USE" and exception must be raised.
|
||||
/// E.g.: <Box DEF="BigBox" USE="MegaBox">
|
||||
/// \throw DeadlyImportError.
|
||||
void Throw_DEF_And_USE();
|
||||
|
||||
/// \fn void Throw_IncorrectAttr(const std::string& pAttrName)
|
||||
/// Call that function when attribute name is incorrect and exception must be raised.
|
||||
/// \param [in] pAttrName - attribute name.
|
||||
/// \throw DeadlyImportError.
|
||||
void Throw_IncorrectAttr(const std::string& pAttrName);
|
||||
|
||||
/// \fn void Throw_IncorrectAttrValue(const std::string& pAttrName)
|
||||
/// Call that function when attribute value is incorrect and exception must be raised.
|
||||
/// \param [in] pAttrName - attribute name.
|
||||
/// \throw DeadlyImportError.
|
||||
void Throw_IncorrectAttrValue(const std::string& pAttrName);
|
||||
|
||||
/// \fn void Throw_MoreThanOnceDefined(const std::string& pNode, const std::string& pDescription)
|
||||
/// Call that function when some type of nodes are defined twice or more when must be used only once and exception must be raised.
|
||||
/// E.g.:
|
||||
/// <Shape>
|
||||
/// <Box/> <!--- first geometry node --->
|
||||
/// <Sphere/> <!--- second geometry node. raise exception --->
|
||||
/// </Shape>
|
||||
/// \throw DeadlyImportError.
|
||||
/// \param [in] pNodeType - type of node which defined one more time.
|
||||
/// \param [in] pDescription - message about error. E.g. what the node defined while exception raised.
|
||||
void Throw_MoreThanOnceDefined(const std::string& pNodeType, const std::string& pDescription);
|
||||
|
||||
/// \fn void Throw_TagCountIncorrect(const std::string& pNode)
|
||||
/// Call that function when count of opening and closing tags which create group(e.g. <Group>) are not equal and exception must be raised.
|
||||
/// E.g.:
|
||||
/// <Scene>
|
||||
/// <Transform> <!--- first grouping node begin --->
|
||||
/// <Group> <!--- second grouping node begin --->
|
||||
/// </Transform> <!--- first grouping node end --->
|
||||
/// </Scene> <!--- one grouping node still not closed --->
|
||||
/// \throw DeadlyImportError.
|
||||
/// \param [in] pNode - node name in which exception happened.
|
||||
void Throw_TagCountIncorrect(const std::string& pNode);
|
||||
|
||||
/// \fn void Throw_USE_NotFound(const std::string& pAttrValue)
|
||||
/// Call that function when defined in "USE" element are not found in graph and exception must be raised.
|
||||
/// \param [in] pAttrValue - "USE" attribute value.
|
||||
/// \throw DeadlyImportError.
|
||||
void Throw_USE_NotFound(const std::string& pAttrValue);
|
||||
|
||||
/***********************************************/
|
||||
/************** Functions: LOG set *************/
|
||||
/***********************************************/
|
||||
|
||||
/// \fn void LogInfo(const std::string& pMessage)
|
||||
/// Short variant for calling \ref DefaultLogger::get()->info()
|
||||
void LogInfo(const std::string& pMessage) { DefaultLogger::get()->info(pMessage); }
|
||||
|
||||
/// \fn void LogWarning(const std::string& pMessage)
|
||||
/// Short variant for calling \ref DefaultLogger::get()->warn()
|
||||
void LogWarning(const std::string& pMessage) { DefaultLogger::get()->warn(pMessage); }
|
||||
|
||||
/// \fn void LogError(const std::string& pMessage)
|
||||
/// Short variant for calling \ref DefaultLogger::get()->error()
|
||||
void LogError(const std::string& pMessage) { DefaultLogger::get()->error(pMessage); }
|
||||
|
||||
/***********************************************/
|
||||
/************** Functions: XML set *************/
|
||||
/***********************************************/
|
||||
|
||||
/// \fn void XML_CheckNode_MustBeEmpty()
|
||||
/// Chek if current node is empty: <node />. If not then exception will throwed.
|
||||
void XML_CheckNode_MustBeEmpty();
|
||||
|
||||
/// \fn bool XML_CheckNode_NameEqual(const std::string& pNodeName)
|
||||
/// Chek if current node name is equal to pNodeName.
|
||||
/// \param [in] pNodeName - name for checking.
|
||||
/// return true if current node name is equal to pNodeName, else - false.
|
||||
bool XML_CheckNode_NameEqual(const std::string& pNodeName) { return mReader->getNodeName() == pNodeName; }
|
||||
|
||||
/// \fn void XML_CheckNode_SkipUnsupported(const std::string& pParentNodeName)
|
||||
/// Skip unsupported node and report about that. Depend on node name can be skipped begin tag of node all whole node.
|
||||
/// \param [in] pParentNodeName - parent node name. Used for reporting.
|
||||
void XML_CheckNode_SkipUnsupported(const std::string& pParentNodeName);
|
||||
|
||||
/// \fn bool XML_SearchNode(const std::string& pNodeName)
|
||||
/// Search for specified node in file. XML file read pointer(mReader) will point to found node or file end after search is end.
|
||||
/// \param [in] pNodeName - requested node name.
|
||||
/// return true - if node is found, else - false.
|
||||
bool XML_SearchNode(const std::string& pNodeName);
|
||||
|
||||
/// \fn bool XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx)
|
||||
/// Read attribute value.
|
||||
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
|
||||
/// \return read data.
|
||||
bool XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx);
|
||||
|
||||
/// \fn float XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx)
|
||||
/// Read attribute value.
|
||||
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
|
||||
/// \return read data.
|
||||
float XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx);
|
||||
|
||||
/// \fn int32_t XML_ReadNode_GetAttrVal_AsI32(const int pAttrIdx)
|
||||
/// Read attribute value.
|
||||
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
|
||||
/// \return read data.
|
||||
int32_t XML_ReadNode_GetAttrVal_AsI32(const int pAttrIdx);
|
||||
|
||||
/// \fn void XML_ReadNode_GetAttrVal_AsCol3f(const int pAttrIdx, aiColor3D& pValue)
|
||||
/// Read attribute value.
|
||||
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
|
||||
/// \param [out] pValue - read data.
|
||||
void XML_ReadNode_GetAttrVal_AsCol3f(const int pAttrIdx, aiColor3D& pValue);
|
||||
|
||||
/// \fn void XML_ReadNode_GetAttrVal_AsVec2f(const int pAttrIdx, aiVector2D& pValue)
|
||||
/// Read attribute value.
|
||||
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
|
||||
/// \param [out] pValue - read data.
|
||||
void XML_ReadNode_GetAttrVal_AsVec2f(const int pAttrIdx, aiVector2D& pValue);
|
||||
|
||||
/// \fn void XML_ReadNode_GetAttrVal_AsVec3f(const int pAttrIdx, aiVector3D& pValue)
|
||||
/// Read attribute value.
|
||||
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
|
||||
/// \param [out] pValue - read data.
|
||||
void XML_ReadNode_GetAttrVal_AsVec3f(const int pAttrIdx, aiVector3D& pValue);
|
||||
|
||||
/// \fn void XML_ReadNode_GetAttrVal_AsListB(const int pAttrIdx, std::list<bool>& pValue)
|
||||
/// Read attribute value.
|
||||
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
|
||||
/// \param [out] pValue - read data.
|
||||
void XML_ReadNode_GetAttrVal_AsListB(const int pAttrIdx, std::list<bool>& pValue);
|
||||
|
||||
/// \fn void XML_ReadNode_GetAttrVal_AsArrB(const int pAttrIdx, std::vector<bool>& pValue)
|
||||
/// \overload void XML_ReadNode_GetAttrVal_AsListBool(const int pAttrIdx, std::list<bool>& pValue)
|
||||
void XML_ReadNode_GetAttrVal_AsArrB(const int pAttrIdx, std::vector<bool>& pValue);
|
||||
|
||||
/// \fn void XML_ReadNode_GetAttrVal_AsListI32(const int pAttrIdx, std::list<int32_t>& pValue)
|
||||
/// Read attribute value.
|
||||
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
|
||||
/// \param [out] pValue - read data.
|
||||
void XML_ReadNode_GetAttrVal_AsListI32(const int pAttrIdx, std::list<int32_t>& pValue);
|
||||
|
||||
/// \fn void XML_ReadNode_GetAttrVal_AsArrI32(const int pAttrIdx, std::vector<int32_t>& pValue)
|
||||
/// \overload void XML_ReadNode_GetAttrVal_AsListI32(const int pAttrIdx, std::list<int32_t>& pValue)
|
||||
void XML_ReadNode_GetAttrVal_AsArrI32(const int pAttrIdx, std::vector<int32_t>& pValue);
|
||||
|
||||
/// \fn void XML_ReadNode_GetAttrVal_AsListF(const int pAttrIdx, std::list<float>& pValue)
|
||||
/// Read attribute value.
|
||||
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
|
||||
/// \param [out] pValue - read data.
|
||||
void XML_ReadNode_GetAttrVal_AsListF(const int pAttrIdx, std::list<float>& pValue);
|
||||
|
||||
/// \fn void XML_ReadNode_GetAttrVal_AsArrF(const int pAttrIdx, std::vector<float>& pValue)
|
||||
/// \overload void XML_ReadNode_GetAttrVal_AsListF(const int pAttrIdx, std::list<float>& pValue)
|
||||
void XML_ReadNode_GetAttrVal_AsArrF(const int pAttrIdx, std::vector<float>& pValue);
|
||||
|
||||
/// \fn void XML_ReadNode_GetAttrVal_AsListD(const int pAttrIdx, std::list<double>& pValue)
|
||||
/// Read attribute value.
|
||||
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
|
||||
/// \param [out] pValue - read data.
|
||||
void XML_ReadNode_GetAttrVal_AsListD(const int pAttrIdx, std::list<double>& pValue);
|
||||
|
||||
/// \fn void XML_ReadNode_GetAttrVal_AsArrD(const int pAttrIdx, std::vector<double>& pValue)
|
||||
/// \overload void XML_ReadNode_GetAttrVal_AsListD(const int pAttrIdx, std::list<double>& pValue)
|
||||
void XML_ReadNode_GetAttrVal_AsArrD(const int pAttrIdx, std::vector<double>& pValue);
|
||||
|
||||
/// \fn void XML_ReadNode_GetAttrVal_AsListCol3f(const int pAttrIdx, std::list<aiColor3D>& pValue)
|
||||
/// Read attribute value.
|
||||
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
|
||||
/// \param [out] pValue - read data.
|
||||
void XML_ReadNode_GetAttrVal_AsListCol3f(const int pAttrIdx, std::list<aiColor3D>& pValue);
|
||||
|
||||
/// \fn void XML_ReadNode_GetAttrVal_AsArrCol3f(const int pAttrIdx, std::vector<aiColor3D>& pValue)
|
||||
/// \overload void XML_ReadNode_GetAttrVal_AsListCol3f(const int pAttrIdx, std::vector<aiColor3D>& pValue)
|
||||
void XML_ReadNode_GetAttrVal_AsArrCol3f(const int pAttrIdx, std::vector<aiColor3D>& pValue);
|
||||
|
||||
/// \fn void XML_ReadNode_GetAttrVal_AsListCol4f(const int pAttrIdx, std::list<aiColor4D>& pValue)
|
||||
/// Read attribute value.
|
||||
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
|
||||
/// \param [out] pValue - read data.
|
||||
void XML_ReadNode_GetAttrVal_AsListCol4f(const int pAttrIdx, std::list<aiColor4D>& pValue);
|
||||
|
||||
/// \fn void XML_ReadNode_GetAttrVal_AsArrCol4f(const int pAttrIdx, std::vector<aiColor4D>& pValue)
|
||||
/// \overload void XML_ReadNode_GetAttrVal_AsListCol4f(const int pAttrIdx, std::list<aiColor4D>& pValue)
|
||||
void XML_ReadNode_GetAttrVal_AsArrCol4f(const int pAttrIdx, std::vector<aiColor4D>& pValue);
|
||||
|
||||
/// \fn void XML_ReadNode_GetAttrVal_AsListVec2f(const int pAttrIdx, std::list<aiVector2D>& pValue)
|
||||
/// Read attribute value.
|
||||
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
|
||||
/// \param [out] pValue - read data.
|
||||
void XML_ReadNode_GetAttrVal_AsListVec2f(const int pAttrIdx, std::list<aiVector2D>& pValue);
|
||||
|
||||
/// \fn void XML_ReadNode_GetAttrVal_AsArrVec2f(const int pAttrIdx, std::vector<aiVector2D>& pValue)
|
||||
/// \overload void XML_ReadNode_GetAttrVal_AsListVec2f(const int pAttrIdx, std::list<aiVector2D>& pValue)
|
||||
void XML_ReadNode_GetAttrVal_AsArrVec2f(const int pAttrIdx, std::vector<aiVector2D>& pValue);
|
||||
|
||||
/// \fn void XML_ReadNode_GetAttrVal_AsListVec3f(const int pAttrIdx, std::list<aiVector3D>& pValue)
|
||||
/// Read attribute value.
|
||||
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
|
||||
/// \param [out] pValue - read data.
|
||||
void XML_ReadNode_GetAttrVal_AsListVec3f(const int pAttrIdx, std::list<aiVector3D>& pValue);
|
||||
|
||||
/// \fn void XML_ReadNode_GetAttrVal_AsArrVec3f(const int pAttrIdx, std::vector<aiVector3D>& pValue)
|
||||
/// \overload void XML_ReadNode_GetAttrVal_AsListVec3f(const int pAttrIdx, std::list<aiVector3D>& pValue)
|
||||
void XML_ReadNode_GetAttrVal_AsArrVec3f(const int pAttrIdx, std::vector<aiVector3D>& pValue);
|
||||
|
||||
/// \fn void XML_ReadNode_GetAttrVal_AsListS(const int pAttrIdx, std::list<std::string>& pValue)
|
||||
/// Read attribute value.
|
||||
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
|
||||
/// \param [out] pValue - read data.
|
||||
void XML_ReadNode_GetAttrVal_AsListS(const int pAttrIdx, std::list<std::string>& pValue);
|
||||
|
||||
/***********************************************/
|
||||
/******* Functions: geometry helper set *******/
|
||||
/***********************************************/
|
||||
|
||||
/// \fn aiVector3D GeometryHelper_Make_Point2D(const float pAngle, const float pRadius)
|
||||
/// Make point on surface oXY.
|
||||
/// \param [in] pAngle - angle in radians between radius-vector of point and oX axis. Angle extends from the oX axis counterclockwise to the radius-vector.
|
||||
/// \param [in] pRadius - length of radius-vector.
|
||||
/// \return made point coordinates.
|
||||
aiVector3D GeometryHelper_Make_Point2D(const float pAngle, const float pRadius);
|
||||
|
||||
/// \fn void GeometryHelper_Make_Arc2D(const float pStartAngle, const float pEndAngle, const float pRadius, size_t pNumSegments, std::list<aiVector3D>& pVertices)
|
||||
/// Make 2D figure - linear circular arc with center in (0, 0). The z-coordinate is 0. The arc extends from the pStartAngle counterclockwise
|
||||
/// to the pEndAngle. If pStartAngle and pEndAngle have the same value, a circle is specified. If the absolute difference between pStartAngle
|
||||
/// and pEndAngle is greater than or equal to 2pi, a circle is specified.
|
||||
/// \param [in] pStartAngle - angle in radians of start of the arc.
|
||||
/// \param [in] pEndAngle - angle in radians of end of the arc.
|
||||
/// \param [in] pRadius - radius of the arc.
|
||||
/// \param [out] pNumSegments - number of segments in arc. In other words - tesselation factor.
|
||||
/// \param [out] pVertices - generated vertices.
|
||||
void GeometryHelper_Make_Arc2D(const float pStartAngle, const float pEndAngle, const float pRadius, size_t pNumSegments, std::list<aiVector3D>& pVertices);
|
||||
|
||||
/// \fn void GeometryHelper_Extend_PointToLine(const std::list<aiVector3D>& pPoint, std::list<aiVector3D>& pLine)
|
||||
/// Create line set from point set.
|
||||
/// \param [in] pPoint - input points list.
|
||||
/// \param [out] pLine - made lines list.
|
||||
void GeometryHelper_Extend_PointToLine(const std::list<aiVector3D>& pPoint, std::list<aiVector3D>& pLine);
|
||||
|
||||
/// \fn GeometryHelper_Extend_PolylineIdxToLineIdx(const std::list<int32_t>& pPolylineCoordIdx, std::list<int32_t>& pLineCoordIdx)
|
||||
/// Create CoordIdx of line set from CoordIdx of polyline set.
|
||||
/// \param [in] pPolylineCoordIdx - vertices indices divided by delimiter "-1". Must contain faces with two or more indices.
|
||||
/// \param [out] pLineCoordIdx - made CoordIdx of line set.
|
||||
void GeometryHelper_Extend_PolylineIdxToLineIdx(const std::list<int32_t>& pPolylineCoordIdx, std::list<int32_t>& pLineCoordIdx);
|
||||
|
||||
/// \fn void GeometryHelper_MakeQL_RectParallelepiped(const aiVector3D& pSize, std::list<aiVector3D>& pVertices)
|
||||
/// Make 3D body - rectangular parallelepiped with center in (0, 0). QL mean quadlist (\sa pVertices).
|
||||
/// \param [in] pSize - scale factor for body for every axis. E.g. (1, 2, 1) mean: X-size and Z-size - 1, Y-size - 2.
|
||||
/// \param [out] pVertices - generated vertices. The list of vertices is grouped in quads.
|
||||
void GeometryHelper_MakeQL_RectParallelepiped(const aiVector3D& pSize, std::list<aiVector3D>& pVertices);
|
||||
|
||||
/// \fn void GeometryHelper_CoordIdxStr2FacesArr(const std::list<int32_t>& pCoordIdx, std::vector<aiFace>& pFaces, unsigned int& pPrimitiveTypes) const
|
||||
/// Create faces array from vertices indices array.
|
||||
/// \param [in] pCoordIdx - vertices indices divided by delimiter "-1".
|
||||
/// \param [in] pFaces - created faces array.
|
||||
/// \param [in] pPrimitiveTypes - type of primitives in faces.
|
||||
void GeometryHelper_CoordIdxStr2FacesArr(const std::list<int32_t>& pCoordIdx, std::vector<aiFace>& pFaces, unsigned int& pPrimitiveTypes) const;
|
||||
|
||||
/// \fn void MeshGeometry_AddColor(aiMesh& pMesh, const std::list<int32_t>& pCoordIdx, const std::list<aiColor4D>& pColors, const bool pColorPerVertex) const
|
||||
/// Add colors to mesh.
|
||||
/// a. If colorPerVertex is FALSE, colours are applied to each face, as follows:
|
||||
/// If the colorIndex field is not empty, one colour is used for each face of the mesh. There shall be at least as many indices in the
|
||||
/// colorIndex field as there are faces in the mesh. The colorIndex field shall not contain any negative entries.
|
||||
/// If the colorIndex field is empty, the colours in the X3DColorNode node are applied to each face of the mesh in order.
|
||||
/// There shall be at least as many colours in the X3DColorNode node as there are faces.
|
||||
/// b. If colorPerVertex is TRUE, colours are applied to each vertex, as follows:
|
||||
/// If the colorIndex field is not empty, colours are applied to each vertex of the mesh in exactly the same manner that the coordIndex
|
||||
/// field is used to choose coordinates for each vertex from the <Coordinate> node. The colorIndex field shall contain end-of-face markers (−1)
|
||||
/// in exactly the same places as the coordIndex field.
|
||||
/// If the colorIndex field is empty, the coordIndex field is used to choose colours from the X3DColorNode node.
|
||||
/// \param [in] pMesh - mesh for adding data.
|
||||
/// \param [in] pCoordIdx - vertices indices divided by delimiter "-1".
|
||||
/// \param [in] pColorIdx - color indices for every vertex divided by delimiter "-1" if \ref pColorPerVertex is true. if \ref pColorPerVertex is false
|
||||
/// then pColorIdx contain color indices for every faces and must not contain delimiter "-1".
|
||||
/// \param [in] pColors - defined colors.
|
||||
/// \param [in] pColorPerVertex - if \ref pColorPerVertex is true then color in \ref pColors defined for every vertex, if false - for every face.
|
||||
void MeshGeometry_AddColor(aiMesh& pMesh, const std::list<int32_t>& pCoordIdx, const std::list<int32_t>& pColorIdx,
|
||||
const std::list<aiColor4D>& pColors, const bool pColorPerVertex) const;
|
||||
|
||||
/// \fn void MeshGeometry_AddColor(aiMesh& pMesh, const std::list<int32_t>& pCoordIdx, const std::list<int32_t>& pColorIdx, const std::list<aiColor3D>& pColors, const bool pColorPerVertex) const;
|
||||
/// \overload void MeshGeometry_AddColor(aiMesh& pMesh, const std::list<int32_t>& pCoordIdx, const std::list<int32_t>& pColorIdx, const std::list<aiColor4D>& pColors, const bool pColorPerVertex) const;
|
||||
void MeshGeometry_AddColor(aiMesh& pMesh, const std::list<int32_t>& pCoordIdx, const std::list<int32_t>& pColorIdx,
|
||||
const std::list<aiColor3D>& pColors, const bool pColorPerVertex) const;
|
||||
|
||||
/// \fn void MeshGeometry_AddColor(aiMesh& pMesh, const std::list<aiColor4D>& pColors, const bool pColorPerVertex) const
|
||||
/// Add colors to mesh.
|
||||
/// \param [in] pMesh - mesh for adding data.
|
||||
/// \param [in] pColors - defined colors.
|
||||
/// \param [in] pColorPerVertex - if \ref pColorPerVertex is true then color in \ref pColors defined for every vertex, if false - for every face.
|
||||
void MeshGeometry_AddColor(aiMesh& pMesh, const std::list<aiColor4D>& pColors, const bool pColorPerVertex) const;
|
||||
|
||||
/// \fn void MeshGeometry_AddColor(aiMesh& pMesh, const std::list<aiColor3D>& pColors, const bool pColorPerVertex) const
|
||||
/// \overload void MeshGeometry_AddColor(aiMesh& pMesh, const std::list<aiColor4D>& pColors, const bool pColorPerVertex) const
|
||||
void MeshGeometry_AddColor(aiMesh& pMesh, const std::list<aiColor3D>& pColors, const bool pColorPerVertex) const;
|
||||
|
||||
/// \fn void MeshGeometry_AddNormal(aiMesh& pMesh, const std::list<int32_t>& pCoordIdx, const std::list<int32_t>& pNormalIdx, const std::list<aiVector3D>& pNormals, const bool pNormalPerVertex) const
|
||||
/// Add normals to mesh. Function work similar to \ref MeshGeometry_AddColor;
|
||||
void MeshGeometry_AddNormal(aiMesh& pMesh, const std::list<int32_t>& pCoordIdx, const std::list<int32_t>& pNormalIdx,
|
||||
const std::list<aiVector3D>& pNormals, const bool pNormalPerVertex) const;
|
||||
|
||||
/// \fn void MeshGeometry_AddNormal(aiMesh& pMesh, const std::list<aiVector3D>& pNormals, const bool pNormalPerVertex) const
|
||||
/// Add normals to mesh. Function work similar to \ref MeshGeometry_AddColor;
|
||||
void MeshGeometry_AddNormal(aiMesh& pMesh, const std::list<aiVector3D>& pNormals, const bool pNormalPerVertex) const;
|
||||
|
||||
/// \fn void MeshGeometry_AddTexCoord(aiMesh& pMesh, const std::list<int32_t>& pCoordIdx, const std::list<int32_t>& pTexCoordIdx, const std::list<aiVector2D>& pTexCoords) const
|
||||
/// Add texture coordinates to mesh. Function work similar to \ref MeshGeometry_AddColor;
|
||||
void MeshGeometry_AddTexCoord(aiMesh& pMesh, const std::list<int32_t>& pCoordIdx, const std::list<int32_t>& pTexCoordIdx,
|
||||
const std::list<aiVector2D>& pTexCoords) const;
|
||||
|
||||
/// \fn void MeshGeometry_AddTexCoord(aiMesh& pMesh, const std::list<aiVector2D>& pTexCoords) const
|
||||
/// Add texture coordinates to mesh. Function work similar to \ref MeshGeometry_AddColor;
|
||||
void MeshGeometry_AddTexCoord(aiMesh& pMesh, const std::list<aiVector2D>& pTexCoords) const;
|
||||
|
||||
/// \fn aiMesh* GeometryHelper_MakeMesh(const std::list<int32_t>& pCoordIdx, const std::list<aiVector3D>& pVertices) const
|
||||
/// Create mesh.
|
||||
/// \param [in] pCoordIdx - vertices indices divided by delimiter "-1".
|
||||
/// \param [in] pVertices - vertices of mesh.
|
||||
/// \return created mesh.
|
||||
aiMesh* GeometryHelper_MakeMesh(const std::list<int32_t>& pCoordIdx, const std::list<aiVector3D>& pVertices) const;
|
||||
|
||||
/***********************************************/
|
||||
/******** Functions: parse set private *********/
|
||||
/***********************************************/
|
||||
|
||||
/// \fn void ParseHelper_Group_Begin()
|
||||
/// Create node element with type "Node" in scene graph. That operation is needed when you enter to X3D group node
|
||||
/// like <Group>, <Transform> etc. When exiting from X3D group node(e.g. </Group>) \ref ParseHelper_Node_Exit must
|
||||
/// be called.
|
||||
/// \param [in] pStatic - flag: if true then static node is created(e.g. <StaticGroup>).
|
||||
void ParseHelper_Group_Begin(const bool pStatic = false);
|
||||
|
||||
/// \fn void ParseHelper_Node_Enter(CX3DImporter_NodeElement* pNode)
|
||||
/// Make pNode as current and enter deeper for parsing child nodes. At end \ref ParseHelper_Node_Exit must be called.
|
||||
/// \param [in] pNode - new current node.
|
||||
void ParseHelper_Node_Enter(CX3DImporter_NodeElement* pNode);
|
||||
|
||||
/// \fn void ParseHelper_Group_End()
|
||||
/// This function must be called when exiting from X3D group node(e.g. </Group>). \ref ParseHelper_Group_Begin.
|
||||
void ParseHelper_Node_Exit();
|
||||
|
||||
/// \fn void ParseHelper_FixTruncatedFloatString(const char* pInStr, std::string& pOutString)
|
||||
/// Attribute values of floating point types can take form ".x"(without leading zero). irrXMLReader can not read this form of values and it
|
||||
/// must be converted to right form - "0.xxx".
|
||||
/// \param [in] pInStr - pointer to input string which can contain incorrect form of values.
|
||||
/// \param [out[ pOutString - output string with right form of values.
|
||||
void ParseHelper_FixTruncatedFloatString(const char* pInStr, std::string& pOutString);
|
||||
|
||||
/// \fn bool ParseHelper_CheckRead_X3DMetadataObject()
|
||||
/// Check if current node has nodes of type X3DMetadataObject. Why we must do it? Because X3DMetadataObject can be in any non-empty X3DNode.
|
||||
/// Meaning that X3DMetadataObject can be in any non-empty node in <Scene>.
|
||||
/// \return true - if metadata node are found and parsed, false - metadata not found.
|
||||
bool ParseHelper_CheckRead_X3DMetadataObject();
|
||||
|
||||
/// \fn bool ParseHelper_CheckRead_X3DMetadataObject()
|
||||
/// Check if current node has nodes of type X3DGeometricPropertyNode. X3DGeometricPropertyNode
|
||||
/// X3DGeometricPropertyNode inheritors:
|
||||
/// <FogCoordinate>, <HAnimDisplacer>, <Color>, <ColorRGBA>, <Coordinate>, <CoordinateDouble>, <GeoCoordinate>, <Normal>,
|
||||
/// <MultiTextureCoordinate>, <TextureCoordinate>, <TextureCoordinate3D>, <TextureCoordinate4D>, <TextureCoordinateGenerator>,
|
||||
/// <FloatVertexAttribute>, <Matrix3VertexAttribute>, <Matrix4VertexAttribute>.
|
||||
/// \return true - if nodes are found and parsed, false - nodes not found.
|
||||
bool ParseHelper_CheckRead_X3DGeometricPropertyNode();
|
||||
|
||||
/// \fn void ParseNode_Root()
|
||||
/// Parse <X3D> node of the file.
|
||||
void ParseNode_Root();
|
||||
|
||||
/// \fn void ParseNode_Head()
|
||||
/// Parse <head> node of the file.
|
||||
void ParseNode_Head();
|
||||
|
||||
/// \fn void ParseNode_Root()
|
||||
/// Parse <Scene> node of the file.
|
||||
void ParseNode_Scene();
|
||||
|
||||
/// \fn void ParseNode_Metadata(CX3DImporter_NodeElement* pParent, const std::string& pNodeName)
|
||||
/// Parse child nodes of <Metadata*> node.
|
||||
/// \param [in] pNodeName - parsed node name. Must be set because that function is general and name needed for checking the end
|
||||
/// and error reporing.
|
||||
/// \param [in] pParentElement - parent metadata element.
|
||||
void ParseNode_Metadata(CX3DImporter_NodeElement* pParentElement, const std::string& pNodeName);
|
||||
|
||||
/// \fn void ParseNode_MetadataBoolean()
|
||||
/// Parse <MetadataBoolean> node of the file.
|
||||
void ParseNode_MetadataBoolean();
|
||||
|
||||
/// \fn void ParseNode_MetadataDouble()
|
||||
/// Parse <MetadataDouble> node of the file.
|
||||
void ParseNode_MetadataDouble();
|
||||
|
||||
/// \fn void ParseNode_MetadataFloat()
|
||||
/// Parse <MetadataFloat> node of the file.
|
||||
void ParseNode_MetadataFloat();
|
||||
|
||||
/// \fn void ParseNode_MetadataInteger()
|
||||
/// Parse <MetadataInteger> node of the file.
|
||||
void ParseNode_MetadataInteger();
|
||||
|
||||
/// \fn void ParseNode_MetadataSet()
|
||||
/// Parse <MetadataSet> node of the file.
|
||||
void ParseNode_MetadataSet();
|
||||
|
||||
/// \fn void ParseNode_MetadataString()
|
||||
/// Parse <MetadataString> node of the file.
|
||||
void ParseNode_MetadataString();
|
||||
|
||||
/// \fn void ParseNode_Geometry2D_Arc2D()
|
||||
/// Parse <Arc2D> node of the file.
|
||||
void ParseNode_Geometry2D_Arc2D();
|
||||
|
||||
/// \fn void ParseNode_Geometry2D_ArcClose2D()
|
||||
/// Parse <ArcClose2D> node of the file.
|
||||
void ParseNode_Geometry2D_ArcClose2D();
|
||||
|
||||
/// \fn void ParseNode_Geometry2D_Circle2D()
|
||||
/// Parse <Circle2D> node of the file.
|
||||
void ParseNode_Geometry2D_Circle2D();
|
||||
|
||||
/// \fn void ParseNode_Geometry2D_Disk2D()
|
||||
/// Parse <Disk2D> node of the file.
|
||||
void ParseNode_Geometry2D_Disk2D();
|
||||
|
||||
/// \fn void ParseNode_Geometry2D_Polyline2D()
|
||||
/// Parse <Polyline2D> node of the file.
|
||||
void ParseNode_Geometry2D_Polyline2D();
|
||||
|
||||
/// \fn void ParseNode_Geometry2D_Polypoint2D()
|
||||
/// Parse <Polypoint2D> node of the file.
|
||||
void ParseNode_Geometry2D_Polypoint2D();
|
||||
|
||||
/// \fn void ParseNode_Geometry2D_Rectangle2D()
|
||||
/// Parse <Rectangle2D> node of the file.
|
||||
void ParseNode_Geometry2D_Rectangle2D();
|
||||
|
||||
/// \fn void ParseNode_Geometry2D_TriangleSet2D()
|
||||
/// Parse <TriangleSet2D> node of the file.
|
||||
void ParseNode_Geometry2D_TriangleSet2D();
|
||||
|
||||
/// \fn void ParseNode_Geometry3D_Box()
|
||||
/// Parse <Box> node of the file.
|
||||
void ParseNode_Geometry3D_Box();
|
||||
|
||||
/// \fn void ParseNode_Geometry3D_Cone()
|
||||
/// Parse <Cone> node of the file.
|
||||
void ParseNode_Geometry3D_Cone();
|
||||
|
||||
/// \fn void ParseNode_Geometry3D_Cylinder()
|
||||
/// Parse <Cylinder> node of the file.
|
||||
void ParseNode_Geometry3D_Cylinder();
|
||||
|
||||
/// \fn void ParseNode_Geometry3D_ElevationGrid()
|
||||
/// Parse <ElevationGrid> node of the file.
|
||||
void ParseNode_Geometry3D_ElevationGrid();
|
||||
|
||||
/// \fn void ParseNode_Geometry3D_Extrusion()
|
||||
/// Parse <Extrusion> node of the file.
|
||||
void ParseNode_Geometry3D_Extrusion();
|
||||
|
||||
/// \fn void ParseNode_Geometry3D_IndexedFaceSet()
|
||||
/// Parse <IndexedFaceSet> node of the file.
|
||||
void ParseNode_Geometry3D_IndexedFaceSet();
|
||||
|
||||
/// \fn void ParseNode_Geometry3D_Sphere()
|
||||
/// Parse <Sphere> node of the file.
|
||||
void ParseNode_Geometry3D_Sphere();
|
||||
|
||||
/// \fn void ParseNode_Grouping_Group()
|
||||
/// Parse <Group> node of the file. And create new node in scene graph.
|
||||
void ParseNode_Grouping_Group();
|
||||
|
||||
/// \fn void ParseNode_Grouping_GroupEnd()
|
||||
/// Doing actions at an exit from <Group>. Walk up in scene graph.
|
||||
void ParseNode_Grouping_GroupEnd();
|
||||
|
||||
/// \fn void ParseNode_Grouping_StaticGroup()
|
||||
/// Parse <StaticGroup> node of the file. And create new node in scene graph.
|
||||
void ParseNode_Grouping_StaticGroup();
|
||||
|
||||
/// \fn void ParseNode_Grouping_StaticGroupEnd()
|
||||
/// Doing actions at an exit from <StaticGroup>. Walk up in scene graph.
|
||||
void ParseNode_Grouping_StaticGroupEnd();
|
||||
|
||||
/// \fn void ParseNode_Grouping_Switch()
|
||||
/// Parse <Switch> node of the file. And create new node in scene graph.
|
||||
void ParseNode_Grouping_Switch();
|
||||
|
||||
/// \fn void ParseNode_Grouping_SwitchEnd()
|
||||
/// Doing actions at an exit from <Switch>. Walk up in scene graph.
|
||||
void ParseNode_Grouping_SwitchEnd();
|
||||
|
||||
/// \fn void ParseNode_Grouping_Transform()
|
||||
/// Parse <Transform> node of the file. And create new node in scene graph.
|
||||
void ParseNode_Grouping_Transform();
|
||||
|
||||
/// \fn void ParseNode_Grouping_TransformEnd()
|
||||
/// Doing actions at an exit from <Transform>. Walk up in scene graph.
|
||||
void ParseNode_Grouping_TransformEnd();
|
||||
|
||||
/// \fn void ParseNode_Rendering_Color()
|
||||
/// Parse <Color> node of the file.
|
||||
void ParseNode_Rendering_Color();
|
||||
|
||||
/// \fn void ParseNode_Rendering_ColorRGBA()
|
||||
/// Parse <ColorRGBA> node of the file.
|
||||
void ParseNode_Rendering_ColorRGBA();
|
||||
|
||||
/// \fn void ParseNode_Rendering_Coordinate()
|
||||
/// Parse <Coordinate> node of the file.
|
||||
void ParseNode_Rendering_Coordinate();
|
||||
|
||||
/// \fn void ParseNode_Rendering_Normal()
|
||||
/// Parse <Normal> node of the file.
|
||||
void ParseNode_Rendering_Normal();
|
||||
|
||||
/// \fn void ParseNode_Rendering_IndexedLineSet()
|
||||
/// Parse <IndexedLineSet> node of the file.
|
||||
void ParseNode_Rendering_IndexedLineSet();
|
||||
|
||||
/// \fn void ParseNode_Rendering_IndexedTriangleFanSet()
|
||||
/// Parse <IndexedTriangleFanSet> node of the file.
|
||||
void ParseNode_Rendering_IndexedTriangleFanSet();
|
||||
|
||||
/// \fn void ParseNode_Rendering_IndexedTriangleSet()
|
||||
/// Parse <IndexedTriangleSet> node of the file.
|
||||
void ParseNode_Rendering_IndexedTriangleSet();
|
||||
|
||||
/// \fn void ParseNode_Rendering_IndexedTriangleStripSet()
|
||||
/// Parse <IndexedTriangleStripSet> node of the file.
|
||||
void ParseNode_Rendering_IndexedTriangleStripSet();
|
||||
|
||||
/// \fn void ParseNode_Rendering_LineSet()
|
||||
/// Parse <LineSet> node of the file.
|
||||
void ParseNode_Rendering_LineSet();
|
||||
|
||||
/// \fn void ParseNode_Rendering_PointSet()
|
||||
/// Parse <PointSet> node of the file.
|
||||
void ParseNode_Rendering_PointSet();
|
||||
|
||||
/// \fn void ParseNode_Rendering_TriangleFanSet()
|
||||
/// Parse <TriangleFanSet> node of the file.
|
||||
void ParseNode_Rendering_TriangleFanSet();
|
||||
|
||||
/// \fn void ParseNode_Rendering_TriangleSet()
|
||||
/// Parse <TriangleSet> node of the file.
|
||||
void ParseNode_Rendering_TriangleSet();
|
||||
|
||||
/// \fn void ParseNode_Rendering_TriangleStripSet()
|
||||
/// Parse <TriangleStripSet> node of the file.
|
||||
void ParseNode_Rendering_TriangleStripSet();
|
||||
|
||||
/// \fn void ParseNode_Texturing_ImageTexture()
|
||||
/// Parse <ImageTexture> node of the file.
|
||||
void ParseNode_Texturing_ImageTexture();
|
||||
|
||||
/// \fn void ParseNode_Texturing_TextureCoordinate()
|
||||
/// Parse <TextureCoordinate> node of the file.
|
||||
void ParseNode_Texturing_TextureCoordinate();
|
||||
|
||||
/// \fn void ParseNode_Texturing_TextureTransform()
|
||||
/// Parse <TextureTransform> node of the file.
|
||||
void ParseNode_Texturing_TextureTransform();
|
||||
|
||||
/// \fn void ParseNode_Shape_Shape()
|
||||
/// Parse <Shape> node of the file.
|
||||
void ParseNode_Shape_Shape();
|
||||
|
||||
/// \fn void ParseNode_Shape_Appearance()
|
||||
/// Parse <Appearance> node of the file.
|
||||
void ParseNode_Shape_Appearance();
|
||||
|
||||
/// \fn void ParseNode_Shape_Material()
|
||||
/// Parse <Material> node of the file.
|
||||
void ParseNode_Shape_Material();
|
||||
|
||||
/// \fn void ParseNode_Networking_Inline()
|
||||
/// Parse <Inline> node of the file.
|
||||
void ParseNode_Networking_Inline();
|
||||
|
||||
/// \fn void ParseNode_Lighting_DirectionalLight()
|
||||
/// Parse <DirectionalLight> node of the file.
|
||||
void ParseNode_Lighting_DirectionalLight();
|
||||
|
||||
/// \fn void ParseNode_Lighting_PointLight()
|
||||
/// Parse <PointLight> node of the file.
|
||||
void ParseNode_Lighting_PointLight();
|
||||
|
||||
/// \fn void ParseNode_Lighting_SpotLight()
|
||||
/// Parse <SpotLight> node of the file.
|
||||
void ParseNode_Lighting_SpotLight();
|
||||
|
||||
public:
|
||||
|
||||
/// \fn X3DImporter()
|
||||
/// Default constructor.
|
||||
X3DImporter()
|
||||
: NodeElement_Cur(NULL), mReader(NULL)
|
||||
{}
|
||||
|
||||
/// \fn ~X3DImporter()
|
||||
/// Default destructor.
|
||||
~X3DImporter();
|
||||
|
||||
/***********************************************/
|
||||
/******** Functions: parse set, public *********/
|
||||
/***********************************************/
|
||||
|
||||
/// \fn void ParseFile(const std::string& pFile, IOSystem* pIOHandler)
|
||||
/// Parse X3D file and fill scene graph. The function has no return value. Result can be found by analyzing the generated graph.
|
||||
/// Also exception can be throwed if trouble will found.
|
||||
/// \param [in] pFile - name of file to be parsed.
|
||||
/// \param [in] pIOHandler - pointer to IO helper object.
|
||||
void ParseFile(const std::string& pFile, IOSystem* pIOHandler);
|
||||
|
||||
/***********************************************/
|
||||
/********* Functions: BaseImporter set *********/
|
||||
/***********************************************/
|
||||
|
||||
bool CanRead(const std::string& pFile, IOSystem* pIOHandler, bool pCheckSig) const;
|
||||
void GetExtensionList(std::set<std::string>& pExtensionList);
|
||||
void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
|
||||
const aiImporterDesc* GetInfo ()const;
|
||||
|
||||
};// class X3DImporter
|
||||
|
||||
}// namespace Assimp
|
||||
|
||||
#endif // INCLUDED_AI_X3D_IMPORTER_H
|
|
@ -0,0 +1,481 @@
|
|||
/// \file X3DImporter_Geometry2D.cpp
|
||||
/// \brief Parsing data from nodes of "Geometry2D" set of X3D.
|
||||
/// \date 2015-2016
|
||||
/// \author nevorek@gmail.com
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
|
||||
#include "X3DImporter.hpp"
|
||||
#include "X3DImporter_Node.hpp"
|
||||
#include "X3DImporter_Macro.hpp"
|
||||
|
||||
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::ParseNode_Geometry2D_Arc2D()
|
||||
{
|
||||
std::string def, use;
|
||||
float endAngle = AI_MATH_HALF_PI_F;
|
||||
float radius = 1;
|
||||
float startAngle = 0;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_RET("endAngle", endAngle, XML_ReadNode_GetAttrVal_AsFloat);
|
||||
MACRO_ATTRREAD_CHECK_RET("radius", radius, XML_ReadNode_GetAttrVal_AsFloat);
|
||||
MACRO_ATTRREAD_CHECK_RET("startAngle", startAngle, XML_ReadNode_GetAttrVal_AsFloat);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Arc2D, ne);
|
||||
}
|
||||
else
|
||||
{
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new CX3DImporter_NodeElement_Geometry2D(CX3DImporter_NodeElement::ENET_Arc2D, NodeElement_Cur);
|
||||
if(!def.empty()) ne->ID = def;
|
||||
|
||||
// create point list of geometry object and convert it to line set.
|
||||
std::list<aiVector3D> tlist;
|
||||
|
||||
GeometryHelper_Make_Arc2D(startAngle, endAngle, radius, 10, tlist);///TODO: IME - AI_CONFIG for NumSeg
|
||||
GeometryHelper_Extend_PointToLine(tlist, ((CX3DImporter_NodeElement_Geometry2D*)ne)->Vertices);
|
||||
((CX3DImporter_NodeElement_Geometry2D*)ne)->NumIndices = 2;
|
||||
// check for X3DMetadataObject childs.
|
||||
if(!mReader->isEmptyElement())
|
||||
ParseNode_Metadata(ne, "Arc2D");
|
||||
else
|
||||
NodeElement_Cur->Child.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::ParseNode_Geometry2D_ArcClose2D()
|
||||
{
|
||||
std::string def, use;
|
||||
std::string closureType("PIE");
|
||||
float endAngle = AI_MATH_HALF_PI_F;
|
||||
float radius = 1;
|
||||
bool solid = false;
|
||||
float startAngle = 0;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_RET("closureType", closureType, mReader->getAttributeValue);
|
||||
MACRO_ATTRREAD_CHECK_RET("endAngle", endAngle, XML_ReadNode_GetAttrVal_AsFloat);
|
||||
MACRO_ATTRREAD_CHECK_RET("radius", radius, XML_ReadNode_GetAttrVal_AsFloat);
|
||||
MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("startAngle", startAngle, XML_ReadNode_GetAttrVal_AsFloat);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_ArcClose2D, ne);
|
||||
}
|
||||
else
|
||||
{
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new CX3DImporter_NodeElement_Geometry2D(CX3DImporter_NodeElement::ENET_ArcClose2D, NodeElement_Cur);
|
||||
if(!def.empty()) ne->ID = def;
|
||||
|
||||
((CX3DImporter_NodeElement_Geometry2D*)ne)->Solid = solid;
|
||||
// create point list of geometry object.
|
||||
GeometryHelper_Make_Arc2D(startAngle, endAngle, radius, 10, ((CX3DImporter_NodeElement_Geometry2D*)ne)->Vertices);///TODO: IME - AI_CONFIG for NumSeg
|
||||
// add chord or two radiuses only if not a circle was defined
|
||||
if(!((fabs(endAngle - startAngle) >= AI_MATH_TWO_PI_F) || (endAngle == startAngle)))
|
||||
{
|
||||
std::list<aiVector3D>& vlist = ((CX3DImporter_NodeElement_Geometry2D*)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("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).
|
||||
}
|
||||
|
||||
((CX3DImporter_NodeElement_Geometry2D*)ne)->NumIndices = ((CX3DImporter_NodeElement_Geometry2D*)ne)->Vertices.size();
|
||||
// check for X3DMetadataObject childs.
|
||||
if(!mReader->isEmptyElement())
|
||||
ParseNode_Metadata(ne, "ArcClose2D");
|
||||
else
|
||||
NodeElement_Cur->Child.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::ParseNode_Geometry2D_Circle2D()
|
||||
{
|
||||
std::string def, use;
|
||||
float radius = 1;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_RET("radius", radius, XML_ReadNode_GetAttrVal_AsFloat);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Circle2D, ne);
|
||||
}
|
||||
else
|
||||
{
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new CX3DImporter_NodeElement_Geometry2D(CX3DImporter_NodeElement::ENET_Circle2D, NodeElement_Cur);
|
||||
if(!def.empty()) ne->ID = def;
|
||||
|
||||
// create point list of geometry object and convert it to line set.
|
||||
std::list<aiVector3D> tlist;
|
||||
|
||||
GeometryHelper_Make_Arc2D(0, 0, radius, 10, tlist);///TODO: IME - AI_CONFIG for NumSeg
|
||||
GeometryHelper_Extend_PointToLine(tlist, ((CX3DImporter_NodeElement_Geometry2D*)ne)->Vertices);
|
||||
((CX3DImporter_NodeElement_Geometry2D*)ne)->NumIndices = 2;
|
||||
// check for X3DMetadataObject childs.
|
||||
if(!mReader->isEmptyElement())
|
||||
ParseNode_Metadata(ne, "Circle2D");
|
||||
else
|
||||
NodeElement_Cur->Child.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::ParseNode_Geometry2D_Disk2D()
|
||||
{
|
||||
std::string def, use;
|
||||
float innerRadius = 0;
|
||||
float outerRadius = 1;
|
||||
bool solid = false;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_RET("innerRadius", innerRadius, XML_ReadNode_GetAttrVal_AsFloat);
|
||||
MACRO_ATTRREAD_CHECK_RET("outerRadius", outerRadius, XML_ReadNode_GetAttrVal_AsFloat);
|
||||
MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Disk2D, ne);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::list<aiVector3D> tlist_o, tlist_i;
|
||||
|
||||
if(innerRadius > outerRadius) Throw_IncorrectAttrValue("innerRadius");
|
||||
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new CX3DImporter_NodeElement_Geometry2D(CX3DImporter_NodeElement::ENET_Disk2D, NodeElement_Cur);
|
||||
if(!def.empty()) ne->ID = def;
|
||||
|
||||
// create point list of geometry object.
|
||||
///TODO: IME - AI_CONFIG for NumSeg
|
||||
GeometryHelper_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.
|
||||
((CX3DImporter_NodeElement_Geometry2D*)ne)->Vertices = tlist_o;
|
||||
((CX3DImporter_NodeElement_Geometry2D*)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.
|
||||
GeometryHelper_Extend_PointToLine(tlist_o, ((CX3DImporter_NodeElement_Geometry2D*)ne)->Vertices);
|
||||
((CX3DImporter_NodeElement_Geometry2D*)ne)->NumIndices = 2;
|
||||
}
|
||||
else
|
||||
{// make disk
|
||||
std::list<aiVector3D>& vlist = ((CX3DImporter_NodeElement_Geometry2D*)ne)->Vertices;// just short alias.
|
||||
|
||||
GeometryHelper_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
|
||||
|
||||
((CX3DImporter_NodeElement_Geometry2D*)ne)->NumIndices = 4;
|
||||
}
|
||||
|
||||
((CX3DImporter_NodeElement_Geometry2D*)ne)->Solid = solid;
|
||||
// check for X3DMetadataObject childs.
|
||||
if(!mReader->isEmptyElement())
|
||||
ParseNode_Metadata(ne, "Disk2D");
|
||||
else
|
||||
NodeElement_Cur->Child.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::ParseNode_Geometry2D_Polyline2D()
|
||||
{
|
||||
std::string def, use;
|
||||
std::list<aiVector2D> lineSegments;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_REF("lineSegments", lineSegments, XML_ReadNode_GetAttrVal_AsListVec2f);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Polyline2D, ne);
|
||||
}
|
||||
else
|
||||
{
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new CX3DImporter_NodeElement_Geometry2D(CX3DImporter_NodeElement::ENET_Polyline2D, NodeElement_Cur);
|
||||
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
|
||||
GeometryHelper_Extend_PointToLine(tlist, ((CX3DImporter_NodeElement_Geometry2D*)ne)->Vertices);
|
||||
((CX3DImporter_NodeElement_Geometry2D*)ne)->NumIndices = 2;
|
||||
// check for X3DMetadataObject childs.
|
||||
if(!mReader->isEmptyElement())
|
||||
ParseNode_Metadata(ne, "Polyline2D");
|
||||
else
|
||||
NodeElement_Cur->Child.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::ParseNode_Geometry2D_Polypoint2D()
|
||||
{
|
||||
std::string def, use;
|
||||
std::list<aiVector2D> point;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_REF("point", point, XML_ReadNode_GetAttrVal_AsListVec2f);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Polypoint2D, ne);
|
||||
}
|
||||
else
|
||||
{
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new CX3DImporter_NodeElement_Geometry2D(CX3DImporter_NodeElement::ENET_Polypoint2D, NodeElement_Cur);
|
||||
if(!def.empty()) ne->ID = def;
|
||||
|
||||
// convert vec2 to vec3
|
||||
for(std::list<aiVector2D>::iterator it2 = point.begin(); it2 != point.end(); it2++)
|
||||
{
|
||||
((CX3DImporter_NodeElement_Geometry2D*)ne)->Vertices.push_back(aiVector3D(it2->x, it2->y, 0));
|
||||
}
|
||||
|
||||
((CX3DImporter_NodeElement_Geometry2D*)ne)->NumIndices = 1;
|
||||
// check for X3DMetadataObject childs.
|
||||
if(!mReader->isEmptyElement())
|
||||
ParseNode_Metadata(ne, "Polypoint2D");
|
||||
else
|
||||
NodeElement_Cur->Child.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::ParseNode_Geometry2D_Rectangle2D()
|
||||
{
|
||||
std::string def, use;
|
||||
aiVector2D size(2, 2);
|
||||
bool solid = false;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_REF("size", size, XML_ReadNode_GetAttrVal_AsVec2f);
|
||||
MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Rectangle2D, ne);
|
||||
}
|
||||
else
|
||||
{
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new CX3DImporter_NodeElement_Geometry2D(CX3DImporter_NodeElement::ENET_Rectangle2D, NodeElement_Cur);
|
||||
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 = ((CX3DImporter_NodeElement_Geometry2D*)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
|
||||
((CX3DImporter_NodeElement_Geometry2D*)ne)->Solid = solid;
|
||||
((CX3DImporter_NodeElement_Geometry2D*)ne)->NumIndices = 4;
|
||||
// check for X3DMetadataObject childs.
|
||||
if(!mReader->isEmptyElement())
|
||||
ParseNode_Metadata(ne, "Rectangle2D");
|
||||
else
|
||||
NodeElement_Cur->Child.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::ParseNode_Geometry2D_TriangleSet2D()
|
||||
{
|
||||
std::string def, use;
|
||||
bool solid = false;
|
||||
std::list<aiVector2D> vertices;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_REF("vertices", vertices, XML_ReadNode_GetAttrVal_AsListVec2f);
|
||||
MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(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 CX3DImporter_NodeElement_Geometry2D(CX3DImporter_NodeElement::ENET_TriangleSet2D, NodeElement_Cur);
|
||||
if(!def.empty()) ne->ID = def;
|
||||
|
||||
// convert vec2 to vec3
|
||||
for(std::list<aiVector2D>::iterator it2 = vertices.begin(); it2 != vertices.end(); it2++)
|
||||
{
|
||||
((CX3DImporter_NodeElement_Geometry2D*)ne)->Vertices.push_back(aiVector3D(it2->x, it2->y, 0));
|
||||
}
|
||||
|
||||
((CX3DImporter_NodeElement_Geometry2D*)ne)->Solid = solid;
|
||||
((CX3DImporter_NodeElement_Geometry2D*)ne)->NumIndices = 3;
|
||||
// check for X3DMetadataObject childs.
|
||||
if(!mReader->isEmptyElement())
|
||||
ParseNode_Metadata(ne, "TriangleSet2D");
|
||||
else
|
||||
NodeElement_Cur->Child.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,947 @@
|
|||
/// \file X3DImporter_Geometry3D.cpp
|
||||
/// \brief Parsing data from nodes of "Geometry3D" set of X3D.
|
||||
/// \date 2015-2016
|
||||
/// \author nevorek@gmail.com
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
|
||||
#include "X3DImporter.hpp"
|
||||
#include "X3DImporter_Macro.hpp"
|
||||
#include "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::ParseNode_Geometry3D_Box()
|
||||
{
|
||||
std::string def, use;
|
||||
bool solid = true;
|
||||
aiVector3D size(2, 2, 2);
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_REF("size", size, XML_ReadNode_GetAttrVal_AsVec3f);
|
||||
MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Box, ne);
|
||||
}
|
||||
else
|
||||
{
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new CX3DImporter_NodeElement_Geometry3D(CX3DImporter_NodeElement::ENET_Box, NodeElement_Cur);
|
||||
if(!def.empty()) ne->ID = def;
|
||||
|
||||
GeometryHelper_MakeQL_RectParallelepiped(size, ((CX3DImporter_NodeElement_Geometry3D*)ne)->Vertices);// get quad list
|
||||
((CX3DImporter_NodeElement_Geometry3D*)ne)->Solid = solid;
|
||||
((CX3DImporter_NodeElement_Geometry3D*)ne)->NumIndices = 4;
|
||||
// check for X3DMetadataObject childs.
|
||||
if(!mReader->isEmptyElement())
|
||||
ParseNode_Metadata(ne, "Box");
|
||||
else
|
||||
NodeElement_Cur->Child.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::ParseNode_Geometry3D_Cone()
|
||||
{
|
||||
std::string use, def;
|
||||
bool bottom = true;
|
||||
float bottomRadius = 1;
|
||||
float height = 2;
|
||||
bool side = true;
|
||||
bool solid = true;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("side", side, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("bottom", bottom, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("height", height, XML_ReadNode_GetAttrVal_AsFloat);
|
||||
MACRO_ATTRREAD_CHECK_RET("bottomRadius", bottomRadius, XML_ReadNode_GetAttrVal_AsFloat);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Cone, ne);
|
||||
}
|
||||
else
|
||||
{
|
||||
const unsigned int tess = 30;///TODO: IME tesselation factor thru ai_property
|
||||
std::vector<aiVector3D> tvec;// temp array for vertices.
|
||||
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new CX3DImporter_NodeElement_Geometry3D(CX3DImporter_NodeElement::ENET_Cone, NodeElement_Cur);
|
||||
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++) ((CX3DImporter_NodeElement_Geometry3D*)ne)->Vertices.push_back(*it);
|
||||
|
||||
((CX3DImporter_NodeElement_Geometry3D*)ne)->Solid = solid;
|
||||
((CX3DImporter_NodeElement_Geometry3D*)ne)->NumIndices = 3;
|
||||
// check for X3DMetadataObject childs.
|
||||
if(!mReader->isEmptyElement())
|
||||
ParseNode_Metadata(ne, "Cone");
|
||||
else
|
||||
NodeElement_Cur->Child.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::ParseNode_Geometry3D_Cylinder()
|
||||
{
|
||||
std::string use, def;
|
||||
bool bottom = true;
|
||||
float height = 2;
|
||||
float radius = 1;
|
||||
bool side = true;
|
||||
bool solid = true;
|
||||
bool top = true;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_RET("radius", radius, XML_ReadNode_GetAttrVal_AsFloat);
|
||||
MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("bottom", bottom, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("top", top, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("side", side, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("height", height, XML_ReadNode_GetAttrVal_AsFloat);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Cylinder, ne);
|
||||
}
|
||||
else
|
||||
{
|
||||
const unsigned int tess = 30;///TODO: IME tesselation factor thru 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 CX3DImporter_NodeElement_Geometry3D(CX3DImporter_NodeElement::ENET_Cylinder, NodeElement_Cur);
|
||||
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 = ((CX3DImporter_NodeElement_Geometry3D*)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)
|
||||
|
||||
((CX3DImporter_NodeElement_Geometry3D*)ne)->Solid = solid;
|
||||
((CX3DImporter_NodeElement_Geometry3D*)ne)->NumIndices = 3;
|
||||
// check for X3DMetadataObject childs.
|
||||
if(!mReader->isEmptyElement())
|
||||
ParseNode_Metadata(ne, "Cylinder");
|
||||
else
|
||||
NodeElement_Cur->Child.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::ParseNode_Geometry3D_ElevationGrid()
|
||||
{
|
||||
std::string use, def;
|
||||
bool ccw = true;
|
||||
bool colorPerVertex = true;
|
||||
float creaseAngle = 0;
|
||||
std::list<float> height;
|
||||
bool normalPerVertex = true;
|
||||
bool solid = true;
|
||||
int32_t xDimension = 0;
|
||||
float xSpacing = 1;
|
||||
int32_t zDimension = 0;
|
||||
float zSpacing = 1;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("creaseAngle", creaseAngle, XML_ReadNode_GetAttrVal_AsFloat);
|
||||
MACRO_ATTRREAD_CHECK_REF("height", height, XML_ReadNode_GetAttrVal_AsListF);
|
||||
MACRO_ATTRREAD_CHECK_RET("xDimension", xDimension, XML_ReadNode_GetAttrVal_AsI32);
|
||||
MACRO_ATTRREAD_CHECK_RET("xSpacing", xSpacing, XML_ReadNode_GetAttrVal_AsFloat);
|
||||
MACRO_ATTRREAD_CHECK_RET("zDimension", zDimension, XML_ReadNode_GetAttrVal_AsI32);
|
||||
MACRO_ATTRREAD_CHECK_RET("zSpacing", zSpacing, XML_ReadNode_GetAttrVal_AsFloat);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(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()) Throw_IncorrectAttrValue("Heights count must be equal to \"xDimension * zDimension\"");
|
||||
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new CX3DImporter_NodeElement_ElevationGrid(CX3DImporter_NodeElement::ENET_ElevationGrid, NodeElement_Cur);
|
||||
if(!def.empty()) ne->ID = def;
|
||||
|
||||
CX3DImporter_NodeElement_ElevationGrid& grid_alias = *((CX3DImporter_NodeElement_ElevationGrid*)ne);// create alias for conveience
|
||||
|
||||
{// create grid vertices list
|
||||
std::list<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.
|
||||
{
|
||||
((CX3DImporter_NodeElement_ElevationGrid*)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(i);
|
||||
grid_alias.CoordIdx.push_back(i + 1);
|
||||
grid_alias.CoordIdx.push_back(-1);
|
||||
}
|
||||
}
|
||||
else// two or more elements in every dimension is set. create quad set.
|
||||
{
|
||||
((CX3DImporter_NodeElement_ElevationGrid*)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(!mReader->isEmptyElement())
|
||||
{
|
||||
ParseHelper_Node_Enter(ne);
|
||||
MACRO_NODECHECK_LOOPBEGIN("ElevationGrid");
|
||||
// check for X3DComposedGeometryNodes
|
||||
if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
|
||||
if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
|
||||
if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
|
||||
if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
|
||||
// check for X3DMetadataObject
|
||||
if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("ElevationGrid");
|
||||
|
||||
MACRO_NODECHECK_LOOPEND("ElevationGrid");
|
||||
ParseHelper_Node_Exit();
|
||||
}// if(!mReader->isEmptyElement())
|
||||
else
|
||||
{
|
||||
NodeElement_Cur->Child.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 droping 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 thru 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::ParseNode_Geometry3D_Extrusion()
|
||||
{
|
||||
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;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_RET("beginCap", beginCap, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("convex", convex, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("creaseAngle", creaseAngle, XML_ReadNode_GetAttrVal_AsFloat);
|
||||
MACRO_ATTRREAD_CHECK_REF("crossSection", crossSection, XML_ReadNode_GetAttrVal_AsArrVec2f);
|
||||
MACRO_ATTRREAD_CHECK_RET("endCap", endCap, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_REF("orientation", orientation, XML_ReadNode_GetAttrVal_AsArrF);
|
||||
MACRO_ATTRREAD_CHECK_REF("scale", scale, XML_ReadNode_GetAttrVal_AsArrVec2f);
|
||||
MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_REF("spine", spine, XML_ReadNode_GetAttrVal_AsArrVec3f);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(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 CX3DImporter_NodeElement_IndexedSet(CX3DImporter_NodeElement::ENET_Extrusion, NodeElement_Cur);
|
||||
if(!def.empty()) ne->ID = def;
|
||||
|
||||
CX3DImporter_NodeElement_IndexedSet& ext_alias = *((CX3DImporter_NodeElement_IndexedSet*)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, transfered 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 transfered 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(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(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,
|
||||
spi * cr_sz + cri, right_col * cr_sz + cri, right_col * cr_sz + cri + 1, 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,
|
||||
spi * cr_sz + cri, right_col * cr_sz + cri, right_col * cr_sz + 0, 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(!mReader->isEmptyElement())
|
||||
ParseNode_Metadata(ne, "Extrusion");
|
||||
else
|
||||
NodeElement_Cur->Child.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::ParseNode_Geometry3D_IndexedFaceSet()
|
||||
{
|
||||
std::string use, def;
|
||||
bool ccw = true;
|
||||
std::list<int32_t> colorIndex;
|
||||
bool colorPerVertex = true;
|
||||
bool convex = true;
|
||||
std::list<int32_t> coordIndex;
|
||||
float creaseAngle = 0;
|
||||
std::list<int32_t> normalIndex;
|
||||
bool normalPerVertex = true;
|
||||
bool solid = true;
|
||||
std::list<int32_t> texCoordIndex;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_REF("colorIndex", colorIndex, XML_ReadNode_GetAttrVal_AsListI32);
|
||||
MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("convex", convex, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_REF("coordIndex", coordIndex, XML_ReadNode_GetAttrVal_AsListI32);
|
||||
MACRO_ATTRREAD_CHECK_RET("creaseAngle", creaseAngle, XML_ReadNode_GetAttrVal_AsFloat);
|
||||
MACRO_ATTRREAD_CHECK_REF("normalIndex", normalIndex, XML_ReadNode_GetAttrVal_AsListI32);
|
||||
MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_REF("texCoordIndex", texCoordIndex, XML_ReadNode_GetAttrVal_AsListI32);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(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 CX3DImporter_NodeElement_IndexedSet(CX3DImporter_NodeElement::ENET_IndexedFaceSet, NodeElement_Cur);
|
||||
if(!def.empty()) ne->ID = def;
|
||||
|
||||
CX3DImporter_NodeElement_IndexedSet& ne_alias = *((CX3DImporter_NodeElement_IndexedSet*)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(!mReader->isEmptyElement())
|
||||
{
|
||||
ParseHelper_Node_Enter(ne);
|
||||
MACRO_NODECHECK_LOOPBEGIN("IndexedFaceSet");
|
||||
// check for X3DComposedGeometryNodes
|
||||
if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
|
||||
if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
|
||||
if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
|
||||
if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
|
||||
if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
|
||||
// check for X3DMetadataObject
|
||||
if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("IndexedFaceSet");
|
||||
|
||||
MACRO_NODECHECK_LOOPEND("IndexedFaceSet");
|
||||
ParseHelper_Node_Exit();
|
||||
}// if(!mReader->isEmptyElement())
|
||||
else
|
||||
{
|
||||
NodeElement_Cur->Child.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::ParseNode_Geometry3D_Sphere()
|
||||
{
|
||||
std::string use, def;
|
||||
float radius = 1;
|
||||
bool solid = true;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_RET("radius", radius, XML_ReadNode_GetAttrVal_AsFloat);
|
||||
MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Sphere, ne);
|
||||
}
|
||||
else
|
||||
{
|
||||
const unsigned int tess = 3;///TODO: IME tesselation factor thru ai_property
|
||||
std::vector<aiVector3D> tlist;
|
||||
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new CX3DImporter_NodeElement_Geometry3D(CX3DImporter_NodeElement::ENET_Sphere, NodeElement_Cur);
|
||||
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++)
|
||||
{
|
||||
((CX3DImporter_NodeElement_Geometry3D*)ne)->Vertices.push_back(*it * radius);
|
||||
}
|
||||
|
||||
((CX3DImporter_NodeElement_Geometry3D*)ne)->Solid = solid;
|
||||
((CX3DImporter_NodeElement_Geometry3D*)ne)->NumIndices = 3;
|
||||
// check for X3DMetadataObject childs.
|
||||
if(!mReader->isEmptyElement())
|
||||
ParseNode_Metadata(ne, "Sphere");
|
||||
else
|
||||
NodeElement_Cur->Child.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,269 @@
|
|||
/// \file X3DImporter_Group.cpp
|
||||
/// \brief Parsing data from nodes of "Grouping" set of X3D.
|
||||
/// \date 2015-2016
|
||||
/// \author nevorek@gmail.com
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
|
||||
#include "X3DImporter.hpp"
|
||||
#include "X3DImporter_Macro.hpp"
|
||||
|
||||
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::ParseNode_Grouping_Group()
|
||||
{
|
||||
std::string def, use;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_USE_CHECKANDAPPLY(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()) NodeElement_Cur->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(mReader->isEmptyElement()) ParseHelper_Node_Exit();
|
||||
}// if(!use.empty()) else
|
||||
}
|
||||
|
||||
void X3DImporter::ParseNode_Grouping_GroupEnd()
|
||||
{
|
||||
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::ParseNode_Grouping_StaticGroup()
|
||||
{
|
||||
std::string def, use;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_USE_CHECKANDAPPLY(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()) NodeElement_Cur->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(mReader->isEmptyElement()) ParseHelper_Node_Exit();
|
||||
}// if(!use.empty()) else
|
||||
}
|
||||
|
||||
void X3DImporter::ParseNode_Grouping_StaticGroupEnd()
|
||||
{
|
||||
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::ParseNode_Grouping_Switch()
|
||||
{
|
||||
std::string def, use;
|
||||
int32_t whichChoice = -1;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_RET("whichChoice", whichChoice, XML_ReadNode_GetAttrVal_AsI32);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_USE_CHECKANDAPPLY(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()) NodeElement_Cur->ID = def;
|
||||
|
||||
// also set values specific to this type of group
|
||||
((CX3DImporter_NodeElement_Group*)NodeElement_Cur)->UseChoice = true;
|
||||
((CX3DImporter_NodeElement_Group*)NodeElement_Cur)->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(mReader->isEmptyElement()) ParseHelper_Node_Exit();
|
||||
}// if(!use.empty()) else
|
||||
}
|
||||
|
||||
void X3DImporter::ParseNode_Grouping_SwitchEnd()
|
||||
{
|
||||
// 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::ParseNode_Grouping_Transform()
|
||||
{
|
||||
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_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_REF("center", center, XML_ReadNode_GetAttrVal_AsVec3f);
|
||||
MACRO_ATTRREAD_CHECK_REF("scale", scale, XML_ReadNode_GetAttrVal_AsVec3f);
|
||||
MACRO_ATTRREAD_CHECK_REF("translation", translation, XML_ReadNode_GetAttrVal_AsVec3f);
|
||||
if(an == "rotation")
|
||||
{
|
||||
std::vector<float> tvec;
|
||||
|
||||
XML_ReadNode_GetAttrVal_AsArrF(idx, tvec);
|
||||
if(tvec.size() != 4) throw DeadlyImportError("<Transform>: rotation vector must have 4 elements.");
|
||||
|
||||
memcpy(rotation, tvec.data(), sizeof(rotation));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if(an == "scaleOrientation")
|
||||
{
|
||||
std::vector<float> tvec;
|
||||
|
||||
XML_ReadNode_GetAttrVal_AsArrF(idx, tvec);
|
||||
if(tvec.size() != 4) throw DeadlyImportError("<Transform>: scaleOrientation vector must have 4 elements.");
|
||||
|
||||
memcpy(scale_orientation, tvec.data(), sizeof(scale_orientation));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_USE_CHECKANDAPPLY(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()) NodeElement_Cur->ID = def;
|
||||
|
||||
//
|
||||
// also set values specific to this type of group
|
||||
//
|
||||
// calculate tranformation 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
|
||||
((CX3DImporter_NodeElement_Group*)NodeElement_Cur)->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(mReader->isEmptyElement()) ParseHelper_Node_Exit();
|
||||
}// if(!use.empty()) else
|
||||
}
|
||||
|
||||
void X3DImporter::ParseNode_Grouping_TransformEnd()
|
||||
{
|
||||
ParseHelper_Node_Exit();// go up in scene graph
|
||||
}
|
||||
|
||||
}// namespace Assimp
|
||||
|
||||
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
@ -0,0 +1,251 @@
|
|||
/// \file X3DImporter_Light.cpp
|
||||
/// \brief Parsing data from nodes of "Lighting" set of X3D.
|
||||
/// \date 2015-2016
|
||||
/// \author nevorek@gmail.com
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
|
||||
#include "X3DImporter.hpp"
|
||||
#include "X3DImporter_Macro.hpp"
|
||||
|
||||
#include <boost/format.hpp>
|
||||
|
||||
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::ParseNode_Lighting_DirectionalLight()
|
||||
{
|
||||
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;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_RET("ambientIntensity", ambientIntensity, XML_ReadNode_GetAttrVal_AsFloat);
|
||||
MACRO_ATTRREAD_CHECK_REF("color", color, XML_ReadNode_GetAttrVal_AsCol3f);
|
||||
MACRO_ATTRREAD_CHECK_REF("direction", direction, XML_ReadNode_GetAttrVal_AsVec3f);
|
||||
MACRO_ATTRREAD_CHECK_RET("global", global, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("intensity", intensity, XML_ReadNode_GetAttrVal_AsFloat);
|
||||
MACRO_ATTRREAD_CHECK_RET("on", on, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_DirectionalLight, ne);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(on)
|
||||
{
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new CX3DImporter_NodeElement_Light(CX3DImporter_NodeElement::ENET_DirectionalLight, NodeElement_Cur);
|
||||
if(!def.empty())
|
||||
ne->ID = def;
|
||||
else
|
||||
ne->ID = boost::str(boost::format("DirectionalLight_%s") % (size_t)ne);// make random name
|
||||
|
||||
((CX3DImporter_NodeElement_Light*)ne)->AmbientIntensity = ambientIntensity;
|
||||
((CX3DImporter_NodeElement_Light*)ne)->Color = color;
|
||||
((CX3DImporter_NodeElement_Light*)ne)->Direction = direction;
|
||||
((CX3DImporter_NodeElement_Light*)ne)->Global = global;
|
||||
((CX3DImporter_NodeElement_Light*)ne)->Intensity = intensity;
|
||||
// Assimp want a node with name similar to a light. "Why? I don't no." )
|
||||
ParseHelper_Group_Begin(false);
|
||||
|
||||
NodeElement_Cur->ID = ne->ID;// assign name to node and return to light element.
|
||||
ParseHelper_Node_Exit();
|
||||
// check for child nodes
|
||||
if(!mReader->isEmptyElement())
|
||||
ParseNode_Metadata(ne, "DirectionalLight");
|
||||
else
|
||||
NodeElement_Cur->Child.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::ParseNode_Lighting_PointLight()
|
||||
{
|
||||
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;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_RET("ambientIntensity", ambientIntensity, XML_ReadNode_GetAttrVal_AsFloat);
|
||||
MACRO_ATTRREAD_CHECK_REF("attenuation", attenuation, XML_ReadNode_GetAttrVal_AsVec3f);
|
||||
MACRO_ATTRREAD_CHECK_REF("color", color, XML_ReadNode_GetAttrVal_AsCol3f);
|
||||
MACRO_ATTRREAD_CHECK_RET("global", global, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("intensity", intensity, XML_ReadNode_GetAttrVal_AsFloat);
|
||||
MACRO_ATTRREAD_CHECK_REF("location", location, XML_ReadNode_GetAttrVal_AsVec3f);
|
||||
MACRO_ATTRREAD_CHECK_RET("on", on, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("radius", radius, XML_ReadNode_GetAttrVal_AsFloat);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_PointLight, ne);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(on)
|
||||
{
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new CX3DImporter_NodeElement_Light(CX3DImporter_NodeElement::ENET_PointLight, NodeElement_Cur);
|
||||
if(!def.empty()) ne->ID = def;
|
||||
|
||||
((CX3DImporter_NodeElement_Light*)ne)->AmbientIntensity = ambientIntensity;
|
||||
((CX3DImporter_NodeElement_Light*)ne)->Attenuation = attenuation;
|
||||
((CX3DImporter_NodeElement_Light*)ne)->Color = color;
|
||||
((CX3DImporter_NodeElement_Light*)ne)->Global = global;
|
||||
((CX3DImporter_NodeElement_Light*)ne)->Intensity = intensity;
|
||||
((CX3DImporter_NodeElement_Light*)ne)->Location = location;
|
||||
((CX3DImporter_NodeElement_Light*)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 = boost::str(boost::format("PointLight_%s") % (size_t)ne);
|
||||
|
||||
NodeElement_Cur->ID = ne->ID;// assign name to node and return to light element.
|
||||
ParseHelper_Node_Exit();
|
||||
// check for child nodes
|
||||
if(!mReader->isEmptyElement())
|
||||
ParseNode_Metadata(ne, "PointLight");
|
||||
else
|
||||
NodeElement_Cur->Child.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::ParseNode_Lighting_SpotLight()
|
||||
{
|
||||
std::string def, use;
|
||||
float ambientIntensity = 0;
|
||||
aiVector3D attenuation(1, 0, 0);
|
||||
float beamWidth = 0.7854;
|
||||
aiColor3D color(1, 1, 1);
|
||||
float cutOffAngle = 1.570796;
|
||||
aiVector3D direction(0, 0, -1);
|
||||
bool global = true;
|
||||
float intensity = 1;
|
||||
aiVector3D location(0, 0, 0);
|
||||
bool on = true;
|
||||
float radius = 100;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_RET("ambientIntensity", ambientIntensity, XML_ReadNode_GetAttrVal_AsFloat);
|
||||
MACRO_ATTRREAD_CHECK_REF("attenuation", attenuation, XML_ReadNode_GetAttrVal_AsVec3f);
|
||||
MACRO_ATTRREAD_CHECK_RET("beamWidth", beamWidth, XML_ReadNode_GetAttrVal_AsFloat);
|
||||
MACRO_ATTRREAD_CHECK_REF("color", color, XML_ReadNode_GetAttrVal_AsCol3f);
|
||||
MACRO_ATTRREAD_CHECK_RET("cutOffAngle", cutOffAngle, XML_ReadNode_GetAttrVal_AsFloat);
|
||||
MACRO_ATTRREAD_CHECK_REF("direction", direction, XML_ReadNode_GetAttrVal_AsVec3f);
|
||||
MACRO_ATTRREAD_CHECK_RET("global", global, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("intensity", intensity, XML_ReadNode_GetAttrVal_AsFloat);
|
||||
MACRO_ATTRREAD_CHECK_REF("location", location, XML_ReadNode_GetAttrVal_AsVec3f);
|
||||
MACRO_ATTRREAD_CHECK_RET("on", on, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("radius", radius, XML_ReadNode_GetAttrVal_AsFloat);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_SpotLight, ne);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(on)
|
||||
{
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new CX3DImporter_NodeElement_Light(CX3DImporter_NodeElement::ENET_SpotLight, NodeElement_Cur);
|
||||
if(!def.empty()) ne->ID = def;
|
||||
|
||||
if(beamWidth > cutOffAngle) beamWidth = cutOffAngle;
|
||||
|
||||
((CX3DImporter_NodeElement_Light*)ne)->AmbientIntensity = ambientIntensity;
|
||||
((CX3DImporter_NodeElement_Light*)ne)->Attenuation = attenuation;
|
||||
((CX3DImporter_NodeElement_Light*)ne)->BeamWidth = beamWidth;
|
||||
((CX3DImporter_NodeElement_Light*)ne)->Color = color;
|
||||
((CX3DImporter_NodeElement_Light*)ne)->CutOffAngle = cutOffAngle;
|
||||
((CX3DImporter_NodeElement_Light*)ne)->Direction = direction;
|
||||
((CX3DImporter_NodeElement_Light*)ne)->Global = global;
|
||||
((CX3DImporter_NodeElement_Light*)ne)->Intensity = intensity;
|
||||
((CX3DImporter_NodeElement_Light*)ne)->Location = location;
|
||||
((CX3DImporter_NodeElement_Light*)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 = boost::str(boost::format("SpotLight_%s") % (size_t)ne);
|
||||
|
||||
NodeElement_Cur->ID = ne->ID;// assign name to node and return to light element.
|
||||
ParseHelper_Node_Exit();
|
||||
// check for child nodes
|
||||
if(!mReader->isEmptyElement())
|
||||
ParseNode_Metadata(ne, "SpotLight");
|
||||
else
|
||||
NodeElement_Cur->Child.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,154 @@
|
|||
/// \file X3DImporter_Macro.hpp
|
||||
/// \brief Useful macrodefines.
|
||||
/// \date 2015-2016
|
||||
/// \author nevorek@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] 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(pDEF, pUSE, pType, pNE) \
|
||||
do { \
|
||||
XML_CheckNode_MustBeEmpty(); \
|
||||
if(!pDEF.empty()) Throw_DEF_And_USE(); \
|
||||
if(!FindNodeElement(pUSE, CX3DImporter_NodeElement::pType, &pNE)) Throw_USE_NotFound(pUSE); \
|
||||
\
|
||||
NodeElement_Cur->Child.push_back(pNE);/* add found object as child to current element */ \
|
||||
} while(false)
|
||||
|
||||
/// \def MACRO_ATTRREAD_LOOPBEG
|
||||
/// Begin of loop that read attributes values.
|
||||
#define MACRO_ATTRREAD_LOOPBEG \
|
||||
for(int idx = 0, idx_end = mReader->getAttributeCount(); idx < idx_end; idx++) \
|
||||
{ \
|
||||
std::string an(mReader->getAttributeName(idx));
|
||||
|
||||
/// \def MACRO_ATTRREAD_LOOPEND
|
||||
/// End of loop that read attributes values.
|
||||
#define MACRO_ATTRREAD_LOOPEND \
|
||||
Throw_IncorrectAttr(an); \
|
||||
}
|
||||
|
||||
/// \def MACRO_ATTRREAD_CHECK_REF
|
||||
/// Check curent attribute name and if it equal to requested then read value. Result write to output variable by reference. If result was read then
|
||||
/// "continue" will called.
|
||||
/// \param [in] pAttrName - attribute name.
|
||||
/// \param [out] pVarName - output variable name.
|
||||
/// \param [in] pFunction - function which read attribute value and write it to pVarName.
|
||||
#define MACRO_ATTRREAD_CHECK_REF(pAttrName, pVarName, pFunction) \
|
||||
if(an == pAttrName) \
|
||||
{ \
|
||||
pFunction(idx, pVarName); \
|
||||
continue; \
|
||||
}
|
||||
|
||||
/// \def MACRO_ATTRREAD_CHECK_RET
|
||||
/// Check curent attribute name and if it equal to requested then read value. Result write to output variable using return value of \ref pFunction.
|
||||
/// If result was read then "continue" will called.
|
||||
/// \param [in] pAttrName - attribute name.
|
||||
/// \param [out] pVarName - output variable name.
|
||||
/// \param [in] pFunction - function which read attribute value and write it to pVarName.
|
||||
#define MACRO_ATTRREAD_CHECK_RET(pAttrName, pVarName, pFunction) \
|
||||
if(an == pAttrName) \
|
||||
{ \
|
||||
pVarName = pFunction(idx); \
|
||||
continue; \
|
||||
}
|
||||
|
||||
/// \def MACRO_ATTRREAD_CHECKUSEDEF_RET
|
||||
/// Compact variant for checking "USE" and "DEF". Also skip bbox attributes: "bboxCenter", "bboxSize".
|
||||
/// If result was read then "continue" will called.
|
||||
/// \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(pDEF_Var, pUSE_Var) \
|
||||
MACRO_ATTRREAD_CHECK_RET("DEF", pDEF_Var, mReader->getAttributeValue); \
|
||||
MACRO_ATTRREAD_CHECK_RET("USE", pUSE_Var, mReader->getAttributeValue); \
|
||||
if(an == "bboxCenter") continue; \
|
||||
if(an == "bboxSize") continue; \
|
||||
if(an == "containerField") continue; \
|
||||
do {} while(false)
|
||||
|
||||
/// \def MACRO_NODECHECK_LOOPBEGIN(pNodeName)
|
||||
/// Begin of loop of parsing child nodes. Do not add ';' at end.
|
||||
/// \param [in] pNodeName - current node name.
|
||||
#define MACRO_NODECHECK_LOOPBEGIN(pNodeName) \
|
||||
do { \
|
||||
bool close_found = false; \
|
||||
\
|
||||
while(mReader->read()) \
|
||||
{ \
|
||||
if(mReader->getNodeType() == irr::io::EXN_ELEMENT) \
|
||||
{
|
||||
|
||||
/// \def MACRO_NODECHECK_LOOPEND(pNodeName)
|
||||
/// End of loop of parsing child nodes.
|
||||
/// \param [in] pNodeName - current node name.
|
||||
#define MACRO_NODECHECK_LOOPEND(pNodeName) \
|
||||
}/* if(mReader->getNodeType() == irr::io::EXN_ELEMENT) */ \
|
||||
else if(mReader->getNodeType() == irr::io::EXN_ELEMENT_END) \
|
||||
{ \
|
||||
if(XML_CheckNode_NameEqual(pNodeName)) \
|
||||
{ \
|
||||
close_found = true; \
|
||||
\
|
||||
break; \
|
||||
} \
|
||||
}/* else if(mReader->getNodeType() == irr::io::EXN_ELEMENT_END) */ \
|
||||
}/* while(mReader->read()) */ \
|
||||
\
|
||||
if(!close_found) Throw_CloseNotFound(pNodeName); \
|
||||
\
|
||||
} while(false)
|
||||
|
||||
#define MACRO_NODECHECK_METADATA(pNodeName) \
|
||||
MACRO_NODECHECK_LOOPBEGIN(pNodeName) \
|
||||
/* and childs must be metadata nodes */ \
|
||||
if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported(pNodeName); \
|
||||
MACRO_NODECHECK_LOOPEND(pNodeName)
|
||||
|
||||
/// \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,236 @@
|
|||
/// \file X3DImporter_Metadata.cpp
|
||||
/// \brief Parsing data from nodes of "Metadata" set of X3D.
|
||||
/// \date 2015-2016
|
||||
/// \author nevorek@gmail.com
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
|
||||
#include "X3DImporter.hpp"
|
||||
#include "X3DImporter_Macro.hpp"
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
|
||||
/// \def MACRO_METADATA_FINDCREATE(pDEF_Var, pUSE_Var, pReference, pValue, pNE, pMetaName)
|
||||
/// Find element by "USE" or create new one.
|
||||
/// \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(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(pDEF_Var, pUSE_Var, pType, pNE); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
pNE = new pMetaClass(NodeElement_Cur); \
|
||||
if(!pDEF_Var.empty()) pNE->ID = pDEF_Var; \
|
||||
\
|
||||
((pMetaClass*)pNE)->Reference = pReference; \
|
||||
((pMetaClass*)pNE)->Value = pValue; \
|
||||
/* also metadata node can contain childs */ \
|
||||
if(!mReader->isEmptyElement()) \
|
||||
ParseNode_Metadata(pNE, pMetaName);/* in that case node element will be added to child elements list of current node. */ \
|
||||
else \
|
||||
NodeElement_Cur->Child.push_back(pNE);/* else - add element to child list manualy */ \
|
||||
\
|
||||
NodeElement_List.push_back(pNE);/* add new element to elements list. */ \
|
||||
}/* if(!pUSE_Var.empty()) else */ \
|
||||
\
|
||||
do {} while(false)
|
||||
|
||||
bool X3DImporter::ParseHelper_CheckRead_X3DMetadataObject()
|
||||
{
|
||||
if(XML_CheckNode_NameEqual("MetadataBoolean"))
|
||||
ParseNode_MetadataBoolean();
|
||||
else if(XML_CheckNode_NameEqual("MetadataDouble"))
|
||||
ParseNode_MetadataDouble();
|
||||
else if(XML_CheckNode_NameEqual("MetadataFloat"))
|
||||
ParseNode_MetadataFloat();
|
||||
else if(XML_CheckNode_NameEqual("MetadataInteger"))
|
||||
ParseNode_MetadataInteger();
|
||||
else if(XML_CheckNode_NameEqual("MetadataSet"))
|
||||
ParseNode_MetadataSet();
|
||||
else if(XML_CheckNode_NameEqual("MetadataString"))
|
||||
ParseNode_MetadataString();
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void X3DImporter::ParseNode_Metadata(CX3DImporter_NodeElement* pParentElement, const std::string& pNodeName)
|
||||
{
|
||||
ParseHelper_Node_Enter(pParentElement);
|
||||
MACRO_NODECHECK_METADATA(mReader->getNodeName());
|
||||
ParseHelper_Node_Exit();
|
||||
}
|
||||
|
||||
// <MetadataBoolean
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// name="" SFString [inputOutput]
|
||||
// reference="" SFString [inputOutput]
|
||||
// value="" MFBool [inputOutput]
|
||||
// />
|
||||
void X3DImporter::ParseNode_MetadataBoolean()
|
||||
{
|
||||
std::string def, use;
|
||||
std::string name, reference;
|
||||
std::list<bool> value;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue);
|
||||
MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue);
|
||||
MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsListB);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
MACRO_METADATA_FINDCREATE(def, use, reference, value, ne, CX3DImporter_NodeElement_MetaBoolean, "MetadataBoolean", ENET_MetaBoolean);
|
||||
}
|
||||
|
||||
// <MetadataDouble
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// name="" SFString [inputOutput]
|
||||
// reference="" SFString [inputOutput]
|
||||
// value="" MFDouble [inputOutput]
|
||||
// />
|
||||
void X3DImporter::ParseNode_MetadataDouble()
|
||||
{
|
||||
std::string def, use;
|
||||
std::string name, reference;
|
||||
std::list<double> value;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue);
|
||||
MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue);
|
||||
MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsListD);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
MACRO_METADATA_FINDCREATE(def, use, reference, value, ne, CX3DImporter_NodeElement_MetaDouble, "MetadataDouble", ENET_MetaDouble);
|
||||
}
|
||||
|
||||
// <MetadataFloat
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// name="" SFString [inputOutput]
|
||||
// reference="" SFString [inputOutput]
|
||||
// value="" MFFloat [inputOutput]
|
||||
// />
|
||||
void X3DImporter::ParseNode_MetadataFloat()
|
||||
{
|
||||
std::string def, use;
|
||||
std::string name, reference;
|
||||
std::list<float> value;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue);
|
||||
MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue);
|
||||
MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsListF);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
MACRO_METADATA_FINDCREATE(def, use, reference, value, ne, CX3DImporter_NodeElement_MetaFloat, "MetadataFloat", ENET_MetaFloat);
|
||||
}
|
||||
|
||||
// <MetadataInteger
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// name="" SFString [inputOutput]
|
||||
// reference="" SFString [inputOutput]
|
||||
// value="" MFInteger [inputOutput]
|
||||
// />
|
||||
void X3DImporter::ParseNode_MetadataInteger()
|
||||
{
|
||||
std::string def, use;
|
||||
std::string name, reference;
|
||||
std::list<int32_t> value;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue);
|
||||
MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue);
|
||||
MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsListI32);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
MACRO_METADATA_FINDCREATE(def, use, reference, value, ne, CX3DImporter_NodeElement_MetaInteger, "MetadataInteger", ENET_MetaInteger);
|
||||
}
|
||||
|
||||
// <MetadataSet
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// name="" SFString [inputOutput]
|
||||
// reference="" SFString [inputOutput]
|
||||
// />
|
||||
void X3DImporter::ParseNode_MetadataSet()
|
||||
{
|
||||
std::string def, use;
|
||||
std::string name, reference;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue);
|
||||
MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_MetaSet, ne);
|
||||
}
|
||||
else
|
||||
{
|
||||
ne = new CX3DImporter_NodeElement_MetaSet(NodeElement_Cur);
|
||||
if(!def.empty()) ne->ID = def;
|
||||
|
||||
((CX3DImporter_NodeElement_MetaSet*)ne)->Reference = reference;
|
||||
// also metadata node can contain childs
|
||||
if(!mReader->isEmptyElement())
|
||||
ParseNode_Metadata(ne, "MetadataSet");
|
||||
else
|
||||
NodeElement_Cur->Child.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::ParseNode_MetadataString()
|
||||
{
|
||||
std::string def, use;
|
||||
std::string name, reference;
|
||||
std::list<std::string> value;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue);
|
||||
MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue);
|
||||
MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsListS);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
MACRO_METADATA_FINDCREATE(def, use, reference, value, ne, CX3DImporter_NodeElement_MetaString, "MetadataString", ENET_MetaString);
|
||||
}
|
||||
|
||||
}// namespace Assimp
|
||||
|
||||
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
@ -0,0 +1,69 @@
|
|||
/// \file X3DImporter_Rendering.cpp
|
||||
/// \brief Parsing data from nodes of "Networking" set of X3D.
|
||||
/// \date 2015-2016
|
||||
/// \author nevorek@gmail.com
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
|
||||
#include "X3DImporter.hpp"
|
||||
#include "X3DImporter_Macro.hpp"
|
||||
|
||||
#include "DefaultIOSystem.h"
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
|
||||
// <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::ParseNode_Networking_Inline()
|
||||
{
|
||||
std::string def, use;
|
||||
bool load = true;
|
||||
std::list<std::string> url;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_RET("load", load, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_REF("url", url, XML_ReadNode_GetAttrVal_AsListS);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_USE_CHECKANDAPPLY(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()) NodeElement_Cur->ID = def;
|
||||
|
||||
if(load && (url.size() > 0))
|
||||
{
|
||||
DefaultIOSystem io_handler;
|
||||
std::string full_path;
|
||||
|
||||
full_path = mFileDir + "/" + url.front();
|
||||
// Attribute "url" can contain list of strings. But we need only one - first.
|
||||
ParseFile(full_path, &io_handler);
|
||||
}
|
||||
|
||||
// check for X3DMetadataObject childs.
|
||||
if(!mReader->isEmptyElement()) ParseNode_Metadata(NodeElement_Cur, "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,761 @@
|
|||
/// \file X3DImporter_Node.hpp
|
||||
/// \brief Elements of scene graph.
|
||||
/// \date 2015-2016
|
||||
/// \author nevorek@gmail.com
|
||||
|
||||
#ifndef INCLUDED_AI_X3D_IMPORTER_NODE_H
|
||||
#define INCLUDED_AI_X3D_IMPORTER_NODE_H
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
#include "../include/assimp/types.h"
|
||||
#include "../include/assimp/scene.h"
|
||||
|
||||
/// \class CX3DImporter_NodeElement
|
||||
/// Base class for elements of nodes.
|
||||
class CX3DImporter_NodeElement
|
||||
{
|
||||
/***********************************************/
|
||||
/******************** Types ********************/
|
||||
/***********************************************/
|
||||
|
||||
public:
|
||||
|
||||
/// \enum EType
|
||||
/// Define what data type contain node element.
|
||||
enum EType
|
||||
{
|
||||
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.
|
||||
};
|
||||
|
||||
/***********************************************/
|
||||
/****************** Constants ******************/
|
||||
/***********************************************/
|
||||
|
||||
public:
|
||||
|
||||
const EType Type;
|
||||
|
||||
/***********************************************/
|
||||
/****************** Variables ******************/
|
||||
/***********************************************/
|
||||
|
||||
public:
|
||||
|
||||
std::string ID;///< ID of the element. Can be empty. In X3D synonym for "ID" attribute.
|
||||
CX3DImporter_NodeElement* Parent;///< Parrent element. If NULL then this node is root.
|
||||
std::list<CX3DImporter_NodeElement*> Child;///< Child elements.
|
||||
|
||||
/***********************************************/
|
||||
/****************** Functions ******************/
|
||||
/***********************************************/
|
||||
|
||||
private:
|
||||
|
||||
/// \fn CX3DImporter_NodeElement(const CX3DImporter_NodeElement& pNodeElement)
|
||||
/// Disabled copy constructor.
|
||||
CX3DImporter_NodeElement(const CX3DImporter_NodeElement& pNodeElement);
|
||||
|
||||
/// \fn CX3DImporter_NodeElement& operator=(const CX3DImporter_NodeElement& pNodeElement)
|
||||
/// Disabled assign operator.
|
||||
CX3DImporter_NodeElement& operator=(const CX3DImporter_NodeElement& pNodeElement);
|
||||
|
||||
/// \fn CX3DImporter_NodeElement()
|
||||
/// Disabled default constructor.
|
||||
CX3DImporter_NodeElement();
|
||||
|
||||
protected:
|
||||
|
||||
/// \fn CX3DImporter_NodeElement(const EType pType, CX3DImporter_NodeElement* pParent)
|
||||
/// In constructor inheritor must set element type.
|
||||
/// \param [in] pType - element type.
|
||||
/// \param [in] pParent - parent element.
|
||||
CX3DImporter_NodeElement(const EType pType, CX3DImporter_NodeElement* pParent)
|
||||
: Type(pType), Parent(pParent)
|
||||
{}
|
||||
|
||||
};// class IX3DImporter_NodeElement
|
||||
|
||||
/// \class CX3DImporter_NodeElement_Group
|
||||
/// Class that define grouping node. Define transformation matrix for children.
|
||||
/// Also can select which child will be kept and others are removed.
|
||||
class CX3DImporter_NodeElement_Group : public CX3DImporter_NodeElement
|
||||
{
|
||||
/***********************************************/
|
||||
/****************** Variables ******************/
|
||||
/***********************************************/
|
||||
|
||||
public:
|
||||
|
||||
aiMatrix4x4 Transformation;///< Transformation matrix.
|
||||
|
||||
/// \var bool Static
|
||||
/// 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.
|
||||
|
||||
/***********************************************/
|
||||
/****************** Functions ******************/
|
||||
/***********************************************/
|
||||
|
||||
private:
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_Group(const CX3DImporter_NodeElement_Group& pNode)
|
||||
/// Disabled copy constructor.
|
||||
CX3DImporter_NodeElement_Group(const CX3DImporter_NodeElement_Group& pNode);
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_Group& operator=(const CX3DImporter_NodeElement_Group& pNode)
|
||||
/// Disabled assign operator.
|
||||
CX3DImporter_NodeElement_Group& operator=(const CX3DImporter_NodeElement_Group& pNode);
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_Group()
|
||||
/// Disabled default constructor.
|
||||
CX3DImporter_NodeElement_Group();
|
||||
|
||||
public:
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_Group(CX3DImporter_NodeElement_Group* pParent, const bool pStatic = false)
|
||||
/// Constructor.
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
/// \param [in] pStatic - static node flag.
|
||||
CX3DImporter_NodeElement_Group(CX3DImporter_NodeElement* pParent, const bool pStatic = false)
|
||||
: CX3DImporter_NodeElement(ENET_Group, pParent), Static(pStatic), UseChoice(false)
|
||||
{}
|
||||
|
||||
};// class CX3DImporter_NodeElement_Group
|
||||
|
||||
/// \class CX3DImporter_NodeElement_Meta
|
||||
/// This struct describe metavalue.
|
||||
class CX3DImporter_NodeElement_Meta : public CX3DImporter_NodeElement
|
||||
{
|
||||
/***********************************************/
|
||||
/****************** Variables ******************/
|
||||
/***********************************************/
|
||||
|
||||
public:
|
||||
|
||||
std::string Name;///< Name of metadata object.
|
||||
/// \var std::string Reference
|
||||
/// If provided, it identifies the metadata standard or other specification that defines the name field. If the reference field is not provided or is
|
||||
/// empty, the meaning of the name field is considered implicit to the characters in the string.
|
||||
std::string Reference;
|
||||
|
||||
/***********************************************/
|
||||
/****************** Functions ******************/
|
||||
/***********************************************/
|
||||
|
||||
private:
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_Meta(const CX3DImporter_NodeElement_Meta& pNode)
|
||||
/// Disabled copy constructor.
|
||||
CX3DImporter_NodeElement_Meta(const CX3DImporter_NodeElement_Meta& pNode);
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_Meta& operator=(const CX3DImporter_NodeElement_Meta& pNode)
|
||||
/// Disabled assign operator.
|
||||
CX3DImporter_NodeElement_Meta& operator=(const CX3DImporter_NodeElement_Meta& pNode);
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_Meta()
|
||||
/// Disabled default constructor.
|
||||
CX3DImporter_NodeElement_Meta();
|
||||
|
||||
public:
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_Meta(const EType pType, CX3DImporter_NodeElement* pParent)
|
||||
/// In constructor inheritor must set element type.
|
||||
/// \param [in] pType - element type.
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
CX3DImporter_NodeElement_Meta(const EType pType, CX3DImporter_NodeElement* pParent)
|
||||
: CX3DImporter_NodeElement(pType, pParent)
|
||||
{}
|
||||
|
||||
};// class CX3DImporter_NodeElement_Meta
|
||||
|
||||
/// \struct CX3DImporter_NodeElement_MetaBoolean
|
||||
/// This struct describe metavalue of type boolean.
|
||||
struct CX3DImporter_NodeElement_MetaBoolean : public CX3DImporter_NodeElement_Meta
|
||||
{
|
||||
std::list<bool> Value;///< Stored value.
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_MetaBoolean(CX3DImporter_NodeElement* pParent)
|
||||
/// Constructor
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
CX3DImporter_NodeElement_MetaBoolean(CX3DImporter_NodeElement* pParent)
|
||||
: CX3DImporter_NodeElement_Meta(ENET_MetaBoolean, pParent)
|
||||
{}
|
||||
|
||||
};// struct CX3DImporter_NodeElement_MetaBoolean
|
||||
|
||||
/// \struct CX3DImporter_NodeElement_MetaDouble
|
||||
/// This struct describe metavalue of type double.
|
||||
struct CX3DImporter_NodeElement_MetaDouble : public CX3DImporter_NodeElement_Meta
|
||||
{
|
||||
std::list<double> Value;///< Stored value.
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_MetaDouble(CX3DImporter_NodeElement* pParent)
|
||||
/// Constructor
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
CX3DImporter_NodeElement_MetaDouble(CX3DImporter_NodeElement* pParent)
|
||||
: CX3DImporter_NodeElement_Meta(ENET_MetaDouble, pParent)
|
||||
{}
|
||||
|
||||
};// struct CX3DImporter_NodeElement_MetaDouble
|
||||
|
||||
/// \struct CX3DImporter_NodeElement_MetaFloat
|
||||
/// This struct describe metavalue of type float.
|
||||
struct CX3DImporter_NodeElement_MetaFloat : public CX3DImporter_NodeElement_Meta
|
||||
{
|
||||
std::list<float> Value;///< Stored value.
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_MetaFloat(CX3DImporter_NodeElement* pParent)
|
||||
/// Constructor
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
CX3DImporter_NodeElement_MetaFloat(CX3DImporter_NodeElement* pParent)
|
||||
: CX3DImporter_NodeElement_Meta(ENET_MetaFloat, pParent)
|
||||
{}
|
||||
|
||||
};// struct CX3DImporter_NodeElement_MetaFloat
|
||||
|
||||
/// \struct CX3DImporter_NodeElement_MetaInteger
|
||||
/// This struct describe metavalue of type integer.
|
||||
struct CX3DImporter_NodeElement_MetaInteger : public CX3DImporter_NodeElement_Meta
|
||||
{
|
||||
std::list<int32_t> Value;///< Stored value.
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_MetaInteger(CX3DImporter_NodeElement* pParent)
|
||||
/// Constructor
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
CX3DImporter_NodeElement_MetaInteger(CX3DImporter_NodeElement* pParent)
|
||||
: CX3DImporter_NodeElement_Meta(ENET_MetaInteger, pParent)
|
||||
{}
|
||||
|
||||
};// struct CX3DImporter_NodeElement_MetaInteger
|
||||
|
||||
/// \struct CX3DImporter_NodeElement_MetaSet
|
||||
/// This struct describe container for metaobjects.
|
||||
struct CX3DImporter_NodeElement_MetaSet : public CX3DImporter_NodeElement_Meta
|
||||
{
|
||||
std::list<CX3DImporter_NodeElement_Meta> Value;///< Stored value.
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_MetaSet(CX3DImporter_NodeElement* pParent)
|
||||
/// Constructor
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
CX3DImporter_NodeElement_MetaSet(CX3DImporter_NodeElement* pParent)
|
||||
: CX3DImporter_NodeElement_Meta(ENET_MetaSet, pParent)
|
||||
{}
|
||||
|
||||
};// struct CX3DImporter_NodeElement_MetaSet
|
||||
|
||||
/// \struct CX3DImporter_NodeElement_MetaString
|
||||
/// This struct describe metavalue of type string.
|
||||
struct CX3DImporter_NodeElement_MetaString : public CX3DImporter_NodeElement_Meta
|
||||
{
|
||||
std::list<std::string> Value;///< Stored value.
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_MetaString(CX3DImporter_NodeElement* pParent)
|
||||
/// Constructor
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
CX3DImporter_NodeElement_MetaString(CX3DImporter_NodeElement* pParent)
|
||||
: CX3DImporter_NodeElement_Meta(ENET_MetaString, pParent)
|
||||
{}
|
||||
|
||||
};// struct CX3DImporter_NodeElement_MetaString
|
||||
|
||||
/// \struct CX3DImporter_NodeElement_Color
|
||||
/// This struct hold <Color> value.
|
||||
struct CX3DImporter_NodeElement_Color : public CX3DImporter_NodeElement
|
||||
{
|
||||
std::list<aiColor3D> Value;///< Stored value.
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_Color(CX3DImporter_NodeElement* pParent)
|
||||
/// Constructor
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
CX3DImporter_NodeElement_Color(CX3DImporter_NodeElement* pParent)
|
||||
: CX3DImporter_NodeElement(ENET_Color, pParent)
|
||||
{}
|
||||
|
||||
};// struct CX3DImporter_NodeElement_Color
|
||||
|
||||
/// \struct CX3DImporter_NodeElement_ColorRGBA
|
||||
/// This struct hold <ColorRGBA> value.
|
||||
struct CX3DImporter_NodeElement_ColorRGBA : public CX3DImporter_NodeElement
|
||||
{
|
||||
std::list<aiColor4D> Value;///< Stored value.
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_ColorRGBA(CX3DImporter_NodeElement* pParent)
|
||||
/// Constructor
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
CX3DImporter_NodeElement_ColorRGBA(CX3DImporter_NodeElement* pParent)
|
||||
: CX3DImporter_NodeElement(ENET_ColorRGBA, pParent)
|
||||
{}
|
||||
|
||||
};// struct CX3DImporter_NodeElement_ColorRGBA
|
||||
|
||||
/// \struct CX3DImporter_NodeElement_Coordinate
|
||||
/// This struct hold <Coordinate> value.
|
||||
struct CX3DImporter_NodeElement_Coordinate : public CX3DImporter_NodeElement
|
||||
{
|
||||
std::list<aiVector3D> Value;///< Stored value.
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_Coordinate(CX3DImporter_NodeElement* pParent)
|
||||
/// Constructor
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
CX3DImporter_NodeElement_Coordinate(CX3DImporter_NodeElement* pParent)
|
||||
: CX3DImporter_NodeElement(ENET_Coordinate, pParent)
|
||||
{}
|
||||
|
||||
};// struct CX3DImporter_NodeElement_Coordinate
|
||||
|
||||
/// \struct CX3DImporter_NodeElement_Normal
|
||||
/// This struct hold <Normal> value.
|
||||
struct CX3DImporter_NodeElement_Normal : public CX3DImporter_NodeElement
|
||||
{
|
||||
std::list<aiVector3D> Value;///< Stored value.
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_Normal(CX3DImporter_NodeElement* pParent)
|
||||
/// Constructor
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
CX3DImporter_NodeElement_Normal(CX3DImporter_NodeElement* pParent)
|
||||
: CX3DImporter_NodeElement(ENET_Normal, pParent)
|
||||
{}
|
||||
|
||||
};// struct CX3DImporter_NodeElement_Normal
|
||||
|
||||
/// \struct CX3DImporter_NodeElement_TextureCoordinate
|
||||
/// This struct hold <TextureCoordinate> value.
|
||||
struct CX3DImporter_NodeElement_TextureCoordinate : public CX3DImporter_NodeElement
|
||||
{
|
||||
std::list<aiVector2D> Value;///< Stored value.
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_TextureCoordinate(CX3DImporter_NodeElement* pParent)
|
||||
/// Constructor
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
CX3DImporter_NodeElement_TextureCoordinate(CX3DImporter_NodeElement* pParent)
|
||||
: CX3DImporter_NodeElement(ENET_TextureCoordinate, pParent)
|
||||
{}
|
||||
|
||||
};// struct CX3DImporter_NodeElement_TextureCoordinate
|
||||
|
||||
/// \class CX3DImporter_NodeElement_Geometry2D
|
||||
/// Two-dimensional figure.
|
||||
class CX3DImporter_NodeElement_Geometry2D : public CX3DImporter_NodeElement
|
||||
{
|
||||
/***********************************************/
|
||||
/****************** Variables ******************/
|
||||
/***********************************************/
|
||||
|
||||
public:
|
||||
|
||||
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.
|
||||
|
||||
/***********************************************/
|
||||
/****************** Functions ******************/
|
||||
/***********************************************/
|
||||
|
||||
private:
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_Geometry2D(const CX3DImporter_NodeElement_Geometry2D& pNode)
|
||||
/// Disabled copy constructor.
|
||||
CX3DImporter_NodeElement_Geometry2D(const CX3DImporter_NodeElement_Geometry2D& pNode);
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_Geometry2D& operator=(const CX3DImporter_NodeElement_Geometry2D& pNode)
|
||||
/// Disabled assign operator.
|
||||
CX3DImporter_NodeElement_Geometry2D& operator=(const CX3DImporter_NodeElement_Geometry2D& pNode);
|
||||
|
||||
public:
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_Geometry2D(const EType pType, CX3DImporter_NodeElement* pParent)
|
||||
/// Constructor.
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
/// \param [in] pType - type of geometry object.
|
||||
CX3DImporter_NodeElement_Geometry2D(const EType pType, CX3DImporter_NodeElement* pParent)
|
||||
: CX3DImporter_NodeElement(pType, pParent), Solid(true)
|
||||
{}
|
||||
|
||||
};// class CX3DImporter_NodeElement_Geometry2D
|
||||
|
||||
/// \class CX3DImporter_NodeElement_Geometry3D
|
||||
/// Three-dimensional body.
|
||||
class CX3DImporter_NodeElement_Geometry3D : public CX3DImporter_NodeElement
|
||||
{
|
||||
/***********************************************/
|
||||
/****************** Variables ******************/
|
||||
/***********************************************/
|
||||
|
||||
public:
|
||||
|
||||
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.
|
||||
|
||||
/***********************************************/
|
||||
/****************** Functions ******************/
|
||||
/***********************************************/
|
||||
|
||||
private:
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_Geometry3D(const CX3DImporter_NodeElement_Geometry3D& pNode)
|
||||
/// Disabled copy constructor.
|
||||
CX3DImporter_NodeElement_Geometry3D(const CX3DImporter_NodeElement_Geometry3D& pNode);
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_Geometry3D& operator=(const CX3DImporter_NodeElement_Geometry3D& pNode)
|
||||
/// Disabled assign operator.
|
||||
CX3DImporter_NodeElement_Geometry3D& operator=(const CX3DImporter_NodeElement_Geometry3D& pNode);
|
||||
|
||||
public:
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_Geometry3D(const EType pType, CX3DImporter_NodeElement* pParent)
|
||||
/// Constructor.
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
/// \param [in] pType - type of geometry object.
|
||||
CX3DImporter_NodeElement_Geometry3D(const EType pType, CX3DImporter_NodeElement* pParent)
|
||||
: CX3DImporter_NodeElement(pType, pParent), Solid(true)
|
||||
{}
|
||||
|
||||
};// class CX3DImporter_NodeElement_Geometry3D
|
||||
|
||||
/// \class CX3DImporter_NodeElement_ElevationGrid
|
||||
/// Uniform rectangular grid of varying height.
|
||||
class CX3DImporter_NodeElement_ElevationGrid : public CX3DImporter_NodeElement_Geometry3D
|
||||
{
|
||||
/***********************************************/
|
||||
/****************** Variables ******************/
|
||||
/***********************************************/
|
||||
|
||||
public:
|
||||
|
||||
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).
|
||||
/// \var CreaseAngle
|
||||
/// 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::list<int32_t> CoordIdx;///< Coordinates list by faces. In X3D format: "-1" - delimiter for faces.
|
||||
|
||||
/***********************************************/
|
||||
/****************** Functions ******************/
|
||||
/***********************************************/
|
||||
|
||||
private:
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_ElevationGrid(const CX3DImporter_NodeElement_ElevationGrid& pNode)
|
||||
/// Disabled copy constructor.
|
||||
CX3DImporter_NodeElement_ElevationGrid(const CX3DImporter_NodeElement_ElevationGrid& pNode);
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_ElevationGrid& operator=(const CX3DImporter_NodeElement_ElevationGrid& pNode)
|
||||
/// Disabled assign operator.
|
||||
CX3DImporter_NodeElement_ElevationGrid& operator=(const CX3DImporter_NodeElement_ElevationGrid& pNode);
|
||||
|
||||
public:
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_ElevationGrid(const EType pType, CX3DImporter_NodeElement* pParent)
|
||||
/// Constructor.
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
/// \param [in] pType - type of geometry object.
|
||||
CX3DImporter_NodeElement_ElevationGrid(const EType pType, CX3DImporter_NodeElement* pParent)
|
||||
: CX3DImporter_NodeElement_Geometry3D(pType, pParent)
|
||||
{}
|
||||
|
||||
};// class CX3DImporter_NodeElement_IndexedSet
|
||||
|
||||
/// \class CX3DImporter_NodeElement_IndexedSet
|
||||
/// Shape with indexed vertices.
|
||||
class CX3DImporter_NodeElement_IndexedSet : public CX3DImporter_NodeElement_Geometry3D
|
||||
{
|
||||
/***********************************************/
|
||||
/****************** Variables ******************/
|
||||
/***********************************************/
|
||||
|
||||
public:
|
||||
|
||||
/// \var CCW
|
||||
/// 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::list<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).
|
||||
/// \var Convex
|
||||
/// 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::list<int32_t> CoordIndex;///< Field to specify the polygonal faces by indexing into the <Coordinate>.
|
||||
/// \var CreaseAngle
|
||||
/// 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::list<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::list<int32_t> TexCoordIndex;///< Field to specify the polygonal faces by indexing into the <TextureCoordinate>.
|
||||
|
||||
/***********************************************/
|
||||
/****************** Functions ******************/
|
||||
/***********************************************/
|
||||
|
||||
private:
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_IndexedSet(const CX3DImporter_NodeElement_IndexedSet& pNode)
|
||||
/// Disabled copy constructor.
|
||||
CX3DImporter_NodeElement_IndexedSet(const CX3DImporter_NodeElement_IndexedSet& pNode);
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_IndexedSet& operator=(const CX3DImporter_NodeElement_IndexedSet& pNode)
|
||||
/// Disabled assign operator.
|
||||
CX3DImporter_NodeElement_IndexedSet& operator=(const CX3DImporter_NodeElement_IndexedSet& pNode);
|
||||
|
||||
public:
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_IndexedSet(const EType pType, CX3DImporter_NodeElement* pParent)
|
||||
/// Constructor.
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
/// \param [in] pType - type of geometry object.
|
||||
CX3DImporter_NodeElement_IndexedSet(const EType pType, CX3DImporter_NodeElement* pParent)
|
||||
: CX3DImporter_NodeElement_Geometry3D(pType, pParent)
|
||||
{}
|
||||
|
||||
};// class CX3DImporter_NodeElement_IndexedSet
|
||||
|
||||
/// \class CX3DImporter_NodeElement_Set
|
||||
/// Shape with set of vertices.
|
||||
class CX3DImporter_NodeElement_Set : public CX3DImporter_NodeElement_Geometry3D
|
||||
{
|
||||
/***********************************************/
|
||||
/****************** Variables ******************/
|
||||
/***********************************************/
|
||||
|
||||
public:
|
||||
|
||||
/// \var CCW
|
||||
/// 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::list<int32_t> CoordIndex;///< Field to specify the polygonal faces by indexing into the <Coordinate>.
|
||||
std::list<int32_t> NormalIndex;///< Field to specify the polygonal faces by indexing into the <Normal>.
|
||||
std::list<int32_t> TexCoordIndex;///< Field to specify the polygonal faces by indexing into the <TextureCoordinate>.
|
||||
std::list<int32_t> VertexCount;///< Field describes how many vertices are to be used in each polyline(polygon) from the <Coordinate> field.
|
||||
|
||||
/***********************************************/
|
||||
/****************** Functions ******************/
|
||||
/***********************************************/
|
||||
|
||||
private:
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_Set(const CX3DImporter_NodeElement_Set& pNode)
|
||||
/// Disabled copy constructor.
|
||||
CX3DImporter_NodeElement_Set(const CX3DImporter_NodeElement_Set& pNode);
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_Set& operator=(const CX3DImporter_NodeElement_Set& pNode)
|
||||
/// Disabled assign operator.
|
||||
CX3DImporter_NodeElement_Set& operator=(const CX3DImporter_NodeElement_Set& pNode);
|
||||
|
||||
public:
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_Set(const EType pType, CX3DImporter_NodeElement* pParent)
|
||||
/// Constructor.
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
/// \param [in] pType - type of geometry object.
|
||||
CX3DImporter_NodeElement_Set(const EType pType, CX3DImporter_NodeElement* pParent)
|
||||
: CX3DImporter_NodeElement_Geometry3D(pType, pParent)
|
||||
{}
|
||||
|
||||
};// class CX3DImporter_NodeElement_Set
|
||||
|
||||
/// \struct CX3DImporter_NodeElement_Shape
|
||||
/// This struct hold <Shape> value.
|
||||
struct CX3DImporter_NodeElement_Shape : public CX3DImporter_NodeElement
|
||||
{
|
||||
/// \fn CX3DImporter_NodeElement_Shape(CX3DImporter_NodeElement_Shape* pParent)
|
||||
/// Constructor
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
CX3DImporter_NodeElement_Shape(CX3DImporter_NodeElement* pParent)
|
||||
: CX3DImporter_NodeElement(ENET_Shape, pParent)
|
||||
{}
|
||||
|
||||
};// struct CX3DImporter_NodeElement_Shape
|
||||
|
||||
/// \struct CX3DImporter_NodeElement_Appearance
|
||||
/// This struct hold <Appearance> value.
|
||||
struct CX3DImporter_NodeElement_Appearance : public CX3DImporter_NodeElement
|
||||
{
|
||||
/// \fn CX3DImporter_NodeElement_Appearance(CX3DImporter_NodeElement_Appearance* pParent)
|
||||
/// Constructor
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
CX3DImporter_NodeElement_Appearance(CX3DImporter_NodeElement* pParent)
|
||||
: CX3DImporter_NodeElement(ENET_Appearance, pParent)
|
||||
{}
|
||||
|
||||
};// struct CX3DImporter_NodeElement_Appearance
|
||||
|
||||
/// \class CX3DImporter_NodeElement_Material
|
||||
/// Material.
|
||||
class CX3DImporter_NodeElement_Material : public CX3DImporter_NodeElement
|
||||
{
|
||||
/***********************************************/
|
||||
/****************** Variables ******************/
|
||||
/***********************************************/
|
||||
|
||||
public:
|
||||
|
||||
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.
|
||||
|
||||
/***********************************************/
|
||||
/****************** Functions ******************/
|
||||
/***********************************************/
|
||||
|
||||
private:
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_Material(const CX3DImporter_NodeElement_Material& pNode)
|
||||
/// Disabled copy constructor.
|
||||
CX3DImporter_NodeElement_Material(const CX3DImporter_NodeElement_Material& pNode);
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_Material& operator=(const CX3DImporter_NodeElement_Material& pNode)
|
||||
/// Disabled assign operator.
|
||||
CX3DImporter_NodeElement_Material& operator=(const CX3DImporter_NodeElement_Material& pNode);
|
||||
|
||||
public:
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_Material(const EType pType, CX3DImporter_NodeElement* pParent)
|
||||
/// Constructor.
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
/// \param [in] pType - type of geometry object.
|
||||
CX3DImporter_NodeElement_Material(CX3DImporter_NodeElement* pParent)
|
||||
: CX3DImporter_NodeElement(ENET_Material, pParent)
|
||||
{}
|
||||
|
||||
};// class CX3DImporter_NodeElement_Material
|
||||
|
||||
/// \struct CX3DImporter_NodeElement_ImageTexture
|
||||
/// This struct hold <ImageTexture> value.
|
||||
struct CX3DImporter_NodeElement_ImageTexture : public CX3DImporter_NodeElement
|
||||
{
|
||||
/// \var RepeatS
|
||||
/// 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.
|
||||
/// \fn CX3DImporter_NodeElement_ImageTexture(CX3DImporter_NodeElement_ImageTexture* pParent)
|
||||
/// Constructor
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
CX3DImporter_NodeElement_ImageTexture(CX3DImporter_NodeElement* pParent)
|
||||
: CX3DImporter_NodeElement(ENET_ImageTexture, pParent)
|
||||
{}
|
||||
|
||||
};// struct CX3DImporter_NodeElement_ImageTexture
|
||||
|
||||
/// \struct CX3DImporter_NodeElement_TextureTransform
|
||||
/// This struct hold <TextureTransform> value.
|
||||
struct CX3DImporter_NodeElement_TextureTransform : public CX3DImporter_NodeElement
|
||||
{
|
||||
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.
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_TextureTransform(CX3DImporter_NodeElement_TextureTransform* pParent)
|
||||
/// Constructor
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
CX3DImporter_NodeElement_TextureTransform(CX3DImporter_NodeElement* pParent)
|
||||
: CX3DImporter_NodeElement(ENET_TextureTransform, pParent)
|
||||
{}
|
||||
|
||||
};// struct CX3DImporter_NodeElement_TextureTransform
|
||||
|
||||
/// \struct CX3DImporter_NodeElement_Light
|
||||
/// This struct hold <TextureTransform> value.
|
||||
struct CX3DImporter_NodeElement_Light : public CX3DImporter_NodeElement
|
||||
{
|
||||
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).
|
||||
|
||||
/// \fn CX3DImporter_NodeElement_Light(EType pLightType, CX3DImporter_NodeElement* pParent)
|
||||
/// Constructor
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
/// \param [in] pLightType - type of the light source.
|
||||
CX3DImporter_NodeElement_Light(EType pLightType, CX3DImporter_NodeElement* pParent)
|
||||
: CX3DImporter_NodeElement(pLightType, pParent)
|
||||
{}
|
||||
|
||||
};// struct CX3DImporter_NodeElement_Light
|
||||
|
||||
#endif // INCLUDED_AI_X3D_IMPORTER_NODE_H
|
|
@ -0,0 +1,772 @@
|
|||
/// \file X3DImporter_Postprocess.cpp
|
||||
/// \brief Convert built scenegraph and objects to Assimp scenegraph.
|
||||
/// \date 2015-2016
|
||||
/// \author nevorek@gmail.com
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
|
||||
#include "X3DImporter.hpp"
|
||||
#include "StandardShapes.h"
|
||||
|
||||
#include <boost/format.hpp>
|
||||
#include <string>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
|
||||
aiMatrix4x4 X3DImporter::PostprocessHelper_Matrix_GlobalToCurrent() const
|
||||
{
|
||||
CX3DImporter_NodeElement* cur_node;
|
||||
std::list<aiMatrix4x4> matr;
|
||||
aiMatrix4x4 out_matr;
|
||||
|
||||
// starting walk from current element to root
|
||||
cur_node = NodeElement_Cur;
|
||||
if(cur_node != NULL)
|
||||
{
|
||||
do
|
||||
{
|
||||
// if cur_node is group then store group transformation matrix in list.
|
||||
if(cur_node->Type == CX3DImporter_NodeElement::ENET_Group) matr.push_back(((CX3DImporter_NodeElement_Group*)cur_node)->Transformation);
|
||||
|
||||
cur_node = cur_node->Parent;
|
||||
} while(cur_node != NULL);
|
||||
}
|
||||
|
||||
// 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 CX3DImporter_NodeElement& pNodeElement, std::list<CX3DImporter_NodeElement*>& pList) const
|
||||
{
|
||||
// walk thru childs and find for metadata.
|
||||
for(std::list<CX3DImporter_NodeElement*>::const_iterator el_it = pNodeElement.Child.begin(); el_it != pNodeElement.Child.end(); el_it++)
|
||||
{
|
||||
if(((*el_it)->Type == CX3DImporter_NodeElement::ENET_MetaBoolean) || ((*el_it)->Type == CX3DImporter_NodeElement::ENET_MetaDouble) ||
|
||||
((*el_it)->Type == CX3DImporter_NodeElement::ENET_MetaFloat) || ((*el_it)->Type == CX3DImporter_NodeElement::ENET_MetaInteger) ||
|
||||
((*el_it)->Type == CX3DImporter_NodeElement::ENET_MetaString))
|
||||
{
|
||||
pList.push_back(*el_it);
|
||||
}
|
||||
else if((*el_it)->Type == CX3DImporter_NodeElement::ENET_MetaSet)
|
||||
{
|
||||
PostprocessHelper_CollectMetadata(**el_it, pList);
|
||||
}
|
||||
}// for(std::list<CX3DImporter_NodeElement*>::const_iterator el_it = pNodeElement.Child.begin(); el_it != pNodeElement.Child.end(); el_it++)
|
||||
}
|
||||
|
||||
bool X3DImporter::PostprocessHelper_ElementIsMetadata(const CX3DImporter_NodeElement::EType pType) const
|
||||
{
|
||||
if((pType == CX3DImporter_NodeElement::ENET_MetaBoolean) || (pType == CX3DImporter_NodeElement::ENET_MetaDouble) ||
|
||||
(pType == CX3DImporter_NodeElement::ENET_MetaFloat) || (pType == CX3DImporter_NodeElement::ENET_MetaInteger) ||
|
||||
(pType == CX3DImporter_NodeElement::ENET_MetaString) || (pType == CX3DImporter_NodeElement::ENET_MetaSet))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool X3DImporter::PostprocessHelper_ElementIsMesh(const CX3DImporter_NodeElement::EType pType) const
|
||||
{
|
||||
if((pType == CX3DImporter_NodeElement::ENET_Arc2D) || (pType == CX3DImporter_NodeElement::ENET_ArcClose2D) ||
|
||||
(pType == CX3DImporter_NodeElement::ENET_Box) || (pType == CX3DImporter_NodeElement::ENET_Circle2D) ||
|
||||
(pType == CX3DImporter_NodeElement::ENET_Cone) || (pType == CX3DImporter_NodeElement::ENET_Cylinder) ||
|
||||
(pType == CX3DImporter_NodeElement::ENET_Disk2D) || (pType == CX3DImporter_NodeElement::ENET_ElevationGrid) ||
|
||||
(pType == CX3DImporter_NodeElement::ENET_Extrusion) || (pType == CX3DImporter_NodeElement::ENET_IndexedFaceSet) ||
|
||||
(pType == CX3DImporter_NodeElement::ENET_IndexedLineSet) || (pType == CX3DImporter_NodeElement::ENET_IndexedTriangleFanSet) ||
|
||||
(pType == CX3DImporter_NodeElement::ENET_IndexedTriangleSet) || (pType == CX3DImporter_NodeElement::ENET_IndexedTriangleStripSet) ||
|
||||
(pType == CX3DImporter_NodeElement::ENET_PointSet) || (pType == CX3DImporter_NodeElement::ENET_LineSet) ||
|
||||
(pType == CX3DImporter_NodeElement::ENET_Polyline2D) || (pType == CX3DImporter_NodeElement::ENET_Polypoint2D) ||
|
||||
(pType == CX3DImporter_NodeElement::ENET_Rectangle2D) || (pType == CX3DImporter_NodeElement::ENET_Sphere) ||
|
||||
(pType == CX3DImporter_NodeElement::ENET_TriangleFanSet) || (pType == CX3DImporter_NodeElement::ENET_TriangleSet) ||
|
||||
(pType == CX3DImporter_NodeElement::ENET_TriangleSet2D) || (pType == CX3DImporter_NodeElement::ENET_TriangleStripSet))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void X3DImporter::Postprocess_BuildLight(const CX3DImporter_NodeElement& pNodeElement, std::list<aiLight*>& pSceneLightList) const
|
||||
{
|
||||
aiLight* new_light = new aiLight;
|
||||
const CX3DImporter_NodeElement_Light& ne = *((CX3DImporter_NodeElement_Light*)&pNodeElement);
|
||||
aiMatrix4x4 transform_matr = PostprocessHelper_Matrix_GlobalToCurrent();
|
||||
|
||||
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 CX3DImporter_NodeElement::ENET_DirectionalLight:
|
||||
new_light->mType = aiLightSource_DIRECTIONAL;
|
||||
new_light->mDirection = ne.Direction, new_light->mDirection *= transform_matr;
|
||||
|
||||
break;
|
||||
case CX3DImporter_NodeElement::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 CX3DImporter_NodeElement::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(boost::str(boost::format("Postprocess_BuildLight. Unknown type of light: %s") % pNodeElement.Type));
|
||||
}
|
||||
|
||||
pSceneLightList.push_back(new_light);
|
||||
}
|
||||
|
||||
void X3DImporter::Postprocess_BuildMaterial(const CX3DImporter_NodeElement& pNodeElement, aiMaterial** pMaterial) const
|
||||
{
|
||||
// check argument
|
||||
if(pMaterial == NULL) throw DeadlyImportError("Postprocess_BuildMaterial. pMaterial is NULL.");
|
||||
if(*pMaterial != NULL) throw DeadlyImportError("Postprocess_BuildMaterial. *pMaterial must be NULL.");
|
||||
|
||||
*pMaterial = new aiMaterial;
|
||||
aiMaterial& taimat = **pMaterial;// creating alias for convenience.
|
||||
|
||||
// at this point pNodeElement point to <Appearance> node. Walk thru childs and add all stored data.
|
||||
for(std::list<CX3DImporter_NodeElement*>::const_iterator el_it = pNodeElement.Child.begin(); el_it != pNodeElement.Child.end(); el_it++)
|
||||
{
|
||||
if((*el_it)->Type == CX3DImporter_NodeElement::ENET_Material)
|
||||
{
|
||||
aiColor3D tcol3;
|
||||
float tvalf;
|
||||
CX3DImporter_NodeElement_Material& tnemat = *((CX3DImporter_NodeElement_Material*)*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.0 - tnemat.Transparency;
|
||||
taimat.AddProperty(&tvalf, 1, AI_MATKEY_OPACITY);
|
||||
}// if((*el_it)->Type == CX3DImporter_NodeElement::ENET_Material)
|
||||
else if((*el_it)->Type == CX3DImporter_NodeElement::ENET_ImageTexture)
|
||||
{
|
||||
CX3DImporter_NodeElement_ImageTexture& tnetex = *((CX3DImporter_NodeElement_ImageTexture*)*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 == CX3DImporter_NodeElement::ENET_ImageTexture)
|
||||
else if((*el_it)->Type == CX3DImporter_NodeElement::ENET_TextureTransform)
|
||||
{
|
||||
aiUVTransform trans;
|
||||
CX3DImporter_NodeElement_TextureTransform& tnetextr = *((CX3DImporter_NodeElement_TextureTransform*)*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 == CX3DImporter_NodeElement::ENET_TextureTransform)
|
||||
}// for(std::list<CX3DImporter_NodeElement*>::const_iterator el_it = pNodeElement.Child.begin(); el_it != pNodeElement.Child.end(); el_it++)
|
||||
}
|
||||
|
||||
void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeElement, aiMesh** pMesh) const
|
||||
{
|
||||
// check argument
|
||||
if(pMesh == NULL) throw DeadlyImportError("Postprocess_BuildMesh. pMesh is NULL.");
|
||||
if(*pMesh != NULL) throw DeadlyImportError("Postprocess_BuildMesh. *pMesh must be NULL.");
|
||||
|
||||
/************************************************************************************************************************************/
|
||||
/************************************************************ Geometry2D ************************************************************/
|
||||
/************************************************************************************************************************************/
|
||||
if((pNodeElement.Type == CX3DImporter_NodeElement::ENET_Arc2D) || (pNodeElement.Type == CX3DImporter_NodeElement::ENET_ArcClose2D) ||
|
||||
(pNodeElement.Type == CX3DImporter_NodeElement::ENET_Circle2D) || (pNodeElement.Type == CX3DImporter_NodeElement::ENET_Disk2D) ||
|
||||
(pNodeElement.Type == CX3DImporter_NodeElement::ENET_Polyline2D) || (pNodeElement.Type == CX3DImporter_NodeElement::ENET_Polypoint2D) ||
|
||||
(pNodeElement.Type == CX3DImporter_NodeElement::ENET_Rectangle2D) || (pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleSet2D))
|
||||
{
|
||||
CX3DImporter_NodeElement_Geometry2D& tnemesh = *((CX3DImporter_NodeElement_Geometry2D*)&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, tnemesh.NumIndices);// create mesh from vertices using Assimp help.
|
||||
|
||||
return;// mesh is build, nothing to do anymore.
|
||||
}
|
||||
/************************************************************************************************************************************/
|
||||
/************************************************************ Geometry3D ************************************************************/
|
||||
/************************************************************************************************************************************/
|
||||
//
|
||||
// Predefined figures
|
||||
//
|
||||
if((pNodeElement.Type == CX3DImporter_NodeElement::ENET_Box) || (pNodeElement.Type == CX3DImporter_NodeElement::ENET_Cone) ||
|
||||
(pNodeElement.Type == CX3DImporter_NodeElement::ENET_Cylinder) || (pNodeElement.Type == CX3DImporter_NodeElement::ENET_Sphere))
|
||||
{
|
||||
CX3DImporter_NodeElement_Geometry3D& tnemesh = *((CX3DImporter_NodeElement_Geometry3D*)&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, tnemesh.NumIndices);// create mesh from vertices using Assimp help.
|
||||
|
||||
return;// mesh is build, nothing to do anymore.
|
||||
}
|
||||
//
|
||||
// Parametric figures
|
||||
//
|
||||
if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_ElevationGrid)
|
||||
{
|
||||
CX3DImporter_NodeElement_ElevationGrid& tnemesh = *((CX3DImporter_NodeElement_ElevationGrid*)&pNodeElement);// create alias for convenience
|
||||
|
||||
// at first create mesh from existing vertices.
|
||||
*pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIdx, tnemesh.Vertices);
|
||||
// copy additional information from children
|
||||
for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
|
||||
{
|
||||
if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
|
||||
MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA)
|
||||
MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Normal)
|
||||
MeshGeometry_AddNormal(**pMesh, ((CX3DImporter_NodeElement_Normal*)*ch_it)->Value, tnemesh.NormalPerVertex);
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate)
|
||||
MeshGeometry_AddTexCoord(**pMesh, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value);
|
||||
else
|
||||
throw DeadlyImportError(boost::str(boost::format("Postprocess_BuildMesh. Unknown child of ElevationGrid: %s.") % (*ch_it)->Type));
|
||||
}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
|
||||
|
||||
return;// mesh is build, nothing to do anymore.
|
||||
}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_ElevationGrid)
|
||||
//
|
||||
// Indexed primitives sets
|
||||
//
|
||||
if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedFaceSet)
|
||||
{
|
||||
CX3DImporter_NodeElement_IndexedSet& tnemesh = *((CX3DImporter_NodeElement_IndexedSet*)&pNodeElement);// create alias for convenience
|
||||
|
||||
// at first search for <Coordinate> node and create mesh.
|
||||
for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
|
||||
{
|
||||
if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
|
||||
{
|
||||
*pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value);
|
||||
}
|
||||
}
|
||||
|
||||
// copy additional information from children
|
||||
for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
|
||||
{
|
||||
if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
|
||||
MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA)
|
||||
MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value,
|
||||
tnemesh.ColorPerVertex);
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
|
||||
{} // skip because already read when mesh created.
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Normal)
|
||||
MeshGeometry_AddNormal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((CX3DImporter_NodeElement_Normal*)*ch_it)->Value,
|
||||
tnemesh.NormalPerVertex);
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate)
|
||||
MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value);
|
||||
else
|
||||
throw DeadlyImportError(boost::str(boost::format("Postprocess_BuildMesh. Unknown child of IndexedFaceSet: %s.") % (*ch_it)->Type));
|
||||
}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
|
||||
|
||||
return;// mesh is build, nothing to do anymore.
|
||||
}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedFaceSet)
|
||||
|
||||
if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedLineSet)
|
||||
{
|
||||
CX3DImporter_NodeElement_IndexedSet& tnemesh = *((CX3DImporter_NodeElement_IndexedSet*)&pNodeElement);// create alias for convenience
|
||||
|
||||
// at first search for <Coordinate> node and create mesh.
|
||||
for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
|
||||
{
|
||||
if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
|
||||
{
|
||||
*pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value);
|
||||
}
|
||||
}
|
||||
|
||||
// copy additional information from children
|
||||
for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
|
||||
{
|
||||
if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
|
||||
MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA)
|
||||
MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value,
|
||||
tnemesh.ColorPerVertex);
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
|
||||
{} // skip because already read when mesh created.
|
||||
else
|
||||
throw DeadlyImportError(boost::str(boost::format("Postprocess_BuildMesh. Unknown child of IndexedLineSet: %s.") % (*ch_it)->Type));
|
||||
}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
|
||||
|
||||
return;// mesh is build, nothing to do anymore.
|
||||
}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedLineSet)
|
||||
|
||||
if((pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedTriangleSet) ||
|
||||
(pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedTriangleFanSet) ||
|
||||
(pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedTriangleStripSet))
|
||||
{
|
||||
CX3DImporter_NodeElement_IndexedSet& tnemesh = *((CX3DImporter_NodeElement_IndexedSet*)&pNodeElement);// create alias for convenience
|
||||
|
||||
// at first search for <Coordinate> node and create mesh.
|
||||
for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
|
||||
{
|
||||
if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
|
||||
{
|
||||
*pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value);
|
||||
}
|
||||
}
|
||||
|
||||
// copy additional information from children
|
||||
for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
|
||||
{
|
||||
if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
|
||||
MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA)
|
||||
MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value,
|
||||
tnemesh.ColorPerVertex);
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
|
||||
{} // skip because already read when mesh created.
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Normal)
|
||||
MeshGeometry_AddNormal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((CX3DImporter_NodeElement_Normal*)*ch_it)->Value,
|
||||
tnemesh.NormalPerVertex);
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate)
|
||||
MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value);
|
||||
else
|
||||
throw DeadlyImportError(boost::str(boost::format("Postprocess_BuildMesh. Unknown child of IndexedTriangleSet or IndexedTriangleFanSet, or \
|
||||
IndexedTriangleStripSet: %s.") % (*ch_it)->Type));
|
||||
}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
|
||||
|
||||
return;// mesh is build, nothing to do anymore.
|
||||
}// if((pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedTriangleFanSet) || (pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedTriangleStripSet))
|
||||
|
||||
if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_Extrusion)
|
||||
{
|
||||
CX3DImporter_NodeElement_IndexedSet& tnemesh = *((CX3DImporter_NodeElement_IndexedSet*)&pNodeElement);// create alias for convenience
|
||||
|
||||
*pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, tnemesh.Vertices);
|
||||
|
||||
return;// mesh is build, nothing to do anymore.
|
||||
}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_Extrusion)
|
||||
|
||||
//
|
||||
// Primitives sets
|
||||
//
|
||||
if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_PointSet)
|
||||
{
|
||||
CX3DImporter_NodeElement_Set& tnemesh = *((CX3DImporter_NodeElement_Set*)&pNodeElement);// create alias for convenience
|
||||
|
||||
// at first search for <Coordinate> node and create mesh.
|
||||
for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
|
||||
{
|
||||
if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
|
||||
{
|
||||
std::vector<aiVector3D> vec_copy;
|
||||
|
||||
vec_copy.reserve(((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.size());
|
||||
for(std::list<aiVector3D>::const_iterator it = ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.begin();
|
||||
it != ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.end(); it++)
|
||||
{
|
||||
vec_copy.push_back(*it);
|
||||
}
|
||||
|
||||
*pMesh = StandardShapes::MakeMesh(vec_copy, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// copy additional information from children
|
||||
for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
|
||||
{
|
||||
if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
|
||||
MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, true);
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA)
|
||||
MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value, true);
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
|
||||
{} // skip because already read when mesh created.
|
||||
else
|
||||
throw DeadlyImportError(boost::str(boost::format("Postprocess_BuildMesh. Unknown child of PointSet: %s.") % (*ch_it)->Type));
|
||||
}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
|
||||
|
||||
return;// mesh is build, nothing to do anymore.
|
||||
}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_PointSet)
|
||||
|
||||
if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_LineSet)
|
||||
{
|
||||
CX3DImporter_NodeElement_Set& tnemesh = *((CX3DImporter_NodeElement_Set*)&pNodeElement);// create alias for convenience
|
||||
|
||||
// at first search for <Coordinate> node and create mesh.
|
||||
for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
|
||||
{
|
||||
if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
|
||||
{
|
||||
*pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value);
|
||||
}
|
||||
}
|
||||
|
||||
// copy additional information from children
|
||||
for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
|
||||
{
|
||||
if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
|
||||
MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, true);
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA)
|
||||
MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value, true);
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
|
||||
{} // skip because already read when mesh created.
|
||||
else
|
||||
throw DeadlyImportError(boost::str(boost::format("Postprocess_BuildMesh. Unknown child of LineSet: %s.") % (*ch_it)->Type));
|
||||
}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
|
||||
|
||||
return;// mesh is build, nothing to do anymore.
|
||||
}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_LineSet)
|
||||
|
||||
if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleFanSet)
|
||||
{
|
||||
CX3DImporter_NodeElement_Set& tnemesh = *((CX3DImporter_NodeElement_Set*)&pNodeElement);// create alias for convenience
|
||||
|
||||
// at first search for <Coordinate> node and create mesh.
|
||||
for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
|
||||
{
|
||||
if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
|
||||
{
|
||||
*pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value);
|
||||
}
|
||||
}
|
||||
|
||||
// copy additional information from children
|
||||
for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
|
||||
{
|
||||
if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
|
||||
MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value,tnemesh.ColorPerVertex);
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA)
|
||||
MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
|
||||
{} // skip because already read when mesh created.
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Normal)
|
||||
MeshGeometry_AddNormal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((CX3DImporter_NodeElement_Normal*)*ch_it)->Value,
|
||||
tnemesh.NormalPerVertex);
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate)
|
||||
MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value);
|
||||
else
|
||||
throw DeadlyImportError(boost::str(boost::format("Postprocess_BuildMesh. Unknown child of TrianlgeFanSet: %s.") % (*ch_it)->Type));
|
||||
}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
|
||||
|
||||
return;// mesh is build, nothing to do anymore.
|
||||
}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleFanSet)
|
||||
|
||||
if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleSet)
|
||||
{
|
||||
CX3DImporter_NodeElement_Set& tnemesh = *((CX3DImporter_NodeElement_Set*)&pNodeElement);// create alias for convenience
|
||||
|
||||
// at first search for <Coordinate> node and create mesh.
|
||||
for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
|
||||
{
|
||||
if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
|
||||
{
|
||||
std::vector<aiVector3D> vec_copy;
|
||||
|
||||
vec_copy.reserve(((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.size());
|
||||
for(std::list<aiVector3D>::const_iterator it = ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.begin();
|
||||
it != ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.end(); it++)
|
||||
{
|
||||
vec_copy.push_back(*it);
|
||||
}
|
||||
|
||||
*pMesh = StandardShapes::MakeMesh(vec_copy, 3);
|
||||
}
|
||||
}
|
||||
|
||||
// copy additional information from children
|
||||
for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
|
||||
{
|
||||
if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
|
||||
MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA)
|
||||
MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
|
||||
{} // skip because already read when mesh created.
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Normal)
|
||||
MeshGeometry_AddNormal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((CX3DImporter_NodeElement_Normal*)*ch_it)->Value,
|
||||
tnemesh.NormalPerVertex);
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate)
|
||||
MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value);
|
||||
else
|
||||
throw DeadlyImportError(boost::str(boost::format("Postprocess_BuildMesh. Unknown child of TrianlgeSet: %s.") % (*ch_it)->Type));
|
||||
}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
|
||||
|
||||
return;// mesh is build, nothing to do anymore.
|
||||
}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleSet)
|
||||
|
||||
if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleStripSet)
|
||||
{
|
||||
CX3DImporter_NodeElement_Set& tnemesh = *((CX3DImporter_NodeElement_Set*)&pNodeElement);// create alias for convenience
|
||||
|
||||
// at first search for <Coordinate> node and create mesh.
|
||||
for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
|
||||
{
|
||||
if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
|
||||
{
|
||||
*pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value);
|
||||
}
|
||||
}
|
||||
|
||||
// copy additional information from children
|
||||
for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
|
||||
{
|
||||
if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
|
||||
MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA)
|
||||
MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
|
||||
{} // skip because already read when mesh created.
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Normal)
|
||||
MeshGeometry_AddNormal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((CX3DImporter_NodeElement_Normal*)*ch_it)->Value,
|
||||
tnemesh.NormalPerVertex);
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate)
|
||||
MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value);
|
||||
else
|
||||
throw DeadlyImportError(boost::str(boost::format("Postprocess_BuildMesh. Unknown child of TriangleStripSet: %s.") % (*ch_it)->Type));
|
||||
}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
|
||||
|
||||
return;// mesh is build, nothing to do anymore.
|
||||
}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleStripSet)
|
||||
|
||||
throw DeadlyImportError(boost::str(boost::format("Postprocess_BuildMesh. Unknown mesh type: %s.") % pNodeElement.Type));
|
||||
}
|
||||
|
||||
void X3DImporter::Postprocess_BuildNode(const CX3DImporter_NodeElement& pNodeElement, aiNode& pSceneNode, std::list<aiMesh*>& pSceneMeshList,
|
||||
std::list<aiMaterial*>& pSceneMaterialList, std::list<aiLight*>& pSceneLightList) const
|
||||
{
|
||||
std::list<CX3DImporter_NodeElement*>::const_iterator chit_begin = pNodeElement.Child.begin();
|
||||
std::list<CX3DImporter_NodeElement*>::const_iterator chit_end = pNodeElement.Child.end();
|
||||
std::list<aiNode*> SceneNode_Child;
|
||||
std::list<aiLight*> SceneNode_Light;
|
||||
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 == CX3DImporter_NodeElement::ENET_Group)
|
||||
{
|
||||
const CX3DImporter_NodeElement_Group& tne_group = *((CX3DImporter_NodeElement_Group*)&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.Child.size()))
|
||||
{
|
||||
chit_begin = pNodeElement.Child.end();
|
||||
chit_end = pNodeElement.Child.end();
|
||||
}
|
||||
else
|
||||
{
|
||||
for(size_t i = 0; i < (size_t)tne_group.Choice; i++) chit_begin++;// forward iterator to choosed node.
|
||||
|
||||
chit_end = chit_begin;
|
||||
chit_end++;// point end iterator to next element after choosed.
|
||||
}
|
||||
}// if(tne_group.UseChoice)
|
||||
}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_Group)
|
||||
|
||||
// Reserve memory for fast access and check children.
|
||||
for(std::list<CX3DImporter_NodeElement*>::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 == CX3DImporter_NodeElement::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 == CX3DImporter_NodeElement::ENET_Shape)
|
||||
{
|
||||
// shape can contain only one geometry and one appearance nodes.
|
||||
Postprocess_BuildShape(*((CX3DImporter_NodeElement_Shape*)*it), SceneNode_Mesh, pSceneMeshList, pSceneMaterialList);
|
||||
}
|
||||
else if(((*it)->Type == CX3DImporter_NodeElement::ENET_DirectionalLight) || ((*it)->Type == CX3DImporter_NodeElement::ENET_PointLight) ||
|
||||
((*it)->Type == CX3DImporter_NodeElement::ENET_SpotLight))
|
||||
{
|
||||
Postprocess_BuildLight(*((CX3DImporter_NodeElement_Light*)*it), pSceneLightList);
|
||||
}
|
||||
else if(!PostprocessHelper_ElementIsMetadata((*it)->Type))// skip metadata
|
||||
{
|
||||
throw DeadlyImportError(boost::str(boost::format("Postprocess_BuildNode. Unknown type: %s.") % (*it)->Type));
|
||||
}
|
||||
}// for(std::list<CX3DImporter_NodeElement*>::const_iterator it = chit_begin; it != chit_end; it++)
|
||||
|
||||
// copy data about children and meshes to aiNode.
|
||||
if(SceneNode_Child.size() > 0)
|
||||
{
|
||||
std::list<aiNode*>::const_iterator it = SceneNode_Child.begin();
|
||||
|
||||
pSceneNode.mNumChildren = 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.size() > 0)
|
||||
{
|
||||
std::list<unsigned int>::const_iterator it = SceneNode_Mesh.begin();
|
||||
|
||||
pSceneNode.mNumMeshes = 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 CX3DImporter_NodeElement_Shape& pShapeNodeElement, std::list<unsigned int>& pNodeMeshInd,
|
||||
std::list<aiMesh*>& pSceneMeshList, std::list<aiMaterial*>& pSceneMaterialList) const
|
||||
{
|
||||
aiMaterial* tmat = NULL;
|
||||
aiMesh* tmesh = NULL;
|
||||
CX3DImporter_NodeElement::EType mesh_type = CX3DImporter_NodeElement::ENET_Invalid;
|
||||
unsigned int mat_ind = 0;
|
||||
|
||||
for(std::list<CX3DImporter_NodeElement*>::const_iterator it = pShapeNodeElement.Child.begin(); it != pShapeNodeElement.Child.end(); it++)
|
||||
{
|
||||
if(PostprocessHelper_ElementIsMesh((*it)->Type))
|
||||
{
|
||||
Postprocess_BuildMesh(**it, &tmesh);
|
||||
if(tmesh != NULL)
|
||||
{
|
||||
// if mesh successfully built then add data about it to arrays
|
||||
pNodeMeshInd.push_back(pSceneMeshList.size());
|
||||
pSceneMeshList.push_back(tmesh);
|
||||
// keep mesh type. Need above for texture coordinate generation.
|
||||
mesh_type = (*it)->Type;
|
||||
}
|
||||
}
|
||||
else if((*it)->Type == CX3DImporter_NodeElement::ENET_Appearance)
|
||||
{
|
||||
Postprocess_BuildMaterial(**it, &tmat);
|
||||
if(tmat != NULL)
|
||||
{
|
||||
// if material successfully built then add data about it to array
|
||||
mat_ind = pSceneMaterialList.size();
|
||||
pSceneMaterialList.push_back(tmat);
|
||||
}
|
||||
}
|
||||
}// for(std::list<CX3DImporter_NodeElement*>::const_iterator it = pShapeNodeElement.Child.begin(); it != pShapeNodeElement.Child.end(); it++)
|
||||
|
||||
// associate read material with read mesh.
|
||||
if((tmesh != NULL) && (tmat != NULL))
|
||||
{
|
||||
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 CX3DImporter_NodeElement::ENET_Box:
|
||||
tm = aiTextureMapping_BOX;
|
||||
break;
|
||||
case CX3DImporter_NodeElement::ENET_Cone:
|
||||
case CX3DImporter_NodeElement::ENET_Cylinder:
|
||||
tm = aiTextureMapping_CYLINDER;
|
||||
break;
|
||||
case CX3DImporter_NodeElement::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 != NULL) && (tmat != NULL))
|
||||
}
|
||||
|
||||
void X3DImporter::Postprocess_CollectMetadata(const CX3DImporter_NodeElement& pNodeElement, aiNode& pSceneNode) const
|
||||
{
|
||||
std::list<CX3DImporter_NodeElement*> meta_list;
|
||||
size_t meta_idx = 0;
|
||||
|
||||
PostprocessHelper_CollectMetadata(pNodeElement, meta_list);// find metadata in current node element.
|
||||
if(meta_list.size() > 0)
|
||||
{
|
||||
if(pSceneNode.mMetaData != NULL) throw DeadlyImportError("Postprocess. MetaData member in node are not NULL. Something went wrong.");
|
||||
|
||||
// copy collected metadata to output node.
|
||||
pSceneNode.mMetaData = new aiMetadata();
|
||||
pSceneNode.mMetaData->mNumProperties = meta_list.size();
|
||||
pSceneNode.mMetaData->mKeys = new aiString[pSceneNode.mMetaData->mNumProperties];
|
||||
pSceneNode.mMetaData->mValues = new aiMetadataEntry[pSceneNode.mMetaData->mNumProperties];
|
||||
for(std::list<CX3DImporter_NodeElement*>::const_iterator it = meta_list.begin(); it != meta_list.end(); it++)
|
||||
{
|
||||
CX3DImporter_NodeElement_Meta* cur_meta = (CX3DImporter_NodeElement_Meta*)*it;
|
||||
|
||||
// due to limitations we can add only first element of value list.
|
||||
// Add an element according to its type.
|
||||
if((*it)->Type == CX3DImporter_NodeElement::ENET_MetaBoolean)
|
||||
{
|
||||
if(((CX3DImporter_NodeElement_MetaBoolean*)cur_meta)->Value.size() > 0)
|
||||
pSceneNode.mMetaData->Set(meta_idx, cur_meta->Name, *(((CX3DImporter_NodeElement_MetaBoolean*)cur_meta)->Value.begin()));
|
||||
}
|
||||
else if((*it)->Type == CX3DImporter_NodeElement::ENET_MetaDouble)
|
||||
{
|
||||
// at this case also converting double to float.
|
||||
if(((CX3DImporter_NodeElement_MetaBoolean*)cur_meta)->Value.size() > 0)
|
||||
pSceneNode.mMetaData->Set(meta_idx, cur_meta->Name, (float)*(((CX3DImporter_NodeElement_MetaDouble*)cur_meta)->Value.begin()));
|
||||
}
|
||||
else if((*it)->Type == CX3DImporter_NodeElement::ENET_MetaFloat)
|
||||
{
|
||||
if(((CX3DImporter_NodeElement_MetaBoolean*)cur_meta)->Value.size() > 0)
|
||||
pSceneNode.mMetaData->Set(meta_idx, cur_meta->Name, *(((CX3DImporter_NodeElement_MetaFloat*)cur_meta)->Value.begin()));
|
||||
}
|
||||
else if((*it)->Type == CX3DImporter_NodeElement::ENET_MetaInteger)
|
||||
{
|
||||
if(((CX3DImporter_NodeElement_MetaBoolean*)cur_meta)->Value.size() > 0)
|
||||
pSceneNode.mMetaData->Set(meta_idx, cur_meta->Name, *(((CX3DImporter_NodeElement_MetaInteger*)cur_meta)->Value.begin()));
|
||||
}
|
||||
else if((*it)->Type == CX3DImporter_NodeElement::ENET_MetaString)
|
||||
{
|
||||
if(((CX3DImporter_NodeElement_MetaBoolean*)cur_meta)->Value.size() > 0)
|
||||
pSceneNode.mMetaData->Set(meta_idx, cur_meta->Name, ((CX3DImporter_NodeElement_MetaString*)cur_meta)->Value.begin()->data());
|
||||
}
|
||||
else
|
||||
{
|
||||
throw DeadlyImportError("Postprocess. Unknown metadata type.");
|
||||
}// if((*it)->Type == CX3DImporter_NodeElement::ENET_Meta*) else
|
||||
}// for(std::list<CX3DImporter_NodeElement*>::const_iterator it = meta_list.begin(); it != meta_list.end(); it++)
|
||||
}// if(meta_list.size() > 0)
|
||||
}
|
||||
|
||||
}// namespace Assimp
|
||||
|
||||
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
@ -0,0 +1,937 @@
|
|||
/// \file X3DImporter_Rendering.cpp
|
||||
/// \brief Parsing data from nodes of "Rendering" set of X3D.
|
||||
/// \date 2015-2016
|
||||
/// \author nevorek@gmail.com
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
|
||||
#include "X3DImporter.hpp"
|
||||
#include "X3DImporter_Macro.hpp"
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
|
||||
// <Color
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// color="" MFColor [inputOutput]
|
||||
// />
|
||||
void X3DImporter::ParseNode_Rendering_Color()
|
||||
{
|
||||
std::string use, def;
|
||||
std::list<aiColor3D> color;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_REF("color", color, XML_ReadNode_GetAttrVal_AsListCol3f);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Color, ne);
|
||||
}
|
||||
else
|
||||
{
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new CX3DImporter_NodeElement_Color(NodeElement_Cur);
|
||||
if(!def.empty()) ne->ID = def;
|
||||
|
||||
((CX3DImporter_NodeElement_Color*)ne)->Value = color;
|
||||
// check for X3DMetadataObject childs.
|
||||
if(!mReader->isEmptyElement())
|
||||
ParseNode_Metadata(ne, "Color");
|
||||
else
|
||||
NodeElement_Cur->Child.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::ParseNode_Rendering_ColorRGBA()
|
||||
{
|
||||
std::string use, def;
|
||||
std::list<aiColor4D> color;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_REF("color", color, XML_ReadNode_GetAttrVal_AsListCol4f);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_ColorRGBA, ne);
|
||||
}
|
||||
else
|
||||
{
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new CX3DImporter_NodeElement_ColorRGBA(NodeElement_Cur);
|
||||
if(!def.empty()) ne->ID = def;
|
||||
|
||||
((CX3DImporter_NodeElement_ColorRGBA*)ne)->Value = color;
|
||||
// check for X3DMetadataObject childs.
|
||||
if(!mReader->isEmptyElement())
|
||||
ParseNode_Metadata(ne, "ColorRGBA");
|
||||
else
|
||||
NodeElement_Cur->Child.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::ParseNode_Rendering_Coordinate()
|
||||
{
|
||||
std::string use, def;
|
||||
std::list<aiVector3D> point;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_REF("point", point, XML_ReadNode_GetAttrVal_AsListVec3f);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Coordinate, ne);
|
||||
}
|
||||
else
|
||||
{
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new CX3DImporter_NodeElement_Coordinate(NodeElement_Cur);
|
||||
if(!def.empty()) ne->ID = def;
|
||||
|
||||
((CX3DImporter_NodeElement_Coordinate*)ne)->Value = point;
|
||||
// check for X3DMetadataObject childs.
|
||||
if(!mReader->isEmptyElement())
|
||||
ParseNode_Metadata(ne, "Coordinate");
|
||||
else
|
||||
NodeElement_Cur->Child.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::ParseNode_Rendering_IndexedLineSet()
|
||||
{
|
||||
std::string use, def;
|
||||
std::list<int32_t> colorIndex;
|
||||
bool colorPerVertex = true;
|
||||
std::list<int32_t> coordIndex;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_REF("colorIndex", colorIndex, XML_ReadNode_GetAttrVal_AsListI32);
|
||||
MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_REF("coordIndex", coordIndex, XML_ReadNode_GetAttrVal_AsListI32);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(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 CX3DImporter_NodeElement_IndexedSet(CX3DImporter_NodeElement::ENET_IndexedLineSet, NodeElement_Cur);
|
||||
if(!def.empty()) ne->ID = def;
|
||||
|
||||
CX3DImporter_NodeElement_IndexedSet& ne_alias = *((CX3DImporter_NodeElement_IndexedSet*)ne);
|
||||
|
||||
ne_alias.ColorIndex = colorIndex;
|
||||
ne_alias.ColorPerVertex = colorPerVertex;
|
||||
ne_alias.CoordIndex = coordIndex;
|
||||
// check for child nodes
|
||||
if(!mReader->isEmptyElement())
|
||||
{
|
||||
ParseHelper_Node_Enter(ne);
|
||||
MACRO_NODECHECK_LOOPBEGIN("IndexedLineSet");
|
||||
// check for Color and Coordinate nodes
|
||||
if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
|
||||
if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
|
||||
if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
|
||||
// check for X3DMetadataObject
|
||||
if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("IndexedLineSet");
|
||||
|
||||
MACRO_NODECHECK_LOOPEND("IndexedLineSet");
|
||||
ParseHelper_Node_Exit();
|
||||
}// if(!mReader->isEmptyElement())
|
||||
else
|
||||
{
|
||||
NodeElement_Cur->Child.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::ParseNode_Rendering_IndexedTriangleFanSet()
|
||||
{
|
||||
std::string use, def;
|
||||
bool ccw = true;
|
||||
bool colorPerVertex = true;
|
||||
std::list<int32_t> index;
|
||||
bool normalPerVertex = true;
|
||||
bool solid = true;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_REF("index", index, XML_ReadNode_GetAttrVal_AsListI32);
|
||||
MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(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 CX3DImporter_NodeElement_IndexedSet(CX3DImporter_NodeElement::ENET_IndexedTriangleFanSet, NodeElement_Cur);
|
||||
if(!def.empty()) ne->ID = def;
|
||||
|
||||
CX3DImporter_NodeElement_IndexedSet& ne_alias = *((CX3DImporter_NodeElement_IndexedSet*)ne);
|
||||
|
||||
ne_alias.CCW = ccw;
|
||||
ne_alias.ColorPerVertex = colorPerVertex;
|
||||
ne_alias.CoordIndex = index;
|
||||
ne_alias.NormalPerVertex = normalPerVertex;
|
||||
ne_alias.Solid = solid;
|
||||
// check for child nodes
|
||||
if(!mReader->isEmptyElement())
|
||||
{
|
||||
ParseHelper_Node_Enter(ne);
|
||||
MACRO_NODECHECK_LOOPBEGIN("IndexedTriangleFanSet");
|
||||
// check for X3DComposedGeometryNodes
|
||||
if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
|
||||
if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
|
||||
if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
|
||||
if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
|
||||
if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
|
||||
// check for X3DMetadataObject
|
||||
if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("IndexedTriangleFanSet");
|
||||
|
||||
MACRO_NODECHECK_LOOPEND("IndexedTriangleFanSet");
|
||||
ParseHelper_Node_Exit();
|
||||
}// if(!mReader->isEmptyElement())
|
||||
else
|
||||
{
|
||||
NodeElement_Cur->Child.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::ParseNode_Rendering_IndexedTriangleSet()
|
||||
{
|
||||
std::string use, def;
|
||||
bool ccw = true;
|
||||
bool colorPerVertex = true;
|
||||
std::list<int32_t> index;
|
||||
bool normalPerVertex = true;
|
||||
bool solid = true;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_REF("index", index, XML_ReadNode_GetAttrVal_AsListI32);
|
||||
MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(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 CX3DImporter_NodeElement_IndexedSet(CX3DImporter_NodeElement::ENET_IndexedTriangleSet, NodeElement_Cur);
|
||||
if(!def.empty()) ne->ID = def;
|
||||
|
||||
CX3DImporter_NodeElement_IndexedSet& ne_alias = *((CX3DImporter_NodeElement_IndexedSet*)ne);
|
||||
|
||||
ne_alias.CCW = ccw;
|
||||
ne_alias.ColorPerVertex = colorPerVertex;
|
||||
ne_alias.CoordIndex = index;
|
||||
ne_alias.NormalPerVertex = normalPerVertex;
|
||||
ne_alias.Solid = solid;
|
||||
// check for child nodes
|
||||
if(!mReader->isEmptyElement())
|
||||
{
|
||||
ParseHelper_Node_Enter(ne);
|
||||
MACRO_NODECHECK_LOOPBEGIN("IndexedTriangleSet");
|
||||
// check for X3DComposedGeometryNodes
|
||||
if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
|
||||
if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
|
||||
if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
|
||||
if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
|
||||
if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
|
||||
// check for X3DMetadataObject
|
||||
if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("IndexedTriangleSet");
|
||||
|
||||
MACRO_NODECHECK_LOOPEND("IndexedTriangleSet");
|
||||
ParseHelper_Node_Exit();
|
||||
}// if(!mReader->isEmptyElement())
|
||||
else
|
||||
{
|
||||
NodeElement_Cur->Child.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::ParseNode_Rendering_IndexedTriangleStripSet()
|
||||
{
|
||||
std::string use, def;
|
||||
bool ccw = true;
|
||||
bool colorPerVertex = true;
|
||||
std::list<int32_t> index;
|
||||
bool normalPerVertex = true;
|
||||
bool solid = true;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_REF("index", index, XML_ReadNode_GetAttrVal_AsListI32);
|
||||
MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(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 CX3DImporter_NodeElement_IndexedSet(CX3DImporter_NodeElement::ENET_IndexedTriangleStripSet, NodeElement_Cur);
|
||||
if(!def.empty()) ne->ID = def;
|
||||
|
||||
CX3DImporter_NodeElement_IndexedSet& ne_alias = *((CX3DImporter_NodeElement_IndexedSet*)ne);
|
||||
|
||||
ne_alias.CCW = ccw;
|
||||
ne_alias.ColorPerVertex = colorPerVertex;
|
||||
ne_alias.CoordIndex = index;
|
||||
ne_alias.NormalPerVertex = normalPerVertex;
|
||||
ne_alias.Solid = solid;
|
||||
// check for child nodes
|
||||
if(!mReader->isEmptyElement())
|
||||
{
|
||||
ParseHelper_Node_Enter(ne);
|
||||
MACRO_NODECHECK_LOOPBEGIN("IndexedTriangleStripSet");
|
||||
// check for X3DComposedGeometryNodes
|
||||
if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
|
||||
if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
|
||||
if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
|
||||
if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
|
||||
if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
|
||||
// check for X3DMetadataObject
|
||||
if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("IndexedTriangleStripSet");
|
||||
|
||||
MACRO_NODECHECK_LOOPEND("IndexedTriangleStripSet");
|
||||
ParseHelper_Node_Exit();
|
||||
}// if(!mReader->isEmptyElement())
|
||||
else
|
||||
{
|
||||
NodeElement_Cur->Child.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::ParseNode_Rendering_LineSet()
|
||||
{
|
||||
std::string use, def;
|
||||
std::list<int32_t> vertexCount;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_REF("vertexCount", vertexCount, XML_ReadNode_GetAttrVal_AsListI32);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(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 CX3DImporter_NodeElement_Set(CX3DImporter_NodeElement::ENET_LineSet, NodeElement_Cur);
|
||||
if(!def.empty()) ne->ID = def;
|
||||
|
||||
CX3DImporter_NodeElement_Set& ne_alias = *((CX3DImporter_NodeElement_Set*)ne);
|
||||
|
||||
ne_alias.VertexCount = vertexCount;
|
||||
// create CoordIdx
|
||||
size_t coord_num = 0;
|
||||
|
||||
ne_alias.CoordIndex.clear();
|
||||
for(std::list<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(coord_num++);// add vertices indices
|
||||
|
||||
ne_alias.CoordIndex.push_back(-1);// add face delimiter.
|
||||
}
|
||||
|
||||
// check for child nodes
|
||||
if(!mReader->isEmptyElement())
|
||||
{
|
||||
ParseHelper_Node_Enter(ne);
|
||||
MACRO_NODECHECK_LOOPBEGIN("LineSet");
|
||||
// check for X3DComposedGeometryNodes
|
||||
if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
|
||||
if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
|
||||
if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
|
||||
// check for X3DMetadataObject
|
||||
if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("LineSet");
|
||||
|
||||
MACRO_NODECHECK_LOOPEND("LineSet");
|
||||
ParseHelper_Node_Exit();
|
||||
}// if(!mReader->isEmptyElement())
|
||||
else
|
||||
{
|
||||
NodeElement_Cur->Child.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::ParseNode_Rendering_PointSet()
|
||||
{
|
||||
std::string use, def;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_PointSet, ne);
|
||||
}
|
||||
else
|
||||
{
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new CX3DImporter_NodeElement_IndexedSet(CX3DImporter_NodeElement::ENET_PointSet, NodeElement_Cur);
|
||||
if(!def.empty()) ne->ID = def;
|
||||
|
||||
// check for child nodes
|
||||
if(!mReader->isEmptyElement())
|
||||
{
|
||||
ParseHelper_Node_Enter(ne);
|
||||
MACRO_NODECHECK_LOOPBEGIN("PointSet");
|
||||
// check for X3DComposedGeometryNodes
|
||||
if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
|
||||
if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
|
||||
if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
|
||||
// check for X3DMetadataObject
|
||||
if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("PointSet");
|
||||
|
||||
MACRO_NODECHECK_LOOPEND("PointSet");
|
||||
ParseHelper_Node_Exit();
|
||||
}// if(!mReader->isEmptyElement())
|
||||
else
|
||||
{
|
||||
NodeElement_Cur->Child.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::ParseNode_Rendering_TriangleFanSet()
|
||||
{
|
||||
std::string use, def;
|
||||
bool ccw = true;
|
||||
bool colorPerVertex = true;
|
||||
std::list<int32_t> fanCount;
|
||||
bool normalPerVertex = true;
|
||||
bool solid = true;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_REF("fanCount", fanCount, XML_ReadNode_GetAttrVal_AsListI32);
|
||||
MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(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 CX3DImporter_NodeElement_Set(CX3DImporter_NodeElement::ENET_TriangleFanSet, NodeElement_Cur);
|
||||
if(!def.empty()) ne->ID = def;
|
||||
|
||||
CX3DImporter_NodeElement_Set& ne_alias = *((CX3DImporter_NodeElement_Set*)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::list<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(coord_num_first);// first vertex is a center and always is [0].
|
||||
ne_alias.CoordIndex.push_back(coord_num_prev++);
|
||||
ne_alias.CoordIndex.push_back(coord_num_prev);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 1 2
|
||||
// 0
|
||||
ne_alias.CoordIndex.push_back(coord_num_first);// first vertex is a center and always is [0].
|
||||
ne_alias.CoordIndex.push_back(coord_num_prev + 1);
|
||||
ne_alias.CoordIndex.push_back(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(!mReader->isEmptyElement())
|
||||
{
|
||||
ParseHelper_Node_Enter(ne);
|
||||
MACRO_NODECHECK_LOOPBEGIN("TriangleFanSet");
|
||||
// check for X3DComposedGeometryNodes
|
||||
if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
|
||||
if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
|
||||
if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
|
||||
if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
|
||||
if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
|
||||
// check for X3DMetadataObject
|
||||
if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("TriangleFanSet");
|
||||
|
||||
MACRO_NODECHECK_LOOPEND("TriangleFanSet");
|
||||
ParseHelper_Node_Exit();
|
||||
}// if(!mReader->isEmptyElement())
|
||||
else
|
||||
{
|
||||
NodeElement_Cur->Child.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::ParseNode_Rendering_TriangleSet()
|
||||
{
|
||||
std::string use, def;
|
||||
bool ccw = true;
|
||||
bool colorPerVertex = true;
|
||||
bool normalPerVertex = true;
|
||||
bool solid = true;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_TriangleSet, ne);
|
||||
}
|
||||
else
|
||||
{
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new CX3DImporter_NodeElement_IndexedSet(CX3DImporter_NodeElement::ENET_TriangleSet, NodeElement_Cur);
|
||||
if(!def.empty()) ne->ID = def;
|
||||
|
||||
CX3DImporter_NodeElement_Set& ne_alias = *((CX3DImporter_NodeElement_Set*)ne);
|
||||
|
||||
ne_alias.CCW = ccw;
|
||||
ne_alias.ColorPerVertex = colorPerVertex;
|
||||
ne_alias.NormalPerVertex = normalPerVertex;
|
||||
ne_alias.Solid = solid;
|
||||
// check for child nodes
|
||||
if(!mReader->isEmptyElement())
|
||||
{
|
||||
ParseHelper_Node_Enter(ne);
|
||||
MACRO_NODECHECK_LOOPBEGIN("TriangleSet");
|
||||
// check for X3DComposedGeometryNodes
|
||||
if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
|
||||
if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
|
||||
if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
|
||||
if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
|
||||
if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
|
||||
// check for X3DMetadataObject
|
||||
if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("TriangleSet");
|
||||
|
||||
MACRO_NODECHECK_LOOPEND("TriangleSet");
|
||||
ParseHelper_Node_Exit();
|
||||
}// if(!mReader->isEmptyElement())
|
||||
else
|
||||
{
|
||||
NodeElement_Cur->Child.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::ParseNode_Rendering_TriangleStripSet()
|
||||
{
|
||||
std::string use, def;
|
||||
bool ccw = true;
|
||||
bool colorPerVertex = true;
|
||||
std::list<int32_t> stripCount;
|
||||
bool normalPerVertex = true;
|
||||
bool solid = true;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_REF("stripCount", stripCount, XML_ReadNode_GetAttrVal_AsListI32);
|
||||
MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(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 CX3DImporter_NodeElement_Set(CX3DImporter_NodeElement::ENET_TriangleStripSet, NodeElement_Cur);
|
||||
if(!def.empty()) ne->ID = def;
|
||||
|
||||
CX3DImporter_NodeElement_Set& ne_alias = *((CX3DImporter_NodeElement_Set*)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::list<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(coord_num0);
|
||||
ne_alias.CoordIndex.push_back(coord_num1);
|
||||
ne_alias.CoordIndex.push_back(coord_num2);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 0 1
|
||||
// 2
|
||||
ne_alias.CoordIndex.push_back(coord_num0);
|
||||
ne_alias.CoordIndex.push_back(coord_num2);
|
||||
ne_alias.CoordIndex.push_back(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(!mReader->isEmptyElement())
|
||||
{
|
||||
ParseHelper_Node_Enter(ne);
|
||||
MACRO_NODECHECK_LOOPBEGIN("TriangleStripSet");
|
||||
// check for X3DComposedGeometryNodes
|
||||
if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
|
||||
if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
|
||||
if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
|
||||
if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
|
||||
if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
|
||||
// check for X3DMetadataObject
|
||||
if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("TriangleStripSet");
|
||||
|
||||
MACRO_NODECHECK_LOOPEND("TriangleStripSet");
|
||||
ParseHelper_Node_Exit();
|
||||
}// if(!mReader->isEmptyElement())
|
||||
else
|
||||
{
|
||||
NodeElement_Cur->Child.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::ParseNode_Rendering_Normal()
|
||||
{
|
||||
std::string use, def;
|
||||
std::list<aiVector3D> vector;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
LogInfo("TRACE: scene rendering Normal b");
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_REF("vector", vector, XML_ReadNode_GetAttrVal_AsListVec3f);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Normal, ne);
|
||||
}
|
||||
else
|
||||
{
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new CX3DImporter_NodeElement_Normal(NodeElement_Cur);
|
||||
if(!def.empty()) ne->ID = def;
|
||||
|
||||
((CX3DImporter_NodeElement_Normal*)ne)->Value = vector;
|
||||
// check for X3DMetadataObject childs.
|
||||
if(!mReader->isEmptyElement())
|
||||
ParseNode_Metadata(ne, "Normal");
|
||||
else
|
||||
NodeElement_Cur->Child.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
|
||||
LogInfo("TRACE: scene rendering Normal e");
|
||||
}
|
||||
|
||||
}// namespace Assimp
|
||||
|
||||
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
|
@ -0,0 +1,209 @@
|
|||
/// \file X3DImporter_Shape.cpp
|
||||
/// \brief Parsing data from nodes of "Shape" set of X3D.
|
||||
/// \date 2015-2016
|
||||
/// \author nevorek@gmail.com
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
|
||||
#include "X3DImporter.hpp"
|
||||
#include "X3DImporter_Macro.hpp"
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
|
||||
// <Shape
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// bboxCenter="0 0 0" SFVec3f [initializeOnly]
|
||||
// bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
|
||||
// >
|
||||
// <!-- ShapeChildContentModel -->
|
||||
// "ShapeChildContentModel is the child-node content model corresponding to X3DShapeNode. ShapeChildContentModel can contain a single Appearance node and a
|
||||
// single geometry node, in any order.
|
||||
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model."
|
||||
// </Shape>
|
||||
// A Shape node is unlit if either of the following is true:
|
||||
// The shape's appearance field is NULL (default).
|
||||
// The material field in the Appearance node is NULL (default).
|
||||
// NOTE Geometry nodes that represent lines or points do not support lighting.
|
||||
void X3DImporter::ParseNode_Shape_Shape()
|
||||
{
|
||||
std::string use, def;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Shape, ne);
|
||||
}
|
||||
else
|
||||
{
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new CX3DImporter_NodeElement_Shape(NodeElement_Cur);
|
||||
if(!def.empty()) ne->ID = def;
|
||||
|
||||
// check for child nodes
|
||||
if(!mReader->isEmptyElement())
|
||||
{
|
||||
ParseHelper_Node_Enter(ne);
|
||||
MACRO_NODECHECK_LOOPBEGIN("Shape");
|
||||
// check for appearance node
|
||||
if(XML_CheckNode_NameEqual("Appearance")) { ParseNode_Shape_Appearance(); continue; }
|
||||
// check for X3DGeometryNodes
|
||||
if(XML_CheckNode_NameEqual("Arc2D")) { ParseNode_Geometry2D_Arc2D(); continue; }
|
||||
if(XML_CheckNode_NameEqual("ArcClose2D")) { ParseNode_Geometry2D_ArcClose2D(); continue; }
|
||||
if(XML_CheckNode_NameEqual("Circle2D")) { ParseNode_Geometry2D_Circle2D(); continue; }
|
||||
if(XML_CheckNode_NameEqual("Disk2D")) { ParseNode_Geometry2D_Disk2D(); continue; }
|
||||
if(XML_CheckNode_NameEqual("Polyline2D")) { ParseNode_Geometry2D_Polyline2D(); continue; }
|
||||
if(XML_CheckNode_NameEqual("Polypoint2D")) { ParseNode_Geometry2D_Polypoint2D(); continue; }
|
||||
if(XML_CheckNode_NameEqual("Rectangle2D")) { ParseNode_Geometry2D_Rectangle2D(); continue; }
|
||||
if(XML_CheckNode_NameEqual("TriangleSet2D")) { ParseNode_Geometry2D_TriangleSet2D(); continue; }
|
||||
if(XML_CheckNode_NameEqual("Box")) { ParseNode_Geometry3D_Box(); continue; }
|
||||
if(XML_CheckNode_NameEqual("Cone")) { ParseNode_Geometry3D_Cone(); continue; }
|
||||
if(XML_CheckNode_NameEqual("Cylinder")) { ParseNode_Geometry3D_Cylinder(); continue; }
|
||||
if(XML_CheckNode_NameEqual("ElevationGrid")) { ParseNode_Geometry3D_ElevationGrid(); continue; }
|
||||
if(XML_CheckNode_NameEqual("Extrusion")) { ParseNode_Geometry3D_Extrusion(); continue; }
|
||||
if(XML_CheckNode_NameEqual("IndexedFaceSet")) { ParseNode_Geometry3D_IndexedFaceSet(); continue; }
|
||||
if(XML_CheckNode_NameEqual("Sphere")) { ParseNode_Geometry3D_Sphere(); continue; }
|
||||
if(XML_CheckNode_NameEqual("IndexedLineSet")) { ParseNode_Rendering_IndexedLineSet(); continue; }
|
||||
if(XML_CheckNode_NameEqual("LineSet")) { ParseNode_Rendering_LineSet(); continue; }
|
||||
if(XML_CheckNode_NameEqual("PointSet")) { ParseNode_Rendering_PointSet(); continue; }
|
||||
if(XML_CheckNode_NameEqual("IndexedTriangleFanSet")) { ParseNode_Rendering_IndexedTriangleFanSet(); continue; }
|
||||
if(XML_CheckNode_NameEqual("IndexedTriangleSet")) { ParseNode_Rendering_IndexedTriangleSet(); continue; }
|
||||
if(XML_CheckNode_NameEqual("IndexedTriangleStripSet")) { ParseNode_Rendering_IndexedTriangleStripSet(); continue; }
|
||||
if(XML_CheckNode_NameEqual("TriangleFanSet")) { ParseNode_Rendering_TriangleFanSet(); continue; }
|
||||
if(XML_CheckNode_NameEqual("TriangleSet")) { ParseNode_Rendering_TriangleSet(); continue; }
|
||||
if(XML_CheckNode_NameEqual("TriangleStripSet")) { ParseNode_Rendering_TriangleStripSet(); continue; }
|
||||
// check for X3DMetadataObject
|
||||
if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("Shape");
|
||||
|
||||
MACRO_NODECHECK_LOOPEND("Shape");
|
||||
ParseHelper_Node_Exit();
|
||||
}// if(!mReader->isEmptyElement())
|
||||
else
|
||||
{
|
||||
NodeElement_Cur->Child.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::ParseNode_Shape_Appearance()
|
||||
{
|
||||
std::string use, def;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Appearance, ne);
|
||||
}
|
||||
else
|
||||
{
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new CX3DImporter_NodeElement_Appearance(NodeElement_Cur);
|
||||
if(!def.empty()) ne->ID = def;
|
||||
|
||||
// check for child nodes
|
||||
if(!mReader->isEmptyElement())
|
||||
{
|
||||
ParseHelper_Node_Enter(ne);
|
||||
MACRO_NODECHECK_LOOPBEGIN("Appearance");
|
||||
if(XML_CheckNode_NameEqual("Material")) { ParseNode_Shape_Material(); continue; }
|
||||
if(XML_CheckNode_NameEqual("ImageTexture")) { ParseNode_Texturing_ImageTexture(); continue; }
|
||||
if(XML_CheckNode_NameEqual("TextureTransform")) { ParseNode_Texturing_TextureTransform(); continue; }
|
||||
// check for X3DMetadataObject
|
||||
if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("Appearance");
|
||||
|
||||
MACRO_NODECHECK_LOOPEND("Appearance");
|
||||
ParseHelper_Node_Exit();
|
||||
}// if(!mReader->isEmptyElement())
|
||||
else
|
||||
{
|
||||
NodeElement_Cur->Child.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::ParseNode_Shape_Material()
|
||||
{
|
||||
std::string use, def;
|
||||
float ambientIntensity = 0.2;
|
||||
float shininess = 0.2;
|
||||
float transparency = 0;
|
||||
aiColor3D diffuseColor(0.8, 0.8, 0.8);
|
||||
aiColor3D emissiveColor(0, 0, 0);
|
||||
aiColor3D specularColor(0, 0, 0);
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_RET("ambientIntensity", ambientIntensity, XML_ReadNode_GetAttrVal_AsFloat);
|
||||
MACRO_ATTRREAD_CHECK_RET("shininess", shininess, XML_ReadNode_GetAttrVal_AsFloat);
|
||||
MACRO_ATTRREAD_CHECK_RET("transparency", transparency, XML_ReadNode_GetAttrVal_AsFloat);
|
||||
MACRO_ATTRREAD_CHECK_REF("diffuseColor", diffuseColor, XML_ReadNode_GetAttrVal_AsCol3f);
|
||||
MACRO_ATTRREAD_CHECK_REF("emissiveColor", emissiveColor, XML_ReadNode_GetAttrVal_AsCol3f);
|
||||
MACRO_ATTRREAD_CHECK_REF("specularColor", specularColor, XML_ReadNode_GetAttrVal_AsCol3f);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Material, ne);
|
||||
}
|
||||
else
|
||||
{
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new CX3DImporter_NodeElement_Material(NodeElement_Cur);
|
||||
if(!def.empty()) ne->ID = def;
|
||||
|
||||
((CX3DImporter_NodeElement_Material*)ne)->AmbientIntensity = ambientIntensity;
|
||||
((CX3DImporter_NodeElement_Material*)ne)->Shininess = shininess;
|
||||
((CX3DImporter_NodeElement_Material*)ne)->Transparency = transparency;
|
||||
((CX3DImporter_NodeElement_Material*)ne)->DiffuseColor = diffuseColor;
|
||||
((CX3DImporter_NodeElement_Material*)ne)->EmissiveColor = emissiveColor;
|
||||
((CX3DImporter_NodeElement_Material*)ne)->SpecularColor = specularColor;
|
||||
// check for child nodes
|
||||
if(!mReader->isEmptyElement())
|
||||
ParseNode_Metadata(ne, "Material");
|
||||
else
|
||||
NodeElement_Cur->Child.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,156 @@
|
|||
/// \file X3DImporter_Texturing.cpp
|
||||
/// \brief Parsing data from nodes of "Texturing" set of X3D.
|
||||
/// \date 2015-2016
|
||||
/// \author nevorek@gmail.com
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
|
||||
#include "X3DImporter.hpp"
|
||||
#include "X3DImporter_Macro.hpp"
|
||||
|
||||
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::ParseNode_Texturing_ImageTexture()
|
||||
{
|
||||
std::string use, def;
|
||||
bool repeatS = true;
|
||||
bool repeatT = true;
|
||||
std::list<std::string> url;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_RET("repeatS", repeatS, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_RET("repeatT", repeatT, XML_ReadNode_GetAttrVal_AsBool);
|
||||
MACRO_ATTRREAD_CHECK_REF("url", url, XML_ReadNode_GetAttrVal_AsListS);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_ImageTexture, ne);
|
||||
}
|
||||
else
|
||||
{
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new CX3DImporter_NodeElement_ImageTexture(NodeElement_Cur);
|
||||
if(!def.empty()) ne->ID = def;
|
||||
|
||||
((CX3DImporter_NodeElement_ImageTexture*)ne)->RepeatS = repeatS;
|
||||
((CX3DImporter_NodeElement_ImageTexture*)ne)->RepeatT = repeatT;
|
||||
// Attribute "url" can contain list of strings. But we need only one - first.
|
||||
if(url.size() > 0)
|
||||
((CX3DImporter_NodeElement_ImageTexture*)ne)->URL = url.front();
|
||||
else
|
||||
((CX3DImporter_NodeElement_ImageTexture*)ne)->URL = "";
|
||||
|
||||
// check for X3DMetadataObject childs.
|
||||
if(!mReader->isEmptyElement())
|
||||
ParseNode_Metadata(ne, "ImageTexture");
|
||||
else
|
||||
NodeElement_Cur->Child.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::ParseNode_Texturing_TextureCoordinate()
|
||||
{
|
||||
std::string use, def;
|
||||
std::list<aiVector2D> point;
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_REF("point", point, XML_ReadNode_GetAttrVal_AsListVec2f);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_TextureCoordinate, ne);
|
||||
}
|
||||
else
|
||||
{
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new CX3DImporter_NodeElement_TextureCoordinate(NodeElement_Cur);
|
||||
if(!def.empty()) ne->ID = def;
|
||||
|
||||
((CX3DImporter_NodeElement_TextureCoordinate*)ne)->Value = point;
|
||||
// check for X3DMetadataObject childs.
|
||||
if(!mReader->isEmptyElement())
|
||||
ParseNode_Metadata(ne, "TextureCoordinate");
|
||||
else
|
||||
NodeElement_Cur->Child.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::ParseNode_Texturing_TextureTransform()
|
||||
{
|
||||
std::string use, def;
|
||||
aiVector2D center(0, 0);
|
||||
float rotation = 0;
|
||||
aiVector2D scale(1, 1);
|
||||
aiVector2D translation(0, 0);
|
||||
CX3DImporter_NodeElement* ne;
|
||||
|
||||
MACRO_ATTRREAD_LOOPBEG;
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||
MACRO_ATTRREAD_CHECK_REF("center", center, XML_ReadNode_GetAttrVal_AsVec2f);
|
||||
MACRO_ATTRREAD_CHECK_RET("rotation", rotation, XML_ReadNode_GetAttrVal_AsFloat);
|
||||
MACRO_ATTRREAD_CHECK_REF("scale", scale, XML_ReadNode_GetAttrVal_AsVec2f);
|
||||
MACRO_ATTRREAD_CHECK_REF("translation", translation, XML_ReadNode_GetAttrVal_AsVec2f);
|
||||
MACRO_ATTRREAD_LOOPEND;
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if(!use.empty())
|
||||
{
|
||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_TextureTransform, ne);
|
||||
}
|
||||
else
|
||||
{
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new CX3DImporter_NodeElement_TextureTransform(NodeElement_Cur);
|
||||
if(!def.empty()) ne->ID = def;
|
||||
|
||||
((CX3DImporter_NodeElement_TextureTransform*)ne)->Center = center;
|
||||
((CX3DImporter_NodeElement_TextureTransform*)ne)->Rotation = rotation;
|
||||
((CX3DImporter_NodeElement_TextureTransform*)ne)->Scale = scale;
|
||||
((CX3DImporter_NodeElement_TextureTransform*)ne)->Translation = translation;
|
||||
// check for X3DMetadataObject childs.
|
||||
if(!mReader->isEmptyElement())
|
||||
ParseNode_Metadata(ne, "TextureTransform");
|
||||
else
|
||||
NodeElement_Cur->Child.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
|
Loading…
Reference in New Issue