We want to display and select the different entities of a MESH scene graph. We define a processor called X3DTK::MESH::Drawer
that displays the content of the Mesh structure in order to display the 3D model and to enable selection. The different entities are the vertices, the edges and the faces.
The example is mainly based upon the creation of a X3DTK::X3DProcessor
so you can see glNormalViewer before reading this example.
X3DTK::MESH::Drawer
traversal, we store the variables necessary to the display for the GL selection mechanism.X3DTK::MESH::Drawer
processor, we draw the different mesh entities and execute the GL commands relative to selection.X3DTK::MESH::Drawer
and the X3DTK::Viewer
, the events being emitted by the X3DTK::Viewer
and treated by the X3DTK::MESH::Drawer
.QGLViewer
, redefining particularly the draw and select methods.#ifndef MESH_DRAWER_GLOBALVARIABLES_H #define MESH_DRAWER_GLOBALVARIABLES_H #include <X3DTK/MESH/scenegraph.h> #include <list> #include <vector> namespace X3DTK { namespace MESH { // State variables for the MESH::Drawer processor. class DrawerStateVariables : public StateVariables { public: DrawerStateVariables(); void initTraversal(); void finishTraversal(); void pushMatrix(const SFMatrix34f &transformation); void popMatrix(); int getCurrentMeshId(); void storeMesh(DefMesh *mesh); inline const DefMesh *getMesh(int i) const {return _meshVector[i];}; inline SFMatrix34f getMatrix(int i) const {return _matrixVector[i];}; inline void setSelectionMode(bool selectionMode) {_selectionMode = selectionMode;}; inline bool getSelectionMode() const {return _selectionMode;}; void setPrimitiveType(int primitiveType) {_primitiveType = primitiveType;}; inline int getPrimitiveType() const {return _primitiveType;}; void changeOneColorPerMesh() {_oneColorPerMesh = !_oneColorPerMesh;}; inline bool getOneColorPerMesh() const {return _oneColorPerMesh;}; private: std::list<SFMatrix34f> _matrixStack; std::vector<SFMatrix34f> _matrixVector; std::vector<DefMesh *> _meshVector; bool _selectionMode; bool _oneColorPerMesh; int _primitiveType; }; } } #endif
#include "MESH_DrawerStateVariables.h" #include <qglobal.h> namespace X3DTK { namespace MESH { DrawerStateVariables::DrawerStateVariables() : StateVariables(), _selectionMode(false), _oneColorPerMesh(true), _primitiveType(1) {} void DrawerStateVariables::initTraversal() { _matrixStack.push_front(SFMatrix34f::identity); _matrixVector.clear(); _meshVector.clear(); } void DrawerStateVariables::finishTraversal() { _matrixStack.pop_front(); if (_matrixStack.size() != 0) { qWarning("Non empty matrix stack at the end of Drawer traversal"); _matrixStack.clear(); } } void DrawerStateVariables::pushMatrix(const SFMatrix34f &transformation) { _matrixStack.push_front(_matrixStack.front()*transformation); } void DrawerStateVariables::popMatrix() { _matrixStack.pop_front(); } void DrawerStateVariables::storeMesh(DefMesh* mesh) { _matrixVector.push_back(_matrixStack.front()); _meshVector.push_back(mesh); } int DrawerStateVariables::getCurrentMeshId() { return _matrixVector.size() - 1; } } }
#ifndef MESH_DRAWER_COREVISITOR_H #define MESH_DRAWER_COREVISITOR_H #include <X3DTK/MESH/scenegraph.h> #include "MESH_DrawerStateVariables.h" namespace X3DTK { namespace MESH { class Transform; // Visitor for the Core component of the Drawer processor. class DrawerCoreVisitor : public CoreVisitor { public: DrawerCoreVisitor(); static void enterMesh(DefMesh *M); static void enterTransform(Transform *T); static void leaveTransform(Transform *T); }; } } #endif
#include "MESH_DrawerCoreVisitor.h" #include <GL/gl.h> #include <iostream> using namespace std; namespace X3DTK { namespace MESH { DrawerCoreVisitor::DrawerCoreVisitor() { // Enter and leave functions. defineEnterFunction(&DrawerCoreVisitor::enterTransform); defineEnterFunction(&DrawerCoreVisitor::enterMesh); defineLeaveFunction(&DrawerCoreVisitor::leaveTransform); } void DrawerCoreVisitor::enterTransform(Transform *T) { glMatrixMode(GL_MODELVIEW); GraphTraversal::getInstanceOf<DrawerStateVariables>()->pushMatrix(T->getTransform()); glPushMatrix(); glMultMatrixf(T->getTransform().toFloat16()); } void DrawerCoreVisitor::leaveTransform(Transform *) { glMatrixMode(GL_MODELVIEW); GraphTraversal::getInstanceOf<DrawerStateVariables>()->popMatrix(); glPopMatrix(); } void DrawerCoreVisitor::enterMesh(DefMesh *M) { // StateVariables assignation. DrawerStateVariables *stateVariables = GraphTraversal::getInstanceOf<DrawerStateVariables>(); stateVariables->storeMesh(M); int meshId = stateVariables->getCurrentMeshId(); if (stateVariables->getSelectionMode()) glPushName(meshId); bool colorPerVertex = M->data().getColorPerVertex(); bool normalPerVertex = M->data().getNormalPerVertex(); switch (stateVariables->getPrimitiveType()) { case 1 : // MeshViewer::VERTICES { glColor3f(1.0, 0.9, 0.8); glPointSize(6.0); const DefMesh::MFVertex& vertices = M->getVertices(); if (stateVariables->getSelectionMode()) { glPushName(1); for (DefMesh::MFVertex::const_iterator v = vertices.begin(), end = vertices.end() ; v != end; ++v) { glPushName((*v)->getIndex()); SFPoint3f point = (*v)->data().getPoint(); glRasterPos3fv(point.f_data()); glPopName(); } glPopName(); } else { glBegin(GL_POINTS); for (DefMesh::MFVertex::const_iterator v = vertices.begin(), end = vertices.end() ; v != end; ++v) { SFPoint3f point = (*v)->data().getPoint(); glVertex3fv(point.f_data()); } glEnd(); } break; } case 2 : // MeshViewer::EDGES { glLineWidth(2.0); const DefMesh::MFEdge &edges = M->getEdges(); if (stateVariables->getSelectionMode()) glPushName(2); int index = 0; for (DefMesh::MFEdge::const_iterator e = edges.begin(), end = edges.end() ; e != end; ++e) { if (stateVariables->getSelectionMode()) glPushName(index++); if ((*e)->isBoundary()) glColor3f(0.3, 0.3, 0.9); else glColor3f(0.7, 0.7, 0.7); // Normal DefMesh::SFFace* firstFace = (*((*e)->getLeftFaces().begin())); if (!firstFace) firstFace = (*((*e)->getRightFaces().begin())); SFVec3f normal; if (normalPerVertex) normal = (*e)->getFromVertex()->data().getNormalOfFace(firstFace); else normal = firstFace->data().getNormal(); glNormal3fv(normal.f_data()); glBegin(GL_LINES); SFPoint3f point = (*e)->getFromVertex()->data().getPoint(); glVertex3fv(point.f_data()); point = (*e)->getToVertex()->data().getPoint(); glVertex3fv(point.f_data()); glEnd(); if (stateVariables->getSelectionMode()) glPopName(); } if (stateVariables->getSelectionMode()) glPopName(); break; } case 3 : // MeshViewer::FACES { const DefMesh::MFFace& faces = M->getFaces(); if (stateVariables->getSelectionMode()) glPushName(3); if (stateVariables->getOneColorPerMesh()) { SFColorRGBA color = SFColorRGBA(0.1*((3+meshId*3)%10), 0.1*((5+meshId*4)%10), 0.1*((7+meshId*5)%10), 1.0); glColor4f(color.r, color.g, color.b, color.a); } for (DefMesh::MFFace::const_iterator f = faces.begin(), end = faces.end() ; f != end; ++f) { if (!normalPerVertex) { SFVec3f normal = (*f)->data().getNormal(); glNormal3fv(normal.f_data()); } if ((!colorPerVertex) && (!stateVariables->getOneColorPerMesh())) { SFColorRGBA color = (*f)->data().getColor(); glColor4f(color.r, color.g, color.b, color.a); } if (stateVariables->getSelectionMode()) glPushName((*f)->getIndex()); glBegin(GL_POLYGON); const DefSFFace::MFEdge& edges = (*f)->getEdges(); for (DefMesh::MFEdge::const_iterator e = edges.begin(), end = edges.end() ; e != end; ++e) { if (normalPerVertex) { SFVec3f normal = (*e)->getFromVertex()->data().getNormalOfFace(*f); glNormal3fv(normal.f_data()); } if ((colorPerVertex) && (!stateVariables->getOneColorPerMesh())) { SFColorRGBA color = (*e)->getFromVertex()->data().getColorOfFace(*f); glColor4f(color.r, color.g, color.b, color.a); } SFPoint3f point = (*e)->getFromVertex()->data().getPoint(); glVertex3fv(point.f_data()); } glEnd(); if (stateVariables->getSelectionMode()) glPopName(); } if (stateVariables->getSelectionMode()) glPopName(); break; } } if (stateVariables->getSelectionMode()) glPopName(); } } }
#ifndef MESH_DRAWER_H #define MESH_DRAWER_H #include "MESH_DrawerStateVariables.h" #include <X3DTK/kernel.h> #include <X3DTK/MESH/scenegraph.h> namespace X3DTK { enum SelectedType {NOTHING, VERTICES, EDGES, FACES}; namespace MESH { // Processor drawing the mesh from the Mesh scene graph. class Drawer : public X3DOnePassProcessor { public: Drawer(); virtual ~Drawer(); void changeDrawPoints(); void changeDrawEdges(); void changeDrawFaces(); inline void changeOneColorPerMesh() {stateVariables->changeOneColorPerMesh();}; void setSelectedType(SelectedType selectedType); void setSelectedMesh(int selectedMesh); void setSelectedId(int selectedId); inline SelectedType getSelectedType() const {return selectedType;}; inline int getSelectedMesh() const {return selectedMesh;}; inline int getSelectedId() const {return selectedId;}; void drawMesh(X3DNode *N, bool selection = false); void drawSelected(); protected: DrawerStateVariables *stateVariables; bool drawPoints, drawEdges, drawFaces; SelectedType selectedType; int selectedMesh; int selectedId; // Draw methods. void drawVertex(const DefSFVertex *vertex); void drawEdge(DefMesh::SFEdge *edge); void drawFace(const DefMesh::SFFace *face); }; } } #endif
#include "MESH_Drawer.h" #include "MESH_DrawerCoreVisitor.h" #include <iostream> using namespace std; namespace X3DTK { namespace MESH { Drawer::Drawer() : X3DOnePassProcessor(), drawPoints(false), drawEdges(true), drawFaces(true), selectedType(NOTHING) { stateVariables = GraphTraversal::getInstanceOf<DrawerStateVariables>(); graphTraversal = new DFSGraphTraversal(); graphTraversal->setComponentVisitor(new DrawerCoreVisitor()); } Drawer::~Drawer() { GraphTraversal::removeInstanceOf<DrawerStateVariables>(); delete graphTraversal; } void Drawer::changeDrawPoints() { drawPoints = !drawPoints; } void Drawer::changeDrawEdges() { drawEdges = !drawEdges; } void Drawer::changeDrawFaces() { drawFaces = !drawFaces; } void Drawer::setSelectedType(SelectedType selectedType) { this->selectedType = selectedType; } void Drawer::setSelectedMesh(int selectedMesh) { this->selectedMesh = selectedMesh; } void Drawer::setSelectedId(int selectedId) { this->selectedId = selectedId; } void Drawer::drawMesh(X3DNode *N, bool selection) { stateVariables->setSelectionMode(selection); if (selection || drawPoints) { stateVariables->setPrimitiveType(VERTICES); stateVariables->initTraversal(); graphTraversal->traverse(N); stateVariables->finishTraversal(); } if (selection || drawEdges) { stateVariables->setPrimitiveType(EDGES); stateVariables->initTraversal(); graphTraversal->traverse(N); stateVariables->finishTraversal(); } if (selection || drawFaces) { stateVariables->setPrimitiveType(FACES); stateVariables->initTraversal(); graphTraversal->traverse(N); stateVariables->finishTraversal(); } } void Drawer::drawSelected() { if (selectedType == NOTHING) return; glPushMatrix(); glMultMatrixf(stateVariables->getMatrix(selectedMesh).toFloat16()); const DefMesh *mesh = stateVariables->getMesh(selectedMesh); bool normalPerVertex = mesh->data().getNormalPerVertex(); glEnable(GL_POLYGON_OFFSET_FILL); #ifdef GL_POLYGON_OFFSET_LINES glEnable(GL_POLYGON_OFFSET_LINES); #endif glPointSize(15.0); glLineWidth(8.0); switch (selectedType) { case NOTHING : break; case VERTICES : { glPointSize(25.0); DefSFVertex *vertex = (mesh->getVertices())[selectedId]; const DefSFVertex::MFFace &faces = vertex->getFaces(); // Normal DefSFFace *firstFace = (*(faces.begin())); SFVec3f normal; if (normalPerVertex) normal = vertex->data().getNormalOfFace(firstFace); else normal = firstFace->data().getNormal(); glNormal3fv(normal.f_data()); glColor3f(1.0, 1.0, 0.0); drawVertex(vertex); glColor3f(0.0, 0.8, 0.0); const DefSFVertex::MFEdge &edges = vertex->getEdges(); for (DefSFVertex::MFEdge::const_iterator e = edges.begin(), end = edges.end() ; e != end; ++e) drawEdge(*e); glColor3f(0.7, 0.9, 0.7); for (DefSFVertex::MFFace::const_iterator f = faces.begin(), end = faces.end() ; f != end; ++f) drawFace(*f); break; } case EDGES : { glLineWidth(15.0); DefSFEdge *edge = (mesh->getEdges())[selectedId]; // Normal DefSFFace *firstFace = (*(edge->getLeftFaces().begin())); if (!firstFace) firstFace = (*(edge->getRightFaces().begin())); SFVec3f normal; if (normalPerVertex) normal = edge->getFromVertex()->data().getNormalOfFace(firstFace); else normal = firstFace->data().getNormal(); glNormal3fv(normal.f_data()); glColor3f(1.0, 1.0, 0.0); drawEdge(edge); glColor3f(0.0, 0.8, 0.0); drawVertex(edge->getFromVertex()); drawVertex(edge->getToVertex()); glColor3f(0.9, 0.7, 0.7); const DefSFEdge::MFFace &lfaces = edge->getLeftFaces(); for (DefSFEdge::MFFace::const_iterator f = lfaces.begin(), end = lfaces.end() ; f != end; ++f) drawFace(*f); glColor3f(0.7, 0.9, 0.7); const DefSFEdge::MFFace &rfaces = edge->getRightFaces(); for (DefSFEdge::MFFace::const_iterator f = rfaces.begin(), end = rfaces.end() ; f != end; ++f) drawFace(*f); break; } case FACES : { DefSFFace *face = (mesh->getFaces())[selectedId]; const DefSFFace::MFEdge &edges = face->getEdges(); // Normal DefSFEdge *firstEdge = (*(edges.begin())); SFVec3f normal; if (normalPerVertex) normal = firstEdge->getFromVertex()->data().getNormalOfFace(face); else normal = face->data().getNormal(); glNormal3fv(normal.f_data()); glColor3f(1.0, 1.0, 0.0); drawFace(face); for (DefSFFace::MFEdge::const_iterator e = edges.begin(), end = edges.end() ; e != end; ++e) { glColor3f(0.0, 0.8, 0.0); drawEdge(*e); glColor3f(0.7, 0.7, 0.7); drawVertex((*e)->getFromVertex()); } break; } } glDisable(GL_POLYGON_OFFSET_FILL); #ifdef GL_POLYGON_OFFSET_LINES glDisable(GL_POLYGON_OFFSET_LINES); #endif glPopMatrix(); } void Drawer::drawVertex(const DefMesh::SFVertex *vertex) { glBegin(GL_POINTS); SFPoint3f point = vertex->data().getPoint(); glVertex3fv(point.f_data()); glEnd(); } void Drawer::drawEdge(DefMesh::SFEdge *edge) { glPolygonOffset(-100, -100); glDisable(GL_LIGHTING); glBegin(GL_LINES); SFPoint3f point = edge->getFromVertex()->data().getPoint(); glVertex3fv(point.f_data()); point = edge->getToVertex()->data().getPoint(); glVertex3fv(point.f_data()); glEnd(); glEnable(GL_LIGHTING); glPolygonOffset(-2, -2); } void Drawer::drawFace(const DefSFFace *face) { const DefSFFace::MFEdge &edges = face->getEdges(); glBegin(GL_POLYGON); for (DefSFFace::MFEdge::const_iterator e = edges.begin(), end = edges.end() ; e != end; ++e) { SFPoint3f point = (*e)->getFromVertex()->data().getPoint(); glVertex3fv(point.f_data()); } glEnd(); } } }
#ifndef SIMPLEMESHGLSCENE_H #define SIMPLEMESHGLSCENE_H #include "MESH_Drawer.h" #include <X3DTK/kernel.h> #include <X3DTK/X3D/meshbuilder.h> #include <X3DTK/MESH/normalsupdater.h> namespace X3DTK { class X3DMemReleaser; namespace X3D { class Scene; class Loader; class X3DBBoxUpdater; } namespace MESH { class Scene; class Drawer; } // Class defining a facade to allow an easy load and display of an X3D scene. class SimpleMeshGLScene { public: SimpleMeshGLScene(); virtual ~SimpleMeshGLScene(); virtual void load(const char *file); virtual void drawMesh(bool selection = false); virtual void drawSelected(); inline SFVec3f getBBoxMin() const {return min;}; inline SFVec3f getBBoxMax() const {return max;}; void release(); inline void changeDrawPoints() {_drawer->changeDrawPoints();}; inline void changeDrawEdges() {_drawer->changeDrawEdges();}; inline void changeDrawFaces() {_drawer->changeDrawFaces();}; inline void changeOneColorPerMesh() {_drawer->changeOneColorPerMesh();}; inline void setSelectedType(SelectedType selectedType) {_drawer->setSelectedType(selectedType);}; inline void setSelectedMesh(int selectedMesh) {_drawer->setSelectedMesh(selectedMesh);}; inline void setSelectedId(int selectedId) {_drawer->setSelectedId(selectedId);}; inline SelectedType getSelectedType() const {return _drawer->getSelectedType();}; inline int getSelectedMesh() const {return _drawer->getSelectedMesh();}; inline int getSelectedId() const {return _drawer->getSelectedId();}; protected: X3D::Scene *scene; MESH::Scene *meshScene; SFVec3f min; SFVec3f max; void loadFile(const char *file); void computeBBox(); void buildMeshScene(); private: X3D::Loader *_loader; X3D::X3DBBoxUpdater *_bboxupdater; X3D::DefMeshBuilder *_builder; MESH::DefNormalsUpdater *_normalUpdater; MESH::Drawer *_drawer; X3DMemReleaser *_releaser; }; } #endif
#include "SimpleMeshGLScene.h" #include <X3DTK/X3D/scenegraph.h> #include <X3DTK/X3D/bboxupdater.h> #include <X3DTK/memreleaser.h> #include <X3DTK/MESH/scenegraph.h> #include <iostream> #include <time.h> using namespace std; namespace X3DTK { SimpleMeshGLScene::SimpleMeshGLScene() : scene(0), meshScene(0) { _loader = X3DLoader::getInstanceOf<X3D::Loader>(); _bboxupdater = X3DProcessor::getInstanceOf<X3D::BBoxUpdater>(); _builder = X3DProcessor::getInstanceOf<X3D::DefMeshBuilder>(); _drawer = X3DProcessor::getInstanceOf<MESH::Drawer>(); _normalUpdater = X3DProcessor::getInstanceOf<MESH::DefNormalsUpdater>(); _releaser = X3DProcessor::getInstanceOf<MemReleaser>(); } SimpleMeshGLScene::~SimpleMeshGLScene() { _releaser->release(scene); _releaser->release(meshScene); scene = 0; meshScene = 0; } void SimpleMeshGLScene::load(const char *file) { loadFile(file); computeBBox(); buildMeshScene(); } void SimpleMeshGLScene::drawMesh(bool selection) { _drawer->drawMesh(meshScene, selection); } void SimpleMeshGLScene::drawSelected() { _drawer->drawSelected(); } void SimpleMeshGLScene::release() { _releaser->release(scene); _releaser->release(meshScene); scene = 0; meshScene = 0; } void SimpleMeshGLScene::loadFile(const char *file) { _releaser->release(scene); _releaser->release(meshScene); scene = 0; meshScene = 0; scene = _loader->load(file, true); } void SimpleMeshGLScene::computeBBox() { _bboxupdater->update(scene, true); if (scene != 0) { SFVec3f center = scene->getBBoxCenter(); SFVec3f size = scene->getBBoxSize(); SFVec3f A = center + 0.5f*size; SFVec3f B = center - 0.5f*size; if (A.x < B.x) { min.x = A.x; max.x = B.x; } else { min.x = B.x; max.x = A.x; } if (A.y < B.y) { min.y = A.y; max.y = B.y; } else { min.y = B.y; max.y = A.y; } if (A.z < B.z) { min.z = A.z; max.z = B.z; } else { min.z = B.z; max.z = A.z; } } } void SimpleMeshGLScene::buildMeshScene() { meshScene = _builder->build(scene); _normalUpdater->updateNormals(meshScene); } }
#ifndef VIEWER_H #define VIEWER_H #include <QGLViewer/qglviewer.h> #include "SimpleMeshGLScene.h" // Viewer for the meshViewer. class Viewer : public QGLViewer { public: Viewer(); ~Viewer(); protected : void loadFile(); void keyPressEvent(QKeyEvent *e); void init(); void draw(); void about(); QString helpString() const; void select(const QMouseEvent *e); void help() const; private: X3DTK::SimpleMeshGLScene scene; X3DTK::BBox BB; // Events dispatched to the scene. inline void toggleDrawPoints() {scene.changeDrawPoints();}; inline void toggleDrawEdges() {scene.changeDrawEdges();}; inline void toggleDrawFaces() {scene.changeDrawFaces();}; inline void toggleOneColorPerMesh() {scene.changeOneColorPerMesh();}; }; #endif
#include "Viewer.h" #include <math.h> #include <iostream> #include <qfiledialog.h> #include <qmessagebox.h> using namespace X3DTK; using namespace std; Viewer::Viewer() { } Viewer::~Viewer() { scene.release(); } void Viewer::keyPressEvent(QKeyEvent *e) { switch (e->key()) { case Qt::Key_L : loadFile(); updateGL(); break; case Qt::Key_V : toggleDrawPoints(); updateGL(); break; case Qt::Key_E : toggleDrawEdges(); updateGL(); break; case Qt::Key_F : toggleDrawFaces(); updateGL(); break; case Qt::Key_C : toggleOneColorPerMesh(); updateGL(); break; default : QGLViewer::keyPressEvent(e); } } 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); // QGLViewer settings. setSceneBoundingBox(scene.getBBoxMin().f_data(), scene.getBBoxMax().f_data()); setSceneRadius(2.0f*sceneRadius()); showEntireScene(); } void Viewer::init() { glPolygonOffset(-2.0, -2.0); #ifdef GL_RESCALE_NORMAL glEnable(GL_RESCALE_NORMAL); #endif loadFile(); } void Viewer::draw() { scene.drawMesh(); scene.drawSelected(); } void Viewer::about() { QMessageBox::about(this, "about the simpleAnimationViewer", "this is an example showing how to animate a simple X3D scene.Type 'h' to display help"); } 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(); } void Viewer::select(const QMouseEvent* e) { // Make openGL context current makeCurrent(); const int SENSITIVITY = 6; const int NB_HITS_MAX = 32768; // Prepare the selection mode static GLuint hits[NB_HITS_MAX]; glSelectBuffer(NB_HITS_MAX, hits); glRenderMode(GL_SELECT); glInitNames(); // Loads the matrices glMatrixMode(GL_PROJECTION); glLoadIdentity(); GLint viewport[4]; glGetIntegerv(GL_VIEWPORT,viewport); camera()->getViewport(viewport); gluPickMatrix(static_cast<GLdouble>(e->x()), static_cast<GLdouble>(e->y()), SENSITIVITY, SENSITIVITY, viewport); // Don't use loadProjectionMatrix() directly as it clears the GL_PROJECTION matrix with a glLoadIdentity. // The false flag indicates that no glLoadIdentity should be called, in order to combine the matrices. camera()->loadProjectionMatrix(false); camera()->loadModelViewMatrix(); // Render scene with objects ids scene.drawMesh(true); glFlush(); // Get the results GLint nb_hits = glRenderMode(GL_RENDER); // Too many elements in selection buffer if (nb_hits < 0) return; // No selection if (nb_hits == 0) { scene.setSelectedType(NOTHING); cout << "No selection" << endl; return; } // Interpret results unsigned int zMin = hits[1]; scene.setSelectedMesh(hits[3]); scene.setSelectedType(static_cast<SelectedType>(hits[4])); scene.setSelectedId(hits[5]); for (int i=1; i<nb_hits; ++i) // Prefer vertices over edges and edges over faces if (hits[i*6+1] < zMin+(((int)scene.getSelectedType() - hits[i*6+4])*200000)) { zMin = hits[i*6+1]; scene.setSelectedMesh(hits[i*6+3]); scene.setSelectedType(static_cast<SelectedType>(hits[i*6+4])); scene.setSelectedId(hits[i*6+5]); } switch (scene.getSelectedType()) { case NOTHING : break; case VERTICES :cout << "Vertex "; break; case EDGES : cout << "Edge "; break; case FACES : cout << "Face "; break; } cout << scene.getSelectedId() << " selected on mesh " << scene.getSelectedMesh() << endl; } QString Viewer::helpString() const { QString message("<b>L</b> loads a new file<br>"); message += "<b>F</b> toggles face display<br>"; message += "<b>E</b> toggles edge display<br>"; message += "<b>V</b> toggles vertex display<br>"; message += "<b>C</b> toggles one color per mesh<br>"; message += "<b>Shift+click</b> to select an element<br>"; message += "<hr>"; message += QGLViewer::helpString(); return message; }
#include "Viewer.h" #include <qapplication.h> using namespace X3DTK; using namespace std; int main(int argc, char *argv[]) { // Read command lines arguments. QApplication application(argc, argv); // Instantiate the viewer. Viewer v; // Make the viewer window visible on screen. v.show(); // Set the viewer as the application main widget. application.setMainWidget(&v); // Run main loop. return application.exec(); }