Developer Documentation

SkeletonNodeT_impl.hh
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4 * Copyright (c) 2001-2015, 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
46
47 //=============================================================================
48 //
49 // CLASS SkeletonNodeT - IMPLEMENTATION
50 //
51 //=============================================================================
52
53 #define ACG_SKELETONNODET_C
54
55 //== INCLUDES =================================================================
56
57 #include "SkeletonNodeT.hh"
58 #include <ACG/GL/gl.hh>
59 #include <ACG/GL/IRenderer.hh>
60 #include <vector>
61 #include <deque>
62
63 //== NAMESPACES ===============================================================
64
65 namespace ACG {
66 namespace SceneGraph {
67
68 //== IMPLEMENTATION ==========================================================
69
70
74 template <class SkeletonType>
75 SkeletonNodeT<SkeletonType>::SkeletonNodeT(SkeletonType &_skeleton, BaseNode *_parent, std::string _name) :
76 BaseNode(_parent, _name),
77 bCoordFramesVisible_(false),
78 skeleton_(_skeleton),
79 hAni_(),
80 fFrameSize_(0.0),
81 slices_(6),
82 stacks_(1)
83 {
84 this->multipassNodeSetActive(3, true);
85
86 sphere_ = new ACG::GLSphere(10, 10);
87 cone_ = new ACG::GLCone(slices_, stacks_, 1.0f, 0.0f, false, false);
88 cylinder_ = new ACG::GLCylinder(10, 2, 1.0f, true, true);
89 }
90
91
92 //------------------------------------------------------------------------------
93
97 template <class SkeletonType>
98 SkeletonNodeT<SkeletonType>::~SkeletonNodeT()
99 {
100 if (sphere_)
101 delete sphere_;
102
103 if (cone_)
104 delete cone_;
105
106 if (cylinder_)
107 delete cylinder_;
108 }
109
110
111 //------------------------------------------------------------------------------
112
116 template <class SkeletonType>
117 SkeletonType& SkeletonNodeT<SkeletonType>::skeleton()
118 {
119 return skeleton_;
120 }
121
122
123 //------------------------------------------------------------------------------
124
128 template <class SkeletonType>
129 void SkeletonNodeT<SkeletonType>::boundingBox(Vec3d& _bbMin, Vec3d& _bbMax)
130 {
131 if(skeleton_.jointCount() == 0)
132 return; // no joints, no contribution to the bound box
133
134 Pose *pose = skeleton_.pose(hAni_);
135 typename SkeletonType::Iterator it;
136 for(it = skeleton_.begin(); it != skeleton_.end(); ++it)
137 {
138 _bbMin.minimize( (Vec3d)pose->globalTranslation((*it)->id()) );
139 _bbMax.maximize( (Vec3d)pose->globalTranslation((*it)->id()) );
140 }
141
142 //choose a proper size for the coordinate frames
143 fFrameSize_ = (_bbMin - _bbMax).norm() * 0.07;
144 }
145
146
147 //----------------------------------------------------------------------------
148
152 template <class SkeletonType>
153 DrawModes::DrawMode SkeletonNodeT<SkeletonType>::availableDrawModes() const
154 {
155 return (DrawModes::WIREFRAME | DrawModes::POINTS | DrawModes::SOLID_FLAT_SHADED
156 | DrawModes::SOLID_FACES_COLORED | DrawModes::SOLID_FACES_COLORED_FLAT_SHADED);
157 }
158
159
160 //----------------------------------------------------------------------------
161
162
163 template <class SkeletonType>
164 double SkeletonNodeT<SkeletonType>::frameSize() {
165 return fFrameSize_;
166 }
167
168
169 //----------------------------------------------------------------------------
170
171
175 template <class SkeletonType>
176 void SkeletonNodeT<SkeletonType>::NormalizeCoordinateFrame(Matrix &_mat)
177 {
178 ACG::Vec3d vec;
179 for(int i = 0; i < 3; ++i)
180 {
181 for(int x = 0; x < 3; ++x)
182 vec[x] = _mat(x, i);
183 vec.normalize();
184 for(int x = 0; x < 3; ++x)
185 _mat(x, i) = vec[x];
186 }
187 }
188
189
190 //----------------------------------------------------------------------------
191
200 template <class SkeletonType>
201 void SkeletonNodeT<SkeletonType>::HSVtoRGB(const Vec4f& _HSV, Vec4f& _RGB)
202 {
203 int h;
204 float f, p, q, t;
205 h = int(floor(_HSV[0] / 60.0));
206 f = _HSV[0] / 60.0 - float(h);
207 p = _HSV[2] * (1 - _HSV[1]);
208 q = _HSV[2] * (1 - _HSV[1] * f);
209 t = _HSV[2] * (1 - _HSV[1] * (1 - f));
210
211 switch(h)
212 {
213 case 0:
214 case 6:
215 _RGB[0] = _HSV[2];
216 _RGB[1] = t;
217 _RGB[2] = p;
218 break;
219 case 1:
220 _RGB[0] = q;
221 _RGB[1] = _HSV[2];
222 _RGB[2] = p;
223 break;
224 case 2:
225 _RGB[0] = p;
226 _RGB[1] = _HSV[2];
227 _RGB[2] = t;
228 break;
229 case 3:
230 _RGB[0] = p;
231 _RGB[1] = q;
232 _RGB[2] = _HSV[2];
233 break;
234 case 4:
235 _RGB[0] = t;
236 _RGB[1] = p;
237 _RGB[2] = _HSV[2];
238 break;
239 case 5:
240 _RGB[0] = _HSV[2];
241 _RGB[1] = p;
242 _RGB[2] = q;
243 break;
244 }
245
246 //always set alpha to 1.0
247 _RGB[3] = 1.0;
248 }
249
250
251 //----------------------------------------------------------------------------
252
261 template <class SkeletonType>
262 void SkeletonNodeT<SkeletonType>::RGBtoHSV(const Vec4f& _RGB, Vec4f& _HSV)
263 {
264 double maxC = _RGB[2];
265 if(maxC < _RGB[1])
266 maxC = _RGB[1];
267 if(maxC < _RGB[0])
268 maxC = _RGB[0];
269 double minC = _RGB[2];
270 if(minC > _RGB[1])
271 minC = _RGB[1];
272 if(minC > _RGB[0])
273 minC = _RGB[0];
274
275 double delta = maxC - minC;
276
277 double V = maxC;
278 double S = 0;
279 double H = 0;
280
281 if(delta == 0)
282 {
283 H = 0;
284 S = 0;
285 }else{
286 S = delta / maxC;
287 double dR = 60 * (maxC - _RGB[0]) / delta + 180;
288 double dG = 60 * (maxC - _RGB[1]) / delta + 180;
289 double dB = 60 * (maxC - _RGB[2]) / delta + 180;
290 if (_RGB[0] == maxC)
291 H = dB - dG;
292 else if (_RGB[1] == maxC)
293 H = 120 + dR - dB;
294 else
295 H = 240 + dG - dR;
296 }
297
298 if(H < 0)
299 H += 360;
300 if(H >= 360)
301 H -= 360;
302
303 _HSV[0] = H;
304 _HSV[1] = S;
305 _HSV[2] = V;
306 }
307
308 //----------------------------------------------------------------------------
309
313 template <class SkeletonType>
314 void SkeletonNodeT<SkeletonType>::draw(GLState& _state, const DrawModes::DrawMode& _drawMode)
315 {
316
317 ACG::GLState::disable(GL_LIGHTING);
318
319 glPushAttrib(GL_ENABLE_BIT);
320
321 Pose *pose = skeleton_.pose(hAni_);
322 typename SkeletonType::Iterator it;
323
324
325
326 // draw points
327 //
328 if (_drawMode & DrawModes::POINTS)
329 {
330 Vec4f jointColor;
331 getJointColor(_state.diffuse_color(), jointColor);
332
333 // draw all joint positions
334 glPointSize(12);
335
336 //we will set the specular color, otherwise the color cannot be seen
337 ACG::Vec4f oldSpecular = _state.specular_color();
338 ACG::Vec4f oldDiffuse = _state.diffuse_color();
339
340 for(it = skeleton_.begin(); it != skeleton_.end(); ++it)
341 {
342
343 // If the vertex is selected, it will be always red
344 if ( (*it)->selected() )
345 {
346 _state.set_color(ACG::Vec4f(1.0f, 0.0f, 0.0f ,1.0f));
347 _state.set_diffuse_color(ACG::Vec4f(1.0f, 0.0f, 0.0f ,1.0f));
348 _state.set_specular_color(ACG::Vec4f(1.0f, 0.0f, 0.0f ,1.0f));
349 }
350 else {
351 // If it is the root joint, it will get some kind of orange color
352 // Otherwise the the Base color is used
353 if ( (*it)->isRoot() )
354 {
355 ACG::Vec4f root_color = ACG::Vec4f(1.0f, 0.66f, 0.0f ,1.0f);
356 _state.set_color(root_color);
357 _state.set_diffuse_color(root_color);
358 _state.set_specular_color(root_color);
359 }
360 else {
361 _state.set_color(ACG::Vec4f(jointColor[0], jointColor[1] , jointColor[2], 1.0));
362 _state.set_ambient_color(ACG::Vec4f(jointColor[0], jointColor[1] , jointColor[2], 1.0));
363 _state.set_diffuse_color(ACG::Vec4f(jointColor[0], jointColor[1] , jointColor[2], 1.0));
364 _state.set_specular_color(ACG::Vec4f(jointColor[0], jointColor[1] , jointColor[2], 1.0));
365 }
366 }
367
368
369 // Simulate glPointSize() with a sphere
370
371 const double sphereSize = unprojectPointSize((double)_state.point_size(),
372 pose->globalTranslation( (*it)->id() ), _state);
373
374 sphere_->draw(_state,sphereSize,ACG::Vec3f(pose->globalTranslation( (*it)->id() )));
375
376 }
377
378 _state.set_specular_color(oldSpecular);
379 _state.set_diffuse_color(oldDiffuse);
380
381
382 // draw the local coordinate frames
383 if(bCoordFramesVisible_)
384 {
385 ACG::GLState::enable(GL_DEPTH_TEST);
386 glPointSize(6.0);
387 glBegin(GL_POINTS);
388 for(it = skeleton_.begin(); it != skeleton_.end(); ++it)
389 {
390 typename SkeletonType::Matrix global = pose->globalMatrix( (*it)->id() );
391 NormalizeCoordinateFrame(global);
392 glColor3f(0.8f, 0.2f, 0.2f);
393 glVertex( global.transform_point(Point(fFrameSize_, 0, 0)) );
394 glColor3f(0.2f, 0.8f, 0.2f);
395 glVertex( global.transform_point(Point(0, fFrameSize_, 0)) );
396 glColor3f(0.2f, 0.2f, 0.8f);
397 glVertex( global.transform_point(Point(0, 0, fFrameSize_)) );
398 }
399 glEnd();
400 glPointSize(_state.point_size());
401 }
402 }
403
404
405 // draw bones
406 //
407 if ( (_drawMode & DrawModes::WIREFRAME)
408 || (_drawMode & DrawModes::SOLID_FLAT_SHADED)
409 || (_drawMode & DrawModes::SOLID_FACES_COLORED)
410 || (_drawMode & DrawModes::SOLID_FACES_COLORED_FLAT_SHADED) )
411 {
412
413 if ( (_drawMode & DrawModes::SOLID_FLAT_SHADED)
414 || (_drawMode & DrawModes::SOLID_FACES_COLORED_FLAT_SHADED) ){
415
416 ACG::GLState::shadeModel(GL_FLAT);
417 ACG::GLState::enable(GL_LIGHTING);
418 }
419
420 if (_drawMode & DrawModes::SOLID_FACES_COLORED)
421 ACG::GLState::shadeModel(GL_FLAT);
422
423
424 glLineWidth(1.5);
425
426 // draw the bones
427 for(it = skeleton_.begin(); it != skeleton_.end(); ++it) {
428
429 //joint is the (unique) tail joint of the bone
430 Joint* joint = *it;
431 Joint* parent = joint->parent();
432
433 // root can be ignored
434 // we only want to draw bones from (parent -> joint)
435 if (parent == 0)
436 continue;
437
438 //select joint color
439 Vec4f baseColor = _state.ambient_color();
440 glColor4fv( &baseColor[0] );
441
442 Vec3d parentPos = pose->globalTranslation(parent->id());
443 Vec3d jointPos = pose->globalTranslation(joint->id());
444
445 Vec3d boneVector = (jointPos - parentPos);
446
447 draw_bone(_state, _drawMode, parentPos, boneVector);
448 }
449
450
451 // draw the local coordinate frames
452 if(bCoordFramesVisible_)
453 {
454 ACG::GLState::disable(GL_COLOR_MATERIAL);
455 ACG::GLState::disable(GL_LIGHTING);
456
457 glLineWidth(3.0);
458 glBegin(GL_LINES);
459 for(it = skeleton_.begin(); it != skeleton_.end(); ++it)
460 {
461 unsigned int index = (*it)->id();
462 typename SkeletonType::Matrix global = pose->globalMatrix(index);
463 NormalizeCoordinateFrame(global);
464 glColor3f(0.8f, 0.2f, 0.2f);
465 glVertex( pose->globalTranslation(index));
466 glVertex( global.transform_point(Point(fFrameSize_, 0, 0)) );
467 glColor3f(0.2f, 0.8f, 0.2f);
468 glVertex( pose->globalTranslation(index));
469 glVertex( global.transform_point(Point(0, fFrameSize_, 0)) );
470 glColor3f(0.2f, 0.2f, 0.8f);
471 glVertex( pose->globalTranslation(index));
472 glVertex( global.transform_point(Point(0, 0, fFrameSize_)) );
473 }
474 glEnd();
475 glLineWidth(_state.line_width());
476 }
477 }
478
479
480 glColor(_state.base_color());
481
482 glPopAttrib();
483 }
484
485 //----------------------------------------------------------------------------
486
490 template <class SkeletonType>
491 void SkeletonNodeT<SkeletonType>::getJointColor( const Vec4f& _baseColor, Vec4f& _result )
492 {
493 Vec4f hsv;
494 RGBtoHSV(_baseColor, hsv);
495
496 hsv[0] += 0.4f;
497 if (hsv[0] > 1.0) hsv[0] -= 1.0;
498
499 hsv[1] += 0.1f;
500 if (hsv[1] > 1.0) hsv[1] = 1.0;
501
502 HSVtoRGB(hsv, _result);
503 }
504
505
506 //----------------------------------------------------------------------------
507
511 template <class SkeletonType>
512 void SkeletonNodeT<SkeletonType>::pick(GLState& _state, PickTarget _target)
513 {
514 unsigned int n_of_vertices = skeleton_.jointCount();
515
516 switch (_target)
517 {
518 case PICK_VERTEX:
519 _state.pick_set_maximum(n_of_vertices);
520 pick_vertices(_state);
521 break;
522
523 case PICK_EDGE:
524 _state.pick_set_maximum(n_of_vertices);
525 pick_edges(_state);
526 break;
527
528 case PICK_ANYTHING:
529 _state.pick_set_maximum(n_of_vertices);
530 pick_vertices(_state);
531 pick_edges(_state);
532 break;
533
534 default:
535 break;
536 }
537 }
538
539
540 //----------------------------------------------------------------------------
541
545 template <class SkeletonType>
546 void SkeletonNodeT<SkeletonType>::pick_vertices(GLState &_state)
547 {
548 glPointSize(16.0);
549 typename SkeletonType::Pose* pose = skeleton_.pose(hAni_);
550 for(typename SkeletonType::Iterator it = skeleton_.begin(); it != skeleton_.end(); ++it)
551 {
552 typename SkeletonType::Joint *joint = *it;
553 _state.pick_set_name(joint->id());
554
555 Vec3d p = pose->globalTranslation(joint->id());
556
557 glBegin(GL_POINTS);
558 glVertex(p);
559 glEnd();
560 }
561 }
562
563
564 //----------------------------------------------------------------------------
565
569 template <class SkeletonType>
570 void SkeletonNodeT<SkeletonType>::pick_edges(GLState &_state)
571 {
572 glLineWidth(10);
573 typename SkeletonType::Pose* pose = skeleton_.pose(hAni_);
574 for(typename SkeletonType::Iterator it = skeleton_.begin(); it != skeleton_.end(); ++it)
575 {
576 Joint *joint = *it;
577 for(typename Joint::ChildIter it_ch = joint->begin(); it_ch != joint->end(); ++it_ch)
578 {
579 Joint *child = *it_ch;
580
581 _state.pick_set_name(child->id());
582
583 Vec3d p0 = pose->globalTranslation(joint->id()),
584 p1 = pose->globalTranslation(child->id());
585
586 glBegin(GL_LINES);
587 glVertex(p0);
588 glVertex(p1);
589 glEnd();
590 }
591 }
592 }
593
594
595 //----------------------------------------------------------------------------
596
600 template <class SkeletonType>
601 void SkeletonNodeT<SkeletonType>::draw_bone(GLState &_state, DrawModes::DrawMode _drawMode, const Point& _parent, const Point& _axis)
602 {
603 _state.push_modelview_matrix();
604
605 // compute modelview matrix of each cone
606 GLMatrixf mv0, mv1;
607 mv0 = mv1 = _state.modelview();
608
609 computeConeMatrices(_state.modelview(), _parent, _axis, &mv0, &mv1);
610
611 // draw cones
612 _state.set_modelview(mv0);
613 cone_->draw_primitive();
614
615 _state.set_modelview(mv1);
616 cone_->draw_primitive();
617
618 _state.pop_modelview_matrix();
619 }
620
621
622 //----------------------------------------------------------------------------
623
624
628 template <class SkeletonType>
629 void SkeletonNodeT<SkeletonType>::addBoneToRenderer(IRenderer* _renderer, RenderObject& _base, const Point& _parent, const Point& _axis)
630 {
631 // define cone mesh data
632 _base.vertexDecl = cone_->getVertexDecl();
633 _base.vertexBuffer = cone_->getVBO();
634 _base.glDrawArrays(GL_TRIANGLES, 0, cone_->getNumTriangles() * 3);
635
636 // save previous modelview transform
637 GLMatrixf prevTransform = _base.modelview;
638
639 // build modelview matrix for each cone
640 GLMatrixf mv0, mv1;
641 computeConeMatrices(prevTransform, _parent, _axis, &mv0, &mv1);
642
643 // add cone objects
644 _base.modelview = mv0;
645 _renderer->addRenderObject(&_base);
646
647 _base.modelview = mv1;
648 _renderer->addRenderObject(&_base);
649
650 // restore previous modelview matrix
651 _base.modelview = prevTransform;
652 }
653
654
655 template <class SkeletonType>
656 void ACG::SceneGraph::SkeletonNodeT<SkeletonType>::computeConeMatrices( const GLMatrixf& _modelView, const Point& _parent, const Point& _axis, GLMatrixf* _outCone0, GLMatrixf* _outCone1 )
657 {
658 Point midPoint = _parent + 0.1 * _axis;
659
660 *_outCone0 = _modelView;
661
662 _outCone0->translate(midPoint[0], midPoint[1], midPoint[2]);
663
664 Point direction = _axis;
665 Point z_axis(0,0,1);
666 Point rot_normal;
667 double rot_angle;
668
669 direction.normalize();
670 rot_angle = acos((z_axis | direction))*180/M_PI;
671 rot_normal = ((z_axis % direction).normalize());
672
673
674 if(fabs(rot_angle) > 0.0001 && fabs(180-rot_angle) > 0.0001)
675 _outCone0->rotate(rot_angle, rot_normal[0], rot_normal[1], rot_normal[2]);
676 else
677 _outCone0->rotate(rot_angle, 1, 0, 0);
678
679 double boneLength = _axis.norm();
680 double radius = boneLength * 0.07;
681
682 *_outCone1 = *_outCone0;
683
684 //draw the large cone from midPoint to the end of the bone
685 _outCone0->scale(radius, radius, boneLength*0.9);
686
687 //rotate 180.0 and draw the the small cone from midPoint to the start
688 _outCone1->scale(radius, radius, boneLength*0.1);
689 _outCone1->rotateX(180.0f);
690 }
691
692
693
694 //----------------------------------------------------------------------------
695
707 template <class SkeletonType>
708 void SkeletonNodeT<SkeletonType>::setActivePose(const AnimationHandle &_hAni)
709 {
710 hAni_ = _hAni;
711 }
712
713
714 //----------------------------------------------------------------------------
715
719 template <class SkeletonType>
720 AnimationHandle SkeletonNodeT<SkeletonType>::activePose()
721 {
722 return hAni_;
723 }
724
725
726 //----------------------------------------------------------------------------
727
731 template <class SkeletonType>
732 void SkeletonNodeT<SkeletonType>::showCoordFrames(bool _bVisible)
733 {
734 bCoordFramesVisible_ = _bVisible;
735 }
736
737 template <class SkeletonType>
738 bool SkeletonNodeT<SkeletonType>::coordFramesVisible()
739 {
740 return bCoordFramesVisible_;
741 }
742
743 //----------------------------------------------------------------------------
744
748 template <class SkeletonType>
749 double SkeletonNodeT<SkeletonType>::unprojectPointSize(double _pointSize, const Vec3d& _point, GLState& _state)
750 {
751 // 1. Project point to screen
752 ACG::Vec3d projected = _state.project( _point );
753
754 // 2. Shift it by the requested point size
755 // glPointSize defines the diameter but we want the radius, so we divide it by two
756 ACG::Vec3d shifted = projected;
757 shifted[0] = shifted[0] + _pointSize / 2.0 ;
758
759 // 3. un-project into 3D
760 ACG::Vec3d unProjectedShifted = _state.unproject( shifted );
761
762 // 4. The difference vector defines the radius in 3D for the sphere
763 ACG::Vec3d difference = unProjectedShifted - _point;
764
765 return difference.norm();
766 }
767
768
769 //----------------------------------------------------------------------------
770
775 template <class SkeletonType>
776 void SkeletonNodeT<SkeletonType>::getRenderObjects(IRenderer* _renderer,
777 GLState& _state,
778 const DrawModes::DrawMode& _drawMode,
779 const Material* _mat)
780 {
781 RenderObject ro;
782 ro.initFromState(&_state);
783
784 // render states
785 ro.depthTest = true;
786 ro.depthWrite = true;
787
788 ro.culling = true;
789 ro.blending = false;
790
791
792 Pose *pose = skeleton_.pose(hAni_);
793 typename SkeletonType::Iterator it;
794
795 Vec4f jointColor;
796 getJointColor(_mat->diffuseColor(), jointColor);
797
798
799 const int numJoints = skeleton_.jointCount();
800
801 // draw points
802 for (unsigned int i = 0; i < _drawMode.getNumLayers(); ++i)
803 {
804 const DrawModes::DrawModeProperties* props = _drawMode.getLayer(i);
805
806 switch (props->primitive())
807 {
808
809 case DrawModes::PRIMITIVE_POINT:
810 {
811 ro.debugName = "SkeletonNode.point";
812 ro.shaderDesc.shadeMode = SG_SHADE_UNLIT;
813
814 if (VertexDeclaration::supportsInstancedArrays())
815 {
816 /*
817 per instance data:
818
819 combined modelview matrix: 3x float4 rows
820 vertex color = emissive as rgba8_unorm
821 */
822
823 const int instanceDataSize = 4*3*4 + 4; // float4x3 + uint
824 const int instanceBufSize = numJoints * instanceDataSize;
825 if (numJoints)
826 {
827 const int numFloats = instanceBufSize/4;
828 std::vector<float> instanceData(numFloats);
829
830 // compute per instance data
831 int instanceDataOffset = 0;
832
833 for(it = skeleton_.begin(); it != skeleton_.end(); ++it)
834 {
835 Vec4f vcolor = Vec4f(0.0f, 0.0f, 0.0f, 1.0f);
836
837 // If the vertex is selected, it will be always red
838 // If it is not selected,
839 if ( (*it)->selected() )
840 vcolor = Vec4f(1.0f, 0.0f, 0.0f, 1.0f);
841 else {
842 // If it is the root joint, it will get some kind of orange color
843 // Otherwise the the Base color is used
844 if ( (*it)->isRoot() )
845 vcolor = Vec4f(1.0f,0.66f, 0.0f, 1.0f);
846 else
847 vcolor = jointColor;
848 }
849
850 Vec3d globalPosD = pose->globalTranslation( (*it)->id() );
851
852 float sphereSize = float(unprojectPointSize((double)_state.point_size(),
853 globalPosD,
854 _state));
855
856 GLMatrixf modelview = ro.modelview;
857 modelview.translate(static_cast<float>(globalPosD[0]), static_cast<float>(globalPosD[1]), static_cast<float>(globalPosD[2]));
858 modelview.scale(sphereSize, sphereSize, sphereSize);
859
860 // store matrix
861 for (int r = 0; r < 3; ++r)
862 for (int c = 0; c < 4; ++c)
863 instanceData[instanceDataOffset++] = modelview(r,c);
864
865 // store color
866 unsigned int uicolor = 0xff000000;
867 uicolor |= (unsigned int)(vcolor[0] * 255.0f) & 0x000000ff;
868 uicolor |= ((unsigned int)(vcolor[1] * 255.0f) << 8) & 0x0000ff00;
869 uicolor |= ((unsigned int)(vcolor[2] * 255.0f) << 16) & 0x00ff0000;
870
871 // union instead of pointer casting
872 union ufunion
873 {
874 unsigned int u;
875 float f;
876 } uitofloat;
877
878 uitofloat.u = uicolor;
879
880 instanceData[instanceDataOffset++] = uitofloat.f;
881 }
882
883 // store instance data in vbo
884 pointInstanceData_.bind();
885 pointInstanceData_.upload(instanceBufSize, &instanceData[0], GL_DYNAMIC_DRAW);
886 pointInstanceData_.unbind();
887
888
889 // init declaration
890 if (!pointInstanceDecl_.getNumElements())
891 {
892 pointInstanceDecl_ = *sphere_->getVertexDecl();
893
894 pointInstanceDecl_.addElement(GL_FLOAT, 4, VERTEX_USAGE_SHADER_INPUT, size_t(0), "inModelView0", 1, pointInstanceData_.id());
895 pointInstanceDecl_.addElement(GL_FLOAT, 4, VERTEX_USAGE_SHADER_INPUT, size_t(0), "inModelView1", 1, pointInstanceData_.id());
896 pointInstanceDecl_.addElement(GL_FLOAT, 4, VERTEX_USAGE_SHADER_INPUT, size_t(0), "inModelView2", 1, pointInstanceData_.id());
897 pointInstanceDecl_.addElement(GL_UNSIGNED_BYTE, 4, VERTEX_USAGE_COLOR, size_t(0), 0, 1, pointInstanceData_.id());
898 }
899
900 ro.shaderDesc.vertexColors = true;
901 ro.shaderDesc.vertexTemplateFile = "Skeleton/instanced_vs.glsl";
902
903 ro.vertexDecl = &pointInstanceDecl_;
904 ro.vertexBuffer = sphere_->getVBO();
905 ro.glDrawInstancedArrays(GL_TRIANGLES, 0, sphere_->getNumTriangles() * 3, numJoints);
906
907 _renderer->addRenderObject(&ro);
908
909 ro.shaderDesc.vertexColors = false;
910 ro.numInstances = 0;
911 ro.shaderDesc.vertexTemplateFile = "";
912 }
913 }
914 else
915 {
916 // create a separate renderobject for each joint
917
918 for(it = skeleton_.begin(); it != skeleton_.end(); ++it)
919 {
920 // If the vertex is selected, it will be always red
921 // If it is not selected,
922 if ( (*it)->selected() )
923 ro.emissive = Vec3f(1.0f, 0.0f, 0.0f);
924 else {
925 // If it is the root joint, it will get some kind of orange color
926 // Otherwise the the Base color is used
927 if ( (*it)->isRoot() )
928 ro.emissive = Vec3f(1.0f,0.66f, 0.0f);
929 else
930 ro.emissive = Vec3f(jointColor[0], jointColor[1] , jointColor[2]);
931 }
932
933
934 // simulate glPointSize( ) with sphere
935
936 const double sphereSize = unprojectPointSize((double)_state.point_size(),
937 pose->globalTranslation( (*it)->id() ),
938 _state);
939
940 sphere_->addToRenderer(_renderer, &ro, sphereSize, ACG::Vec3f(pose->globalTranslation( (*it)->id() )));
941 }
942 }
943
944
945 } break;
946
947
948 case DrawModes::PRIMITIVE_POLYGON:
949 {
950 ro.debugName = "SkeletonNode.bone";
951
952 ro.setupShaderGenFromDrawmode(props);
953
954 ro.setMaterial(_mat);
955 ACG::Vec4f baseColor = _state.ambient_color();
956 ro.emissive = ACG::Vec3f(baseColor[0],baseColor[1],baseColor[2]);
957
958
959
960 if (VertexDeclaration::supportsInstancedArrays())
961 {
962 /*
963 per instance data:
964
965 combined modelview matrix: 3x float4 rows
966 inverse transpose of modelview: 3x float3 rows
967 */
968
969 const int instanceDataFloats = 3*4 + 3*3;
970 const int instanceDataSize = instanceDataFloats * 4;
971 const int instanceBufSize = 2 * numJoints * instanceDataSize; // 2 cones per bone
972 if (numJoints)
973 {
974 const int numFloats = instanceBufSize/4;
975 std::vector<float> instanceData(numFloats);
976
977 // compute per instance data
978 int instanceDataOffset = 0;
979 GLMatrixf cone0, cone1, cone0IT, cone1IT;
980
981 for(it = skeleton_.begin(); it != skeleton_.end(); ++it)
982 {
983 //joint is the (unique) tail joint of the bone
984 Joint* joint = *it;
985 Joint* parent = joint->parent();
986
987 // root can be ignored
988 // we only want to draw bones from (parent -> joint)
989 if (parent == 0)
990 continue;
991
992 Vec3d parentPos = pose->globalTranslation(parent->id());
993 Vec3d jointPos = pose->globalTranslation(joint->id());
994
995 Vec3d boneVector = (jointPos - parentPos);
996
997 // compute cone modelview matrices
998 computeConeMatrices(ro.modelview, parentPos, boneVector, &cone0, &cone1);
999
1000 // compute inverse transpose for normal transform
1001 cone0IT = cone0;
1002 cone1IT = cone1;
1003 cone0IT.invert();
1004 cone1IT.invert();
1005
1006 // store matrices
1007 for (int r = 0; r < 3; ++r)
1008 for (int c = 0; c < 4; ++c)
1009 instanceData[instanceDataOffset++] = cone0(r,c);
1010
1011 for (int r = 0; r < 3; ++r)
1012 for (int c = 0; c < 3; ++c)
1013 instanceData[instanceDataOffset++] = cone0IT(c,r);
1014
1015 for (int r = 0; r < 3; ++r)
1016 for (int c = 0; c < 4; ++c)
1017 instanceData[instanceDataOffset++] = cone1(r,c);
1018
1019 for (int r = 0; r < 3; ++r)
1020 for (int c = 0; c < 3; ++c)
1021 instanceData[instanceDataOffset++] = cone1IT(c,r);
1022 }
1023
1024 const int numBones = instanceDataOffset / instanceDataFloats;
1025
1026 // store instance data in vbo
1027 boneInstanceData_.bind();
1028 boneInstanceData_.upload(instanceDataOffset * 4, &instanceData[0], GL_DYNAMIC_DRAW);
1029 boneInstanceData_.unbind();
1030
1031
1032 // init declaration
1033
1034 if (!boneInstanceDecl_.getNumElements())
1035 {
1036 boneInstanceDecl_ = *cone_->getVertexDecl();
1037
1038 boneInstanceDecl_.addElement(GL_FLOAT, 4, VERTEX_USAGE_SHADER_INPUT, (size_t)0, "inModelView0", 1, boneInstanceData_.id());
1039 boneInstanceDecl_.addElement(GL_FLOAT, 4, VERTEX_USAGE_SHADER_INPUT, (size_t)0, "inModelView1", 1, boneInstanceData_.id());
1040 boneInstanceDecl_.addElement(GL_FLOAT, 4, VERTEX_USAGE_SHADER_INPUT, (size_t)0, "inModelView2", 1, boneInstanceData_.id());
1041 boneInstanceDecl_.addElement(GL_FLOAT, 3, VERTEX_USAGE_SHADER_INPUT, (size_t)0, "inModelViewIT0", 1, boneInstanceData_.id());
1042 boneInstanceDecl_.addElement(GL_FLOAT, 3, VERTEX_USAGE_SHADER_INPUT, (size_t)0, "inModelViewIT1", 1, boneInstanceData_.id());
1043 boneInstanceDecl_.addElement(GL_FLOAT, 3, VERTEX_USAGE_SHADER_INPUT, (size_t)0, "inModelViewIT2", 1, boneInstanceData_.id());
1044 }
1045
1046 ro.vertexDecl = &boneInstanceDecl_;
1047 ro.vertexBuffer = cone_->getVBO();
1048 ro.glDrawInstancedArrays(GL_TRIANGLES, 0, cone_->getNumTriangles() * 3, numBones);
1049
1050 ro.shaderDesc.vertexTemplateFile = "Skeleton/instanced_wvit_vs.glsl";
1051
1052 _renderer->addRenderObject(&ro);
1053
1054 ro.numInstances = 0;
1055 ro.shaderDesc.vertexTemplateFile = "";
1056 }
1057 }
1058 else
1059 {
1060 // create separate renderobject for each bone
1061
1062 for(it = skeleton_.begin(); it != skeleton_.end(); ++it) {
1063
1064 //joint is the (unique) tail joint of the bone
1065 Joint* joint = *it;
1066 Joint* parent = joint->parent();
1067
1068 // root can be ignored
1069 // we only want to draw bones from (parent -> joint)
1070 if (parent == 0)
1071 continue;
1072
1073 Vec3d parentPos = pose->globalTranslation(parent->id());
1074 Vec3d jointPos = pose->globalTranslation(joint->id());
1075
1076 Vec3d boneVector = (jointPos - parentPos);
1077
1078 addBoneToRenderer(_renderer, ro, parentPos, boneVector);
1079 }
1080 }
1081
1082 } break;
1083
1084 default: break;
1085 }
1086 }
1087
1088
1089 // draw coordframes
1090
1091 if (bCoordFramesVisible_)
1092 {
1093 ro.shaderDesc.shadeMode = SG_SHADE_UNLIT;
1094
1095 for(it = skeleton_.begin(); it != skeleton_.end(); ++it)
1096 {
1097 unsigned int index = (*it)->id();
1098 typename SkeletonType::Matrix global = pose->globalMatrix(index);
1099 NormalizeCoordinateFrame(global);
1100
1101 // color for each arrow
1102 Vec3f colors[] = {
1103 Vec3f(0.8f, 0.2f, 0.2f),
1104 Vec3f(0.2f, 0.8f, 0.2f),
1105 Vec3f(0.2f, 0.2f, 0.8f)
1106 };
1107
1108 Point points[] = {
1109 Point(fFrameSize_, 0, 0),
1110 Point(0, fFrameSize_, 0),
1111 Point(0, 0, fFrameSize_)
1112 };
1113
1114
1115 // simulate glLineWidth(3) with cylinder
1116 float lineWidth = (float)unprojectPointSize(3.0f, pose->globalTranslation(index), _state);
1117
1118 // glPointSize(6)
1119 float sphereSize = (float)unprojectPointSize(6.0f, pose->globalTranslation(index), _state);
1120
1121 // draw coordframe arrows
1122 for (int i = 0; i < 3; ++i)
1123 {
1124 ro.emissive = colors[i];
1125
1126 // cylinder start and end points
1127 Vec3f vstart = (Vec3f)pose->globalTranslation(index);
1128 Vec3f vend = (Vec3f)global.transform_point(points[i]);
1129
1130 Vec3f vdir = vend - vstart;
1131 float height = vdir.length();
1132
1133 cylinder_->addToRenderer(_renderer, &ro, height, vstart, vdir, lineWidth);
1134 sphere_->addToRenderer(_renderer, &ro, sphereSize, vend);
1135 }
1136 }
1137
1138
1139
1140 }
1141
1142
1143 }
1144
1145
1146
1147
1148
1149
1150 //=============================================================================
1151 } // namespace SceneGraph
1152 } // namespace ACG
1153 //=============================================================================
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::GLState::enable
static void enable(GLenum _cap, bool _warnRemoved=true)
replaces glEnable, but supports locking
Definition: GLState.cc:1507
ACG::glColor
void glColor(const Vec3f &_v)
Wrapper: glColor for Vec3f.
Definition: gl.hh:144
ACG::RenderObject::initFromState
void initFromState(GLState *_glState)
Initializes a RenderObject instance.
Definition: RenderObject.cc:61
ACG::GLState::pop_modelview_matrix
void pop_modelview_matrix()
pop modelview matrix
Definition: GLState.cc:1026
ACG::GLState::shadeModel
static void shadeModel(GLenum _mode)
replaces glShadeModel, supports locking
Definition: GLState.cc:1729
ACG::GLState::specular_color
const Vec4f & specular_color() const
get specular color
Definition: GLState.hh:941
JointT::id
size_t id() const
returns the joint id
Definition: JointT_impl.hh:97
ACG::VERTEX_USAGE_SHADER_INPUT
defined by user via VertexElement::shaderInputName_
Definition: VertexDeclaration.hh:71
ACG::GLState::set_diffuse_color
void set_diffuse_color(const Vec4f &_col)
set diffuse color
Definition: GLState.cc:722
ACG::GLState
Definition: GLState.hh:213
ACG::GLState::point_size
float point_size() const
get point size
Definition: GLState.hh:970
ACG::GLMatrixT::rotateX
void rotateX(Scalar _angle, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with a rotation matrix (angle in degree, x-axis)
Definition: GLMatrixT.hh:192
ACG
Namespace providing different geometric functions concerning angles.
Definition: BaseObjectData.hh:68
ACG::GLState::project
Vec3d project(const Vec3d &_point) const
project point in world coordinates to window coordinates
Definition: GLState.cc:640
ACG::Vec4f
VectorT< float, 4 > Vec4f
Definition: VectorT.hh:138
ACG::GLCone
Definition: GLPrimitives.hh:169
ACG::GLState::base_color
const Vec4f & base_color() const
get base color (used when lighting is off)
Definition: GLState.hh:926
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
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::RenderObject::vertexBuffer
GLuint vertexBuffer
VBO, IBO ids, ignored if VAO is provided.
Definition: RenderObject.hh:162
ACG::GLState::diffuse_color
const Vec4f & diffuse_color() const
get diffuse color
Definition: GLState.hh:936
ACG::IRenderer
Definition: IRenderer.hh:78
SceneGraph
Definition: QtPrincipalAxisDialog.hh:67
JointT::end
ChildIter end()
Returns the end iterator for the joints children.
Definition: JointT_impl.hh:186
ACG::SceneGraph::PickTarget
PickTarget
What target to use for picking.
Definition: PickTarget.hh:73
ACG::GLState::unproject
Vec3d unproject(const Vec3d &_winPoint) const
unproject point in window coordinates _winPoint to world coordinates
Definition: GLState.cc:651
ACG::Matrix4x4T::invert
bool invert()
matrix inversion (returns true on success)
Definition: Matrix4x4T_impl.hh:291
ACG::GLState::push_modelview_matrix
void push_modelview_matrix()
push modelview matrix
Definition: GLState.cc:1010
ACG::GLState::set_modelview
void set_modelview(const GLMatrixd &_m)
set modelview
Definition: GLState.hh:728
ACG::SceneGraph::Material::diffuseColor
void diffuseColor(const Vec4f &_d)
set the diffuse color.
Definition: MaterialNode.hh:180
JointT
Represents a single joint in the skeleton.
Definition: JointT.hh:60
ACG::GLState::disable
static void disable(GLenum _cap, bool _warnRemoved=true)
replaces glDisable, but supports locking
Definition: GLState.cc:1527
ACG::Vec3f
VectorT< float, 3 > Vec3f
Definition: VectorT.hh:119
ACG::SceneGraph::SkeletonNodeT::SkeletonNodeT
SkeletonNodeT(SkeletonType &_skeleton, BaseNode *_parent=0, std::string _name="<SkeletonNode>")
Constructor.
Definition: SkeletonNodeT_impl.hh:75
ACG::GLMatrixT< float >
ACG::GLState::set_ambient_color
void set_ambient_color(const Vec4f &_col)
set ambient color
Definition: GLState.cc:707
ACG::GLState::pick_set_maximum
bool pick_set_maximum(size_t _idx)
Set the maximal number of primitives/components of your object.
Definition: GLState.cc:1051
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
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::numInstances
GLsizei numInstances
Definition: RenderObject.hh:204
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::GLSphere
Definition: GLPrimitives.hh:139
ACG::SceneGraph::BaseNode
Definition: BaseNode.hh:104
ACG::glVertex
void glVertex(const Vec2i &_v)
Wrapper: glVertex for Vec2i.
Definition: gl.hh:95
ACG::GLState::set_specular_color
void set_specular_color(const Vec4f &_col)
set specular color
Definition: GLState.cc:737
ACG::SceneGraph::DrawModes::DrawModeProperties
DrawModeProperties stores a set of properties that defines, how to render an object.
Definition: DrawModes.hh:177
ACG::GLState::set_color
void set_color(const Vec4f &_col)
set color
Definition: GLState.cc:691
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::SceneGraph::DrawModes::DrawMode
Specifies a DrawMode.
Definition: DrawModes.hh:288
ACG::VERTEX_USAGE_COLOR
"inColor"
Definition: VertexDeclaration.hh:68
OpenMesh::VectorT::length
auto length() const -> decltype(std::declval< VectorT< S, DIM >>().norm())
compute squared euclidean norm
Definition: Vector11T.hh:423
JointT::parent
Joint * parent()
Returns the parent joint.
Definition: JointT_impl.hh:156
ACG::GLState::pick_set_name
void pick_set_name(size_t _idx)
sets the current name/color (like glLoadName(_idx))
Definition: GLState.cc:1061
ACG::SceneGraph::SkeletonNodeT
Definition: SkeletonNodeT.hh:77
ACG::SceneGraph::SkeletonNodeT::computeConeMatrices
void computeConeMatrices(const GLMatrixf &_modelView, const Point &_parent, const Point &_axis, GLMatrixf *_outCone0, GLMatrixf *_outCone1)
Helper function to compute modelview matrices for the two cones composing a bone. ...
Definition: SkeletonNodeT_impl.hh:656
ACG::GLState::modelview
const GLMatrixd & modelview() const
get modelview matrix
Definition: GLState.hh:791
ACG::RenderObject::setupShaderGenFromDrawmode
void setupShaderGenFromDrawmode(const SceneGraph::DrawModes::DrawModeProperties *_props)
Fills out ShaderGenDesc parameters based on Drawmode properties.
Definition: RenderObject.cc:137
ACG::GLState::line_width
float line_width() const
get line width
Definition: GLState.hh:975
ACG::SceneGraph::DrawModes::DrawMode::getLayer
const DrawModeProperties * getLayer(unsigned int _i) const
returns the property set at layer i
Definition: DrawModes.cc:535
ACG::GLCylinder
Definition: GLPrimitives.hh:218
OpenMesh::VectorT::normalize
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM >>().norm())
Definition: Vector11T.hh:434
ACG::RenderObject
Interface class between scenegraph and renderer.
Definition: RenderObject.hh:98
ACG::SceneGraph::DrawModes::DrawMode::getNumLayers
size_t getNumLayers() const
returns the layer count
Definition: DrawModes.cc:531
ACG::SceneGraph::Material
Definition: MaterialNode.hh:79
AnimationHandle
A handle used to refer to an animation or to a specific frame in an animation.
Definition: AnimationHandle.hh:47
ACG::GLState::ambient_color
const Vec4f & ambient_color() const
get ambient color
Definition: GLState.hh:931
ACG::RenderObject::modelview
GLMatrixd modelview
Modelview transform.
Definition: RenderObject.hh:138
JointT::begin
ChildIter begin()
Returns an iterator on the joints children.
Definition: JointT_impl.hh:175