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>
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>
118 {
119  return skeleton_;
120 }
121 
122 
123 //------------------------------------------------------------------------------
124 
128 template <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 }
145 
146 
147 //----------------------------------------------------------------------------
148 
152 template <class SkeletonType>
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>
165  return fFrameSize_;
166 }
167 
168 
169 //----------------------------------------------------------------------------
170 
171 
175 template <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 
200 template <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 
261 template <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 
313 template <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)
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>
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>
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>
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>
709 {
710  hAni_ = _hAni;
711 }
712 
713 
714 //----------------------------------------------------------------------------
715 
719 template <class SkeletonType>
721 {
722  return hAni_;
723 }
724 
725 
726 //----------------------------------------------------------------------------
727 
731 template <class SkeletonType>
733 {
734  bCoordFramesVisible_ = _bVisible;
735 }
736 
737 template <class SkeletonType>
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>
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 //=============================================================================
void rotate(Scalar angle, Scalar x, Scalar y, Scalar z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
static void enable(GLenum _cap, bool _warnRemoved=true)
replaces glEnable, but supports locking
Definition: GLState.cc:1507
void glColor(const Vec3f &_v)
Wrapper: glColor for Vec3f.
Definition: gl.hh:144
void initFromState(GLState *_glState)
Initializes a RenderObject instance.
Definition: RenderObject.cc:61
void pop_modelview_matrix()
pop modelview matrix
Definition: GLState.cc:1026
static void shadeModel(GLenum _mode)
replaces glShadeModel, supports locking
Definition: GLState.cc:1729
const Vec4f & specular_color() const
get specular color
Definition: GLState.hh:941
size_t id() const
returns the joint id
Definition: JointT_impl.hh:97
defined by user via VertexElement::shaderInputName_
void set_diffuse_color(const Vec4f &_col)
set diffuse color
Definition: GLState.cc:722
float point_size() const
get point size
Definition: GLState.hh:970
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
Namespace providing different geometric functions concerning angles.
Vec3d project(const Vec3d &_point) const
project point in world coordinates to window coordinates
Definition: GLState.cc:640
VectorT< float, 4 > Vec4f
Definition: VectorT.hh:138
const Vec4f & base_color() const
get base color (used when lighting is off)
Definition: GLState.hh:926
ShaderGenDesc shaderDesc
Drawmode and other shader params.
void translate(Scalar _x, Scalar _y, Scalar _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with translation matrix (x,y,z)
vector_type & maximize(const vector_type &_rhs)
maximize values: same as *this = max(*this, _rhs), but faster
Definition: Vector11T.hh:568
GLuint vertexBuffer
VBO, IBO ids, ignored if VAO is provided.
const Vec4f & diffuse_color() const
get diffuse color
Definition: GLState.hh:936
ChildIter end()
Returns the end iterator for the joints children.
Definition: JointT_impl.hh:186
PickTarget
What target to use for picking.
Definition: PickTarget.hh:73
Vec3d unproject(const Vec3d &_winPoint) const
unproject point in window coordinates _winPoint to world coordinates
Definition: GLState.cc:651
bool invert()
matrix inversion (returns true on success)
void push_modelview_matrix()
push modelview matrix
Definition: GLState.cc:1010
void set_modelview(const GLMatrixd &_m)
set modelview
Definition: GLState.hh:728
void diffuseColor(const Vec4f &_d)
set the diffuse color.
Represents a single joint in the skeleton.
Definition: JointT.hh:60
static void disable(GLenum _cap, bool _warnRemoved=true)
replaces glDisable, but supports locking
Definition: GLState.cc:1527
VectorT< float, 3 > Vec3f
Definition: VectorT.hh:119
SkeletonNodeT(SkeletonType &_skeleton, BaseNode *_parent=0, std::string _name="<SkeletonNode>")
Constructor.
void set_ambient_color(const Vec4f &_col)
set ambient color
Definition: GLState.cc:707
bool pick_set_maximum(size_t _idx)
Set the maximal number of primitives/components of your object.
Definition: GLState.cc:1051
void scale(Scalar _x, Scalar _y, Scalar _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with scaling matrix (x,y,z)
vector_type & minimize(const vector_type &_rhs)
minimize values: same as *this = min(*this, _rhs), but faster
Definition: Vector11T.hh:540
const VertexDeclaration * vertexDecl
Defines the vertex buffer layout, ignored if VAO is provided.
auto norm() const -> decltype(std::sqrt(std::declval< VectorT< S, DIM >>().sqrnorm()))
compute euclidean norm
Definition: Vector11T.hh:414
void glVertex(const Vec2i &_v)
Wrapper: glVertex for Vec2i.
Definition: gl.hh:95
void set_specular_color(const Vec4f &_col)
set specular color
Definition: GLState.cc:737
DrawModeProperties stores a set of properties that defines, how to render an object.
Definition: DrawModes.hh:177
void set_color(const Vec4f &_col)
set color
Definition: GLState.cc:691
virtual void addRenderObject(RenderObject *_renderObject)
Callback for the scenegraph nodes, which send new render objects via this function.
Definition: IRenderer.cc:104
auto length() const -> decltype(std::declval< VectorT< S, DIM >>().norm())
compute squared euclidean norm
Definition: Vector11T.hh:423
Joint * parent()
Returns the parent joint.
Definition: JointT_impl.hh:156
void pick_set_name(size_t _idx)
sets the current name/color (like glLoadName(_idx))
Definition: GLState.cc:1061
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. ...
const GLMatrixd & modelview() const
get modelview matrix
Definition: GLState.hh:791
void setupShaderGenFromDrawmode(const SceneGraph::DrawModes::DrawModeProperties *_props)
Fills out ShaderGenDesc parameters based on Drawmode properties.
float line_width() const
get line width
Definition: GLState.hh:975
const DrawModeProperties * getLayer(unsigned int _i) const
returns the property set at layer i
Definition: DrawModes.cc:535
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM >>().norm())
Definition: Vector11T.hh:434
Interface class between scenegraph and renderer.
Definition: RenderObject.hh:98
size_t getNumLayers() const
returns the layer count
Definition: DrawModes.cc:531
A handle used to refer to an animation or to a specific frame in an animation.
const Vec4f & ambient_color() const
get ambient color
Definition: GLState.hh:931
GLMatrixd modelview
Modelview transform.
ChildIter begin()
Returns an iterator on the joints children.
Definition: JointT_impl.hh:175