Developer Documentation
PrincipalAxisNode.cc
1 /*===========================================================================*\
2  * *
3  * OpenFlipper *
4  * Copyright (c) 2001-2016, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39  * *
40 \*===========================================================================*/
41 
42 
43 //=============================================================================
44 //
45 // CLASS PrincipalAxisNode - IMPLEMENTATION
46 //
47 //=============================================================================
48 
49 
50 //== INCLUDES =================================================================
51 
52 #include <ACG/GL/acg_glew.hh>
53 #include "PrincipalAxisNode.hh"
54 #include <ACG/GL/IRenderer.hh>
55 #include <ACG/GL/gl.hh>
56 
57 #include <ACG/QtWidgets/QtPrincipalAxisDialog.hh>
58 
59 #include <limits>
60 
61 //== NAMESPACES ===============================================================
62 
63 namespace ACG {
64 namespace SceneGraph {
65 
66 
67 //== IMPLEMENTATION ==========================================================
68 
69 
70 // void
71 // MyGlutPrimitiveNode::
72 // initialize()
73 // {
74 // std::cerr << "initialize MyGlutPrimitiveNode static members!\n";
75 // update_display_lists();
76 // initialized_ = true;
77 // }
78 
79 
80 
83  const std::string& _name)
84  : BaseNode(_parent, _name),
85  auto_range_(false),
86  max_abs_value_(1.0),
87  min_abs_value_(0.0),
88  max_draw_radius_(1.0),
89  min_draw_radius_(0.0),
90  default_radius_(true),
91  slices_(10),
92  cylinder_radius_scale_(1.0),
93  min_spacing_(0.0),
94  draw_style_(DS_3D),
95  color_mode_(CM_Axis),
96  cone_height_factor_(2.5f),
97  cylinder_(8, 2, 1.0f, true, false),
98  cone_(8, 2, 2.0f / cone_height_factor_, 0.0f, true, false),
99  invalidateInstanceData_(true),
100  supportsInstancing_(-1),
101  vbo_(0),
102  updateVBO_(true) {
103 
104  static const Vec4f default_cols[3] = {
105  Vec4f(0.91f, 0.11f, 0.09f, 1.0f),
106  Vec4f(0.0f, .43f, 1.0f , 1.0f),
107  Vec4f(0.0f, 0.70f, 0.0f , 1.0f)
108  };
109  for (int i = 0; i < 3; ++i) {
110  for (int j = 0; j < 4; ++j) {
111  axes_colors[i][j] = default_cols[i][j];
112  }
113  }
114 
115  for(unsigned int i=0; i<3; ++i)
116  show_tensor_component_[i] = 2;
117 }
118 
119 
120 //----------------------------------------------------------------------------
121 
122 
124 {
125 }
126 
127 //----------------------------------------------------------------------------
128 
129 void PrincipalAxisNode::set_color_mode(ColorMode _cm)
130 {
131  if (color_mode_ != _cm)
132  {
133  color_mode_ = _cm;
134  invalidateInstanceData_ = true;
135  }
136 }
137 
138 //----------------------------------------------------------------------------
139 
140 void
141 PrincipalAxisNode::
142 show_options_dialog()
143 {
145  pd->show();
146 }
147 
148 
149 //----------------------------------------------------------------------------
150 
151 
152 void
153 PrincipalAxisNode::
154 show_tensor_component(unsigned int _i, unsigned char _show)
155 {
156  if (_i > 2) return;
157 
158  // instance data has to be invalidated if components change visibility.
159  // toggling between single and double direction is possible without update
160  if ((show_tensor_component_[_i] && !_show) || (!show_tensor_component_[_i] && _show))
161  invalidateInstanceData_ = true;
162 
163  show_tensor_component_[_i] = _show;
164 
165  auto_update_range();
166  updateVBO();
167 }
168 
169 
170 //----------------------------------------------------------------------------
171 
172 
173 void
174 PrincipalAxisNode::
175 resize(size_t _n)
176 {
177  size_t old_n = pc_.size();
178 
179  pc_.resize(_n);
180  draw_pc_.resize(_n);
181 
182  // initialize new draw_pc_ values
183  for(size_t i=old_n; i<_n; ++i)
184  draw_pc_[i] = false;
185 
186  auto_update_range();
187 }
188 
189 
190 //----------------------------------------------------------------------------
191 
192 
193 void
194 PrincipalAxisNode::
195 enable ( size_t _i)
196 {
197  if(_i < draw_pc_.size())
198  {
199  if (!draw_pc_[_i])
200  {
201  draw_pc_[_i] = true;
202  invalidateInstanceData_ = true;
203  }
204  }
205  else std::cerr << "principal component index out of range\n";
206 }
207 
208 
209 //----------------------------------------------------------------------------
210 
211 
212 void
213 PrincipalAxisNode::
214 disable ( size_t _i)
215 {
216  if(_i < draw_pc_.size())
217  {
218  if (!draw_pc_[_i])
219  {
220  draw_pc_[_i] = false;
221  invalidateInstanceData_ = true;
222  }
223  }
224  else std::cerr << "principal component index out of range\n";
225 }
226 
227 
228 //----------------------------------------------------------------------------
229 
230 
231 void
232 PrincipalAxisNode::
233 disable_all()
234 {
235  for(size_t i=0; i<pc_.size(); ++i)
236  disable(i);
237 }
238 
239 
240 //----------------------------------------------------------------------------
241 
242 
243 void
244 PrincipalAxisNode::
245 set(size_t _i, const PrincipalComponent& _pc)
246 {
247  if( _i < pc_.size())
248  {
249  // set values
250  pc_[_i] = _pc;
251 
252  // update range
253  if( auto_range_)
254  auto_update_range();
255 
256  invalidateInstanceData_ = true;
257 
258 // // update bounding_box
259 // update_bounding_box();
260  }
261  else std::cerr << "PrincipalComponent index error!\n";
262 
263  updateVBO();
264 }
265 
266 
267 //----------------------------------------------------------------------------
268 
269 
270 void
271 PrincipalAxisNode::
272 get(size_t _i, PrincipalComponent& _pc)
273 {
274  if( _i < pc_.size())
275  {
276  // set values
277  _pc = pc_[_i];
278  }
279  else std::cerr << "PrincipalComponent index error!\n";
280 }
281 
282 //----------------------------------------------------------------------------
283 
284 
285 void
286 PrincipalAxisNode::
287 add(const PrincipalComponent& _pc, bool _enable)
288 {
289  pc_.push_back(_pc);
290  draw_pc_.push_back(_enable);
291 
292  // update range
293  if( auto_range_)
294  auto_update_range();
295 
296  invalidateInstanceData_ = true;
297 
298  updateVBO();
299 }
300 
301 
302 //----------------------------------------------------------------------------
303 
304 
305 void
306 PrincipalAxisNode::
307 set_auto_range( bool _b)
308 {
309  auto_range_ = _b;
310 }
311 
312 
313 //----------------------------------------------------------------------------
314 
315 
316 void
317 PrincipalAxisNode::
318 set_min_abs_value( double _v)
319 {
320  if( auto_range_)
321  std::cerr << "Warning: Auto update min/max abs_values is enabled! Setting has no effect.\n";
322 
323  min_abs_value_ = _v;
324  invalidateInstanceData_ = true;
325  updateVBO();
326 }
327 
328 
329 //----------------------------------------------------------------------------
330 
331 
332 void
333 PrincipalAxisNode::
334 set_max_abs_value( double _v)
335 {
336  if( auto_range_)
337  std::cerr << "Warning: Auto update min/max abs_values is enabled! Setting has no effect.\n";
338 
339  max_abs_value_ = _v;
340  invalidateInstanceData_ = true;
341  updateVBO();
342 }
343 
344 //----------------------------------------------------------------------------
345 
346 
347 void
348 PrincipalAxisNode::
349 set_min_draw_radius( double _v)
350 {
351  min_draw_radius_ = _v;
352  default_radius_ = false;
353  invalidateInstanceData_ = true;
354  updateVBO();
355 }
356 
357 
358 //----------------------------------------------------------------------------
359 
360 
361 void
362 PrincipalAxisNode::
363 set_max_draw_radius( double _v)
364 {
365  max_draw_radius_ = _v;
366  default_radius_ = false;
367  invalidateInstanceData_ = true;
368  updateVBO();
369 }
370 
371 
372 //----------------------------------------------------------------------------
373 
374 
375 void
376 PrincipalAxisNode::
377 auto_update_range()
378 {
379  min_abs_value_ = std::numeric_limits<double>::max();
380  max_abs_value_ = 0.0;
381 
382  for(size_t i=0; i<pc_.size(); ++i)
383  if(draw_pc_[i])
384  for(size_t j=0; j<3; ++j)
385  if(show_tensor_component_[j])
386  {
387  max_abs_value_ = std::max( max_abs_value_, pc_[i].a[j].norm() );
388  min_abs_value_ = std::min( min_abs_value_, pc_[i].a[j].norm() );
389  }
390 
391  update_bounding_box();
392 }
393 
394 
395 //----------------------------------------------------------------------------
396 
397 
398 void
399 PrincipalAxisNode::
400 update_bounding_box()
401 {
402  bool uninitialized = true;
403 
404  bbMin_ = Vec3d( FLT_MAX, FLT_MAX, FLT_MAX);
405  bbMax_ = Vec3d(-FLT_MAX,-FLT_MAX,-FLT_MAX);
406 
407  for(size_t i=0; i<pc_.size(); ++i)
408  {
409  Vec3d lmin = (pc_[i].p) - Vec3d(1,1,1)*max_draw_radius_;
410  Vec3d lmax = (pc_[i].p) + Vec3d(1,1,1)*max_draw_radius_;
411 
412  if(draw_pc_[i])
413  {
414  if(uninitialized)
415  {
416  bbMin_ = lmin;
417  bbMax_ = lmax;
418  uninitialized = false;
419  }
420  else
421  {
422  bbMin_.minimize(lmin);
423  bbMax_.maximize(lmax);
424  }
425  }
426 
427  }
428 }
429 
430 
431 //----------------------------------------------------------------------------
432 
433 
434 void
436 boundingBox(Vec3d& _bbMin, Vec3d& _bbMax)
437 {
438  if( bbMin_ != Vec3d(FLT_MAX, FLT_MAX, FLT_MAX) )
439  {
440  _bbMin.minimize( bbMin_);
441  _bbMax.maximize( bbMax_);
442  }
443 }
444 
445 
446 //----------------------------------------------------------------------------
447 
448 
452 {
453  return ( DrawModes::POINTS |
458 }
459 
460 
461 //----------------------------------------------------------------------------
462 
463 
464 void
466 draw(GLState& /*_state*/, const DrawModes::DrawMode& _drawMode)
467 {
468  if( draw_style_ == DS_3D)
469  ACG::GLState::enable(GL_LIGHTING);
470  else
471  ACG::GLState::disable(GL_LIGHTING);
472 
473  if (_drawMode & DrawModes::SOLID_SMOOTH_SHADED)
474  ACG::GLState::shadeModel(GL_SMOOTH);
475  else
476  ACG::GLState::shadeModel(GL_FLAT);
477 
478  glMatrixMode(GL_MODELVIEW);
479 
480  for(unsigned int i=0; i<pc_.size(); ++i)
481  if( draw_pc_[i] )
482  draw_principal_component( pc_[i]);
483 }
484 
485 
486 //----------------------------------------------------------------------------
487 
488 
489 void
490 PrincipalAxisNode::
491 draw_principal_component(const PrincipalComponent& _pc)
492 {
493  glPushMatrix();
494  glTranslated( _pc.p[0], _pc.p[1], _pc.p[2]);
495 
496  // for(unsigned int i=0; i<1; ++i)
497  for(size_t i=0; i<3; ++i)
498  {
499  if( ! show_tensor_component_[i]) continue;
500 
501  Vec3d a;
502  a = _pc.a[i];
503 
504  // compute arrow length in world coords
505  double length;
506  length = std::max( min_abs_value_, a.norm());
507  length = std::min( max_abs_value_, length );
508 
509  if( a.norm() > 1e-8 )
510  a.normalize();
511 
512  // Bug fixed: Visualizing all unit vectors yieled scaled_length = nan
513  double scaled_length(min_draw_radius_);
514  if( fabs(max_abs_value_-min_abs_value_) > 1e-6)
515  scaled_length += (length-min_abs_value_)/(max_abs_value_-min_abs_value_)*(max_draw_radius_-min_draw_radius_);
516 
517  a *= scaled_length;
518 
519 // std::cerr << "**************************\n";
520 // std::cerr << "min_abs_value: " << min_abs_value_ << std::endl;
521 // std::cerr << "max_abs_value: " << max_abs_value_ << std::endl;
522 // std::cerr << "min_draw_radius: " << min_draw_radius_ << std::endl;
523 // std::cerr << "max_draw_radius: " << max_draw_radius_ << std::endl;
524 // std::cerr << "scaled_length: " << scaled_length << std::endl;
525 // std::cerr << "length : " << length << std::endl;
526 // std::cerr << "sign : " << _pc.sign[i] << std::endl;
527 // std::cerr << "**************************\n";
528 
529 
530  if( color_mode_ == CM_Sign)
531  {
532  // choose color due to eigenvalue sign
533  if(_pc.sign[i] == true)
534  {
535  glColor3f(1.f, 0.f, 0.f);
536 
537  GLfloat mat_amb_diff[] = {1.0, 0.0, 0.0, 1.0};
538  glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_amb_diff);
539  glColor4fv( mat_amb_diff);
540  }
541  else
542  {
543  glColor3f(0.f, 0.f, 1.f);
544 
545  GLfloat mat_amb_diff[] = {0.0, 0.0, 1.0, 1.0};
546  glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_amb_diff);
547  glColor4fv( mat_amb_diff);
548  }
549  }
550  else
551  // also default
552  {
553  // choose color due to eigenvalue
554  glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, axes_colors[i]);
555  glColor4fv( axes_colors[i]);
556  }
557 
558  // draw both axis
559  if( draw_style_ == DS_3D)
560  {
561  double radius = max_draw_radius_ * 0.015 * cylinder_radius_scale_;
562 
563  draw_arrow( a , radius);
564 
565  if( show_tensor_component_[i] == 2)
566  draw_arrow( a*(-1), radius);
567  }
568  else
569  {
570  double width = cylinder_radius_scale_;
571 
572  draw_line( a , width);
573  if( show_tensor_component_[i] == 2)
574  draw_line( a*(-1), width);
575  }
576  }
577 
578  glPopMatrix();
579 }
580 
581 
582 //----------------------------------------------------------------------------
583 
584 
585 void
586 PrincipalAxisNode::
587 draw_arrow( const Vec3d& _axis, double _r)
588 {
589  double size = _axis.norm();
590 
591  if( size > 1e-10)
592  {
593  glPushMatrix();
594 
595 
596  Vec3d direction = _axis;
597  Vec3d z_axis(0,0,1);
598  Vec3d rot_normal;
599  double rot_angle;
600 
601  direction.normalize();
602  rot_angle = acos((z_axis | direction))*180/M_PI;
603  rot_normal = ((z_axis % direction).normalize());
604 
605 
606  if(fabs(rot_angle) > 0.0001 && fabs(180-rot_angle) > 0.0001)
607  glRotatef(rot_angle,rot_normal[0], rot_normal[1], rot_normal[2]);
608  else
609  glRotatef(rot_angle,1,0,0);
610 
611  glPushMatrix();
612  glScalef(_r, _r, 0.85f*size);
613  cylinder_.draw_primitive();
614  glPopMatrix();
615 
616  glPushMatrix();
617  glTranslatef(0, 0, 0.85f*size);
618  glScalef(cone_height_factor_ * _r, cone_height_factor_ * _r, cone_height_factor_ * _r);
619  cone_.draw_primitive();
620  glPopMatrix();
621 
622 
623 
624 
625  glPopMatrix();
626  }
627 }
628 
629 
630 //----------------------------------------------------------------------------
631 
632 
633 void
634 PrincipalAxisNode::
635 draw_line( const Vec3d& _axis, double _w)
636 {
637  glLineWidth(_w);
638 
639  glBegin(GL_LINES);
640  glVertex3f(0.0f,0.0f,0.0f);
641  glVertex3f(_axis[0], _axis[1], _axis[2]);
642  glEnd();
643 }
644 
645 //----------------------------------------------------------------------------
646 
647 
648 void
650 pick(GLState& /*_state*/, PickTarget _target)
651 {
652  switch (_target)
653  {
654  case PICK_ANYTHING:
655  case PICK_FACE:
656  {
657 // ACG::GLState::disable(GL_LIGHTING);
658 // ACG::GLState::shadeModel(GL_FLAT);
659 // glPushMatrix();
660 // glTranslatef(position_[0], position_[1], position_[2]);
661 // draw_obj();
662 // glPopMatrix();
663  break;
664  }
665 
666  default:
667  break;
668  }
669 }
670 
671 
672 //----------------------------------------------------------------------------
673 
674 
675 void PrincipalAxisNode::set_axes_colors(const Vec4f colors[3]) {
676  for (size_t i = 0; i < 3; ++i) {
677  for (size_t j = 0; j < 4; ++j) {
678  axes_colors[i][j] = colors[i][j];
679  }
680  }
681 
682  invalidateInstanceData_ = true;
683  updateVBO();
684 }
685 
686 void PrincipalAxisNode::get_axes_colors(Vec4f out_colors[3]) const {
687  for (size_t i = 0; i < 3; ++i) {
688  for (size_t j = 0; j < 4; ++j) {
689  out_colors[i][j] = axes_colors[i][j];
690  }
691  }
692 }
693 
694 
695 //----------------------------------------------------------------------------
696 
697 
698 // Following code is taken from http://stackoverflow.com/questions/4372224/fast-method-for-computing-3x3-symmetric-matrix-spectral-decomposition:
699 // Slightly modified version of Stan Melax's code for 3x3 matrix diagonalization (Thanks Stan!)
700 // source: http://www.melax.com/diag.html?attredirects=0
701 void PrincipalAxisNode::diagonalize(const double (&A)[3][3], double (&Q)[3][3], double (&D)[3][3])
702 {
703  // A must be a symmetric matrix.
704  // returns Q and D such that
705  // Diagonal matrix D = QT * A * Q; and A = Q*D*QT
706  const int maxsteps=24; // certainly wont need that many.
707  double o[3], m[3];
708  double q [4] = {0.0,0.0,0.0,1.0};
709  double jr[4];
710  double AQ[3][3];
711  for(int i=0;i < maxsteps;++i)
712  {
713  int k0, k1, k2;
714  double sqw, sqx, sqy, sqz;
715  double tmp1, tmp2, mq;
716  double thet, sgn, t, c;
717 
718  // quat to matrix
719  sqx = q[0]*q[0];
720  sqy = q[1]*q[1];
721  sqz = q[2]*q[2];
722  sqw = q[3]*q[3];
723  Q[0][0] = ( sqx - sqy - sqz + sqw);
724  Q[1][1] = (-sqx + sqy - sqz + sqw);
725  Q[2][2] = (-sqx - sqy + sqz + sqw);
726  tmp1 = q[0]*q[1];
727  tmp2 = q[2]*q[3];
728  Q[1][0] = 2.0 * (tmp1 + tmp2);
729  Q[0][1] = 2.0 * (tmp1 - tmp2);
730  tmp1 = q[0]*q[2];
731  tmp2 = q[1]*q[3];
732  Q[2][0] = 2.0 * (tmp1 - tmp2);
733  Q[0][2] = 2.0 * (tmp1 + tmp2);
734  tmp1 = q[1]*q[2];
735  tmp2 = q[0]*q[3];
736  Q[2][1] = 2.0 * (tmp1 + tmp2);
737  Q[1][2] = 2.0 * (tmp1 - tmp2);
738 
739  // AQ = A * Q
740  AQ[0][0] = Q[0][0]*A[0][0]+Q[1][0]*A[0][1]+Q[2][0]*A[0][2];
741  AQ[0][1] = Q[0][1]*A[0][0]+Q[1][1]*A[0][1]+Q[2][1]*A[0][2];
742  AQ[0][2] = Q[0][2]*A[0][0]+Q[1][2]*A[0][1]+Q[2][2]*A[0][2];
743  AQ[1][0] = Q[0][0]*A[0][1]+Q[1][0]*A[1][1]+Q[2][0]*A[1][2];
744  AQ[1][1] = Q[0][1]*A[0][1]+Q[1][1]*A[1][1]+Q[2][1]*A[1][2];
745  AQ[1][2] = Q[0][2]*A[0][1]+Q[1][2]*A[1][1]+Q[2][2]*A[1][2];
746  AQ[2][0] = Q[0][0]*A[0][2]+Q[1][0]*A[1][2]+Q[2][0]*A[2][2];
747  AQ[2][1] = Q[0][1]*A[0][2]+Q[1][1]*A[1][2]+Q[2][1]*A[2][2];
748  AQ[2][2] = Q[0][2]*A[0][2]+Q[1][2]*A[1][2]+Q[2][2]*A[2][2];
749  // D = Qt * AQ
750  D[0][0] = AQ[0][0]*Q[0][0]+AQ[1][0]*Q[1][0]+AQ[2][0]*Q[2][0];
751  D[0][1] = AQ[0][0]*Q[0][1]+AQ[1][0]*Q[1][1]+AQ[2][0]*Q[2][1];
752  D[0][2] = AQ[0][0]*Q[0][2]+AQ[1][0]*Q[1][2]+AQ[2][0]*Q[2][2];
753  D[1][0] = AQ[0][1]*Q[0][0]+AQ[1][1]*Q[1][0]+AQ[2][1]*Q[2][0];
754  D[1][1] = AQ[0][1]*Q[0][1]+AQ[1][1]*Q[1][1]+AQ[2][1]*Q[2][1];
755  D[1][2] = AQ[0][1]*Q[0][2]+AQ[1][1]*Q[1][2]+AQ[2][1]*Q[2][2];
756  D[2][0] = AQ[0][2]*Q[0][0]+AQ[1][2]*Q[1][0]+AQ[2][2]*Q[2][0];
757  D[2][1] = AQ[0][2]*Q[0][1]+AQ[1][2]*Q[1][1]+AQ[2][2]*Q[2][1];
758  D[2][2] = AQ[0][2]*Q[0][2]+AQ[1][2]*Q[1][2]+AQ[2][2]*Q[2][2];
759  o[0] = D[1][2];
760  o[1] = D[0][2];
761  o[2] = D[0][1];
762  m[0] = fabs(o[0]);
763  m[1] = fabs(o[1]);
764  m[2] = fabs(o[2]);
765 
766  k0 = (m[0] > m[1] && m[0] > m[2])?0: (m[1] > m[2])? 1 : 2; // index of largest element of offdiag
767  k1 = (k0+1)%3;
768  k2 = (k0+2)%3;
769  if (o[k0]==0.0)
770  {
771  break; // diagonal already
772  }
773  thet = (D[k2][k2]-D[k1][k1])/(2.0*o[k0]);
774  sgn = (thet > 0.0)?1.0:-1.0;
775  thet *= sgn; // make it positive
776  t = sgn /(thet +((thet < 1.E6)?sqrt(thet*thet+1.0):thet)) ; // sign(T)/(|T|+sqrt(T^2+1))
777  c = 1.0/sqrt(t*t+1.0); // c= 1/(t^2+1) , t=s/c
778  if(c==1.0)
779  {
780  break; // no room for improvement - reached machine precision.
781  }
782  jr[0 ] = jr[1] = jr[2] = jr[3] = 0.0;
783  jr[k0] = sgn*sqrt((1.0-c)/2.0); // using 1/2 angle identity sin(a/2) = sqrt((1-cos(a))/2)
784  jr[k0] *= -1.0; // since our quat-to-matrix convention was for v*M instead of M*v
785  jr[3 ] = sqrt(1.0f - jr[k0] * jr[k0]);
786  if(jr[3]==1.0)
787  {
788  break; // reached limits of floating point precision
789  }
790  q[0] = (q[3]*jr[0] + q[0]*jr[3] + q[1]*jr[2] - q[2]*jr[1]);
791  q[1] = (q[3]*jr[1] - q[0]*jr[2] + q[1]*jr[3] + q[2]*jr[0]);
792  q[2] = (q[3]*jr[2] + q[0]*jr[1] - q[1]*jr[0] + q[2]*jr[3]);
793  q[3] = (q[3]*jr[3] - q[0]*jr[0] - q[1]*jr[1] - q[2]*jr[2]);
794  mq = sqrt(q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]);
795  q[0] /= mq;
796  q[1] /= mq;
797  q[2] /= mq;
798  q[3] /= mq;
799  }
800 }
801 
803  const DrawModes::DrawMode& _drawMode,
804  const ACG::SceneGraph::Material* _mat) {
805 
806  if (pc_.empty())
807  return;
808 
809 
810  if (draw_style_ == DS_2D && !lineDecl_.getNumElements())
811  {
812  // line vertex layout
813  // float3 pos
814  // float x_offset (for quad extrusion with line width in vertex shader)
815  float lineVBOData[] =
816  {
817  0.0f, 0.0f, 1.0f, -1.0f,
818  0.0f, 0.0f, 0.0f, 1.0f,
819  0.0f, 0.0f, 1.0f, 1.0f,
820  0.0f, 0.0f, 0.0f, -1.0f,
821  };
822 
823  lineBuffer_.upload(sizeof(lineVBOData), lineVBOData, GL_STATIC_DRAW);
824 
825  lineDecl_.addElement(GL_FLOAT, 3, VERTEX_USAGE_POSITION);
826  lineDecl_.addElement(GL_FLOAT, 1, VERTEX_USAGE_SHADER_INPUT, size_t(0), "pa_xOffset");
827  }
828 
829  // check support for instancing if not done yet
830  if (supportsInstancing_ < 0)
831  supportsInstancing_ = checkExtensionSupported("GL_ARB_instanced_arrays") ? 1 : 0;
832  if (supportsInstancing_)
833  {
834  RenderObject obj;
835 
836  obj.initFromState(&_state);
837  obj.depthTest = true;
838 
839  if (!_drawMode.getLayer(0)->lighting())
840  obj.shaderDesc.shadeMode = SG_SHADE_UNLIT;
841  else
842  {
843  if (_drawMode.getLayer(0)->flatShaded())
844  obj.shaderDesc.shadeMode = SG_SHADE_FLAT;
845  else
846  obj.shaderDesc.shadeMode = SG_SHADE_GOURAUD;
847  }
848 
849 
850  // count number of instances
851  int numInstances = 0;
852 
853  int visibleTensors = 0;
854  for (size_t k = 0; k < 3; ++k)
855  {
856  if (show_tensor_component_[k])
857  ++visibleTensors;
858  }
859 
860  for (size_t i = 0; i < pc_.size(); ++i)
861  {
862  if (draw_pc_[i])
863  numInstances += visibleTensors;
864  }
865 
866  if (!numInstances)
867  return;
868 
869  if (invalidateInstanceData_)
870  {
871  /*
872  data stored per instance:
873  float4x3 world matrix
874  byte4_unorm color
875  */
876 
877  const int numDwordsPerInstance = 4 * 3 + 2;
878  std::vector<float> instanceData(numInstances * numDwordsPerInstance);
879  int instanceOffset = 0;
880 
881  for (unsigned int i = 0; i < pc_.size(); ++i)
882  {
883  if (draw_pc_[i])
884  {
885  const PrincipalComponent& pc = pc_[i];
886  for (unsigned int k = 0; k < 3; ++k)
887  {
888  if (!show_tensor_component_[k]) continue;
889 
890  // compute axis transform
891  double size = 1.0;
892  GLMatrixd axisWorld = axisTransform(pc, k, &size);
893 
894  // store 4x3 part of axis transform
895 
896  for (int r = 0; r < 3; ++r)
897  for (int c = 0; c < 4; ++c)
898  instanceData[instanceOffset * numDwordsPerInstance + r * 4 + c] = axisWorld(r, c);
899 
900  // store size
901  instanceData[instanceOffset * numDwordsPerInstance + 4 * 3] = size;
902 
903  // store color
904  Vec4uc instanceColor(0, 0, 0, 255);
905 
906  if (color_mode_ == CM_Sign)
907  {
908  // choose color based on eigenvalue sign
909  if (pc.sign[k] == true)
910  instanceColor = Vec4uc(255, 0, 0, 255);
911  else
912  instanceColor = Vec4uc(0, 0, 255, 255);
913  }
914  else // choose color based on eigenvalue
915  {
916  for (int m = 0; m < 4; ++m)
917  instanceColor[m] = static_cast<unsigned char>(std::max(std::min(int(axes_colors[k][m] * 255.0f), int(255)), int(0)));
918  }
919 
920  memcpy(&instanceData[instanceOffset * numDwordsPerInstance + 4 * 3 + 1], instanceColor.data(), 4);
921 
922  ++instanceOffset;
923  }
924  }
925  }
926 
927  lineInstanceBuffer_.upload(instanceData.size() * 4, &instanceData[0], GL_STATIC_DRAW);
928 
929  lineDeclInstanced_.clear();
930  // vbo data layout
931  lineDeclInstanced_.addElement(GL_FLOAT, 3, VERTEX_USAGE_POSITION);
932  lineDeclInstanced_.addElement(GL_FLOAT, 1, VERTEX_USAGE_SHADER_INPUT, size_t(0), "pa_xOffset");
933  // instance data layout
934  lineDeclInstanced_.addElement(GL_FLOAT, 4, VERTEX_USAGE_SHADER_INPUT, size_t(0), "pa_worldTransform0", 1, lineInstanceBuffer_.id());
935  lineDeclInstanced_.addElement(GL_FLOAT, 4, VERTEX_USAGE_SHADER_INPUT, size_t(0), "pa_worldTransform1", 1, lineInstanceBuffer_.id());
936  lineDeclInstanced_.addElement(GL_FLOAT, 4, VERTEX_USAGE_SHADER_INPUT, size_t(0), "pa_worldTransform2", 1, lineInstanceBuffer_.id());
937  lineDeclInstanced_.addElement(GL_FLOAT, 1, VERTEX_USAGE_SHADER_INPUT, size_t(0), "pa_size", 1, lineInstanceBuffer_.id());
938  lineDeclInstanced_.addElement(GL_UNSIGNED_BYTE, 4, VERTEX_USAGE_COLOR, size_t(0), 0, 1, lineInstanceBuffer_.id());
939 
940  cylinderDeclInstanced_.clear();
941  cylinderDeclInstanced_ = *cylinder_.getVertexDecl();
942  cylinderDeclInstanced_.addElement(GL_FLOAT, 4, VERTEX_USAGE_SHADER_INPUT, size_t(0), "pa_worldTransform0", 1, lineInstanceBuffer_.id());
943  cylinderDeclInstanced_.addElement(GL_FLOAT, 4, VERTEX_USAGE_SHADER_INPUT, size_t(0), "pa_worldTransform1", 1, lineInstanceBuffer_.id());
944  cylinderDeclInstanced_.addElement(GL_FLOAT, 4, VERTEX_USAGE_SHADER_INPUT, size_t(0), "pa_worldTransform2", 1, lineInstanceBuffer_.id());
945  cylinderDeclInstanced_.addElement(GL_FLOAT, 1, VERTEX_USAGE_SHADER_INPUT, size_t(0), "pa_size", 1, lineInstanceBuffer_.id());
946  cylinderDeclInstanced_.addElement(GL_UNSIGNED_BYTE, 4, VERTEX_USAGE_COLOR, size_t(0), 0, 1, lineInstanceBuffer_.id());
947 
948  invalidateInstanceData_ = false;
949  }
950 
951  // scale and offset based on visualization mode (single or both directions)
952  Vec3f pa_scale(0.0f, 0.0f, 0.0f), pa_offset(0.0f, 0.0f, 0.0f);
953 
954  int curTensor = 0;
955  for (int k = 0; k < 3; ++k)
956  {
957  if (show_tensor_component_[k] == 2)
958  {
959  pa_scale[curTensor] = 2.0f;
960  pa_offset[curTensor] = -1.0f;
961  }
962  else
963  {
964  pa_scale[curTensor] = 1.0f;
965  pa_offset[curTensor] = 0.0f;
966  }
967  if (show_tensor_component_[k])
968  ++curTensor;
969  }
970 
971  if (draw_style_ == DS_2D)
972  {
973  // line object
974  obj.debugName = "PrincipalAxisNode.line";
975  obj.name = name() + std::string(".line");
976 
977  obj.shaderDesc.shadeMode = SG_SHADE_UNLIT;
978  obj.shaderDesc.vertexColors = true;
979  obj.shaderDesc.vertexTemplateFile = "PrincipalAxisNode/lines_extruded_instanced.glsl";
980 
981  obj.setUniform("pa_lineWidth", float(cylinder_radius_scale_));
982  obj.setUniform("pa_screenSize", Vec2f(_state.viewport_width(), _state.viewport_height()));
983  obj.setUniform("pa_scale", pa_scale);
984  obj.setUniform("pa_offset", pa_offset);
985  obj.setUniform("pa_visible_tensors", visibleTensors);
986 
987  obj.vertexBuffer = lineBuffer_.id();
988  obj.vertexDecl = &lineDeclInstanced_;
989 
990  obj.glDrawInstancedArrays(GL_TRIANGLE_STRIP, 0, 4, numInstances);
991 
992  _renderer->addRenderObject(&obj);
993  }
994  else
995  {
996  float radius = max_draw_radius_ * 0.015 * cylinder_radius_scale_;
997 
998  obj.debugName = "PrincipalAxisNode.cylinder";
999  obj.name = name() + std::string(".cylinder");
1000 
1001  obj.shaderDesc.vertexColors = true;
1002  obj.shaderDesc.vertexTemplateFile = "PrincipalAxisNode/3d_instanced.glsl";
1003  obj.shaderDesc.colorMaterialMode = GL_AMBIENT_AND_DIFFUSE;
1004 
1005  obj.ambient = obj.diffuse = Vec3f(1.0f, 1.0f, 1.0f);
1006 
1007  obj.setUniform("pa_cone_radius", radius);
1008  obj.setUniform("pa_cone_offset", Vec3f(0.0f, 0.0f, 0.0f));
1009  obj.setUniform("pa_scale", pa_scale * 0.85f);
1010  obj.setUniform("pa_offset", pa_offset * 0.85f);
1011  obj.setUniform("pa_visible_tensors", visibleTensors);
1012 
1013  obj.vertexBuffer = cylinder_.getVBO();
1014  obj.vertexDecl = &cylinderDeclInstanced_;
1015 
1016  obj.glDrawInstancedArrays(GL_TRIANGLES, 0, cylinder_.getNumTriangles() * 3, numInstances);
1017 
1018  _renderer->addRenderObject(&obj);
1019 
1020  // arrowheads
1021  obj.debugName = "PrincipalAxisNode.cone";
1022 
1023  obj.shaderDesc.vertexTemplateFile = "PrincipalAxisNode/3d_cone_instanced.glsl";
1024 
1025  obj.setUniform("pa_cone_radius", cone_height_factor_ * radius);
1026  obj.setUniform("pa_cone_offset", Vec3f(0.0f, 0.0f, 0.0f));
1027  obj.setUniform("pa_cone_mirror", 1.0f);
1028 
1029  obj.vertexBuffer = cone_.getVBO();
1030 
1031  obj.glDrawInstancedArrays(GL_TRIANGLES, 0, cone_.getNumTriangles() * 3, numInstances);
1032 
1033  _renderer->addRenderObject(&obj);
1034 
1035  if (show_tensor_component_[0] == 2 ||
1036  show_tensor_component_[1] == 2 ||
1037  show_tensor_component_[2] == 2)
1038  {
1039  obj.debugName = "PrincipalAxisNode.cone_mirror";
1040  obj.setUniform("pa_cone_mirror", -1.0f);
1041 
1042  _renderer->addRenderObject(&obj);
1043  }
1044  }
1045  }
1046  else
1047  {
1048  // non-instanced
1049 
1050 // emitIndividualRenderobjects(_renderer, _state, _drawMode, _mat);
1051 
1052  RenderObject ro;
1053  ro.initFromState(&_state);
1054  ro.setMaterial(_mat);
1055 
1056  nodeName_ = std::string("PrincipalAxisNode: ") + name();
1057  ro.debugName = nodeName_;
1058 
1059  ro.depthTest = true;
1060  ro.depthWrite = true;
1061 
1062  ro.shaderDesc.shadeMode = SG_SHADE_UNLIT;
1063 
1064  // simulate line width via quad extrusion in geometry shader
1065  QString geomTemplate = ShaderProgGenerator::getShaderDir();
1066  geomTemplate += "Wireframe/geom_line2quad.tpl";
1067 
1068  ro.shaderDesc.geometryTemplateFile = geomTemplate;
1069 
1070  ro.setUniform("screenSize",
1071  Vec2f((float)_state.viewport_width(),
1072  (float)_state.viewport_height()));
1073  ro.setUniform("lineWidth", static_cast<float>(cylinder_radius_scale_));
1074 
1075  createVBO();
1076  ro.vertexBuffer = vbo_;
1077  // vertexDecl is defined in createVBO
1078  ro.vertexDecl = &vertexDecl_;
1079 
1080  int curOffset = 0;
1081  int vertexCount = static_cast<int>(pc_.size() * 2);
1082  for (int i = 0; i < 3; ++i)
1083  {
1084  if (show_tensor_component_[i])
1085  {
1086  // set axis color
1087  for (int k = 0; k < 3; ++k)
1088  ro.emissive[k] = axes_colors[i][k];
1089 
1090  ro.glDrawArrays(GL_LINES, curOffset, vertexCount);
1091  _renderer->addRenderObject(&ro);
1092 
1093  curOffset += vertexCount;
1094  }
1095  }
1096 
1097  }
1098 }
1099 
1100 //----------------------------------------------------------------------------
1101 
1103 {
1104  RenderObject obj;
1105 
1106  obj.initFromState(&_state);
1107  obj.depthTest = true;
1108 
1109  if (!_drawMode.getLayer(0)->lighting())
1110  obj.shaderDesc.shadeMode = SG_SHADE_UNLIT;
1111  else
1112  {
1113  if (_drawMode.getLayer(0)->flatShaded())
1114  obj.shaderDesc.shadeMode = SG_SHADE_FLAT;
1115  else
1116  obj.shaderDesc.shadeMode = SG_SHADE_GOURAUD;
1117  }
1118 
1119 
1120  for (size_t i = 0; i < pc_.size(); ++i)
1121  {
1122  if (draw_pc_[i])
1123  {
1124  const PrincipalComponent& pc = pc_[i];
1125 
1126  for (unsigned int k = 0; k < 3; ++k)
1127  {
1128  if (!show_tensor_component_[k]) continue;
1129 
1130  if (color_mode_ == CM_Sign)
1131  {
1132  // choose color due to eigenvalue sign
1133  if (pc.sign[k] == true)
1134  obj.ambient = obj.diffuse = Vec3f(1.0f, 0.0f, 0.0f);
1135  else
1136  obj.ambient = obj.diffuse = Vec3f(0.0f, 0.0f, 1.0f);
1137  }
1138  else // choose color due to eigenvalue
1139  obj.ambient = obj.diffuse = Vec3f(axes_colors[k][0], axes_colors[k][1], axes_colors[k][2]);
1140 
1141  double size = 1.0;
1142  GLMatrixd axisModelView = _state.modelview() * axisTransform(pc, k, &size);
1143 
1144  if (size > 1e-10)
1145  {
1146  // draw both axis
1147  if (draw_style_ == DS_3D)
1148  {
1149  double radius = max_draw_radius_ * 0.015 * cylinder_radius_scale_;
1150 
1151  // cylinder
1152  obj.name = name() + std::string(".cylinder");
1153 
1154  obj.modelview = axisModelView;
1155 
1156  if (show_tensor_component_[k] == 2)
1157  {
1158  obj.modelview.scale(radius, radius, 2.0 * 0.85 * size);
1159  obj.modelview.translate(0.0, 0.0, -0.5);
1160  }
1161  else
1162  obj.modelview.scale(radius, radius, 0.85 * size);
1163 
1164  obj.vertexDecl = cylinder_.getVertexDecl();
1165  obj.vertexBuffer = cylinder_.getVBO();
1166 
1167  obj.glDrawArrays(GL_TRIANGLES, 0, cylinder_.getNumTriangles() * 3);
1168 
1169  _renderer->addRenderObject(&obj);
1170 
1171  // arrowhead
1172  obj.name = name() + std::string(".cone");
1173 
1174  obj.modelview = axisModelView;
1175  obj.modelview.translate(0, 0, 0.85 * size);
1176  obj.modelview.scale(cone_height_factor_ * radius, cone_height_factor_ * radius, cone_height_factor_ * radius);
1177 
1178  obj.vertexDecl = cone_.getVertexDecl();
1179  obj.vertexBuffer = cone_.getVBO();
1180 
1181  obj.glDrawArrays(GL_TRIANGLES, 0, cone_.getNumTriangles() * 3);
1182 
1183  _renderer->addRenderObject(&obj);
1184 
1185  if (show_tensor_component_[k] == 2)
1186  {
1187  obj.modelview = axisModelView;
1188  obj.modelview.rotate(180, 1, 0, 0);
1189  obj.modelview.translate(0, 0, 0.85 * size);
1190 
1191  obj.modelview.scale(cone_height_factor_ * radius, cone_height_factor_ * radius, cone_height_factor_ * radius);
1192 
1193  _renderer->addRenderObject(&obj);
1194  }
1195  }
1196  else
1197  {
1198  // line object
1199  obj.name = name() + std::string(".line");
1200 
1201  obj.modelview = axisModelView;
1202  obj.shaderDesc.shadeMode = SG_SHADE_UNLIT;
1203  obj.emissive = obj.diffuse;
1204 
1205  if (show_tensor_component_[k] == 2)
1206  {
1207  obj.modelview.scale(1.0, 1.0, 2.0 * size);
1208  obj.modelview.translate(0.0, 0.0, -0.5);
1209  }
1210  else
1211  obj.modelview.scale(1.0, 1.0, size);
1212 
1213  obj.vertexBuffer = lineBuffer_.id();
1214  obj.vertexDecl = &lineDecl_;
1215 
1216  obj.glDrawArrays(GL_LINES, 0, 2);
1217 
1218  _renderer->addRenderObject(&obj);
1219  }
1220  }
1221  }
1222  }
1223  }
1224 }
1225 
1226 //----------------------------------------------------------------------------
1227 
1228 Vec3d
1230 axisScaled(const PrincipalComponent& _pc, int _axis) const
1231 {
1232  Vec3d a;
1233  a = _pc.a[_axis];
1234 
1235  // compute arrow length in world coords
1236  double length;
1237  length = std::max(min_abs_value_, a.norm());
1238  length = std::min(max_abs_value_, length);
1239 
1240  if (a.norm() > 1e-8)
1241  a.normalize();
1242 
1243  // Bug fixed: Visualizing all unit vectors yieled scaled_length = nan
1244  double scaled_length(min_draw_radius_);
1245 
1246  if (fabs(max_abs_value_ - min_abs_value_) > 1e-6)
1247  scaled_length += (length - min_abs_value_) / (max_abs_value_ - min_abs_value_)*(max_draw_radius_ - min_draw_radius_);
1248 
1249  a *= scaled_length;
1250  return a;
1251 }
1252 
1253 //----------------------------------------------------------------------------
1254 
1255 GLMatrixd
1257 axisTransform(const PrincipalComponent& _pc, int _axis, double* _outSize) const
1258 {
1259  assert(0 <= _axis && _axis < 3);
1260 
1262  axisTransform.identity();
1263  axisTransform.translate(_pc.p);
1264 
1265  Vec3d a = axisScaled(_pc, _axis);
1266  double size = a.norm();
1267 
1268  if (_outSize)
1269  *_outSize = size;
1270 
1271  // orientation
1272  if (size > 1e-10)
1273  {
1274  Vec3d direction = a;
1275  Vec3d z_axis(0, 0, 1);
1276  Vec3d rot_normal;
1277  double rot_angle;
1278  direction.normalize();
1279  rot_angle = acos((z_axis | direction)) * 180 / M_PI;
1280  rot_normal = ((z_axis % direction).normalize());
1281 
1282  if (fabs(rot_angle) > 0.0001 && fabs(180 - rot_angle) > 0.0001)
1283  axisTransform.rotate(rot_angle, rot_normal[0], rot_normal[1], rot_normal[2]);
1284  else
1285  axisTransform.rotate(rot_angle, 1, 0, 0);
1286  }
1287 
1288  return axisTransform;
1289 }
1290 
1291 //----------------------------------------------------------------------------
1292 
1293 
1294 
1296  if (!updateVBO_)
1297  return;
1298 
1299  // create vbo if it does not exist
1300  if (!vbo_)
1301  glGenBuffers(1, &vbo_);
1302 
1303  int tensorComponentCount = 0;
1304  for (int i = 0; i < 3; ++i) {
1305  tensorComponentCount += show_tensor_component_[i] ? 1 : 0;
1306  }
1307  vertexDecl_.clear();
1308  vertexDecl_.addElement(GL_FLOAT, 3, VERTEX_USAGE_POSITION);
1309 
1310  //3 coordinates per vertex, 2 vertices per principal component
1311  std::vector<float> vboData(3 * 2 * tensorComponentCount * pc_.size(), 0.f);
1312 
1313  float* vboPtr = &vboData[0];
1314 
1315  for (int tensor_component = 0; tensor_component < 3; ++tensor_component) {
1316  if (!show_tensor_component_[tensor_component]) continue;
1317 
1318  for (std::vector<PrincipalComponent>::const_iterator it = pc_.begin();
1319  it != pc_.end(); ++it) {
1320 
1321  Vec3d pc_dir = it->a[tensor_component];
1322 
1323  /*
1324  * Weird scale computation copied from draw().
1325  */
1326  const double pc_dir_norm = pc_dir.norm();
1327  double length;
1328  length = std::max( min_abs_value_, pc_dir_norm);
1329  length = std::min( max_abs_value_, length );
1330 
1331  if( pc_dir_norm > 1e-8 ) pc_dir.normalize();
1332 
1333  // Bug fixed: Visualizing all unit vectors yieled scaled_length = nan
1334  double scaled_length(min_draw_radius_);
1335  if (fabs(max_abs_value_-min_abs_value_) > 1e-6)
1336  scaled_length += (length-min_abs_value_)/(max_abs_value_-min_abs_value_)*(max_draw_radius_-min_draw_radius_);
1337 
1338  pc_dir *= scaled_length;
1339 
1340  const Vec3d pc_from = it->p -
1341  (show_tensor_component_[tensor_component] == 2
1342  ? pc_dir
1343  : Vec3d(0, 0, 0));
1344  const Vec3d pc_to = it->p + pc_dir;
1345 
1346  for (int i = 0; i < 3; ++i)
1347  *(vboPtr++) = pc_from[i];
1348  for (int i = 0; i < 3; ++i)
1349  *(vboPtr++) = pc_to[i];
1350  }
1351  }
1352  assert(vboPtr == &vboData[0] + vboData.size());
1353 
1354  glBindBuffer(GL_ARRAY_BUFFER_ARB, vbo_);
1355  glBufferData(GL_ARRAY_BUFFER_ARB, vboData.size() * sizeof(float),
1356  &vboData[0], GL_STATIC_DRAW_ARB);
1357 
1358  // Update done.
1359  updateVBO_ = false;
1360 }
1361 
1362 //=============================================================================
1363 } // namespace SceneGraph
1364 } // namespace ACG
1365 //=============================================================================
DrawMode SOLID_SMOOTH_SHADED
draw smooth shaded (Gouraud shaded) faces (requires halfedge normals)
Definition: DrawModes.cc:82
vector_type & maximize(const vector_type &_rhs)
maximize values: same as *this = max(*this, _rhs), but faster
Definition: Vector11T.hh:563
DrawMode WIREFRAME
draw wireframe
Definition: DrawModes.cc:78
Namespace providing different geometric functions concerning angles.
void boundingBox(Vec3d &_bbMin, Vec3d &_bbMax)
update bounding box
pick any of the prior targets (should be implemented for all nodes)
Definition: PickTarget.hh:84
VectorT< unsigned char, 4 > Vec4uc
Definition: VectorT.hh:128
auto norm() const -> decltype(std::sqrt(std::declval< VectorT< S, DIM >>().sqrnorm()))
compute euclidean norm
Definition: Vector11T.hh:409
VectorT< float, 3 > Vec3f
Definition: VectorT.hh:119
static void enable(GLenum _cap, bool _warnRemoved=true)
replaces glEnable, but supports locking
std::string name() const
Returns: name of node (needs not be unique)
DrawModes::DrawMode availableDrawModes() const
return available draw modes
defined by user via VertexElement::shaderInputName_
VectorT< float, 4 > Vec4f
Definition: VectorT.hh:138
void initFromState(GLState *_glState)
Initializes a RenderObject instance.
Definition: RenderObject.cc:61
int viewport_width() const
get viewport width
Definition: GLState.hh:822
GLMatrixd axisTransform(const PrincipalComponent &_pc, int _axis, double *_outSize=0) const
world transform of an axis (orientation and translation)
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM >>().norm())
Definition: Vector11T.hh:429
static void disable(GLenum _cap, bool _warnRemoved=true)
replaces glDisable, but supports locking
unsigned int getNumElements() const
Scalar * data()
access to Scalar array
Definition: Vector11T.hh:195
Interface class between scenegraph and renderer.
Definition: RenderObject.hh:98
void emitIndividualRenderobjects(IRenderer *_renderer, GLState &_state, const DrawModes::DrawMode &_drawMode, const ACG::SceneGraph::Material *_mat)
emit individual objects for each axis for each principal component (slow if tensor count high) ...
PrincipalAxisNode(BaseNode *_parent=0, const std::string &_name="<PrincipalAxis>")
Default constructor.
bool default_radius_
Indicates whether the min/max draw radius has been changed from its default setting.
bool flatShaded() const
Is flat shading used (Normals per face)?
Definition: DrawModes.hh:225
bool lighting() const
Is lighting enabled?
Definition: DrawModes.hh:216
VectorT< float, 2 > Vec2f
Definition: VectorT.hh:102
Vec3d axisScaled(const PrincipalComponent &_pc, int _axis) const
scaled axis
void pick(GLState &_state, PickTarget _target)
picking
DrawMode HIDDENLINE
draw hidden line (2 rendering passes needed)
Definition: DrawModes.cc:80
void addElement(const VertexElement *_pElement)
VectorT< double, 3 > Vec3d
Definition: VectorT.hh:121
void scale(Scalar _x, Scalar _y, Scalar _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with scaling matrix (x,y,z)
static void shadeModel(GLenum _mode)
replaces glShadeModel, supports locking
void getRenderObjects(IRenderer *_renderer, GLState &_state, const DrawModes::DrawMode &_drawMode, const ACG::SceneGraph::Material *_mat)
Overriding BaseNode::getRenderObjects.
GLuint vertexBuffer
VBO, IBO ids, ignored if VAO is provided.
int viewport_height() const
get viewport height
Definition: GLState.hh:824
void setUniform(const char *_name, GLint _value)
set values for int uniforms
virtual void addRenderObject(RenderObject *_renderObject)
Callback for the scenegraph nodes, which send new render objects via this function.
Definition: IRenderer.cc:104
void createVBO()
creates the vbo only if update was requested
static QString getShaderDir()
void draw(GLState &_state, const DrawModes::DrawMode &_drawMode)
drawing the primitive
ShaderGenDesc shaderDesc
Drawmode and other shader params.
PickTarget
What target to use for picking.
Definition: PickTarget.hh:73
vector_type & minimize(const vector_type &_rhs)
minimize values: same as *this = min(*this, _rhs), but faster
Definition: Vector11T.hh:535
void identity()
setup an identity matrix
const DrawModeProperties * getLayer(unsigned int _i) const
returns the property set at layer i
Definition: DrawModes.cc:535
DrawMode SOLID_FLAT_SHADED
draw flat shaded faces (requires face normals)
Definition: DrawModes.cc:81
picks faces (should be implemented for all nodes)
Definition: PickTarget.hh:78
bool checkExtensionSupported(const std::string &_extension)
Definition: gl.cc:107
void rotate(Scalar angle, Scalar x, Scalar y, Scalar z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
const VertexDeclaration * vertexDecl
Defines the vertex buffer layout, ignored if VAO is provided.
void translate(Scalar _x, Scalar _y, Scalar _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with translation matrix (x,y,z)
DrawMode POINTS
draw unlighted points using the default base color
Definition: DrawModes.cc:73