【问题标题】:OpenGL/Glut draw Pyramid - Skeleton BonesOpenGL/Glut 绘制金字塔 - 骨骼骨骼
【发布时间】:2014-02-09 02:30:34
【问题描述】:

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

绘制关节
glvertex3d // and/or 
glutWireSphere

还有骨头用

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

这看起来与下一张图片非常相似,但是这个骨骼描述并没有给出任何关于骨骼旋转的直觉。

我想要一些看起来更类似于下图的东西,骨骼被绘制成细长的金字塔。

Glut 似乎对此没有帮助。

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

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

【问题讨论】:

    标签: opengl 3d glut freeglut


    【解决方案1】:

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

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

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

    所以你可以这样做:

    // 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 来获得四面体效果。事实上,如果glutWireTetrahedron 没有按照glutWireCone 实现,我不会感到很惊讶

    【讨论】:

    • 谢谢 Jherico,很好的回答!!!我刚刚按照您的建议进行了这项工作。也感谢您将我指向 GLM,我以前从未使用过它,并且似乎非常有帮助,我希望我更早地指出了这一点 :) 您的回答当然被接受,但我也会发布我的代码 sn-p 以供将来使用其他人引用(记下#includes 和一些 cmets)
    【解决方案2】:

    正如上面评论中提到的,Jherico 的回答确实帮助我解决了这个问题。

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

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

    #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();
    

    结果:

    【讨论】:

    • 没有理由使用glTranslated 代替glTranslatef。我不确定 norm() 是做什么的。如果是 glm::length(_endddBoneVec3 - _startBoneVec3); 可能会更清楚
    • 没错,我只是习惯于大部分时间使用双打。函数norm() 是我大量使用的 Eigen 库的一个函数,它对你的提案做同样的事情。代码片段是从我的代码中粘贴的,但对于此示例,函数 glm::length 可能确实更直观。
    • 补充说明,Eigen 也提供了类似的解决方案,注明here
    猜你喜欢
    • 1970-01-01
    • 2017-05-05
    • 1970-01-01
    • 2017-05-03
    • 1970-01-01
    • 1970-01-01
    • 2022-11-21
    • 2012-10-17
    • 2014-09-23
    相关资源
    最近更新 更多