Certaines choses utiles sur les rotations:
- Les trois vecteurs orthonormés disposés en rangées définissent une transformation en une nouvelle base (une rotation dans cette base).
- La transposition de toute rotation est son inverse.
- Ainsi, trois vecteurs orthonormés disposés en colonnes définissent une rotation d'une certaine base dans votre cadre de référence "monde".
Ainsi, le problème est de trouver un ensemble de trois vecteurs orthonormés et les organiser comme
| x1 x2 x3 0 |
| y1 y2 y3 0 |
| z1 z2 z3 0 |
| 0 0 0 1 |
c'est exactement ce que la méthode décrite essaie de faire, si cela ne fonctionne pas, alors il est un problème avec votre implémentation.
Nous pouvons évidemment utiliser votre normal comme (x1, y1, z1), mais le problème est que le système a une infinité de solutions pour les deux vecteurs restants (bien que connaître l'un d'eux vous donne l'autre, comme produit croisé) . Le code suivant devrait donner un vecteur stable perpendiculaire à (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];
Il utilise essentiellement Gram-Schmidt orthogonalisation avec la dimension qui est déjà le plus orthogonal au vecteur normal.v3 peut alors être obtenu en prenant le produit croisé normal
et v2
.
Vous devrez peut-être prendre soin de configurer la rotation, il s'agit de l'origine, donc vous devez appliquer la translation après la rotation et c'est pour les vecteurs colonnes plutôt que pour les vecteurs lignes. Si vous utilisez OpenGL, assurez-vous qu'OpenGL accepte les tableaux dans l'ordre des colonnes (plutôt que dans l'ordre majeur de la rangée C), donc vous devrez peut-être transposer. Je crains de ne pas avoir testé ce qui précède, je l'ai simplement récupéré à partir d'un code que j'ai écrit il y a un certain temps et je l'ai adapté à votre problème! J'espère n'avoir oublié aucun détail.
Edit: J'ai oublié quelque chose :)
La matrice ci-dessus suppose votre normale au polygone est le long de l'axe x, et je soupçonne de Furtif il ne sera pas, tout ce que vous devez faire est Mettez le vecteur "normal" dans la colonne correcte de la matrice de rotation, et v2/v3 dans les deux autres colonnes. Donc, si la normale à votre polygone est le long de l'axe z, alors la normale va dans la troisième colonne et v2/v3 vont dans les deux premières colonnes. Nous sommes désolés si cela peut causer de la confusion.
Pour une raison aléatoire je me retrouve à revoir cette réponse, quand je choisis la dimension la plus orthogonale j'aurais dû utiliser la valeur absolue des composantes du vecteur normal - j'ai corrigé cela dans la réponse. –
Que faire si la normale n'est pas le long des axes? Si, à la place, c'est quelque chose comme <1, 1, 1>? – Ren
L'algorithme mappe une normale arbitraire sur l'un des axes (ou l'inverse), si vous voulez faire tourner une normale sur une autre normale, je trouverais une rotation autour du produit croisé des deux normales. –