X3DTK::MESH::TemplateMesh
and X3DTK::MESH::VertexSet
, allowing to write generic template processors that have these template parameters.
Here we write a simple X3DTK::X3DProcessor that traverses the MESH scene graph and prints some basic informations which are the matrix transformations to the world coordinates as well as the list of points (in the world coordinates) for a X3DTK::MESH::TemplateMesh
. For an example of processor creation see glNormalViewer.
This example illustrates simply the use of templates and the Mesh data mechanism. Indeed the flexibility of the library is that the user is free to choose the Mesh data and use any processor. At the instantiation of the template processor, the compilation will succeed depending on the presence of required data, allowing to have optional data. For more details about this mechanism, I recommend you to see ... or the meshExtension example.
Some important functions and classes:
enterTransform
and leaveX3DGroupingNode
pushes and pops the transform matrices. enterTemplateMesh
prints the informations. We test the presence of the VertexPointData
by a call to the template method find
of VData
. Here this data is optional and the code will compile if it is not present in VData
. For Visual Studio 6 users, notice the use of the preprocessor directive TEMPLATE_SPECIALIZATION_SUPPORTED. 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.#ifndef MESHTRANSFORMCOMPUTERGLOBALVARIABLES_H #define MESHTRANSFORMCOMPUTERGLOBALVARIABLES_H #include <X3DTK/kernel.h> #include <list> namespace X3DTK { namespace MESH { // State variables for the MeshTransformComputer processor. template<class MData, class VData, class EData, class FData, bool readOnly> class TransformComputerStateVariables : public StateVariables { public: TransformComputerStateVariables(); void init(); void finish(); void pushMatrix(const SFMatrix34f &transformation); void popMatrix(); SFMatrix34f getMatrix() const {return _matrixStack.front();}; private: std::list<SFMatrix34f> _matrixStack; }; } } #include "MESH_TransformComputerStateVariables.inl" #endif
namespace X3DTK { namespace MESH { template<class MData, class VData, class EData, class FData, bool RW> TransformComputerStateVariables<MData, VData, EData, FData, RW>::TransformComputerStateVariables() : StateVariables() { } template<class MData, class VData, class EData, class FData, bool RW> void TransformComputerStateVariables<MData, VData, EData, FData, RW>::init() { _matrixStack.push_front(SFMatrix34f::identity); } template<class MData, class VData, class EData, class FData, bool RW> void TransformComputerStateVariables<MData, VData, EData, FData, RW>::finish() { _matrixStack.clear(); } template<class MData, class VData, class EData, class FData, bool RW> void TransformComputerStateVariables<MData, VData, EData, FData, RW>::pushMatrix(const SFMatrix34f &transformation) { _matrixStack.push_front(_matrixStack.front()*transformation); } template<class MData, class VData, class EData, class FData, bool RW> void TransformComputerStateVariables<MData, VData, EData, FData, RW>::popMatrix() { _matrixStack.pop_front(); } } }
#ifndef MESHTRANSFORMCOMPUTERCOREVISITOR_H #define MESHTRANSFORMCOMPUTERCOREVISITOR_H #include "MESH_TransformComputerStateVariables.h" #include <X3DTK/MESH/scenegraph.h> #include <iostream> namespace X3DTK { namespace MESH { class X3DGroupingNode; class Transform; // Visitor for the Core component of the MeshTransformComputer processor. template<class MData, class VData, class EData, class FData, bool readOnly> class TransformComputerCoreVisitor : public CoreVisitor { public: TransformComputerCoreVisitor(); static void enterMesh(TemplateMesh<MData, VData, EData, FData, readOnly> *M); static void enterTransform(Transform *T); static void leaveX3DGroupingNode(X3DGroupingNode *N); }; } } #include "MESH_TransformComputerCoreVisitor.inl" #endif
namespace X3DTK { namespace MESH { template<class MData, class VData, class EData, class FData, bool RW> TransformComputerCoreVisitor<MData, VData, EData, FData, RW>::TransformComputerCoreVisitor() { // Enter functions. define(Recorder<TemplateMesh<MData, VData, EData, FData, RW> >::getEnterFunction(&TransformComputerCoreVisitor::enterMesh)); define(Recorder<Transform>::getEnterFunction(&TransformComputerCoreVisitor::enterTransform)); // Leave function define(Recorder<X3DGroupingNode>::getLeaveFunction(&TransformComputerCoreVisitor::leaveX3DGroupingNode)); } template<class MData, class VData, class EData, class FData, bool RW> void TransformComputerCoreVisitor<MData, VData, EData, FData, RW>::enterMesh(TemplateMesh<MData, VData, EData, FData, RW> *M) { // StateVariables assignation. TransformComputerStateVariables<MData, VData, EData, FData, RW> *stateVariables = Singleton<TransformComputerStateVariables<MData, VData, EData, FData, RW> >::getInstance(); std::cout << "enter Mesh" << std::endl; std::cout << "Transform:" << std::endl << stateVariables->getMatrix() << std::endl; std::cout << " number of vertices = " << M->getVertices().size() << std::endl; // Test the optional presence of MESH::VertexPointData in VData. #ifdef TEMPLATE_SPECIALIZATION_SUPPORTED if (VData::template find<MESH::VertexPointData>()) #endif { // Accessing the MESH::VertexPointData of VData. for (typename TemplateMesh<MData, VData, EData, FData, RW>::MFVertex::const_iterator it = M->getVertices().begin(); it != M->getVertices().end(); ++it) #ifdef TEMPLATE_SPECIALIZATION_SUPPORTED std::cout << (*it)->template ogetData<MESH::VertexPointData>().getPoint() << std::endl; #else std::cout << (*it)->data().getPoint() << std::endl; #endif } } template<class MData, class VData, class EData, class FData, bool RW> void TransformComputerCoreVisitor<MData, VData, EData, FData, RW>::enterTransform(Transform *T) { // Pushing the current transformation matrix on the stack. Singleton<TransformComputerStateVariables<MData, VData, EData, FData, RW> >::getInstance()->pushMatrix(T->getTransform()); } template<class MData, class VData, class EData, class FData, bool RW> void TransformComputerCoreVisitor<MData, VData, EData, FData, RW>::leaveX3DGroupingNode(X3DGroupingNode *) { // Poping the current transformation matrix of the stack. Singleton<TransformComputerStateVariables<MData, VData, EData, FData, RW> >::getInstance()->popMatrix(); } } }
#ifndef MESHTRANSFORMCOMPUTER_H #define MESHTRANSFORMCOMPUTER_H #include "MESH_TransformComputerStateVariables.h" #include "MESH_TransformComputerCoreVisitor.h" #include <X3DTK/kernel.h> #include <X3DTK/MESH/scenegraph.h> namespace X3DTK { namespace MESH { // MeshTransformComputer processor. template<class MData, class VData, class EData, class FData, bool readOnly> class TransformComputer : public X3DOnePassProcessor { public: TransformComputer(); virtual ~TransformComputer(); virtual void print(SFNode N); }; } } #include "MESH_TransformComputer.inl" #endif
namespace X3DTK { namespace MESH { template<class MData, class VData, class EData, class FData, bool RW> TransformComputer<MData, VData, EData, FData, RW>::TransformComputer() { setGraphTraversal(new DFSGraphTraversal()); getGraphTraversal()->setComponentVisitor(new TransformComputerCoreVisitor<MData, VData, EData, FData, RW>()); } template<class MData, class VData, class EData, class FData, bool RW> TransformComputer<MData, VData, EData, FData, RW>::~TransformComputer() { Singleton<TransformComputerStateVariables<MData, VData, EData, FData, RW> >::removeInstance(); } template<class MData, class VData, class EData, class FData, bool RW> void TransformComputer<MData, VData, EData, FData, RW>::print(SFNode N) { // Testing the presence of MESH::VertexPointData #ifdef TEMPLATE_SPECIALIZATION_SUPPORTED if (VData::template find<MESH::VertexPointData>()) #endif { Singleton<TransformComputerStateVariables<MData, VData, EData, FData, RW> >::getInstance()->init(); traverse(N); Singleton<TransformComputerStateVariables<MData, VData, EData, FData, RW> >::getInstance()->finish(); } } } }
#include "MESH_TransformComputer.h" #include <X3DTK/X3D/scenegraph.h> #include <X3DTK/X3D/meshbuilder.h> #include <iostream> using namespace X3DTK; using namespace std; int main(int argc, char *argv[]) { if (argc <= 1) { cerr << "usage: meshtransformcomputer input" << endl; exit(0); } // DefaultLoader to load the default X3D Nodes. X3D::Loader *loader = Singleton<X3D::Loader>::getInstance(); // Instanciation of the new MeshBuilder. X3D::MeshBuilder *meshbuilder = Singleton<X3D::MeshBuilder>::getInstance(); // Instanciation of the new MeshTransformComputer. MESH::TransformComputer<MESH::MeshData, MESH::VertexData, MESH::EdgeData, MESH::FaceData, true> *mtc = Singleton<MESH::TransformComputer<MESH::MeshData, MESH::VertexData, MESH::EdgeData, MESH::FaceData, true> >::getInstance(); // Loads the scene. X3D::Scene *s = loader->load(argv[1], false); MESH::Scene *ms = meshbuilder->build(s); // Prints the scene. mtc->print(ms); // removes all instances. Singleton<X3D::MeshBuilder>::removeInstance(); Singleton<MESH::TransformComputer<MESH::MeshData, MESH::VertexData, MESH::EdgeData, MESH::FaceData, true> >::removeInstance(); Singleton<X3D::Loader>::removeInstance(); return 1; }