确定四分之一旋转是顺时针还是逆时针

时间:2014-08-26 04:50:30

标签: unity3d quaternions

我正在使用以下代码处理将我的播放器模型旋转到鼠标位置。

void Update() {
    // Generate a plane that intersects the transform's position with an upwards normal.
    Plane playerPlane = new Plane(Vector3.up, transform.position);

    // Generate a ray from the cursor position
    Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

    // Determine the point where the cursor ray intersects the plane.
    // This will be the point that the object must look towards to be looking at the mouse.
    // Raycasting to a Plane object only gives us a distance, so we'll have to take the distance,
    // then find the point along that ray that meets that distance. This will be the point
    // to look at.
    float hitdist = 0f;
    // If the ray is parallel to the plane, Raycast will return false.
    if (playerPlane.Raycast(ray, out hitdist)) {
        // Get the point along the ray that hits the calculated distance.
        var targetPoint = ray.GetPoint(hitdist);

        // Determine the target rotation. This is the rotation if the transform looks at the target point.
        Quaternion targetRotation = Quaternion.LookRotation(targetPoint - transform.position);


        // Smoothly rotate towards the target point.
        transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, speed * Time.deltaTime); // WITH SPEED
        //transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, 1); // WITHOUT SPEED!!!
    }

我希望能够确定旋转是顺时针还是逆时针以用于动画目的。处理这个问题的最佳方法是什么?我对四元数很不熟悉,所以我不确定如何处理这个问题。

2 个答案:

答案 0 :(得分:1)

四元数之间的角度是无符号的。您将始终获得最短距离,除非您主动指定轴(视点),否则无法定义“逆时针”或“顺时针”。

然而,你可以做的是采取你感兴趣的轴(我认为它是你的基准面的法线......也许是你的世界的垂直?)并采用你的四元数的平面2D组件,将它们映射到那里并计算它们之间的简单2D角度。

Quaternion A; //first Quaternion - this is your desired rotation Quaternion B; //second Quaternion - this is your current rotation

// define an axis, usually just up Vector3 axis = new Vector3(0.0f, 1.0f, 0.0f);

// mock rotate the axis with each quaternion Vector3 vecA = A * axis; Vector3 vecB = B * axis;

// now we need to compute the actual 2D rotation projections on the base plane float angleA = Mathf.Atan2(vecA.x, vecA.z) * Mathf.Rad2Deg; float angleB = Mathf.Atan2(vecB.x, vecB.z) * Mathf.Rad2Deg;

// get the signed difference in these angles var angleDiff = Mathf.DeltaAngle( angleA, angleB );

这应该是它。我自己从来没有这样做,上面的代码没有经过测试。类似于:http://answers.unity3d.com/questions/26783/how-to-get-the-signed-angle-between-two-quaternion.html

即使A或B不是四元数,它也应该有效,但其中一个是欧拉角旋转。

答案 1 :(得分:0)

我认为我可以用一种可以从概念上帮助您的方式来解释整个“四元数的符号角”这一想法。

二维四元数(复数)具有一个符号角,即atan2(B,A)。

但是,考虑复数的更正确的方法是使用无符号角,即acos(A / norm)。然后,当B为正时,该角度相对于XY定向平面,当B为负时,相对于YX定向平面(考虑将XY定向平面当作一张纸并将其翻转然后以这种方式测量角度,在这种情况下,该角度从XY定向平面的角度来看将具有相反的符号。)

在2D中,只有两个定向旋转平面,即XY定向平面和YX定向平面,因此“正负角”的想法实际上只是一个技巧,它既可以获取无正负角又可以定向旋转的平面打包成一个数字。但是,就像四元数一样,复数被自然地编码为无符号角加上定向的旋转平面。

四元数的无符号角相同:acos(A / norm)。但是“符号角”技巧无法在3D中使用,因为现在您可以旋转无限数量的定向平面,因此单个符号角无法像在2D情况下那样对所有旋转信息进行编码。

在3D中使符号角有意义的唯一方法是参考特定的定向平面,例如XY定向平面。您可以将其投影或旋转到该定向平面上,然后测量其相对于该定向平面的正负角。在您的情况下,您希望将四元数投影到定向平面上,然后如果投影的四元数的定向平面与目标定向平面的符号不同,则可以通过获取无符号角并翻转符号来获得有符号角。