59 #define ACG_SKELETONNODET_C
63 #include "SkeletonNodeT.hh"
64 #include <ACG/GL/gl.hh>
65 #include <ACG/GL/IRenderer.hh>
72 namespace SceneGraph {
80 template <
class SkeletonType>
83 bCoordFramesVisible_(false),
93 cone_ =
new ACG::GLCone(slices_, stacks_, 1.0f, 0.0f,
false,
false);
103 template <
class SkeletonType>
122 template <
class SkeletonType>
134 template <
class SkeletonType>
137 if(skeleton_.jointCount() == 0)
140 Pose *pose = skeleton_.pose(hAni_);
141 typename SkeletonType::Iterator it;
142 for(it = skeleton_.begin(); it != skeleton_.end(); ++it)
144 _bbMin.minimize( (
Vec3d)pose->globalTranslation((*it)->id()) );
145 _bbMax.maximize( (
Vec3d)pose->globalTranslation((*it)->id()) );
149 fFrameSize_ = (_bbMin - _bbMax).norm() * 0.07;
158 template <
class SkeletonType>
169 template <
class SkeletonType>
181 template <
class SkeletonType>
185 for(
int i = 0; i < 3; ++i)
187 for(
int x = 0; x < 3; ++x)
190 for(
int x = 0; x < 3; ++x)
206 template <
class SkeletonType>
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));
267 template <
class SkeletonType>
270 double maxC = _RGB[2];
275 double minC = _RGB[2];
281 double delta = maxC - minC;
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;
298 else if (_RGB[1] == maxC)
319 template <
class SkeletonType>
325 glPushAttrib(GL_ENABLE_BIT);
327 Pose *pose = skeleton_.pose(hAni_);
328 typename SkeletonType::Iterator it;
346 for(it = skeleton_.begin(); it != skeleton_.end(); ++it)
350 if ( (*it)->selected() )
359 if ( (*it)->isRoot() )
377 const double sphereSize = unprojectPointSize((
double)_state.
point_size(),
378 pose->globalTranslation( (*it)->id() ), _state);
380 sphere_->draw(_state,sphereSize,
ACG::Vec3f(pose->globalTranslation( (*it)->id() )));
389 if(bCoordFramesVisible_)
394 for(it = skeleton_.begin(); it != skeleton_.end(); ++it)
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_)) );
426 if (_drawMode & DrawModes::SOLID_FACES_COLORED)
433 for(it = skeleton_.begin(); it != skeleton_.end(); ++it) {
446 glColor4fv( &baseColor[0] );
448 Vec3d parentPos = pose->globalTranslation(parent->
id());
449 Vec3d jointPos = pose->globalTranslation(joint->
id());
451 Vec3d boneVector = (jointPos - parentPos);
453 draw_bone(_state, _drawMode, parentPos, boneVector);
458 if(bCoordFramesVisible_)
465 for(it = skeleton_.begin(); it != skeleton_.end(); ++it)
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_)) );
496 template <
class SkeletonType>
500 RGBtoHSV(_baseColor, hsv);
503 if (hsv[0] > 1.0) hsv[0] -= 1.0;
506 if (hsv[1] > 1.0) hsv[1] = 1.0;
508 HSVtoRGB(hsv, _result);
517 template <
class SkeletonType>
520 unsigned int n_of_vertices = skeleton_.jointCount();
526 pick_vertices(_state);
536 pick_vertices(_state);
551 template <
class SkeletonType>
555 typename SkeletonType::Pose* pose = skeleton_.pose(hAni_);
556 for(
typename SkeletonType::Iterator it = skeleton_.begin(); it != skeleton_.end(); ++it)
558 typename SkeletonType::Joint *joint = *it;
561 Vec3d p = pose->globalTranslation(joint->id());
575 template <
class SkeletonType>
579 typename SkeletonType::Pose* pose = skeleton_.pose(hAni_);
580 for(
typename SkeletonType::Iterator it = skeleton_.begin(); it != skeleton_.end(); ++it)
583 for(
typename Joint::ChildIter it_ch = joint->
begin(); it_ch != joint->
end(); ++it_ch)
585 Joint *child = *it_ch;
589 Vec3d p0 = pose->globalTranslation(joint->
id()),
590 p1 = pose->globalTranslation(child->
id());
606 template <
class SkeletonType>
615 computeConeMatrices(_state.
modelview(), _parent, _axis, &mv0, &mv1);
619 cone_->draw_primitive();
622 cone_->draw_primitive();
634 template <
class SkeletonType>
640 _base.glDrawArrays(GL_TRIANGLES, 0, cone_->getNumTriangles() * 3);
647 computeConeMatrices(prevTransform, _parent, _axis, &mv0, &mv1);
661 template <
class SkeletonType>
664 Point midPoint = _parent + 0.1 * _axis;
666 *_outCone0 = _modelView;
668 _outCone0->
translate(midPoint[0], midPoint[1], midPoint[2]);
670 Point direction = _axis;
675 direction.normalize();
676 rot_angle = acos((z_axis | direction))*180/M_PI;
677 rot_normal = ((z_axis % direction).normalize());
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]);
683 _outCone0->
rotate(rot_angle, 1, 0, 0);
685 double boneLength = _axis.norm();
686 double radius = boneLength * 0.07;
688 *_outCone1 = *_outCone0;
691 _outCone0->
scale(radius, radius, boneLength*0.9);
694 _outCone1->
scale(radius, radius, boneLength*0.1);
713 template <
class SkeletonType>
725 template <
class SkeletonType>
737 template <
class SkeletonType>
740 bCoordFramesVisible_ = _bVisible;
743 template <
class SkeletonType>
746 return bCoordFramesVisible_;
754 template <
class SkeletonType>
763 shifted[0] = shifted[0] + _pointSize / 2.0 ;
769 ACG::Vec3d difference = unProjectedShifted - _point;
771 return difference.norm();
781 template <
class SkeletonType>
792 ro.depthWrite =
true;
798 Pose *pose = skeleton_.pose(hAni_);
799 typename SkeletonType::Iterator it;
805 const int numJoints = skeleton_.jointCount();
808 for (
unsigned int i = 0; i < _drawMode.
getNumLayers(); ++i)
812 switch (props->primitive())
815 case DrawModes::PRIMITIVE_POINT:
817 ro.debugName =
"SkeletonNode.point";
829 const int instanceDataSize = 4*3*4 + 4;
830 const int instanceBufSize = numJoints * instanceDataSize;
833 const int numFloats = instanceBufSize/4;
834 std::vector<float> instanceData(numFloats);
837 int instanceDataOffset = 0;
839 for(it = skeleton_.begin(); it != skeleton_.end(); ++it)
845 if ( (*it)->selected() )
846 vcolor =
Vec4f(1.0f, 0.0f, 0.0f, 1.0f);
850 if ( (*it)->isRoot() )
851 vcolor =
Vec4f(1.0f,0.66f, 0.0f, 1.0f);
856 Vec3d globalPosD = pose->globalTranslation( (*it)->id() );
858 float sphereSize = float(unprojectPointSize((
double)_state.
point_size(),
863 modelview.
translate(globalPosD[0], globalPosD[1], globalPosD[2]);
864 modelview.
scale(sphereSize, sphereSize, sphereSize);
867 for (
int r = 0; r < 3; ++r)
868 for (
int c = 0; c < 4; ++c)
869 instanceData[instanceDataOffset++] = modelview(r,c);
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;
884 uitofloat.u = uicolor;
886 instanceData[instanceDataOffset++] = uitofloat.f;
890 pointInstanceData_.bind();
891 pointInstanceData_.upload(instanceBufSize, &instanceData[0], GL_DYNAMIC_DRAW);
892 pointInstanceData_.unbind();
896 if (!pointInstanceDecl_.getNumElements())
898 pointInstanceDecl_ = *sphere_->getVertexDecl();
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());
907 ro.
shaderDesc.vertexTemplateFile =
"Skeleton/instanced_vs.glsl";
911 ro.glDrawInstancedArrays(GL_TRIANGLES, 0, sphere_->getNumTriangles() * 3, numJoints);
924 for(it = skeleton_.begin(); it != skeleton_.end(); ++it)
928 if ( (*it)->selected() )
929 ro.emissive =
Vec3f(1.0f, 0.0f, 0.0f);
933 if ( (*it)->isRoot() )
934 ro.emissive =
Vec3f(1.0f,0.66f, 0.0f);
936 ro.emissive =
Vec3f(jointColor[0], jointColor[1] , jointColor[2]);
942 const double sphereSize = unprojectPointSize((
double)_state.
point_size(),
943 pose->globalTranslation( (*it)->id() ),
946 sphere_->addToRenderer(_renderer, &ro, sphereSize,
ACG::Vec3f(pose->globalTranslation( (*it)->id() )));
954 case DrawModes::PRIMITIVE_POLYGON:
956 ro.debugName =
"SkeletonNode.bone";
960 ro.setMaterial(_mat);
962 ro.emissive =
ACG::Vec3f(baseColor[0],baseColor[1],baseColor[2]);
975 const int instanceDataFloats = 3*4 + 3*3;
976 const int instanceDataSize = instanceDataFloats * 4;
977 const int instanceBufSize = 2 * numJoints * instanceDataSize;
980 const int numFloats = instanceBufSize/4;
981 std::vector<float> instanceData(numFloats);
984 int instanceDataOffset = 0;
985 GLMatrixf cone0, cone1, cone0IT, cone1IT;
987 for(it = skeleton_.begin(); it != skeleton_.end(); ++it)
998 Vec3d parentPos = pose->globalTranslation(parent->
id());
999 Vec3d jointPos = pose->globalTranslation(joint->
id());
1001 Vec3d boneVector = (jointPos - parentPos);
1004 computeConeMatrices(ro.
modelview, parentPos, boneVector, &cone0, &cone1);
1013 for (
int r = 0; r < 3; ++r)
1014 for (
int c = 0; c < 4; ++c)
1015 instanceData[instanceDataOffset++] = cone0(r,c);
1017 for (
int r = 0; r < 3; ++r)
1018 for (
int c = 0; c < 3; ++c)
1019 instanceData[instanceDataOffset++] = cone0IT(c,r);
1021 for (
int r = 0; r < 3; ++r)
1022 for (
int c = 0; c < 4; ++c)
1023 instanceData[instanceDataOffset++] = cone1(r,c);
1025 for (
int r = 0; r < 3; ++r)
1026 for (
int c = 0; c < 3; ++c)
1027 instanceData[instanceDataOffset++] = cone1IT(c,r);
1030 const int numBones = instanceDataOffset / instanceDataFloats;
1033 boneInstanceData_.bind();
1034 boneInstanceData_.upload(instanceDataOffset * 4, &instanceData[0], GL_DYNAMIC_DRAW);
1035 boneInstanceData_.unbind();
1040 if (!boneInstanceDecl_.getNumElements())
1042 boneInstanceDecl_ = *cone_->getVertexDecl();
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());
1054 ro.glDrawInstancedArrays(GL_TRIANGLES, 0, cone_->getNumTriangles() * 3, numBones);
1056 ro.
shaderDesc.vertexTemplateFile =
"Skeleton/instanced_wvit_vs.glsl";
1068 for(it = skeleton_.begin(); it != skeleton_.end(); ++it) {
1079 Vec3d parentPos = pose->globalTranslation(parent->
id());
1080 Vec3d jointPos = pose->globalTranslation(joint->
id());
1082 Vec3d boneVector = (jointPos - parentPos);
1084 addBoneToRenderer(_renderer, ro, parentPos, boneVector);
1097 if (bCoordFramesVisible_)
1101 for(it = skeleton_.begin(); it != skeleton_.end(); ++it)
1103 unsigned int index = (*it)->id();
1104 typename SkeletonType::Matrix global = pose->globalMatrix(index);
1105 NormalizeCoordinateFrame(global);
1109 Vec3f(0.8f, 0.2f, 0.2f),
1110 Vec3f(0.2f, 0.8f, 0.2f),
1111 Vec3f(0.2f, 0.2f, 0.8f)
1115 Point(fFrameSize_, 0, 0),
1116 Point(0, fFrameSize_, 0),
1117 Point(0, 0, fFrameSize_)
1122 float lineWidth = (float)unprojectPointSize(3.0f, pose->globalTranslation(index), _state);
1125 float sphereSize = (float)unprojectPointSize(6.0f, pose->globalTranslation(index), _state);
1128 for (
int i = 0; i < 3; ++i)
1130 ro.emissive = colors[i];
1133 Vec3f vstart = (
Vec3f)pose->globalTranslation(index);
1134 Vec3f vend = (
Vec3f)global.transform_point(points[i]);
1136 Vec3f vdir = vend - vstart;
1137 float height = vdir.length();
1139 cylinder_->addToRenderer(_renderer, &ro, height, vstart, vdir, lineWidth);
1140 sphere_->addToRenderer(_renderer, &ro, sphereSize, vend);
ShaderGenDesc shaderDesc
Drawmode and other shader params.
void NormalizeCoordinateFrame(Matrix &_mat)
Normalizes a coordinate frame defined by the given matrix.
void HSVtoRGB(const Vec4f &_HSV, Vec4f &_RGB)
Convert HSV color to RGB.
void setActivePose(const AnimationHandle &_hAni)
Set the pose which should be rendered.
Namespace providing different geometric functions concerning angles.
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. ...
static void enable(GLenum _cap)
replaces glEnable, but supports locking
ChildIter begin()
Returns an iterator on the joints children.
void pick_set_name(unsigned int _idx)
sets the current name/color (like glLoadName(_idx))
PickTarget
What target to use for picking.
double unprojectPointSize(double _pointSize, const Vec3d &_point, GLState &_state)
Simulate glPointSize(12) with a sphere.
void draw(GLState &_state, const DrawModes::DrawMode &_drawMode)
Renders the nodes contents using the given render state and draw mode.
void showCoordFrames(bool _bVisible=true)
Toggle visibility of coordinate frames for all joints.
static void disable(GLenum _cap)
replaces glDisable, but supports locking
bool pick_set_maximum(unsigned int _idx)
Set the maximal number of primitives/components of your object.
void pick(GLState &_state, PickTarget _target)
Renders the node in picking mode, restricted to the node components given by _target.
pick any of the prior targets (should be implemented for all nodes)
void multipassNodeSetActive(const unsigned int _i, bool _active)
Set Node status to traverse in a specific pass.
Interface class between scenegraph and renderer.
Vec3d unproject(const Vec3d &_winPoint) const
unproject point in window coordinates _winPoint to world coordinates
GLuint vertexBuffer
VBO, IBO ids, ignored if VAO is provided.
const DrawModeProperties * getLayer(unsigned int _i) const
returns the property set at layer i
DrawMode SOLID_FLAT_SHADED
draw flat shaded faces (requires face normals)
void set_ambient_color(const Vec4f &_col)
set ambient color
void initFromState(GLState *_glState)
Initializes a RenderObject instance.
VectorT< float, 4 > Vec4f
ChildIter end()
Returns the end iterator for the joints children.
static void shadeModel(GLenum _mode)
replaces glShadeModel, supports locking
void draw_bone(GLState &_state, DrawModes::DrawMode _drawMode, const Point &_parent, const Point &_axis)
Helper function to draw the bones.
const GLMatrixd & modelview() const
get modelview matrix
DrawModes::DrawMode availableDrawModes() const
Returns available draw modes.
void getRenderObjects(IRenderer *_renderer, GLState &_state, const DrawModes::DrawMode &_drawMode, const Material *_mat)
Adds renderobjects to renderer for flexible shader pipeline.
void pick_edges(GLState &_state)
Pick method for edges.
SkeletonNodeT(SkeletonType &_skeleton, BaseNode *_parent=0, std::string _name="<SkeletonNode>")
Constructor.
void addBoneToRenderer(IRenderer *_renderer, RenderObject &_base, const Point &_parent, const Point &_axis)
Helper function to create a renderobject for bones.
void set_diffuse_color(const Vec4f &_col)
set diffuse color
void glColor(const Vec3f &_v)
Wrapper: glColor for Vec3f.
picks verices (may not be implemented for all nodes)
void diffuseColor(const Vec4f &_d)
set the diffuse color.
void push_modelview_matrix()
push modelview matrix
picks edges (may not be implemented for all nodes)
void translate(Scalar _x, Scalar _y, Scalar _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with translation matrix (x,y,z)
const VertexDeclaration * vertexDecl
Defines the vertex buffer layout, ignored if VAO is provided.
AnimationHandle activePose()
Get the pose that is used for rendering.
size_t getNumLayers() const
returns the layer count
void scale(Scalar _x, Scalar _y, Scalar _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with scaling matrix (x,y,z)
const Vec4f & specular_color() const
get specular color
void pick_vertices(GLState &_state)
Pick method for vertices.
DrawModeProperties stores a set of properties that defines, how to render an object.
void set_color(const Vec4f &_col)
set color
float line_width() const
get line width
static bool supportsInstancedArrays()
VectorT< float, 3 > Vec3f
void rotateX(Scalar _angle, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with a rotation matrix (angle in degree, x-axis)
defined by user via VertexElement::shaderInputName_
Joint * parent()
Returns the parent joint.
float point_size() const
get point size
DrawMode POINTS
draw unlighted points using the default base color
void rotate(Scalar angle, Scalar x, Scalar y, Scalar z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
~SkeletonNodeT()
Destructor.
void pop_modelview_matrix()
pop modelview matrix
virtual void addRenderObject(RenderObject *_renderObject)
Callback for the scenegraph nodes, which send new render objects via this function.
DrawMode WIREFRAME
draw wireframe
void set_specular_color(const Vec4f &_col)
set specular color
unsigned int id()
returns the joint id
DrawMode SOLID_FACES_COLORED
draw colored, but not lighted faces using face colors
A handle used to refer to an animation or to a specific frame in an animation.
GLMatrixd modelview
Modelview transform.
void set_modelview(const GLMatrixd &_m)
set modelview
void RGBtoHSV(const Vec4f &_RGB, Vec4f &_HSV)
Convert RGB color to HSV.
void setupShaderGenFromDrawmode(const SceneGraph::DrawModes::DrawModeProperties *_props)
Fills out ShaderGenDesc parameters based on Drawmode properties.
const Vec4f & ambient_color() const
get ambient color
void boundingBox(Vec3d &_bbMin, Vec3d &_bbMax)
Returns the bounding box of this node.
SkeletonType & skeleton()
Returns a pointer to the skeleton.
DrawMode SOLID_FACES_COLORED_FLAT_SHADED
draw flat shaded and colored faces (requires face normals and colors)
Represents a single joint in the skeleton.
bool invert()
matrix inversion (returns true on success)
const Vec4f & base_color() const
get base color (used when lighting is off)
void glVertex(const Vec2i &_v)
Wrapper: glVertex for Vec2i.
Vec3d project(const Vec3d &_point) const
project point in world coordinates to window coordinates
void getJointColor(const Vec4f &_baseColor, Vec4f &_result)
get a joint color suitable to the baseColor
const Vec4f & diffuse_color() const
get diffuse color
double frameSize()
returns the size of the rendered coordinate system