You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenGL 2下利用JointTransform矩阵计算蒙皮网格骨骼起止点的方法

实现步骤

1. 梳理骨骼基础数据

首先要明确每个骨骼的父骨骼索引,以及绑定姿态下骨骼的局部尾部位置(即骨骼自身原点指向末端的局部Vector3,可从模型骨骼数据提取,或自定义骨骼时直接设定)。

2. 计算骨骼世界空间起止点

起始点计算

  • 根骨骼(父索引为-1):将其JointTransform矩阵作用于局部原点(0,0,0),取变换结果的前三个分量作为世界空间起始点。
  • 子骨骼:直接使用其父骨骼的结束点作为自身起始点,因为子骨骼的起点就是父骨骼的末端。

结束点计算

将骨骼的局部尾部位置转换为齐次坐标(x,y,z,1),乘以当前帧的JointTransform矩阵,取结果的前三个分量即为世界空间结束点。

3. OpenGL 2 绘制骨骼线条

准备顶点数据

按顺序将所有骨骼的起始点、结束点存入顶点数组,每两个顶点对应一条骨骼线段。

设置OpenGL状态

glDisable(GL_LIGHTING); // 禁用光照,避免影响线条显示
glLineWidth(2.0f);      // 设置线条宽度,可按需调整
glColor3f(1.0f, 0.0f, 0.0f); // 设置线条颜色,示例为红色

执行绘制

glBegin(GL_LINES);
for (int i = 0; i < boneCount; i++) {
    Vector3& start = boneStartPoints[i];
    Vector3& end = boneEndPoints[i];
    glVertex3f(start.x, start.y, start.z);
    glVertex3f(end.x, end.y, end.z);
}
glEnd();

关键代码示例

// 骨骼数据结构
struct Bone {
    int parentIndex;
    Vector3 localEndPos;
    Matrix4 jointTransform;
};

vector<Bone> bones;
vector<Vector3> boneStartPoints;
vector<Vector3> boneEndPoints;

// 计算所有骨骼的起止点
void calculateBonePositions() {
    boneStartPoints.clear();
    boneEndPoints.clear();

    for (int i = 0; i < bones.size(); i++) {
        Bone& bone = bones[i];
        Vector3 startPos;

        if (bone.parentIndex == -1) {
            startPos = bone.jointTransform * Vector3(0, 0, 0);
        } else {
            startPos = boneEndPoints[bone.parentIndex];
        }

        Vector3 endPos = bone.jointTransform * bone.localEndPos;
        boneStartPoints.push_back(startPos);
        boneEndPoints.push_back(endPos);
    }
}

// 绘制骨骼
void renderBones() {
    glDisable(GL_LIGHTING);
    glLineWidth(2.0f);
    glColor3f(1.0f, 0.0f, 0.0f);

    glBegin(GL_LINES);
    for (int i = 0; i < bones.size(); i++) {
        Vector3& s = boneStartPoints[i];
        Vector3& e = boneEndPoints[i];
        glVertex3f(s.x, s.y, s.z);
        glVertex3f(e.x, e.y, e.z);
    }
    glEnd();

    // 恢复原有渲染状态(按需执行)
    glEnable(GL_LIGHTING);
    glLineWidth(1.0f);
}

注意事项

  • 确保JointTransform是世界空间矩阵,若为局部空间矩阵,需通过父矩阵链式相乘转换为世界空间矩阵(根骨骼用自身矩阵,子骨骼为父骨骼世界矩阵乘自身局部矩阵)。
  • 导入模型的骨骼局部尾部位置,可通过绑定姿态下父骨骼变换矩阵的逆矩阵,乘以子骨骼绑定姿态原点得到。
  • 绘制前需设置正确的投影、视图矩阵,保证骨骼线条能正常显示在视口中。

内容的提问来源于stack exchange,提问作者thatGuy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 04:45:32