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.
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.
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.
#ifndef MYMESHDATA_H
#define MYMESHDATA_H
#include <X3DTK/MESH/scenegraph.h>
#include <X3DTK/simplifiedmeshscene.h>
namespace X3DTK {
namespace MESH {
class VertexDistanceData
{
public:
void setDistance(float distance);
inline float getDistance() const {return _distance;};
private:
float _distance;
};
#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
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;
void computeVerticesDistance(MyMesh *M);
}
typedef TemplateSimplifiedMeshScene<MESH::MyMeshData, MESH::MyVertexData, MESH::EdgeData, MESH::MyFaceData, true> MySimplifiedMeshScene;
}
#endif
#include "MyMeshData.h"
namespace X3DTK {
namespace MESH {
void VertexDistanceData::setDistance(float distance)
{
_distance = distance;
}
void computeVerticesDistance(MyMesh *M)
{
float maxDistance = 0.0f;
const MESH::MyMesh::MFVertex &vertices = M->getVertices();
for (MyMesh::MFVertex::const_iterator v = vertices.begin(); v != vertices.end(); ++v)
{
const SFPoint3f &P =(*v)->data().getPoint();
SFVec3f OP = P - SFPoint3f::null;
float distance = OP.norm();
(*v)->data().setDistance(distance);
if (distance > maxDistance)
maxDistance = distance;
}
for (MyMesh::MFVertex::const_iterator nv = vertices.begin(); nv != vertices.end(); ++nv)
(*nv)->data().setDistance((*nv)->data().getDistance()/maxDistance);
}
}
}
#ifndef MESH_BASICDRAWER_H
#define MESH_BASICDRAWER_H
#include <X3DTK/kernel.h>
#include "MyMeshData.h"
namespace X3DTK {
namespace MESH {
class BasicDrawer
{
public:
void drawFaces(MyMesh *M);
private:
SFColor getColor(float level) const;
};
}
}
#endif
#include "BasicDrawer.h"
#include <iostream>
using namespace std;
namespace X3DTK {
namespace MESH {
void BasicDrawer::drawFaces(MyMesh *M)
{
glEnable(GL_LIGHTING);
const MyMesh::MFFace &faces = M->getFaces();
for (MyMesh::MFFace::const_iterator f = faces.begin(), end = faces.end() ; f != end; ++f)
{
glBegin(GL_POLYGON);
const MySFFace::MFEdge &edges = (*f)->getEdges();
for (MySFFace::MFEdge::const_iterator e = edges.begin(), end = edges.end() ; e != end; ++e)
{
MySFVertex *v = (*e)->getFromVertex();
glNormal3fv(v->data().getNormalOfFace(*f));
glColor3fv(getColor(v->data().getDistance()));
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);
}
}
}
#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);
if (name.isEmpty())
return;
scene.load(name);
computeVerticesDistance(scene.getMesh());
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 Thu Jun 3 10:12:14 2004 for X3DToolKit by
1.3.6