Uygulamamın kullanıcısının parmağını ekranda sürükleyerek ekranın ortasına çizilen bir 3B nesneyi döndürmesine izin vermeye çalışıyorum. Ekrandaki yatay bir hareket sabit bir Y ekseni etrafında dönme anlamına gelir ve dikey bir hareket X ekseni etrafında dönme anlamına gelir. Sahip olduğum sorun, sadece bir eksen etrafında dönmeye izin verirseniz, nesne iyi döner, ancak ikinci bir döndürme tanıttığımda nesne beklendiği gibi dönmüyor olmasıdır.
İşte olanların bir resmi:
Mavi eksen sabit eksenimi temsil ediyor. Bu sabit mavi eksene sahip ekranı hayal edin. Nesnenin buna göre dönmesini istiyorum. Olan şey kırmızı.
İşte bildiklerim:
- Y (0, 1, 0) etrafındaki ilk döndürme, modelin mavi alandan (bu boşluk A olarak adlandırılır) başka bir boşluğa (bu boşluk B olarak adlandırılır) hareket etmesine neden olur
- Vektörü (1, 0, 0) kullanarak tekrar döndürmeye çalışmak, B boşluğundaki x ekseni etrafında döner.
Bildiğim (düşündüğüm) göz önüne alındığında, denediğim şey (kısaca W koordinatını bırakarak):
- İlk önce bir Kuaterniyon kullanarak Y (0, 1, 0) etrafında döndürün.
- Dönüş Y Kuaterniyonunu bir Matrise dönüştürün.
- X eksenini yeni boşluğa göre almak için Y dönüş matrisini sabit eksenim x Vector (1, 0, 0) ile çarpın.
- Bir Kuvaterniyon kullanarak bu yeni X Vector etrafında döndürün.
İşte kod:
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;
}
Bu beklediğim gibi çalışmıyor. Dönme çalışıyor gibi görünüyor, ancak bir noktada yatay hareket Y ekseni etrafında dönmüyor, Z ekseni etrafında dönüyor gibi görünüyor.
Anlayışımın yanlış olup olmadığından veya başka bir şeyin soruna neden olup olmadığından emin değilim. Döndürmenin yanı sıra nesneye yaptığım başka dönüşümler de var. Döndürme uygulamadan önce nesneyi merkeze taşıyorum. Yukarıdaki fonksiyonumdan döndürülen matrisi kullanarak döndürüyorum, sonra nesneyi görebilmek için Z yönünde -2'ye çeviriyorum. Ben bu benim rotasyonları berbat olduğunu sanmıyorum, ama yine de bunun için kod:
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;
}
Birkaç gündür bunun üzerinde kaldım. Yardım çok takdir edilmektedir.
================================================== ================
GÜNCELLEME:
Bunu Unity'de çalıştırmak kolaydır. Başlangıçta ortalanmış bir küpü döndüren bazı kodlar şunlardır:
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);
}
}
Dönüşleri beklediğim gibi yapan kısım , dönüşümdeki fonksiyonun Space.World
parametresidir Rotate
.
Birlik kullanabilseydim, maalesef bu davranışı kendim kodlamalıyım.