土法炼钢兴趣小组的算法知识备份

游戏中的数学 (11) - 骨骼动画数学

目录

引言

骨骼动画是现代 3D 游戏角色的标准。它基于层级变换 (Hierarchical Transformations)。 每个骨骼(Bone)都是一个坐标系,子骨骼的变换是相对于父骨骼的。

IK vs FK

1. 正向动力学 (Forward Kinematics - FK)

这是最自然的动画方式:旋转关节,末端随之移动。 例如:旋转肩膀 -> 旋转手肘 -> 手掌移动。

数学上,这是矩阵乘法的链式反应: \[ M_{hand} = M_{shoulder} \times M_{elbow} \times M_{wrist} \]

2. 反向动力学 (Inverse Kinematics - IK)

这是 FK 的逆问题:已知末端目标位置,求各关节的角度。 例如:手要放在门把手上,肩膀和手肘应该怎么转?

这是一个非线性方程组求解问题,通常有多个解(或无解)。

常用算法:CCD (Cyclic Coordinate Descent)

CCD 是一种迭代算法,思路非常直观:从末端关节开始,逐个调整父关节,使末端指向目标。

算法步骤: 1. 遍历骨骼链,从最后一个骨骼(末端)到根骨骼。 2. 对于每个骨骼,计算”当前末端位置”到”目标位置”的向量。 3. 旋转当前骨骼,使得末端位置尽可能接近目标。 4. 重复上述过程多次,直到误差小于阈值。

代码片段 (伪代码):

void SolveCCD(Transform[] bones, Vector3 target, int iterations = 10) {
    for (int i = 0; i < iterations; i++) {
        // 从倒数第二个骨骼开始(末端本身不需要旋转)
        for (int j = bones.Length - 2; j >= 0; j--) {
            Transform bone = bones[j];
            Transform endEffector = bones[bones.Length - 1];
            
            Vector3 toEnd = endEffector.position - bone.position;
            Vector3 toTarget = target - bone.position;
            
            // 计算旋转:将 toEnd 旋转到 toTarget
            Quaternion rotation = Quaternion.FromToRotation(toEnd, toTarget);
            bone.rotation = rotation * bone.rotation;
        }
        
        if (Vector3.Distance(bones[bones.Length-1].position, target) < 0.01f)
            break;
    }
}

常用算法:FABRIK

FABRIK (Forward And Backward Reaching Inverse Kinematics) 不使用旋转角度,而是直接操作关节位置。 1. 前向: 将末端拉到目标点,然后拉直骨骼链。 2. 后向: 将根节点拉回原点,再次拉直骨骼链。 3. 迭代: 重复直到收敛。 它比 CCD 更快且更自然,避免了奇怪的扭曲。

3. 蒙皮 (Skinning)

骨骼动了,网格(Mesh)怎么动? 每个顶点通常受多个骨骼影响(权重 Weight)。 \[ P_{final} = \sum (w_i \times M_i \times P_{bind}) \] 这称为线性混合蒙皮 (Linear Blend Skinning - LBS)。

总结


< 上一篇: 曲线数学 | 回到目录 | 下一篇: 随机与噪声 >


By .