9

次の問題で苦労しています。私は骨のアニメーションを扱っており、(つまり) プレイヤーの頭が空間内の別のオブジェクトをたどる必要があります。上軸は +Z、前軸は +Y、クォータニオンの大きさは W です。gluLookAt のメサ コードを使用し、3x3 マトリックスを使用してクォータニオンに変換しようとしましたが、期待どおりに動作しません。だから私は別の方向に行く...

これまでのところ、少なくともプレーヤーの頭が適切な方向に回転している(ただし、X角度がY回転軸に影響を与えているように見える)「ほぼ」動作している次のコードを取得しましたが、オブジェクトを追跡する代わりにまっすぐ上を向いています約65度の床:

qt LookRotation( v3 lookAt, v3 upDirection )
{
qt t;

v3 forward = lookAt;
v3 up = upDirection;

OrthoNormalize( &forward, &up );

v3 right = v3_cross( up, forward );

mat3 m = mat3_make( right.x, up.x, forward.x,
                    right.y, up.y, forward.y,
                    right.z, up.z, forward.z );

t.w = sqrtf( 1.0f +
             m.r[ 0 ].x +
             m.r[ 1 ].y +
             m.r[ 2 ].z ) * 0.5f;

float w4_recip = 1.0f / ( 4.0f * t.w );

t.x = ( m.r[ 2 ].y - m.r[ 1 ].z ) * w4_recip;

t.y = ( m.r[ 0 ].z - m.r[ 2 ].x ) * w4_recip;

t.z = ( m.r[ 1 ].x - m.r[ 0 ].y ) * w4_recip;

t = qt_normalize( t );

return t;
}

... ... ...

v3 v = v3_sub( vec4_to_v3( transform.world.r[ 3 ] /* The object XYZ location in the world */),
           skeleton->final_pose.location[ i ] /* i = The head joint location */ );

v = v3_normalize( v );

qt q = LookRotation( v,
        v3_make( 0.0f, 0.0f, 1.0f ) );

誰かがこの問題を理解するのを手伝ってくれますか...私はクォータニオンに慣れていないので、どこを台無しにしたのか本当にわかりません。かなりの調査の後、基本的に私がやりたいことは、Unity API のようなものです: http://docs.unity3d.com/Documentation/ScriptReference/Quaternion.LookRotation.html

4

3 に答える 3

13

この関数は必要なことを行うと思います:

/// <summary>
/// Evaluates a rotation needed to be applied to an object positioned at sourcePoint to face destPoint
/// </summary>
/// <param name="sourcePoint">Coordinates of source point</param>
/// <param name="destPoint">Coordinates of destionation point</param>
/// <returns></returns>
public static Quaternion LookAt(Vector3 sourcePoint, Vector3 destPoint)
{
    Vector3 forwardVector = Vector3.Normalize(destPoint - sourcePoint);

    float dot = Vector3.Dot(Vector3.forward, forwardVector);

    if (Math.Abs(dot - (-1.0f)) < 0.000001f)
    {
        return new Quaternion(Vector3.up.x, Vector3.up.y, Vector3.up.z, 3.1415926535897932f);
    }
    if (Math.Abs(dot - (1.0f)) < 0.000001f)
    {
        return Quaternion.identity;
    }

    float rotAngle = (float)Math.Acos(dot);
    Vector3 rotAxis = Vector3.Cross(Vector3.forward, forwardVector);
    rotAxis = Vector3.Normalize(rotAxis);
    return CreateFromAxisAngle(rotAxis, rotAngle);
}

// just in case you need that function also
public static Quaternion CreateFromAxisAngle(Vector3 axis, float angle)
{
    float halfAngle = angle * .5f;
    float s = (float)System.Math.Sin(halfAngle);
    Quaternion q;
    q.x = axis.x * s;
    q.y = axis.y * s;
    q.z = axis.z * s;
    q.w = (float)System.Math.Cos(halfAngle);
    return q;
}

このコードはここから来ています: https://gamedev.stackexchange.com/questions/15070/orienting-a-model-to-face-a-target 変換の実装である私のケースに合うように少し変更しました。 Unity3D を使用しない LookAt。

于 2013-07-15T12:52:07.423 に答える