Developer Documentation
Loading...
Searching...
No Matches
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
65namespace ACG {
66namespace SceneGraph {
67
68//== IMPLEMENTATION ==========================================================
69
70
74template <class SkeletonType>
75SkeletonNodeT<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
92//------------------------------------------------------------------------------
93
97template <class SkeletonType>
99{
100 if (sphere_)
101 delete sphere_;
102
103 if (cone_)
104 delete cone_;
106 if (cylinder_)
107 delete cylinder_;
108}
109
111//------------------------------------------------------------------------------
112
116template <class SkeletonType>
119 return skeleton_;
120}
121
122
123//------------------------------------------------------------------------------
124
128template <class SkeletonType>
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}
146
147//----------------------------------------------------------------------------
152template <class SkeletonType>
157}
158
159
160//----------------------------------------------------------------------------
161
162
163template <class SkeletonType>
165 return fFrameSize_;
166}
167
168
169//----------------------------------------------------------------------------
170
171
175template <class SkeletonType>
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
200template <class SkeletonType>
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
261template <class SkeletonType>
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
313template <class SkeletonType>
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)
411 {
412
413 if ( (_drawMode & DrawModes::SOLID_FLAT_SHADED)
415
417 ACG::GLState::enable(GL_LIGHTING);
418 }
419
420 if (_drawMode & DrawModes::SOLID_FACES_COLORED)
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
490template <class SkeletonType>
491void 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
511template <class SkeletonType>
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
545template <class SkeletonType>
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
569template <class SkeletonType>
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
600template <class SkeletonType>
601void 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
628template <class SkeletonType>
629void 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
655template <class SkeletonType>
656void 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
707template <class SkeletonType>
709{
710 hAni_ = _hAni;
711}
712
713
714//----------------------------------------------------------------------------
715
719template <class SkeletonType>
724
725
726//----------------------------------------------------------------------------
727
731template <class SkeletonType>
733{
734 bCoordFramesVisible_ = _bVisible;
735}
736
737template <class SkeletonType>
739{
740 return bCoordFramesVisible_;
741}
742
743//----------------------------------------------------------------------------
744
748template <class SkeletonType>
749double 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
775template <class SkeletonType>
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
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(), pose->globalTranslation( (*it)->id() ), _state);
937
938 sphere_->addToRenderer(_renderer, &ro, sphereSize, ACG::Vec3f(pose->globalTranslation( (*it)->id() )));
939 }
940 }
941
942
943 } break;
944
945
946 case DrawModes::PRIMITIVE_POLYGON:
947 {
948 ro.debugName = "SkeletonNode.bone";
949
951
952 ro.setMaterial(_mat);
953 ACG::Vec4f baseColor = _state.ambient_color();
954 ro.emissive = ACG::Vec3f(baseColor[0],baseColor[1],baseColor[2]);
955
956
957
959 {
960 /*
961 per instance data:
962
963 combined modelview matrix: 3x float4 rows
964 inverse transpose of modelview: 3x float3 rows
965 */
966
967 const int instanceDataFloats = 3*4 + 3*3;
968 const int instanceDataSize = instanceDataFloats * 4;
969 const int instanceBufSize = 2 * numJoints * instanceDataSize; // 2 cones per bone
970 if (numJoints)
971 {
972 const int numFloats = instanceBufSize/4;
973 std::vector<float> instanceData(numFloats);
974
975 // compute per instance data
976 int instanceDataOffset = 0;
977 GLMatrixf cone0, cone1, cone0IT, cone1IT;
978
979 for(it = skeleton_.begin(); it != skeleton_.end(); ++it)
980 {
981 //joint is the (unique) tail joint of the bone
982 Joint* joint = *it;
983 Joint* parent = joint->parent();
984
985 // root can be ignored
986 // we only want to draw bones from (parent -> joint)
987 if (parent == 0)
988 continue;
989
990 Vec3d parentPos = pose->globalTranslation(parent->id());
991 Vec3d jointPos = pose->globalTranslation(joint->id());
992
993 Vec3d boneVector = (jointPos - parentPos);
994
995 // compute cone modelview matrices
996 computeConeMatrices(ro.modelview, parentPos, boneVector, &cone0, &cone1);
997
998 // compute inverse transpose for normal transform
999 cone0IT = cone0;
1000 cone1IT = cone1;
1001 cone0IT.invert();
1002 cone1IT.invert();
1003
1004 // store matrices
1005 for (int r = 0; r < 3; ++r)
1006 for (int c = 0; c < 4; ++c)
1007 instanceData[instanceDataOffset++] = cone0(r,c);
1008
1009 for (int r = 0; r < 3; ++r)
1010 for (int c = 0; c < 3; ++c)
1011 instanceData[instanceDataOffset++] = cone0IT(c,r);
1012
1013 for (int r = 0; r < 3; ++r)
1014 for (int c = 0; c < 4; ++c)
1015 instanceData[instanceDataOffset++] = cone1(r,c);
1016
1017 for (int r = 0; r < 3; ++r)
1018 for (int c = 0; c < 3; ++c)
1019 instanceData[instanceDataOffset++] = cone1IT(c,r);
1020 }
1021
1022 const int numBones = instanceDataOffset / instanceDataFloats;
1023
1024 // store instance data in vbo
1025 boneInstanceData_.bind();
1026 boneInstanceData_.upload(instanceDataOffset * 4, &instanceData[0], GL_DYNAMIC_DRAW);
1027 boneInstanceData_.unbind();
1028
1029
1030 // init declaration
1031
1032 if (!boneInstanceDecl_.getNumElements())
1033 {
1034 boneInstanceDecl_ = *cone_->getVertexDecl();
1035
1036 boneInstanceDecl_.addElement(GL_FLOAT, 4, VERTEX_USAGE_SHADER_INPUT, static_cast<size_t>(0), "inModelView0", 1, boneInstanceData_.id());
1037 boneInstanceDecl_.addElement(GL_FLOAT, 4, VERTEX_USAGE_SHADER_INPUT, static_cast<size_t>(0), "inModelView1", 1, boneInstanceData_.id());
1038 boneInstanceDecl_.addElement(GL_FLOAT, 4, VERTEX_USAGE_SHADER_INPUT, static_cast<size_t>(0), "inModelView2", 1, boneInstanceData_.id());
1039 boneInstanceDecl_.addElement(GL_FLOAT, 3, VERTEX_USAGE_SHADER_INPUT, static_cast<size_t>(0), "inModelViewIT0", 1, boneInstanceData_.id());
1040 boneInstanceDecl_.addElement(GL_FLOAT, 3, VERTEX_USAGE_SHADER_INPUT, static_cast<size_t>(0), "inModelViewIT1", 1, boneInstanceData_.id());
1041 boneInstanceDecl_.addElement(GL_FLOAT, 3, VERTEX_USAGE_SHADER_INPUT, static_cast<size_t>(0), "inModelViewIT2", 1, boneInstanceData_.id());
1042 }
1043
1044 ro.vertexDecl = &boneInstanceDecl_;
1045 ro.vertexBuffer = cone_->getVBO();
1046 ro.glDrawInstancedArrays(GL_TRIANGLES, 0, cone_->getNumTriangles() * 3, numBones);
1047
1048 ro.shaderDesc.vertexTemplateFile = "Skeleton/instanced_wvit_vs.glsl";
1049
1050 _renderer->addRenderObject(&ro);
1051
1052 ro.numInstances = 0;
1053 ro.shaderDesc.vertexTemplateFile = "";
1054 }
1055 }
1056 else
1057 {
1058 // create separate renderobject for each bone
1059
1060 for(it = skeleton_.begin(); it != skeleton_.end(); ++it) {
1061
1062 //joint is the (unique) tail joint of the bone
1063 Joint* joint = *it;
1064 Joint* parent = joint->parent();
1065
1066 // root can be ignored
1067 // we only want to draw bones from (parent -> joint)
1068 if (parent == 0)
1069 continue;
1070
1071 Vec3d parentPos = pose->globalTranslation(parent->id());
1072 Vec3d jointPos = pose->globalTranslation(joint->id());
1073
1074 Vec3d boneVector = (jointPos - parentPos);
1075
1076 addBoneToRenderer(_renderer, ro, parentPos, boneVector);
1077 }
1078 }
1079
1080 } break;
1081
1082 default: break;
1083 }
1084 }
1085
1086
1087 // draw coordframes
1088
1089 if (bCoordFramesVisible_)
1090 {
1091 ro.shaderDesc.shadeMode = SG_SHADE_UNLIT;
1092
1093 for(it = skeleton_.begin(); it != skeleton_.end(); ++it)
1094 {
1095 unsigned int index = (*it)->id();
1096 typename SkeletonType::Matrix global = pose->globalMatrix(index);
1097 NormalizeCoordinateFrame(global);
1098
1099 // color for each arrow
1100 Vec3f colors[] = {
1101 Vec3f(0.8f, 0.2f, 0.2f),
1102 Vec3f(0.2f, 0.8f, 0.2f),
1103 Vec3f(0.2f, 0.2f, 0.8f)
1104 };
1105
1106 Point points[] = {
1107 Point(fFrameSize_, 0, 0),
1108 Point(0, fFrameSize_, 0),
1109 Point(0, 0, fFrameSize_)
1110 };
1111
1112
1113 // simulate glLineWidth(3) with cylinder
1114 float lineWidth = (float)unprojectPointSize(3.0f, pose->globalTranslation(index), _state);
1115
1116 // glPointSize(6)
1117 float sphereSize = (float)unprojectPointSize(6.0f, pose->globalTranslation(index), _state);
1118
1119 // draw coordframe arrows
1120 for (int i = 0; i < 3; ++i)
1121 {
1122 ro.emissive = colors[i];
1123
1124 // cylinder start and end points
1125 Vec3f vstart = (Vec3f)pose->globalTranslation(index);
1126 Vec3f vend = (Vec3f)global.transform_point(points[i]);
1127
1128 Vec3f vdir = vend - vstart;
1129 float height = vdir.length();
1130
1131 cylinder_->addToRenderer(_renderer, &ro, height, vstart, vdir, lineWidth);
1132 sphere_->addToRenderer(_renderer, &ro, sphereSize, vend);
1133 }
1134 }
1135
1136
1137
1138 }
1139
1140
1141}
1142
1143
1144
1145
1146
1147
1148//=============================================================================
1149} // namespace SceneGraph
1150} // namespace ACG
1151//=============================================================================
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 rotateX(Scalar _angle, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with a rotation matrix (angle in degree, x-axis)
Definition GLMatrixT.hh:190
void translate(Scalar _x, Scalar _y, Scalar _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with translation matrix (x,y,z)
void set_specular_color(const Vec4f &_col)
set specular color
Definition GLState.cc:737
void set_ambient_color(const Vec4f &_col)
set ambient color
Definition GLState.cc:707
void pop_modelview_matrix()
pop modelview matrix
Definition GLState.cc:1026
static void enable(GLenum _cap, bool _warnRemoved=true)
replaces glEnable, but supports locking
Definition GLState.cc:1507
const Vec4f & specular_color() const
get specular color
Definition GLState.hh:966
const GLMatrixd & modelview() const
get modelview matrix
Definition GLState.hh:816
void pick_set_name(size_t _idx)
sets the current name/color (like glLoadName(_idx))
Definition GLState.cc:1061
const Vec4f & base_color() const
get base color (used when lighting is off)
Definition GLState.hh:951
bool pick_set_maximum(size_t _idx)
Set the maximal number of primitives/components of your object.
Definition GLState.cc:1051
void set_modelview(const GLMatrixd &_m)
set modelview
Definition GLState.hh:753
Vec3d unproject(const Vec3d &_winPoint) const
unproject point in window coordinates _winPoint to world coordinates
Definition GLState.cc:651
Vec3d project(const Vec3d &_point) const
project point in world coordinates to window coordinates
Definition GLState.cc:640
void set_color(const Vec4f &_col)
set color
Definition GLState.cc:691
static void disable(GLenum _cap, bool _warnRemoved=true)
replaces glDisable, but supports locking
Definition GLState.cc:1527
const Vec4f & ambient_color() const
get ambient color
Definition GLState.hh:956
float line_width() const
get line width
Definition GLState.hh:1000
static void shadeModel(GLenum _mode)
replaces glShadeModel, supports locking
Definition GLState.cc:1729
const Vec4f & diffuse_color() const
get diffuse color
Definition GLState.hh:961
void push_modelview_matrix()
push modelview matrix
Definition GLState.cc:1010
void set_diffuse_color(const Vec4f &_col)
set diffuse color
Definition GLState.cc:722
float point_size() const
get point size
Definition GLState.hh:995
virtual void addRenderObject(RenderObject *_renderObject)
Callback for the scenegraph nodes, which send new render objects via this function.
Definition IRenderer.cc:104
bool invert()
matrix inversion (returns true on success)
void multipassNodeSetActive(const unsigned int _i, bool _active)
Set Node status to traverse in a specific pass.
Definition BaseNode.cc:228
DrawModeProperties stores a set of properties that defines, how to render an object.
Definition DrawModes.hh:177
const DrawModeProperties * getLayer(unsigned int _i) const
returns the property set at layer i
Definition DrawModes.cc:525
size_t getNumLayers() const
returns the layer count
Definition DrawModes.cc:521
void diffuseColor(const Vec4f &_d)
set the diffuse color.
void showCoordFrames(bool _bVisible=true)
Toggle visibility of coordinate frames for all joints.
void draw(GLState &_state, const DrawModes::DrawMode &_drawMode) override
Renders the nodes contents using the given render state and draw mode.
void draw_bone(GLState &_state, DrawModes::DrawMode _drawMode, const Point &_parent, const Point &_axis)
Helper function to draw the bones.
void pick(GLState &_state, PickTarget _target) override
Renders the node in picking mode, restricted to the node components given by _target.
void boundingBox(Vec3d &_bbMin, Vec3d &_bbMax) override
Returns the bounding box of this node.
AnimationHandle activePose()
Get the pose that is used for rendering.
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.
void addBoneToRenderer(IRenderer *_renderer, RenderObject &_base, const Point &_parent, const Point &_axis)
Helper function to create a renderobject for bones.
void setActivePose(const AnimationHandle &_hAni)
Set the pose which should be rendered.
void pick_vertices(GLState &_state)
Pick method for vertices.
void getJointColor(const Vec4f &_baseColor, Vec4f &_result)
get a joint color suitable to the baseColor
double frameSize()
returns the size of the rendered coordinate system
void pick_edges(GLState &_state)
Pick method for edges.
DrawModes::DrawMode availableDrawModes() const override
Returns available draw modes.
SkeletonNodeT(SkeletonType &_skeleton, BaseNode *_parent=nullptr, std::string _name="<SkeletonNode>")
Constructor.
void getRenderObjects(IRenderer *_renderer, GLState &_state, const DrawModes::DrawMode &_drawMode, const Material *_mat) override
Adds renderobjects to renderer for flexible shader pipeline.
void HSVtoRGB(const Vec4f &_HSV, Vec4f &_RGB)
Convert HSV color to RGB.
void NormalizeCoordinateFrame(Matrix &_mat)
Normalizes a coordinate frame defined by the given matrix.
void RGBtoHSV(const Vec4f &_RGB, Vec4f &_HSV)
Convert RGB color to HSV.
double unprojectPointSize(double _pointSize, const Vec3d &_point, GLState &_state)
Simulate glPointSize(12) with a sphere.
SkeletonType & skeleton()
Returns a pointer to the skeleton.
static bool supportsInstancedArrays()
A handle used to refer to an animation or to a specific frame in an animation.
Represents a single joint in the skeleton.
Definition JointT.hh:61
ChildIter end()
Returns the end iterator for the joints children.
size_t id() const
returns the joint id
ChildIter begin()
Returns an iterator on the joints children.
Joint * parent()
Returns the parent joint.
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 length() const -> decltype(std::declval< VectorT< S, DIM > >().norm())
compute squared euclidean norm
Definition Vector11T.hh:443
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_FACES_COLORED
draw colored, but not lighted faces using face colors
Definition DrawModes.cc:84
DrawMode SOLID_FACES_COLORED_FLAT_SHADED
draw flat shaded and colored faces (requires face normals and colors)
Definition DrawModes.cc:94
DrawMode WIREFRAME
draw wireframe
Definition DrawModes.cc:78
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_EDGE
picks edges (may not be implemented for all nodes)
Definition PickTarget.hh:80
@ PICK_ANYTHING
pick any of the prior targets (should be implemented for all nodes)
Definition PickTarget.hh:84
@ PICK_VERTEX
picks verices (may not be implemented for all nodes)
Definition PickTarget.hh:82
Namespace providing different geometric functions concerning angles.
void glColor(const Vec3f &_v)
Wrapper: glColor for Vec3f.
Definition gl.hh:144
VectorT< float, 4 > Vec4f
Definition VectorT.hh:138
VectorT< float, 3 > Vec3f
Definition VectorT.hh:119
void glVertex(const Vec2i &_v)
Wrapper: glVertex for Vec2i.
Definition gl.hh:95
@ VERTEX_USAGE_COLOR
"inColor"
@ VERTEX_USAGE_SHADER_INPUT
defined by user via VertexElement::shaderInputName_
Interface class between scenegraph and renderer.
ShaderGenDesc shaderDesc
Drawmode and other shader params.
const VertexDeclaration * vertexDecl
Defines the vertex buffer layout, ignored if VAO is provided.
void setupShaderGenFromDrawmode(const SceneGraph::DrawModes::DrawModeProperties *_props)
Fills out ShaderGenDesc parameters based on Drawmode properties.
GLMatrixd modelview
Modelview transform.
GLuint vertexBuffer
VBO, IBO ids, ignored if VAO is provided.
void initFromState(GLState *_glState)
Initializes a RenderObject instance.