2010-11-04 26 views
12

J'ai deux matrices de rotation qui décrivent des rotations arbitraires. (4x4 opengl compatible)interpoler entre les matrices de rotation

maintenant je veux interpoler entre eux, de sorte qu'il suit un chemin radial d'une rotation à l'autre. penser à une caméra sur un trépied à la recherche d'un sens, puis en tournant. Si j'interpole chaque composant, j'obtiens un résultat de compression, donc je pense que j'ai besoin d'interpoler seulement certains composants de la matrice. mais lesquels?

Répondre

1

Vous devez convertir la matrice en une représentation différente - les quaternions fonctionnent bien pour cela, et l'interpolation des quaternions est une opération bien définie.

+0

merci! alors comment puis-je convertir une matrice en quaternion? – clamp

+0

Je vous suggère de commencer par lire ceci: http://en.wikipedia.org/wiki/Quaternion – tdammers

14

Vous devez utiliser SLERP pour les parties en rotation des matrices, et linéaire pour les autres parties. Le meilleur moyen est de transformer vos matrices en quaternions et d'utiliser le quaternion (plus simple) SLERP: http://en.wikipedia.org/wiki/Slerp.

Je suggère de lire Graphic Gems II ou III, en particulier les sections sur la décomposition des matrices en transformations plus simples. Voici la source de Spencer W. Thomas pour ce chapitre:

http://tog.acm.org/resources/GraphicsGems/gemsii/unmatrix.c

Bien sûr, je vous suggère d'apprendre comment faire vous-même. Ce n'est vraiment pas si dur, juste beaucoup d'algèbre agaçante. Et enfin, voici un article sur la façon de transformer une matrice en un quaternion, et à l'arrière, par le logiciel Id: http://cache-www.intel.com/cd/00/00/29/37/293748_293748.pdf


Modifier: Ceci est la formule à peu près tout le monde cite, il est d'une 1985 SIGGRAPH papier.

alt text

:

- qm = interpolated quaternion 
- qa = quaternion a (first quaternion to be interpolated between) 
- qb = quaternion b (second quaternion to be interpolated between) 
- t = a scalar between 0.0 (at qa) and 1.0 (at qb) 
- θ is half the angle between qa and qb 

code:

quat slerp(quat qa, quat qb, double t) { 
    // quaternion to return 
    quat qm = new quat(); 
    // Calculate angle between them. 
    double cosHalfTheta = qa.w * qb.w + qa.x * qb.x + qa.y * qb.y + qa.z * qb.z; 
    // if qa=qb or qa=-qb then theta = 0 and we can return qa 
    if (abs(cosHalfTheta) >= 1.0){ 
     qm.w = qa.w;qm.x = qa.x;qm.y = qa.y;qm.z = qa.z; 
     return qm; 
    } 
    // Calculate temporary values. 
    double halfTheta = acos(cosHalfTheta); 
    double sinHalfTheta = sqrt(1.0 - cosHalfTheta*cosHalfTheta); 
    // if theta = 180 degrees then result is not fully defined 
    // we could rotate around any axis normal to qa or qb 
    if (fabs(sinHalfTheta) < 0.001){ // fabs is floating point absolute 
     qm.w = (qa.w * 0.5 + qb.w * 0.5); 
     qm.x = (qa.x * 0.5 + qb.x * 0.5); 
     qm.y = (qa.y * 0.5 + qb.y * 0.5); 
     qm.z = (qa.z * 0.5 + qb.z * 0.5); 
     return qm; 
    } 
    double ratioA = sin((1 - t) * halfTheta)/sinHalfTheta; 
    double ratioB = sin(t * halfTheta)/sinHalfTheta; 
    //calculate Quaternion. 
    qm.w = (qa.w * ratioA + qb.w * ratioB); 
    qm.x = (qa.x * ratioA + qb.x * ratioB); 
    qm.y = (qa.y * ratioA + qb.y * ratioB); 
    qm.z = (qa.z * ratioA + qb.z * ratioB); 
    return qm; 
} 

De: http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/

+0

ok, merci disons que j'utilise Quaternions à la place. puis-je interpoler chacun des 4 composants pour obtenir une transition en douceur? – clamp

+0

Edited ma réponse avec la formule et un code plus facile à digérer. –

+0

Vous premier groupe de liens ne fonctionne plus :( – Narfanator