meshTransformComputer

Introduction

This example is about how to write a template processor of the MESH scene graph. The MESH scene graph is based upon two template nodes which are 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:

MESH::TransformComputerStateVariables

We store the matrix stack to enable the transformation of the vertices in the world coordinates.

MESH::TransformComputerCoreVisitor

We define three enter functions for visited nodes. 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.

MESH::TransformComputer

This is the facade of the processor which aggregates the visitors of the different components.

Code

MESH_TransformComputerStateVariables.h

#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

MESH_TransformComputerStateVariables.inl

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();
}

}
}

MESH_TransformComputerCoreVisitor.h

#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

MESH_TransformComputerCoreVisitor.inl

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();
}

}
}

MESH_TransformComputer.h

#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

MESH_TransformComputer.inl

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();
  }  
}

}
}

main.cpp

#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;
}

Generated on Fri Jul 30 12:02:32 2004 for X3DToolKit by doxygen 1.3.6