c - 四元数 "lookAt"函数

标签 c math opengl quaternions

我正在努力解决以下问题。我正在处理骨骼动画,我希望(即)玩家的头部跟随空间中的另一个物体。我的上轴是 +Z 我的前轴是 +Y,四元数的大小在 W 中。我尝试使用 gluLookAt 的 mesa 代码并使用 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

最佳答案

我认为这个函数可以满足您的需求:

/// <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 的情况下实现 transform.LookAt。

关于c - 四元数 "lookAt"函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12435671/

相关文章:

c - 如果我们将它与 if 和 'equal to' 运算符一起使用,为什么 float 会给出不同的输出?请看下面的代码 :

c - 如何删除获取文件名的路径

algorithm - 如何按数值对数字进行排名?

python - 如何在 Python 中存储计算结果,这样我的程序就不会对同一事物进行两次计算?

xcode - OpenCv ImShow()函数闪烁

c++ - 在 Linux-64 上编译 NeHe(或其他面向 32 位的)示例

c - 如何在变量中获取curl输出?

c - 如何将数组拆分为特定大小

java - 将图像插入java代码编辑器

iphone - 开发iPhone游戏时 "gotchas"是什么?