mySimplifiedMeshViewer

Introduction

This example shows how to extend the X3DTK::SimplifiedMeshScene class by adding an attribute to the vertex X3DTK::MESH::SFVertex entity. We read the simplified MESH scene graph and draw the faces by drawing false color vertices. You can see the example simplifiedMeshViewer.

Some important functions and classes:

MyMeshData

We define a new attribute called X3DTK::MESH::VertexDistanceData. To simplify the syntax of the use of new objects, we use typedef to avoid having very long type names. We define a small function that computes the distance attribute of the vertex from the other attributes.

BasicDrawer

We implement a small drawer which draws the scene loaded by the X3DTK::SimplifiedMeshScene. X3DTK::MESH::BasicDrawer draws the false color faces. It provides an example of requests that can be done to the Mesh node.

Code

MyMeshData.h

#ifndef MYMESHDATA_H
#define MYMESHDATA_H

#include <X3DTK/MESH/scenegraph.h>
#include <X3DTK/simplifiedmeshscene.h>

namespace X3DTK {
namespace MESH {

// My vertex data structure containing the weight information.

class VertexDistanceData
{
public:
  void setDistance(float distance);
  inline float getDistance() const {return _distance;};
  
private:
  float _distance;  
};

// My Mesh data aggregates using recursive typelists.
// Typedefs are useful to simplify template syntax.
#ifdef TEMPLATE_SPECIALIZATION_SUPPORTED

typedef clist<tlist<VertexPointData, tlist<VertexNormalData, tlist<VertexColorData, tlist<VertexDistanceData> > > > > MyVertexData;
typedef clist<tlist<FaceNormalData, tlist<FaceColorData> > > MyFaceData;
typedef clist<tlist<MeshNormalData, tlist<MeshColorData> > > MyMeshData;

#else

class MyVertexData : public VertexData, public VertexDistanceData {};
class MyFaceData : public FaceData {};
class MyMeshData : public MeshData {};

#endif

// My MESH entities.

typedef TemplateMesh<MESH::MyMeshData, MESH::MyVertexData, MESH::EdgeData, MESH::MyFaceData, true> MyMesh;
typedef TemplateVertex<MESH::MyMeshData, MESH::MyVertexData, MESH::EdgeData, MESH::MyFaceData, true> MyVertex;
typedef SFTemplateVertex<MESH::MyMeshData, MESH::MyVertexData, MESH::EdgeData, MESH::MyFaceData, true> MySFVertex;
typedef SFTemplateEdge<MESH::MyMeshData, MESH::MyVertexData, MESH::EdgeData, MESH::MyFaceData, true> MySFEdge;
typedef SFTemplateFace<MESH::MyMeshData, MESH::MyVertexData, MESH::EdgeData, MESH::MyFaceData, true> MySFFace;

// function computing the norm attribute of the vertices
void computeVerticesDistance(MyMesh *M);

}

// My SimpleMeshScene

typedef TemplateSimplifiedMeshScene<MESH::MyMeshData, MESH::MyVertexData, MESH::EdgeData, MESH::MyFaceData, true> MySimplifiedMeshScene;

}

#endif

MyMeshData.h

#include "MyMeshData.h"

namespace X3DTK {
namespace MESH {

void VertexDistanceData::setDistance(float distance) 
{
  _distance = distance;
}

void computeVerticesDistance(MyMesh *M)
{
  // computing distance to (0, 0, 0) point.
  float maxDistance = 0.0f;
  // Getting the vertices.
  const MESH::MyMesh::MFVertex &vertices = M->getVertices();
  // Iterating the vertices.
  for (MyMesh::MFVertex::const_iterator v = vertices.begin(); v != vertices.end(); ++v)
  {
    // Getting the point.
    const SFPoint3f &P =(*v)->data().getPoint();
    SFVec3f OP = P - SFPoint3f::null;
    float distance = OP.norm(); 
    
    // Setting the distance.
    (*v)->data().setDistance(distance);
    
    // Updating the maximum distance.
    if (distance > maxDistance)
      maxDistance = distance;
  }
  
  // normalizing in [0, 1]
  for (MyMesh::MFVertex::const_iterator nv = vertices.begin(); nv != vertices.end(); ++nv)
    (*nv)->data().setDistance((*nv)->data().getDistance()/maxDistance);
}

}
}

BasicDrawer.h

#ifndef MESH_BASICDRAWER_H
#define MESH_BASICDRAWER_H

#include <X3DTK/kernel.h>
#include "MyMeshData.h"

namespace X3DTK {
namespace MESH {

// Processor drawing the mesh from the Mesh scene graph.

class BasicDrawer
{
public:
  void drawFaces(MyMesh *M);

private:
  SFColor getColor(float level) const;
};

}
}

#endif

BasicDrawer.cpp

#include "BasicDrawer.h"

#include <iostream>

using namespace std;

namespace X3DTK {
namespace MESH {

void BasicDrawer::drawFaces(MyMesh *M)
{
  glEnable(GL_LIGHTING);
  
  // Getting the faces.
  const MyMesh::MFFace &faces = M->getFaces();
  // iterating the faces. 
  for (MyMesh::MFFace::const_iterator f = faces.begin(), end = faces.end() ; f != end; ++f)
  {
    glBegin(GL_POLYGON);
    // getting the edges of the face.
    const MySFFace::MFEdge &edges = (*f)->getEdges();
    // iterating the edges to iterate the vertices of the face.
    for (MySFFace::MFEdge::const_iterator e = edges.begin(), end = edges.end() ; e != end; ++e)
    {
      // Getting the vertex.
      MySFVertex *v = (*e)->getFromVertex();
      // setting the normal of the vertex.
      glNormal3fv(v->data().getNormalOfFace(*f));

      // setting the color of the vertex depending on the distance.
      glColor3fv(getColor(v->data().getDistance()));
      
      // Getting the point data.   
      glVertex3fv(v->data().getPoint());
    }
    glEnd();
  }
}

SFColor BasicDrawer::getColor(float level) const
{
  float r, g, b;
  float f, q, V, S, t, v;
  int i;
  
  v = 4.0f*(1.0f - level);
  i = (int)floorf(v);
  f = v - i;
  q = 1.0f - f;
  t = f;
  V = 1.0f;
  S = 0.0f;

  switch(i)
  {
    case 0 : r = V;  g = t;  b = S; break;
    case 1 : r = q;  g = V;  b = S; break;
    case 2 : r = S;  g = V;  b = t;  break;
    case 3 : r = S;  g = q;  b = V;  break;
    case 4 : r = t;  g = S;  b = V;  break;
    default : r = 0.0f;  g = 0.0f;  b = 0.0f;  break;
  }
  
  return SFColor(r, g, b);
}

}
}

Viewer.h

#ifndef VIEWER_H
#define VIEWER_H

#include <QGLViewer/qglviewer.h>
#include "MyMeshData.h"
#include "BasicDrawer.h"

// Viewer for the meshViewer.

class Viewer : public QGLViewer
{
public:
  Viewer();
  
protected :
  void loadFile();
  void keyPressEvent(QKeyEvent *e);
  void init();
  void draw();
  QString helpString() const;
  void help() const;
  
private:
  X3DTK::MySimplifiedMeshScene scene;
  X3DTK::MESH::BasicDrawer drawer;
};

#endif

Viewer.cpp

#include "Viewer.h"
#include <math.h>
#include <iostream>
#include <qfiledialog.h>
#include <qmessagebox.h> 

using namespace std;
using namespace X3DTK::MESH;

Viewer::Viewer()
{
}

void Viewer::keyPressEvent(QKeyEvent *e)
{
  switch (e->key())
  {
    case Qt::Key_L : loadFile(); break;
    default        : QGLViewer::keyPressEvent(e);
  }
  updateGL();  
}

void Viewer::loadFile()
{
  QString name = QFileDialog::getOpenFileName("", "X3D files (*.x3d *.X3D);;All files (*)", this);
  
  // In case of Cancel
  if (name.isEmpty())
    return;

  // Loads the file name.
  scene.load(name);
  computeVerticesDistance(scene.getMesh());
  
  // QGLViewer settings.
  setSceneBoundingBox(scene.getBBoxMin(), scene.getBBoxMax());
  showEntireScene(); 
}

void Viewer::init()
{
  glPolygonOffset(-2.0, -2.0);
#ifdef GL_RESCALE_NORMAL
  glEnable(GL_RESCALE_NORMAL);
#endif

  loadFile();
}

void Viewer::draw()
{
  if (scene.getMesh() == 0) return;
  
  drawer.drawFaces(scene.getMesh());
}

QString Viewer::helpString() const
{
  QString message("");
  
  message += "<b>L</b>" + QString(" loads a new file<br>");
  
  message += QGLViewer::helpString();
  
  return message;
}

void Viewer::help() const
{
  QMessageBox *mb = new QMessageBox("help", helpString(), QMessageBox::NoIcon,QMessageBox::Ok | QMessageBox::Default, QMessageBox::NoButton,QMessageBox::NoButton, NULL, "Help", false,Qt::WStyle_DialogBorder | Qt::WType_Dialog | Qt::WDestructiveClose);
  mb->show();
}

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