123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691 |
- #ifndef IGL_OPENGL2_MOUSECONTROLLER_H
- #define IGL_OPENGL2_MOUSECONTROLLER_H
- #include <Eigen/StdVector>
- #include "RotateWidget.h"
- #include "TranslateWidget.h"
- #include <Eigen/Core>
- #include <Eigen/Geometry>
- #include <vector>
- namespace igl
- {
- namespace opengl2
- {
- class MouseController
- {
- public:
- typedef Eigen::VectorXi VectorXb;
-
-
-
-
-
-
-
-
- static inline void propogate_to_descendants_if(
- const VectorXb & S,
- const Eigen::VectorXi & P,
- VectorXb & T);
-
-
-
-
-
-
-
-
- static inline void color_if(
- const VectorXb & S,
- const Eigen::Vector4f & selected_color,
- const Eigen::Vector4f & unselected_color,
- Eigen::MatrixXf & C);
- enum WidgetMode
- {
- WIDGET_MODE_ROTATE = 0,
- WIDGET_MODE_TRANSLATE = 1,
- NUM_WIDGET_MODES = 2,
- };
- private:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- bool m_is_selecting;
- VectorXb m_selection;
- int m_down_x,m_down_y,m_drag_x,m_drag_y;
- int m_width,m_height;
- igl::opengl2::RotateWidget m_widget;
- igl::opengl2::TranslateWidget m_trans_widget;
- Eigen::Quaterniond m_widget_rot_at_selection;
-
- typedef std::vector<
- Eigen::Quaterniond,
- Eigen::aligned_allocator<Eigen::Quaterniond> > RotationList;
- typedef std::vector< Eigen::Vector3d > TranslationList;
- RotationList
- m_rotations,
- m_rotations_at_selection,
- m_fk_rotations_at_selection,
- m_parent_rotations_at_selection;
- TranslationList
- m_translations,
- m_translations_at_selection,
- m_fk_translations_at_selection;
- bool m_root_enabled;
- WidgetMode m_widget_mode;
- public:
- MouseController();
-
- inline const VectorXb & selection() const{return m_selection;};
-
- inline const bool & is_selecting() const{return m_is_selecting;}
- inline bool is_widget_down() const{return m_widget.is_down();}
- inline bool is_trans_widget_down() const{return m_trans_widget.is_down();}
-
- inline const RotationList & rotations() const{return m_rotations;}
- inline const TranslationList & translations() const{return m_translations;}
-
- inline bool & root_enabled(){ return m_root_enabled;}
- inline void reshape(const int w, const int h);
-
-
-
-
-
-
- inline bool down(const int x, const int y);
- inline bool drag(const int x, const int y);
- inline bool up(const int x, const int y);
-
- inline void draw() const;
-
-
-
-
-
-
-
- inline void set_selection_from_last_drag(
- const Eigen::MatrixXd & C,
- const Eigen::MatrixXi & BE,
- const Eigen::VectorXi & P,
- const Eigen::VectorXi & RP);
-
- inline void set_selection(
- const Eigen::VectorXi & S,
- const Eigen::MatrixXd & C,
- const Eigen::MatrixXi & BE,
- const Eigen::VectorXi & P,
- const Eigen::VectorXi & RP);
-
-
-
-
- inline void set_size(const int n);
-
- inline void reset();
- inline void reset_selected();
- inline void reset_rotations();
- inline void reset_selected_rotations();
- inline void reset_translations();
- inline void reset_selected_translations();
- inline bool set_rotations(const RotationList & vQ);
- inline bool set_translations(const TranslationList & vT);
-
- inline void clear_selection();
-
- inline bool any_selection() const;
- inline void set_widget_mode(const WidgetMode & mode);
- public:
- EIGEN_MAKE_ALIGNED_OPERATOR_NEW
- };
- }
- }
- #include "../line_segment_in_rectangle.h"
- #include "draw_rectangular_marquee.h"
- #include "project.h"
- #include "../forward_kinematics.h"
- #include <iostream>
- #include <algorithm>
- #include <functional>
- inline void igl::opengl2::MouseController::propogate_to_descendants_if(
- const VectorXb & S,
- const Eigen::VectorXi & P,
- VectorXb & T)
- {
- using namespace std;
- const int n = S.rows();
- assert(P.rows() == n);
-
- T = S;
- vector<bool> seen(n,false);
-
- const function<bool(int)> look_up = [&](int e) -> bool
- {
- if(e==-1)
- {
- return false;
- }
- if(!seen[e])
- {
- seen[e] = true;
- T(e) |= look_up(P(e));
- }
- return T(e);
- };
- for(int e = 0;e<n;e++)
- {
- if(!seen[e])
- {
- T(e) = look_up(e);
- }
- }
- }
- inline void igl::opengl2::MouseController::color_if(
- const VectorXb & S,
- const Eigen::Vector4f & selected_color,
- const Eigen::Vector4f & unselected_color,
- Eigen::MatrixXf & C)
- {
- C.resize(S.rows(),4);
- for(int e=0;e<S.rows();e++)
- {
- C.row(e) = S(e)?selected_color:unselected_color;
- }
- }
- inline igl::opengl2::MouseController::MouseController():
- m_is_selecting(false),
- m_selection(),
- m_down_x(-1),m_down_y(-1),m_drag_x(-1),m_drag_y(-1),
- m_width(-1),m_height(-1),
- m_widget(),
- m_widget_rot_at_selection(),
-
- m_trans_widget(),
- m_rotations(),
- m_translations(),
- m_rotations_at_selection(),
- m_root_enabled(true),
- m_widget_mode(WIDGET_MODE_ROTATE)
- {
- }
- inline void igl::opengl2::MouseController::reshape(const int w, const int h)
- {
- m_width = w;
- m_height = h;
- }
- inline bool igl::opengl2::MouseController::down(const int x, const int y)
- {
- using namespace std;
- m_down_x = m_drag_x =x;
- m_down_y = m_drag_y =y;
- const bool widget_down = any_selection() &&
- (
- (m_widget_mode == WIDGET_MODE_ROTATE && m_widget.down(x,m_height-y)) ||
- (m_widget_mode == WIDGET_MODE_TRANSLATE &&
- m_trans_widget.down(x,m_height-y))
- );
- if(!widget_down)
- {
- m_is_selecting = true;
- }
- return m_is_selecting || widget_down;
- }
- inline bool igl::opengl2::MouseController::drag(const int x, const int y)
- {
- using namespace std;
- using namespace Eigen;
- m_drag_x = x;
- m_drag_y = y;
- if(m_is_selecting)
- {
- return m_is_selecting;
- }else
- {
- switch(m_widget_mode)
- {
- default:
- case WIDGET_MODE_ROTATE:
- {
- if(!m_widget.drag(x,m_height-y))
- {
- return false;
- }
- assert(any_selection());
- assert(m_selection.size() == (int)m_rotations.size());
- assert(m_selection.size() == (int)m_translations.size());
- for(int e = 0;e<m_selection.size();e++)
- {
- if(m_selection(e))
- {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- const Quaterniond & frame = m_fk_rotations_at_selection[e];
- m_rotations[e] =
- m_rotations_at_selection[e] *
- frame.conjugate() *
- (m_widget.rot*m_widget_rot_at_selection.conjugate()) *
- frame;
- }
- }
- }
- case WIDGET_MODE_TRANSLATE:
- {
- if(!m_trans_widget.drag(x,m_height-y))
- {
- return false;
- }
- assert(any_selection());
- assert(m_selection.size() == (int)m_rotations.size());
- assert(m_selection.size() == (int)m_translations.size());
- for(int e = 0;e<m_selection.size();e++)
- {
- if(m_selection(e))
- {
- m_translations[e] =
- m_translations_at_selection[e] +
- m_parent_rotations_at_selection[e].conjugate()*
- m_trans_widget.m_trans;
- }
- }
- }
- }
- return true;
- }
- }
- inline bool igl::opengl2::MouseController::up(const int x, const int y)
- {
- m_is_selecting = false;
- m_widget.up(x,m_height-y);
- m_trans_widget.up(x,m_height-y);
- return false;
- }
- inline void igl::opengl2::MouseController::draw() const
- {
- if(any_selection())
- {
- switch(m_widget_mode)
- {
- default:
- case WIDGET_MODE_ROTATE:
- m_widget.draw();
- break;
- case WIDGET_MODE_TRANSLATE:
- m_trans_widget.draw();
- break;
- }
- }
- if(m_is_selecting)
- {
-
- GLboolean dt;
- glGetBooleanv(GL_DEPTH_TEST,&dt);
- int old_vp[4];
- glGetIntegerv(GL_VIEWPORT,old_vp);
-
- glViewport(0,0,m_width,m_height);
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- gluOrtho2D(0,m_width,0,m_height);
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
- glDisable(GL_DEPTH_TEST);
- draw_rectangular_marquee(
- m_down_x,
- m_height-m_down_y,
- m_drag_x,
- m_height-m_drag_y);
-
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
- glViewport(old_vp[0],old_vp[1],old_vp[2],old_vp[3]);
- dt?glEnable(GL_DEPTH_TEST):glDisable(GL_DEPTH_TEST);
- }
- }
- inline void igl::opengl2::MouseController::set_selection_from_last_drag(
- const Eigen::MatrixXd & C,
- const Eigen::MatrixXi & BE,
- const Eigen::VectorXi & P,
- const Eigen::VectorXi & RP)
- {
- using namespace Eigen;
- using namespace std;
- m_rotations_at_selection = m_rotations;
- m_translations_at_selection = m_translations;
- assert(BE.rows() == P.rows());
- m_selection = VectorXb::Zero(BE.rows());
-
-
-
-
- vector<Quaterniond,aligned_allocator<Quaterniond> > vQ;
- vector<Vector3d> vT;
- forward_kinematics(C,BE,P,m_rotations,m_translations,vQ,vT);
-
- for(int e = 0;e<BE.rows();e++)
- {
- Affine3d a = Affine3d::Identity();
- a.translate(vT[e]);
- a.rotate(vQ[e]);
- Vector3d s = a * (Vector3d)C.row(BE(e,0));
- Vector3d d = a * (Vector3d)C.row(BE(e,1));
- Vector3d projs = project(s);
- Vector3d projd = project(d);
- m_selection(e) = line_segment_in_rectangle(
- projs.head(2),projd.head(2),
- Vector2d(m_down_x,m_height-m_down_y),
- Vector2d(m_drag_x,m_height-m_drag_y));
- }
- return set_selection(m_selection,C,BE,P,RP);
- }
- inline void igl::opengl2::MouseController::set_selection(
- const Eigen::VectorXi & S,
- const Eigen::MatrixXd & C,
- const Eigen::MatrixXi & BE,
- const Eigen::VectorXi & P,
- const Eigen::VectorXi & RP)
- {
- using namespace Eigen;
- using namespace std;
- vector<Quaterniond,aligned_allocator<Quaterniond> > & vQ =
- m_fk_rotations_at_selection;
- vector<Vector3d> & vT = m_fk_translations_at_selection;
- forward_kinematics(C,BE,P,m_rotations,m_translations,vQ,vT);
- m_parent_rotations_at_selection.resize(
- m_rotations.size(),Quaterniond::Identity());
- for(size_t r = 0;r<vQ.size();r++)
- {
- if(P(r)>=0)
- {
- m_parent_rotations_at_selection[r] = vQ[P(r)];
- }
- }
- if(&m_selection != &S)
- {
- m_selection = S;
- }
- assert(m_selection.rows() == BE.rows());
- assert(BE.rows() == P.rows());
- assert(BE.rows() == RP.rows());
-
- auto propagate = [&](const int e, const VectorXb & S, VectorXb & N)
- {
- if(S(e))
- {
- int f = e;
- while(true)
- {
- int p = P(f);
- if(p==-1||!S(p))
- {
- break;
- }
- N(f) = false;
- f = p;
- }
- }
- };
- VectorXb prev_selection = m_selection;
-
- while(true)
- {
-
- VectorXb SRP(VectorXb::Zero(RP.maxCoeff()+1));
- for(int e = 0;e<BE.rows();e++)
- {
- SRP(RP(e)) |= m_selection(e);
- }
- for(int e = 0;e<BE.rows();e++)
- {
- m_selection(e) = SRP(RP(e));
- }
-
- VectorXb new_selection = m_selection;
- for(int e = 0;e<P.rows();e++)
- {
- propagate(e,m_selection,new_selection);
- }
- m_selection = new_selection;
- if(m_selection==prev_selection)
- {
- break;
- }
- prev_selection = m_selection;
- }
-
- if(m_selection.array().any())
- {
-
- Vector3d avg_pos(0,0,0);
-
- m_widget_rot_at_selection.coeffs().setConstant(0);
- m_widget.rot.coeffs().array().setConstant(0);
- Quaterniond cur_rot(0,0,0,0);
- int num_selection = 0;
-
- for(int e = 0;e<BE.rows();e++)
- {
- if(m_selection(e))
- {
- Vector3d s = C.row(BE(e,0));
- Vector3d d = C.row(BE(e,1));
- auto b = (d-s).transpose().eval();
- {
- Affine3d a = Affine3d::Identity();
- a.translate(vT[e]);
- a.rotate(vQ[e]);
- avg_pos += a*s;
- }
-
- Quaterniond rot_at_bind;
- rot_at_bind.setFromTwoVectors(Vector3d(1,0,0),b);
- const Quaterniond abs_rot = vQ[e] * rot_at_bind;
- m_widget_rot_at_selection.coeffs() += abs_rot.coeffs();
-
- num_selection++;
- }
- }
-
- avg_pos.array() /= (double)num_selection;
-
- m_widget_rot_at_selection.coeffs().array() /= (double)num_selection;
- m_widget_rot_at_selection.normalize();
- m_widget.rot = m_widget_rot_at_selection;
- m_widget.pos = avg_pos;
- m_trans_widget.m_pos = avg_pos;
-
- m_trans_widget.m_trans.setConstant(0);
- }
- m_widget.m_is_enabled = true;
- m_trans_widget.m_is_enabled = true;
- for(int s = 0;s<m_selection.rows();s++)
- {
-
- if(!m_root_enabled && m_selection(s) && P(s) == -1)
- {
- m_widget.m_is_enabled = false;
- m_trans_widget.m_is_enabled = false;
- break;
- }
- }
- }
- inline void igl::opengl2::MouseController::set_size(const int n)
- {
- using namespace Eigen;
- clear_selection();
- m_rotations.clear();
- m_rotations.resize(n,Quaterniond::Identity());
- m_translations.clear();
- m_translations.resize(n,Vector3d(0,0,0));
- m_selection = VectorXb::Zero(n);
- }
- inline void igl::opengl2::MouseController::reset()
- {
- reset_rotations();
- reset_translations();
- }
- inline void igl::opengl2::MouseController::reset_selected()
- {
- reset_selected_rotations();
- reset_selected_translations();
- }
- inline void igl::opengl2::MouseController::reset_rotations()
- {
- using namespace Eigen;
- using namespace std;
- fill(m_rotations.begin(),m_rotations.end(),Quaterniond::Identity());
-
- clear_selection();
- }
- inline void igl::opengl2::MouseController::reset_selected_rotations()
- {
- using namespace Eigen;
- for(int e = 0;e<m_selection.size();e++)
- {
- if(m_selection(e))
- {
- m_rotations[e] = Quaterniond::Identity();
- }
- }
- }
- inline void igl::opengl2::MouseController::reset_translations()
- {
- using namespace Eigen;
- using namespace std;
- fill(m_translations.begin(),m_translations.end(),Vector3d(0,0,0));
-
- clear_selection();
- }
- inline void igl::opengl2::MouseController::reset_selected_translations()
- {
- using namespace Eigen;
- for(int e = 0;e<m_selection.size();e++)
- {
- if(m_selection(e))
- {
- m_translations[e] = Vector3d(0,0,0);
- }
- }
- }
- inline bool igl::opengl2::MouseController::set_rotations(const RotationList & vQ)
- {
- if(vQ.size() != m_rotations.size())
- {
- return false;
- }
- assert(!any_selection());
- m_rotations = vQ;
- return true;
- }
- inline bool igl::opengl2::MouseController::set_translations(const TranslationList & vT)
- {
- if(vT.size() != m_translations.size())
- {
- return false;
- }
- assert(!any_selection());
- m_translations = vT;
- return true;
- }
- inline void igl::opengl2::MouseController::clear_selection()
- {
- m_selection.setConstant(false);
- }
- inline bool igl::opengl2::MouseController::any_selection() const
- {
- return m_selection.array().any();
- }
- inline void igl::opengl2::MouseController::set_widget_mode(const WidgetMode & mode)
- {
- switch(m_widget_mode)
- {
- default:
- case WIDGET_MODE_TRANSLATE:
- m_widget.pos = m_trans_widget.m_pos+m_trans_widget.m_trans;
- break;
- case WIDGET_MODE_ROTATE:
- break;
- }
- m_widget_mode = mode;
- }
- #endif
|