我猜Quaternion.mul()
是乘以?我認爲你需要做的不僅僅是一次乘法來做旋轉。下面是我使用的繞軸角度(四元)旋轉的矢量或點代碼:
private double[] vecQuat = new double[4];
private double[] resQuat = new double[4];
private double[] thisQuat = new double[4];
private double[] conj = new double[4];
/**
* Rotates a vector (or point) around this axis-angle
*
* @param vectorX the x component of the vector (or point)
* @param vectorY the y component of the vector (or point)
* @param vectorZ the z component of the vector (or point)
* @param outputArray the array in which the results will be stored
*/
public void RotateVector(double vectorX, double vectorY, double vectorZ, double[] outputArray){
vecQuat[0] = 0.0f;
vecQuat[1] = vectorX;
vecQuat[2] = vectorY;
vecQuat[3] = vectorZ;
thisQuat[0] = w;
thisQuat[1] = x;
thisQuat[2] = y;
thisQuat[3] = z;
getConjugate(conj);
Multiply(vecQuat,conj,resQuat);
Multiply(thisQuat,resQuat,vecQuat);
outputArray[0] = vecQuat[1];
outputArray[1] = vecQuat[2];
outputArray[2] = vecQuat[3];
}
public void getConjugate(double[] outputArray){
outputArray[0] = w;
outputArray[1] = -x;
outputArray[2] = -y;
outputArray[3] = -z;
}
public void Multiply(double[] aq, double[] rq, double[] outputArray){
outputArray[0] = aq[0] * rq[0] - aq[1] * rq[1] - aq[2] * rq[2] - aq[3] * rq[3];
outputArray[1] = aq[0] * rq[1] + aq[1] * rq[0] + aq[2] * rq[3] - aq[3] * rq[2];
outputArray[2] = aq[0] * rq[2] + aq[2] * rq[0] + aq[3] * rq[1] - aq[1] * rq[3];
outputArray[3] = aq[0] * rq[3] + aq[3] * rq[0] + aq[1] * rq[2] - aq[2] * rq[1];
}
我不知道libgdx,但也許一看,看它是否有一個像一個旋轉功能一個在上面。如果沒有,你也許可以將其添加在
編輯:
我並不確切地知道你想要用相機做什麼,但這裏是我用四元數爲RTS遊戲的例子設置在太空中(想家園)。宇宙飛船有一個direction vector
(它們正在旅行的方向),用於每嘀次更新它們的移動並旋轉它們以面對行駛方向(在draw()
函數中)。他們也有一個target vector
:位於船的位置和當前目的地之間。該船隻能以每秒turningCircle
弧度轉彎。所以在更新動作每個刻度之後,我將方向/目標向量的叉積轉換爲旋轉軸,並以turningCircle
爲角度來創建一個四元數。我用四元數旋轉船的方向矢量來「轉向」船。最後的結果是船上有多個蜱蟲,轉向一個優美的弧線,直到它朝着正確的方向前進。
同樣的過程也可以在戰鬥飛行模擬器中用來模擬AI飛機的轉向。使用四元數還將避免'真空鎖',真正的飛機受到的影響!但是,使用四元數,你的AI飛機可能會發現在一半時間內顛倒飛行更方便,所以你可能不得不沿着其機身軸線進行一些額外的慢速旋轉(即, z軸)以模擬飛行員將自己定位到「向上」。這實際上是相當容易只需添加直角向上和向右向量,以向前(方向)矢量
這裏做的是代碼(減去定向向上矢量位):
/**
* The current position of the spaceship
*/
private Vertex3D currentPosition;
/**
* The target position of the spaceship
*/
private Vertex3D targetPosition;
/**
* The current direction in which the spaceship is travelling
*/
private Vector directionVector;
/**
* The vector towards which the spaceship is turning
*/
private Vector targetVector;
/**
* The right orientation vector
*/
private Vector rightOrientationVector;
/**
* The up orientation vector
*/
private Vector upOrientationVector;
/**
* Angle in radians by which directionVector turns towards TargetVector every tick
*/
private double turningCircle = 0.05f;
public Spaceship(Vertex3D target){
currentPosition = new Vertex3D(0,0,0);
// right hand coordinate system: ship is facing "away" from the camera
directionVector = new Vector(currentPosition, 0,0,-1);
rightOrientationVector = new Vector(currentPosition, 1,0,0);
upOrientationVector = new Vector(currentPosition, 0,1,0);
targetPosition = target;
}
protected void tick(){
incrementPosition();
turn();
draw();
}
protected void incrementPosition(){
// get movement
double velocity = getVelocity();
// move
currentPosition.mX(currentPosition.mX + directionVector.mX * velocity);
currentPosition.mY(currentPosition.mY + directionVector.mY * velocity);
currentPosition.mZ(currentPosition.mZ + directionVector.mZ * velocity);
}
private double[] cross = new double[3];
private double[] newDir = new double[3];
private Quaternion quat;
protected void turn(){
// update target vector relative to new position
setTargetVector();
// turn direction vector towards target vector
MathsExtras.crossProduct(directionVector.mX, directionVector.mY, directionVector.mZ, targetVector.mX, targetVector.mY, targetVector.mZ, cross);
quat = new Quaternion(cross[0], cross[1], cross[2], turningCircle);
quat.RotateVector(directionVector.mX, directionVector.mY, directionVector.mZ, newDir);
directionVector.mX = newDir[0];
directionVector.mY = newDir[1];
directionVector.mZ = newDir[2];
direction.normalise();
// update right orientation
MathsExtras.crossProduct(direction.mX, direction.mY, direction.mZ, upOrientationVector.mX, upOrientationVector.mY, upOrientationVector.mZ, cross);
rightOrientationVector.mX = cross[0];
rightOrientationVector.mY = cross[1];
rightOrientationVector.mZ = cross[2];
rightOrientationVector.normalise();
// update up orientation
MathsExtras.crossProduct(rightOrientationVector.mX, rightOrientationVector.mY, rightOrientationVector.mZ, direction.mX, direction.mY, direction.mZ, cross);
upOrientationVector.mX = cross[0];
upOrientationVector.mY = cross[1];
upOrientationVector.mZ = cross[2];
upOrientationVector.normalise();
}
protected void setTargetVector(){
targetVector.mX = targetPosition.getmX() - currentPosition.getmX();
targetVector.mY = targetPosition.getmY() - currentPosition.getmY();
targetVector.mZ = targetPosition.getmZ() - currentPosition.getmZ();
targetVector.normalise();
}
因此,如果您想使用相同的代碼說出讓相機查看第一人稱射擊遊戲中的對象,您可以將方向矢量設置爲玩家正在查看的方向,並將currentPosition設置爲玩家/相機位置,目標作爲目標對象,並將角度旋轉角度/您希望相機轉多快。在draw()
你只想用lookAt(directionVector.mX + currentPosition.mX, directionVector.mY + currentPosition.mY, directionVector.mZ + currentPosition.mZ)
很酷,我想我可能會擴展它們的'Quaternion'類來添加更多的功能。我不相信有一個旋轉的方法,所以這可能是非常有用的! ...你有什麼建議,我應該如何更新相機與四元數旋轉後已應用到它? –
如果您使用相機的x,y,z座標作爲RotateVector()中的參數,那麼將在輸出數組中放入相機的新xyz位置,該位置已經按照四元數軸的指定進行了旋轉,該軸固定在原點。如果你從原點到四元數的x,y,z畫一條線,這將幫助你形象化你將要旋轉的軸...在我自己的引擎中,我不會移動相機,我只是將變換應用到場景中的對象上,使它們位於正確的位置,使它們移動,轉向等。 –
添加了一個帶有代碼的示例 –