ฉันพยายามให้ผู้ใช้แอปหมุนวัตถุ 3 มิติที่กึ่งกลางหน้าจอโดยลากนิ้วบนหน้าจอ การเคลื่อนไหวในแนวนอนบนหน้าจอหมายถึงการหมุนรอบแกน Y ที่คงที่และการเคลื่อนที่ในแนวตั้งหมายถึงการหมุนรอบแกน X ปัญหาที่ฉันมีคือถ้าฉันอนุญาตให้หมุนรอบหนึ่งแกนวัตถุจะหมุนได้ดี แต่ทันทีที่ฉันแนะนำการหมุนครั้งที่สองวัตถุจะไม่หมุนตามที่คาดไว้
นี่คือภาพของสิ่งที่เกิดขึ้น:
แกนสีน้ำเงินแสดงถึงแกนคงที่ของฉัน รูปภาพหน้าจอที่มีแกนสีน้ำเงินคงที่นี้ นี่คือสิ่งที่ฉันต้องการให้วัตถุหมุนในความสัมพันธ์กับ สิ่งที่เกิดขึ้นคือสีแดง
นี่คือสิ่งที่ฉันรู้:
- การหมุนรอบแรกรอบ Y (0, 1, 0) ทำให้โมเดลย้ายจากพื้นที่สีน้ำเงิน (เรียกพื้นที่นี้ A) ไปยังพื้นที่อื่น (เรียกพื้นที่นี้ B)
- พยายามหมุนอีกครั้งโดยใช้เวกเตอร์ (1, 0, 0) หมุนรอบแกน x ในอวกาศ B ไม่ได้อยู่ในอวกาศ A ซึ่งไม่ใช่สิ่งที่ฉันตั้งใจจะทำ
นี่คือสิ่งที่ฉันพยายามให้ในสิ่งที่ฉัน (คิด) ฉันรู้ (ออกจาก coord W เพราะความกะทัดรัด):
- หมุนไปรอบ ๆ Y (0, 1, 0) โดยใช้ Quaternion
- แปลงการหมุน Y Quaternion เป็นเมทริกซ์
- คูณเมทริกซ์การหมุน Y ด้วยแกนคงที่ x เวกเตอร์ (1, 0, 0) เพื่อให้ได้แกน X สัมพันธ์กับพื้นที่ใหม่
- หมุน X เวกเตอร์ใหม่โดยใช้ Quaternion
นี่คือรหัส:
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
ฉันไม่แน่ใจว่าความเข้าใจของฉันผิดหรืออย่างอื่นทำให้เกิดปัญหาหรือไม่ ฉันมีการแปลงอื่น ๆ ที่ฉันทำกับวัตถุนอกเหนือจากการหมุน ฉันย้ายวัตถุไปที่กึ่งกลางก่อนที่จะใช้การหมุน ฉันหมุนมันโดยใช้เมทริกซ์ที่คืนมาจากฟังก์ชั่นด้านบนของฉันจากนั้นฉันก็แปลมัน -2 ในทิศทาง Z เพื่อให้ฉันเห็นวัตถุ ฉันไม่คิดว่านี่จะทำให้การหมุนเวียนของฉันยุ่ง แต่นี่คือรหัสสำหรับสิ่งนั้น:
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;
}
ฉันติดอยู่กับเรื่องนี้สองสามวัน ช่วยชื่นชมมาก
================================================== ================
UPDATE:
การทำให้สิ่งนี้ทำงานใน 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 ได้ฉันก็ต้องใช้รหัสพฤติกรรมนี้ด้วยตัวเอง