我正在开始一个需要控制虚拟角色的项目。该角色正在多个 3D 引擎中渲染,例如 Three.JS 和 iOS SceneKit。
我正在使用 OpenNI 获取骨架每个关节的四元数,它看起来像这样:
保存并传递四元数的代码如下所示:
float confidence = context.getJointOrientationSkeleton(userId, jointName,
joint);
joints[jointIndex]=joint.m00;
joints[jointIndex+1]=joint.m01;
joints[jointIndex+2]=joint.m02;
joints[jointIndex+3]=joint.m10;
joints[jointIndex+4]=joint.m11;
joints[jointIndex+5]=joint.m12;
joints[jointIndex+6]=joint.m20;
joints[jointIndex+7]=joint.m21;
joints[jointIndex+8]=joint.m22;
jointIndex+=9;
这对骨骼的每个关节都重复。
最后一行和最后一列始终[0 0 0 1] [0, 0, 0, 1]
是4x4 matrix
.
我希望能够使用这些数据进行正确的旋转,但我得到的旋转肯定是错误的。
这就是我处理矩阵的方式:(伪代码)
row1 = [m00 m01 m02 0]
row2 = [m10 m11 m12 0]
row3 = [m20 m21 m22 0]
row4 = [0 0 0 1]
matrix4by4 = matrix4x4(rows:[row1,row2,row3,row4])
然后我用两种方法得到了四元数,两种方法都显示不好的旋转,我找不到什么问题或我错过了什么。
第一种方法
有一个 iOS 函数可以获取 3x3 或 4x4 矩阵,并将其转换为四元数:
boneRotation = simd_quatf.init(matrix4by4).vector //X,Y,Z,W
第二种方法
我在网上找到了以下代码:
let tr = m00 + m11 + m22
var qw = 0
var qx = 0
var qy = 0
var qz = 0
if (tr > 0) {
var S = sqrt(tr+1.0) * 2 // S=4*qw
qw = 0.25 * S
qx = (m21 - m12) / S
qy = (m02 - m20) / S
qz = (m10 - m01) / S
} else if ((m00 > m11) && (m00 > m22)) {
var S = sqrt(1.0 + m00 - m11 - m22) * 2 // S=4*qx
qw = (m21 - m12) / S
qx = 0.25 * S
qy = (m01 + m10) / S
qz = (m02 + m20) / S
} else if (m11 > m22) {
var S = sqrt(1.0 + m11 - m00 - m22) * 2 // S=4*qy
qw = (m02 - m20) / S
qx = (m01 + m10) / S
qy = 0.25 * S
qz = (m12 + m21) / S
} else {
let S = sqrt(1.0 + m22 - m00 - m11) * 2 // S=4*qz
var = (m10 - m01) / S
qx = (m02 + m20) / S
qy = (m12 + m21) / S
qz = 0.25 * S
}
boneRotation = vector4(qx, qy, qw, qz)
我开始只测试肩部和肘部旋转,以帮助我想象可能出现的问题或缺失,并制作了一个视频。
以下是它的行为方式:https ://www.youtube.com/watch?v=xUtNiwH_AGk
我会错过什么?例如,肩部的旋转轴是这样的:
先感谢您 :-)
YouTuve 视频:https ://www.youtube.com/watch?v=xUtNiwH_AGk