Tôi đang cố gắng để người dùng ứng dụng của mình xoay một vật thể 3D được vẽ ở giữa màn hình bằng cách kéo ngón tay của họ trên màn hình. Chuyển động ngang trên màn hình có nghĩa là xoay quanh trục Y cố định và chuyển động dọc có nghĩa là xoay quanh trục X. Vấn đề tôi gặp phải là nếu tôi chỉ cho phép xoay quanh một trục thì đối tượng sẽ quay tốt, nhưng ngay khi tôi giới thiệu một vòng quay thứ hai thì đối tượng không quay như mong đợi.
Dưới đây là hình ảnh về những gì đang xảy ra:
Trục màu xanh đại diện cho trục cố định của tôi. Hình ảnh màn hình có trục màu xanh cố định này. Đây là những gì tôi muốn đối tượng xoay liên quan đến. Những gì đang xảy ra là màu đỏ.
Đây là những gì tôi biết:
- Vòng xoay đầu tiên quanh Y (0, 1, 0) làm cho mô hình di chuyển từ không gian màu xanh lam (gọi không gian này là A) sang không gian khác (gọi không gian này là B)
- Cố gắng xoay một lần nữa bằng vectơ (1, 0, 0) xoay quanh trục x trong không gian B KHÔNG trong không gian A không phải là điều tôi muốn làm.
Đây là những gì tôi đã thử, đưa ra những gì tôi (nghĩ) mà tôi biết (bỏ qua tọa độ W cho ngắn gọn):
- Đầu tiên xoay quanh Y (0, 1, 0) bằng cách sử dụng Quancyion.
- Chuyển đổi phép quay Y Quancyion thành Ma trận.
- Nhân ma trận xoay Y với trục cố định của tôi x Vector (1, 0, 0) để có trục X liên quan đến không gian mới.
- Xoay quanh X Vector mới này bằng cách sử dụng Quancyion.
Đây là mã:
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;
}
Điều này không hoạt động như tôi mong đợi. Xoay dường như hoạt động, nhưng tại một số điểm chuyển động ngang không xoay quanh trục Y, nó dường như xoay quanh trục Z.
Tôi không chắc liệu sự hiểu biết của tôi là sai hay nếu điều gì khác gây ra vấn đề. Tôi có một số biến đổi khác mà tôi đang làm với đối tượng ngoài xoay vòng. Tôi di chuyển đối tượng đến trung tâm trước khi áp dụng xoay vòng. Tôi xoay nó bằng cách sử dụng ma trận trả về từ hàm của tôi ở trên, sau đó tôi dịch nó -2 theo hướng Z để tôi có thể nhìn thấy đối tượng. Tôi không nghĩ rằng điều này đang làm rối tung các vòng quay của tôi, nhưng đây là mã cho dù sao đi nữa:
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;
}
Tôi đã bị mắc kẹt trong vài ngày. Giúp đỡ được nhiều đánh giá cao.
================================================== ================
CẬP NHẬT:
Làm cho điều này để làm việc trong Unity là đơn giản. Đây là một số mã xoay một khối lập phương ở giữa:
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);
}
}
Phần làm cho các phép quay hoạt động như tôi mong đợi là Space.World
tham số cho Rotate
hàm trên biến đổi.
Nếu tôi có thể sử dụng Unity, tôi sẽ không may tự mình viết mã cho hành vi này.