2012-04-27 74 views
2

我有一個使用四元數圍繞固定點的相機。問題是,當相機圍繞x軸旋轉並通過杆時,相機將翻轉併產生鏡像圖像。這是有道理的,因爲相機朝向相反的方向,但相機的向上矢量沒有改變。顯然,一個新的矢量需要從外觀矢量和正確的矢量來計算,但是我似乎無法使它工作。注意:這使用http://commons.apache.org/math/api-2.2/org/apache/commons/math/geometry/Rotation.html來表示四元數。如何避免相機翻轉四元數旋轉?

無論如何,我正在使用以下基本步驟來旋轉相機。

旋轉四元數被初始化到身份[1,0,0,0]:

private Rotation total = Rotation.IDENTITY; 

和照相機的向上矢量被初始化爲:

private Vector3D up = new Vector3D(0, 1, 0); 

旋轉完成通過將相機的當前旋轉存儲爲四元數,然後將任何後續旋轉應用於該四元數,然後將組合的四元數(總數)用於旋轉相機的位置。下面的代碼描述此過程:

/** 
* Rotates the camera by combining the current rotation (total) with any new axis/angle representation of a new rotation (newAxis, rotation). 
*/ 
public void rotateCamera() { 
    if (rotation != 0) { 
     //Construct quaternion from the new rotation: 
     Rotation local = new Rotation(Math.cos(rotation/2), Math.sin(rotation/2) * newAxis.getX(), Math.sin(rotation/2) * newAxis.getY(), Math.sin(rotation/2) * newAxis.getZ(), true); 

     //Generate new camera rotation quaternion from current rotation quaternion and new rotation quaternion: 
     total = total.applyTo(local); 

     //Rotate the position of the camera using the camera rotation quaternion: 
     cam = rotateVector(local, cam); 

     //rotation is complete so set the next rotation to 0 
     rotation = 0; 
    } 
} 

/** 
* Rotate a vector around a quaternion rotation. 
* 
* @param rotation The quaternion rotation. 
* @param vector A vector to be rotated. 
* @return The rotated vector. 
*/ 
public Vector3D rotateVector(Rotation rotation, Vector3D vector) { 
    //set world centre to origin, i.e. (width/2, height/2, 0) to (0, 0, 0) 
    vector = new Vector3D(vector.getX() - width/2, vector.getY() - height/2, vector.getZ()); 

    //rotate vector 
    vector = rotation.applyTo(vector); 

    //set vector in world coordinates, i.e. (0, 0, 0) to (width/2, height/2, 0) 
    return new Vector3D(vector.getX() + width/2, vector.getY() + height/2, vector.getZ()); 
} 

字段newAxis和旋轉,其存儲任何新的旋轉的軸/角度通過按鍵產生如下:

@Override 
public void keyPressed(KeyEvent e) { 
    if (e.getKeyCode() == KeyEvent.VK_W) { 
     camera.setAxis(new Vector3D(1, 0, 0)); 
     camera.setRotation(0.1); 
    } 
    if (e.getKeyCode() == KeyEvent.VK_A) { 
     camera.setAxis(new Vector3D(0, 1, 0)); 
     camera.setRotation(0.1); 
    } 
    if (e.getKeyCode() == KeyEvent.VK_S) { 
     camera.setAxis(new Vector3D(1, 0, 0)); 
     camera.setRotation(-0.1); 
    } 
    if (e.getKeyCode() == KeyEvent.VK_D) { 
     camera.setAxis(new Vector3D(0, 1, 0)); 
     camera.setRotation(-0.1); 
    } 
} 

在每個呈現循環的rotateCamera ()方法被調用,然後下面的代碼設置相機:

glu.gluLookAt(camera.getCam().getX(), camera.getCam().getY(), camera.getCam().getZ(), camera.getView().getX(), camera.getView().getY(), camera.getView().getZ(), 0, 1, 0); 
+3

我不明白你爲什麼使用gluLookAt,它會計算相機的位置和你想看的東西的旋轉。如果您已經自己計算旋轉角度,爲什麼不直接設置視圖矩陣? – Ishtar 2012-04-27 17:39:59

回答

1

你正在做一件奇怪的事。單位四元數表示整個方向。你通常不會使用'up'向量。但是......看起來你只需要使用一個常量「向上」向量[0,1,0]而不是從四元數中得到它就可以得到你想要的效果。

這聽起來像你不需要四元數。你想要的是一個恆定的[向上]向量[0,1,0]。然後你需要一個'at'點,這永遠是你的軌道。然後,您需要一個可以圍繞y軸旋轉的「眼睛」點(圍繞您的軌道點)或圍繞由「向上」向量和軌道點與軌道點之間的向量之間的叉積定義的軸'眼睛'點。

+0

感謝您的回答。原來我這樣做的方式是調用: glu.gluLookAt(camera.getCam()。getX(),camera.getCam()。getY(),camera.getCam()。getZ(),camera.getView ().getX(),camera.getView()。getY(),camera.getView()。getZ(),0,1,0); 但這會導致相機翻轉。我認爲四元組是正確的方法來做到這一點。我應該使用glTranslatef()和glMultMatrixf以及來自四元數的矩陣,因爲我知道Ishtar會提示? – noise 2012-05-01 17:07:51

+0

@noise在什麼情況下會導致相機翻轉?以什麼方式翻動? – JCooper 2012-05-02 14:29:54