Matrix 将全局层次旋转转换为局部旋转和反向旋转

Matrix 将全局层次旋转转换为局部旋转和反向旋转,matrix,rotation,global,local,quaternions,Matrix,Rotation,Global,Local,Quaternions,我有一个分层框架,其中平移和旋转在全局空间中表示。我需要将骨架转换为局部坐标,然后再转换回来。我对翻译没有问题,但我似乎无法使旋转工作 最初,我有旋转矩阵,但我可以轻松地将它们转换为Euler或四元数,并尝试使用它们。我正在使用Irrlicht引擎数学库 因此,我的代码遍历每个骨骼,只要骨骼有下一个父骨骼,就应用转换 从全球到本地: for(; iter != absolutePose.end(); iter++) { if(hierarchy->find(iter->bon

我有一个分层框架,其中平移和旋转在全局空间中表示。我需要将骨架转换为局部坐标,然后再转换回来。我对翻译没有问题,但我似乎无法使旋转工作

最初,我有旋转矩阵,但我可以轻松地将它们转换为Euler或四元数,并尝试使用它们。我正在使用Irrlicht引擎数学库

因此,我的代码遍历每个骨骼,只要骨骼有下一个父骨骼,就应用转换

从全球到本地:

for(; iter != absolutePose.end(); iter++)
{
    if(hierarchy->find(iter->boneID) != hierarchy->end())
    {
        BoneID parentNodeID = hierarchy[iter->boneID];
        relativePose[iter->boneID].position.X = iter->position.X - absolutePose[parentNodeId].position.X;
        relativePose[iter->boneID].position.Y = iter->position.Y - absolutePose[parentNodeId].position.Y;
        relativePose[iter->boneID].position.Z = iter->position.Z - absolutePose[parentNodeId].position.Z;

                    ////Rotation Part/////////
        float pq[4] ={0.0,0.0,0.0,0.0};
        MatrixToQuaternion(absolutePose[parentNodeId].orientation, pq);

        irr::core::quaternion quat(q[0],q[1],q[2],q[3]);
        irr::core::quaternion parentquat(pq[0],pq[1],pq[2],pq[3]);

        quat = quat.makeInverse();

        quat = quat*parentquat;

        float newQuat[4] = {quat.X, quat.Y, quat.Z, quat.W};
        QuaternionToMatrix(newQuat,relativePose[iter->first].orientation);

    }
    else // top bone
    {
        relativePose[iter->boneID].position.X = iter->position.X;
        relativePose[iter->boneID].position.Y = iter->position.Y;
        relativePose[iter->boneID].position.Z = iter->position.Z;

        relativePose[iter->boneID].orientation = iter->second.orientation;
    }
}
然后从本地到全球:

for(; iter != relativePose.end(); iter++)
    {
        absolutePose[iter->boneID].position.position = iter->position;
        auto nextParent = hierarchy->find(iter->boneID);
        while(nextParent != hierarchy->end())
        {
            absolutePose[iter->boneID].position.X += relativePose[nextParent->boneID].position.X;
            absolutePose[iter->boneID].position.Y += relativePose[nextParent->boneID].position.Y;
            absolutePose[iter->boneID].position.Z += relativePose[nextParent->boneID].position.Z;

            ////Rotation part///
            float q[4] ={0.0,0.0,0.0,0.0};
            MatrixToQuaternion(relativePose[iter->boneID].orientation, q);

            float pq[4] ={0.0,0.0,0.0,0.0};
            MatrixToQuaternion(relativePose[nextParent->boneID].orientation, pq);
            irr::core::quaternion quat(q[0],q[1],q[2],q[3]);
            irr::core::quaternion parentquat(pq[0],pq[1],pq[2],pq[3]);

            quat = parentquat*quat;

            float newQuat[4] = {quat.X, quat.Y, quat.Z, quat.W};
            QuaternionToMatrix(newQuat,absolutePose[iter->boneID].orientation);
            //////

            nextParent = hierarchy->find(nextParent->boneID);
        }
    }

我已经有一段时间的问题了,我也尝试过保持矩阵模式并切换到Euler角度。有人能帮我找出我做错了什么吗?

不管你用的是矩阵还是四元数。我建议不要在这里使用欧拉角。在我看来,问题在于,当转换为局部坐标时,您将反转子四元数而不是父四元数,而当转换为全局坐标时,您不会传播旋转

假设方向应用于右侧的列向量:

q_1、q_2和q_3是链中三个物体的全局方向。如果我们想使用相对方向r_2和r_3,那么必须将父对象的旋转从其子对象中移除。我们可以看到q_2=q_1*r_2和q_3=q_1*r_2*r_3=q_2*r_3

求相对值,得到r_3=q_2'*q_3,同样,r_2=q_1'*q_2,其中q_2'是矩阵或四元数的逆

如果要从全局转换为局部,则需要记住:

q_3=q_1*r_2*r_3

所有父方向都需要向下传播到最终子体。因此,您要么需要使用递归来获取从子对象到根对象的所有方向更改,要么需要从父对象开始,在向下遍历子对象时传播/累积每个链接的所有方向更改


作为事后考虑,我认为您还需要确保根节点意识到其相对位置等于其绝对位置。否则您将遇到问题。

使用矩阵或四元数无关紧要。我建议不要在这里使用欧拉角。在我看来,问题在于,当转换为局部坐标时,您将反转子四元数而不是父四元数,而当转换为全局坐标时,您不会传播旋转

假设方向应用于右侧的列向量:

q_1、q_2和q_3是链中三个物体的全局方向。如果我们想使用相对方向r_2和r_3,那么必须将父对象的旋转从其子对象中移除。我们可以看到q_2=q_1*r_2和q_3=q_1*r_2*r_3=q_2*r_3

求相对值,得到r_3=q_2'*q_3,同样,r_2=q_1'*q_2,其中q_2'是矩阵或四元数的逆

如果要从全局转换为局部,则需要记住:

q_3=q_1*r_2*r_3

所有父方向都需要向下传播到最终子体。因此,您要么需要使用递归来获取从子对象到根对象的所有方向更改,要么需要从父对象开始,在向下遍历子对象时传播/累积每个链接的所有方向更改


作为事后考虑,我认为您还需要确保根节点意识到其相对位置等于其绝对位置。否则您将遇到问题。

我有包含骨骼绝对位置的矩阵。我想把它们转换成相对位置。你的答案是什么?对不起,这是3D编程的新手。我有包含骨骼绝对位置的矩阵。我想把它们转换成相对位置。你的答案是什么?对不起,我对3D编程非常陌生。