如何正确表示骨骼系统?

我现在代表我的骨骼系统如下,伪代码:

root = {} root.rot = v3(0,0,0) root.pos = v3(0,0,0) function create_child(parent,rot,length): child_bone = {} child_bone.rot = parent.rot + rot child_bone.pos = parent.pos + v3(0,0,bone.length).rotate(child_bone.rot) 

这适用于大多数情况下,但有时我得到奇怪的场合,旋转父骨头让孩子骨头旋转狂乱。 什么是骨系统的正确的math表示?

Solutions Collecting From Web of "如何正确表示骨骼系统?"

在这里输入图像描述

这里主要介绍如何find一个骨头的位置:

你从骨头的局部空间开始,那里的根在原点,并且尖端的距离等于沿着它的一个轴的骨长度,只要你从我的代码中可以看出你使用的是Z轴,我在我的图像中使用x,从现在开始我将它称为z轴,因为您使用它(image1)。

要去父母的本地空间,你必须做一个轮换,然后翻译。 旋转是骨骼相对于其母体的旋转,现在父骨骼的顶端(图像中的绿色骨骼)在原点处,我们必须沿着Z轴平移母体的长度骨到达根源于原始的绿骨的局部空间。 (图3)

我们重复这些步骤到达红骨的局部空间(图4和5)

最后一个旋转是从红骨的局部空间到骨架的局部空间(注意,所有的旋转都围绕着不同的枢轴点旋转(不管是当前系统的原点,但是由于你在它们之间做了翻译)更改),这是您发布的代码中的问题之一。

如果必要的话,您可能需要应用另一组转换才能到达世界空间,如果您的电枢本地空间不是相对于世界空间转换或旋转的,则不需要这些步骤。

在我看来,应用这些转换有两个好方法,一个是使用matrix,另一个是使用四元数。

4点p0,p1,p2和p3是你在图6中看到的4个点,它们是:红根,绿根,蓝根,蓝尖。

len0是红色的长度,len1是绿色的长度,len2是蓝色的长度。

红色(r0,q0)为30,绿色(r1,q1)为30,蓝色(r2,q2)为60。 所有相对于父母。

matrix具有列向量,并因此而后乘,所以从右向左应用转换。

matrix:

 //rotate creates a rotation matrix represented by an angle and an axis //translate creates a translation matrix along the specified vector mat4 r0 = rotate(30,vec3(1,0,0)) * translate(vec3(0,0,len0)); mat4 r1 = rotate(-30,vec3(1,0,0)) * translate(vec3(0,0,len1)); mat4 r2 = rotate(60,vec3(1,0,0)) * translate(vec3(0,0,len2)); p0 = glm::vec4(0,0,0,1); p1 = r0 * p0; p2 = r0 * r1 * p0; p3 = r0 * r1 * r2 * p0; 

四元数:

 //angleAxis creates a Quaternion based on the angle and an axis quat q0 = angleAxis(30,vec3(1,0,0)); quat q1 = angleAxis(-30,vec3(1,0,0)); quat q2 = angleAxis(60,vec3(1,0,0)); p0 = vec3(0,0,0); p1 = q0 * vec3(0,0,len0); p2 = q0 * ( (q1 * vec3(0,0,len1) ) + vec3(0,0,len0) ); p3 = q0 * (q1 * ( (q2 * vec3(0,0,len2) ) + vec3(0,0,len1) ) + vec3(0,0,len0) ); 

代码基本上是应用所有的转换,如开始所述。 matrix基本上是一步一步地完成单个骨骼的平移和旋转,而四元数只能存储旋转,并且必须在额外的步骤中翻译它们。

您可以按照此处所述计算您需要的职位。 你不能像你在样本中那样计算旋转,因为没有旋转存在。 问题是,所有不同的旋转应用是围绕不同的枢轴点旋转,需要翻译之间。 你可以按照我做的方式存储相对于父对象的旋转,也可以使用matrix将matrix中的平移和旋转存储到同一个matrix中,然后就不再需要这个位置了。

希望这有助于,随时提问。