2010-12-14 65 views
13

J'ai un modèle pivoté par un quaternion. Je ne peux que définir la rotation, je ne peux pas ajouter ou soustraire de quoi que ce soit. J'ai besoin d'obtenir la valeur d'un axe, et de lui ajouter un angle (peut-être un degré ou un radian?) Et de rajouter le quaternion modifié.tournant un quaternion sur 1 axe?

Comment est-ce que je peux faire ceci? (réponse sur chaque axe).

+1

Je pense que vous avez besoin de clarifier un peu plus loin. Vous dites que vous ne pouvez définir que la rotation ... Un quaternion sert le même but qu'une matrice de rotation. La différence étant que le quaternion est numériquement stable, ils sont plus chers à appliquer à la géométrie 3D mais sont moins coûteux pour la concaténation ... Ils sont donc typiquement utilisés quand de longues séries de rotations doivent être appliquées et ensuite ils sont transformés en rotation matrices avant l'application. S'il vous plaît clarifier ce que vous entendez par réponse sur chaque axe, peut-être vous voulez quaternion -> trois matrice de rotation où chacun est d'environ un axe? – Quaternion

Répondre

29

Vous pouvez multiplier deux quaternions ensemble pour produire un troisième quaternion résultant des deux rotations. Notez que la multiplication du quaternion n'est pas commutative, ce qui signifie que l'ordre est important (si vous le faites plusieurs fois dans votre tête, vous pouvez voir pourquoi).

Vous pouvez produire un quaternion qui représente une rotation d'un angle donné autour d'un axe particulier avec quelque chose comme ceci (excusez le fait qu'il est C++, pas 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(); 
} 

Donc, pour tourner autour de la Axe x par exemple, vous pouvez créer un quaternion avec createFromAxisAngle(1, 0, 0, M_PI/2) et le multiplier par le quaternion de rotation actuel de votre modèle.

+3

Cela a fonctionné. Merci beaucoup!^_^ – William

+0

@William - pas de soucis – sje397

+2

Donc si je veux créer un quaternion avec une rotation de -15 degrés sur l'axe X, je devrais appeler createFromAxisAngle (1, 0, 0, -15 * PI/180)? Merci! – VladN

2

J'ai créé un code exécutable depuis le post de sje397 pour tester d'autres détails plus tard, pensais-je partager. En utilisant C finalement la raison pour aucune classe de 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; 
} 

Sortie

(0,0871557, 0, 0, 0,996195)