OpenGL/Glut绘制棱锥体-骨架骨骼

OpenGL/Glut绘制棱锥体-骨架骨骼,opengl,3d,glut,freeglut,Opengl,3d,Glut,Freeglut,我想在OpenGL中绘制一个人体骨架(姿势估计项目),使用任何可能有用的工具包。 我已经有了一些简单的工作,用 glvertex3d // and/or glutWireSphere 骨头上有 glBbegin(GL_Lines) glvertex3d // coordinates of starting point glvertex3d // coordinates of ending point glEnd() 这看起来与下一张图片非常相似,但是这张骨骼描述并没有给出任何关于骨骼旋转的

我想在OpenGL中绘制一个人体骨架(姿势估计项目),使用任何可能有用的工具包。 我已经有了一些简单的工作,用

glvertex3d // and/or 
glutWireSphere
骨头上有

glBbegin(GL_Lines)
glvertex3d // coordinates of starting point
glvertex3d // coordinates of ending point
glEnd()
这看起来与下一张图片非常相似,但是这张骨骼描述并没有给出任何关于骨骼旋转的直觉

我想要一些看起来更像下图的东西,骨骼画成细长的金字塔

在这方面,供过于求似乎没有帮助

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

是否有可用的工具,或者这应该是一个自定义解决方案?

GLUT对象将使用当前的OpenGL modelview矩阵绘制。这可用于控制渲染对象的位置、旋转,甚至缩放。使用圆锥体时,首先平移(使用
glTranslate()
)到一个端点的位置,然后旋转(使用
glRotate()
glMultMatrix()
)使圆锥体指向另一个端点。最后,调用
GLUTWIRCONE()
方法,使高度等于从一个端点到另一个端点的距离

棘手的一点是找到
glRotate()
参数。默认情况下,GLUT将沿Z轴绘制圆锥体,因此旋转需要是将Z轴旋转到端点减去起点定义的轴所需的任何旋转。GLM数学库对于这类事情非常有用。它甚至有一个很好的解释

所以你可以这样做:

// 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);

通过为glut圆锥体中的切片数指定3,可以获得四面体效果。事实上,如果
glutwire四面体
没有按照
glutwire圆锥体

实现,我不会感到非常惊讶。正如上面的评论所述,杰里科的回答确实帮助我解决了这个问题

这个答案建立在他的帖子上,只是为了让事情更完整一点,以备将来参考

请查找GLM库,它是一个只包含头文件的库,因此您不需要构建它,只需链接到它并包含必要的头文件即可。它有一些很棒的工具,如下所示

#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();
#定义GLM_FORCE_RADIANS//以实现GLM和OpenGL API遗留函数之间的兼容性
#包括
#包含//用于glm::mat4\U cast//铸造四元数->mat4
#包含//用于glm::旋转
#包含//用于glm::to_字符串
...
...
...
//_下面使用的startBoneVec3是Eigen::Vector3d
//_endddBoneVec3下面使用的是Eigen::Vector3d
...
...
...
//
//接头
//
glPushMatrix();
glTranslated(_startBoneVec3(0),_startBoneVec3(1),_startBoneVec3(2));
(1.0,30,30);
glPopMatrix();
...
...
//
//骨头
//
glPushMatrix();
float bonelelength=(_endddBoneVec3-_startBoneVec3).norm();
glTranslated(_startBoneVec3(0),_startBoneVec3(1),_startBoneVec3(2));
glm::vec3_glmStart(_startBoneVec3(0),_startBoneVec3(1),_startBoneVec3(2));
glm::vec3(0),1,2),;
glm::vec3 _glmdirr=glm::normalize(_glmendd-_glmStart);//正常化非常重要!!!
glm::quat _glmRotQuat=glm::rotation(glm::vec3(0,0,1),_glmdirr);//计算两个规格化向量之间的旋转四元数
//glm::mat4 _glmRotMat=glm::mat4 _cast(_glmRotQuat);//四元数->mat4
glm::mat4 _glmRotMat=glm::toMat4(_glmRotQuat);//四元数->mat4

//谢谢杰里科,很好的回答!!!我只是按照你的建议做了这件事。还感谢您给我指出GLM,我以前从未使用过它,而且似乎非常有帮助,我希望我早就被指出:)您的答案当然可以接受,但我也会发布我的代码片段供其他人将来参考(记下#包括和一些注释)没有理由使用
glTranslated
而不是
glTranslatef
。我不确定norm()做什么。如果是glm::length(_endddBoneVec3-_startBoneVec3),这可能更清楚;没错,我只是习惯了大部分时间和替身一起工作。函数
norm()。代码snipet是从我的代码中粘贴而来的,但对于本例来说,函数
glm::length
可能确实更直观。只需另外注意,Eigen也提供了类似的解决方案。
#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();