내 앱 사용자가 화면에서 손가락을 드래그하여 화면 중앙에 그려진 3D 객체를 회전 시키려고합니다. 화면에서 수평 이동은 고정 된 Y 축을 중심으로 회전하는 것을 의미하고 수직 이동은 X 축을 중심으로 회전하는 것을 의미합니다. 내가 겪고있는 문제는 한 축을 중심으로 회전을 허용하면 객체가 잘 회전하지만 두 번째 회전을 시작하자마자 예상대로 객체가 회전하지 않는다는 것입니다.
다음은 무슨 일이 일어나고 있는지 보여주는 그림입니다.
파란색 축은 고정 축을 나타냅니다. 이 고정 된 파란색 축이있는 화면을 그리십시오. 이것이 객체가 회전하기를 원하는 것입니다. 일어나는 일은 빨간색입니다.
내가 아는 것은 다음과 같습니다.
- Y (0, 1, 0) 주위의 첫 번째 회전으로 인해 모델이 파란색 공간 (이 공간 A라고 함)에서 다른 공간 (이 공간 B라고 함)으로 이동합니다.
- 벡터 (1, 0, 0)를 사용하여 다시 회전하려고하면 공간 A의 공간이 아닌 공간 B의 x 축을 중심으로 회전합니다.
내가 아는 것을 감안할 때 내가 시도한 것은 다음과 같습니다 (간결하게 W 코드를 생략).
- 먼저 쿼터니언을 사용하여 Y (0, 1, 0) 주위를 회전합니다.
- 회전 Y 쿼터니언을 행렬로 변환합니다.
- Y 회전 행렬에 고정 축 x 벡터 (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를 사용할 수 있다면 불행히도이 동작을 직접 코딩해야합니다.