diff --git a/Polyhedron/demo/Polyhedron/CMakeLists.txt b/Polyhedron/demo/Polyhedron/CMakeLists.txt index d6a7d13a990..dcdf368e36f 100644 --- a/Polyhedron/demo/Polyhedron/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/CMakeLists.txt @@ -279,9 +279,12 @@ if(CGAL_Qt5_FOUND AND Qt5_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND) target_link_libraries(scene_sm_shortest_path_item scene_surface_mesh_item_decorator scene_surface_mesh_item scene_polylines_item) if(EIGEN3_FOUND ) - qt5_wrap_ui( editionUI_FILES Plugins/Surface_mesh_deformation/Deform_mesh.ui ) add_item(scene_textured_polyhedron_item Scene_textured_polyhedron_item.cpp texture.cpp) qt5_use_modules( scene_textured_polyhedron_item Svg ) + add_item(scene_textured_surface_mesh_item Scene_textured_surface_mesh_item.cpp texture.cpp) + qt5_use_modules( scene_textured_surface_mesh_item Svg ) + + qt5_wrap_ui( editionUI_FILES Plugins/Surface_mesh_deformation/Deform_mesh.ui ) add_item(scene_edit_polyhedron_item Plugins/Surface_mesh_deformation/Scene_edit_polyhedron_item.cpp ${editionUI_FILES}) target_link_libraries(scene_edit_polyhedron_item scene_polyhedron_item scene_surface_mesh_item scene_polyhedron_and_sm_item_k_ring_selection diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/CMakeLists.txt index 942bc06bd17..a08284fb116 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/CMakeLists.txt @@ -9,6 +9,11 @@ if(EIGEN3_FOUND) qt5_wrap_ui( parameterizationUI_FILES Parameterization_widget.ui ARAP_dialog.ui OTE_dialog.ui) polyhedron_demo_plugin(parameterization_plugin Parameterization_plugin ${parameterizationUI_FILES}) target_link_libraries(parameterization_plugin ${CGAL_Core_LIBRARY} ${CGAL_Core_3RD_PARTY_LIBRARIES} scene_polyhedron_item scene_textured_polyhedron_item scene_polyhedron_selection_item) + + polyhedron_demo_plugin(parameterization_sm_plugin Parameterization_plugin ${parameterizationUI_FILES}) + target_link_libraries(parameterization_sm_plugin ${CGAL_Core_LIBRARY} ${CGAL_Core_3RD_PARTY_LIBRARIES} scene_surface_mesh_item scene_textured_surface_mesh_item scene_surface_mesh_selection_item) + target_compile_definitions(parameterization_sm_plugin PUBLIC "-DUSE_SURFACE_MESH" ) + else(CGAL_Core_FOUND) message(STATUS "NOTICE: CGAL Core was not found. The Parameterization plugin will not be available.") endif(CGAL_Core_FOUND) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Parameterization_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Parameterization_plugin.cpp index 23ec66020ae..aa47a6170f0 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Parameterization_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Parameterization_plugin.cpp @@ -2,13 +2,26 @@ #include #include #include - +#ifdef USE_SURFACE_MESH +#include "Scene_surface_mesh_item.h" +#include "Scene_textured_surface_mesh_item.h" +#include "Scene_polyhedron_selection_item.h" +#include "SMesh_type.h" +#else #include "Scene_polyhedron_item.h" #include "Scene_textured_polyhedron_item.h" #include "Scene_polyhedron_selection_item.h" #include "Textured_polyhedron_type.h" #include "Polyhedron_type.h" - +#include +#include +#include +#include +#include +#include +#endif +#include +#include #include "Scene.h" #include #include @@ -16,13 +29,10 @@ #include #include #include - #include #include #include -#include -#include #include #include @@ -38,40 +48,64 @@ #include #include -#include #include #include #include +#include #include #include #include #include -#include -#include + #include #include -#include #include "ui_Parameterization_widget.h" #include "ui_ARAP_dialog.h" #include "ui_OTE_dialog.h" +#ifdef USE_SURFACE_MESH +typedef Scene_surface_mesh_item Scene_facegraph_item; +typedef Scene_textured_surface_mesh_item Scene_textured_facegraph_item; +typedef SMesh Textured_face_graph; +typedef SMesh Base_face_graph; +typedef SMesh Face_graph; +typedef EPICK Traits; + +#else +typedef Scene_polyhedron_item Scene_facegraph_item; +typedef Scene_textured_polyhedron_item Scene_textured_facegraph_item; +typedef Textured_polyhedron Textured_face_graph; +typedef Textured_face_graph::Base Base_face_graph; +typedef Polyhedron Face_graph; +typedef Kernel Traits; + +#endif + namespace SMP = CGAL::Surface_mesh_parameterization; -typedef boost::unordered_set Component; +typedef boost::unordered_set::face_descriptor> Component; typedef std::vector Components; -struct Is_selected_property_map{ - typedef boost::graph_traits::edge_descriptor edge_descriptor; - std::vector* is_selected_ptr; - Is_selected_property_map() - : is_selected_ptr(NULL) {} - Is_selected_property_map(std::vector& is_selected) - : is_selected_ptr( &is_selected) {} - std::size_t id(edge_descriptor ed) { return ed.halfedge()->id()/2; } +struct Is_selected_property_map{ + typedef boost::graph_traits::edge_descriptor edge_descriptor; + typedef boost::property_map::type HIndexMap; + std::vector* is_selected_ptr; + Base_face_graph* graph; + HIndexMap idmap; + Is_selected_property_map() + : is_selected_ptr(NULL), graph(NULL) {} + Is_selected_property_map(std::vector& is_selected, + Base_face_graph* graph) + : is_selected_ptr( &is_selected), graph(graph) + { + idmap = get(boost::halfedge_index, *graph); + } + + std::size_t id(edge_descriptor ed) { return get(idmap, halfedge(ed, *graph))/2; } friend bool get(Is_selected_property_map map, edge_descriptor ed) { @@ -162,18 +196,18 @@ private: namespace SMP = CGAL::Surface_mesh_parameterization; -typedef Kernel::FT FT; -typedef boost::graph_traits::vertex_descriptor P_vertex_descriptor; -typedef Kernel::Point_2 Point_2; -typedef boost::graph_traits::edge_descriptor P_edge_descriptor; -typedef boost::graph_traits::halfedge_descriptor P_halfedge_descriptor; +typedef Traits::FT FT; +typedef boost::graph_traits::vertex_descriptor P_vertex_descriptor; +typedef Traits::Point_2 Point_2; +typedef boost::graph_traits::edge_descriptor P_edge_descriptor; +typedef boost::graph_traits::halfedge_descriptor P_halfedge_descriptor; // Textured polyhedron -typedef boost::graph_traits:: +typedef boost::graph_traits:: edge_descriptor T_edge_descriptor; -typedef boost::graph_traits:: +typedef boost::graph_traits:: halfedge_descriptor T_halfedge_descriptor; -typedef boost::graph_traits:: +typedef boost::graph_traits:: vertex_descriptor T_vertex_descriptor; // Seam @@ -185,28 +219,32 @@ typedef boost::associative_property_map UV_pmap; typedef boost::associative_property_map Seam_edge_pmap; typedef boost::associative_property_map Seam_vertex_pmap; -typedef CGAL::Seam_mesh Seam_mesh; +typedef CGAL::Seam_mesh Seam_mesh; -typedef boost::graph_traits::vertex_descriptor vertex_descriptor; -typedef boost::graph_traits::halfedge_descriptor halfedge_descriptor; -typedef boost::graph_traits::face_descriptor face_descriptor; +typedef boost::graph_traits::vertex_descriptor s_vertex_descriptor; +typedef boost::graph_traits::halfedge_descriptor s_halfedge_descriptor; +typedef boost::graph_traits::face_descriptor s_face_descriptor; -typedef boost::unordered_set Component; -typedef std::vector Components; +typedef boost::unordered_set:: +face_descriptor> Component; +typedef std::vector Components; -typedef boost::unordered_set SComponent; -typedef std::vector SComponents; +typedef boost::unordered_set SComponent; +typedef std::vector SComponents; class UVItem : public QGraphicsItem { public : UVItem(Components* components, + Base_face_graph* graph, std::vector >uv_borders, QRectF brect) : QGraphicsItem(), bounding_rect(brect), components(components), + graph(graph), m_borders(uv_borders), m_concatenated_borders(), m_current_component(0) @@ -250,16 +288,30 @@ public : pen.setWidth(0); painter->setPen(pen); painter->setBrush(brush); +#ifdef USE_SURFACE_MESH +SMesh::Property_map > uv; +uv = graph->add_property_map >("h:uv",std::make_pair(0.0f,0.0f)).first; +#endif for( Component::iterator fi = components->at(m_current_component).begin(); fi != components->at(m_current_component).end(); ++fi) { - Textured_polyhedron::Facet_handle f(*fi); + boost::graph_traits::face_descriptor f(*fi); +#ifdef USE_SURFACE_MESH + QPointF points[3]; + boost::graph_traits::halfedge_descriptor h = halfedge(f, *graph);; + points[0] = QPointF(get(uv, h).first, get(uv, h).second); + h = next(halfedge(f, *graph), *graph); + points[1] = QPointF(get(uv, h).first, get(uv, h).second); + h = next(next(halfedge(f, *graph), *graph), *graph); + points[2] = QPointF(get(uv, h).first, get(uv, h).second); +#else QPointF points[3]; points[0] = QPointF(f->halfedge()->u(), f->halfedge()->v()); points[1] = QPointF(f->halfedge()->next()->u(), f->halfedge()->next()->v()); points[2] = QPointF(f->halfedge()->next()->next()->u(), f->halfedge()->next()->next()->v()); +#endif painter->drawPolygon(points,3); } @@ -273,6 +325,7 @@ private: QString texMesh_name; QRectF bounding_rect; Components* components; + Base_face_graph* graph; std::vector > m_borders; std::vector m_concatenated_borders; int m_current_component; @@ -351,14 +404,14 @@ public: { if (scene->selectionIndices().size() == 1) { - return qobject_cast(scene->item(scene->mainSelectionIndex())) + return qobject_cast(scene->item(scene->mainSelectionIndex())) || qobject_cast(scene->item(scene->mainSelectionIndex())); } Q_FOREACH(CGAL::Three::Scene_interface::Item_id id, scene->selectionIndices()) { - //if one polyhedron is found in the selection, it's fine - if (qobject_cast(scene->item(id))) + //if one facegraph is found in the selection, it's fine + if (qobject_cast(scene->item(id))) return true; } return false; @@ -383,7 +436,7 @@ public Q_SLOTS: void replacePolyline() { if(current_uv_item) - qobject_cast(projections.key(current_uv_item))->add_border_edges(std::vector(0)); + qobject_cast(projections.key(current_uv_item))->add_border_edges(std::vector(0)); int id = scene->mainSelectionIndex(); @@ -409,7 +462,7 @@ public Q_SLOTS: ui_widget.graphicsView->fitInView(current_uv_item->boundingRect(), Qt::KeepAspectRatio); ui_widget.component_numberLabel->setText(QString("Component : %1/%2").arg(current_uv_item->current_component()+1).arg(current_uv_item->number_of_components())); dock_widget->setWindowTitle(tr("UVMapping for %1").arg(current_uv_item->item_name())); - qobject_cast(projections.key(current_uv_item))->add_border_edges(current_uv_item->concatenated_borders()); + qobject_cast(projections.key(current_uv_item))->add_border_edges(current_uv_item->concatenated_borders()); } } @@ -491,11 +544,11 @@ void Polyhedron_demo_parameterization_plugin::on_nextButton_pressed() void Polyhedron_demo_parameterization_plugin::parameterize(const Parameterization_method method) { // get active polyhedron - Scene_polyhedron_item* poly_item = NULL; + Scene_facegraph_item* poly_item = NULL; CGAL::Three::Scene_interface::Item_id index = scene->mainSelectionIndex(); Q_FOREACH(CGAL::Three::Scene_interface::Item_id id, scene->selectionIndices()) { - poly_item = qobject_cast(scene->item(id)); + poly_item = qobject_cast(scene->item(id)); if(!poly_item) { continue; @@ -513,14 +566,15 @@ void Polyhedron_demo_parameterization_plugin::parameterize(const Parameterizatio return; } - Polyhedron* pMesh = poly_item->polyhedron(); + Face_graph* pMesh = poly_item->face_graph(); if(!pMesh) { messages->error("Selected item has no valid polyhedron."); return; } - +#ifndef USE_SURFACE_MESH pMesh->normalize_border(); +#endif Scene_polyhedron_selection_item* sel_item = NULL; bool is_seamed = false; Q_FOREACH(CGAL::Three::Scene_interface::Item_id id, scene->selectionIndices()) @@ -548,7 +602,7 @@ void Polyhedron_demo_parameterization_plugin::parameterize(const Parameterizatio Seam_vertex_uhm seam_vertex_uhm(false); Seam_vertex_pmap seam_vertex_pm(seam_vertex_uhm); - if(!is_seamed && pMesh->is_closed()) + if(!is_seamed && is_closed(*pMesh)) { messages->error("The selected mesh has no (real or virtual) border."); return; @@ -563,12 +617,13 @@ void Polyhedron_demo_parameterization_plugin::parameterize(const Parameterizatio QTime time; time.start(); // add textured polyhedon to the scene + #ifndef USE_SURFACE_MESH Textured_polyhedron *tpMesh = new Textured_polyhedron(); Textured_polyhedron_builder builder; builder.run(*pMesh,*tpMesh); tpMesh->compute_normals(); tpMesh->normalize_border(); - Textured_polyhedron::Base tMesh = static_cast(*tpMesh); + Base_face_graph tMesh = static_cast(*tpMesh); CGAL::set_halfedgeds_items_id(tMesh); std::vector mark(tpMesh->size_of_halfedges()/2,false); @@ -627,7 +682,71 @@ void Polyhedron_demo_parameterization_plugin::parameterize(const Parameterizatio } } } +#else + // \todo for surface_mesh + Base_face_graph tMesh = *pMesh; + std::vector mark(num_halfedges(tMesh)/2,false); + std::vector seam_edges; + typedef boost::property_map::type VIDMap; + VIDMap vidmap = get(boost::vertex_index, tMesh); + if(is_seamed) + { + //create a textured_polyhedron edges selection from the ids of the corresponding vertices + typedef boost::property_map::type HIDMap; + HIDMap hidmap = get(boost::halfedge_index, tMesh); + BOOST_FOREACH(P_edge_descriptor ed, sel_item->selected_edges) + { + boost::graph_traits::vertex_descriptor a(source(ed, *pMesh)), b(target(ed, *pMesh)); + for(boost::graph_traits::edge_iterator it = + edges(tMesh).begin(); it != edges(tMesh).end(); + ++it) + { + boost::graph_traits::vertex_descriptor ta(source(*it, tMesh)), tb(target(*it, tMesh)); + + if((get(vidmap, ta) == get(vidmap, a) && get(vidmap,tb) == get(vidmap,b)) + || + (get(vidmap,ta) == get(vidmap,b) && get(vidmap,tb) == get(vidmap,a))) + { + T_edge_descriptor ted(*it); + seam_edges.push_back(ted); + break; + } + } + + } + qDebug() << sel_item->selected_edges.size() << ", " << seam_edges.size(); + //fill seam mesh pmaps + BOOST_FOREACH(T_edge_descriptor ed, seam_edges) + { + T_halfedge_descriptor hd = halfedge(ed, tMesh); + T_vertex_descriptor svd(source(hd, tMesh)), tvd(target(hd, tMesh)); + if(!is_border(ed, tMesh)) + { + put(seam_edge_pm, ed, true); + put(seam_vertex_pm, svd, true); + put(seam_vertex_pm, tvd, true); + mark[get(hidmap, hd)/2] = true; + } + } + } + + // map the cones from the selection plugin to the textured polyhedron + boost::unordered_set unordered_cones; + if(method == PARAM_OTE) { + BOOST_FOREACH(P_vertex_descriptor vd, sel_item->selected_vertices) { + boost::graph_traits::vertex_descriptor pvd(vd); + boost::graph_traits::vertex_iterator it = vertices(tMesh).begin(), + end = vertices(tMesh).end(); + for(; it!=end; ++it) { + boost::graph_traits::vertex_descriptor tvd(*it); + if(get(vidmap, *it) == get(vidmap, pvd)) { + unordered_cones.insert(tvd); + } + } + } + } +#endif Seam_mesh sMesh(tMesh, seam_edge_pm, seam_vertex_pm); sMesh.set_seam_edges_number(seam_edges.size()); @@ -637,13 +756,11 @@ void Polyhedron_demo_parameterization_plugin::parameterize(const Parameterizatio QString new_item_name; //determine the different connected_components - boost::property_map::type fim = get(boost::face_external_index, tMesh); - boost::vector_property_map::type> fccmap(fim); + boost::container::flat_map::face_descriptor, int> face_component_map; + boost::associative_property_map< boost::container::flat_map > + fccmap(face_component_map); - Is_selected_property_map edge_pmap(mark); + Is_selected_property_map edge_pmap(mark, &tMesh); int number_of_components = CGAL::Polygon_mesh_processing::connected_components( @@ -663,9 +780,9 @@ void Polyhedron_demo_parameterization_plugin::parameterize(const Parameterizatio // the SEAM MESH faces of each connected component SComponents s_components(number_of_components); - Textured_polyhedron::Base::Facet_iterator fit; - for(fit = tMesh.facets_begin(); fit != tMesh.facets_end(); ++fit) { - s_components.at(fccmap[fit]).insert(face_descriptor(fit)); + for(boost::graph_traits::face_iterator fit = faces(tMesh).begin(); + fit != faces(tMesh).end(); ++fit) { + s_components.at(fccmap[*fit]).insert(s_face_descriptor(*fit)); } // once per component @@ -677,7 +794,7 @@ void Polyhedron_demo_parameterization_plugin::parameterize(const Parameterizatio for(int current_component=0; current_component border; + std::vector border; PMP::border_halfedges(s_components.at(current_component), sMesh, std::back_inserter(border)); @@ -686,17 +803,17 @@ void Polyhedron_demo_parameterization_plugin::parameterize(const Parameterizatio std::cout << border.size() << " border halfedges" << std::endl; // find longest border in the connected component - halfedge_descriptor bhd; // a halfedge on the (possibly virtual) border - boost::unordered_set visited; + s_halfedge_descriptor bhd; // a halfedge on the (possibly virtual) border + boost::unordered_set visited; FT result_len = 0; - BOOST_FOREACH(halfedge_descriptor hd, border) + BOOST_FOREACH(s_halfedge_descriptor hd, border) { assert(is_border(hd, sMesh)); if(visited.find(hd) == visited.end()) { FT len = 0; - BOOST_FOREACH(halfedge_descriptor haf, halfedges_around_face(hd, sMesh)) + BOOST_FOREACH(s_halfedge_descriptor haf, halfedges_around_face(hd, sMesh)) { len += PMP::edge_length(haf, sMesh); visited.insert(haf); @@ -709,19 +826,21 @@ void Polyhedron_demo_parameterization_plugin::parameterize(const Parameterizatio } } } - CGAL_postcondition(bhd != halfedge_descriptor()); + CGAL_postcondition(bhd != s_halfedge_descriptor()); CGAL_postcondition(is_border(bhd, sMesh)); + typedef boost::property_map::type VPMap; + VPMap vpmap =get(boost::vertex_point, tMesh); // collect the border edges for that connected component - BOOST_FOREACH(halfedge_descriptor haf, halfedges_around_face(bhd, sMesh)) + BOOST_FOREACH(s_halfedge_descriptor haf, halfedges_around_face(bhd, sMesh)) { - uv_borders[current_component].push_back(source(haf, tMesh)->point().x()); - uv_borders[current_component].push_back(source(haf, tMesh)->point().y()); - uv_borders[current_component].push_back(source(haf, tMesh)->point().z()); + uv_borders[current_component].push_back(get(vpmap, source(haf, tMesh)).x()); + uv_borders[current_component].push_back(get(vpmap, source(haf, tMesh)).y()); + uv_borders[current_component].push_back(get(vpmap, source(haf, tMesh)).z()); - uv_borders[current_component].push_back(target(haf, tMesh)->point().x()); - uv_borders[current_component].push_back(target(haf, tMesh)->point().y()); - uv_borders[current_component].push_back(target(haf, tMesh)->point().z()); + uv_borders[current_component].push_back(get(vpmap, target(haf, tMesh)).x()); + uv_borders[current_component].push_back(get(vpmap, target(haf, tMesh)).y()); + uv_borders[current_component].push_back(get(vpmap, target(haf, tMesh)).z()); } switch(method) @@ -829,7 +948,7 @@ void Polyhedron_demo_parameterization_plugin::parameterize(const Parameterizatio Parameterizer parameterizer(orb); // mark cones in the seam mesh - typedef boost::unordered_map Cones; + typedef boost::unordered_map Cones; Cones cmap; if(!SMP::internal::locate_unordered_cones Indices; + typedef boost::unordered_map Indices; Indices indices; CGAL::Polygon_mesh_processing::connected_component( face(opposite(bhd, sMesh), sMesh), @@ -875,10 +994,10 @@ void Polyhedron_demo_parameterization_plugin::parameterize(const Parameterizatio } //end for each component QApplication::restoreOverrideCursor(); - - Textured_polyhedron::Base::Halfedge_iterator it1; - Textured_polyhedron::Halfedge_iterator it2; QPointF min(FLT_MAX, FLT_MAX), max(-FLT_MAX, -FLT_MAX); +#ifndef USE_SURFACE_MESH + Base_face_graph::Halfedge_iterator it1; + Textured_polyhedron::Halfedge_iterator it2; for(it1 = tMesh.halfedges_begin(), it2 = tpMesh->halfedges_begin(); it1 != tMesh.halfedges_end()&& @@ -899,21 +1018,57 @@ void Polyhedron_demo_parameterization_plugin::parameterize(const Parameterizatio if(v>max.y()) max.setY(v); } +#else + SMesh::Property_map > uv; + uv = tMesh.add_property_map >("h:uv",std::make_pair(0.0f,0.0f)).first; + Base_face_graph::Halfedge_iterator it; + for(it = tMesh.halfedges_begin(); + it != tMesh.halfedges_end(); + ++it) + { + Seam_mesh::halfedge_descriptor hd(*it); + FT u = uv_pm[target(hd, sMesh)].x(); + FT v = uv_pm[target(hd, sMesh)].y(); + put(uv, *it, std::make_pair(u,v)); + if(umax.x()) + max.setX(u); + if(vmax.y()) + max.setY(v); + } + +#endif Components* components = new Components(0); components->resize(number_of_components); - Textured_polyhedron::Base::Facet_iterator bfit; - Textured_polyhedron::Facet_iterator tfit; - for(bfit = tMesh.facets_begin(), tfit = tpMesh->facets_begin(); - bfit != tMesh.facets_end() && tfit != tpMesh->facets_end(); - ++bfit, ++tfit) + boost::graph_traits::face_iterator bfit; +#ifdef USE_SURFACE_MESH + for(bfit = faces(tMesh).begin(); + bfit != faces(tMesh).end(); + ++bfit) { - components->at(fccmap[bfit]).insert(tfit); + components->at(fccmap[*bfit]).insert(*bfit); } - UVItem *projection = new UVItem(components, uv_borders, QRectF(min, max)); + Scene_textured_facegraph_item* new_item = new Scene_textured_facegraph_item(tMesh); + UVItem *projection = new UVItem(components,new_item->textured_face_graph(), uv_borders, QRectF(min, max)); projection->set_item_name(new_item_name); - Scene_textured_polyhedron_item* new_item = new Scene_textured_polyhedron_item(tpMesh); +#else + boost::graph_traits::face_iterator tfit; + for(bfit = faces(tMesh).begin(), tfit = faces(*tpMesh).begin(); + bfit != faces(tMesh).end() && tfit != faces(*tpMesh).end(); + ++bfit, ++tfit) + { + components->at(fccmap[*bfit]).insert(*tfit); + } + + UVItem *projection = new UVItem(components,tpMesh, uv_borders, QRectF(min, max)); + projection->set_item_name(new_item_name); + Scene_textured_facegraph_item* new_item = new Scene_textured_facegraph_item(tpMesh); +#endif new_item->setName(new_item_name); new_item->setColor(Qt::white); new_item->setRenderingMode(poly_item->renderingMode()); @@ -927,9 +1082,9 @@ void Polyhedron_demo_parameterization_plugin::parameterize(const Parameterizatio graphics_scene->addItem(projection); projections[new_item] = projection; if(current_uv_item) - qobject_cast(projections.key(current_uv_item))->add_border_edges(std::vector(0)); + qobject_cast(projections.key(current_uv_item))->add_border_edges(std::vector(0)); current_uv_item = projection; - qobject_cast(projections.key(current_uv_item))->add_border_edges(current_uv_item->concatenated_borders()); + qobject_cast(projections.key(current_uv_item))->add_border_edges(current_uv_item->concatenated_borders()); if(dock_widget->isHidden()) dock_widget->setVisible(true); dock_widget->setWindowTitle(tr("UVMapping for %1").arg(new_item->name())); diff --git a/Polyhedron/demo/Polyhedron/Scene_textured_surface_mesh_item.cpp b/Polyhedron/demo/Polyhedron/Scene_textured_surface_mesh_item.cpp new file mode 100644 index 00000000000..ec1f0322dd4 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Scene_textured_surface_mesh_item.cpp @@ -0,0 +1,412 @@ +#include "Scene_textured_surface_mesh_item.h" +#include +#include +#include +#include +#include + +typedef EPICK ::Point_3 Point; + +struct Scene_textured_surface_mesh_item_priv +{ + Scene_textured_surface_mesh_item_priv(Scene_textured_surface_mesh_item* parent) + :sm(new SMesh), textureId(-1) + { + item = parent; + texture.GenerateCheckerBoard(2048,2048,128,0,0,0,250,250,255); + uv = sm->add_property_map >("h:uv",std::make_pair(0.0f,0.0f)).first; + + } + Scene_textured_surface_mesh_item_priv(const SMesh& p, Scene_textured_surface_mesh_item* parent) + : sm(new SMesh(p)),textureId(-1),smooth_shading(true) + + { + item = parent; + texture.GenerateCheckerBoard(2048,2048,128,0,0,0,250,250,255); + uv = sm->add_property_map >("h:uv",std::make_pair(0.0f,0.0f)).first; + } + Scene_textured_surface_mesh_item_priv(SMesh* const p,Scene_textured_surface_mesh_item* parent) + :sm(p),textureId(-1),smooth_shading(true) + { + item = parent; + texture.GenerateCheckerBoard(2048,2048,128,0,0,0,250,250,255); + uv = sm->add_property_map >("h:uv",std::make_pair(0.0f,0.0f)).first; + } + + ~Scene_textured_surface_mesh_item_priv() + { + delete sm; + } + + void initializeBuffers(CGAL::Three::Viewer_interface *viewer) const; + void compute_normals_and_vertices(void) const; + + enum VAOs { + Facets=0, + Edges, + Border_edges, + NbOfVaos + }; + enum VBOs { + B_Facets=0, + B_Edges, + B_Border_Edges, + NbOfVbos + }; + + SMesh* sm; + Texture texture; + SMesh::Property_map > uv; + mutable GLuint textureId; + mutable QOpenGLShaderProgram* program; + //[Px][Py][Pz][Nx][Ny][Nz][u][v] + mutable std::vector faces_buffer; + //[Px][Py][Pz][u][v] + mutable std::vector edges_buffer; + //[Px][Py][Pz] + mutable std::vector border_edges_buffer; + bool smooth_shading; + + Scene_textured_surface_mesh_item* item; + typedef Scene_textured_surface_mesh_item I; +}; +void Scene_textured_surface_mesh_item_priv::initializeBuffers(CGAL::Three::Viewer_interface *viewer = 0) const +{ + if(GLuint(-1) == textureId) { + viewer->glGenTextures(1, &textureId); + } + + //Faces + program = item->getShaderProgram(I::PROGRAM_WITH_TEXTURE, viewer); + program->bind(); + item->vaos[Facets]->bind(); + item->buffers[B_Facets].bind(); + item->buffers[B_Facets].allocate(faces_buffer.data(), + static_cast(faces_buffer.size()*sizeof(float))); + + program->enableAttributeArray("vertex"); + program->enableAttributeArray("normal"); + program->enableAttributeArray("v_texCoord"); + + program->setAttributeBuffer("vertex", GL_FLOAT, 0, 3, 8 * sizeof(float)); + program->setAttributeBuffer("normal", GL_FLOAT, 3 * sizeof(float), 3, 8 * sizeof(float)); + program->setAttributeBuffer("v_texCoord", GL_FLOAT, 6 * sizeof(float), 2, 8 * sizeof(float)); + + item->buffers[B_Facets].release(); + item->vaos[Facets]->release(); + program->release(); + + //Edges + program = item->getShaderProgram(I::PROGRAM_WITH_TEXTURED_EDGES, viewer); + program->bind(); + item->vaos[Edges]->bind(); + item->buffers[B_Edges].bind(); + item->buffers[B_Edges].allocate(edges_buffer.data(), + static_cast(edges_buffer.size()*sizeof(float))); + + program->enableAttributeArray("vertex"); + program->enableAttributeArray("v_texCoord"); + + program->setAttributeBuffer("vertex", GL_FLOAT, 0, 3, 5 * sizeof(float)); + program->setAttributeBuffer("v_texCoord", GL_FLOAT, 3 * sizeof(float), 2, 5 * sizeof(float)); + + item->buffers[B_Edges].release(); + item->vaos[Edges]->release(); + program->release(); + + + + + viewer->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + viewer->glActiveTexture(GL_TEXTURE0); + viewer->glBindTexture(GL_TEXTURE_2D, textureId); + viewer->glTexImage2D(GL_TEXTURE_2D, + 0, + GL_RGB, + texture.GetWidth(), + texture.GetHeight(), + 0, + GL_RGB, + GL_UNSIGNED_BYTE, + texture.GetData()); + viewer->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + viewer->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + viewer->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + viewer->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + item->are_buffers_filled = true; +} + +void +Scene_textured_surface_mesh_item_priv::compute_normals_and_vertices(void) const +{ + QApplication::setOverrideCursor(Qt::WaitCursor); + faces_buffer.resize(0); + + + typedef boost::graph_traits::face_iterator face_iterator; + typedef boost::graph_traits::face_iterator face_iterator; + const qglviewer::Vec offset = static_cast(QGLViewer::QGLViewerPool().first())->offset(); + + //Faces + SMesh::Property_map positions = + sm->points(); + SMesh::Property_map fnormals = + sm->add_property_map("f:normal").first; + CGAL::Polygon_mesh_processing::compute_face_normals(*sm,fnormals); + + for(face_iterator f = faces(*sm).begin(); + f != faces(*sm).end(); + ++f) + { + + SMesh::Halfedge_around_face_circulator he(halfedge(*f, *sm), *sm); + SMesh::Halfedge_around_face_circulator end = he; + CGAL_For_all(he,end) + { + //position [3] + const Point& p = get(positions, target(*he, *sm)); + faces_buffer.push_back(p.x() + offset.x); + faces_buffer.push_back(p.y() + offset.y); + faces_buffer.push_back(p.z() + offset.z); + //normals [3] + const EPICK::Vector_3& n = get(fnormals, face(*he, *sm)); + faces_buffer.push_back(n[0]); + faces_buffer.push_back(n[1]); + faces_buffer.push_back(n[2]); + //uvs [2] + const float u = get(uv, *he).first; + const float v = get(uv, *he).second; + faces_buffer.push_back(u); + faces_buffer.push_back(v); + } + } + + //Edges + typedef EPICK::Point_3 Point; + typedef SMesh::Edge_iterator Edge_iterator; + + Edge_iterator he; + + for(he = edges(*sm).begin(); + he != edges(*sm).end(); + ++he) + { + + //position [3] + const Point& a = sm->point(target(*he, *sm)); + const Point& b = sm->point(source(*he, *sm)); + edges_buffer.push_back(a.x() + offset.x); + edges_buffer.push_back(a.y() + offset.y); + edges_buffer.push_back(a.z() + offset.z); + //uvs [2] + float u = get(uv, halfedge(*he, *sm)).first; + float v = get(uv, halfedge(*he, *sm)).second; + + edges_buffer.push_back(u); + edges_buffer.push_back(v); + //position [3] + edges_buffer.push_back(b.x() + offset.x); + edges_buffer.push_back(b.y() + offset.y); + edges_buffer.push_back(b.z() + offset.z); + + //uvs [2] + u = get(uv, opposite(halfedge(*he, *sm), *sm)).first; + v = get(uv, opposite(halfedge(*he, *sm), *sm)).second; + + edges_buffer.push_back(u); + edges_buffer.push_back(v); + + } + + + QApplication::restoreOverrideCursor(); +} + +Scene_textured_surface_mesh_item::Scene_textured_surface_mesh_item() + : Scene_item(Scene_textured_surface_mesh_item_priv::NbOfVbos,Scene_textured_surface_mesh_item_priv::NbOfVaos) +{ + cur_shading=FlatPlusEdges; + is_selected=false; + d = new Scene_textured_surface_mesh_item_priv(this); + invalidateOpenGLBuffers(); +} + +Scene_textured_surface_mesh_item::Scene_textured_surface_mesh_item(SMesh* const p) + : Scene_item(Scene_textured_surface_mesh_item_priv::NbOfVbos,Scene_textured_surface_mesh_item_priv::NbOfVaos) +{ + cur_shading=FlatPlusEdges; + is_selected=false; + d = new Scene_textured_surface_mesh_item_priv(p,this); + invalidateOpenGLBuffers(); +} + +Scene_textured_surface_mesh_item::Scene_textured_surface_mesh_item(const SMesh& p) + : Scene_item(Scene_textured_surface_mesh_item_priv::NbOfVbos,Scene_textured_surface_mesh_item_priv::NbOfVaos) +{ + cur_shading=FlatPlusEdges; + is_selected=false; + d = new Scene_textured_surface_mesh_item_priv(p,this); + invalidateOpenGLBuffers(); +} + +Scene_textured_surface_mesh_item::~Scene_textured_surface_mesh_item() +{ + delete d; +} + +Scene_textured_surface_mesh_item* +Scene_textured_surface_mesh_item::clone() const { + return new Scene_textured_surface_mesh_item(*d->sm); +} + +// Load textured_polyhedron from .OFF file +bool +Scene_textured_surface_mesh_item::load(std::istream& in) +{ + std::cout<<"LOAD"<> *d->sm; + invalidateOpenGLBuffers(); + return in && !isEmpty(); +} + +// Write textured_polyhedron to .OFF file +bool +Scene_textured_surface_mesh_item::save(std::ostream& out) const +{ + out << *d->sm; + return (bool) out; +} + +QString +Scene_textured_surface_mesh_item::toolTip() const +{ + if(!d->sm) + return QString(); + + return QObject::tr("

Textured polyhedron %1 (mode: %5, color: %6)

" + "

Number of vertices: %2
" + "Number of edges: %3
" + "Number of facets: %4

") + .arg(this->name()) + .arg(num_vertices(*d->sm)) + .arg(num_halfedges(*d->sm)/2) + .arg(num_faces(*d->sm)) + .arg(this->renderingModeName()) + .arg(this->color().name()); +} + +// Points/Wireframe/Flat/Gouraud OpenGL drawing in a display list +void Scene_textured_surface_mesh_item::draw(CGAL::Three::Viewer_interface* viewer) const { + + if(!are_buffers_filled) + { + d->compute_normals_and_vertices(); + d->initializeBuffers(viewer); + } + vaos[Scene_textured_surface_mesh_item_priv::Facets]->bind(); + viewer->glActiveTexture(GL_TEXTURE0); + viewer->glBindTexture(GL_TEXTURE_2D, d->textureId); + attribBuffers(viewer, PROGRAM_WITH_TEXTURE); + d->program=getShaderProgram(PROGRAM_WITH_TEXTURE); + d->program->bind(); + viewer->glDrawArrays(GL_TRIANGLES, 0, static_cast(d->faces_buffer.size()/8)); + //Clean-up + d->program->release(); + vaos[Scene_textured_surface_mesh_item_priv::Facets]->release(); + +} +void Scene_textured_surface_mesh_item::drawEdges(CGAL::Three::Viewer_interface* viewer) const { + if(!are_buffers_filled) + d->initializeBuffers(viewer); + + vaos[Scene_textured_surface_mesh_item_priv::Edges]->bind(); + viewer->glActiveTexture(GL_TEXTURE0); + viewer->glBindTexture(GL_TEXTURE_2D, d->textureId); + attribBuffers(viewer, PROGRAM_WITH_TEXTURED_EDGES); + + d->program=getShaderProgram(PROGRAM_WITH_TEXTURED_EDGES); + d->program->bind(); + viewer->glDrawArrays(GL_LINES, 0, static_cast(d->edges_buffer.size()/5)); + + vaos[Scene_textured_surface_mesh_item_priv::Edges]->release(); + d->program->release(); + + vaos[Scene_textured_surface_mesh_item_priv::Border_edges]->bind(); + attribBuffers(viewer, PROGRAM_NO_SELECTION); + d->program=getShaderProgram(PROGRAM_NO_SELECTION); + d->program->bind(); + viewer->glLineWidth(4.0); + d->program->setAttributeValue("colors", QColor(Qt::blue)); + viewer->glDrawArrays(GL_LINES, 0, static_cast(d->border_edges_buffer.size()/3)); + viewer->glLineWidth(1.0); + //Clean-up + d->program->release(); + vaos[Scene_textured_surface_mesh_item_priv::Border_edges]->release(); +} + + +SMesh* +Scene_textured_surface_mesh_item::textured_face_graph() { return d->sm; } +const SMesh* +Scene_textured_surface_mesh_item::textured_face_graph() const { return d->sm; } + +bool +Scene_textured_surface_mesh_item::isEmpty() const { + return (d->sm == 0) || d->sm->is_empty(); +} + +void +Scene_textured_surface_mesh_item::compute_bbox() const { + const Point& p = d->sm->point(*vertices(*d->sm).begin()); + CGAL::Bbox_3 bbox(p.x(), p.y(), p.z(), p.x(), p.y(), p.z()); + + for(boost::graph_traits::vertex_iterator it = vertices(*d->sm).begin(); + it != vertices(*d->sm).end(); + ++it) { + bbox = bbox + d->sm->point(*it).bbox(); + } + _bbox = Bbox(bbox.xmin(),bbox.ymin(),bbox.zmin(), + bbox.xmax(),bbox.ymax(),bbox.zmax()); +} +void +Scene_textured_surface_mesh_item::invalidateOpenGLBuffers() +{ + are_buffers_filled = false; + compute_bbox(); +} +void +Scene_textured_surface_mesh_item::selection_changed(bool p_is_selected) +{ + if(p_is_selected != is_selected) + { + is_selected = p_is_selected; + initializeBuffers(); + //to be replaced by a functor in the d-pointer when the merging is done + if(p_is_selected) + Q_EMIT selectionChanged(); + } + else + is_selected = p_is_selected; +} +void Scene_textured_surface_mesh_item::add_border_edges(std::vector border_edges) +{ + d->border_edges_buffer = border_edges; + d->program=getShaderProgram(PROGRAM_NO_SELECTION); + d->program->bind(); + vaos[Scene_textured_surface_mesh_item_priv::Border_edges]->bind(); + buffers[Scene_textured_surface_mesh_item_priv::B_Border_Edges].bind(); + buffers[Scene_textured_surface_mesh_item_priv::B_Border_Edges].allocate(d->border_edges_buffer.data(), + static_cast(d->border_edges_buffer.size()*sizeof(float))); + d->program->enableAttributeArray("vertex"); + d->program->setAttributeBuffer("vertex",GL_FLOAT,0,3); + d->program->disableAttributeArray("colors"); + buffers[Scene_textured_surface_mesh_item_priv::B_Border_Edges].release(); + vaos[Scene_textured_surface_mesh_item_priv::Border_edges]->release(); + + d->program->release(); + itemChanged(); + +} diff --git a/Polyhedron/demo/Polyhedron/Scene_textured_surface_mesh_item.h b/Polyhedron/demo/Polyhedron/Scene_textured_surface_mesh_item.h new file mode 100644 index 00000000000..c77851c0b69 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Scene_textured_surface_mesh_item.h @@ -0,0 +1,65 @@ +#ifndef SCENE_TEXTURED_SURFACE_MESH_ITEM_H +#define SCENE_TEXTURED_SURFACE_MESH_ITEM_H +#include +#include +#include "SMesh_type.h" +#include +#include "texture.h" + +#ifdef scene_textured_surface_mesh_item_EXPORTS +# define SCENE_TEXTURED_SURFACE_MESH_ITEM_EXPORT Q_DECL_EXPORT +#else +# define SCENE_TEXTURED_SURFACE_MESH_ITEM_EXPORT Q_DECL_IMPORT +#endif + +struct Scene_textured_surface_mesh_item_priv; +// This class represents a textured polyhedron in the OpenGL scene +class SCENE_TEXTURED_SURFACE_MESH_ITEM_EXPORT Scene_textured_surface_mesh_item + : public CGAL::Three::Scene_item { + Q_OBJECT +public: + Scene_textured_surface_mesh_item(); + // Scene_textured_surface_mesh_item(const Scene_textured_surface_mesh_item&); + Scene_textured_surface_mesh_item(const SMesh& p); + Scene_textured_surface_mesh_item(SMesh* const p); + ~Scene_textured_surface_mesh_item(); + + Scene_textured_surface_mesh_item* clone() const; + + // IO + bool load(std::istream& in); + bool save(std::ostream& out) const; + + // Function for displaying meta-data of the item + virtual QString toolTip() const; + + // Indicate if rendering mode is supported + virtual bool supportsRenderingMode(RenderingMode m) const { return (m != Splatting && m != PointsPlusNormals && m != Points && m != Gouraud && m != ShadedPoints); } + // Points/Wireframe/Flat/Gouraud OpenGL drawing in a display list + void draw() const {} + virtual void draw(CGAL::Three::Viewer_interface*) const; + virtual void drawEdges() const {} + virtual void drawEdges(CGAL::Three::Viewer_interface* viewer) const; + + // Get wrapped textured_polyhedron + SMesh* textured_face_graph(); + const SMesh* textured_face_graph() const; + + // Get dimensions + bool isFinite() const { return true; } + bool isEmpty() const; + void compute_bbox() const; + virtual void invalidateOpenGLBuffers(); + virtual void selection_changed(bool); + void add_border_edges(std::vector border_edges); + +Q_SIGNALS: + void selectionChanged(); + +protected: + friend struct Scene_textured_surface_mesh_item_priv; + Scene_textured_surface_mesh_item_priv* d; + +}; // end class Scene_textured_surface_mesh_item + +#endif // SCENE_TEXTURED_SURFACE_MESH_ITEM_H