1

我正在使用四元数和 XNA 蒙皮模型示例(现在已有数周......)。我从一些开源传感器板上收到了两组四元数,这些天你可以在网上购买。我能够编写一些代码来接收这些四元数,并且能够用它们旋转四肢。现在我的问题如下。在我的示例中,我使用的是右上臂和右下臂,我可以分别旋转它们。我的初始位置如下图所示,非常完美。

http://i.imgur.com/c7qei.png “初始位置”

现在,当我想向前旋转我的右臂时,我应该有我的最终位置,如下图右侧所示。但不知何故,结果是左侧的一个位置,但我真正的“物理”手臂指向前方。

http://i.imgur.com/tXCp6.png “理想的最终位置(右),真正的错误位置(左)”

有些下臂无法补偿上臂的旋转。我确信我错过了一小步。下面我把我正在使用的代码的关键部分

    protected override void Update(GameTime gameTime)
    {
        HandleInput();

        UpdateCamera(gameTime);

        // Read gamepad inputs.
        float initposition = currentGamePadState.ThumbSticks.Right.X;
        float armRotation = Math.Max(currentGamePadState.ThumbSticks.Right.Y, 0);

        // these quaternions are received from bluetooth
        Upper.Z = Fq1;
        Upper.Y = -Fq2;
        Upper.X = -Fq3; // set 1 quaternions
        Upper.W = Fq4;
        //***************************

        forearm.Z = Uq1;
        forearm.Y = -Uq2;
        forearm.X = -Uq3;
        forearm.W = Uq4; // set 2 quaternions





        // set initial position
        if (initialpos == true)
        {
            initposition = 0.9f;
            R_forTransform = Matrix.CreateRotationY(initposition);

            R_forarminderinit = skinningData.BoneIndices["R_UpperArm"];
            L_forTransform = Matrix.CreateRotationY(-initposition);
            L_forTransform = Matrix.CreateRotationX(-initposition);
            L_forTransform = Matrix.CreateRotationZ(-initposition);
            L_forarminderinit = skinningData.BoneIndices["L_UpperArm"];

         }


        // Create rotation matrices for the upper and lower arm bones.

        Matrix upperarmTransform = Matrix.CreateFromQuaternion(Upper);
        Matrix forearmTransform = Matrix.CreateFromQuaternion(forearm);



        animationPlayer.GetBoneTransforms().CopyTo(boneTransforms, 0);
        if (initialpos == true)
        {
            boneTransforms[R_forarminderinit] = R_forTransform * boneTransforms[R_forarminderinit];
            boneTransforms[L_forarminderinit] = L_forTransform * boneTransforms[L_forarminderinit];
        }

        int forearmindex = skinningData.BoneIndices["R_Forearm"];
        int upperarmindex = skinningData.BoneIndices["R_UpperArm"];
        boneTransforms[upperarmindex] = upperarmTransform * boneTransforms[upperarmindex];
        boneTransforms[forearmindex] = (forearmTransform) * boneTransforms[forearmindex];
        animationPlayer.UpdateWorldTransforms(Matrix.Identity, boneTransforms);
        animationPlayer.UpdateSkinTransforms();
        UpdateBoundingSpheres();
        base.Update(gameTime);
    }

我想问你能不能帮我解开这个谜。我希望我在描述我的问题时尽可能清楚。此外,我要提前感谢您的努力。

你的

戴夫

4

1 回答 1

0

在我看来,您有一些混淆的参考框架。这是我认为我所看到的:

您的外部传感器报告它们相对于世界的方向。另一方面,您的渲染代码处理上臂参考框架中的下臂。

如果我们假设初始方向是q_u = [0,0,0,1]q_l=[0,0,0,1],当您旋转手臂指向前方时,新方向都是[0,. 707,0,.707]或类似的东西,因为两个臂段都经历了相对于世界的π/2 旋转。

渲染手臂时,将整个手臂(不仅仅是上臂)旋转 q_u。这是有道理的,因为您要确保肘部保持连接。但随后您将下臂旋转q_l,它已旋转了应有的两倍,因为它保持了肩部的旋转。如果您将手臂伸直,但将身体转过来,您会看到同样的事情发生:上臂会旋转身体旋转的量,而下臂会再次旋转同样的量。

处理此问题的最简单方法可能是从q_l中删除q_u。如果q_k是下臂对于上臂的旋转,则q_k = q_u' * q_l其中q_u'是逆四元数(只是取反分量)。w

于 2012-12-05T15:45:11.423 回答