Algunas cosas útiles acerca de rotaciones:
- Cualquier tres vectores ortonormales dispuestos como filas definen una transformación en una nueva base (una rotación en esa base).
- La transposición de cualquier rotación es inversa.
- Por lo tanto, cualesquiera tres vectores ortonormales dispuestos como columnas definen una rotación desde alguna base en su marco de referencia "mundial".
Por lo tanto, el problema es encontrar cualquier conjunto de tres vectores ortonormales y disponerlos como
| x1 x2 x3 0 |
| y1 y2 y3 0 |
| z1 z2 z3 0 |
| 0 0 0 1 |
esto es exactamente lo que el método que se describe trata de hacer, si no funciona, entonces hay es un problema con su implementación.
Obviamente podemos usar su normal como (x1, y1, z1), pero el problema es que el sistema tiene infinitas soluciones para los dos vectores restantes (aunque conocer uno de ellos le da al otro, como producto cruzado) . El siguiente código debe dar un vector estable perpendicular a (x1, y1, z1):
float normal[3] = { ... };
int imin = 0;
for(int i=0; i<3; ++i)
if(std::abs(normal[i]) < std::abs(normal[imin]))
imin = i;
float v2[3] = {0,0,0};
float dt = normal[imin];
v2[imin] = 1;
for(int i=0;i<3;i++)
v2[i] -= dt*normal[i];
Esto básicamente utiliza Gram-Schmidt descomposición ortogonal con la dimensión que ya es más ortogonal al vector normal.v3 puede obtenerse tomando el producto cruzado de normal
y v2
.
Es posible que deba tener cuidado al configurar la rotación, se trata del origen, por lo que debe aplicar la traducción después de la rotación y para los vectores de columnas en lugar de los vectores de filas. Si usa OpenGL, observe que OpenGL toma las matrices en orden principal de la columna (en lugar del orden principal de la fila de C), por lo que es posible que deba transponer.
Me temo que no he probado lo anterior, simplemente lo he atrapado de algún código que escribí hace un tiempo y lo he adaptado a su problema. Espero no haber olvidado ningún detalle.
Edit: se olvidó de algo :)
La matriz anterior supone su normal al polígono es a lo largo del eje x, y tengo la sospecha de que no será, todo lo que necesita hacer es coloque el vector "normal" en la columna correcta de la matriz de rotación, y v2/v3 en las otras dos columnas. Entonces, si la normal a su polígono es a lo largo del eje z, entonces la normal va en la tercera columna y v2/v3 en las dos primeras columnas.
Lo siento si eso causa alguna confusión.
Por una razón aleatoria me encuentro revisitando esta respuesta, cuando selecciono la dimensión más ortogonal debería haber usado el valor absoluto de los componentes normales del vector; lo he corregido en la respuesta. –
¿Qué pasa si la normal no está en ninguno de los ejes? Si, en cambio, es algo así como <1, 1, 1>? – Ren
El algoritmo asigna una normalidad arbitraria a uno de los ejes (o viceversa), si desea rotar una normal a otra normal, encontraría una rotación sobre el producto cruzado de las dos normales. –