From b422ca258c480b86b21bcbf9828d080fbf38d587 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 11 Jul 2019 16:26:57 +0200 Subject: [PATCH] Only update locally the geometry of the item when moving a vertex around. --- .../Scene_polyhedron_selection_item.cpp | 12 +- .../Polyhedron/Scene_surface_mesh_item.cpp | 358 ++++++++++++++++++ .../demo/Polyhedron/Scene_surface_mesh_item.h | 1 + 3 files changed, 370 insertions(+), 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/Scene_polyhedron_selection_item.cpp b/Polyhedron/demo/Polyhedron/Scene_polyhedron_selection_item.cpp index 09270611ceb..57d91757be6 100644 --- a/Polyhedron/demo/Polyhedron/Scene_polyhedron_selection_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_polyhedron_selection_item.cpp @@ -694,6 +694,7 @@ void Scene_polyhedron_selection_item::inverse_selection() void Scene_polyhedron_selection_item::set_highlighting(bool b) { + setProperty("is_highlighting", b); k_ring_selector.setHighLighting(b); } void Scene_polyhedron_selection_item::set_operation_mode(int mode) @@ -1012,6 +1013,12 @@ bool Scene_polyhedron_selection_item::treat_selection(const std::setmanipulated_frame->setPosition(p.x()+offset.x, p.y()+offset.y, p.z()+offset.z); viewer->setManipulatedFrame(d->manipulated_frame); connect(d->manipulated_frame, SIGNAL(modified()), this, SLOT(updateTick())); + if(property("is_highlighting").toBool()) + { + setProperty("need_hl_restore", true); + set_highlighting(false); + qDebug()<<":coucou"; + } invalidateOpenGLBuffers(); Q_EMIT updateInstructions("Ctrl+Right-click to move the point. \nHit Ctrl+Z to leave the selection. (2/2)"); } @@ -1931,7 +1938,8 @@ void Scene_polyhedron_selection_item::moveVertex() d->manipulated_frame->position().y-offset.y, d->manipulated_frame->position().z-offset.z)); invalidateOpenGLBuffers(); - poly_item->invalidateOpenGLBuffers(); + poly_item->updateVertex(vh); + // poly_item->invalidateOpenGLBuffers(); d->ready_to_move = false; } } @@ -1944,6 +1952,8 @@ void Scene_polyhedron_selection_item::validateMoveVertex() viewer->setManipulatedFrame(NULL); invalidateOpenGLBuffers(); poly_item->itemChanged(); + if(property("need_hl_restore").toBool()) + set_highlighting(true); Q_EMIT updateInstructions("Select a vertex. (1/2)"); } diff --git a/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp b/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp index 7793692024d..d0b6434d2b5 100644 --- a/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp @@ -2281,3 +2281,361 @@ void Scene_surface_mesh_item::computeItemColorVectorAutomatically(bool b) { this->setProperty("recompute_colors",b); } + +void Scene_surface_mesh_item::updateVertex(vertex_descriptor vh) +{ + typedef CGAL::Buffer_for_vao CPF; + + const CGAL::qglviewer::Vec offset = + static_cast( + CGAL::QGLViewer::QGLViewerPool().first())->offset(); + //gouraud + { + std::size_t id = vh; + QOpenGLBuffer *vbo = &(getTriangleContainer(0)->getVbo(Tri::Smooth_vertices)->vbo); + cgal_gl_data new_point[3]; + Point_3 p = face_graph()->point(vh); + for(int i=0; i<3; ++i) + new_point[i]=p[i]+offset[i]; + + + getTriangleContainer(0)->getVbo(Tri::Smooth_vertices)->bind(); + vbo->write(3*sizeof(cgal_gl_data)*id,new_point,3*sizeof(cgal_gl_data)); + getTriangleContainer(0)->getVbo(Tri::Smooth_vertices)->release(); + + vbo =&(getPointContainer(0)->getVbo(Pt::Vertices)->vbo); + getPointContainer(0)->getVbo(Pt::Vertices)->bind(); + vbo->write(3*sizeof(cgal_gl_data)*id,new_point,3*sizeof(cgal_gl_data)); + getPointContainer(0)->getVbo(Pt::Vertices)->release(); + + vbo =&(getEdgeContainer(0)->getVbo(Ed::Vertices)->vbo); + getEdgeContainer(0)->getVbo(Pt::Vertices)->bind(); + vbo->write(3*sizeof(cgal_gl_data)*id,new_point,3*sizeof(cgal_gl_data)); + getEdgeContainer(0)->getVbo(Pt::Vertices)->release(); + + for(auto v_it : CGAL::vertices_around_target(vh, *face_graph())) + { + EPICK::Vector_3 n = CGAL::Polygon_mesh_processing::compute_vertex_normal(v_it, *face_graph()); + for(int i=0; i<3; ++i) + new_point[i]=n[i]; + id = v_it; + vbo =&(getTriangleContainer(0)->getVbo(Tri::Smooth_normals)->vbo); + getTriangleContainer(0)->getVbo(Tri::Smooth_normals)->bind(); + vbo->write(3*sizeof(cgal_gl_data)*id,new_point,3*sizeof(cgal_gl_data)); + getTriangleContainer(0)->getVbo(Tri::Smooth_normals)->release(); + } + } + //flat + std::size_t size = 0; + if(CGAL::is_triangle_mesh(*face_graph())) + { + size = 3; + } + else if (CGAL::is_quad_mesh(*face_graph())) + { + size = 6; + } + + for(auto f : CGAL::faces_around_target(halfedge(vh, *face_graph()), *face_graph())) + { + if(size == 0) + { + for(std::size_t i = 0; i < (std::size_t)f; ++i) + { + size += CGAL::degree(f, *face_graph()); + } + } + EPICK::Vector_3 n = CGAL::Polygon_mesh_processing::compute_face_normal(f, *face_graph()); + cgal_gl_data new_normal[3]; + for(int i=0; i<3; ++i) + new_normal[i]=n[i]; + + std::size_t id = f; + std::size_t vid = 0; + + if(is_triangle(halfedge(f,*face_graph()),*face_graph())) + { + for(halfedge_descriptor hd : halfedges_around_face(halfedge(f, *face_graph()),*face_graph())) + { + Point_3 p = face_graph()->point(source(hd, *face_graph())); + cgal_gl_data new_point[3]; + for(int i=0; i<3; ++i) + { + new_point[i]=p[i]+offset[i]; + } + QOpenGLBuffer *vbo = &(getTriangleContainer(1)->getVbo(Tri::Flat_normals)->vbo); + getTriangleContainer(1)->getVbo(Tri::Flat_normals)->bind(); + vbo->write((3*size*id+vid)*sizeof(cgal_gl_data),new_normal, 3*sizeof(cgal_gl_data)); + getTriangleContainer(1)->getVbo(Tri::Flat_normals)->release(); + + vbo = &(getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->vbo); + getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->bind(); + vbo->write((3*size*id+vid)*sizeof(cgal_gl_data),new_point, 3*sizeof(cgal_gl_data)); + getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->release(); + vid+=3; + } + } + else + { + std::vector facet_points; + for(halfedge_descriptor hd : halfedges_around_face(halfedge(f, *face_graph()),*face_graph())) + { + facet_points.push_back(face_graph()->point(target(hd, *face_graph()))); + } + bool is_convex = CPF::is_facet_convex(facet_points, n); + if(is_convex && is_quad(halfedge(f,*face_graph()),*face_graph())) + { + //1st half + halfedge_descriptor hd = halfedge(f, *face_graph()); + Point_3 p = face_graph()->point(source(hd, *face_graph())); + cgal_gl_data new_point[3]; + for(int i=0; i<3; ++i) + { + new_point[i]=p[i]+offset[i]; + } + QOpenGLBuffer *vbo = &(getTriangleContainer(1)->getVbo(Tri::Flat_normals)->vbo); + getTriangleContainer(1)->getVbo(Tri::Flat_normals)->bind(); + vbo->write((3*size*id+vid)*sizeof(cgal_gl_data),new_normal, 3*sizeof(cgal_gl_data)); + getTriangleContainer(1)->getVbo(Tri::Flat_normals)->release(); + vbo = &(getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->vbo); + getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->bind(); + vbo->write((3*size*id+vid)*sizeof(cgal_gl_data),new_point, 3*sizeof(cgal_gl_data)); + getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->release(); + vid+=3; + + hd = next(halfedge(f, *face_graph()),*face_graph()); + p = face_graph()->point(source(hd, *face_graph())); + for(int i=0; i<3; ++i) + { + new_point[i]=p[i]+offset[i]; + } + vbo = &(getTriangleContainer(1)->getVbo(Tri::Flat_normals)->vbo); + getTriangleContainer(1)->getVbo(Tri::Flat_normals)->bind(); + vbo->write((3*size*id+vid)*sizeof(cgal_gl_data),new_normal, 3*sizeof(cgal_gl_data)); + getTriangleContainer(1)->getVbo(Tri::Flat_normals)->release(); + vbo = &(getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->vbo); + getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->bind(); + vbo->write((3*size*id+vid)*sizeof(cgal_gl_data),new_point, 3*sizeof(cgal_gl_data)); + getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->release(); + vid+=3; + + hd = next(next(halfedge(f, *face_graph()),*face_graph()), *face_graph()); + p = face_graph()->point(source(hd, *face_graph())); + for(int i=0; i<3; ++i) + { + new_point[i]=p[i]+offset[i]; + } + vbo = &(getTriangleContainer(1)->getVbo(Tri::Flat_normals)->vbo); + getTriangleContainer(1)->getVbo(Tri::Flat_normals)->bind(); + vbo->write((3*size*id+vid)*sizeof(cgal_gl_data),new_normal, 3*sizeof(cgal_gl_data)); + getTriangleContainer(1)->getVbo(Tri::Flat_normals)->release(); + vbo = &(getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->vbo); + getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->bind(); + vbo->write((3*size*id+vid)*sizeof(cgal_gl_data),new_point, 3*sizeof(cgal_gl_data)); + getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->release(); + vid+=3; + + //2nd half + hd = halfedge(f, *face_graph()); + p = face_graph()->point(source(hd, *face_graph())); + for(int i=0; i<3; ++i) + { + new_point[i]=p[i]+offset[i]; + } + vbo = &(getTriangleContainer(1)->getVbo(Tri::Flat_normals)->vbo); + getTriangleContainer(1)->getVbo(Tri::Flat_normals)->bind(); + vbo->write((3*size*id+vid)*sizeof(cgal_gl_data),new_normal, 3*sizeof(cgal_gl_data)); + getTriangleContainer(1)->getVbo(Tri::Flat_normals)->release(); + vbo = &(getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->vbo); + getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->bind(); + vbo->write((3*size*id+vid)*sizeof(cgal_gl_data),new_point, 3*sizeof(cgal_gl_data)); + getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->release(); + vid+=3; + + hd = next(next(halfedge(f, *face_graph()),*face_graph()), *face_graph()); + p = face_graph()->point(source(hd, *face_graph())); + for(int i=0; i<3; ++i) + { + new_point[i]=p[i]+offset[i]; + } + vbo = &(getTriangleContainer(1)->getVbo(Tri::Flat_normals)->vbo); + getTriangleContainer(1)->getVbo(Tri::Flat_normals)->bind(); + vbo->write((3*size*id+vid)*sizeof(cgal_gl_data),new_normal, 3*sizeof(cgal_gl_data)); + getTriangleContainer(1)->getVbo(Tri::Flat_normals)->release(); + vbo = &(getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->vbo); + getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->bind(); + vbo->write((3*size*id+vid)*sizeof(cgal_gl_data),new_point, 3*sizeof(cgal_gl_data)); + getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->release(); + vid+=3; + + hd = prev(halfedge(f, *face_graph()), *face_graph()); + p = face_graph()->point(source(hd, *face_graph())); + for(int i=0; i<3; ++i) + { + new_point[i]=p[i]+offset[i]; + } + vbo = &(getTriangleContainer(1)->getVbo(Tri::Flat_normals)->vbo); + getTriangleContainer(1)->getVbo(Tri::Flat_normals)->bind(); + vbo->write((3*size*id+vid)*sizeof(cgal_gl_data),new_normal, 3*sizeof(cgal_gl_data)); + getTriangleContainer(1)->getVbo(Tri::Flat_normals)->release(); + vbo = &(getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->vbo); + getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->bind(); + vbo->write((3*size*id+vid)*sizeof(cgal_gl_data),new_point, 3*sizeof(cgal_gl_data)); + getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->release(); + } + else if(is_convex) + { + Point_3 p0,p1,p2; + SMesh::Halfedge_around_face_circulator he(halfedge(f, *face_graph()), *face_graph()); + SMesh::Halfedge_around_face_circulator he_end = he; + + while(next(*he, *face_graph()) != prev(*he_end, *face_graph())) + { + ++he; + vertex_descriptor v0(target(*he_end, *face_graph())), + v1(target(*he, *face_graph())), + v2(target(next(*he, *face_graph()), *face_graph())); + p0 = face_graph()->point(v0); + p1 = face_graph()->point(v1); + p2 = face_graph()->point(v2); + cgal_gl_data new_point[3]; + QOpenGLBuffer *vbo =nullptr; + for(int i=0; i<3; ++i) + { + new_point[i]=p0[i]+offset[i]; + } + vbo = &(getTriangleContainer(1)->getVbo(Tri::Flat_normals)->vbo); + getTriangleContainer(1)->getVbo(Tri::Flat_normals)->bind(); + vbo->write((3*size*id+vid)*sizeof(cgal_gl_data),new_normal, 3*sizeof(cgal_gl_data)); + getTriangleContainer(1)->getVbo(Tri::Flat_normals)->release(); + vbo = &(getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->vbo); + getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->bind(); + vbo->write((3*size*id+vid)*sizeof(cgal_gl_data),new_point, 3*sizeof(cgal_gl_data)); + getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->release(); + + for(int i=0; i<3; ++i) + { + new_point[i]=p1[i]+offset[i]; + } + vbo = &(getTriangleContainer(1)->getVbo(Tri::Flat_normals)->vbo); + getTriangleContainer(1)->getVbo(Tri::Flat_normals)->bind(); + vbo->write((3*size*id+vid)*sizeof(cgal_gl_data),new_normal, 3*sizeof(cgal_gl_data)); + getTriangleContainer(1)->getVbo(Tri::Flat_normals)->release(); + vbo = &(getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->vbo); + getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->bind(); + vbo->write((3*size*id+vid)*sizeof(cgal_gl_data),new_point, 3*sizeof(cgal_gl_data)); + getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->release(); + + for(int i=0; i<3; ++i) + { + new_point[i]=p2[i]+offset[i]; + } + vbo = &(getTriangleContainer(1)->getVbo(Tri::Flat_normals)->vbo); + getTriangleContainer(1)->getVbo(Tri::Flat_normals)->bind(); + vbo->write((3*size*id+vid)*sizeof(cgal_gl_data),new_normal, 3*sizeof(cgal_gl_data)); + getTriangleContainer(1)->getVbo(Tri::Flat_normals)->release(); + vbo = &(getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->vbo); + getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->bind(); + vbo->write((3*size*id+vid)*sizeof(cgal_gl_data),new_point, 3*sizeof(cgal_gl_data)); + getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->release(); + } + } + else + { + //Computes the normal of the facet + if(n == CGAL::NULL_VECTOR) + { + boost::graph_traits::halfedge_descriptor start = prev(halfedge(f, *face_graph()), *face_graph()); + boost::graph_traits::halfedge_descriptor hd = halfedge(f, *face_graph()); + boost::graph_traits::halfedge_descriptor next_=next(hd, *face_graph()); + do + { + const Point_3& pa = face_graph()->point(target(hd, *face_graph())); + const Point_3& pb = face_graph()->point(target(next_, *face_graph())); + const Point_3& pc = face_graph()->point(target(prev(hd, *face_graph()), *face_graph())); + if (!CGAL::collinear (pa, pb, pc)) + { + n = CGAL::cross_product(pb-pa, pc -pa); + break; + } + next_ =next(next_, *face_graph()); + }while(next_ != start); + + if (n == CGAL::NULL_VECTOR) // No normal could be computed, return + { + qDebug()<<"Warning : normal is not valid. Facet not updated"; + continue; + } + } + //check if normal contains NaN values + if (n.x() != n.x() || n.y() != n.y() || n.z() != n.z()) + { + qDebug()<<"Warning : normal is not valid. Facet not displayed"; + continue; + } + + typedef FacetTriangulator::vertex_descriptor> FT; + EPICK::Vector_3 voffset(offset.x,offset.y,offset.z); + FT triangulation(f,n,face_graph(), voffset); + //iterates on the internal faces + for(FT::CDT::Finite_faces_iterator + ffit = triangulation.cdt->finite_faces_begin(), + end = triangulation.cdt->finite_faces_end(); + ffit != end; ++ffit) + { + if(ffit->info().is_external) + continue; + Point_3 p = ffit->vertex(0)->point(); + cgal_gl_data new_point[3]; + for(int i=0; i<3; ++i) + { + new_point[i]=p[i]; + } + QOpenGLBuffer *vbo = &(getTriangleContainer(1)->getVbo(Tri::Flat_normals)->vbo); + getTriangleContainer(1)->getVbo(Tri::Flat_normals)->bind(); + vbo->write((3*size*id+vid)*sizeof(cgal_gl_data),new_normal, 3*sizeof(cgal_gl_data)); + getTriangleContainer(1)->getVbo(Tri::Flat_normals)->release(); + vbo = &(getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->vbo); + getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->bind(); + vbo->write((3*size*id+vid)*sizeof(cgal_gl_data),new_point, 3*sizeof(cgal_gl_data)); + getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->release(); + vid+=3; + + + p = ffit->vertex(1)->point(); + for(int i=0; i<3; ++i) + { + new_point[i]=p[i]; + } + vbo = &(getTriangleContainer(1)->getVbo(Tri::Flat_normals)->vbo); + getTriangleContainer(1)->getVbo(Tri::Flat_normals)->bind(); + vbo->write((3*size*id+vid)*sizeof(cgal_gl_data),new_normal, 3*sizeof(cgal_gl_data)); + getTriangleContainer(1)->getVbo(Tri::Flat_normals)->release(); + vbo = &(getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->vbo); + getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->bind(); + vbo->write((3*size*id+vid)*sizeof(cgal_gl_data),new_point, 3*sizeof(cgal_gl_data)); + getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->release(); + vid+=3; + + p=ffit->vertex(2)->point(); + for(int i=0; i<3; ++i) + { + new_point[i]=p[i]; + } + vbo = &(getTriangleContainer(1)->getVbo(Tri::Flat_normals)->vbo); + getTriangleContainer(1)->getVbo(Tri::Flat_normals)->bind(); + vbo->write((3*size*id+vid)*sizeof(cgal_gl_data),new_normal, 3*sizeof(cgal_gl_data)); + getTriangleContainer(1)->getVbo(Tri::Flat_normals)->release(); + vbo = &(getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->vbo); + getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->bind(); + vbo->write((3*size*id+vid)*sizeof(cgal_gl_data),new_point, 3*sizeof(cgal_gl_data)); + getTriangleContainer(1)->getVbo(Tri::Flat_vertices)->release(); + vid+=3; + + } + } + } + } + invalidate_aabb_tree(); + redraw(); +} diff --git a/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.h b/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.h index c2bf3d8fd9c..b36c7c58afc 100644 --- a/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.h +++ b/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.h @@ -154,6 +154,7 @@ public: QSlider* alphaSlider(); void computeElements() const Q_DECL_OVERRIDE; void initializeBuffers(CGAL::Three::Viewer_interface*)const Q_DECL_OVERRIDE; + void updateVertex(vertex_descriptor vh); Q_SIGNALS: void item_is_about_to_be_changed();