From 1882658a94ffc900fa5c75a78fdeb76f21efe2a1 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 2 May 2018 11:05:05 +0200 Subject: [PATCH] Add depth-peeling to the scene. --- .../Plugins/Mesh_3/Io_image_plugin.cpp | 3 +- Polyhedron/demo/Polyhedron/Scene.cpp | 494 ++++++++++++++++-- Polyhedron/demo/Polyhedron/Scene.h | 25 +- Polyhedron/demo/Polyhedron/Scene_c3t3_item.h | 2 +- .../demo/Polyhedron/Scene_group_item.cpp | 156 +++++- Polyhedron/demo/Polyhedron/Scene_item.cpp | 12 + .../demo/Polyhedron/Scene_polylines_item.h | 2 +- .../Polyhedron/Scene_surface_mesh_item.cpp | 64 ++- .../demo/Polyhedron/Scene_surface_mesh_item.h | 5 +- Polyhedron/demo/Polyhedron/Viewer.cpp | 29 + Polyhedron/demo/Polyhedron/Viewer.h | 8 +- .../Polyhedron/resources/shader_with_light.f | 96 ++-- .../Polyhedron/resources/shader_with_light.v | 7 +- Three/include/CGAL/Three/Scene_group_item.h | 119 +++-- Three/include/CGAL/Three/Scene_item.h | 20 +- Three/include/CGAL/Three/Viewer_interface.h | 11 + 16 files changed, 900 insertions(+), 153 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Io_image_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Io_image_plugin.cpp index 8c9957ac8bd..314e0a4792b 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Io_image_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Io_image_plugin.cpp @@ -807,8 +807,9 @@ private Q_SLOTS: this, SLOT(erase_group())); group_map.remove(img_item); QList deletion; - Q_FOREACH(Scene_item* child, group->getChildren()) + Q_FOREACH(Scene_interface::Item_id id, group->getChildren()) { + Scene_item* child = group->getChild(id); group->unlockChild(child); deletion.append(scene->item_id(child)); } diff --git a/Polyhedron/demo/Polyhedron/Scene.cpp b/Polyhedron/demo/Polyhedron/Scene.cpp index 1ffdc5f96aa..fec0ee23ac1 100644 --- a/Polyhedron/demo/Polyhedron/Scene.cpp +++ b/Polyhedron/demo/Polyhedron/Scene.cpp @@ -24,6 +24,7 @@ #include #include #include +#include Scene::Scene(QObject* parent) @@ -37,6 +38,8 @@ Scene::Scene(QObject* parent) double, double, double)), this, SLOT(setSelectionRay(double, double, double, double, double, double))); + connect(this, SIGNAL(indexErased(Scene_interface::Item_id)), + this, SLOT(adjustIds(Scene_interface::Item_id))); picked = false; gl_init = false; @@ -46,6 +49,7 @@ Scene::addItem(CGAL::Three::Scene_item* item) { Bbox bbox_before = bbox(); m_entries.push_back(item); + Item_id id = m_entries.size() - 1; connect(item, SIGNAL(itemChanged()), this, SLOT(itemChanged())); connect(item, SIGNAL(itemVisibilityChanged()), @@ -70,7 +74,7 @@ Scene::addItem(CGAL::Three::Scene_item* item) index_map[list.at(i)->index()] = m_entries.size() -1; } Q_EMIT updated(); - Item_id id = m_entries.size() - 1; + children.push_back(id); Q_EMIT newItem(id); CGAL::Three::Scene_group_item* group = qobject_cast(item); @@ -95,13 +99,14 @@ Scene::replaceItem(Scene::Item_id index, CGAL::Three::Scene_item* item, bool emi qobject_cast(m_entries[index]); if(group) { - QList children; - Q_FOREACH(CGAL::Three::Scene_item* child, group->getChildren()) + QList group_children; + Q_FOREACH(Item_id id, group->getChildren()) { + CGAL::Three::Scene_item* child = group->getChild(id); group->unlockChild(child); - children << item_id(child); + group_children << item_id(child); } - erase(children); + erase(group_children); } CGAL::Three::Scene_group_item* parent = m_entries[index]->parentGroup(); bool is_locked = false; @@ -166,7 +171,10 @@ Scene::erase(Scene::Item_id index) item->parentGroup()->removeChild(item); //removes the item from all groups that contain it - m_entries.removeAll(item); + Item_id removed_item = item_id(item); + children.removeAll(removed_item); + indexErased(removed_item); + m_entries.removeAll(item); Q_EMIT itemAboutToBeDestroyed(item); item->aboutToBeDestroyed(); item->deleteLater(); @@ -207,8 +215,9 @@ Scene::erase(QList indices) Scene_group_item* group = qobject_cast(item); if(group) { - Q_FOREACH(Scene_item* child, group->getChildren()) + Q_FOREACH(Item_id id, group->getChildren()) { + CGAL::Three::Scene_item* child = group->getChild(id); if(!to_be_removed.contains(child)) to_be_removed.push_back(child); } @@ -220,7 +229,11 @@ Scene::erase(QList indices) Q_FOREACH(Scene_item* item, to_be_removed) { if(item->parentGroup()) item->parentGroup()->removeChild(item); - m_entries.removeAll(item); + Item_id removed_item = item_id(item); + children.removeAll(removed_item); + indexErased(removed_item); + m_entries.removeAll(item); + Q_EMIT itemAboutToBeDestroyed(item); item->aboutToBeDestroyed(); item->deleteLater(); @@ -255,6 +268,7 @@ void Scene::remove_item_from_groups(Scene_item* item) if(group) { group->removeChild(item); + children.push_back(item_id(item)); } } Scene::~Scene() @@ -308,22 +322,96 @@ Scene::duplicate(Item_id index) void Scene::initializeGL(CGAL::Three::Viewer_interface* viewer) { - - //Setting the light options - - // Create light components - GLfloat ambientLight[] = { 0.4f, 0.4f, 0.4f, 1.0f }; - GLfloat diffuseLight[] = { 1.0f, 1.0f, 1.0, 1.0f }; - GLfloat specularLight[] = { 0.0f, 0.0f, 0.0f, 1.0f }; - GLfloat position[] = { 0.0f, 0.0f, 1.0f, 1.0f }; - - // Assign created components to GL_LIGHT0 - viewer->glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight); - viewer->glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight); - viewer->glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight); - viewer->glLightfv(GL_LIGHT0, GL_POSITION, position); - - gl_init = true; + + //Vertex source code + const char vertex_source[] = + { + "#version 120 \n" + "attribute highp vec4 vertex; \n" + "attribute highp vec2 v_texCoord; \n" + "uniform highp mat4 projection_matrix; \n" + "varying highp vec2 f_texCoord; \n" + "void main(void) \n" + "{ \n" + " f_texCoord = v_texCoord; \n" + " gl_Position = projection_matrix * vertex; \n" + "} \n" + + }; + //Fragment source code + const char fragment_source[] = + { + "#version 120 \n" + "varying highp vec2 f_texCoord; \n" + "uniform sampler2D texture; \n" + "void main(void) \n" + "{ \n" + " gl_FragColor = texture2D(texture, f_texCoord); \n" + "} \n" + }; + + + QOpenGLShader *vertex_shader = new QOpenGLShader(QOpenGLShader::Vertex); + if(!vertex_shader->compileSourceCode(vertex_source)) + { + std::cerr<<"Compiling vertex source FAILED"<compileSourceCode(fragment_source)) + { + std::cerr<<"Compiling fragmentsource FAILED"<makeCurrent(); + vao = new QOpenGLVertexArrayObject(); + vao->create(); + program.bind(); + vao->bind(); + vbo[0].bind(); + vbo[0].allocate(points, 18 * sizeof(float)); + program.enableAttributeArray("vertex"); + program.setAttributeArray("vertex", GL_FLOAT, 0, 3); + vbo[0].release(); + + vbo[1].bind(); + vbo[1].allocate(uvs, 12 * sizeof(float)); + program.enableAttributeArray("v_texCoord"); + program.setAttributeArray("v_texCoord", GL_FLOAT, 0, 2); + vbo[1].release(); + vao->release(); + program.release(); + gl_init = true; } void Scene::s_itemAboutToBeDestroyed(CGAL::Three::Scene_item *rmv_itm) @@ -367,15 +455,321 @@ bool item_should_be_skipped_in_draw(Scene_item* item) { } return true; } + +void Scene::renderScene(const QList &items, + Viewer_interface *viewer, + QMap& picked_item_IDs, + bool with_names, + int pass, + bool writing_depth, + QOpenGLFramebufferObject *fbo) +{ + viewer->makeCurrent(); + viewer->setCurrentPass(pass); + viewer->setDepthWriting(writing_depth); + viewer->setDepthPeelingFbo(fbo); + Q_FOREACH(Scene_interface::Item_id index, items) + { + CGAL::Three::Scene_item& item = *m_entries[index]; + CGAL::Three::Scene_group_item* group = + qobject_cast(&item); + if(index == selected_item || selected_items_list.contains(index)) + { + item.selection_changed(true); + } + else + + { + item.selection_changed(false); + } + + if(group ||item.visible()) + { + if( group || item.renderingMode() == Flat || item.renderingMode() == FlatPlusEdges || item.renderingMode() == Gouraud) + { + if(with_names) { + viewer->glClearDepth(1.0); + viewer->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } + if(item.renderingMode() == Gouraud) + viewer->glShadeModel(GL_SMOOTH); + else + viewer->glShadeModel(GL_FLAT); + item.draw(viewer); + } + + if(with_names) { + + // read depth buffer at pick location; + float depth = 1.0; + viewer->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(group) + group->renderChildren(viewer, picked_item_IDs, picked_pixel, with_names); + } + } +} + +void Scene::renderWireScene(const QList &items, + Viewer_interface *viewer, + QMap& picked_item_IDs, + bool with_names) +{ + Q_FOREACH(Scene_interface::Item_id index, items) + { + CGAL::Three::Scene_item& item = *m_entries[index]; + CGAL::Three::Scene_group_item* group = + qobject_cast(&item); + if(index == selected_item || selected_items_list.contains(index)) + { + item.selection_changed(true); + } + else + { + item.selection_changed(false); + } + + if(group ||item.visible()) + { + if( group || (!with_names && item.renderingMode() == FlatPlusEdges ) + || item.renderingMode() == Wireframe + || item.renderingMode() == PointsPlusNormals) + { + viewer->glDisable(GL_LIGHTING); + viewer->glPointSize(2.f); + viewer->glLineWidth(1.0f); + item.drawEdges(viewer); + } + else{ + if( item.renderingMode() == PointsPlusNormals ){ + viewer->glDisable(GL_LIGHTING); + 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); + } + item.drawEdges(viewer); + } + } + + if((item.renderingMode() == Wireframe || item.renderingMode() == PointsPlusNormals ) + && with_names) + { + + // read depth buffer at pick location; + float depth = 1.0; + viewer->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; + } + } + } + } +} + +void Scene::renderPointScene(const QList &items, + Viewer_interface *viewer, + QMap& picked_item_IDs, + bool with_names) +{ + Q_FOREACH(Scene_interface::Item_id index, items) + { + CGAL::Three::Scene_item& item = *m_entries[index]; + CGAL::Three::Scene_group_item* group = + qobject_cast(&item); + if(group ||item.visible()) + { + if(item.renderingMode() == Points && with_names) { + viewer->glClearDepth(1.0); + viewer->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } + + if(group || item.renderingMode() == Points || + (item.renderingMode() == PointsPlusNormals) || + (item.renderingMode() == ShadedPoints)) + { + viewer->glDisable(GL_LIGHTING); + viewer->glPointSize(3.0f); + viewer->glLineWidth(1.0f); + item.drawPoints(viewer); + } + if(item.renderingMode() == Points && with_names) { + // read depth buffer at pick location; + float depth = 1.0; + viewer->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; + } + } + } + } +} + + + bool Scene::has_alpha() + { + Q_FOREACH(Scene_item* item, m_entries) + if(item->alpha() != 1.0f) + return true; + return false; + } void Scene::draw_aux(bool with_names, CGAL::Three::Viewer_interface* viewer) { + viewer->makeCurrent(); QMap picked_item_IDs; if(with_names) viewer->glEnable(GL_DEPTH_TEST); if(!gl_init) initializeGL(viewer); + renderScene(children, viewer, picked_item_IDs, with_names, -1, false, NULL); + if(!with_names && has_alpha()) + { + std::vector fbos; + std::vector depth_test; + QColor background = viewer->backgroundColor(); + + fbos.resize((int)viewer->total_pass()); + depth_test.resize((int)viewer->total_pass()-1); + + //first pass + fbos[0] = new QOpenGLFramebufferObject(viewer->width(), viewer->height(),QOpenGLFramebufferObject::Depth, GL_TEXTURE_2D, GL_RGBA32F); + fbos[0]->bind(); + viewer->glDisable(GL_BLEND); + viewer->glEnable(GL_DEPTH_TEST); + viewer->glDepthFunc(GL_LESS); + viewer->glEnable(GL_ALPHA_TEST); + viewer->glClearColor(0.0f, + 0.0f, + 0.0f, + 0.0f); + viewer->glClearDepth(1); + viewer->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + renderScene(children, viewer, picked_item_IDs, false, 0,false, NULL); + fbos[0]->release(); + depth_test[0] = new QOpenGLFramebufferObject(viewer->width(), viewer->height(),QOpenGLFramebufferObject::Depth, GL_TEXTURE_2D, GL_RGBA32F); + depth_test[0]->bind(); + viewer->glDisable(GL_BLEND); + viewer->glEnable(GL_DEPTH_TEST); + viewer->glDepthFunc(GL_LESS); + viewer->glEnable(GL_ALPHA_TEST); + viewer->glClearColor(0.0f, + 0.0f, + 0.0f, + 0.0f); + viewer->glClearDepth(1); + viewer->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + renderScene(children, viewer, picked_item_IDs, false, 0,true, NULL); + depth_test[0]->release(); + + //other passes + for(int i=1; itotal_pass()-1; ++i) + { + fbos[i] = new QOpenGLFramebufferObject(viewer->width(), viewer->height(),QOpenGLFramebufferObject::Depth, GL_TEXTURE_2D, GL_RGBA32F); + fbos[i]->bind(); + viewer->glDisable(GL_BLEND); + viewer->glEnable(GL_DEPTH_TEST); + viewer->glDepthFunc(GL_LESS); + viewer->glEnable(GL_ALPHA_TEST); + viewer->glClearColor(0.0f, + 0.0f, + 0.0f, + 0.0f); + viewer->glClearDepth(1); + viewer->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + renderWireScene(children, viewer, picked_item_IDs, false); + renderPointScene(children, viewer, picked_item_IDs, false); + renderScene(children, viewer, picked_item_IDs, false, i, false, depth_test[i-1]); + fbos[i]->release(); + + depth_test[i] = new QOpenGLFramebufferObject(viewer->width(), viewer->height(),QOpenGLFramebufferObject::Depth, GL_TEXTURE_2D, GL_RGBA32F); + depth_test[i]->bind(); + viewer->glDisable(GL_BLEND); + viewer->glEnable(GL_DEPTH_TEST); + viewer->glDepthFunc(GL_LESS); + viewer->glEnable(GL_ALPHA_TEST); + viewer->glClearColor(0.0f, + 0.0f, + 0.0f, + 0.0f); + viewer->glClearDepth(1); + viewer->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + renderScene(children, viewer, picked_item_IDs, false, i, true, depth_test[i-1]); + depth_test[i]->release(); + } + + + //last pass + fbos[(int)viewer->total_pass()-1] = new QOpenGLFramebufferObject(viewer->width(), viewer->height(),QOpenGLFramebufferObject::Depth, GL_TEXTURE_2D, GL_RGBA32F); + fbos[(int)viewer->total_pass()-1]->bind(); + viewer->glDisable(GL_BLEND); + viewer->glEnable(GL_DEPTH_TEST); + viewer->glDepthFunc(GL_LESS); + viewer->glEnable(GL_ALPHA_TEST); + viewer->glClearColor(0.0f, + 0.0f, + 0.0f, + 0.0f); + viewer->glClearDepth(1); + viewer->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + renderScene(children, viewer, picked_item_IDs, false, (int)viewer->total_pass()-1, false, depth_test[(int)viewer->total_pass()-2]); + fbos[(int)viewer->total_pass()-1]->release(); + + + //blending + program.bind(); + vao->bind(); + viewer->glClearColor(background.redF(), + background.greenF(), + background.blueF(), + 1.0f); + viewer->glDisable(GL_DEPTH_TEST); + viewer->glClear(GL_COLOR_BUFFER_BIT); + viewer->glEnable(GL_BLEND); + viewer->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + QMatrix4x4 proj_mat; + proj_mat.setToIdentity(); + proj_mat.ortho(-1,1,-1,1,0,1); + program.setUniformValue("projection_matrix", proj_mat); + for(int i=0; i< (int)viewer->total_pass()-1; ++i) + delete depth_test[i]; + for(int i = (int)viewer->total_pass()-1; i>=0; --i) + { + viewer->glBindTexture(GL_TEXTURE_2D, fbos[i]->texture()); + viewer->glDrawArrays(GL_TRIANGLES,0,static_cast(6)); + delete fbos[i]; + } + viewer->glDisable(GL_BLEND); + viewer->glEnable(GL_DEPTH_TEST); + vao->release(); + program.release(); + } + + viewer->glDepthFunc(GL_LEQUAL); + // Wireframe OpenGL drawing + renderWireScene(children, viewer, picked_item_IDs, with_names); + // Points OpenGL drawing + renderPointScene(children, viewer, picked_item_IDs, with_names); + + /*{ // Flat/Gouraud OpenGL drawing for(int index = 0; index < m_entries.size(); ++index) { @@ -575,7 +969,7 @@ Scene::draw_aux(bool with_names, CGAL::Three::Viewer_interface* viewer) } } } - +//}*/ if(with_names) { QList depths = picked_item_IDs.keys(); @@ -784,8 +1178,11 @@ bool Scene::dropMimeData(const QMimeData * /*data*/, CGAL::Three::Scene_group_item* group = qobject_cast(item(i)); if(group) - Q_FOREACH(Scene_item* child, group->getChildren()) + Q_FOREACH(Item_id id, group->getChildren()) + { + CGAL::Three::Scene_item* child = item(id); groups_children << item_id(child); + } } // Insure that children of selected groups will not be added twice Q_FOREACH(int i, selected_items_list) @@ -803,7 +1200,7 @@ bool Scene::dropMimeData(const QMimeData * /*data*/, if(group) { Q_FOREACH(int id, selected_items_list) - if(group->getChildren().contains(item(id))) + if(group->getChildren().contains(id)) { one_contained = true; break; @@ -821,6 +1218,7 @@ bool Scene::dropMimeData(const QMimeData * /*data*/, if(item->parentGroup()) { item->parentGroup()->removeChild(item); + children.push_back(item_id(item)); } } redraw_model(); @@ -844,7 +1242,7 @@ void Scene::moveRowUp() Scene_group_item* group = selected_item->parentGroup(); if(group) { - int id = group->getChildren().indexOf(selected_item); + int id = group->getChildren().indexOf(item_id(selected_item)); group->moveUp(id); } } @@ -852,8 +1250,9 @@ void Scene::moveRowUp() { //if not in group QModelIndex baseId = index_map.key(mainSelectionIndex()); - int newId = index_map.value(index(baseId.row()-1, baseId.column(),baseId.parent())) ; - m_entries.move(mainSelectionIndex(), newId); + int newId = children.indexOf( + index_map.value(index(baseId.row()-1, baseId.column(),baseId.parent()))) ; + children.move(children.indexOf(item_id(selected_item)), newId); } redraw_model(); setSelectedItem(m_entries.indexOf(selected_item)); @@ -869,7 +1268,7 @@ void Scene::moveRowDown() Scene_group_item* group = selected_item->parentGroup(); if(group) { - int id = group->getChildren().indexOf(selected_item); + int id = group->getChildren().indexOf(item_id(selected_item)); group->moveDown(id); } } @@ -877,7 +1276,8 @@ void Scene::moveRowDown() { //if not in group QModelIndex baseId = index_map.key(mainSelectionIndex()); - int newId = index_map.value(index(baseId.row()+1, baseId.column(),baseId.parent())) ; + int newId = children.indexOf( + index_map.value(index(baseId.row()+1, baseId.column(),baseId.parent()))) ; m_entries.move(mainSelectionIndex(), newId); } redraw_model(); @@ -1158,9 +1558,10 @@ void Scene::redraw_model() clear(); index_map.clear(); //fills the model - Q_FOREACH(Scene_item* item, m_entries) + Q_FOREACH(Item_id id, children) + { - organize_items(item, invisibleRootItem(), 0); + organize_items(m_entries[id], invisibleRootItem(), 0); } Q_EMIT restoreCollapsedState(); } @@ -1172,7 +1573,12 @@ void Scene::changeGroup(Scene_item *item, CGAL::Three::Scene_group_item *target_ if(item->parentGroup()->isChildLocked(item)) return; item->parentGroup()->removeChild(item); + children.push_back(item_id(item)); } + else + { + children.removeAll(item_id(item)); + } //add the item to the target group target_group->addChild(item); item->moveToGroup(target_group); @@ -1292,8 +1698,9 @@ void Scene::organize_items(Scene_item* item, QStandardItem* root, int loop) qobject_cast(item); if(group) { - Q_FOREACH(Scene_item*child, group->getChildren()) - { + Q_FOREACH(Item_id id, group->getChildren()) + { + CGAL::Three::Scene_item* child = group->getChild(id); organize_items(child, list.first(), loop+1); } } @@ -1332,6 +1739,8 @@ QList Scene::getModelIndexFromId(int id) const void Scene::addGroup(Scene_group_item* group) { connect(this, SIGNAL(drawFinished()), group, SLOT(resetDraw())); + connect(this, SIGNAL(indexErased(Scene_interface::Item_id)), + group, SLOT(adjustIds(Scene_interface::Item_id))); group->setScene(this); } @@ -1387,3 +1796,16 @@ void Scene::zoomToPosition(QPoint point, Viewer_interface *viewer) } } } + +void Scene::adjustIds(Item_id removed_id) +{ + for(int i = 0; i < children.size(); ++i) + { + if(children[i] >= removed_id) + --children[i]; + } + for(int i = removed_id; i < numberOfEntries(); ++i) + { + m_entries[i]->setId(i-1);//the signal is emitted before m_entries is amputed from the item, so new id is current id -1. + } +} diff --git a/Polyhedron/demo/Polyhedron/Scene.h b/Polyhedron/demo/Polyhedron/Scene.h index 48545a07753..aa778970fb7 100644 --- a/Polyhedron/demo/Polyhedron/Scene.h +++ b/Polyhedron/demo/Polyhedron/Scene.h @@ -24,6 +24,7 @@ #include class QEvent; class QMouseEvent; +class QOpenGLFramebufferObject; namespace CGAL { namespace Three{ class Viewer_interface;}} //! This class is not supposed to be used by Plugins, but sometimes you may need access to @@ -190,8 +191,8 @@ public Q_SLOTS: if(group) { QList list; - Q_FOREACH(CGAL::Three::Scene_item* child, group->getChildrenForSelection()) - list<getChildrenForSelection()) + list<update();} void s_itemAboutToBeDestroyed(CGAL::Three::Scene_item *); @@ -241,12 +245,24 @@ private: * to its current renderingMode. If with_names is true, uses * the OpenGL mode GL_WITH_NAMES, essentially used for the picking.*/ void draw_aux(bool with_names, CGAL::Three::Viewer_interface*); + bool has_alpha(); + void renderScene(const QList &items, + CGAL::Three::Viewer_interface* viewer, QMap &picked_item_IDs, bool with_names, + int pass, bool writing_depth, + QOpenGLFramebufferObject* fbo); + void renderWireScene(const QList &items, + Viewer_interface *viewer, QMap &picked_item_IDs, bool with_names); + void renderPointScene(const QList &items, + Viewer_interface *viewer, + QMap& picked_item_IDs, + bool with_names); // Re-draw the hierarchy of the view. void organize_items(CGAL::Three::Scene_item* item, QStandardItem *root, int loop); // List of Scene_items. typedef QList Entries; //List containing all the scene_items. Entries m_entries; + QList children; // Index of the currently selected item. int selected_item; //List of indices of the currently selected items. @@ -259,6 +275,11 @@ private: QPoint picked_pixel; bool gl_init; QMap index_map; + float points[18]; + float uvs[12]; + QOpenGLShaderProgram program; + QOpenGLVertexArrayObject* vao; + mutable QOpenGLBuffer vbo[2]; }; // end class Scene diff --git a/Polyhedron/demo/Polyhedron/Scene_c3t3_item.h b/Polyhedron/demo/Polyhedron/Scene_c3t3_item.h index 465a8c6fd16..fd8e84d40b0 100644 --- a/Polyhedron/demo/Polyhedron/Scene_c3t3_item.h +++ b/Polyhedron/demo/Polyhedron/Scene_c3t3_item.h @@ -119,7 +119,7 @@ public: void drawEdges(CGAL::Three::Viewer_interface* viewer) const Q_DECL_OVERRIDE; void drawPoints(CGAL::Three::Viewer_interface * viewer) const Q_DECL_OVERRIDE; //When selecting a c3t3 item, we don't want to select its children, so we can still apply Operations to it - QList getChildrenForSelection() const Q_DECL_OVERRIDE { return QList(); } + QList getChildrenForSelection() const Q_DECL_OVERRIDE { return QList(); } public: QMenu* contextMenu() Q_DECL_OVERRIDE; void copyProperties(Scene_item *) Q_DECL_OVERRIDE; diff --git a/Polyhedron/demo/Polyhedron/Scene_group_item.cpp b/Polyhedron/demo/Polyhedron/Scene_group_item.cpp index 39da3bf8416..4514839653b 100644 --- a/Polyhedron/demo/Polyhedron/Scene_group_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_group_item.cpp @@ -14,16 +14,16 @@ Scene_group_item::Scene_group_item(QString name, int nb_vbos, int nb_vaos ) bool Scene_group_item::isFinite() const { - Q_FOREACH(Scene_item *item, children) - if(!item->isFinite()){ - return false; - } - return true; + Q_FOREACH(Scene_interface::Item_id id, children) + if(!getChild(id)->isFinite()){ + return false; + } + return true; } bool Scene_group_item::isEmpty() const { - Q_FOREACH(Scene_item *item, children) - if(!item->isEmpty()){ + Q_FOREACH(Scene_interface::Item_id id, children) + if(!getChild(id)->isEmpty()){ return true; } return true; @@ -37,8 +37,8 @@ Scene_group_item::Bbox Scene_group_item::bbox() const bool Scene_group_item::supportsRenderingMode(RenderingMode m) const { - Q_FOREACH(Scene_item* item, children) - if(!item->supportsRenderingMode(m)) + Q_FOREACH(Scene_interface::Item_id id, children) + if(!getChild(id)->supportsRenderingMode(m)) return false; return true; @@ -53,38 +53,50 @@ QString Scene_group_item::toolTip() const { void Scene_group_item::addChild(Scene_item* new_item) { - if(!children.contains(new_item)) + if(!children.contains(scene->item_id(new_item))) { - children.append(new_item); + children.append(scene->item_id(new_item)); update_group_number(new_item, has_group+1); } } +void Scene_group_item::addChild(Scene_interface::Item_id new_id) +{ + if(!children.contains(new_id)) + { + children.append(new_id); + update_group_number(getChild(new_id), has_group+1); + } +} + void Scene_group_item::update_group_number(Scene_item * new_item, int n) { Scene_group_item* group = qobject_cast(new_item); if(group) - Q_FOREACH(Scene_item* child, group->getChildren()) - update_group_number(child,n+1); + Q_FOREACH(Scene_interface::Item_id id, group->getChildren()){ + + update_group_number(getChild(id),n+1); + } new_item->has_group = n; } void Scene_group_item::setColor(QColor c) { Scene_item::setColor(c); - Q_FOREACH(Scene_item* child, children) + Q_FOREACH(Scene_interface::Item_id id, children) { - child->setColor(c); + getChild(id)->setColor(c); } } void Scene_group_item::setRenderingMode(RenderingMode m) { Scene_item::setRenderingMode(m); - Q_FOREACH(Scene_item* child, children) + Q_FOREACH(Scene_interface::Item_id id, children) { + Scene_item* child = getChild(id); if(child->supportsRenderingMode(m)) child->setRenderingMode(m); } @@ -93,8 +105,9 @@ void Scene_group_item::setRenderingMode(RenderingMode m) void Scene_group_item::setVisible(bool b) { Scene_item::setVisible(b); - Q_FOREACH(Scene_item* child, children) + Q_FOREACH(Scene_interface::Item_id id, children) { + Scene_item* child = getChild(id); child->setVisible(b); child->itemChanged(); } @@ -123,7 +136,9 @@ void Scene_group_item::moveUp(int i) void Scene_group_item::draw(CGAL::Three::Viewer_interface* viewer) const { if(viewer->inDrawWithNames() || already_drawn ) return; - Q_FOREACH(Scene_item* child, children) { + Q_FOREACH(Scene_interface::Item_id id, children) + { + Scene_item* child = getChild(id); if(!child->visible()) continue; switch(child->renderingMode()) { case Flat: @@ -153,7 +168,9 @@ void Scene_group_item::draw(CGAL::Three::Viewer_interface* viewer) const { void Scene_group_item::drawEdges(CGAL::Three::Viewer_interface* viewer) const { if(viewer->inDrawWithNames() || already_drawn ) return; - Q_FOREACH(Scene_item* child, children) { + Q_FOREACH(Scene_interface::Item_id id, children) + { + Scene_item* child = getChild(id); if(!child->visible()) continue; switch(child->renderingMode()) { case FlatPlusEdges: @@ -183,7 +200,9 @@ void Scene_group_item::drawEdges(CGAL::Three::Viewer_interface* viewer) const void Scene_group_item::drawPoints(CGAL::Three::Viewer_interface* viewer) const { if(viewer->inDrawWithNames() || already_drawn ) return; - Q_FOREACH(Scene_item* child, children) { + Q_FOREACH(Scene_interface::Item_id id, children) + { + Scene_item* child = getChild(id); if(!child->visible()) continue; switch(child->renderingMode()) { case Points: @@ -210,22 +229,101 @@ void Scene_group_item::drawPoints(CGAL::Three::Viewer_interface* viewer) const already_drawn = true; } +void Scene_group_item::renderChildren(Viewer_interface *viewer, + QMap& picked_item_IDs, + const QPoint& picked_pixel, + bool with_names) +{ + + Q_FOREACH(Scene_interface::Item_id id, children){ + if(with_names) { + viewer->glClearDepth(1.0); + viewer->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } + if(id == scene->mainSelectionIndex()|| scene->selectionIndices().contains(id)) + { + getChild(id)->selection_changed(true); + } + else + { + getChild(id)->selection_changed(false); + } + if(getChild(id)->visible() && + (getChild(id)->renderingMode() == Flat || + getChild(id)->renderingMode() == FlatPlusEdges || + getChild(id)->renderingMode() == Gouraud)) + { + getChild(id)->draw(viewer); + } + + if(getChild(id)->visible() && + (getChild(id)->renderingMode() == FlatPlusEdges + || getChild(id)->renderingMode() == Wireframe + || getChild(id)->renderingMode() == PointsPlusNormals)) + { + getChild(id)->drawEdges(viewer); + } + + if(getChild(id)->visible() && + (getChild(id)->renderingMode() == Points || + (getChild(id)->renderingMode() == PointsPlusNormals) || + (getChild(id)->renderingMode() == ShadedPoints))) + { + getChild(id)->drawPoints(viewer); + } + if(with_names) { + // read depth buffer at pick location; + float depth = 1.0; + viewer->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] = id; + } + } + } +} + void Scene_group_item::lockChild(Scene_item *child) { - if(!children.contains(child)) + lockChild(scene->item_id(child)); +} + +void Scene_group_item::lockChild(Scene_interface::Item_id id) +{ + if(!children.contains(id)) return; - child->setProperty("lock", true); + getChild(id)->setProperty("lock", true); +} + +void Scene_group_item::unlockChild(Scene_interface::Item_id id) +{ + if(!children.contains(id)) + return; + getChild(id)->setProperty("lock", false); } void Scene_group_item::unlockChild(Scene_item *child) { - if(!children.contains(child)) - return; - child->setProperty("lock", false); + unlockChild(scene->item_id(child)); } +bool Scene_group_item::isChildLocked(Scene_interface::Item_id id) +{ + if(!children.contains(id) + || (!getChild(id)->property("lock").toBool()) ) + return false; + return true; + } bool Scene_group_item::isChildLocked(Scene_item *child) { - if(!children.contains(child) - || (!child->property("lock").toBool()) ) - return false; - return true; + return isChildLocked(scene->item_id(child)); } + +void Scene_group_item::setAlpha(int ) +{ + + Q_FOREACH(Scene_interface::Item_id id, children) + { + scene->item(id)->setAlpha(static_cast(alpha()*255)); + } +} + diff --git a/Polyhedron/demo/Polyhedron/Scene_item.cpp b/Polyhedron/demo/Polyhedron/Scene_item.cpp index a11c68658e8..ab71b73c78c 100644 --- a/Polyhedron/demo/Polyhedron/Scene_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_item.cpp @@ -229,3 +229,15 @@ void CGAL::Three::Scene_item::compute_diag_bbox()const ); } + +void Scene_item::setId(int id) {cur_id = id; } +int Scene_item::getId() const { return cur_id; } +float Scene_item::alpha() const +{ + return 1.0f; +} + +void Scene_item::setAlpha(int ) +{ + +} diff --git a/Polyhedron/demo/Polyhedron/Scene_polylines_item.h b/Polyhedron/demo/Polyhedron/Scene_polylines_item.h index 75c854438b2..a59f4b8abb2 100644 --- a/Polyhedron/demo/Polyhedron/Scene_polylines_item.h +++ b/Polyhedron/demo/Polyhedron/Scene_polylines_item.h @@ -64,7 +64,7 @@ public: void smooth(std::vector& polyline); //When selecting a polylineitem, we don't want to select its children, so we can still apply Operations to it - QList getChildrenForSelection() const { return QList(); } + QList getChildrenForSelection() const { return QList(); } public Q_SLOTS: virtual void invalidateOpenGLBuffers(); diff --git a/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp b/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp index d3de2a71771..d84148b0613 100644 --- a/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp @@ -11,6 +11,9 @@ #include #include #include +#include +#include +#include //#include #include @@ -91,6 +94,7 @@ struct Scene_surface_mesh_item_priv{ vertices_displayed = false; edges_displayed = false; faces_displayed = false; + alphaSlider = NULL; } Scene_surface_mesh_item_priv(SMesh* sm, Scene_surface_mesh_item *parent): @@ -102,10 +106,13 @@ struct Scene_surface_mesh_item_priv{ vertices_displayed = false; edges_displayed = false; faces_displayed = false; + alphaSlider = NULL; } ~Scene_surface_mesh_item_priv() { + if(alphaSlider) + delete alphaSlider; if(smesh_) { delete smesh_; @@ -199,6 +206,7 @@ struct Scene_surface_mesh_item_priv{ unsigned int number_of_degenerated_faces; int genus; bool self_intersect; + QSlider* alphaSlider; }; const char* aabb_property_name = "Scene_surface_mesh_item aabb tree"; @@ -313,7 +321,13 @@ void Scene_surface_mesh_item_priv::addFlatData(Point p, EPICK::Vector_3 n, CGAL: void Scene_surface_mesh_item_priv::compute_elements() { QApplication::setOverrideCursor(Qt::WaitCursor); - + if(!alphaSlider) + { + alphaSlider = new QSlider(::Qt::Horizontal); + alphaSlider->setMinimum(0); + alphaSlider->setMaximum(255); + alphaSlider->setValue(255); + } smooth_vertices.clear(); smooth_normals.clear(); flat_vertices.clear(); @@ -652,6 +666,7 @@ void Scene_surface_mesh_item_priv::initializeBuffers(CGAL::Three::Viewer_interfa void Scene_surface_mesh_item::draw(CGAL::Three::Viewer_interface *viewer) const { viewer->glShadeModel(GL_SMOOTH); + QOpenGLFramebufferObject* fbo = viewer->depthPeelingFbo(); if(!are_buffers_filled) { d->compute_elements(); @@ -664,10 +679,16 @@ void Scene_surface_mesh_item::draw(CGAL::Three::Viewer_interface *viewer) const if(renderingMode() == Gouraud) { vaos[Scene_surface_mesh_item_priv::Smooth_facets]->bind(); - if(is_selected) - d->program->setAttributeValue("is_selected", true); - else - d->program->setAttributeValue("is_selected", false); + d->program->setAttributeValue("is_selected", is_selected); + d->program->setUniformValue("comparing", viewer->currentPass() > 0);; + d->program->setUniformValue("width", viewer->width()*1.0f); + d->program->setUniformValue("height", viewer->height()*1.0f); + d->program->setUniformValue("near", (float)viewer->camera()->zNear()); + d->program->setUniformValue("far", (float)viewer->camera()->zFar()); + d->program->setUniformValue("writing", viewer->isDepthWriting()); + d->program->setUniformValue("alpha", alpha()); + if( fbo) + viewer->glBindTexture(GL_TEXTURE_2D, fbo->texture()); if(!d->has_vcolors) d->program->setAttributeValue("colors", this->color()); viewer->glDrawElements(GL_TRIANGLES, static_cast(d->idx_data_.size()), @@ -683,6 +704,15 @@ void Scene_surface_mesh_item::draw(CGAL::Three::Viewer_interface *viewer) const d->program->setAttributeValue("is_selected", false); if(!d->has_fcolors) d->program->setAttributeValue("colors", this->color()); + d->program->setUniformValue("comparing", viewer->currentPass() > 0); + d->program->setUniformValue("width", viewer->width()*1.0f); + d->program->setUniformValue("height", viewer->height()*1.0f); + d->program->setUniformValue("near", (float)viewer->camera()->zNear()); + d->program->setUniformValue("far", (float)viewer->camera()->zFar()); + d->program->setUniformValue("writing", viewer->isDepthWriting()); + d->program->setUniformValue("alpha", alpha()); + if( fbo) + viewer->glBindTexture(GL_TEXTURE_2D, fbo->texture()); viewer->glDrawArrays(GL_TRIANGLES,0,static_cast(d->nb_flat/3)); vaos[Scene_surface_mesh_item_priv::Flat_facets]->release(); } @@ -1719,6 +1749,15 @@ QMenu* Scene_surface_mesh_item::contextMenu() actionZoomToId->setObjectName("actionZoomToId"); connect(actionZoomToId, &QAction::triggered, this, &Scene_surface_mesh_item::zoomToId); + + QMenu *container = new QMenu(tr("Alpha value")); + QWidgetAction *sliderAction = new QWidgetAction(0); + sliderAction->setDefaultWidget(d->alphaSlider); + connect(d->alphaSlider, &QSlider::valueChanged, + [this](){redraw();}); + container->addAction(sliderAction); + menu->addMenu(container); + setProperty("menu_changed", true); menu->setProperty(prop_name, true); } @@ -1970,4 +2009,19 @@ bool Scene_surface_mesh_item::shouldDisplayIds(CGAL::Three::Scene_item *current_ return this == current_item; } +float Scene_surface_mesh_item::alpha() const +{ + if(!d->alphaSlider) + return 1.0f; + return (float)d->alphaSlider->value() / 255.0f; +} +void Scene_surface_mesh_item::setAlpha(int alpha) +{ + if(!d->alphaSlider) + d->compute_elements(); + d->alphaSlider->setValue(alpha); + redraw(); +} + +QSlider* Scene_surface_mesh_item::alphaSlider() { return d->alphaSlider; } diff --git a/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.h b/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.h index 49dd7f43b05..29e46c40df0 100644 --- a/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.h +++ b/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.h @@ -20,8 +20,8 @@ #include "properties.h" +class QSlider; struct Scene_surface_mesh_item_priv; - class SCENE_SURFACE_MESH_ITEM_EXPORT Scene_surface_mesh_item : public CGAL::Three::Scene_item, public CGAL::Three::Scene_zoomable_item_interface, @@ -129,6 +129,9 @@ public: void printAllIds(CGAL::Three::Viewer_interface*) Q_DECL_OVERRIDE; bool shouldDisplayIds(CGAL::Three::Scene_item *current_item) const Q_DECL_OVERRIDE; bool testDisplayId(double x, double y, double z, CGAL::Three::Viewer_interface*)const Q_DECL_OVERRIDE; + float alpha() const Q_DECL_OVERRIDE; + void setAlpha(int alpha) Q_DECL_OVERRIDE; + QSlider* alphaSlider(); Q_SIGNALS: void item_is_about_to_be_changed(); diff --git a/Polyhedron/demo/Polyhedron/Viewer.cpp b/Polyhedron/demo/Polyhedron/Viewer.cpp index acbf788d131..b08d4c03d6b 100644 --- a/Polyhedron/demo/Polyhedron/Viewer.cpp +++ b/Polyhedron/demo/Polyhedron/Viewer.cpp @@ -38,6 +38,18 @@ public: QTimer messageTimer; QOpenGLFunctions_4_3_Compatibility* _recentFunctions; bool is_2d_selection_mode; + // D e p t h P e e l i n g + // \param pass the current pass in the Depth Peeling (transparency) algorithm. + // -1 means that no depth peeling is applied. + // \param writing_depth means that the color of the faces will be drawn in a grayscale + // according to the depth of the fragment in the shader. It is used by the transparency. + // \param fbo contains the texture used by the Depth Peeling algorithm. + // Should be NULL if pass <= 0; + int current_pass; + bool writing_depth; + int total_pass; + int current_total_pass; + QOpenGLFramebufferObject* dp_fbo; //! The buffers used to draw the axis system QOpenGLBuffer buffer; @@ -88,6 +100,7 @@ Viewer::Viewer(QWidget* parent, bool antialiasing) d->shader_programs.resize(NB_OF_PROGRAMS); d->textRenderer = new TextRenderer(); d->is_2d_selection_mode = false; + d->total_pass = 4; connect( d->textRenderer, SIGNAL(sendMessage(QString,int)), this, SLOT(printMessage(QString,int)) ); connect(&d->messageTimer, SIGNAL(timeout()), SLOT(hideMessage())); @@ -434,6 +447,7 @@ void Viewer_impl::draw_aux(bool with_names, Viewer* viewer) { if(scene == 0) return; + current_total_pass = viewer->inFastDrawing() ? total_pass/2 : total_pass; viewer->glLineWidth(1.0f); viewer->glPointSize(2.f); viewer->glEnable(GL_POLYGON_OFFSET_FILL); @@ -1025,3 +1039,18 @@ void Viewer::setStaticImage(QImage image) { d->static_image = image; } const QImage& Viewer:: staticImage() const { return d->static_image; } +void Viewer::setCurrentPass(int pass) { d->current_pass = pass; } + +void Viewer::setDepthWriting(bool writing_depth) { d->writing_depth = writing_depth; } + +void Viewer::setDepthPeelingFbo(QOpenGLFramebufferObject* fbo) { d->dp_fbo = fbo; } + +int Viewer::currentPass()const{ return d->current_pass; } +bool Viewer::isDepthWriting()const{ return d->writing_depth; } +QOpenGLFramebufferObject *Viewer::depthPeelingFbo(){ return d->dp_fbo; } +float Viewer::total_pass() +{ + return d->current_total_pass * 1.0f; +} + +#include "Viewer.moc" diff --git a/Polyhedron/demo/Polyhedron/Viewer.h b/Polyhedron/demo/Polyhedron/Viewer.h index b36ed537775..03158691e5f 100644 --- a/Polyhedron/demo/Polyhedron/Viewer.h +++ b/Polyhedron/demo/Polyhedron/Viewer.h @@ -139,7 +139,13 @@ protected: public: QOpenGLFunctions_4_3_Compatibility* openGL_4_3_functions() Q_DECL_OVERRIDE; - + void setCurrentPass(int pass) Q_DECL_OVERRIDE; + void setDepthWriting(bool writing_depth) Q_DECL_OVERRIDE; + void setDepthPeelingFbo(QOpenGLFramebufferObject *fbo) Q_DECL_OVERRIDE; + int currentPass()const Q_DECL_OVERRIDE; + bool isDepthWriting()const Q_DECL_OVERRIDE; + QOpenGLFramebufferObject* depthPeelingFbo()Q_DECL_OVERRIDE; + float total_pass()Q_DECL_OVERRIDE; }; // end class Viewer diff --git a/Polyhedron/demo/Polyhedron/resources/shader_with_light.f b/Polyhedron/demo/Polyhedron/resources/shader_with_light.f index 42447b42f76..68e0e419712 100644 --- a/Polyhedron/demo/Polyhedron/resources/shader_with_light.f +++ b/Polyhedron/demo/Polyhedron/resources/shader_with_light.f @@ -1,48 +1,70 @@ #version 120 varying highp vec4 color; -varying highp vec4 fP; +varying highp vec4 fP; varying highp vec3 fN; varying highp float dist[6]; -uniform highp vec4 light_pos; -uniform highp vec4 light_diff; -uniform highp vec4 light_spec; +uniform highp vec4 light_pos; +uniform highp vec4 light_diff; +uniform highp vec4 light_spec; uniform highp vec4 light_amb; -uniform highp float spec_power ; -uniform int is_two_side; +uniform highp float spec_power; +uniform int is_two_side; uniform bool is_selected; uniform bool is_clipbox_on; -void main(void) { +uniform highp float near; +uniform highp float far; +uniform highp float width; +uniform highp float height; +uniform bool comparing; +uniform bool writing; +uniform sampler2D sampler; -if(is_clipbox_on) - if(dist[0]>0 || - dist[1]>0 || - dist[2]>0 || - dist[3]>0 || - dist[4]>0 || - dist[5]>0) - discard; - - highp vec3 L = light_pos.xyz - fP.xyz; - highp vec3 V = -fP.xyz; - highp vec3 N; - if(fN == highp vec3(0.0,0.0,0.0)) - N = highp vec3(0.0,0.0,0.0); - else - N = normalize(fN); - L = normalize(L); - V = normalize(V); - highp vec3 R = reflect(-L, N); - vec4 diffuse; - if(is_two_side == 1) - diffuse = abs(dot(N,L)) * light_diff * color; - else - diffuse = max(dot(N,L), 0.0) * light_diff * color; - highp vec4 specular = pow(max(dot(R,V), 0.0), spec_power) * light_spec; - vec4 ret_color = vec4((color*light_amb).xyz + diffuse.xyz + specular.xyz,1); - if(is_selected) - gl_FragColor = vec4(ret_color.r+70.0/255.0, ret_color.g+70.0/255.0, ret_color.b+70.0/255.0, 1.0); - else - gl_FragColor = ret_color; +highp float depth(float z) +{ + return (2 * near) / (far + near - z * (far - near)); } +void main(void) { + if(is_clipbox_on) + if(dist[0]>0 || + dist[1]>0 || + dist[2]>0 || + dist[3]>0 || + dist[4]>0 || + dist[5]>0) + discard; + + float alpha = color.a; + float d = depth(gl_FragCoord.z); + float test = texture2D(sampler, vec2(gl_FragCoord.x/width, gl_FragCoord.y/height)).r; + if(comparing && d <= test) + discard; + if(writing) + gl_FragColor = vec4(d,d,d,1.0); + else + { + vec4 my_color = vec4(color.xyz, 1.0); + highp vec3 L = light_pos.xyz - fP.xyz; + highp vec3 V = -fP.xyz; + highp vec3 N; + if(fN == highp vec3(0.0,0.0,0.0)) + N = highp vec3(0.0,0.0,0.0); + else + N = normalize(fN); + L = normalize(L); + V = normalize(V); + highp vec3 R = reflect(-L, N); + vec4 diffuse; + if(is_two_side == 1) + diffuse = abs(dot(N,L)) * light_diff * color; + else + diffuse = max(dot(N,L), 0.0) * light_diff * my_color; + highp vec4 specular = pow(max(dot(R,V), 0.0), spec_power) * light_spec; + vec4 ret_color = vec4((my_color*light_amb).xyz + diffuse.xyz + specular.xyz,1); + if(is_selected) + gl_FragColor = vec4(ret_color.r+70.0/255.0, ret_color.g+70.0/255.0, ret_color.b+70.0/255.0, alpha); + else + gl_FragColor = vec4(ret_color.xyz, alpha); + } +} diff --git a/Polyhedron/demo/Polyhedron/resources/shader_with_light.v b/Polyhedron/demo/Polyhedron/resources/shader_with_light.v index 2510ff515b1..31704260a76 100644 --- a/Polyhedron/demo/Polyhedron/resources/shader_with_light.v +++ b/Polyhedron/demo/Polyhedron/resources/shader_with_light.v @@ -1,7 +1,7 @@ #version 120 attribute highp vec4 vertex; attribute highp vec3 normals; -attribute highp vec3 colors; +attribute highp vec4 colors; uniform highp mat4 mvp_matrix; uniform highp mat4 mv_matrix; varying highp vec4 fP; @@ -11,6 +11,7 @@ varying highp float dist[6]; uniform bool is_clipbox_on; uniform highp mat4x4 clipbox1; uniform highp mat4x4 clipbox2; +uniform highp float alpha; void compute_distances(void) { @@ -32,8 +33,8 @@ void compute_distances(void) void main(void) { - color = vec4(colors, 1.0); - + color = vec4(colors.xyz, alpha); + // if(is_clipbox_on) compute_distances(); fP = mv_matrix * vertex; diff --git a/Three/include/CGAL/Three/Scene_group_item.h b/Three/include/CGAL/Three/Scene_group_item.h index cef9dee3748..cfefc8a664a 100644 --- a/Three/include/CGAL/Three/Scene_group_item.h +++ b/Three/include/CGAL/Three/Scene_group_item.h @@ -52,28 +52,48 @@ public : //!Sets the scene; void setScene(Scene_interface* s) { scene = s; } //!Returns false to avoid disturbing the BBox of the scene. - bool isFinite() const; + bool isFinite() const Q_DECL_OVERRIDE; //!Returns true to avoid disturbing the BBox of the scene. - bool isEmpty() const ; + bool isEmpty() const Q_DECL_OVERRIDE; /*! - * \brief Locks a child - * - * A locked child cannot be moved out of the group nor can it be deleted. - * Use it to prevent a child to be destroyed without its parent. - */ - void lockChild(CGAL::Three::Scene_item*); - /*! - * \brief Unlocks a child - * - * @see lockChild() - */ - void unlockChild(CGAL::Three::Scene_item*); - /*! - * \brief Tells if a child is locked. - * \return true if the child is locked. - * @see lockChild() - */ - bool isChildLocked(CGAL::Three::Scene_item*); + * \brief Locks a child + * + * A locked child cannot be moved out of the group nor can it be deleted. + * Use it to prevent a child to be destroyed without its parent. + */ + void lockChild(CGAL::Three::Scene_item*); + /*! + * \brief Locks a child + * + * A locked child cannot be moved out of the group nor can it be deleted. + * Use it to prevent a child to be destroyed without its parent. + */ + void lockChild(Scene_interface::Item_id id); + + /*! + * \brief Unlocks a child + * + * @see lockChild() + */ + void unlockChild(CGAL::Three::Scene_item*); + /*! + * \brief Unlocks a child + * + * @see lockChild() + */ + void unlockChild(Scene_interface::Item_id id); + /*! + * \brief Tells if a child is locked. + * \return true if the child is locked. + * @see lockChild() + */ + bool isChildLocked(CGAL::Three::Scene_item*); + /*! + * \brief Tells if a child is locked. + * \return true if the child is locked. + * @see lockChild() + */ + bool isChildLocked(Scene_interface::Item_id id); //!Returns if the group_item is currently expanded or collapsed in the Geometric Objects list. //! True means expanded, false means collapsed. //! @see isExpanded(). @@ -83,15 +103,15 @@ public : //! @see isExpanded(). void setExpanded(bool); //!Returns an empty Bbox to avoid disturbing the Bbox of the scene. - Bbox bbox() const; + Bbox bbox() const Q_DECL_OVERRIDE; //!Not supported. - Scene_item* clone() const {return 0;} + Scene_item* clone() const Q_DECL_OVERRIDE {return 0;} //! Indicates if the rendering mode is supported. //! \returns true for all rendering modes that are shared by //! all of the children. - bool supportsRenderingMode(RenderingMode m) const; + bool supportsRenderingMode(RenderingMode m) const Q_DECL_OVERRIDE; //!\returns a string containing the number of children. - QString toolTip() const; + QString toolTip() const Q_DECL_OVERRIDE; /// Draw functions /// Scene_group_item's children are not drawn by the scene, they are drawn by the group. @@ -102,32 +122,52 @@ public : //! and `Scene_item::drawPoints` for each child if its current //! rendering mode is adequat. //! @see #RenderingMode - virtual void draw(CGAL::Three::Viewer_interface*) const; + virtual void draw(CGAL::Three::Viewer_interface*) const Q_DECL_OVERRIDE; //!\brief draws all the children //! //! Calls `Scene_item::drawEdges()`, then calls `Scene_item::draw()` //! and `Scene_item::drawPoints` for each child if its current //! rendering mode is adequat. //! @see #RenderingMode - virtual void drawEdges(CGAL::Three::Viewer_interface*) const; + virtual void drawEdges(CGAL::Three::Viewer_interface*) const Q_DECL_OVERRIDE; //!\brief draws all the children //! //! Calls `Scene_item::drawPoints()`, then calls `Scene_item::draw()` //! and `Scene_item::drawEdges()` for each child if its current //! rendering mode is adequat. //! @see #RenderingMode - virtual void drawPoints(CGAL::Three::Viewer_interface*) const; + virtual void drawPoints(CGAL::Three::Viewer_interface*) const Q_DECL_OVERRIDE; + //! + //! \brief deals with the rendering, selecting and picking of + //! the group's children. + //! + //! \param picked_item_IDs the depth-index map + //! \param picked_pixel the screen point that has been picked. + //! \param with_names should be `true` if a picking is being performed. + //! + virtual void renderChildren(Viewer_interface *, + QMap& picked_item_IDs, const QPoint &picked_pixel, + bool with_names); + ///@} //!Adds a CGAL::Three::Scene_item* to the list of children. //!@see getChildren() @see removeChild() void addChild(Scene_item* new_item); + //!Adds a CGAL::Three::Scene_item* to the list of children from its id. + //! //!@see getChildren() @see removeChild() + void addChild(Scene_interface::Item_id new_id); + //! \brief getChild gives access to the Scene_item of the wanted index. + //! \returns the `CGAL::Three::Scene_item` which index is `id`. + //! + Scene_item* getChild(Scene_interface::Item_id id) { return scene->item(id);} + Scene_item* getChild(Scene_interface::Item_id id) const{ return scene->item(id);} //!Sets all the children to the specified color. - void setColor(QColor c); + void setColor(QColor c) Q_DECL_OVERRIDE; //!Sets all the children in the specified rendering mode. - void setRenderingMode(RenderingMode m); + void setRenderingMode(RenderingMode m) Q_DECL_OVERRIDE; //!Sets all the children to the specified visibility. - void setVisible(bool b); + void setVisible(bool b) Q_DECL_OVERRIDE; //!Sets all the children in points mode. void setPointsMode() { setRenderingMode(Points); @@ -160,11 +200,14 @@ public : void setPointsPlusNormalsMode(){ setRenderingMode(PointsPlusNormals); } + //!Sets the alpha value for the froup and all its children. + virtual void setAlpha(int) Q_DECL_OVERRIDE; + //! \brief Returns a list of all the direct children. //! //! Only returns children that have this item as a parent. //! Children of these children are not returned. - QList getChildren() const {return children;} + QList getChildren() const {return children;} //! \brief getChildrenForSelection returns the list of //! children to select along with the group. @@ -173,7 +216,7 @@ public : //! this function defines which of its children will be added too. //! Typically overriden to allow applying an operation from the //! Operation menu only to the parent item and not to its children. - virtual QList getChildrenForSelection() const {return children;} + virtual QList getChildrenForSelection() const {return children;} //!Removes a Scene_item from the list of children. //!@see getChildren() @see addChild() void removeChild( Scene_item* item) @@ -182,7 +225,13 @@ public : return; update_group_number(item,0); item->moveToGroup(0); - children.removeOne(item); + children.removeOne(scene->item_id(item)); + } + //!Removes a Scene_item from the list of children using its index. + //!@see getChildren() @see addChild() + void removeChild( Scene_interface::Item_id id) + { + removeChild(scene->item(id)); } //!Moves a child up in the list. void moveUp(int); @@ -199,13 +248,13 @@ public Q_SLOTS: //! `draw()` function. void resetDraw() { already_drawn = false;} private: - void update_group_number(Scene_item*new_item, int n); + void update_group_number(Scene_item* new_item, int n); bool expanded; mutable bool already_drawn; protected: Scene_interface *scene; //!Contains a reference to all the children of this group. - QList children; + QList children; }; //end of class Scene_group_item diff --git a/Three/include/CGAL/Three/Scene_item.h b/Three/include/CGAL/Three/Scene_item.h index 823cb06a489..cd03411ef77 100644 --- a/Three/include/CGAL/Three/Scene_item.h +++ b/Three/include/CGAL/Three/Scene_item.h @@ -235,6 +235,15 @@ public: //! the Operations menu, actions to save or clone the item if it is supported //! and any contextual action for the item. virtual QMenu* contextMenu(); + //! + //! \brief setId informs the item of its current index in the scene entries. + //! + void setId(int id); + + //! + //! \brief getId returns the current index of this item in the scene entries. + //! + int getId()const; //!Handles key press events. virtual bool keyPressEvent(QKeyEvent*){return false;} @@ -354,7 +363,15 @@ public Q_SLOTS: //!This might be needed as items are not always deleted right away by Qt and this behaviour may cause a simily //!memory leak, for example when multiple items are created at the same time. virtual void itemAboutToBeDestroyed(Scene_item*); - + //!Returns the alpha value for the item. + //! Must be called within a valid openGl context. + virtual float alpha() const; + + //! Sets the value of the aplha Slider for this item. + //! + //! Must be overriden; + //! \param alpha must be between 0 and 255 + virtual void setAlpha(int alpha); //!Selects a point through raycasting. virtual void select(double orig_x, double orig_y, @@ -432,6 +449,7 @@ protected: /*! Contains the VAOs. */ std::vector vaos; + int cur_id; //!Adds a VAO to the Map. void addVaos(int i) { diff --git a/Three/include/CGAL/Three/Viewer_interface.h b/Three/include/CGAL/Three/Viewer_interface.h index fedbd99991b..4087ef5414e 100644 --- a/Three/include/CGAL/Three/Viewer_interface.h +++ b/Three/include/CGAL/Three/Viewer_interface.h @@ -37,6 +37,7 @@ class QImage; class QMouseEvent; class QKeyEvent; class QOpenGLShaderProgram; +class QOpenGLFramebufferObject; class TextRenderer; class TextListItem; @@ -213,6 +214,9 @@ public: //! Returns the static image to be displayed in 2D selection mode. virtual const QImage& staticImage() const = 0; + //!The number of passes that are performed for the scene transparency. + //! Customizable from the MainWindow or the SubViewer menu. + virtual float total_pass() = 0; Q_SIGNALS: //!Emit this to signal that the `id`th item has been picked. void selected(int id); @@ -255,6 +259,13 @@ public: //! @returns a pointer to an initialized QOpenGLFunctions_4_3_Compatibility if `isOpenGL_4_3()` is `true` //! @returns NULL if `isOpenGL_4_3()` is `false` virtual QOpenGLFunctions_4_3_Compatibility* openGL_4_3_functions() = 0; + virtual void setCurrentPass(int pass) = 0; + virtual void setDepthWriting(bool writing_depth) = 0; + virtual void setDepthPeelingFbo(QOpenGLFramebufferObject* fbo) = 0; + + virtual int currentPass()const = 0; + virtual bool isDepthWriting()const = 0; + virtual QOpenGLFramebufferObject* depthPeelingFbo() = 0; }; // end class Viewer_interface } }