Developer Documentation
Loading...
Searching...
No Matches
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
63namespace ACG {
64namespace 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
126
127//----------------------------------------------------------------------------
128
129void 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
140void
141PrincipalAxisNode::
142show_options_dialog()
143{
144 QtPrincipalAxisDialog* pd = new QtPrincipalAxisDialog(*this);
145 pd->show();
146}
147
148
149//----------------------------------------------------------------------------
150
151
152void
153PrincipalAxisNode::
154show_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
173void
174PrincipalAxisNode::
175resize(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
193void
194PrincipalAxisNode::
195enable ( 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
212void
213PrincipalAxisNode::
214disable ( 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
231void
232PrincipalAxisNode::
233disable_all()
234{
235 for(size_t i=0; i<pc_.size(); ++i)
236 disable(i);
237}
238
239
240//----------------------------------------------------------------------------
241
242
243void
244PrincipalAxisNode::
245set(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
270void
271PrincipalAxisNode::
272get(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
285void
286PrincipalAxisNode::
287add(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
305void
306PrincipalAxisNode::
307set_auto_range( bool _b)
308{
309 auto_range_ = _b;
310}
311
312
313//----------------------------------------------------------------------------
314
315
316void
317PrincipalAxisNode::
318set_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
332void
333PrincipalAxisNode::
334set_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
347void
348PrincipalAxisNode::
349set_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
361void
362PrincipalAxisNode::
363set_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
375void
376PrincipalAxisNode::
377auto_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
398void
399PrincipalAxisNode::
400update_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
434void
436boundingBox(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
459
460
461//----------------------------------------------------------------------------
462
463
464void
466draw(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
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
489void
490PrincipalAxisNode::
491draw_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
585void
586PrincipalAxisNode::
587draw_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
633void
634PrincipalAxisNode::
635draw_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
648void
650pick(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
675void 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
686void 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
701void 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
1228Vec3d
1230axisScaled(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
1257axisTransform(const PrincipalComponent& _pc, int _axis, double* _outSize) const
1258{
1259 assert(0 <= _axis && _axis < 3);
1260
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//=============================================================================
void rotate(Scalar angle, Scalar x, Scalar y, Scalar z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
void scale(Scalar _x, Scalar _y, Scalar _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with scaling matrix (x,y,z)
void translate(Scalar _x, Scalar _y, Scalar _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with translation matrix (x,y,z)
static void enable(GLenum _cap, bool _warnRemoved=true)
replaces glEnable, but supports locking
Definition GLState.cc:1507
const GLMatrixd & modelview() const
get modelview matrix
Definition GLState.hh:816
int viewport_width() const
get viewport width
Definition GLState.hh:847
static void disable(GLenum _cap, bool _warnRemoved=true)
replaces glDisable, but supports locking
Definition GLState.cc:1527
int viewport_height() const
get viewport height
Definition GLState.hh:849
static void shadeModel(GLenum _mode)
replaces glShadeModel, supports locking
Definition GLState.cc:1729
virtual void addRenderObject(RenderObject *_renderObject)
Callback for the scenegraph nodes, which send new render objects via this function.
Definition IRenderer.cc:104
void identity()
setup an identity matrix
std::string name() const
Returns: name of node (needs not be unique)
Definition BaseNode.hh:415
bool flatShaded() const
Is flat shading used (Normals per face)?
Definition DrawModes.hh:225
bool lighting() const
Is lighting enabled?
Definition DrawModes.hh:216
const DrawModeProperties * getLayer(unsigned int _i) const
returns the property set at layer i
Definition DrawModes.cc:525
void draw(GLState &_state, const DrawModes::DrawMode &_drawMode) override
drawing the primitive
Vec3d axisScaled(const PrincipalComponent &_pc, int _axis) const
scaled axis
void createVBO()
creates the vbo only if update was requested
void getRenderObjects(IRenderer *_renderer, GLState &_state, const DrawModes::DrawMode &_drawMode, const ACG::SceneGraph::Material *_mat) override
Overriding BaseNode::getRenderObjects.
void pick(GLState &_state, PickTarget _target) override
picking
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.
void boundingBox(Vec3d &_bbMin, Vec3d &_bbMax) override
update bounding box
DrawModes::DrawMode availableDrawModes() const override
return available draw modes
GLMatrixd axisTransform(const PrincipalComponent &_pc, int _axis, double *_outSize=0) const
world transform of an axis (orientation and translation)
void addElement(const VertexElement *_pElement)
unsigned int getNumElements() const
Scalar * data()
access to Scalar array
Definition Vector11T.hh:201
vector_type & maximize(const vector_type &_rhs)
maximize values: same as *this = max(*this, _rhs), but faster
Definition Vector11T.hh:588
vector_type & minimize(const vector_type &_rhs)
minimize values: same as *this = min(*this, _rhs), but faster
Definition Vector11T.hh:560
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM > >().norm())
Definition Vector11T.hh:454
auto norm() const -> decltype(std::sqrt(std::declval< VectorT< S, DIM > >().sqrnorm()))
compute euclidean norm
Definition Vector11T.hh:434
DrawMode SOLID_SMOOTH_SHADED
draw smooth shaded (Gouraud shaded) faces (requires halfedge normals)
Definition DrawModes.cc:82
DrawMode WIREFRAME
draw wireframe
Definition DrawModes.cc:78
DrawMode HIDDENLINE
draw hidden line (2 rendering passes needed)
Definition DrawModes.cc:80
DrawMode POINTS
draw unlighted points using the default base color
Definition DrawModes.cc:73
DrawMode SOLID_FLAT_SHADED
draw flat shaded faces (requires face normals)
Definition DrawModes.cc:81
PickTarget
What target to use for picking.
Definition PickTarget.hh:74
@ PICK_ANYTHING
pick any of the prior targets (should be implemented for all nodes)
Definition PickTarget.hh:84
@ PICK_FACE
picks faces (should be implemented for all nodes)
Definition PickTarget.hh:78
Namespace providing different geometric functions concerning angles.
VectorT< float, 4 > Vec4f
Definition VectorT.hh:138
bool checkExtensionSupported(const std::string &_extension)
Definition gl.cc:107
VectorT< float, 3 > Vec3f
Definition VectorT.hh:119
VectorT< float, 2 > Vec2f
Definition VectorT.hh:102
@ VERTEX_USAGE_COLOR
"inColor"
@ VERTEX_USAGE_POSITION
"inPosition"
@ VERTEX_USAGE_SHADER_INPUT
defined by user via VertexElement::shaderInputName_
VectorT< unsigned char, 4 > Vec4uc
Definition VectorT.hh:128
VectorT< double, 3 > Vec3d
Definition VectorT.hh:121
Interface class between scenegraph and renderer.
Vec3f diffuse
material definitions
ShaderGenDesc shaderDesc
Drawmode and other shader params.
const VertexDeclaration * vertexDecl
Defines the vertex buffer layout, ignored if VAO is provided.
GLMatrixd modelview
Modelview transform.
std::string name
Name for logging.
GLuint vertexBuffer
VBO, IBO ids, ignored if VAO is provided.
void setUniform(const char *_name, GLint _value)
set values for int uniforms
void initFromState(GLState *_glState)
Initializes a RenderObject instance.