Merge pull request #990 from maxGimeno/Polyhedorn_demo-New_picking-GF

Polyhedron_demo : New picking
This commit is contained in:
Laurent Rineau 2016-04-11 11:58:35 +02:00
commit f8aabdcc36
7 changed files with 128 additions and 132 deletions

View File

@ -331,10 +331,10 @@ Scene::drawWithNames(CGAL::Three::Viewer_interface* viewer)
{ {
draw_aux(true, viewer); draw_aux(true, viewer);
} }
void void
Scene::draw_aux(bool with_names, CGAL::Three::Viewer_interface* viewer) Scene::draw_aux(bool with_names, CGAL::Three::Viewer_interface* viewer)
{ {
QMap<float, int> picked_item_IDs;
if(!ms_splatting->viewer_is_set) if(!ms_splatting->viewer_is_set)
ms_splatting->setViewer(viewer); ms_splatting->setViewer(viewer);
if(!gl_init) if(!gl_init)
@ -342,14 +342,15 @@ Scene::draw_aux(bool with_names, CGAL::Three::Viewer_interface* viewer)
// Flat/Gouraud OpenGL drawing // Flat/Gouraud OpenGL drawing
for(int index = 0; index < m_entries.size(); ++index) for(int index = 0; index < m_entries.size(); ++index)
{ {
if(with_names) {
viewer->glPushName(index);
}
CGAL::Three::Scene_item& item = *m_entries[index]; CGAL::Three::Scene_item& item = *m_entries[index];
if(item.visible()) if(item.visible())
{ {
if(item.renderingMode() == Flat || item.renderingMode() == FlatPlusEdges || item.renderingMode() == Gouraud) if(item.renderingMode() == Flat || item.renderingMode() == FlatPlusEdges || item.renderingMode() == Gouraud)
{ {
if(with_names) {
glClearDepth(1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
viewer->glEnable(GL_LIGHTING); viewer->glEnable(GL_LIGHTING);
viewer->glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); viewer->glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
viewer->glPointSize(2.f); viewer->glPointSize(2.f);
@ -372,23 +373,36 @@ Scene::draw_aux(bool with_names, CGAL::Three::Viewer_interface* viewer)
item.draw(viewer); item.draw(viewer);
else else
item.draw(); item.draw();
if(with_names) {
// read depth buffer at pick location;
float depth = 1.0;
glReadPixels(picked_pixel.x(),viewer->camera()->screenHeight()-1-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;
}
}
} }
} }
if(with_names) {
viewer->glPopName();
}
} }
glDepthFunc(GL_LEQUAL); glDepthFunc(GL_LEQUAL);
// Wireframe OpenGL drawing // Wireframe OpenGL drawing
for(int index = 0; index < m_entries.size(); ++index) for(int index = 0; index < m_entries.size(); ++index)
{ {
if(with_names) {
viewer->glPushName(index);
}
CGAL::Three::Scene_item& item = *m_entries[index]; CGAL::Three::Scene_item& item = *m_entries[index];
if(item.visible()) if(item.visible())
{ {
if(item.renderingMode() == FlatPlusEdges || item.renderingMode() == Wireframe) if((item.renderingMode() == Wireframe || item.renderingMode() == PointsPlusNormals )
&& with_names)
{
glClearDepth(1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
if((!with_names && item.renderingMode() == FlatPlusEdges )
|| item.renderingMode() == Wireframe)
{ {
viewer->glDisable(GL_LIGHTING); viewer->glDisable(GL_LIGHTING);
viewer->glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); viewer->glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
@ -396,11 +410,11 @@ glDepthFunc(GL_LEQUAL);
viewer->glLineWidth(1.0f); viewer->glLineWidth(1.0f);
if(index == selected_item || selected_items_list.contains(index)) if(index == selected_item || selected_items_list.contains(index))
{ {
item.selection_changed(true); item.selection_changed(true);
} }
else else
{ {
item.selection_changed(false); item.selection_changed(false);
} }
@ -432,27 +446,37 @@ glDepthFunc(GL_LEQUAL);
item.draw_edges(); item.draw_edges();
} }
} }
} if((item.renderingMode() == Wireframe || item.renderingMode() == PointsPlusNormals )
if(with_names) { && with_names)
viewer->glPopName(); {
// read depth buffer at pick location;
float depth = 1.0;
glReadPixels(picked_pixel.x(),viewer->camera()->screenHeight()-1-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;
}
}
} }
} }
// Points OpenGL drawing // Points OpenGL drawing
for(int index = 0; index < m_entries.size(); ++index) for(int index = 0; index < m_entries.size(); ++index)
{ {
if(with_names) {
viewer->glPushName(index);
}
CGAL::Three::Scene_item& item = *m_entries[index]; CGAL::Three::Scene_item& item = *m_entries[index];
if(item.visible()) if(item.visible())
{ {
if(item.renderingMode() == Points || item.renderingMode() == PointsPlusNormals) if(item.renderingMode() == Points && with_names) {
glClearDepth(1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
if(item.renderingMode() == Points ||
(!with_names && item.renderingMode() == PointsPlusNormals))
{ {
viewer->glDisable(GL_LIGHTING); viewer->glDisable(GL_LIGHTING);
viewer->glPolygonMode(GL_FRONT_AND_BACK,GL_POINT); viewer->glPolygonMode(GL_FRONT_AND_BACK,GL_POINT);
viewer->glPointSize(2.f); viewer->glPointSize(2.0f);
viewer->glLineWidth(1.0f); viewer->glLineWidth(1.0f);
if(viewer) if(viewer)
@ -460,55 +484,78 @@ glDepthFunc(GL_LEQUAL);
else else
item.draw_points(); item.draw_points();
} }
} if(item.renderingMode() == Points && with_names) {
if(with_names) { // read depth buffer at pick location;
viewer->glPopName(); float depth = 1.0;
} glReadPixels(picked_pixel.x(),viewer->camera()->screenHeight()-1-picked_pixel.y(),1,1,GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
} if (depth != 1.0)
glDepthFunc(GL_LESS);
// Splatting
if(!with_names && ms_splatting->isSupported())
{
ms_splatting->beginVisibilityPass();
for(int index = 0; index < m_entries.size(); ++index)
{
CGAL::Three::Scene_item& item = *m_entries[index];
if(item.visible() && item.renderingMode() == Splatting)
{
if(viewer)
{ {
item.draw_splats(viewer); //add object to list of picked objects;
picked_item_IDs[depth] = index;
} }
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();
} }
if(!with_names)
{
glDepthFunc(GL_LESS);
// Splatting
if(!with_names && ms_splatting->isSupported())
{
//scrolls the sceneView to the selected item's line. ms_splatting->beginVisibilityPass();
if(picked) for(int index = 0; index < m_entries.size(); ++index)
Q_EMIT(itemPicked(index_map.key(mainSelectionIndex()))); {
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<float> depths = picked_item_IDs.keys();
if(!depths.isEmpty())
{
qSort(depths);
int id = picked_item_IDs[depths.first()];
setSelectedItemIndex(id);
viewer->setSelectedName(id);
}
}
if(with_names) if(with_names)
picked = true; picked = true;
else else
picked = false; picked = false;
//scrolls the sceneView to the selected item's line.
if(picked)
{
Q_EMIT(itemPicked(index_map.key(mainSelectionIndex())));
}
} }

View File

@ -112,6 +112,8 @@ public:
void initializeGL(); void initializeGL();
/*! Is called by Viewer::draw(). Is deprecated and does nothing.*/ /*! Is called by Viewer::draw(). Is deprecated and does nothing.*/
void draw(); void draw();
/*! Sets the screen coordinates of the currently picked point.*/
void setPickedPixel(const QPoint &p) {picked_pixel = p;}
/*! Is deprecated and does nothing.*/ /*! Is deprecated and does nothing.*/
void drawWithNames(); void drawWithNames();
/*! Is called by Viewer::draw(Viewer_interface*). Calls draw_aux(false, viewer). /*! Is called by Viewer::draw(Viewer_interface*). Calls draw_aux(false, viewer).
@ -274,6 +276,7 @@ private:
//!Index of the item_B. //!Index of the item_B.
int item_B; int item_B;
bool picked; bool picked;
QPoint picked_pixel;
bool gl_init; bool gl_init;
static GlSplat::SplatRenderer* ms_splatting; static GlSplat::SplatRenderer* ms_splatting;
static int ms_splattingCounter; static int ms_splattingCounter;

View File

@ -55,12 +55,6 @@ Viewer::Viewer(QWidget* parent, bool antialiasing)
tr("Selects and display context " tr("Selects and display context "
"menu of the selected item")); "menu of the selected item"));
#endif // QGLVIEWER_VERSION >= 2.5.0 #endif // QGLVIEWER_VERSION >= 2.5.0
for(int i=0; i<16; i++)
pickMatrix_[i]=0;
pickMatrix_[0]=1;
pickMatrix_[5]=1;
pickMatrix_[10]=1;
pickMatrix_[15]=1;
prev_radius = sceneRadius(); prev_radius = sceneRadius();
axis_are_displayed = true; axis_are_displayed = true;
} }
@ -237,6 +231,7 @@ void Viewer::mousePressEvent(QMouseEvent* event)
if(event->button() == Qt::RightButton && if(event->button() == Qt::RightButton &&
event->modifiers().testFlag(Qt::ShiftModifier)) event->modifiers().testFlag(Qt::ShiftModifier))
{ {
select(event->pos()); select(event->pos());
requestContextMenu(event->globalPos()); requestContextMenu(event->globalPos());
event->accept(); event->accept();
@ -432,8 +427,7 @@ void Viewer::attrib_buffers(int program_name) const {
QMatrix4x4 mv_mat; QMatrix4x4 mv_mat;
// transformation of the manipulated frame // transformation of the manipulated frame
QMatrix4x4 f_mat; QMatrix4x4 f_mat;
// used for the picking. Is Identity except while selecting an item.
QMatrix4x4 pick_mat;
f_mat.setToIdentity(); f_mat.setToIdentity();
//fills the MVP and MV matrices. //fills the MVP and MV matrices.
GLdouble d_mat[16]; GLdouble d_mat[16];
@ -445,10 +439,6 @@ void Viewer::attrib_buffers(int program_name) const {
this->camera()->getModelViewMatrix(d_mat); this->camera()->getModelViewMatrix(d_mat);
for (int i=0; i<16; ++i) for (int i=0; i<16; ++i)
mv_mat.data()[i] = GLfloat(d_mat[i]); 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<Viewer*>(this)->glGetIntegerv(GL_LIGHT_MODEL_TWO_SIDE, const_cast<Viewer*>(this)->glGetIntegerv(GL_LIGHT_MODEL_TWO_SIDE,
&is_both_sides); &is_both_sides);
@ -556,59 +546,19 @@ void Viewer::attrib_buffers(int program_name) const {
program->release(); program->release();
} }
void Viewer::pickMatrix(GLdouble x, GLdouble y, GLdouble width, GLdouble height,
GLint viewport[4])
{
//GLfloat m[16];
GLfloat sx, sy;
GLfloat tx, ty;
sx = viewport[2] / width;
sy = viewport[3] / height;
tx = (viewport[2] + 2.0 * (viewport[0] - x)) / width;
ty = (viewport[3] + 2.0 * (viewport[1] - y)) / height;
#define M(row, col) pickMatrix_[col*4+row]
M(0, 0) = sx;
M(0, 1) = 0.0;
M(0, 2) = 0.0;
M(0, 3) = tx;
M(1, 0) = 0.0;
M(1, 1) = sy;
M(1, 2) = 0.0;
M(1, 3) = ty;
M(2, 0) = 0.0;
M(2, 1) = 0.0;
M(2, 2) = 1.0;
M(2, 3) = 0.0;
M(3, 0) = 0.0;
M(3, 1) = 0.0;
M(3, 2) = 0.0;
M(3, 3) = 1.0;
#undef M
//pickMatrix_[i] = m[i];
}
void Viewer::beginSelection(const QPoint &point) void Viewer::beginSelection(const QPoint &point)
{ {
QGLViewer::beginSelection(point); makeCurrent();
//set the picking matrix to allow the picking glEnable(GL_SCISSOR_TEST);
static GLint viewport[4]; glScissor(point.x(), camera()->screenHeight()-1-point.y(), 1, 1);
camera()->getViewport(viewport); d->scene->setPickedPixel(point);
pickMatrix(point.x(), point.y(), selectRegionWidth(), selectRegionHeight(), viewport);
} }
void Viewer::endSelection(const QPoint& point) void Viewer::endSelection(const QPoint&)
{ {
QGLViewer::endSelection(point); glDisable(GL_SCISSOR_TEST);
//set the pick matrix to Identity //redraw thetrue scene for the glReadPixel in postSelection();
for(int i=0; i<16; i++) updateGL();
pickMatrix_[i]=0;
pickMatrix_[0]=1;
pickMatrix_[5]=1;
pickMatrix_[10]=1;
pickMatrix_[15]=1;
} }
void Viewer::makeArrow(double R, int prec, qglviewer::Vec from, qglviewer::Vec to, qglviewer::Vec color, AxisData &data) void Viewer::makeArrow(double R, int prec, qglviewer::Vec from, qglviewer::Vec to, qglviewer::Vec color, AxisData &data)

View File

@ -111,13 +111,6 @@ protected:
void keyPressEvent(QKeyEvent*); void keyPressEvent(QKeyEvent*);
//!Deal with context menu events //!Deal with context menu events
void contextMenuEvent(QContextMenuEvent*); void contextMenuEvent(QContextMenuEvent*);
/*! \brief Encapsulates the pickMatrix.
* Source code of gluPickMatrix slightly modified : instead of multiplying the current matrix by this value,
* sets the viewer's pickMatrix_ so that the drawing area is only around the cursor. This is because since CGAL 4.7,
* 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]);
/*! /*!
* \brief makeArrow creates an arrow and stores it in a struct of vectors. * \brief makeArrow creates an arrow and stores it in a struct of vectors.
* \param R the radius of the arrow. * \param R the radius of the arrow.

View File

@ -22,6 +22,7 @@
#define SCENE_DRAW_INTERFACE_H #define SCENE_DRAW_INTERFACE_H
class QKeyEvent; class QKeyEvent;
class QPoint;
namespace CGAL namespace CGAL
{ {
namespace Three { namespace Three {
@ -36,6 +37,8 @@ public:
virtual void draw() = 0; virtual void draw() = 0;
virtual void draw(CGAL::Three::Viewer_interface*) { draw(); }; virtual void draw(CGAL::Three::Viewer_interface*) { draw(); };
virtual void drawWithNames() = 0; 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 void drawWithNames(CGAL::Three::Viewer_interface*) { drawWithNames(); }
virtual bool keyPressEvent(QKeyEvent* e) = 0; virtual bool keyPressEvent(QKeyEvent* e) = 0;
virtual float get_bbox_length() const = 0; virtual float get_bbox_length() const = 0;

View File

@ -109,7 +109,7 @@ public:
//! Used by the items to avoid SEGFAULT. //! Used by the items to avoid SEGFAULT.
bool extension_is_found; bool extension_is_found;
//!The matrix used for the picking. //!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) //!Sets the binding for SHIFT+LEFT CLICK to SELECT (initially used in Scene_polyhedron_selection_item.h)
void setBindingSelect() void setBindingSelect()
{ {