2010-11-04 18 views
12

tengo dos matrices de rotación que describen rotaciones arbitrarias. (4x4 compatible con OpenGL)interpolar entre las matrices de rotación

ahora quiero interpolar entre ellos, de modo que siga una trayectoria radial de una rotación a la otra. piense en una cámara en un trípode mirando hacia un lado y luego girando.

si interpolo cada componente, obtengo un resultado de compresión, así que creo que necesito interpolar solo ciertos componentes de la matriz. pero cuales?

Respuesta

1

Necesita convertir la matriz en una representación diferente; los cuaterniones funcionan bien para esto, y la interpolación de cuaterniones es una operación bien definida.

+0

gracias! Entonces, ¿cómo puedo convertir una matriz en un cuaternión? – clamp

+0

Sugiero que comiences leyendo esto: http://en.wikipedia.org/wiki/Quaternion – tdammers

14

Debe usar SLERP para las partes rotatorias de las matrices, y lineal para las otras partes. La mejor manera es convertir sus matrices en cuaterniones y usar el cuaternión (más simple) SLERP: http://en.wikipedia.org/wiki/Slerp.

Sugiero leer Graphic Gems II o III, específicamente las secciones sobre matrices en descomposición en transformaciones más simples. Aquí está la fuente Spencer W. Thomas' para este capítulo:

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

Por supuesto, le sugiero que aprender cómo hacer esto por sí mismo. Realmente no es tan difícil, solo un montón de álgebra molesta. Y, por último, aquí hay un gran papel en cómo convertir una matriz en un cuaternión, y de vuelta, por id Software: http://cache-www.intel.com/cd/00/00/29/37/293748_293748.pdf


Editar: Esta es la fórmula casi todo el mundo cita, que es de una SIGGRAPH 1985 papel.

alt text

Dónde:

- 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 

Código:

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; 
} 

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

+0

bien, gracias digamos que uso Quaternions en su lugar. ¿Acabo de interpolar cada uno de los 4 componentes para obtener una transición suave? – clamp

+0

Edité mi respuesta con la fórmula y algunos códigos más fáciles de digerir. –

+0

Tu primer grupo de enlaces ya no funciona :( – Narfanator

Cuestiones relacionadas