将BVH动画的根部绕Y轴旋转一个角度

时间:2019-02-11 14:45:32

标签: c# unity3d rotation quaternions

即使您不熟悉BVH文件格式,也许您也可以帮助我组合两个旋转方式。

我只是从BVH文件中获取根的旋转(复制x,y,z值),如下所示设置根的通道:

CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation

我想绕y轴(0,1,0)将根旋转一定程度,可以是0到360。此旋转在某些帧上有效。但是,在大多数帧中,根部旋转得很奇怪(就像发生了万向节锁定一样)。

这是我使用的代码。 Unity中的C#。我只想正确地应用根的绕y轴的旋转。

当绕y轴旋转0度时,我可以确认代码工作正常(正确的BVH动画)。因此,错误必须是这两个旋转(qBefore和YawRotationQuaternion)的组合。

private Vector3 getFinalRootRotation(Vector3 rotationFromBvh, float angle)
{
    // [INITIALIZE]: Convert Euler to Quaternion for each axis. 
    Quaternion qX = Quaternion.AngleAxis(rotationFromBvh.x, Vector3.right);
    Quaternion qY = Quaternion.AngleAxis(rotationFromBvh.y, Vector3.up);
    Quaternion qZ = Quaternion.AngleAxis(rotationFromBvh.z, Vector3.forward);
    Quaternion qBefore = qY * qX * qZ; // Multiply them in the correct order.
                                       // Order in BVH file is ZXY.

qY*qX*qZ欧拉x,y,z结果相同Quaternion.Euler(rotationFromBvh)

    // [CREATE ROTATION AROUND Y]: Get the quaternion of rotating around y axis.
    Quaternion YawRotationQuaternion = Quaternion.AngleAxis(angle, Vector3.up);

    // [APPLY ROTATION AROUND Y]
    Quaternion qAfter = qBefore * YawRotationQuaternion;

    // [RETURN IN XYZ FORM]
    return qAfter.eulerAngles;
}

我的目标是创建一个具有新根旋转的新BVH。这是我在文件中写入新旋转的代码的一部分。此代码已经过测试,可以创建BVH文件。

private string CreateMLine(Vector3 rootPosition, Vector3 rootRotation, List<Vector3> rotations)
{
    StringBuilder s = new StringBuilder();
    // Apply root's translation and rotation.
    s.Append(rootPosition.x + " " + rootPosition.y + " " + rootPosition.z + " ");
    s.Append(rootRotation.z + " " + rootRotation.x + " " + rootRotation.y + " ");

    for(int i=1; i<rotations.Count; i++) // start at 1 ==> skip rotation of the root.

    {
        s.Append(rotations[i].z + " " + rotations[i].x + " " + rotations[i].y + " ");
    }
    s.Append("\n");
    return s.ToString();
}

1 个答案:

答案 0 :(得分:0)

我说您有充分的理由按Zrotation Xrotation Yrotation的顺序获得BVH的值。

来自Quaternion.eulerAngles

  

围绕z轴旋转euler.z度,围绕x轴旋转euler.x度和围绕y轴旋转euler.y度的旋转(按此顺序)

所以我认为错误在于

Quaternion qBefore = qY * qX * qZ;

使用错误的顺序。


它应该是

Quaternion qBefore = qZ * qX * qY;

我建议改用Quaternion.Euler

  

返回围绕z轴旋转z度,围绕x轴旋转x度和围绕y轴旋转y度的旋转。

Quaternion qBefore = Quaternion.Euler(rotationFromBvh.x, rotationFromBvh.y, rotationFromBvh.z);