2010-12-14 93 views
13

我有一个由四元数旋转的模型。我只能设置旋转,我不能从任何东西中加或减。我需要得到一个坐标轴的值,并且添加一个角度(可能是度数或弧度?),然后重新添加修改后的四元数。在一个轴上旋转一个四元数?

我该怎么做? (在每个轴上回答)。

+1

我认为你需要进一步澄清了一点。你说你只能设置旋转......四元数的作用与旋转矩阵相同。不同之处在于,四元数在数值上是稳定的,它们应用于3D几何体更昂贵,但串联的成本更低......因此,它们通常在需要应用长序列旋转时使用,然后将它们转换回旋转申请前的矩阵。请澄清你的意思回答每个轴,也许你想要四元数 - >三个旋转矩阵,其中每个是关于一个轴? – Quaternion 2010-12-14 07:27:12

回答

29

您可以将两个四元数相乘以产生第三个四元数,这是两次旋转的结果。请注意,四元数乘法不是可交换的,这意味着顺序很重要(如果你在头几次这样做,你可以看到为什么)。

可以产生表示通过围绕特定轴线成一定角度的旋转像这样的东西(原谅的事实,这是C++,而不是Java)四元数:

Quaternion Quaternion::create_from_axis_angle(const double &xx, const double &yy, const double &zz, const double &a) 
{ 
    // Here we calculate the sin(theta/2) once for optimization 
    double factor = sin(a/2.0); 

    // Calculate the x, y and z of the quaternion 
    double x = xx * factor; 
    double y = yy * factor; 
    double z = zz * factor; 

    // Calcualte the w value by cos(theta/2) 
    double w = cos(a/2.0); 

    return Quaternion(x, y, z, w).normalize(); 
} 

所以围绕旋转例如,你可以用createFromAxisAngle(1, 0, 0, M_PI/2)创建一个四元数,并将它乘以模型的当前旋转四元数。

+3

工作。非常感谢你!^_^ – William 2010-12-14 07:54:21

+0

@William - 无后顾之忧 – sje397 2010-12-14 09:50:06

+2

所以如果我想在X轴上创建一个-15度旋转的四元数,我应该调用createFromAxisAngle(1,0,0,-15 * PI/180)?谢谢! – VladN 2012-10-25 13:15:58

2

从sje397的帖子中创建了一个可运行的代码,用于测试其他细节,以为我会分享。最终使用C没有Quaternion类的原因。

#include <iostream> 
#include <math.h> 
using namespace std; 

struct float4{ 
    float x; 
    float y; 
    float z; 
    float w; 
}; 
float4 make_float4(float x, float y, float z, float w){ 
    float4 quat = {x,y,z,w}; 
    return quat; 
} 
float dot(float4 a) 
{ 
    return (((a.x * a.x) + (a.y * a.y)) + (a.z * a.z)) + (a.w * a.w); 
} 
float4 normalize(float4 q) 
{ 
    float num = dot(q); 
    float inv = 1.0f/(sqrtf(num)); 
    return make_float4(q.x * inv, q.y * inv, q.z * inv, q.w * inv); 
} 
float4 create_from_axis_angle(const float &xx, const float &yy, const float &zz, const float &a) 
{ 
    // Here we calculate the sin(theta/2) once for optimization 
    float factor = sinf(a/2.0f); 

    float4 quat; 
    // Calculate the x, y and z of the quaternion 
    quat.x = xx * factor; 
    quat.y = yy * factor; 
    quat.z = zz * factor; 

    // Calcualte the w value by cos(theta/2) 
    quat.w = cosf(a/2.0f); 
    return normalize(quat); 
} 
int main() 
{ 
    float degrees = 10.0f; 
    float4 quat = create_from_axis_angle(1, 0, 0, degrees*(3.14159f/180.0f)); 
    cout << "> (" << quat.x << ", " <<quat.y << ", " <<quat.z << ", " <<quat.w << ")" << endl; 
    return 0; 
} 

输出

(0.0871557,0,0,0.996195)