私はアプリのユーザーに、画面上で指をドラッグして、画面の中央に描かれた3Dオブジェクトを回転させようとしています。画面上の水平方向の動きは、固定されたY軸の周りの回転を意味し、垂直方向の動きは、X軸の周りの回転を意味します。私が抱えている問題は、1つの軸の周りの回転を許可するだけでオブジェクトが正常に回転するのに、2番目の回転を導入するとすぐにオブジェクトが期待どおりに回転しないことです。
これが何が起こっているかの写真です:
青い軸は固定軸を表します。この固定された青い軸を持つ画面を描きます。これは、オブジェクトに関連して回転させたいものです。何が起こっているのかは赤です。
私が知っていることは次のとおりです。
- Y(0、1、0)を中心とした最初の回転により、モデルは青いスペース(このスペースAと呼ばれる)から別のスペース(このスペースBと呼ばれる)に移動します。
- ベクトル(1、0、0)を使用して再度回転しようとすると、スペースAではなくスペースBでx軸を中心に回転します。
私が知っていることを考えると、私が試したものがあります(簡潔にするためにW座標を除外します):
- 最初に、クォータニオンを使用してY(0、1、0)を中心に回転します。
- 回転Yクォータニオンをマトリックスに変換します。
- Y回転行列に固定軸x Vector(1、0、0)を掛けて、新しい空間に関連するX軸を取得します。
- クォータニオンを使用して、この新しいXベクトルを中心に回転します。
コードは次のとおりです。
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;
}
これは期待どおりに機能しません。回転は機能しているように見えますが、ある時点で水平方向の動きがY軸を中心に回転せず、Z軸を中心に回転しているように見えます。
私の理解が間違っているのか、他の何かが問題を引き起こしているのかはわかりません。回転以外にも、オブジェクトに対して行っている他の変換がいくつかあります。回転を適用する前にオブジェクトを中心に移動します。上記の関数から返されたマトリックスを使用して回転し、Z方向に-2変換して、オブジェクトが見えるようにします。私はこれが私の回転を台無しにしているとは思わないが、とにかくそれのためのコードはここにある:
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;
}
私はこれに数日間こだわっています。ヘルプは大歓迎です。
================================================= ================
更新:
これをUnityで機能させるのは簡単です。以下は、原点を中心に立方体を回転させるコードです。
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);
}
}
回転を期待どおりに動作させる部分は、変換の関数Space.World
へのパラメーターですRotate
。
Unityを使用できる場合、残念ながら自分でこの動作をコーディングする必要があります。