The template Mesh relative classes are X3DTK::X3D::MeshBuilder
which builds the MESH scene graph and all the processors of the MESH scene graph. As you saw it myStructureComputer you can use the default instantiations (X3DTK::X3D::DefMeshBuilder
) and you the MESH scene graph in a non-template C++ code. If you need to add information per vertex, you can create you own data structure by aggregating vertex data structures.
That is what is done in this example, where we want to add a weight information per vertex, aggregating into X3DTK::MESH::MyVertexData
:
X3DTK::MESH::VertexPointData
, predefined structure X3DTK::MESH::VertexNormalData
, predefined structure X3DTK::MESH::VertexWeightData
, personal structure.Some important functions and classes:
X3DTK::X3D::Coordinate
to add a weight attribute per vertex. So we add a weight member of type X3DTK::MFFloat
. As we did it in newNodeViewer for the X3DTK::X3D::FCylinder
node, we record the type name as well as the new attribute in the constructor.X3DTK::X3D::Loader
by setting X3DTK::X3D::MyRenderingCreator
as a new creator for the Rendering component.X3DTK::MESH::VertexWeightData
because it is a per vertex information. Then we define our own vertex data, by aggregating the structures we need. Here we want point data, normal data and of course weight data. For that we use the automatic class generation via X3DTK::clist
and X3DTK::tlist
. Thus define X3DTK::MESH::MyVertexData
, X3DTK::MESH::MyFaceData
, X3DTK::MESH::MyMeshData
.For Visual Studio 6 users, notice the use of the TEMPLATE_SPECIALIZATION_SUPPORTED preprocessor definition. The difference between the two codes is that in the case of TEMPLATE_SPECIALIZATION_SUPPORTED, the access of data is optional and there won't be a compilation error if the data is not present. The type list cannot be defined in Visual Studio 6, that is why the inheritance is hand-made.
X3DTK::X3D::MeshBuilder
, by adding a visitor function for X3DTK::X3D::MyCoordinate
in which we access to the weight data of the vertices. That is why we derive X3DTK::X3D::MeshBuilderRenderingVisitor
.X3DTK::X3D::MyCoordinate node
. We extend X3DTK::MESH::MeshX3DBuilder
by deriving X3DTK::MESH::MeshX3DBuilderCoreVisitor
.X3DTK::X3D::MeshBuilder
, X3DTK::MESH::MeshX3DBuilder
with our X3DTK::MESH::MyVertexData
, X3DTK::MESH::MyFaceData
, X3DTK::MESH::MyMeshData
as template parameters.#ifndef MYCOORDINATE_H #define MYCOORDINATE_H #include <X3DTK/X3D/scenegraph.h> namespace X3DTK { namespace X3D { // Class X3D::MyCoordinate extending the X3D::Coordinate node by adding a weight information. class MyCoordinate : public Coordinate { public: MyCoordinate(); void setWeight(const MFFloat &weight); inline const MFFloat &getWeight() const {return _weight;}; private: MFFloat _weight; }; } } #endif
#include "X3D_MyCoordinate.h" #include <iostream> using namespace std; namespace X3DTK { namespace X3D { MyCoordinate::MyCoordinate() : Coordinate() { define(Recorder<MyCoordinate>::getTypeName("MyCoordinate")); define(Recorder<MyCoordinate, MFFloat>::getAttribute("weight", &MyCoordinate::_weight, MFFloat())); } void MyCoordinate::setWeight(const MFFloat &weight) { _weight = weight; } } }
#ifndef MYRENDERINGCREATOR_H #define MYRENDERINGCREATOR_H #include <X3DTK/X3D/scenegraph.h> namespace X3DTK { namespace X3D { // Component creator for the Rendering component defining the default // X3D nodes plus MyCoordinate. class MyRenderingCreator : public RenderingCreator { public: MyRenderingCreator(); }; } } #endif
#include "X3D_MyRenderingCreator.h" #include "X3D_MyCoordinate.h" namespace X3DTK { namespace X3D { MyRenderingCreator::MyRenderingCreator() : RenderingCreator() { // Defines the new creation functions for the new nodes. define(Recorder<MyCoordinate>::getCreationFunction()); } } }
#ifndef MESHMYMESHDATA_H #define MESHMYMESHDATA_H #include <X3DTK/MESH/scenegraph.h> namespace X3DTK { namespace MESH { // My vertex data structure containing the weight information. class VertexWeightData { public: void setWeight(const SFFloat &weight) {_weight = weight;}; inline const SFFloat &getWeight() const {return _weight;}; private: SFFloat _weight; }; // My Mesh data aggregates. #ifdef TEMPLATE_SPECIALIZATION_SUPPORTED typedef clist<tlist<VertexPointData, tlist<VertexNormalData, tlist<VertexWeightData> > > > MyVertexData; typedef clist<tlist<FaceNormalData> > MyFaceData; typedef clist<tlist<MeshNormalData> > MyMeshData; #else class MyVertexData : public VertexData, public VertexWeightData {}; class MyFaceData : public FaceData {}; class MyMeshData : public MeshData {}; #endif } } #endif
#ifndef MYMESHBUILDERRENDERINGVISITOR_H #define MYMESHBUILDERRENDERINGVISITOR_H #include <X3DTK/X3D/meshbuilder.h> #include "X3D_MyCoordinate.h" namespace X3DTK { namespace X3D { // Visitor for the Rendering component of the MyMeshBuilder processor. template<class MData, class VData, class EData, class FData, bool readOnly> class MyMeshBuilderRenderingVisitor : public TemplateMeshBuilderRenderingVisitor<MData, VData, EData, FData, readOnly> { public: MyMeshBuilderRenderingVisitor(); static void enterMyCoordinate(MyCoordinate *C); }; } } #include "X3D_MyMeshBuilderRenderingVisitor.inl" #endif
namespace X3DTK { namespace X3D { template<class MData, class VData, class EData, class FData, bool RW> MyMeshBuilderRenderingVisitor<MData, VData, EData, FData, RW>::MyMeshBuilderRenderingVisitor() : TemplateMeshBuilderRenderingVisitor<MData, VData, EData, FData, RW>() { define(Recorder<MyCoordinate>::getEnterFunction(&MyMeshBuilderRenderingVisitor::enterMyCoordinate)); } template<class MData, class VData, class EData, class FData, bool RW> void MyMeshBuilderRenderingVisitor<MData, VData, EData, FData, RW>::enterMyCoordinate(MyCoordinate *C) { TemplateMeshBuilderStateVariables<MData, VData, EData, FData, RW> *stateVariables = Singleton<TemplateMeshBuilderStateVariables<MData, VData, EData, FData, RW> >::getInstance(); MESH::TemplateVertex<MData, VData, EData, FData, RW> *MC = dynamic_cast<MESH::TemplateVertex<MData, VData, EData, FData, RW> *>(stateVariables->getNode(C)); if (MC != 0) { // Filling the Vertices. const MFFloat &weight = C->getWeight(); const typename MESH::TemplateVertex<MData, VData, EData, FData, RW>::MFVertex &vertices = MC->getVertices(); // Test the optional presence of MESH::VertexPointData in VData. #ifdef TEMPLATE_SPECIALIZATION_SUPPORTED if (VData::template find<MESH::VertexWeightData>() && weight.size() >= vertices.size()) #endif { MFFloat::const_iterator w = weight.begin(); // Accessing the MESH::VertexWeightData of VData. for (typename MESH::TemplateVertex<MData, VData, EData, FData, RW>::MFVertex::const_iterator v = vertices.begin(); v != vertices.end(); ++v) { #ifdef TEMPLATE_SPECIALIZATION_SUPPORTED (*v)->template ogetData<MESH::VertexWeightData>().setWeight(*w); #else (*v)->data().setWeight(*w); #endif ++w; } } stateVariables->addCoupleNode(C, MC); } stateVariables->pushNode(MC); } } }
#ifndef MYMESHX3DBUILDERVISITOR_H #define MYMESHX3DBUILDERVISITOR_H #include <X3DTK/MESH/x3dbuilder.h> #include "X3D_MyCoordinate.h" namespace X3DTK { namespace MESH { // Visitor for the Core component of the MyX3DBuilder processor. template<class MData, class VData, class EData, class FData, bool RW> class MyX3DBuilderCoreVisitor : public TemplateX3DBuilderCoreVisitor<MData, VData, EData, FData, RW> { public: MyX3DBuilderCoreVisitor(); static void enterVertex(TemplateVertex<MData, VData, EData, FData, RW> *V); }; } } #include "MESH_MyX3DBuilderCoreVisitor.inl" #endif
namespace X3DTK { namespace MESH { template<class MData, class VData, class EData, class FData, bool RW> MyX3DBuilderCoreVisitor<MData, VData, EData, FData, RW>::MyX3DBuilderCoreVisitor() { define(Recorder<TemplateVertex<MData, VData, EData, FData, RW> >::getEnterFunction(&MyX3DBuilderCoreVisitor::enterVertex)); } template<class MData, class VData, class EData, class FData, bool RW> void MyX3DBuilderCoreVisitor<MData, VData, EData, FData, RW>::enterVertex(TemplateVertex<MData, VData, EData, FData, RW> *V) { // StateVariables assignation. TemplateX3DBuilderStateVariables<MData, VData, EData, FData, RW> *stateVariables = Singleton<TemplateX3DBuilderStateVariables<MData, VData, EData, FData, RW> >::getInstance(); // Test of the presence of MESH::VertexWeightData in VData. #ifdef TEMPLATE_SPECIALIZATION_SUPPORTED if (!VData::template find<VertexWeightData>()) { // Call to super class function. TemplateX3DBuilderCoreVisitor<MData, VData, EData, FData, RW>::enterVertex(V); } else #endif { // Recoding the creation of the node. X3D::MyCoordinate *NC = dynamic_cast<X3D::MyCoordinate *>(stateVariables->getNode(V)); if (NC == 0) { // Create a new MyCoordinate. NC = new X3D::MyCoordinate(); const typename TemplateVertex<MData, VData, EData, FData, RW>::MFVertex &vertices = V->getVertices(); // Test the optional presence of MESH::VertexPointData in VData. #ifdef TEMPLATE_SPECIALIZATION_SUPPORTED if (VData::template find<MESH::VertexPointData>()) #endif { // Updating Coordinate. MFVec3f point; // Accessing the MESH::VertexPointData of VData. for (typename TemplateVertex<MData, VData, EData, FData, RW>::MFVertex::const_iterator v = vertices.begin(); v != vertices.end(); ++v) #ifdef TEMPLATE_SPECIALIZATION_SUPPORTED point.push_back(SFVec3f((*v)->template ogetData<MESH::VertexPointData>().getPoint())); #else point.push_back(SFVec3f((*v)->data().getPoint())); #endif NC->setPoint(point); } MFFloat weight; // Accessing the MESH::VertexWeightData of VData. #ifdef TEMPLATE_SPECIALIZATION_SUPPORTED if (VData::template find<MESH::VertexWeightData>()) #endif { for (typename TemplateVertex<MData, VData, EData, FData, RW>::MFVertex::const_iterator v = vertices.begin(); v != vertices.end(); ++v) { #ifdef TEMPLATE_SPECIALIZATION_SUPPORTED weight.push_back((*v)->template ogetData<MESH::VertexWeightData>().getWeight()); #else weight.push_back((*v)->data().getWeight()); #endif } } NC->setWeight(weight); // memorizing the couple (V, NC) to avoid to create a new Coordinate // if V is visited a second time. stateVariables->addCoupleNode(V, NC); } stateVariables->pushNode(NC); } } } }
#include "MESH_MyMeshData.h" #include "X3D_MyRenderingCreator.h" #include "X3D_MyMeshBuilderRenderingVisitor.h" #include "MESH_MyX3DBuilderCoreVisitor.h" #include <X3DTK/X3D/scenegraph.h> #include <X3DTK/X3D/meshbuilder.h> #include <X3DTK/MESH/x3dbuilder.h> #include <X3DTK/X3D/scenesaver.h> #include <iostream> #include <X3DTK/graphtester.h> using namespace X3DTK; using namespace std; int main(int argc, char *argv[]) { if (argc <= 1) { cerr << "usage: extendedmeshsaver input" << endl; exit(0); } // DefaultLoader to load the default X3D Nodes. X3D::Loader *loader = Singleton<X3D::Loader>::getInstance(); loader->setComponentCreator(new X3D::MyRenderingCreator()); // Instanciation of the new MeshBuilder. X3D::TemplateMeshBuilder<MESH::MyMeshData, MESH::MyVertexData, MESH::EdgeData, MESH::MyFaceData, true> *meshbuilder = Singleton<X3D::TemplateMeshBuilder<MESH::MyMeshData, MESH::MyVertexData, MESH::EdgeData, MESH::MyFaceData, true> >::getInstance(); meshbuilder->setComponentVisitor(new X3D::MyMeshBuilderRenderingVisitor<MESH::MyMeshData, MESH::MyVertexData, MESH::EdgeData, MESH::MyFaceData, true>()); // Instanciation of the new MeshX3DBuilder. MESH::TemplateX3DBuilder<MESH::MyMeshData, MESH::MyVertexData, MESH::EdgeData, MESH::MyFaceData, true> *meshx3dbuilder = Singleton<MESH::TemplateX3DBuilder<MESH::MyMeshData, MESH::MyVertexData, MESH::EdgeData, MESH::MyFaceData, true> >::getInstance(); meshx3dbuilder->setComponentVisitor(new MESH::MyX3DBuilderCoreVisitor<MESH::MyMeshData, MESH::MyVertexData, MESH::EdgeData, MESH::MyFaceData, true>()); // Instanciation of the SceneSaver. X3D::SceneSaver *saver = Singleton<X3D::SceneSaver>::getInstance(); // Loads the scene. X3D::Scene *s = loader->load(argv[1], false); cout << "s = " << s << endl; GraphTester *gt = Singleton<GraphTester>::getInstance(); gt->test(s); cout << "end test" << endl; MESH::Scene *ms = meshbuilder->build(s); X3D::Scene *ss = meshx3dbuilder->build(ms); saver->saveAs(ss, "myfile.x3d"); // removes all instances. Singleton<X3D::TemplateMeshBuilder<MESH::MyMeshData, MESH::MyVertexData, MESH::EdgeData, MESH::MyFaceData, true> >::removeInstance(); Singleton<MESH::TemplateX3DBuilder<MESH::MyMeshData, MESH::MyVertexData, MESH::EdgeData, MESH::MyFaceData, true> >::removeInstance(); Singleton<X3D::Loader>::removeInstance(); return 1; }