From 24b16b4710c0a9eeef5f0d9ce9717930e3b3277d Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 5 Apr 2016 10:35:26 +0200 Subject: [PATCH] New picking finished. Far more efficient. --- Polyhedron/demo/Polyhedron/Scene.cpp | 198 ++++++++++-------- Polyhedron/demo/Polyhedron/Scene.h | 3 + Polyhedron/demo/Polyhedron/Viewer.cpp | 20 +- Polyhedron/demo/Polyhedron/Viewer.h | 2 +- .../include/CGAL/Three/Scene_draw_interface.h | 3 + Three/include/CGAL/Three/Viewer_interface.h | 2 +- 6 files changed, 125 insertions(+), 103 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Scene.cpp b/Polyhedron/demo/Polyhedron/Scene.cpp index 6fdd9ea6c93..45e5df71de8 100644 --- a/Polyhedron/demo/Polyhedron/Scene.cpp +++ b/Polyhedron/demo/Polyhedron/Scene.cpp @@ -331,10 +331,10 @@ Scene::drawWithNames(CGAL::Three::Viewer_interface* viewer) { draw_aux(true, viewer); } - void Scene::draw_aux(bool with_names, CGAL::Three::Viewer_interface* viewer) { + QMap picked_item_IDs; if(!ms_splatting->viewer_is_set) ms_splatting->setViewer(viewer); if(!gl_init) @@ -343,7 +343,8 @@ Scene::draw_aux(bool with_names, CGAL::Three::Viewer_interface* viewer) for(int index = 0; index < m_entries.size(); ++index) { if(with_names) { - viewer->glPushName(index); + glClearDepth(1.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } CGAL::Three::Scene_item& item = *m_entries[index]; if(item.visible()) @@ -375,140 +376,151 @@ Scene::draw_aux(bool with_names, CGAL::Three::Viewer_interface* viewer) } } if(with_names) { - viewer->glPopName(); + + // read depth buffer at pick location; + float depth = 1.0; + glReadPixels(picked_pixel.x(),picked_pixel.y(),1,1,GL_DEPTH_COMPONENT, GL_FLOAT, &depth); + if (depth != 1.0) + { + //add object to list of picked objects; + picked_item_IDs[depth] = index; + } } } -glDepthFunc(GL_LEQUAL); - // Wireframe OpenGL drawing - for(int index = 0; index < m_entries.size(); ++index) + if(!with_names) { - if(with_names) { - viewer->glPushName(index); - } - CGAL::Three::Scene_item& item = *m_entries[index]; - if(item.visible()) + glDepthFunc(GL_LEQUAL); + // Wireframe OpenGL drawing + for(int index = 0; index < m_entries.size(); ++index) { - if(item.renderingMode() == FlatPlusEdges || item.renderingMode() == Wireframe) + CGAL::Three::Scene_item& item = *m_entries[index]; + if(item.visible()) { - viewer->glDisable(GL_LIGHTING); - viewer->glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); - viewer->glPointSize(2.f); - viewer->glLineWidth(1.0f); - if(index == selected_item || selected_items_list.contains(index)) + if(item.renderingMode() == FlatPlusEdges || item.renderingMode() == Wireframe) { - item.selection_changed(true); - } - else - { - item.selection_changed(false); - } - - - - if(viewer) - item.draw_edges(viewer); - else - item.draw_edges(); - } - else{ - if( item.renderingMode() == PointsPlusNormals ){ viewer->glDisable(GL_LIGHTING); viewer->glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); viewer->glPointSize(2.f); viewer->glLineWidth(1.0f); if(index == selected_item || selected_items_list.contains(index)) { - item.selection_changed(true); } else { - item.selection_changed(false); } + + + if(viewer) item.draw_edges(viewer); else item.draw_edges(); } + else{ + if( item.renderingMode() == PointsPlusNormals ){ + viewer->glDisable(GL_LIGHTING); + viewer->glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); + viewer->glPointSize(2.f); + viewer->glLineWidth(1.0f); + if(index == selected_item || selected_items_list.contains(index)) + { + + item.selection_changed(true); + } + else + { + + item.selection_changed(false); + } + if(viewer) + item.draw_edges(viewer); + else + item.draw_edges(); + } + } } } - if(with_names) { - viewer->glPopName(); - } - } - // Points OpenGL drawing - for(int index = 0; index < m_entries.size(); ++index) - { - if(with_names) { - viewer->glPushName(index); - } - CGAL::Three::Scene_item& item = *m_entries[index]; - if(item.visible()) - { - if(item.renderingMode() == Points || item.renderingMode() == PointsPlusNormals) - { - viewer->glDisable(GL_LIGHTING); - viewer->glPolygonMode(GL_FRONT_AND_BACK,GL_POINT); - viewer->glPointSize(2.f); - viewer->glLineWidth(1.0f); - - if(viewer) - item.draw_points(viewer); - else - item.draw_points(); - } - } - if(with_names) { - viewer->glPopName(); - } - } - glDepthFunc(GL_LESS); - // Splatting - if(!with_names && ms_splatting->isSupported()) - { - - ms_splatting->beginVisibilityPass(); + // Points OpenGL drawing for(int index = 0; index < m_entries.size(); ++index) { CGAL::Three::Scene_item& item = *m_entries[index]; - if(item.visible() && item.renderingMode() == Splatting) + if(item.visible()) { - - if(viewer) + if(item.renderingMode() == Points || item.renderingMode() == PointsPlusNormals) { - item.draw_splats(viewer); + viewer->glDisable(GL_LIGHTING); + viewer->glPolygonMode(GL_FRONT_AND_BACK,GL_POINT); + viewer->glPointSize(2.f); + viewer->glLineWidth(1.0f); + + if(viewer) + item.draw_points(viewer); + else + item.draw_points(); } - else - item.draw_splats(); } - } - ms_splatting->beginAttributePass(); - for(int index = 0; index < m_entries.size(); ++index) - { CGAL::Three::Scene_item& item = *m_entries[index]; - if(item.visible() && item.renderingMode() == Splatting) + glDepthFunc(GL_LESS); + // Splatting + if(!with_names && ms_splatting->isSupported()) + { + + ms_splatting->beginVisibilityPass(); + for(int index = 0; index < m_entries.size(); ++index) { - viewer->glColor4d(item.color().redF(), item.color().greenF(), item.color().blueF(), item.color().alphaF()); - if(viewer) - item.draw_splats(viewer); - else - item.draw_splats(); + CGAL::Three::Scene_item& item = *m_entries[index]; + if(item.visible() && item.renderingMode() == Splatting) + { + + if(viewer) + { + item.draw_splats(viewer); + } + else + item.draw_splats(); + } + } + ms_splatting->beginAttributePass(); + for(int index = 0; index < m_entries.size(); ++index) + { CGAL::Three::Scene_item& item = *m_entries[index]; + if(item.visible() && item.renderingMode() == Splatting) + { + viewer->glColor4d(item.color().redF(), item.color().greenF(), item.color().blueF(), item.color().alphaF()); + if(viewer) + item.draw_splats(viewer); + else + item.draw_splats(); + } + } + ms_splatting->finalize(); + + } + } + else + { + QList depths = picked_item_IDs.keys(); + if(!depths.isEmpty()) + { + qSort(depths); + int id = picked_item_IDs[depths.first()]; + setSelectedItemIndex(id); + viewer->setSelectedName(id); } - ms_splatting->finalize(); - } - - //scrolls the sceneView to the selected item's line. - if(picked) - Q_EMIT(itemPicked(index_map.key(mainSelectionIndex()))); if(with_names) picked = true; else picked = false; + //scrolls the sceneView to the selected item's line. + if(picked) + { + Q_EMIT(itemPicked(index_map.key(mainSelectionIndex()))); + } } diff --git a/Polyhedron/demo/Polyhedron/Scene.h b/Polyhedron/demo/Polyhedron/Scene.h index 7e938d163fb..9dbac4ade72 100644 --- a/Polyhedron/demo/Polyhedron/Scene.h +++ b/Polyhedron/demo/Polyhedron/Scene.h @@ -112,6 +112,8 @@ public: void initializeGL(); /*! Is called by Viewer::draw(). Is deprecated and does nothing.*/ void draw(); + /*! Sets the screen coordinates of the currently picked point.*/ + void setPickedPixel(const QPoint &p) {picked_pixel = p;} /*! Is deprecated and does nothing.*/ void drawWithNames(); /*! Is called by Viewer::draw(Viewer_interface*). Calls draw_aux(false, viewer). @@ -274,6 +276,7 @@ private: //!Index of the item_B. int item_B; bool picked; + QPoint picked_pixel; bool gl_init; static GlSplat::SplatRenderer* ms_splatting; static int ms_splattingCounter; diff --git a/Polyhedron/demo/Polyhedron/Viewer.cpp b/Polyhedron/demo/Polyhedron/Viewer.cpp index 48f80eea8b0..b52d1fab6d2 100644 --- a/Polyhedron/demo/Polyhedron/Viewer.cpp +++ b/Polyhedron/demo/Polyhedron/Viewer.cpp @@ -237,6 +237,7 @@ void Viewer::mousePressEvent(QMouseEvent* event) if(event->button() == Qt::RightButton && event->modifiers().testFlag(Qt::ShiftModifier)) { + select(event->pos()); requestContextMenu(event->globalPos()); event->accept(); @@ -435,7 +436,6 @@ void Viewer::attrib_buffers(int program_name) const { mv_mat.data()[i] = GLfloat(d_mat[i]); for (int i=0; i<16; ++i) pick_mat.data()[i] = this->pickMatrix_[i]; - mvp_mat = pick_mat * mvp_mat; const_cast(this)->glGetIntegerv(GL_LIGHT_MODEL_TWO_SIDE, @@ -546,7 +546,7 @@ void Viewer::attrib_buffers(int program_name) const { void Viewer::pickMatrix(GLdouble x, GLdouble y, GLdouble width, GLdouble height, -GLint viewport[4]) +GLint viewport[4]) const { //GLfloat m[16]; GLfloat sx, sy; @@ -575,21 +575,25 @@ GLint viewport[4]) M(3, 2) = 0.0; M(3, 3) = 1.0; #undef M - - //pickMatrix_[i] = m[i]; } void Viewer::beginSelection(const QPoint &point) { - QGLViewer::beginSelection(point); + // QGLViewer::beginSelection(point); + makeCurrent(); //set the picking matrix to allow the picking static GLint viewport[4]; camera()->getViewport(viewport); - pickMatrix(point.x(), point.y(), selectRegionWidth(), selectRegionHeight(), viewport); + pickMatrix(point.x(), point.y(), 1, 1, viewport); + glEnable(GL_SCISSOR_TEST); + glScissor(point.x(), point.y(), 1, 1); + d->scene->setPickedPixel(point); } -void Viewer::endSelection(const QPoint& point) +void Viewer::endSelection(const QPoint&) { - QGLViewer::endSelection(point); + //QGLViewer::endSelection(point); + glDisable(GL_SCISSOR_TEST); + //set the pick matrix to Identity for(int i=0; i<16; i++) pickMatrix_[i]=0; diff --git a/Polyhedron/demo/Polyhedron/Viewer.h b/Polyhedron/demo/Polyhedron/Viewer.h index 3435ebe047d..321221bfccc 100644 --- a/Polyhedron/demo/Polyhedron/Viewer.h +++ b/Polyhedron/demo/Polyhedron/Viewer.h @@ -114,7 +114,7 @@ protected: * the drawing system changed to use shaders, and these need this value. pickMatrix_ is passed to the shaders in * Scene_item::attrib_buffers(CGAL::Three::Viewer_interface* viewer, int program_name).*/ void pickMatrix(GLdouble x, GLdouble y, GLdouble width, GLdouble height, - GLint viewport[4]); + GLint viewport[4]) const; /*! * \brief makeArrow creates an arrow and stores it in a struct of vectors. * \param R the radius of the arrow. diff --git a/Three/include/CGAL/Three/Scene_draw_interface.h b/Three/include/CGAL/Three/Scene_draw_interface.h index c9fa3f0844b..4bce8217347 100644 --- a/Three/include/CGAL/Three/Scene_draw_interface.h +++ b/Three/include/CGAL/Three/Scene_draw_interface.h @@ -22,6 +22,7 @@ #define SCENE_DRAW_INTERFACE_H class QKeyEvent; +class QPoint; namespace CGAL { namespace Three { @@ -36,6 +37,8 @@ public: virtual void draw() = 0; virtual void draw(CGAL::Three::Viewer_interface*) { draw(); }; virtual void drawWithNames() = 0; + /*! Sets the screen coordinates of the currently picked point.*/ + virtual void setPickedPixel(const QPoint &e) = 0; virtual void drawWithNames(CGAL::Three::Viewer_interface*) { drawWithNames(); } virtual bool keyPressEvent(QKeyEvent* e) = 0; virtual float get_bbox_length() const = 0; diff --git a/Three/include/CGAL/Three/Viewer_interface.h b/Three/include/CGAL/Three/Viewer_interface.h index e99b5bbd785..9735a666467 100644 --- a/Three/include/CGAL/Three/Viewer_interface.h +++ b/Three/include/CGAL/Three/Viewer_interface.h @@ -109,7 +109,7 @@ public: //! Used by the items to avoid SEGFAULT. bool extension_is_found; //!The matrix used for the picking. - GLfloat pickMatrix_[16]; + mutable GLfloat pickMatrix_[16]; //!Sets the binding for SHIFT+LEFT CLICK to SELECT (initially used in Scene_polyhedron_selection_item.h) void setBindingSelect() {