MouseController.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #ifndef IGL_OPENGL2_MOUSECONTROLLER_H
  9. #define IGL_OPENGL2_MOUSECONTROLLER_H
  10. // Needs to be included before others
  11. #include <Eigen/StdVector>
  12. #include "RotateWidget.h"
  13. #include "TranslateWidget.h"
  14. #include <Eigen/Core>
  15. #include <Eigen/Geometry>
  16. #include <vector>
  17. // Class for control a skeletal FK rig with the mouse.
  18. namespace igl
  19. {
  20. namespace opengl2
  21. {
  22. class MouseController
  23. {
  24. public:
  25. typedef Eigen::VectorXi VectorXb;
  26. // Propogate selection to descendants so that selected bones and their
  27. // subtrees are all selected.
  28. //
  29. // Input:
  30. // S #S list of whether selected
  31. // P #S list of bone parents
  32. // Output:
  33. // T #S list of whether selected
  34. static inline void propogate_to_descendants_if(
  35. const VectorXb & S,
  36. const Eigen::VectorXi & P,
  37. VectorXb & T);
  38. // Create a matrix of colors for the selection and their descendants.
  39. //
  40. // Inputs:
  41. // selection #S list of whether a bone is selected
  42. // selected_color color for selected bones
  43. // unselected_color color for unselected bones
  44. // Outputs:
  45. // C #P by 4 list of colors
  46. static inline void color_if(
  47. const VectorXb & S,
  48. const Eigen::Vector4f & selected_color,
  49. const Eigen::Vector4f & unselected_color,
  50. Eigen::MatrixXf & C);
  51. enum WidgetMode
  52. {
  53. WIDGET_MODE_ROTATE = 0,
  54. WIDGET_MODE_TRANSLATE = 1,
  55. NUM_WIDGET_MODES = 2,
  56. };
  57. private:
  58. // m_is_selecting whether currently selecting
  59. // m_selection #m_rotations list of whether a bone is selected
  60. // m_down_x x-coordinate of mouse location at down
  61. // m_down_y y-coordinate 〃
  62. // m_drag_x x-coordinate of mouse location at drag
  63. // m_drag_y y-coordinate 〃
  64. // m_widget rotation widget for selected bone
  65. // m_width width of containing window
  66. // m_height height 〃
  67. // m_rotations list of rotations for each bone
  68. // m_rotations_at_selection list of rotations for each bone at time of
  69. // selection
  70. // m_translations list of translations for each bone
  71. // m_fk_rotations_at_selection list of rotations for each bone at time of
  72. // selection
  73. // m_root_enabled Whether root is enabled
  74. bool m_is_selecting;
  75. VectorXb m_selection;
  76. int m_down_x,m_down_y,m_drag_x,m_drag_y;
  77. int m_width,m_height;
  78. igl::opengl2::RotateWidget m_widget;
  79. igl::opengl2::TranslateWidget m_trans_widget;
  80. Eigen::Quaterniond m_widget_rot_at_selection;
  81. //Eigen::Vector3d m_trans_widget_trans_at_selection;
  82. typedef std::vector<
  83. Eigen::Quaterniond,
  84. Eigen::aligned_allocator<Eigen::Quaterniond> > RotationList;
  85. typedef std::vector< Eigen::Vector3d > TranslationList;
  86. RotationList
  87. m_rotations,
  88. m_rotations_at_selection,
  89. m_fk_rotations_at_selection,
  90. m_parent_rotations_at_selection;
  91. TranslationList
  92. m_translations,
  93. m_translations_at_selection,
  94. m_fk_translations_at_selection;
  95. bool m_root_enabled;
  96. WidgetMode m_widget_mode;
  97. public:
  98. MouseController();
  99. // Returns const reference to m_selection
  100. inline const VectorXb & selection() const{return m_selection;};
  101. // 〃 m_is_selecting
  102. inline const bool & is_selecting() const{return m_is_selecting;}
  103. inline bool is_widget_down() const{return m_widget.is_down();}
  104. inline bool is_trans_widget_down() const{return m_trans_widget.is_down();}
  105. // 〃 m_rotations
  106. inline const RotationList & rotations() const{return m_rotations;}
  107. inline const TranslationList & translations() const{return m_translations;}
  108. // Returns non-const reference to m_root_enabled
  109. inline bool & root_enabled(){ return m_root_enabled;}
  110. inline void reshape(const int w, const int h);
  111. // Process down, drag, up mouse events
  112. //
  113. // Inputs:
  114. // x x-coordinate of mouse click with respect to container
  115. // y y-coordinate 〃
  116. // Returns true if accepted (action taken).
  117. inline bool down(const int x, const int y);
  118. inline bool drag(const int x, const int y);
  119. inline bool up(const int x, const int y);
  120. // Draw selection box and widget
  121. inline void draw() const;
  122. // Set `m_selection` based on the last drag selection and initialize
  123. // widget.
  124. //
  125. // Inputs:
  126. // C #C by dim list of joint positions at rest
  127. // BE #BE by 2 list of bone indices at rest
  128. // P #P list of bone parents
  129. inline void set_selection_from_last_drag(
  130. const Eigen::MatrixXd & C,
  131. const Eigen::MatrixXi & BE,
  132. const Eigen::VectorXi & P,
  133. const Eigen::VectorXi & RP);
  134. // Set from explicit selection
  135. inline void set_selection(
  136. const Eigen::VectorXi & S,
  137. const Eigen::MatrixXd & C,
  138. const Eigen::MatrixXi & BE,
  139. const Eigen::VectorXi & P,
  140. const Eigen::VectorXi & RP);
  141. // Set size of skeleton
  142. //
  143. // Inputs:
  144. // n number of bones
  145. inline void set_size(const int n);
  146. // Resets m_rotation elements to identity
  147. inline void reset();
  148. inline void reset_selected();
  149. inline void reset_rotations();
  150. inline void reset_selected_rotations();
  151. inline void reset_translations();
  152. inline void reset_selected_translations();
  153. inline bool set_rotations(const RotationList & vQ);
  154. inline bool set_translations(const TranslationList & vT);
  155. // Sets all entries in m_selection to false
  156. inline void clear_selection();
  157. // Returns true iff some element in m_selection is true
  158. inline bool any_selection() const;
  159. inline void set_widget_mode(const WidgetMode & mode);
  160. public:
  161. EIGEN_MAKE_ALIGNED_OPERATOR_NEW
  162. };
  163. }
  164. }
  165. // Implementation
  166. #include "../line_segment_in_rectangle.h"
  167. #include "draw_rectangular_marquee.h"
  168. #include "project.h"
  169. #include "../forward_kinematics.h"
  170. #include "../matlab_format.h"
  171. #include "../any_of.h"
  172. #include <iostream>
  173. #include <algorithm>
  174. #include <functional>
  175. inline void igl::opengl2::MouseController::propogate_to_descendants_if(
  176. const VectorXb & S,
  177. const Eigen::VectorXi & P,
  178. VectorXb & T)
  179. {
  180. using namespace std;
  181. const int n = S.rows();
  182. assert(P.rows() == n);
  183. // dynamic programming
  184. T = S;
  185. vector<bool> seen(n,false);
  186. // Recursively look up chain and see if ancestor is selected
  187. const function<bool(int)> look_up = [&](int e) -> bool
  188. {
  189. if(e==-1)
  190. {
  191. return false;
  192. }
  193. if(!seen[e])
  194. {
  195. seen[e] = true;
  196. T(e) |= look_up(P(e));
  197. }
  198. return T(e);
  199. };
  200. for(int e = 0;e<n;e++)
  201. {
  202. if(!seen[e])
  203. {
  204. T(e) = look_up(e);
  205. }
  206. }
  207. }
  208. inline void igl::opengl2::MouseController::color_if(
  209. const VectorXb & S,
  210. const Eigen::Vector4f & selected_color,
  211. const Eigen::Vector4f & unselected_color,
  212. Eigen::MatrixXf & C)
  213. {
  214. C.resize(S.rows(),4);
  215. for(int e=0;e<S.rows();e++)
  216. {
  217. C.row(e) = S(e)?selected_color:unselected_color;
  218. }
  219. }
  220. inline igl::opengl2::MouseController::MouseController():
  221. m_is_selecting(false),
  222. m_selection(),
  223. m_down_x(-1),m_down_y(-1),m_drag_x(-1),m_drag_y(-1),
  224. m_width(-1),m_height(-1),
  225. m_widget(),
  226. m_widget_rot_at_selection(),
  227. //m_trans_widget_trans_at_selection(),
  228. m_trans_widget(),
  229. m_rotations(),
  230. m_translations(),
  231. m_rotations_at_selection(),
  232. m_root_enabled(true),
  233. m_widget_mode(WIDGET_MODE_ROTATE)
  234. {
  235. }
  236. inline void igl::opengl2::MouseController::reshape(const int w, const int h)
  237. {
  238. m_width = w;
  239. m_height = h;
  240. }
  241. inline bool igl::opengl2::MouseController::down(const int x, const int y)
  242. {
  243. using namespace std;
  244. m_down_x = m_drag_x =x;
  245. m_down_y = m_drag_y =y;
  246. const bool widget_down = any_selection() &&
  247. (
  248. (m_widget_mode == WIDGET_MODE_ROTATE && m_widget.down(x,m_height-y)) ||
  249. (m_widget_mode == WIDGET_MODE_TRANSLATE &&
  250. m_trans_widget.down(x,m_height-y))
  251. );
  252. if(!widget_down)
  253. {
  254. m_is_selecting = true;
  255. }
  256. return m_is_selecting || widget_down;
  257. }
  258. inline bool igl::opengl2::MouseController::drag(const int x, const int y)
  259. {
  260. using namespace std;
  261. using namespace Eigen;
  262. m_drag_x = x;
  263. m_drag_y = y;
  264. if(m_is_selecting)
  265. {
  266. return m_is_selecting;
  267. }else
  268. {
  269. switch(m_widget_mode)
  270. {
  271. default: // fall through
  272. case WIDGET_MODE_ROTATE:
  273. {
  274. if(!m_widget.drag(x,m_height-y))
  275. {
  276. return false;
  277. }
  278. assert(any_selection());
  279. assert(m_selection.size() == (int)m_rotations.size());
  280. assert(m_selection.size() == (int)m_translations.size());
  281. for(int e = 0;e<m_selection.size();e++)
  282. {
  283. if(m_selection(e))
  284. {
  285. // Let:
  286. // w.θr = w.θ ⋅ w.θ₀*
  287. // w.θr takes (absolute) frame of w.θ₀ to w.θ:
  288. // w.θ = w.θr ⋅ w.θ₀
  289. // Define:
  290. // w.θ₀ = θfk ⋅ θx,
  291. // the absolute rotation of the x axis to the deformed bone at
  292. // selection. Likewise,
  293. // w.θ = θfk' ⋅ θx,
  294. // the current absolute rotation of the x axis to the deformed bone.
  295. // Define recursively:
  296. // θfk = θfk(p) ⋅ Θr,
  297. // then because we're only changeing this relative rotation
  298. // θfk' = θfk(p) ⋅ Θr ⋅ θr* ⋅ θr'
  299. // θfk' = θfk ⋅ θr* ⋅ θr'
  300. // w.θ ⋅ θx* = θfk ⋅ θr* ⋅ θr'
  301. // θr ⋅ θfk* ⋅ w.θ ⋅ θx* = θr'
  302. // θr ⋅ θfk* ⋅ w.θr ⋅ w.θ₀ ⋅ θx* = θr'
  303. // θr ⋅ θfk* ⋅ w.θr ⋅ θfk ⋅θx ⋅ θx* = θr'
  304. // θr ⋅ θfk* ⋅ w.θr ⋅ θfk = θr'
  305. // which I guess is the right multiply change after being changed to
  306. // the bases of θfk, the rotation of the bone relative to its rest
  307. // frame.
  308. //
  309. const Quaterniond & frame = m_fk_rotations_at_selection[e];
  310. m_rotations[e] =
  311. m_rotations_at_selection[e] *
  312. frame.conjugate() *
  313. (m_widget.rot*m_widget_rot_at_selection.conjugate()) *
  314. frame;
  315. }
  316. }
  317. }
  318. case WIDGET_MODE_TRANSLATE:
  319. {
  320. if(!m_trans_widget.drag(x,m_height-y))
  321. {
  322. return false;
  323. }
  324. assert(any_selection());
  325. assert(m_selection.size() == (int)m_rotations.size());
  326. assert(m_selection.size() == (int)m_translations.size());
  327. for(int e = 0;e<m_selection.size();e++)
  328. {
  329. if(m_selection(e))
  330. {
  331. m_translations[e] =
  332. m_translations_at_selection[e] +
  333. m_parent_rotations_at_selection[e].conjugate()*
  334. m_trans_widget.m_trans;
  335. }
  336. }
  337. }
  338. }
  339. return true;
  340. }
  341. }
  342. inline bool igl::opengl2::MouseController::up(const int x, const int y)
  343. {
  344. m_is_selecting = false;
  345. m_widget.up(x,m_height-y);
  346. m_trans_widget.up(x,m_height-y);
  347. return false;
  348. }
  349. inline void igl::opengl2::MouseController::draw() const
  350. {
  351. if(any_selection())
  352. {
  353. switch(m_widget_mode)
  354. {
  355. default:
  356. case WIDGET_MODE_ROTATE:
  357. m_widget.draw();
  358. break;
  359. case WIDGET_MODE_TRANSLATE:
  360. m_trans_widget.draw();
  361. break;
  362. }
  363. }
  364. if(m_is_selecting)
  365. {
  366. // Remember settings
  367. GLboolean dt;
  368. glGetBooleanv(GL_DEPTH_TEST,&dt);
  369. int old_vp[4];
  370. glGetIntegerv(GL_VIEWPORT,old_vp);
  371. // True screen space
  372. glViewport(0,0,m_width,m_height);
  373. glMatrixMode(GL_PROJECTION);
  374. glPushMatrix();
  375. glLoadIdentity();
  376. gluOrtho2D(0,m_width,0,m_height);
  377. glMatrixMode(GL_MODELVIEW);
  378. glPushMatrix();
  379. glLoadIdentity();
  380. glDisable(GL_DEPTH_TEST);
  381. draw_rectangular_marquee(
  382. m_down_x,
  383. m_height-m_down_y,
  384. m_drag_x,
  385. m_height-m_drag_y);
  386. // Restore settings
  387. glMatrixMode(GL_PROJECTION);
  388. glPopMatrix();
  389. glMatrixMode(GL_MODELVIEW);
  390. glPopMatrix();
  391. glViewport(old_vp[0],old_vp[1],old_vp[2],old_vp[3]);
  392. dt?glEnable(GL_DEPTH_TEST):glDisable(GL_DEPTH_TEST);
  393. }
  394. }
  395. inline void igl::opengl2::MouseController::set_selection_from_last_drag(
  396. const Eigen::MatrixXd & C,
  397. const Eigen::MatrixXi & BE,
  398. const Eigen::VectorXi & P,
  399. const Eigen::VectorXi & RP)
  400. {
  401. using namespace Eigen;
  402. using namespace std;
  403. m_rotations_at_selection = m_rotations;
  404. m_translations_at_selection = m_translations;
  405. assert(BE.rows() == P.rows());
  406. m_selection = VectorXb::Zero(BE.rows());
  407. // m_rotation[e] is the relative rotation stored at bone e (as seen by the
  408. // joint traveling with its parent)
  409. // vQ[e] is the absolute rotation of a bone at rest to its current position:
  410. // vQ[e] = vQ[p(e)] * m_rotation[e]
  411. vector<Quaterniond,aligned_allocator<Quaterniond> > vQ;
  412. vector<Vector3d> vT;
  413. forward_kinematics(C,BE,P,m_rotations,m_translations,vQ,vT);
  414. // Loop over deformed bones
  415. for(int e = 0;e<BE.rows();e++)
  416. {
  417. Affine3d a = Affine3d::Identity();
  418. a.translate(vT[e]);
  419. a.rotate(vQ[e]);
  420. Vector3d s = a * (Vector3d)C.row(BE(e,0));
  421. Vector3d d = a * (Vector3d)C.row(BE(e,1));
  422. Vector3d projs = project(s);
  423. Vector3d projd = project(d);
  424. m_selection(e) = line_segment_in_rectangle(
  425. projs.head(2),projd.head(2),
  426. Vector2d(m_down_x,m_height-m_down_y),
  427. Vector2d(m_drag_x,m_height-m_drag_y));
  428. }
  429. return set_selection(m_selection,C,BE,P,RP);
  430. }
  431. inline void igl::opengl2::MouseController::set_selection(
  432. const Eigen::VectorXi & S,
  433. const Eigen::MatrixXd & C,
  434. const Eigen::MatrixXi & BE,
  435. const Eigen::VectorXi & P,
  436. const Eigen::VectorXi & RP)
  437. {
  438. using namespace Eigen;
  439. using namespace std;
  440. vector<Quaterniond,aligned_allocator<Quaterniond> > & vQ =
  441. m_fk_rotations_at_selection;
  442. vector<Vector3d> & vT = m_fk_translations_at_selection;
  443. forward_kinematics(C,BE,P,m_rotations,m_translations,vQ,vT);
  444. m_parent_rotations_at_selection.resize(
  445. m_rotations.size(),Quaterniond::Identity());
  446. for(size_t r = 0;r<vQ.size();r++)
  447. {
  448. if(P(r)>=0)
  449. {
  450. m_parent_rotations_at_selection[r] = vQ[P(r)];
  451. }
  452. }
  453. if(&m_selection != &S)
  454. {
  455. m_selection = S;
  456. }
  457. assert(m_selection.rows() == BE.rows());
  458. assert(BE.rows() == P.rows());
  459. assert(BE.rows() == RP.rows());
  460. // Zero-out S up a path of ones from e
  461. auto propagate = [&](const int e, const VectorXb & S, VectorXb & N)
  462. {
  463. if(S(e))
  464. {
  465. int f = e;
  466. while(true)
  467. {
  468. int p = P(f);
  469. if(p==-1||!S(p))
  470. {
  471. break;
  472. }
  473. N(f) = false;
  474. f = p;
  475. }
  476. }
  477. };
  478. VectorXb prev_selection = m_selection;
  479. // Combine upward, group rigid parts, repeat
  480. while(true)
  481. {
  482. // Spread selection accross rigid pieces
  483. VectorXb SRP(VectorXb::Zero(RP.maxCoeff()+1));
  484. for(int e = 0;e<BE.rows();e++)
  485. {
  486. SRP(RP(e)) |= m_selection(e);
  487. }
  488. for(int e = 0;e<BE.rows();e++)
  489. {
  490. m_selection(e) = SRP(RP(e));
  491. }
  492. // Clear selections below m_selection ancestors
  493. VectorXb new_selection = m_selection;
  494. for(int e = 0;e<P.rows();e++)
  495. {
  496. propagate(e,m_selection,new_selection);
  497. }
  498. m_selection = new_selection;
  499. if(m_selection==prev_selection)
  500. {
  501. break;
  502. }
  503. prev_selection = m_selection;
  504. }
  505. // Now selection should contain just bone roots of m_selection subtrees
  506. if(any_of(m_selection))
  507. {
  508. // Taking average
  509. Vector3d avg_pos(0,0,0);
  510. //m_trans_widget_trans_at_selection.setConstant(0);
  511. m_widget_rot_at_selection.coeffs().setConstant(0);
  512. m_widget.rot.coeffs().array().setConstant(0);
  513. Quaterniond cur_rot(0,0,0,0);
  514. int num_selection = 0;
  515. // Compute average widget for selection
  516. for(int e = 0;e<BE.rows();e++)
  517. {
  518. if(m_selection(e))
  519. {
  520. Vector3d s = C.row(BE(e,0));
  521. Vector3d d = C.row(BE(e,1));
  522. auto b = (d-s).transpose().eval();
  523. {
  524. Affine3d a = Affine3d::Identity();
  525. a.translate(vT[e]);
  526. a.rotate(vQ[e]);
  527. avg_pos += a*s;
  528. }
  529. // Rotation of x axis to this bone
  530. Quaterniond rot_at_bind;
  531. rot_at_bind.setFromTwoVectors(Vector3d(1,0,0),b);
  532. const Quaterniond abs_rot = vQ[e] * rot_at_bind;
  533. m_widget_rot_at_selection.coeffs() += abs_rot.coeffs();
  534. //m_trans_widget_trans_at_selection += vT[e];
  535. num_selection++;
  536. }
  537. }
  538. // Take average
  539. avg_pos.array() /= (double)num_selection;
  540. //m_trans_widget_trans_at_selection.array() /= (double)num_selection;
  541. m_widget_rot_at_selection.coeffs().array() /= (double)num_selection;
  542. m_widget_rot_at_selection.normalize();
  543. m_widget.rot = m_widget_rot_at_selection;
  544. m_widget.pos = avg_pos;
  545. m_trans_widget.m_pos = avg_pos;
  546. //m_trans_widget.m_trans = m_trans_widget_trans_at_selection;
  547. m_trans_widget.m_trans.setConstant(0);
  548. }
  549. m_widget.m_is_enabled = true;
  550. m_trans_widget.m_is_enabled = true;
  551. for(int s = 0;s<m_selection.rows();s++)
  552. {
  553. // a root is selected then disable.
  554. if(!m_root_enabled && m_selection(s) && P(s) == -1)
  555. {
  556. m_widget.m_is_enabled = false;
  557. m_trans_widget.m_is_enabled = false;
  558. break;
  559. }
  560. }
  561. }
  562. inline void igl::opengl2::MouseController::set_size(const int n)
  563. {
  564. using namespace Eigen;
  565. clear_selection();
  566. m_rotations.clear();
  567. m_rotations.resize(n,Quaterniond::Identity());
  568. m_translations.clear();
  569. m_translations.resize(n,Vector3d(0,0,0));
  570. m_selection = VectorXb::Zero(n);
  571. }
  572. inline void igl::opengl2::MouseController::reset()
  573. {
  574. reset_rotations();
  575. reset_translations();
  576. }
  577. inline void igl::opengl2::MouseController::reset_selected()
  578. {
  579. reset_selected_rotations();
  580. reset_selected_translations();
  581. }
  582. inline void igl::opengl2::MouseController::reset_rotations()
  583. {
  584. using namespace Eigen;
  585. using namespace std;
  586. fill(m_rotations.begin(),m_rotations.end(),Quaterniond::Identity());
  587. // cop out. just clear selection
  588. clear_selection();
  589. }
  590. inline void igl::opengl2::MouseController::reset_selected_rotations()
  591. {
  592. using namespace Eigen;
  593. for(int e = 0;e<m_selection.size();e++)
  594. {
  595. if(m_selection(e))
  596. {
  597. m_rotations[e] = Quaterniond::Identity();
  598. }
  599. }
  600. }
  601. inline void igl::opengl2::MouseController::reset_translations()
  602. {
  603. using namespace Eigen;
  604. using namespace std;
  605. fill(m_translations.begin(),m_translations.end(),Vector3d(0,0,0));
  606. // cop out. just clear selection
  607. clear_selection();
  608. }
  609. inline void igl::opengl2::MouseController::reset_selected_translations()
  610. {
  611. using namespace Eigen;
  612. for(int e = 0;e<m_selection.size();e++)
  613. {
  614. if(m_selection(e))
  615. {
  616. m_translations[e] = Vector3d(0,0,0);
  617. }
  618. }
  619. }
  620. inline bool igl::opengl2::MouseController::set_rotations(const RotationList & vQ)
  621. {
  622. if(vQ.size() != m_rotations.size())
  623. {
  624. return false;
  625. }
  626. assert(!any_selection());
  627. m_rotations = vQ;
  628. return true;
  629. }
  630. inline bool igl::opengl2::MouseController::set_translations(const TranslationList & vT)
  631. {
  632. if(vT.size() != m_translations.size())
  633. {
  634. return false;
  635. }
  636. assert(!any_selection());
  637. m_translations = vT;
  638. return true;
  639. }
  640. inline void igl::opengl2::MouseController::clear_selection()
  641. {
  642. m_selection.setConstant(false);
  643. }
  644. inline bool igl::opengl2::MouseController::any_selection() const
  645. {
  646. return igl::any_of(m_selection);
  647. }
  648. inline void igl::opengl2::MouseController::set_widget_mode(const WidgetMode & mode)
  649. {
  650. switch(m_widget_mode)
  651. {
  652. default:
  653. case WIDGET_MODE_TRANSLATE:
  654. m_widget.pos = m_trans_widget.m_pos+m_trans_widget.m_trans;
  655. break;
  656. case WIDGET_MODE_ROTATE:
  657. break;
  658. }
  659. m_widget_mode = mode;
  660. }
  661. #endif