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