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
82 PrincipalAxisNode::PrincipalAxisNode( BaseNode* _parent,
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
123 PrincipalAxisNode::~PrincipalAxisNode()
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 {
144 QtPrincipalAxisDialog* pd = new QtPrincipalAxisDialog(*this);
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
435 PrincipalAxisNode::
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
449 DrawModes::DrawMode
450 PrincipalAxisNode::
451 availableDrawModes() const
452 {
453 return ( DrawModes::POINTS |
454 DrawModes::WIREFRAME |
455 DrawModes::HIDDENLINE |
456 DrawModes::SOLID_FLAT_SHADED |
457 DrawModes::SOLID_SMOOTH_SHADED );
458 }
459
460
461 //----------------------------------------------------------------------------
462
463
464 void
465 PrincipalAxisNode::
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
649 PrincipalAxisNode::
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
802 void PrincipalAxisNode::getRenderObjects(IRenderer* _renderer, GLState& _state,
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
1102 void PrincipalAxisNode::emitIndividualRenderobjects(IRenderer* _renderer, GLState& _state, const DrawModes::DrawMode& _drawMode, const ACG::SceneGraph::Material* _mat)
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
1229 PrincipalAxisNode::
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
1256 PrincipalAxisNode::
1257 axisTransform(const PrincipalComponent& _pc, int _axis, double* _outSize) const
1258 {
1259 assert(0 <= _axis && _axis < 3);
1260
1261 GLMatrixd axisTransform;
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
1295 void PrincipalAxisNode::createVBO() {
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 //=============================================================================
ACG::GLMatrixT::rotate
void rotate(Scalar angle, Scalar x, Scalar y, Scalar z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
Definition: GLMatrixT_impl.hh:155
ACG::ShaderProgGenerator::getShaderDir
static QString getShaderDir()
Definition: ShaderGenerator.cc:2451
ACG::RenderObject::initFromState
void initFromState(GLState *_glState)
Initializes a RenderObject instance.
Definition: RenderObject.cc:61
ACG::RenderObject::setUniform
void setUniform(const char *_name, GLint _value)
set values for int uniforms
Definition: RenderObject.cc:413
ACG::VERTEX_USAGE_SHADER_INPUT
defined by user via VertexElement::shaderInputName_
Definition: VertexDeclaration.hh:71
ACG::SceneGraph::PrincipalAxisNode::emitIndividualRenderobjects
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) ...
Definition: PrincipalAxisNode.cc:1102
ACG::GLState
Definition: GLState.hh:213
ACG::SceneGraph::PICK_FACE
picks faces (should be implemented for all nodes)
Definition: PickTarget.hh:78
ACG::SceneGraph::DrawModes::DrawModeProperties::flatShaded
bool flatShaded() const
Is flat shading used (Normals per face)?
Definition: DrawModes.hh:225
ACG::VertexDeclaration::getNumElements
unsigned int getNumElements() const
Definition: VertexDeclaration.cc:309
ACG::GLState::viewport_width
int viewport_width() const
get viewport width
Definition: GLState.hh:822
ACG::Vec2f
VectorT< float, 2 > Vec2f
Definition: VectorT.hh:102
ACG::SceneGraph::DrawModes::DrawModeProperties::lighting
bool lighting() const
Is lighting enabled?
Definition: DrawModes.hh:216
ACG
Namespace providing different geometric functions concerning angles.
Definition: BaseObjectData.hh:68
ACG::Vec4f
VectorT< float, 4 > Vec4f
Definition: VectorT.hh:138
ACG::SceneGraph::ACG::GLState::disable
static void disable(GLenum _cap, bool _warnRemoved=true)
replaces glDisable, but supports locking
ACG::RenderObject::shaderDesc
ShaderGenDesc shaderDesc
Drawmode and other shader params.
Definition: RenderObject.hh:225
ACG::GLMatrixT::translate
void translate(Scalar _x, Scalar _y, Scalar _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with translation matrix (x,y,z)
Definition: GLMatrixT_impl.hh:96
OpenMesh::VectorT
Definition: Vector11T.hh:83
ACG::Matrix4x4T::identity
void identity()
setup an identity matrix
Definition: Matrix4x4T_impl.hh:250
ACG::SceneGraph::DrawModes::HIDDENLINE
DrawMode HIDDENLINE
draw hidden line (2 rendering passes needed)
Definition: DrawModes.cc:80
OpenMesh::VectorT::maximize
vector_type & maximize(const vector_type &_rhs)
maximize values: same as *this = max(*this, _rhs), but faster
Definition: Vector11T.hh:568
ACG::SceneGraph::PrincipalAxisNode::pick
void pick(GLState &_state, PickTarget _target) override
picking
Definition: PrincipalAxisNode.cc:650
ACG::RenderObject::vertexBuffer
GLuint vertexBuffer
VBO, IBO ids, ignored if VAO is provided.
Definition: RenderObject.hh:162
ACG::VertexDeclaration::clear
void clear()
Definition: VertexDeclaration.cc:570
ACG::SceneGraph::PrincipalAxisNode::boundingBox
void boundingBox(Vec3d &_bbMin, Vec3d &_bbMax) override
update bounding box
Definition: PrincipalAxisNode.cc:436
ACG::SceneGraph::DrawModes::SOLID_SMOOTH_SHADED
DrawMode SOLID_SMOOTH_SHADED
draw smooth shaded (Gouraud shaded) faces (requires halfedge normals)
Definition: DrawModes.cc:82
ACG::IRenderer
Definition: IRenderer.hh:78
OpenMesh::VectorT::data
Scalar * data()
access to Scalar array
Definition: Vector11T.hh:200
SceneGraph
Definition: QtPrincipalAxisDialog.hh:67
ACG::SceneGraph::PickTarget
PickTarget
What target to use for picking.
Definition: PickTarget.hh:73
ACG::SceneGraph::PrincipalAxisNode::availableDrawModes
DrawModes::DrawMode availableDrawModes() const override
return available draw modes
Definition: PrincipalAxisNode.cc:451
ACG::Vec3f
VectorT< float, 3 > Vec3f
Definition: VectorT.hh:119
ACG::SceneGraph::PrincipalAxisNode::createVBO
void createVBO()
creates the vbo only if update was requested
Definition: PrincipalAxisNode.cc:1295
ACG::VERTEX_USAGE_POSITION
"inPosition"
Definition: VertexDeclaration.hh:65
ACG::SceneGraph::PrincipalAxisNode::default_radius_
bool default_radius_
Indicates whether the min/max draw radius has been changed from its default setting.
Definition: PrincipalAxisNode.hh:277
ACG::GLMatrixT< double >
ACG::VertexDeclaration::addElement
void addElement(const VertexElement *_pElement)
Definition: VertexDeclaration.cc:115
ACG::SceneGraph::PICK_ANYTHING
pick any of the prior targets (should be implemented for all nodes)
Definition: PickTarget.hh:84
ACG::GLMatrixT::scale
void scale(Scalar _x, Scalar _y, Scalar _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with scaling matrix (x,y,z)
Definition: GLMatrixT_impl.hh:75
ACG::GLState::viewport_height
int viewport_height() const
get viewport height
Definition: GLState.hh:824
OpenMesh::VectorT::minimize
vector_type & minimize(const vector_type &_rhs)
minimize values: same as *this = min(*this, _rhs), but faster
Definition: Vector11T.hh:540
ACG::RenderObject::vertexDecl
const VertexDeclaration * vertexDecl
Defines the vertex buffer layout, ignored if VAO is provided.
Definition: RenderObject.hh:208
OpenMesh::VectorT::norm
auto norm() const -> decltype(std::sqrt(std::declval< VectorT< S, DIM >>().sqrnorm()))
compute euclidean norm
Definition: Vector11T.hh:414
ACG::SceneGraph::BaseNode
Definition: BaseNode.hh:104
ACG::SceneGraph::DrawModes::POINTS
DrawMode POINTS
draw unlighted points using the default base color
Definition: DrawModes.cc:73
ACG::IRenderer::addRenderObject
virtual void addRenderObject(RenderObject *_renderObject)
Callback for the scenegraph nodes, which send new render objects via this function.
Definition: IRenderer.cc:104
ACG::QtPrincipalAxisDialog
Definition: QtPrincipalAxisDialog.hh:87
ACG::SceneGraph::DrawModes::SOLID_FLAT_SHADED
DrawMode SOLID_FLAT_SHADED
draw flat shaded faces (requires face normals)
Definition: DrawModes.cc:81
ACG::SceneGraph::PrincipalAxisNode::PrincipalAxisNode
PrincipalAxisNode(BaseNode *_parent=0, const std::string &_name="<PrincipalAxis>")
Default constructor.
Definition: PrincipalAxisNode.cc:82
ACG::SceneGraph::DrawModes::DrawMode
Specifies a DrawMode.
Definition: DrawModes.hh:288
ACG::VERTEX_USAGE_COLOR
"inColor"
Definition: VertexDeclaration.hh:68
ACG::SceneGraph::DrawModes::WIREFRAME
DrawMode WIREFRAME
draw wireframe
Definition: DrawModes.cc:78
ACG::SceneGraph::PrincipalAxisNode::~PrincipalAxisNode
virtual ~PrincipalAxisNode()
destructor
Definition: PrincipalAxisNode.cc:123
ACG::checkExtensionSupported
bool checkExtensionSupported(const std::string &_extension)
Definition: gl.cc:107
ACG::SceneGraph::ACG::GLState::enable
static void enable(GLenum _cap, bool _warnRemoved=true)
replaces glEnable, but supports locking
ACG::SceneGraph::PrincipalAxisNode::axisTransform
GLMatrixd axisTransform(const PrincipalComponent &_pc, int _axis, double *_outSize=0) const
world transform of an axis (orientation and translation)
Definition: PrincipalAxisNode.cc:1257
ACG::SceneGraph::PrincipalAxisNode::axisScaled
Vec3d axisScaled(const PrincipalComponent &_pc, int _axis) const
scaled axis
Definition: PrincipalAxisNode.cc:1230
ACG::SceneGraph::PrincipalAxisNode::getRenderObjects
void getRenderObjects(IRenderer *_renderer, GLState &_state, const DrawModes::DrawMode &_drawMode, const ACG::SceneGraph::Material *_mat) override
Overriding BaseNode::getRenderObjects.
Definition: PrincipalAxisNode.cc:802
ACG::SceneGraph::DrawModes::DrawMode::getLayer
const DrawModeProperties * getLayer(unsigned int _i) const
returns the property set at layer i
Definition: DrawModes.cc:535
ACG::SceneGraph::PrincipalAxisNode::draw
void draw(GLState &_state, const DrawModes::DrawMode &_drawMode) override
drawing the primitive
Definition: PrincipalAxisNode.cc:466
ACG::SceneGraph::ACG::SceneGraph::BaseNode::name
std::string name() const
Returns: name of node (needs not be unique)
Definition: MeshNode2T_impl.hh:415
OpenMesh::VectorT::normalize
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM >>().norm())
Definition: Vector11T.hh:434
ACG::Vec4uc
VectorT< unsigned char, 4 > Vec4uc
Definition: VectorT.hh:128
ACG::RenderObject
Interface class between scenegraph and renderer.
Definition: RenderObject.hh:98
ACG::SceneGraph::ACG::GLState::shadeModel
static void shadeModel(GLenum _mode)
replaces glShadeModel, supports locking
ACG::SceneGraph::Material
Definition: MaterialNode.hh:79
ACG::SceneGraph::PrincipalComponent
Definition: PrincipalAxisNode.hh:80
ACG::Vec3d
VectorT< double, 3 > Vec3d
Definition: VectorT.hh:121