Quaternion.mul()
掛け算だと思いますか?回転を行うには、1回以上の乗算を行う必要があると思います。ベクトルまたは点を軸角度(クォータニオン)を中心に回転させるために使用するコードは次のとおりです。
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
船は1秒あたりラジアンでしか向きを変えることができません。したがって、ティックごとに動きを更新した後、方向/ターゲットベクトルの外積を取得して回転軸を取得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をプレーヤー/カメラの位置として設定できます。 、ターゲットオブジェクトとしてのターゲット、および角度/カメラを回転させる速度のturningCirlce。あなたはdraw()
ただ使うでしょうlookAt(directionVector.mX + currentPosition.mX, directionVector.mY + currentPosition.mY, directionVector.mZ + currentPosition.mZ)