1
votes

I would like to draw a human skeleton (pose estimation project) in OpenGL, using whichever toolkit might be helpful. I already have something simple working, drawing the joints with

glvertex3d // and/or 
glutWireSphere

and the bones with

glBbegin(GL_Lines)
glvertex3d // coordinates of starting point
glvertex3d // coordinates of ending point
glEnd()

This looks like very similar to the next picture, however this bone depiction doesn't give any intuition about bone rotation.

enter image description here

I would like to have something looking more similar to the following picture, with bones drawn as elongated pyramids.

enter image description here

Glut doesn't seem to help on this.

glutWireCone // better than simple line, but still no intuition about rotation
glutWireTetrahedron // not really useful / parametrizable

Is there any tool available or should this be a custom solution?

2

2 Answers

3
votes

GLUT objects will be drawn using the current OpenGL modelview matrix. This can be used to control the position, rotation, or even the scaling of the rendered object. With a cone, you would first translate (using glTranslate()) to the position of one end point, and then rotate (using glRotate() or glMultMatrix()) so that your cone was pointed towards the other endpoint. Finally you call your glutWireCone() method so that the height is equal to the distance from one endpoint to the other.

The tricky bit is finding the glRotate() parameters. GLUT will draw the cone by default along the Z axis, so your rotation needs to be whatever rotation would be required to rotate the Z axis to the axis defined by your end point minus your start point. The GLM math library can be really useful for this kind of thing. It even has a function for it

quat rotation(vec3 const & orig, vec3 const & dest)     

So you could do something like this:

// these are filled in with your start and end points
glm::vec3 start, end; 
glm::vec3 direction = end - start;
glm::quat rotation = rotation(glm::vec3(0, 0, 1), direction);
glm::mat4 rotationMatrix = glm::mat4_cast(rotation);
glMultMatrixf(&rotationMatrix);

You can get the tetrahedron effect by specifying 3 for the number of slices in your glut cone. In fact I wouldn't be very surprised if glutWireTetrahedron wasn't implemented in terms of glutWireCone

0
votes

As mentioned in the comment above, Jherico's answer really helped me solve this problem.

This answer builts uppon his post, just to make things a bit more complete, for future reference.

Please find the GLM library here, it's a header only library, so you don't need to build this, just link to it and include the necessary header files. It has some great tools, as can be seen below.

#define GLM_FORCE_RADIANS // for compatibility between GLM and OpenGL API legacy functions
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>    // for glm::mat4_cast // casting quaternion->mat4
#include <glm/gtx/quaternion.hpp>  // for glm::rotation
#include <glm/gtx/string_cast.hpp> // for glm::to_string
...
...
...
// _startBoneVec3 used below is Eigen::Vector3d
// _endddBoneVec3 used below is Eigen::Vector3d
...
...
...
//
// for JOINTS
//
glPushMatrix();
    glTranslated( _startBoneVec3(0),_startBoneVec3(1),_startBoneVec3(2) );
    glutWireSphere(1.0,30,30);
glPopMatrix();
...
...
//
// for BONES
//
glPushMatrix();
    float boneLength = ( _endddBoneVec3  - _startBoneVec3 ).norm();
    glTranslated(        _startBoneVec3(0),_startBoneVec3(1),_startBoneVec3(2) );
    glm::vec3 _glmStart( _startBoneVec3(0),_startBoneVec3(1),_startBoneVec3(2) );
    glm::vec3 _glmEnddd( _endddBoneVec3(0),_endddBoneVec3(1),_endddBoneVec3(2) );
    glm::vec3 _glmDirrr   = glm::normalize( _glmEnddd - _glmStart ); // super important to normalize!!!
    glm::quat _glmRotQuat = glm::rotation( glm::vec3(0,0,1),_glmDirrr); // calculates rotation quaternion between 2 normalized vectors
  //glm::mat4 _glmRotMat = glm::mat4_cast(_glmRotQuat); // quaternion -> mat4
    glm::mat4 _glmRotMat = glm::toMat4   (_glmRotQuat); // quaternion -> mat4
  //std::cout <<  glm::to_string(_glmDirrr) << std::endl;
    glMultMatrixf(glm::value_ptr(_glmRotMat));
    glutWireCone(4.2,boneLength,4,20); // cone with 4 slices = pyramid-like
glPopMatrix();

Result:

enter image description here