Change the semantic of the Scene_group_item

New feature: an object of class `Scene_group_item`, or derived, is
responsible for drawing its children items. That is the first
approximation of a scene graph.

For that goal, several steps were needed.

- Remove the overload of `Scene::draw()` and `Scene::drawWithNames()`
  that does not have the viewer as parameter. Remove then from
  `Scene_draw_interface` as well.

- Add `Viewer::inDrawWithNames()` so that items, including the
  `Scene_group_item`, can now if a draw function is called for the
  picking or not.

- Add the draw function in `Scene_group_item`:
```
  virtual void draw(CGAL::Three::Viewer_interface*) const;
  virtual void draw_edges(CGAL::Three::Viewer_interface*) const;
  virtual void draw_points(CGAL::Three::Viewer_interface*) const;
  virtual void draw_splats(CGAL::Three::Viewer_interface*) const;
```
  Those draw functions actually call the draw functions of all the
  visible children, depending on their rendering mode. If
  `viewer->inDrawWithNames()`, draw nothing, and let the children be
  drawn with their own names. Another solution could be that the draw
  functions of `Scene_group_item` use `glPushName/glPopName`. That API
  seems to be usable with a scene graph.

- Add in `Scene_item` two functions:
```
  void moveToGroup(Scene_group_item* group);
  Scene_group_item* parentGroup() const;
```
  That is one first step to allow the `has_group` data member to become
  a private member, instead a public one (ugly!!).

Then the big change is in the scene:

- The scene will not call the draw function of items with a parent
  group, if the group itself is visible. If the group is not visible but
  the children are set to visible, then they are drawn anyway. That
  means that a group can "steal" the drawing of its children when it is
  visible. That behavior is really convenient for the use case I have in
  mind, but it may be strange.

- In the picking, in `drawWithName()`, the draw function of all items
  are called, even if they have a parent group.

Cosmetic:

  - Move the definition of the constructor `Scene_item::Scene_item` in
    the cpp file.
This commit is contained in:
Laurent Rineau 2016-03-04 14:37:53 +01:00
parent 96c4dc60de
commit 80d7a738e4
10 changed files with 160 additions and 88 deletions

View File

@ -311,27 +311,28 @@ Scene::keyPressEvent(QKeyEvent* e){
return res;
}
void
Scene::draw()
{
draw_aux(false, 0);
}
void
Scene::draw(CGAL::Three::Viewer_interface* viewer)
{
draw_aux(false, viewer);
}
void
Scene::drawWithNames()
{
draw_aux(true, 0);
}
void
Scene::drawWithNames(CGAL::Three::Viewer_interface* viewer)
{
draw_aux(true, viewer);
}
bool item_should_be_skipped_in_draw(Scene_item* item) {
if(!item->visible()) return true;
if(item->has_group == 0) return false;
Scene_group_item* group = item->parentGroup();
while(group != 0) {
if(!group->visible()) return false;
group = group->parentGroup();
}
return true;
}
void
Scene::draw_aux(bool with_names, CGAL::Three::Viewer_interface* viewer)
{
@ -342,10 +343,12 @@ Scene::draw_aux(bool with_names, CGAL::Three::Viewer_interface* viewer)
// Flat/Gouraud OpenGL drawing
for(int index = 0; index < m_entries.size(); ++index)
{
CGAL::Three::Scene_item& item = *m_entries[index];
if(with_names) {
viewer->glPushName(index);
} else {
if(item_should_be_skipped_in_draw(&item)) continue;
}
CGAL::Three::Scene_item& item = *m_entries[index];
if(item.visible())
{
if(item.renderingMode() == Flat || item.renderingMode() == FlatPlusEdges || item.renderingMode() == Gouraud)
@ -378,14 +381,17 @@ Scene::draw_aux(bool with_names, CGAL::Three::Viewer_interface* viewer)
viewer->glPopName();
}
}
glDepthFunc(GL_LEQUAL);
glDepthFunc(GL_LEQUAL);
// Wireframe OpenGL drawing
for(int index = 0; index < m_entries.size(); ++index)
{
CGAL::Three::Scene_item& item = *m_entries[index];
if(with_names) {
viewer->glPushName(index);
}
CGAL::Three::Scene_item& item = *m_entries[index];
else {
if(item_should_be_skipped_in_draw(&item)) continue;
}
if(item.visible())
{
if(item.renderingMode() == FlatPlusEdges || item.renderingMode() == Wireframe)
@ -442,10 +448,12 @@ glDepthFunc(GL_LEQUAL);
// Points OpenGL drawing
for(int index = 0; index < m_entries.size(); ++index)
{
CGAL::Three::Scene_item& item = *m_entries[index];
if(with_names) {
viewer->glPushName(index);
} else {
if(item_should_be_skipped_in_draw(&item)) continue;
}
CGAL::Three::Scene_item& item = *m_entries[index];
if(item.visible())
{
if(item.renderingMode() == Points || item.renderingMode() == PointsPlusNormals)
@ -474,6 +482,7 @@ glDepthFunc(GL_LEQUAL);
for(int index = 0; index < m_entries.size(); ++index)
{
CGAL::Three::Scene_item& item = *m_entries[index];
if(item_should_be_skipped_in_draw(&item)) continue;
if(item.visible() && item.renderingMode() == Splatting)
{
@ -486,9 +495,11 @@ glDepthFunc(GL_LEQUAL);
}
}
ms_splatting->beginAttributePass();
for(int index = 0; index < m_entries.size(); ++index)
{ CGAL::Three::Scene_item& item = *m_entries[index];
ms_splatting->beginAttributePass();
for(int index = 0; index < m_entries.size(); ++index)
{
CGAL::Three::Scene_item& item = *m_entries[index];
if(item_should_be_skipped_in_draw(&item)) continue;
if(item.visible() && item.renderingMode() == Splatting)
{
viewer->glColor4d(item.color().redF(), item.color().greenF(), item.color().blueF(), item.color().alphaF());
@ -1077,7 +1088,7 @@ void Scene::changeGroup(Scene_item *item, CGAL::Three::Scene_group_item *target_
}
//add the item to the target group
target_group->addChild(item);
item->has_group = target_group->has_group +1;
item->moveToGroup(target_group);
}
float Scene::get_bbox_length() const

View File

@ -110,10 +110,6 @@ public:
* of OpenGL code that needs a context.
*/
void initializeGL();
/*! Is called by Viewer::draw(). Is deprecated and does nothing.*/
void draw();
/*! Is deprecated and does nothing.*/
void drawWithNames();
/*! Is called by Viewer::draw(Viewer_interface*). Calls draw_aux(false, viewer).
* @see draw_aux(bool with_names, Viewer_interface).*/
void draw(CGAL::Three::Viewer_interface*);

View File

@ -1,5 +1,5 @@
#include <CGAL/Three/Scene_group_item.h>
#include <CGAL/Three/Viewer_interface.h>
#include <QDebug>
using namespace CGAL::Three;
@ -114,3 +114,55 @@ void Scene_group_item::moveUp(int i)
{
children.move(i, i-1);
}
void Scene_group_item::draw(CGAL::Three::Viewer_interface* viewer) const {
if(viewer->inDrawWithNames()) return;
Q_FOREACH(Scene_item* child, children) {
if(!child->visible()) continue;
switch(child->renderingMode()) {
case Flat:
case FlatPlusEdges:
case Gouraud:
child->draw(viewer); break;
default: break;
}
}
}
void Scene_group_item::draw_edges(CGAL::Three::Viewer_interface* viewer) const
{
if(viewer->inDrawWithNames()) return;
Q_FOREACH(Scene_item* child, children) {
if(!child->visible()) continue;
switch(child->renderingMode()) {
case FlatPlusEdges:
case Wireframe:
case PointsPlusNormals:
child->draw_edges(viewer); break;
default: break;
}
}
}
void Scene_group_item::draw_points(CGAL::Three::Viewer_interface* viewer) const
{
if(viewer->inDrawWithNames()) return;
Q_FOREACH(Scene_item* child, children) {
if(!child->visible()) continue;
switch(child->renderingMode()) {
case Points:
case PointsPlusNormals:
child->draw_points(viewer); break;
default: break;
}
}
}
void Scene_group_item::draw_splats(CGAL::Three::Viewer_interface* viewer) const
{
if(viewer->inDrawWithNames()) return;
Q_FOREACH(Scene_item* child, children) {
if(child->visible() && child->renderingMode() == Splatting)
child->draw_splats(viewer);
}
}

View File

@ -1,4 +1,5 @@
#include <CGAL/Three/Scene_item.h>
#include <CGAL/Three/Scene_group_item.h>
#include <CGAL/Three/Scene_interface.h>
#include <QMenu>
#include <iostream>
@ -6,6 +7,37 @@
#include <CGAL/Three/Viewer_interface.h>
const QColor CGAL::Three::Scene_item::defaultColor = QColor(100, 100, 255);
CGAL::Three::Scene_item::Scene_item(int buffers_size, int vaos_size)
: name_("unamed"),
color_(defaultColor),
visible_(true),
are_buffers_filled(false),
rendering_mode(FlatPlusEdges),
defaultContextMenu(0),
buffersSize(buffers_size),
vaosSize(vaos_size),
vaos(vaos_size)
{
is_bbox_computed = false;
is_monochrome = true;
for(int i=0; i<vaosSize; i++)
{
addVaos(i);
vaos[i]->create();
}
buffers.reserve(buffersSize);
for(int i=0; i<buffersSize; i++)
{
QOpenGLBuffer n_buf;
buffers.push_back(n_buf);
buffers[i].create();
}
nb_isolated_vertices = 0;
has_group = 0;
parent_group = 0;
}
CGAL::Three::Scene_item::~Scene_item() {
delete defaultContextMenu;
for(int i=0; i<buffersSize; i++)
@ -101,6 +133,19 @@ QMenu* CGAL::Three::Scene_item::contextMenu()
return defaultContextMenu;
}
CGAL::Three::Scene_group_item* CGAL::Three::Scene_item::parentGroup() const {
return parent_group;
}
void CGAL::Three::Scene_item::
moveToGroup(CGAL::Three::Scene_group_item* group) {
parent_group = group;
if(group)
has_group = group->has_group + 1;
else
has_group = 0;
}
void CGAL::Three::Scene_item::invalidateOpenGLBuffers() {}
void CGAL::Three::Scene_item::selection_changed(bool) {}

View File

@ -16,6 +16,7 @@ public:
bool twosides;
bool macro_mode;
bool inFastDrawing;
bool inDrawWithNames;
void draw_aux(bool with_names, Viewer*);
@ -31,6 +32,7 @@ Viewer::Viewer(QWidget* parent, bool antialiasing)
d->twosides = false;
d->macro_mode = false;
d->inFastDrawing = true;
d->inDrawWithNames = false;
d->shader_programs.resize(NB_OF_PROGRAMS);
setShortcut(EXIT_VIEWER, 0);
setShortcut(DRAW_AXIS, 0);
@ -321,6 +323,7 @@ void Viewer_impl::draw_aux(bool with_names, Viewer* viewer)
viewer->glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST);
viewer->glBlendFunc(GL_ONE, GL_ZERO);
}
inDrawWithNames = with_names;
if(with_names)
scene->drawWithNames(viewer);
else
@ -329,6 +332,10 @@ void Viewer_impl::draw_aux(bool with_names, Viewer* viewer)
viewer->glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
}
bool Viewer::inDrawWithNames() const {
return d->inDrawWithNames;
}
void Viewer::drawWithNames()
{
QGLViewer::draw();

View File

@ -59,6 +59,8 @@ public:
bool antiAliasing() const;
//! @returns the fastDrawing state.
bool inFastDrawing() const;
//! Implementation of `Viewer_interface::inDrawWithNames()`
bool inDrawWithNames() const;
//! Implementation of `Viewer_interface::attrib_buffers()`
void attrib_buffers(int program_name) const;
//! Implementation of `Viewer_interface::getShaderProgram()`

View File

@ -33,10 +33,8 @@ class Scene_draw_interface {
public:
virtual ~Scene_draw_interface(){}
virtual void initializeGL() = 0;
virtual void draw() = 0;
virtual void draw(CGAL::Three::Viewer_interface*) { draw(); };
virtual void drawWithNames() = 0;
virtual void drawWithNames(CGAL::Three::Viewer_interface*) { drawWithNames(); }
virtual void draw(CGAL::Three::Viewer_interface*) = 0;
virtual void drawWithNames(CGAL::Three::Viewer_interface*) = 0;
virtual bool keyPressEvent(QKeyEvent* e) = 0;
virtual float get_bbox_length() const = 0;
};

View File

@ -62,6 +62,15 @@ public :
bool supportsRenderingMode(RenderingMode m) const;
//!Prints the number of children.
QString toolTip() const;
/// Draw functions
///@{
virtual void draw(CGAL::Three::Viewer_interface*) const;
virtual void draw_edges(CGAL::Three::Viewer_interface*) const;
virtual void draw_points(CGAL::Three::Viewer_interface*) const;
virtual void draw_splats(CGAL::Three::Viewer_interface*) const;
///@}
//!Adds a Scene_item* to the list of children.
//!@see getChildren. @see removeChild.
void addChild(Scene_item* new_item);

View File

@ -43,6 +43,7 @@ class QKeyEvent;
namespace CGAL {
namespace Three {
class Scene_group_item;
class Viewer_interface;
//! This class represents an object in the OpenGL scene
class SCENE_ITEM_EXPORT Scene_item : public QObject {
@ -78,72 +79,12 @@ public:
//! The default color of a scene_item.
static const QColor defaultColor; // defined in Scene_item.cpp
//!The default Constructor.
/*!
* Initializes the number of VBOs to 20 and VAOs to 10 and creates them.
*/
Scene_item()
: name_("unamed"),
color_(defaultColor),
visible_(true),
are_buffers_filled(false),
rendering_mode(FlatPlusEdges),
defaultContextMenu(0),
buffersSize(20),
vaosSize(10),
vaos(10)
{
is_bbox_computed = false;
is_monochrome = true;
for(int i=0; i<vaosSize; i++)
{
addVaos(i);
vaos[i]->create();
}
buffers.reserve(buffersSize);
for(int i=0; i<buffersSize; i++)
{
QOpenGLBuffer n_buf;
buffers.push_back(n_buf);
buffers[i].create();
}
nb_isolated_vertices = 0;
has_group = 0;
}
//!The Constructor.
/*!
* Initializes the number of VBOs and VAOs and creates them.
*/
Scene_item(int buffers_size, int vaos_size)
: name_("unamed"),
color_(defaultColor),
visible_(true),
are_buffers_filled(false),
rendering_mode(FlatPlusEdges),
defaultContextMenu(0),
buffersSize(buffers_size),
vaosSize(vaos_size),
vaos(vaos_size)
{
is_bbox_computed = false;
is_monochrome = true;
for(int i=0; i<vaosSize; i++)
{
addVaos(i);
vaos[i]->create();
}
Scene_item(int buffers_size = 20, int vaos_size = 10);
buffers.reserve(buffersSize);
for(int i=0; i<buffersSize; i++)
{
QOpenGLBuffer n_buf;
buffers.push_back(n_buf);
buffers[i].create();
}
nb_isolated_vertices = 0;
has_group = 0;
}
//! Setter for the number of isolated vertices.
void setNbIsolatedvertices(std::size_t nb) { nb_isolated_vertices = nb;}
//! Getter for the number of isolated vertices.
@ -243,6 +184,9 @@ public:
//!Handles key press events.
virtual bool keyPressEvent(QKeyEvent*){return false;}
//!The parent group, or 0 if the item is not in a group.
Scene_group_item* parentGroup() const;
//!Contains the header for the table in the statistics dialog
/*!
* A header data is composed of 2 columns : the Categories and the titles.
@ -306,6 +250,10 @@ public Q_SLOTS:
virtual void setName(QString n) { name_ = n; }
//!Setter for the visibility of the item.
virtual void setVisible(bool b) { visible_ = b; }
//!Set the parent group. If `group==0`, then the item has no parent.
//!This function is called by `Scene::changeGroup` and should not be
//!called manually.
virtual void moveToGroup(Scene_group_item* group);
//!Setter for the rendering mode of the item.
//!@see RenderingMode
virtual void setRenderingMode(RenderingMode m) {
@ -378,6 +326,8 @@ protected:
QColor color_;
//!The visibility of the item.
bool visible_;
//!The parent group, or 0 if the item is not in a group.
Scene_group_item* parent_group;
//!Specifies if the item is currently selected.
bool is_selected;
//! Specifies if the item is monochrome and uses uniform attribute for its color

View File

@ -80,6 +80,8 @@ public:
static QString dumpFrame(const qglviewer::Frame&);
//! @returns the fastDrawing state.
virtual bool inFastDrawing() const = 0;
//! @returns if the viewer is in `drawWithNames()`
virtual bool inDrawWithNames() const = 0;
/*! Passes all the uniform data to the shaders.
* According to program_name, this data may change.