J'essaie de laisser l'utilisateur de mon application faire pivoter un objet 3D dessiné au centre de l'écran en faisant glisser son doigt sur l'écran. Un mouvement horizontal à l'écran signifie une rotation autour d'un axe Y fixe, et un mouvement vertical signifie une rotation autour de l'axe X. Le problème que j'ai est que si je permets juste une rotation autour d'un axe, l'objet tourne bien, mais dès que j'introduis une deuxième rotation, l'objet ne tourne pas comme prévu.
Voici une photo de ce qui se passe:
L'axe bleu représente mon axe fixe. Imaginez l'écran ayant cet axe bleu fixe. C'est à cela que je veux que l'objet tourne par rapport. Ce qui se passe est en rouge.
Voici ce que je sais:
- La première rotation autour de Y (0, 1, 0) provoque le déplacement du modèle de l'espace bleu (appelez cet espace A) vers un autre espace (appelez cet espace B)
- Essayer de pivoter à nouveau en utilisant le vecteur (1, 0, 0) tourne autour de l'axe x dans l'espace B PAS dans l'espace A, ce qui n'est pas ce que je veux faire.
Voici ce que j'ai essayé, compte tenu de ce que je pense (je pense) (en omettant la coordonnée W par souci de concision):
- Faites d'abord tourner autour de Y (0, 1, 0) à l'aide d'un Quaternion.
- Convertissez la rotation Y Quaternion en une matrice.
- Multipliez la matrice de rotation Y par mon axe fixe x vecteur (1, 0, 0) pour obtenir l'axe X par rapport au nouvel espace.
- Tournez autour de ce nouveau vecteur X à l'aide d'un Quaternion.
Voici le code:
private float[] rotationMatrix() {
final float[] xAxis = {1f, 0f, 0f, 1f};
final float[] yAxis = {0f, 1f, 0f, 1f};
float[] rotationY = Quaternion.fromAxisAngle(yAxis, -angleX).toMatrix();
// multiply x axis by rotationY to put it in object space
float[] xAxisObjectSpace = new float[4];
multiplyMV(xAxisObjectSpace, 0, rotationY, 0, xAxis, 0);
float[] rotationX = Quaternion.fromAxisAngle(xAxisObjectSpace, -angleY).toMatrix();
float[] rotationMatrix = new float[16];
multiplyMM(rotationMatrix, 0, rotationY, 0, rotationX, 0);
return rotationMatrix;
}
Cela ne fonctionne pas comme je l'espère. La rotation semble fonctionner, mais à un moment donné, le mouvement horizontal ne tourne pas autour de l'axe Y, il semble tourner autour de l'axe Z.
Je ne sais pas si ma compréhension est fausse ou si quelque chose d'autre cause un problème. J'ai d'autres transformations que je fais à l'objet en plus de la rotation. Je déplace l'objet au centre avant d'appliquer la rotation. Je le fais pivoter en utilisant la matrice renvoyée par ma fonction ci-dessus, puis je le translate -2 dans la direction Z pour que je puisse voir l'objet. Je ne pense pas que cela perturbe mes rotations, mais voici le code pour cela de toute façon:
private float[] getMvpMatrix() {
// translates the object to where we can see it
final float[] translationMatrix = new float[16];
setIdentityM(translationMatrix, 0);
translateM(translationMatrix, 0, translationMatrix, 0, 0f, 0f, -2);
float[] rotationMatrix = rotationMatrix();
// centers the object
final float[] centeringMatrix = new float[16];
setIdentityM(centeringMatrix, 0);
float moveX = (extents.max[0] + extents.min[0]) / 2f;
float moveY = (extents.max[1] + extents.min[1]) / 2f;
float moveZ = (extents.max[2] + extents.min[2]) / 2f;
translateM(centeringMatrix, 0, //
-moveX, //
-moveY, //
-moveZ //
);
// apply the translations/rotations
final float[] modelMatrix = new float[16];
multiplyMM(modelMatrix, 0, translationMatrix, 0, rotationMatrix, 0);
multiplyMM(modelMatrix, 0, modelMatrix, 0, centeringMatrix, 0);
final float[] mvpMatrix = new float[16];
multiplyMM(mvpMatrix, 0, projectionMatrix, 0, modelMatrix, 0);
return mvpMatrix;
}
Je suis coincé là-dessus depuis quelques jours. L'aide est très appréciée.
================================================== ================
MISE À JOUR:
Faire fonctionner cela dans Unity est simple. Voici un code qui fait pivoter un cube centré à l'origine:
public class CubeController : MonoBehaviour {
Vector3 xAxis = new Vector3 (1f, 0f, 0f);
Vector3 yAxis = new Vector3 (0f, 1f, 0f);
// Update is called once per frame
void FixedUpdate () {
float horizontal = Input.GetAxis ("Horizontal");
float vertical = Input.GetAxis ("Vertical");
transform.Rotate (xAxis, vertical, Space.World);
transform.Rotate (yAxis, -horizontal, Space.World);
}
}
La partie qui fait que les rotations se comportent comme je l'attends est le Space.World
paramètre de la Rotate
fonction sur la transformation.
Si je pouvais utiliser Unity je le ferais, malheureusement, je dois coder ce comportement moi-même.