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:
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.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 { // 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
#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); } } }
#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
#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); } } }
#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
#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(); }