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  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.91, 0.11, 0.09, 1.0),
106  Vec4f(0.0, .43, 1.0, 1.0),
107  Vec4f(0.0, 0.70, 0.0, 1.0)
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(unsigned int _n)
176 {
177  unsigned int old_n = pc_.size();
178 
179  pc_.resize(_n);
180  draw_pc_.resize(_n);
181 
182  // initialize new draw_pc_ values
183  for(unsigned int 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 ( unsigned int _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 ( unsigned int _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(unsigned int i=0; i<pc_.size(); ++i)
236  disable(i);
237 }
238 
239 
240 //----------------------------------------------------------------------------
241 
242 
243 void
244 PrincipalAxisNode::
245 set(unsigned int _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(unsigned int _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(unsigned int i=0; i<pc_.size(); ++i)
383  if(draw_pc_[i])
384  for(unsigned 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(unsigned int 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(unsigned int 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 base_radius = _r;
590  double top_radius = _r;
591  double size = _axis.norm();
592 
593  if( size > 1e-10)
594  {
595  glPushMatrix();
596 
597  unsigned int slices(8);
598 
599  Vec3d direction = _axis;
600  Vec3d z_axis(0,0,1);
601  Vec3d rot_normal;
602  double rot_angle;
603 
604  direction.normalize();
605  rot_angle = acos((z_axis | direction))*180/M_PI;
606  rot_normal = ((z_axis % direction).normalize());
607 
608 
609  if(fabs(rot_angle) > 0.0001 && fabs(180-rot_angle) > 0.0001)
610  glRotatef(rot_angle,rot_normal[0], rot_normal[1], rot_normal[2]);
611  else
612  glRotatef(rot_angle,1,0,0);
613 
614  glPushMatrix();
615  glScalef(_r, _r, 0.85f*size);
616  cylinder_.draw_primitive();
617  glPopMatrix();
618 
619  glPushMatrix();
620  glTranslatef(0, 0, 0.85f*size);
621  glScalef(cone_height_factor_ * _r, cone_height_factor_ * _r, cone_height_factor_ * _r);
622  cone_.draw_primitive();
623  glPopMatrix();
624 
625 
626 
627 
628  glPopMatrix();
629  }
630 }
631 
632 
633 //----------------------------------------------------------------------------
634 
635 
636 void
637 PrincipalAxisNode::
638 draw_line( const Vec3d& _axis, double _w)
639 {
640  glLineWidth(_w);
641 
642  glBegin(GL_LINES);
643  glVertex3f(0,0,0);
644  glVertex3f(_axis[0], _axis[1], _axis[2]);
645  glEnd();
646 }
647 
648 //----------------------------------------------------------------------------
649 
650 
651 void
653 pick(GLState& /*_state*/, PickTarget _target)
654 {
655  switch (_target)
656  {
657  case PICK_ANYTHING:
658  case PICK_FACE:
659  {
660 // ACG::GLState::disable(GL_LIGHTING);
661 // ACG::GLState::shadeModel(GL_FLAT);
662 // glPushMatrix();
663 // glTranslatef(position_[0], position_[1], position_[2]);
664 // draw_obj();
665 // glPopMatrix();
666  break;
667  }
668 
669  default:
670  break;
671  }
672 }
673 
674 
675 //----------------------------------------------------------------------------
676 
677 
678 void PrincipalAxisNode::set_axes_colors(const Vec4f colors[3]) {
679  for (int i = 0; i < 3; ++i) {
680  for (int j = 0; j < 4; ++j) {
681  axes_colors[i][j] = colors[i][j];
682  }
683  }
684 
685  invalidateInstanceData_ = true;
686  updateVBO();
687 }
688 
689 void PrincipalAxisNode::get_axes_colors(Vec4f out_colors[3]) const {
690  for (int i = 0; i < 3; ++i) {
691  for (int j = 0; j < 4; ++j) {
692  out_colors[i][j] = axes_colors[i][j];
693  }
694  }
695 }
696 
697 
698 //----------------------------------------------------------------------------
699 
700 
701 // Following code is taken from http://stackoverflow.com/questions/4372224/fast-method-for-computing-3x3-symmetric-matrix-spectral-decomposition:
702 // Slightly modified version of Stan Melax's code for 3x3 matrix diagonalization (Thanks Stan!)
703 // source: http://www.melax.com/diag.html?attredirects=0
704 void PrincipalAxisNode::diagonalize(const double (&A)[3][3], double (&Q)[3][3], double (&D)[3][3])
705 {
706  // A must be a symmetric matrix.
707  // returns Q and D such that
708  // Diagonal matrix D = QT * A * Q; and A = Q*D*QT
709  const int maxsteps=24; // certainly wont need that many.
710  double o[3], m[3];
711  double q [4] = {0.0,0.0,0.0,1.0};
712  double jr[4];
713  double AQ[3][3];
714  for(int i=0;i < maxsteps;++i)
715  {
716  int k0, k1, k2;
717  double sqw, sqx, sqy, sqz;
718  double tmp1, tmp2, mq;
719  double thet, sgn, t, c;
720 
721  // quat to matrix
722  sqx = q[0]*q[0];
723  sqy = q[1]*q[1];
724  sqz = q[2]*q[2];
725  sqw = q[3]*q[3];
726  Q[0][0] = ( sqx - sqy - sqz + sqw);
727  Q[1][1] = (-sqx + sqy - sqz + sqw);
728  Q[2][2] = (-sqx - sqy + sqz + sqw);
729  tmp1 = q[0]*q[1];
730  tmp2 = q[2]*q[3];
731  Q[1][0] = 2.0 * (tmp1 + tmp2);
732  Q[0][1] = 2.0 * (tmp1 - tmp2);
733  tmp1 = q[0]*q[2];
734  tmp2 = q[1]*q[3];
735  Q[2][0] = 2.0 * (tmp1 - tmp2);
736  Q[0][2] = 2.0 * (tmp1 + tmp2);
737  tmp1 = q[1]*q[2];
738  tmp2 = q[0]*q[3];
739  Q[2][1] = 2.0 * (tmp1 + tmp2);
740  Q[1][2] = 2.0 * (tmp1 - tmp2);
741 
742  // AQ = A * Q
743  AQ[0][0] = Q[0][0]*A[0][0]+Q[1][0]*A[0][1]+Q[2][0]*A[0][2];
744  AQ[0][1] = Q[0][1]*A[0][0]+Q[1][1]*A[0][1]+Q[2][1]*A[0][2];
745  AQ[0][2] = Q[0][2]*A[0][0]+Q[1][2]*A[0][1]+Q[2][2]*A[0][2];
746  AQ[1][0] = Q[0][0]*A[0][1]+Q[1][0]*A[1][1]+Q[2][0]*A[1][2];
747  AQ[1][1] = Q[0][1]*A[0][1]+Q[1][1]*A[1][1]+Q[2][1]*A[1][2];
748  AQ[1][2] = Q[0][2]*A[0][1]+Q[1][2]*A[1][1]+Q[2][2]*A[1][2];
749  AQ[2][0] = Q[0][0]*A[0][2]+Q[1][0]*A[1][2]+Q[2][0]*A[2][2];
750  AQ[2][1] = Q[0][1]*A[0][2]+Q[1][1]*A[1][2]+Q[2][1]*A[2][2];
751  AQ[2][2] = Q[0][2]*A[0][2]+Q[1][2]*A[1][2]+Q[2][2]*A[2][2];
752  // D = Qt * AQ
753  D[0][0] = AQ[0][0]*Q[0][0]+AQ[1][0]*Q[1][0]+AQ[2][0]*Q[2][0];
754  D[0][1] = AQ[0][0]*Q[0][1]+AQ[1][0]*Q[1][1]+AQ[2][0]*Q[2][1];
755  D[0][2] = AQ[0][0]*Q[0][2]+AQ[1][0]*Q[1][2]+AQ[2][0]*Q[2][2];
756  D[1][0] = AQ[0][1]*Q[0][0]+AQ[1][1]*Q[1][0]+AQ[2][1]*Q[2][0];
757  D[1][1] = AQ[0][1]*Q[0][1]+AQ[1][1]*Q[1][1]+AQ[2][1]*Q[2][1];
758  D[1][2] = AQ[0][1]*Q[0][2]+AQ[1][1]*Q[1][2]+AQ[2][1]*Q[2][2];
759  D[2][0] = AQ[0][2]*Q[0][0]+AQ[1][2]*Q[1][0]+AQ[2][2]*Q[2][0];
760  D[2][1] = AQ[0][2]*Q[0][1]+AQ[1][2]*Q[1][1]+AQ[2][2]*Q[2][1];
761  D[2][2] = AQ[0][2]*Q[0][2]+AQ[1][2]*Q[1][2]+AQ[2][2]*Q[2][2];
762  o[0] = D[1][2];
763  o[1] = D[0][2];
764  o[2] = D[0][1];
765  m[0] = fabs(o[0]);
766  m[1] = fabs(o[1]);
767  m[2] = fabs(o[2]);
768 
769  k0 = (m[0] > m[1] && m[0] > m[2])?0: (m[1] > m[2])? 1 : 2; // index of largest element of offdiag
770  k1 = (k0+1)%3;
771  k2 = (k0+2)%3;
772  if (o[k0]==0.0)
773  {
774  break; // diagonal already
775  }
776  thet = (D[k2][k2]-D[k1][k1])/(2.0*o[k0]);
777  sgn = (thet > 0.0)?1.0:-1.0;
778  thet *= sgn; // make it positive
779  t = sgn /(thet +((thet < 1.E6)?sqrt(thet*thet+1.0):thet)) ; // sign(T)/(|T|+sqrt(T^2+1))
780  c = 1.0/sqrt(t*t+1.0); // c= 1/(t^2+1) , t=s/c
781  if(c==1.0)
782  {
783  break; // no room for improvement - reached machine precision.
784  }
785  jr[0 ] = jr[1] = jr[2] = jr[3] = 0.0;
786  jr[k0] = sgn*sqrt((1.0-c)/2.0); // using 1/2 angle identity sin(a/2) = sqrt((1-cos(a))/2)
787  jr[k0] *= -1.0; // since our quat-to-matrix convention was for v*M instead of M*v
788  jr[3 ] = sqrt(1.0f - jr[k0] * jr[k0]);
789  if(jr[3]==1.0)
790  {
791  break; // reached limits of floating point precision
792  }
793  q[0] = (q[3]*jr[0] + q[0]*jr[3] + q[1]*jr[2] - q[2]*jr[1]);
794  q[1] = (q[3]*jr[1] - q[0]*jr[2] + q[1]*jr[3] + q[2]*jr[0]);
795  q[2] = (q[3]*jr[2] + q[0]*jr[1] - q[1]*jr[0] + q[2]*jr[3]);
796  q[3] = (q[3]*jr[3] - q[0]*jr[0] - q[1]*jr[1] - q[2]*jr[2]);
797  mq = sqrt(q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]);
798  q[0] /= mq;
799  q[1] /= mq;
800  q[2] /= mq;
801  q[3] /= mq;
802  }
803 }
804 
806  const DrawModes::DrawMode& _drawMode,
807  const ACG::SceneGraph::Material* _mat) {
808 
809  if (pc_.empty())
810  return;
811 
812 
813  if (draw_style_ == DS_2D && !lineDecl_.getNumElements())
814  {
815  // line vertex layout
816  // float3 pos
817  // float x_offset (for quad extrusion with line width in vertex shader)
818  float lineVBOData[] =
819  {
820  0.0f, 0.0f, 1.0f, -1.0f,
821  0.0f, 0.0f, 0.0f, 1.0f,
822  0.0f, 0.0f, 1.0f, 1.0f,
823  0.0f, 0.0f, 0.0f, -1.0f,
824  };
825 
826  lineBuffer_.upload(sizeof(lineVBOData), lineVBOData, GL_STATIC_DRAW);
827 
828  lineDecl_.addElement(GL_FLOAT, 3, VERTEX_USAGE_POSITION);
829  lineDecl_.addElement(GL_FLOAT, 1, VERTEX_USAGE_SHADER_INPUT, size_t(0), "pa_xOffset");
830  }
831 
832  // check support for instancing if not done yet
833  if (supportsInstancing_ < 0)
834  supportsInstancing_ = checkExtensionSupported("GL_ARB_instanced_arrays") ? 1 : 0;
835  if (supportsInstancing_)
836  {
837  RenderObject obj;
838 
839  obj.initFromState(&_state);
840  obj.depthTest = true;
841 
842  if (!_drawMode.getLayer(0)->lighting())
843  obj.shaderDesc.shadeMode = SG_SHADE_UNLIT;
844  else
845  {
846  if (_drawMode.getLayer(0)->flatShaded())
847  obj.shaderDesc.shadeMode = SG_SHADE_FLAT;
848  else
849  obj.shaderDesc.shadeMode = SG_SHADE_GOURAUD;
850  }
851 
852 
853  // count number of instances
854  int numInstances = 0;
855 
856  int visibleTensors = 0;
857  for (unsigned int k = 0; k < 3; ++k)
858  {
859  if (show_tensor_component_[k])
860  ++visibleTensors;
861  }
862 
863  for (size_t i = 0; i < pc_.size(); ++i)
864  {
865  if (draw_pc_[i])
866  numInstances += visibleTensors;
867  }
868 
869  if (!numInstances)
870  return;
871 
872  if (invalidateInstanceData_)
873  {
874  /*
875  data stored per instance:
876  float4x3 world matrix
877  byte4_unorm color
878  */
879 
880  const int numDwordsPerInstance = 4 * 3 + 2;
881  std::vector<float> instanceData(numInstances * numDwordsPerInstance);
882  int instanceOffset = 0;
883 
884  for (unsigned int i = 0; i < pc_.size(); ++i)
885  {
886  if (draw_pc_[i])
887  {
888  const PrincipalComponent& pc = pc_[i];
889  for (unsigned int k = 0; k < 3; ++k)
890  {
891  if (!show_tensor_component_[k]) continue;
892 
893  // compute axis transform
894  double size = 1.0;
895  GLMatrixd axisWorld = axisTransform(pc, k, &size);
896 
897  // store 4x3 part of axis transform
898 
899  for (int r = 0; r < 3; ++r)
900  for (int c = 0; c < 4; ++c)
901  instanceData[instanceOffset * numDwordsPerInstance + r * 4 + c] = axisWorld(r, c);
902 
903  // store size
904  instanceData[instanceOffset * numDwordsPerInstance + 4 * 3] = size;
905 
906  // store color
907  Vec4uc instanceColor(0, 0, 0, 255);
908 
909  if (color_mode_ == CM_Sign)
910  {
911  // choose color based on eigenvalue sign
912  if (pc.sign[k] == true)
913  instanceColor = Vec4uc(255, 0, 0, 255);
914  else
915  instanceColor = Vec4uc(0, 0, 255, 255);
916  }
917  else // choose color based on eigenvalue
918  {
919  for (int m = 0; m < 4; ++m)
920  instanceColor[m] = static_cast<unsigned char>(std::max(std::min(int(axes_colors[k][m] * 255.0f), int(255)), int(0)));
921  }
922 
923  memcpy(&instanceData[instanceOffset * numDwordsPerInstance + 4 * 3 + 1], instanceColor.data(), 4);
924 
925  ++instanceOffset;
926  }
927  }
928  }
929 
930  lineInstanceBuffer_.upload(instanceData.size() * 4, &instanceData[0], GL_STATIC_DRAW);
931 
932  lineDeclInstanced_.clear();
933  // vbo data layout
934  lineDeclInstanced_.addElement(GL_FLOAT, 3, VERTEX_USAGE_POSITION);
935  lineDeclInstanced_.addElement(GL_FLOAT, 1, VERTEX_USAGE_SHADER_INPUT, size_t(0), "pa_xOffset");
936  // instance data layout
937  lineDeclInstanced_.addElement(GL_FLOAT, 4, VERTEX_USAGE_SHADER_INPUT, size_t(0), "pa_worldTransform0", 1, lineInstanceBuffer_.id());
938  lineDeclInstanced_.addElement(GL_FLOAT, 4, VERTEX_USAGE_SHADER_INPUT, size_t(0), "pa_worldTransform1", 1, lineInstanceBuffer_.id());
939  lineDeclInstanced_.addElement(GL_FLOAT, 4, VERTEX_USAGE_SHADER_INPUT, size_t(0), "pa_worldTransform2", 1, lineInstanceBuffer_.id());
940  lineDeclInstanced_.addElement(GL_FLOAT, 1, VERTEX_USAGE_SHADER_INPUT, size_t(0), "pa_size", 1, lineInstanceBuffer_.id());
941  lineDeclInstanced_.addElement(GL_UNSIGNED_BYTE, 4, VERTEX_USAGE_COLOR, size_t(0), 0, 1, lineInstanceBuffer_.id());
942 
943  cylinderDeclInstanced_.clear();
944  cylinderDeclInstanced_ = *cylinder_.getVertexDecl();
945  cylinderDeclInstanced_.addElement(GL_FLOAT, 4, VERTEX_USAGE_SHADER_INPUT, size_t(0), "pa_worldTransform0", 1, lineInstanceBuffer_.id());
946  cylinderDeclInstanced_.addElement(GL_FLOAT, 4, VERTEX_USAGE_SHADER_INPUT, size_t(0), "pa_worldTransform1", 1, lineInstanceBuffer_.id());
947  cylinderDeclInstanced_.addElement(GL_FLOAT, 4, VERTEX_USAGE_SHADER_INPUT, size_t(0), "pa_worldTransform2", 1, lineInstanceBuffer_.id());
948  cylinderDeclInstanced_.addElement(GL_FLOAT, 1, VERTEX_USAGE_SHADER_INPUT, size_t(0), "pa_size", 1, lineInstanceBuffer_.id());
949  cylinderDeclInstanced_.addElement(GL_UNSIGNED_BYTE, 4, VERTEX_USAGE_COLOR, size_t(0), 0, 1, lineInstanceBuffer_.id());
950 
951  invalidateInstanceData_ = false;
952  }
953 
954  // scale and offset based on visualization mode (single or both directions)
955  Vec3f pa_scale(0.0f, 0.0f, 0.0f), pa_offset(0.0f, 0.0f, 0.0f);
956 
957  int curTensor = 0;
958  for (int k = 0; k < 3; ++k)
959  {
960  if (show_tensor_component_[k] == 2)
961  {
962  pa_scale[curTensor] = 2.0f;
963  pa_offset[curTensor] = -1.0f;
964  }
965  else
966  {
967  pa_scale[curTensor] = 1.0f;
968  pa_offset[curTensor] = 0.0f;
969  }
970  if (show_tensor_component_[k])
971  ++curTensor;
972  }
973 
974  if (draw_style_ == DS_2D)
975  {
976  // line object
977  obj.debugName = "PrincipalAxisNode.line";
978  obj.name = name() + std::string(".line");
979 
980  obj.shaderDesc.shadeMode = SG_SHADE_UNLIT;
981  obj.shaderDesc.vertexColors = true;
982  obj.shaderDesc.vertexTemplateFile = "PrincipalAxisNode/lines_extruded_instanced.glsl";
983 
984  obj.setUniform("pa_lineWidth", float(cylinder_radius_scale_));
985  obj.setUniform("pa_screenSize", Vec2f(_state.viewport_width(), _state.viewport_height()));
986  obj.setUniform("pa_scale", pa_scale);
987  obj.setUniform("pa_offset", pa_offset);
988  obj.setUniform("pa_visible_tensors", visibleTensors);
989 
990  obj.vertexBuffer = lineBuffer_.id();
991  obj.vertexDecl = &lineDeclInstanced_;
992 
993  obj.glDrawInstancedArrays(GL_TRIANGLE_STRIP, 0, 4, numInstances);
994 
995  _renderer->addRenderObject(&obj);
996  }
997  else
998  {
999  float radius = max_draw_radius_ * 0.015 * cylinder_radius_scale_;
1000 
1001  obj.debugName = "PrincipalAxisNode.cylinder";
1002  obj.name = name() + std::string(".cylinder");
1003 
1004  obj.shaderDesc.vertexColors = true;
1005  obj.shaderDesc.vertexTemplateFile = "PrincipalAxisNode/3d_instanced.glsl";
1006  obj.shaderDesc.colorMaterialMode = GL_AMBIENT_AND_DIFFUSE;
1007 
1008  obj.ambient = obj.diffuse = Vec3f(1.0f, 1.0f, 1.0f);
1009 
1010  obj.setUniform("pa_cone_radius", radius);
1011  obj.setUniform("pa_cone_offset", Vec3f(0.0f, 0.0f, 0.0f));
1012  obj.setUniform("pa_scale", pa_scale * 0.85f);
1013  obj.setUniform("pa_offset", pa_offset * 0.85f);
1014  obj.setUniform("pa_visible_tensors", visibleTensors);
1015 
1016  obj.vertexBuffer = cylinder_.getVBO();
1017  obj.vertexDecl = &cylinderDeclInstanced_;
1018 
1019  obj.glDrawInstancedArrays(GL_TRIANGLES, 0, cylinder_.getNumTriangles() * 3, numInstances);
1020 
1021  _renderer->addRenderObject(&obj);
1022 
1023  // arrowheads
1024  obj.debugName = "PrincipalAxisNode.cone";
1025 
1026  obj.shaderDesc.vertexTemplateFile = "PrincipalAxisNode/3d_cone_instanced.glsl";
1027 
1028  obj.setUniform("pa_cone_radius", cone_height_factor_ * radius);
1029  obj.setUniform("pa_cone_offset", Vec3f(0.0f, 0.0f, 0.0f));
1030  obj.setUniform("pa_cone_mirror", 1.0f);
1031 
1032  obj.vertexBuffer = cone_.getVBO();
1033 
1034  obj.glDrawInstancedArrays(GL_TRIANGLES, 0, cone_.getNumTriangles() * 3, numInstances);
1035 
1036  _renderer->addRenderObject(&obj);
1037 
1038  if (show_tensor_component_[0] == 2 ||
1039  show_tensor_component_[1] == 2 ||
1040  show_tensor_component_[2] == 2)
1041  {
1042  obj.debugName = "PrincipalAxisNode.cone_mirror";
1043  obj.setUniform("pa_cone_mirror", -1.0f);
1044 
1045  _renderer->addRenderObject(&obj);
1046  }
1047  }
1048  }
1049  else
1050  {
1051  // non-instanced
1052 
1053 // emitIndividualRenderobjects(_renderer, _state, _drawMode, _mat);
1054 
1055  RenderObject ro;
1056  ro.initFromState(&_state);
1057  ro.setMaterial(_mat);
1058 
1059  nodeName_ = std::string("PrincipalAxisNode: ") + name();
1060  ro.debugName = nodeName_.c_str();
1061 
1062  ro.depthTest = true;
1063  ro.depthWrite = true;
1064 
1065  ro.shaderDesc.shadeMode = SG_SHADE_UNLIT;
1066 
1067  // simulate line width via quad extrusion in geometry shader
1068  QString geomTemplate = ShaderProgGenerator::getShaderDir();
1069  geomTemplate += "Wireframe/geom_line2quad.tpl";
1070 
1071  ro.shaderDesc.geometryTemplateFile = geomTemplate;
1072 
1073  ro.setUniform("screenSize",
1074  Vec2f((float)_state.viewport_width(),
1075  (float)_state.viewport_height()));
1076  ro.setUniform("lineWidth", static_cast<float>(cylinder_radius_scale_));
1077 
1078  createVBO();
1079  ro.vertexBuffer = vbo_;
1080  // vertexDecl is defined in createVBO
1081  ro.vertexDecl = &vertexDecl_;
1082 
1083  int curOffset = 0;
1084  int vertexCount = static_cast<int>(pc_.size() * 2);
1085  for (int i = 0; i < 3; ++i)
1086  {
1087  if (show_tensor_component_[i])
1088  {
1089  // set axis color
1090  for (int k = 0; k < 3; ++k)
1091  ro.emissive[k] = axes_colors[i][k];
1092 
1093  ro.glDrawArrays(GL_LINES, curOffset, vertexCount);
1094  _renderer->addRenderObject(&ro);
1095 
1096  curOffset += vertexCount;
1097  }
1098  }
1099 
1100  }
1101 }
1102 
1103 //----------------------------------------------------------------------------
1104 
1106 {
1107  RenderObject obj;
1108 
1109  obj.initFromState(&_state);
1110  obj.depthTest = true;
1111 
1112  if (!_drawMode.getLayer(0)->lighting())
1113  obj.shaderDesc.shadeMode = SG_SHADE_UNLIT;
1114  else
1115  {
1116  if (_drawMode.getLayer(0)->flatShaded())
1117  obj.shaderDesc.shadeMode = SG_SHADE_FLAT;
1118  else
1119  obj.shaderDesc.shadeMode = SG_SHADE_GOURAUD;
1120  }
1121 
1122 
1123  for (unsigned int i = 0; i < pc_.size(); ++i)
1124  {
1125  if (draw_pc_[i])
1126  {
1127  const PrincipalComponent& pc = pc_[i];
1128 
1129  for (unsigned int k = 0; k < 3; ++k)
1130  {
1131  if (!show_tensor_component_[k]) continue;
1132 
1133  if (color_mode_ == CM_Sign)
1134  {
1135  // choose color due to eigenvalue sign
1136  if (pc.sign[k] == true)
1137  obj.ambient = obj.diffuse = Vec3f(1.0f, 0.0f, 0.0f);
1138  else
1139  obj.ambient = obj.diffuse = Vec3f(0.0f, 0.0f, 1.0f);
1140  }
1141  else // choose color due to eigenvalue
1142  obj.ambient = obj.diffuse = Vec3f(axes_colors[k][0], axes_colors[k][1], axes_colors[k][2]);
1143 
1144  double size = 1.0;
1145  GLMatrixd axisModelView = _state.modelview() * axisTransform(pc, k, &size);
1146 
1147  if (size > 1e-10)
1148  {
1149  // draw both axis
1150  if (draw_style_ == DS_3D)
1151  {
1152  double radius = max_draw_radius_ * 0.015 * cylinder_radius_scale_;
1153 
1154  // cylinder
1155  obj.name = name() + std::string(".cylinder");
1156 
1157  obj.modelview = axisModelView;
1158 
1159  if (show_tensor_component_[k] == 2)
1160  {
1161  obj.modelview.scale(radius, radius, 2.0 * 0.85 * size);
1162  obj.modelview.translate(0.0, 0.0, -0.5);
1163  }
1164  else
1165  obj.modelview.scale(radius, radius, 0.85 * size);
1166 
1167  obj.vertexDecl = cylinder_.getVertexDecl();
1168  obj.vertexBuffer = cylinder_.getVBO();
1169 
1170  obj.glDrawArrays(GL_TRIANGLES, 0, cylinder_.getNumTriangles() * 3);
1171 
1172  _renderer->addRenderObject(&obj);
1173 
1174  // arrowhead
1175  obj.name = name() + std::string(".cone");
1176 
1177  obj.modelview = axisModelView;
1178  obj.modelview.translate(0, 0, 0.85 * size);
1179  obj.modelview.scale(cone_height_factor_ * radius, cone_height_factor_ * radius, cone_height_factor_ * radius);
1180 
1181  obj.vertexDecl = cone_.getVertexDecl();
1182  obj.vertexBuffer = cone_.getVBO();
1183 
1184  obj.glDrawArrays(GL_TRIANGLES, 0, cone_.getNumTriangles() * 3);
1185 
1186  _renderer->addRenderObject(&obj);
1187 
1188  if (show_tensor_component_[k] == 2)
1189  {
1190  obj.modelview = axisModelView;
1191  obj.modelview.rotate(180, 1, 0, 0);
1192  obj.modelview.translate(0, 0, 0.85 * size);
1193 
1194  obj.modelview.scale(cone_height_factor_ * radius, cone_height_factor_ * radius, cone_height_factor_ * radius);
1195 
1196  _renderer->addRenderObject(&obj);
1197  }
1198  }
1199  else
1200  {
1201  // line object
1202  obj.name = name() + std::string(".line");
1203 
1204  obj.modelview = axisModelView;
1205  obj.shaderDesc.shadeMode = SG_SHADE_UNLIT;
1206  obj.emissive = obj.diffuse;
1207 
1208  if (show_tensor_component_[k] == 2)
1209  {
1210  obj.modelview.scale(1.0, 1.0, 2.0 * size);
1211  obj.modelview.translate(0.0, 0.0, -0.5);
1212  }
1213  else
1214  obj.modelview.scale(1.0, 1.0, size);
1215 
1216  obj.vertexBuffer = lineBuffer_.id();
1217  obj.vertexDecl = &lineDecl_;
1218 
1219  obj.glDrawArrays(GL_LINES, 0, 2);
1220 
1221  _renderer->addRenderObject(&obj);
1222  }
1223  }
1224  }
1225  }
1226  }
1227 }
1228 
1229 //----------------------------------------------------------------------------
1230 
1231 Vec3d
1233 axisScaled(const PrincipalComponent& _pc, int _axis) const
1234 {
1235  Vec3d a;
1236  a = _pc.a[_axis];
1237 
1238  // compute arrow length in world coords
1239  double length;
1240  length = std::max(min_abs_value_, a.norm());
1241  length = std::min(max_abs_value_, length);
1242 
1243  if (a.norm() > 1e-8)
1244  a.normalize();
1245 
1246  // Bug fixed: Visualizing all unit vectors yieled scaled_length = nan
1247  double scaled_length(min_draw_radius_);
1248 
1249  if (fabs(max_abs_value_ - min_abs_value_) > 1e-6)
1250  scaled_length += (length - min_abs_value_) / (max_abs_value_ - min_abs_value_)*(max_draw_radius_ - min_draw_radius_);
1251 
1252  a *= scaled_length;
1253  return a;
1254 }
1255 
1256 //----------------------------------------------------------------------------
1257 
1258 GLMatrixd
1260 axisTransform(const PrincipalComponent& _pc, int _axis, double* _outSize) const
1261 {
1262  assert(0 <= _axis && _axis < 3);
1263 
1265  axisTransform.identity();
1266  axisTransform.translate(_pc.p);
1267 
1268  Vec3d a = axisScaled(_pc, _axis);
1269  double size = a.norm();
1270 
1271  if (_outSize)
1272  *_outSize = size;
1273 
1274  // orientation
1275  if (size > 1e-10)
1276  {
1277  Vec3d direction = a;
1278  Vec3d z_axis(0, 0, 1);
1279  Vec3d rot_normal;
1280  double rot_angle;
1281  direction.normalize();
1282  rot_angle = acos((z_axis | direction)) * 180 / M_PI;
1283  rot_normal = ((z_axis % direction).normalize());
1284 
1285  if (fabs(rot_angle) > 0.0001 && fabs(180 - rot_angle) > 0.0001)
1286  axisTransform.rotate(rot_angle, rot_normal[0], rot_normal[1], rot_normal[2]);
1287  else
1288  axisTransform.rotate(rot_angle, 1, 0, 0);
1289  }
1290 
1291  return axisTransform;
1292 }
1293 
1294 //----------------------------------------------------------------------------
1295 
1296 
1297 
1299  if (!updateVBO_)
1300  return;
1301 
1302  // create vbo if it does not exist
1303  if (!vbo_)
1304  glGenBuffersARB(1, &vbo_);
1305 
1306  int tensorComponentCount = 0;
1307  for (int i = 0; i < 3; ++i) {
1308  tensorComponentCount += show_tensor_component_[i] ? 1 : 0;
1309  }
1310  vertexDecl_.clear();
1311  vertexDecl_.addElement(GL_FLOAT, 3, VERTEX_USAGE_POSITION);
1312 
1313  //3 coordinates per vertex, 2 vertices per principal component
1314  std::vector<float> vboData(3 * 2 * tensorComponentCount * pc_.size(), 0.f);
1315 
1316  float* vboPtr = &vboData[0];
1317 
1318  for (int tensor_component = 0; tensor_component < 3; ++tensor_component) {
1319  if (!show_tensor_component_[tensor_component]) continue;
1320 
1321  for (std::vector<PrincipalComponent>::const_iterator it = pc_.begin();
1322  it != pc_.end(); ++it) {
1323 
1324  Vec3d pc_dir = it->a[tensor_component];
1325 
1326  /*
1327  * Weird scale computation copied from draw().
1328  */
1329  const double pc_dir_norm = pc_dir.norm();
1330  double length;
1331  length = std::max( min_abs_value_, pc_dir_norm);
1332  length = std::min( max_abs_value_, length );
1333 
1334  if( pc_dir_norm > 1e-8 ) pc_dir.normalize();
1335 
1336  // Bug fixed: Visualizing all unit vectors yieled scaled_length = nan
1337  double scaled_length(min_draw_radius_);
1338  if (fabs(max_abs_value_-min_abs_value_) > 1e-6)
1339  scaled_length += (length-min_abs_value_)/(max_abs_value_-min_abs_value_)*(max_draw_radius_-min_draw_radius_);
1340 
1341  pc_dir *= scaled_length;
1342 
1343  const Vec3d pc_from = it->p -
1344  (show_tensor_component_[tensor_component] == 2
1345  ? pc_dir
1346  : Vec3d(0, 0, 0));
1347  const Vec3d pc_to = it->p + pc_dir;
1348 
1349  for (int i = 0; i < 3; ++i)
1350  *(vboPtr++) = pc_from[i];
1351  for (int i = 0; i < 3; ++i)
1352  *(vboPtr++) = pc_to[i];
1353  }
1354  }
1355  assert(vboPtr == &vboData[0] + vboData.size());
1356 
1357  glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo_);
1358  glBufferDataARB(GL_ARRAY_BUFFER_ARB, vboData.size() * sizeof(float),
1359  &vboData[0], GL_STATIC_DRAW_ARB);
1360 
1361  // Update done.
1362  updateVBO_ = false;
1363 }
1364 
1365 //=============================================================================
1366 } // namespace SceneGraph
1367 } // namespace ACG
1368 //=============================================================================
VectorT< float, 2 > Vec2f
Definition: VectorT.hh:108
void draw(GLState &_state, const DrawModes::DrawMode &_drawMode)
drawing the primitive
void createVBO()
creates the vbo only if update was requested
DrawMode SOLID_SMOOTH_SHADED
draw smooth shaded (Gouraud shaded) faces (requires halfedge normals)
Definition: DrawModes.cc:88
DrawMode HIDDENLINE
draw hidden line (2 rendering passes needed)
Definition: DrawModes.cc:86
DrawMode SOLID_FLAT_SHADED
draw flat shaded faces (requires face normals)
Definition: DrawModes.cc:87
void translate(Scalar _x, Scalar _y, Scalar _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with translation matrix (x,y,z)
Definition: GLMatrixT.cc:102
unsigned int getNumElements() const
VectorT< float, 4 > Vec4f
Definition: VectorT.hh:144
DrawMode WIREFRAME
draw wireframe
Definition: DrawModes.cc:84
bool flatShaded() const
Is flat shading used (Normals per face)?
Definition: DrawModes.hh:231
PrincipalAxisNode(BaseNode *_parent=0, std::string _name="<PrincipalAxis>")
Default constructor.
defined by user via VertexElement::shaderInputName_
const VertexDeclaration * vertexDecl
Defines the vertex buffer layout, ignored if VAO is provided.
int viewport_width() const
get viewport width
Definition: GLState.hh:825
bool lighting() const
Is lighting enabled?
Definition: DrawModes.hh:222
DrawMode POINTS
draw unlighted points using the default base color
Definition: DrawModes.cc:79
static QString getShaderDir()
void rotate(Scalar angle, Scalar x, Scalar y, Scalar z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
Definition: GLMatrixT.cc:161
PickTarget
What target to use for picking.
Definition: BaseNode.hh:99
void addElement(const VertexElement *_pElement)
void identity()
setup an identity matrix
Definition: Matrix4x4T.cc:256
vector_type & maximize(const vector_type &_rhs)
maximize values: same as *this = max(*this, _rhs), but faster
Definition: Vector11T.hh:562
static void enable(GLenum _cap)
replaces glEnable, but supports locking
VectorT< float, 3 > Vec3f
Definition: VectorT.hh:125
virtual void addRenderObject(RenderObject *_renderObject)
Callback for the scenegraph nodes, which send new render objects via this function.
Definition: IRenderer.cc:108
Vec3d axisScaled(const PrincipalComponent &_pc, int _axis) const
scaled axis
VectorT< unsigned char, 4 > Vec4uc
Definition: VectorT.hh:134
void setUniform(const char *_name, GLint _value)
set values for int uniforms
const DrawModeProperties * getLayer(unsigned int _i) const
returns the property set at layer i
static void disable(GLenum _cap)
replaces glDisable, but supports locking
std::string name() const
Returns: name of node (needs not be unique)
Definition: MeshNode2T.cc:446
Namespace providing different geometric functions concerning angles.
Definition: DBSCANT.cc:51
void scale(Scalar _x, Scalar _y, Scalar _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with scaling matrix (x,y,z)
Definition: GLMatrixT.cc:81
DrawModes::DrawMode availableDrawModes() const
return available draw modes
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM >>().norm())
Definition: Vector11T.hh:428
GLMatrixd axisTransform(const PrincipalComponent &_pc, int _axis, double *_outSize=0) const
world transform of an axis (orientation and translation)
auto norm() const -> decltype(std::sqrt(std::declval< VectorT< S, DIM >>().sqrnorm()))
compute euclidean norm
Definition: Vector11T.hh:408
void addElement(const VertexElement *_pElement)
void initFromState(GLState *_glState)
Initializes a RenderObject instance.
Definition: RenderObject.cc:69
bool checkExtensionSupported(const std::string &_extension)
Definition: gl.cc:73
pick any of the prior targets (should be implemented for all nodes)
Definition: BaseNode.hh:110
vector_type & minimize(const vector_type &_rhs)
minimize values: same as *this = min(*this, _rhs), but faster
Definition: Vector11T.hh:534
int viewport_height() const
get viewport height
Definition: GLState.hh:827
void pick(GLState &_state, PickTarget _target)
picking
bool default_radius_
Indicates whether the min/max draw radius has been changed from its default setting.
Interface class between scenegraph and renderer.
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) ...
void getRenderObjects(IRenderer *_renderer, GLState &_state, const DrawModes::DrawMode &_drawMode, const ACG::SceneGraph::Material *_mat)
Overriding BaseNode::getRenderObjects.
VectorT< double, 3 > Vec3d
Definition: VectorT.hh:127
picks faces (should be implemented for all nodes)
Definition: BaseNode.hh:104
void boundingBox(Vec3d &_bbMin, Vec3d &_bbMax)
update bounding box
GLuint vertexBuffer
VBO, IBO ids, ignored if VAO is provided.
ShaderGenDesc shaderDesc
Drawmode and other shader params.
static void shadeModel(GLenum _mode)
replaces glShadeModel, supports locking
Scalar * data()
access to Scalar array
Definition: Vector11T.hh:193