Ich versuche, dem Benutzer meiner App das Drehen eines in der Mitte des Bildschirms gezeichneten 3D-Objekts zu ermöglichen, indem er seinen Finger auf dem Bildschirm zieht. Eine horizontale Bewegung auf dem Bildschirm bedeutet eine Drehung um eine feste Y-Achse, und eine vertikale Bewegung bedeutet eine Drehung um die X-Achse. Das Problem, das ich habe, ist, dass wenn ich nur eine Drehung um eine Achse zulasse, das Objekt sich gut dreht, aber sobald ich eine zweite Drehung einführe, dreht sich das Objekt nicht wie erwartet.
Hier ist ein Bild von dem, was passiert:
Die blaue Achse repräsentiert meine feste Achse. Stellen Sie sich den Bildschirm mit dieser festen blauen Achse vor. Ich möchte, dass sich das Objekt in Bezug auf dieses dreht. Was passiert ist in rot.
Folgendes weiß ich:
- Die erste Drehung um Y (0, 1, 0) bewirkt, dass sich das Modell vom blauen Feld (dieses Feld als A bezeichnen) in ein anderes Feld (dieses Feld als B bezeichnen) bewegt.
- Der Versuch, erneut mit dem Vektor (1, 0, 0) zu drehen, dreht sich um die x-Achse in Raum B NICHT in Raum A, was nicht meine Absicht ist.
Folgendes habe ich versucht, vorausgesetzt, was ich (glaube) weiß (der Kürze halber die W-Koordinate weglassen):
- Drehen Sie zuerst mit einem Quaternion um Y (0, 1, 0).
- Wandle die Rotation Y-Quaternion in eine Matrix um.
- Multiplizieren Sie die Y-Rotationsmatrix mit meiner festen Achse x Vektor (1, 0, 0), um die X-Achse in Bezug auf den neuen Raum zu erhalten.
- Drehen Sie sich mit einer Quaternion um diesen neuen X-Vektor.
Hier ist der 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;
}
Das funktioniert nicht so, wie ich es erwarte. Die Drehung scheint zu funktionieren, aber irgendwann dreht sich die horizontale Bewegung nicht um die Y-Achse, sondern um die Z-Achse.
Ich bin mir nicht sicher, ob mein Verständnis falsch ist oder ob etwas anderes ein Problem verursacht. Neben der Rotation gibt es noch einige andere Transformationen, die ich an dem Objekt vornehme. Ich bewege das Objekt in die Mitte, bevor ich es drehe. Ich drehe es mit der von meiner obigen Funktion zurückgegebenen Matrix und übersetze es dann -2 in Z-Richtung, damit ich das Objekt sehen kann. Ich glaube nicht, dass dies meine Rotationen durcheinander bringt, aber hier ist der Code dafür:
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;
}
Ich bin seit ein paar Tagen dabei. Hilfe wird sehr geschätzt.
================================================ ================
AKTUALISIEREN:
Es ist unkompliziert, dies in Unity zum Laufen zu bringen. Hier ist ein Code, der einen am Ursprung zentrierten Würfel dreht:
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);
}
}
Der Teil, der bewirkt, dass sich die Rotationen wie erwartet verhalten, ist der Space.World
Parameter für die Rotate
Funktion der Transformation.
Wenn ich Unity verwenden könnte, müsste ich dieses Verhalten leider selbst codieren.