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.X3DTK::X3D::Coordinate
to add a weight attribute per vertex. So we add a weight member of type X3DTK::MFFloat
.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
.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(); MyCoordinate(const MFVec3f &point, const MFFloat &weight); virtual SFAbstractNode clone() const; virtual ~MyCoordinate(); void setWeight(const MFFloat &weight); inline const MFFloat &getWeight() const {return _weight;}; virtual void load(const X3DFileElement *element); virtual SFString &write(SFString &output) const; protected: MyCoordinate(const MyCoordinate &C); private: MFFloat _weight; }; } } #endif
#include "X3D_MyCoordinate.h" #include <iostream> using namespace std; namespace X3DTK { namespace X3D { MyCoordinate::MyCoordinate() : Coordinate() { defineTypeName("MyCoordinate"); } MyCoordinate::MyCoordinate(const MFVec3f &point, const MFFloat &weight) : Coordinate(point), _weight(weight) { defineTypeName("MyCoordinate"); } MyCoordinate::MyCoordinate(const MyCoordinate &C) : Coordinate(C), _weight(C._weight) { } SFAbstractNode MyCoordinate::clone() const { return new MyCoordinate(*this); } MyCoordinate::~MyCoordinate() { } void MyCoordinate::setWeight(const MFFloat &weight) { _weight = weight; } void MyCoordinate::load(const X3DFileElement *element) { Coordinate::load(element); int index; index = element->getIndexAttribute("weight"); if (index != -1) _weight = MFFloat(element->getAttribute(index)); } SFString &MyCoordinate::write(SFString &output) const { Coordinate::write(output); if (!_weight.empty()) output += " weight=\"" + toSFString(_weight) + "\""; return output; } } }
#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. defineNode<MyCoordinate>(); } } }
#ifndef MESHMYMESHDATA_H #define MESHMYMESHDATA_H #include <X3DTK/MESH/scenegraph.h> namespace X3DTK { namespace MESH { // My vertex data structure containing the weight information. struct VertexWeightData { void setWeight(const SFFloat &weight) {_weight = weight;}; inline const SFFloat &getWeight() const {return _weight;}; private: SFFloat _weight; }; // My Mesh data aggregates. typedef clist<tlist<VertexPointData, tlist<VertexNormalData, tlist<VertexWeightData> > > > MyVertexData; typedef clist<tlist<FaceNormalData> > MyFaceData; typedef clist<tlist<MeshNormalData> > MyMeshData; } } #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 MeshBuilderRenderingVisitor<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 readOnly> MyMeshBuilderRenderingVisitor<MData, VData, EData, FData, readOnly>::MyMeshBuilderRenderingVisitor() : MeshBuilderRenderingVisitor<MData, VData, EData, FData, readOnly>() { defineEnterFunction(&MyMeshBuilderRenderingVisitor::enterMyCoordinate); } template<class MData, class VData, class EData, class FData, bool readOnly> void MyMeshBuilderRenderingVisitor<MData, VData, EData, FData, readOnly>::enterMyCoordinate(MyCoordinate *C) { MeshBuilderStateVariables *stateVariables = GraphTraversal::getInstanceOf<MeshBuilderStateVariables>(); MESH::Vertex<VData, EData, FData, readOnly> *MC = dynamic_cast<MESH::Vertex<VData, EData, FData, readOnly> *>(stateVariables->getNode(C)); if (MC != 0) { // Filling the Vertices. const MFFloat &weight = C->getWeight(); const typename MESH::Mesh<MData, VData, EData, FData, readOnly>::MFVertex &vertices = MC->getVertices(); // Test the optional presence of MESH::VertexPointData in VData. if (VData::template find<MESH::VertexWeightData>() && weight.size() >= vertices.size()) { MFFloat::const_iterator w = weight.begin(); // Accessing the MESH::VertexWeightData of VData. for (typename MESH::Mesh<MData, VData, EData, FData, readOnly>::MFVertex::const_iterator v = vertices.begin(); v != vertices.end(); ++v) { (*v)->template ogetData<MESH::VertexWeightData>().setWeight(*w); ++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 readOnly> class MyX3DBuilderCoreVisitor : public X3DBuilderCoreVisitor<MData, VData, EData, FData, readOnly> { public: MyX3DBuilderCoreVisitor(); static void enterVertex(Vertex<VData, EData, FData, readOnly> *V); }; } } #include "MESH_MyX3DBuilderCoreVisitor.inl" #endif
namespace X3DTK { namespace MESH { template<class MData, class VData, class EData, class FData, bool readOnly> MyX3DBuilderCoreVisitor<MData, VData, EData, FData, readOnly>::MyX3DBuilderCoreVisitor() { defineEnterFunction(&MyX3DBuilderCoreVisitor::enterVertex); } template<class MData, class VData, class EData, class FData, bool readOnly> void MyX3DBuilderCoreVisitor<MData, VData, EData, FData, readOnly>::enterVertex(Vertex<VData, EData, FData, readOnly> *V) { // StateVariables assignation. X3DBuilderStateVariables<MData, VData, EData, FData, readOnly> *stateVariables = GraphTraversal::getInstanceOf<X3DBuilderStateVariables<MData, VData, EData, FData, readOnly> >(); // Test of the presence of MESH::VertexWeightData in VData. if (!VData::template find<VertexWeightData>()) { // Call to super class function. X3DBuilderCoreVisitor<MData, VData, EData, FData, readOnly>::enterVertex(V); } else { // 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 Vertex<VData, EData, FData, readOnly>::MFVertex &vertices = V->getVertices(); // Test the optional presence of MESH::VertexPointData in VData. if (VData::template find<MESH::VertexPointData>()) { // Updating Coordinate. MFVec3f point; // Accessing the MESH::VertexPointData of VData. for (typename Vertex<VData, EData, FData, readOnly>::MFVertex::const_iterator v = vertices.begin(); v != vertices.end(); ++v) point.push_back(SFVec3f((*v)->template ogetData<MESH::VertexPointData>().getPoint())); NC->setPoint(point); } MFFloat weight; // Accessing the MESH::VertexWeightData of VData. if (VData::template find<MESH::VertexWeightData>()) { for (typename Vertex<VData, EData, FData, readOnly>::MFVertex::const_iterator v = vertices.begin(); v != vertices.end(); ++v) { weight.push_back((*v)->template ogetData<MESH::VertexWeightData>().getWeight()); } } 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 = X3DLoader::getInstanceOf<X3D::Loader>(); loader->setComponentCreator(new X3D::MyRenderingCreator()); // Instanciation of the new MeshBuilder. X3D::MeshBuilder<MESH::MyMeshData, MESH::MyVertexData, MESH::EdgeData, MESH::MyFaceData, true> *meshbuilder = X3DProcessor::getInstanceOf<X3D::MeshBuilder<MESH::MyMeshData, MESH::MyVertexData, MESH::EdgeData, MESH::MyFaceData, true> >(); meshbuilder->setComponentVisitor(new X3D::MyMeshBuilderRenderingVisitor<MESH::MyMeshData, MESH::MyVertexData, MESH::EdgeData, MESH::MyFaceData, true>()); // Instanciation of the new MeshX3DBuilder. MESH::X3DBuilder<MESH::MyMeshData, MESH::MyVertexData, MESH::EdgeData, MESH::MyFaceData, true> *meshx3dbuilder = X3DProcessor::getInstanceOf<MESH::X3DBuilder<MESH::MyMeshData, MESH::MyVertexData, MESH::EdgeData, MESH::MyFaceData, true> >(); meshx3dbuilder->setComponentVisitor(new MESH::MyX3DBuilderCoreVisitor<MESH::MyMeshData, MESH::MyVertexData, MESH::EdgeData, MESH::MyFaceData, true>()); // Instanciation of the SceneSaver. X3D::SceneSaver *saver = X3DProcessor::getInstanceOf<X3D::SceneSaver>(); // Loads the scene. X3D::Scene *s = loader->load(argv[1], false); cout << "s = " << s << endl; GraphTester *gt = X3DProcessor::getInstanceOf<GraphTester>(); 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. X3DProcessor::removeAllInstances(); X3DLoader::removeInstanceOf<X3D::Loader>(); return 1; }