D-pointer for Scene_edit_polyhedron_item

This commit is contained in:
Maxime Gimeno 2016-05-09 15:07:50 +02:00
parent cdcd5626e7
commit 00b834b7d8
2 changed files with 741 additions and 669 deletions

View File

@ -33,9 +33,9 @@
#include <QGLShaderProgram>
typedef Polyhedron::Vertex_handle Vertex_handle;
typedef boost::graph_traits<Polyhedron>::vertex_descriptor vertex_descriptor;
typedef boost::graph_traits<Polyhedron>::vertex_iterator vertex_iterator;
typedef Polyhedron::Vertex_handle Vertex_handle;
typedef boost::graph_traits<Polyhedron>::vertex_descriptor vertex_descriptor;
typedef boost::graph_traits<Polyhedron>::vertex_iterator vertex_iterator;
typedef boost::graph_traits<Polyhedron>::face_descriptor face_descriptor;
typedef boost::graph_traits<Polyhedron>::halfedge_descriptor halfedge_descriptor;
typedef boost::graph_traits<Polyhedron>::edge_descriptor edge_descriptor;
@ -193,6 +193,8 @@ struct Mouse_keyboard_state_deformation
{ }
};
typedef std::list<Control_vertices_data> Ctrl_vertices_group_data_list;
struct Scene_edit_polyhedron_item_priv;
// This class represents a polyhedron in the OpenGL scene
class SCENE_EDIT_POLYHEDRON_ITEM_EXPORT Scene_edit_polyhedron_item
: public CGAL::Three::Scene_group_item {
@ -242,8 +244,8 @@ public:
void compute_bbox() const;
Bbox bbox() const{return Scene_item::bbox();}
int get_k_ring() { return k_ring_selector.k_ring; }
void set_k_ring(int v) { k_ring_selector.k_ring = v; }
int get_k_ring();
void set_k_ring(int v);
// take mouse events from viewer, main-window does not work
// take keyboard events from main-window, which is more stable
@ -252,34 +254,12 @@ public:
void ShowAsSphere(bool b);
public Q_SLOTS:
void reset_spheres()
{
spheres = NULL;
}
void reset_spheres();
void updateDeform();
void change();
void invalidateOpenGLBuffers();
void selected(const std::set<Polyhedron::Vertex_handle>& m)
{
bool any_changes = false;
for(std::set<vertex_descriptor>::const_iterator it = m.begin(); it != m.end(); ++it)
{
vertex_descriptor vh = *it;
bool changed = false;
if(ui_widget->ROIRadioButton->isChecked()) {
if(ui_widget->InsertRadioButton->isChecked()) { changed = insert_roi_vertex(vh);}
else { changed = erase_roi_vertex(vh); }
}
else {
if(ui_widget->InsertRadioButton->isChecked()) { changed = insert_control_vertex(vh); }
else { changed = erase_control_vertex(vh); }
}
any_changes |= changed;
}
if(any_changes) { invalidateOpenGLBuffers(); Q_EMIT itemChanged(); }
}
void selected(const std::set<Polyhedron::Vertex_handle>& m);
void select(double orig_x,
double orig_y,
@ -291,119 +271,20 @@ public Q_SLOTS:
void deform(); // deform the mesh
void remesh();
// members
private:
Ui::DeformMesh* ui_widget;
Scene_polyhedron_item* poly_item;
bool need_change;
// For drawing
mutable std::vector<GLdouble> positions;
mutable std::vector<unsigned int> tris;
mutable std::vector<unsigned int> edges;
mutable std::vector<GLdouble> color_lines;
mutable std::vector<GLdouble> color_bbox;
mutable std::vector<GLdouble> ROI_points;
mutable std::vector<GLdouble> control_points;
mutable std::vector<GLdouble> ROI_color;
mutable std::vector<GLdouble> control_color;
mutable std::vector<GLdouble> normals;
mutable std::vector<GLdouble> pos_bbox;
mutable std::vector<GLdouble> pos_axis;
mutable std::vector<GLdouble> pos_frame_plane;
mutable QOpenGLShaderProgram *program;
mutable QOpenGLShaderProgram bbox_program;
mutable std::size_t nb_ROI;
mutable std::size_t nb_control;
mutable std::size_t nb_axis;
mutable std::size_t nb_bbox;
mutable Scene_spheres_item* spheres;
protected:
friend struct Scene_edit_polyhedron_item_priv;
Scene_edit_polyhedron_item_priv* d;
enum Buffer
{
Facet_vertices =0,
Facet_normals,
Roi_vertices,
Control_vertices,
Bbox_vertices,
Axis_vertices,
Axis_colors,
Frame_vertices,
NumberOfBuffers
};
enum Vao
{
Facets=0,
Roi_points,
Edges,
BBox,
Control_points,
Axis,
Frame_plane,
NumberOfVaos
};
mutable QOpenGLBuffer *in_bu;
using CGAL::Three::Scene_item::initializeBuffers;
void initializeBuffers(CGAL::Three::Viewer_interface *viewer) const;
void compute_normals_and_vertices(void);
void compute_bbox(const CGAL::Three::Scene_interface::Bbox&);
void reset_drawing_data();
Deform_mesh* deform_mesh;
typedef std::list<Control_vertices_data> Ctrl_vertices_group_data_list;
Ctrl_vertices_group_data_list::iterator active_group;
Ctrl_vertices_group_data_list ctrl_vertex_frame_map; // keep list of group of control vertices with assoc data
double length_of_axis; // for drawing axis at a group of control vertices
// by interleaving 'viewer's events (check constructor), keep followings:
Mouse_keyboard_state_deformation state;
//For constraint rotation
qglviewer::LocalConstraint rot_constraint;
bool is_rot_free;
bool own_poly_item; //indicates if the poly_item should be deleted by the destructor
Scene_polyhedron_item_k_ring_selection k_ring_selector;
public:
// Deformation related functions //
bool insert_control_vertex(vertex_descriptor v)
{
if(!is_there_any_ctrl_vertices_group()) {
print_message("There is no group of control vertices, create one!");
return false;
} // no group of control vertices to insert
bool insert_control_vertex(vertex_descriptor v);
bool inserted = deform_mesh->insert_control_vertex(v);
if(inserted) {
active_group->ctrl_vertices_group.push_back(v);
active_group->refresh();
}
return inserted;
}
bool insert_roi_vertex(vertex_descriptor v);
bool insert_roi_vertex(vertex_descriptor v)
{
return deform_mesh->insert_roi_vertex(v);
}
bool erase_control_vertex(vertex_descriptor v);
bool erase_control_vertex(vertex_descriptor v)
{
if(deform_mesh->erase_control_vertex(v)) // API should be safe enough to do that (without checking empty group of control vertices etc.)
{
refresh_all_group_centers(); // since we don't know which group of control vertices v is erased from, refresh all
return true;
}
print_message("Selected vertex is not a control vertex!");
return false;
}
bool erase_roi_vertex(vertex_descriptor v)
{
erase_control_vertex(v); // erase control vertex
return deform_mesh->erase_roi_vertex(v);
}
bool erase_roi_vertex(vertex_descriptor v);
void set_all_vertices_as_roi()
{
@ -414,208 +295,23 @@ public:
}
}
void clear_roi()
{
for(Ctrl_vertices_group_data_list::iterator it = ctrl_vertex_frame_map.begin(); it != ctrl_vertex_frame_map.end(); ++it)
{
delete it->frame;
}
ctrl_vertex_frame_map.clear();
deform_mesh->clear_roi_vertices();
void clear_roi();
create_ctrl_vertices_group(); // create one new group of control vertices
}
void create_ctrl_vertices_group();
void create_ctrl_vertices_group()
{
for(Ctrl_vertices_group_data_list::iterator it = ctrl_vertex_frame_map.begin(); it != ctrl_vertex_frame_map.end(); ++it) {
if(it->ctrl_vertices_group.empty()) {
active_group = it;
return;
}
}
void delete_ctrl_vertices_group(bool create_new = true);
// No empty group of control vertices
qglviewer::ManipulatedFrame* new_frame = new qglviewer::ManipulatedFrame();
new_frame->setRotationSensitivity(2.0f);
connect(new_frame, SIGNAL(manipulated()), this, SLOT(change()));
void prev_ctrl_vertices_group();
void next_ctrl_vertices_group();
void pivoting_end();
Control_vertices_data hgd(deform_mesh, new_frame);
ctrl_vertex_frame_map.push_back(hgd);
hgd.refresh();
void pivoting_begin();
active_group = --ctrl_vertex_frame_map.end();
invalidateOpenGLBuffers();
Q_EMIT itemChanged();
print_message("A new empty group of control vertices is created.");
}
void delete_ctrl_vertices_group(bool create_new = true)
{
if(!is_there_any_ctrl_vertices_group()) {
print_message("There is no group of control vertices to be deleted!");
return;
} // no group of control vertices
// delete group representative
for(Ctrl_vertices_group_data_list::iterator it = ctrl_vertex_frame_map.begin(); it != ctrl_vertex_frame_map.end(); ++it)
{
if(it == active_group)
{
delete it->frame;
for(std::vector<vertex_descriptor>::iterator v_it = it->ctrl_vertices_group.begin(); v_it != it->ctrl_vertices_group.end(); ++v_it) {
deform_mesh->erase_control_vertex(*v_it);
}
ctrl_vertex_frame_map.erase(it);
break;
}
}
// assign another ctrl_vertices_group to active_group
Ctrl_vertices_group_data_list::iterator hgb, hge;
if( is_there_any_ctrl_vertices_group(hgb, hge) )
{
active_group = hgb;
} // no group of control vertices
else if(create_new)
{
create_ctrl_vertices_group();
}
}
void prev_ctrl_vertices_group()
{
Ctrl_vertices_group_data_list::iterator hgb, hge;
if( !is_there_any_ctrl_vertices_group(hgb, hge) ) {
print_message("There is no group of control vertices to iterate on!");
return;
}
// shift
if(hgb == active_group) { active_group = --hge; }
else {--active_group; }
}
void next_ctrl_vertices_group()
{
Ctrl_vertices_group_data_list::iterator hgb, hge;
if( !is_there_any_ctrl_vertices_group(hgb, hge) ) {
print_message("There is no group of control vertices to iterate on!");
return;
}
// shift
if(--hge == active_group) { active_group = hgb; }
else {++active_group; }
}
void pivoting_end()
{
for(Ctrl_vertices_group_data_list::iterator it = ctrl_vertex_frame_map.begin(); it != ctrl_vertex_frame_map.end(); ++it)
{
//update constraint rotation vector, set only for the last group
it->rot_direction = it->frame->rotation().rotate( qglviewer::Vec(0.,0.,1.) );
//translate center of the frame
qglviewer::Vec vec= it->frame->position();
it->refresh();
it->frame_initial_center = vec;
it->frame->setPosition(vec);
}
for(Ctrl_vertices_group_data_list::iterator it = ctrl_vertex_frame_map.begin(); it != ctrl_vertex_frame_map.end(); ++it)
{
it->frame->blockSignals(false);
}
}
void pivoting_begin()
{
is_rot_free=true;
rot_constraint.setRotationConstraintType(qglviewer::AxisPlaneConstraint::FREE);
rot_constraint.setTranslationConstraintType(qglviewer::AxisPlaneConstraint::FREE);
// just block signals to prevent deformation
for(Ctrl_vertices_group_data_list::iterator it = ctrl_vertex_frame_map.begin(); it != ctrl_vertex_frame_map.end(); ++it)
{
it->frame->blockSignals(true);
}
}
void save_roi(const char* file_name) const
{
std::ofstream out(file_name);
// save roi
out << deform_mesh->roi_vertices().size() << std::endl;
BOOST_FOREACH(vertex_descriptor vd, deform_mesh->roi_vertices())
{
out << vd->id() << " ";
}
out << std::endl;
// save control vertices
out << ctrl_vertex_frame_map.size() << std::endl; // control vertices count
for(Ctrl_vertices_group_data_list::const_iterator hgb = ctrl_vertex_frame_map.begin(); hgb != ctrl_vertex_frame_map.end(); ++hgb) {
out << hgb->ctrl_vertices_group.size() << std::endl;
for(std::vector<vertex_descriptor>::const_iterator hb = hgb->ctrl_vertices_group.begin(); hb != hgb->ctrl_vertices_group.end(); ++hb)
{
out << (*hb)->id() << " ";
}
out << std::endl;
}
}
void read_roi(const char* file_name)
{
clear_roi();
delete_ctrl_vertices_group(false);
// put vertices to vector
std::vector<vertex_descriptor> all_vertices;
all_vertices.reserve(num_vertices(deform_mesh->halfedge_graph()));
vertex_iterator vb, ve;
for(boost::tie(vb, ve) = vertices(deform_mesh->halfedge_graph()); vb != ve; ++vb) {
all_vertices.push_back(*vb);
}
// read roi
std::ifstream in(file_name);
int roi_size;
in >> roi_size;
while(roi_size-- > 0)
{
std::size_t v_id;
in >> v_id;
insert_roi_vertex(all_vertices[v_id]);
}
// read control vertices
int ctrl_vertices_group_size;
in >> ctrl_vertices_group_size;
while(ctrl_vertices_group_size-- > 0)
{
create_ctrl_vertices_group();
int ctrl_size;
in >> ctrl_size;
while(ctrl_size-- > 0)
{
std::size_t v_id;
in >> v_id;
insert_control_vertex(all_vertices[v_id]);
}
}
}
void overwrite_deform_object()
{
deform_mesh->overwrite_initial_geometry();
refresh_all_group_centers();
}
void reset_deform_object()
{
deform_mesh->reset();
refresh_all_group_centers();
}
void save_roi(const char* file_name) const;
void read_roi(const char* file_name);
void overwrite_deform_object();
void reset_deform_object();
struct Is_selected {
Deform_mesh* dm;
Is_selected(Deform_mesh* dm) : dm(dm) {}
@ -624,14 +320,7 @@ public:
}
};
boost::optional<std::size_t> get_minimum_isolated_component() {
Travel_isolated_components::Minimum_visitor visitor;
Travel_isolated_components().travel<Vertex_handle>
(vertices(*polyhedron()).first, vertices(*polyhedron()).second,
polyhedron()->size_of_vertices(), Is_selected(deform_mesh), visitor);
return visitor.minimum;
}
boost::optional<std::size_t> get_minimum_isolated_component();
struct Select_roi_output {
Select_roi_output(Deform_mesh* dm) : dm(dm) { }
void operator()(Vertex_handle vh) {
@ -640,18 +329,8 @@ public:
Deform_mesh* dm;
};
boost::optional<std::size_t> select_isolated_components(std::size_t threshold) {
typedef boost::function_output_iterator<Select_roi_output> Output_iterator;
Output_iterator out(deform_mesh);
boost::optional<std::size_t> select_isolated_components(std::size_t threshold) ;
Travel_isolated_components::Selection_visitor<Output_iterator> visitor(threshold, out);
Travel_isolated_components().travel<Vertex_handle>
(vertices(*polyhedron()).first, vertices(*polyhedron()).second,
polyhedron()->size_of_vertices(), Is_selected(deform_mesh), visitor);
if(visitor.any_inserted) { invalidateOpenGLBuffers(); Q_EMIT itemChanged(); }
return visitor.minimum_visitor.minimum;
}
protected:
// Deformation related functions //
void print_message(const QString& /*message*/)
@ -659,113 +338,17 @@ protected:
// std::cout << message.toStdString() << std::endl;
}
bool is_there_any_ctrl_vertices_group(Ctrl_vertices_group_data_list::iterator& hgb, Ctrl_vertices_group_data_list::iterator& hge)
{
hgb = ctrl_vertex_frame_map.begin(); hge = ctrl_vertex_frame_map.end();
return hgb != hge;
}
bool is_there_any_ctrl_vertices_group(Ctrl_vertices_group_data_list::iterator& hgb, Ctrl_vertices_group_data_list::iterator& hge);
bool is_there_any_ctrl_vertices_group()
{
Ctrl_vertices_group_data_list::iterator hgb, hge;
return is_there_any_ctrl_vertices_group(hgb, hge);
}
bool is_there_any_ctrl_vertices_group();
bool is_there_any_ctrl_vertices()
{
Ctrl_vertices_group_data_list::iterator hgb, hge;
if(!is_there_any_ctrl_vertices_group(hgb, hge)) { return false; } // there isn't any group of control vertices
for(; hgb != hge; ++hgb) // check inside groups of control vertices
{
if(!hgb->ctrl_vertices_group.empty()) { return true; }
}
return false;
}
void refresh_all_group_centers()
{
for(Ctrl_vertices_group_data_list::iterator it = ctrl_vertex_frame_map.begin(); it != ctrl_vertex_frame_map.end(); ++it)
{ it->refresh(); }
}
bool activate_closest_manipulated_frame(int x, int y)
{
if(state.ctrl_pressing && (state.left_button_pressing || state.right_button_pressing) )
{ // user is deforming currently don't change the state
return false;
}
if(ctrl_vertex_frame_map.empty()) { return false; }
rot_constraint.setRotationConstraintType(qglviewer::AxisPlaneConstraint::FREE);
rot_constraint.setTranslationConstraintType(qglviewer::AxisPlaneConstraint::FREE);
QGLViewer* viewer = *QGLViewer::QGLViewerPool().begin();
qglviewer::Camera* camera = viewer->camera();
if(!state.ctrl_pressing)
{
if(viewer->manipulatedFrame() == NULL)
{ return false;}
viewer->setManipulatedFrame(NULL);
return true;
}
// now find closest frame and make it active manipulated frame
Ctrl_vertices_group_data_list::iterator min_it = ctrl_vertex_frame_map.begin();
const qglviewer::Vec& pos_it = camera->projectedCoordinatesOf(min_it->frame->position());
float min_dist = std::pow(pos_it.x - x, 2) + std::pow(pos_it.y - y, 2);
for(Ctrl_vertices_group_data_list::iterator it = ctrl_vertex_frame_map.begin(); it != ctrl_vertex_frame_map.end(); ++it)
{
const qglviewer::Vec& pos_it = camera->projectedCoordinatesOf(it->frame->position());
float dist = std::pow(pos_it.x - x, 2) + std::pow(pos_it.y - y, 2);
if(dist < min_dist) {
min_dist = dist;
min_it = it;
}
}
//set rotation constraint for the manipulated frame
if (!is_rot_free){
rot_constraint.setRotationConstraintDirection(min_it->rot_direction);
rot_constraint.setRotationConstraintType(qglviewer::AxisPlaneConstraint::AXIS);
min_it->frame->setConstraint(&rot_constraint);
}
else
{
if( ui_widget->ActivateFixedPlaneCheckBox->isChecked())
{
// the constraint is local to the frame
rot_constraint.setTranslationConstraint(qglviewer::AxisPlaneConstraint::PLANE,qglviewer::Vec(0,0,1));
if(!ui_widget->ActivatePivotingCheckBox->isChecked()){
rot_constraint.setRotationConstraintType(qglviewer::AxisPlaneConstraint::FORBIDDEN);
}
min_it->frame->setConstraint(&rot_constraint);
}
}
if(viewer->manipulatedFrame() == min_it->frame)
{ return false; }
viewer->setManipulatedFrame(min_it->frame);
return true;
}
bool is_there_any_ctrl_vertices();
void refresh_all_group_centers();
bool activate_closest_manipulated_frame(int x, int y);
bool keyPressEvent(QKeyEvent* e);
void update_normals() {
BOOST_FOREACH(vertex_descriptor vd, deform_mesh->roi_vertices())
{
std::size_t id = vd->id();
const Polyhedron::Traits::Vector_3& n =
CGAL::Polygon_mesh_processing::compute_vertex_normal(vd, deform_mesh->halfedge_graph());
normals[id*3] = n.x();
normals[id*3+1] = n.y();
normals[id*3+2] = n.z();
}
}
void update_normals();
double scene_diag() const {
const double& xdelta = bbox().xmax() - bbox().xmin();