我猜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画一条线,这将帮助你形象化你将要旋转的轴...在我自己的引擎中,我不会移动相机,我只是将变换应用到场景中的对象上,使它们位于正确的位置,使它们移动,转向等。 –
添加了一个带有代码的示例 –