5

kullanarak bir 6DOF Kamerada 'roll' uygulayan problemler Bu konuya birkaç hafta harcadım ve uygun bir çözüm bulamıyorum ve bazı tavsiyelere ihtiyacım var gibi görünmüyor.LWJGL - Kuaterniyonlar ve bir çeviri matrisi

LWJGL/Java kullanarak bir Camera sınıfı oluşturmaya çalışıyorum ve rulman (yaw), pitch ve roll rotasyonlarını işlemek için Quaternions kullanıyorum. Bu kameranın 3D alandaki tüm 6 derecelik hareketleri gerçekleştirmesini ve yuvarlanmasını istiyorum. Rulman, Perde ve Rulo tüm kuaterniyonlardır. Onları bir 'değişim' kuaterniyonuna çarpar ve bundan bir çeviri matrisi oluşturur. Bunu bir float tamponuna koydum ve model matrisini, matrisini içeren arabamla çoğalıyorum.

Doğru şekilde çalışması için rulman ve pitch rotasyonlarını alabilirim, ancak ruloyu uygularken sorunlarım var. Temel olarak, Z ekseni etrafında dönen (haddeleme) işe yaramıyor. Fotoğraf makinesini "yuvarladığımda", yerel kamera yönü ekseni yerine global Z ekseni etrafında dönüyormuş gibi görünüyor. Ben genellikle quaternionları çarptığım sırasına göre 3'lük 2'yi işe alabilirim, ama onları birlikte çalışamıyorum.

Hepsi bağımsız çalıştığından, bunları birleştirip döndürme matrisi oluşturduğum yönlendirme yöntemimde bir sorun olduğunu varsayarak düşünüyorum. Sorunların bütün sınıf yapıştırarak yaşıyorum, işte rotasyona ilişkin yöntemler ve bildirimleri şunlardır:

private final static float DEGTORAD = (float)(Math.PI/180);  

//Eye - position of the camera in the 3D world. 
private Vector3f eye; 

//Camera axis vectors, calculated each time reorient() is called. 
//Initialized to global x, y, and z axis initially. 
private Vector3f up; 
private Vector3f right; 
private Vector3f direction; 

//Angles of rotation (in degrees)  
private float pitchAngle; 
private float bearingAngle; 
private float rollAngle; 

private Quaternion pitch; 
private Quaternion bearing; 
private Quaternion roll; 

private FloatBuffer viewMatrixBuffer = BufferUtils.createFloatBuffer(16); 
private Quaternion currentOrientation; 

...

/** 
* Change the bearing (yaw) 
* @param bearing delta in degrees 
*/ 
public void bearing(float bearingDelta){ 
    bearingAngle += bearingDelta; 
    if(bearingAngle > 360){ 
     bearingAngle -= 360; 
    }else if(bearingAngle < 0){ 
     bearingAngle += 360; 
    } 
    bearing.setFromAxisAngle(new Vector4f(0f, 1f, 0f, bearingAngle * DEGTORAD)); 
    bearing.normalise(); 
} 

/** 
* Change the pitch 
* @param pitch delta in degrees 
*/ 
public void pitch(float pitchDelta){ 
    pitchAngle += pitchDelta; 
    if(pitchAngle > 360){ 
     pitchAngle -= 360; 
    }else if(pitchAngle < 0){ 
     pitchAngle += 360; 
    } 
    pitch.setFromAxisAngle(new Vector4f(1f, 0f, 0f, pitchAngle * DEGTORAD)); 
    pitch.normalise(); 
} 

/** 
* @param initialRoll 
*/ 
public void roll(float initialRoll) { 
    rollAngle += initialRoll; 
    if(rollAngle > 360){ 
     rollAngle -= 360; 
    }else if(rollAngle < 0){ 
     rollAngle += 360; 
    } 
    roll.setFromAxisAngle(new Vector4f(0, 0, 1, rollAngle * DEGTORAD)); 
    roll.normalise(); 
} 

/** 
* Change direction to focus on a certain point in the world 
* @param eye 
*/ 
public void lookThrough(){ 
    reorient(); 
    GL11.glMultMatrix(viewMatrixBuffer); 
}  

public void reorient(){ 
    //Multiply in order: bearing, pitch, roll. Non-commutative! 
    Quaternion change = new Quaternion(); 
    Quaternion.mul(bearing, pitch, change); 
    Quaternion.mul(roll, change, change); 
    // orient the camera... 
    Matrix4f rotationMatrix = getRotationMatrix(change); 

    //Get the looking direction 
    direction.x = rotationMatrix.m20; 
    direction.y = rotationMatrix.m21; 
    direction.z = rotationMatrix.m22; 

    //Set the position 
    rotationMatrix.m30 = eye.x; 
    rotationMatrix.m31 = eye.y; 
    rotationMatrix.m32 = eye.z; 
    rotationMatrix.m33 = 1; 

    rotationMatrix.invert(); 
    rotationMatrix.store(viewMatrixBuffer); 

    viewMatrixBuffer.rewind(); 

    Vector3f.cross(new Vector3f(0,1,0), direction, null).normalise(right); 
    Vector3f.cross(right, direction, null).normalise(up);    
} 

Vector3f, Kuaterniyon ve Matrix4f tüm lwjgl sınıfları vardır, özel değil.

Bu yüzden sorum, Rulman, Perde ve Ruloları temsil eden 3 Kuaterniyon verildi, bu rotasyonları doğru olarak göstermek için ModelView matrisini nasıl değiştirebilirim?

DÜZENLEME: Bunun çok yakın olduğunu hissediyorum. RiverC'nin yorumunda Gist bağlantısını görün. Çok derece döndükten sonra görünüm, yuvarlanırken normale dönmeden önce etrafa atlar. Onun özü orada, ama hala biraz kapalı.

cevap

3

Çarpmaları yanlış sırada yapıyorsunuz.

q1 ve q2 olmak üzere iki döndürme için q2 q1 değerini izleyecektir (dönmeler genellikle iletişim kuralı değil), q2 * q1 değerini çarpın.

Bir FPS denetimi gibi bir gimbal stili sistemde öncelik sırası her zaman yaw, pitch, roll olur. Eğer koduna baktığımızda yine

change = Quaternion.mul(Quaternion.mul(roll, pitch, change), yaw, change); 

, üçüncü Kuaterniyon sadece irade her güncelleme için yeni kuaterniyonlara yaratmak değil öneririz olur, bir java noktası olarak

roll * pitch * yaw 

: Bu aşağıdaki matematik öneririm Sonucun üzerine yazılır, bu yüzden sıfırlamaya veya her kare/güncellemeyi yeniden oluşturmaya gerek yoktur.

Bu döndürme sırası olayı kafa karıştırıcıdır, ancak Quaternions üzerindeki Wiki sayfasına bakarsanız, genel kuraldır.

+0

Güncelleme için teşekkürler. Bu koda bir süre dokunmadım, bu yüzden LWJGl ile hızlanmaya başlıyorum. Sanırım yakınım. Gsimard tarafından önerilen değişikliklerinizi ve değişikliklerinizi yaptıktan sonra, daha da yaklaşıyorum. Ancak, yaw (sorudaki) 0 olduğunda, zift iyidir. Sapw 180 olduğunda, perde tersine çevrilir (perdeli yukarı doğru kamerayı aşağı doğru hareket ettirir). Ayrıca, rotasyon yaklaşık 20 derece döndükten sonra sporadik hale gelir. Dönmeye devam edersem seviyelere çıkar. Yani bir şey hala doğru değil. Kodu github'a koyacağım ve bu soruyu bu gece daha sonra güncelleyeceğim. Sanırım neredeyse orada. Tekrar teşekkürler. – framauro13

+0

Neden oluşturduktan sonra döndürme matrisine bir şeyler yapıyorsunuz? Bir Mat4'ü doğrudan Shader'a gönderebilmeniz ve onu sahnenin köşelerini değiştirmeksizin çoğaltmak için kullanabilmeniz gerekir. Demek istediğim, kodun '// yönünü belirle' kısmı. Kamerayı çarpma yoluyla dengelemek için kullanmaya çalışıyormuşsunuz gibi görünüyor, ama deneyimlerimde bu isabet ve özledim. Onu düşürmeyi dene. –

+0

Ben * düşünüyorum * başlangıçta öyle yaptım ki, vektörü, vektörü, dünyadaki nesnelerle etkileşime geçmek için bir vektör oluşturmak için göz vektörüyle özetleyebilirim. Bir 'toplayıcı' vektör az ya da çok. Ayrıca, sorunu saygısız bir şekilde düzelttim. Yatak ve zift sırasını değiştirdim, böylece satır Quaternion.mul (Quaternion.mul (roll, rulman, change), pitch, change); Okumaya devam ediyor. Miktar. – framauro13

3

Bunun eski olduğunu biliyorum, ama yine de bir tahmin yapmama izin verin. Sorun Kendin söyledin tam olarak ne:

ben "roll" kamera yerine yerel kamera yönü ekseninin küresel Z ekseni etrafında rulo gibi görünüyor hiç

. Eğer vektör (0,0,1) etrafında rulo kendisine sorulan çünkü

O asal Z ekseni, yani yok.

Bu birim kuaterniyonların yaptığı şeydir: bir vektörü (burada bir dizi vektörler, döndürme matrisiniz), sanal skalerlerin bazı açı işlevleri ile hayali vektörel bölümü (x, y, z) tarafından belirtilen bir eksen etrafında döndürürler. (w = cos (açı/2)). Ben

roll.setFromAxisAngle(new Vector4f(direction.x, direction.y, direction.z, rollAngle * DEGTORAD)); 

: Bence bu soldan sağa doğru başınızı eğerek olduğu gibi kameranızı inişli çıkışlı olduğunu yapmaya çalıştıkları anlıyorsa

, o zaman yön vektörü etrafında rulo quaternion inşa etmeliyiz yön vektörünüzün normalleştirildiği varsayılırsa veya LWJGL, setFromAxisAngle numaralı telefonu ararken üniter olmayan bir eksen vektörü ile ne yapacağını bilir.

+0

Güncelleme için teşekkürler. Bu değişimi yaptım ve yakın, yine de bazı garip davranışlar alıyorum. Bu değişikliği RiverC tarafından önerilen ile yaptım ve orada bir yorumda yeni sorunları açıkladı. Bu gece eve geldiğimde daha fazla ayrıntı ile güncellenir. Tekrar teşekkürler, yardımı takdir ediyorum. – framauro13

İlgili konular