バックグラウンド
私はLWJGL 3.0を使用してJavaでFPSゲームを作成しようとしています。私は(ロールが使用されていない)、ピッチとヨーを持っているカメラのクラスを、設定しました。それはモデルを持っているように、カメラ自体が、エンティティを拡張します。このモデルは、私はカメラが向いているところはどこでも、常にカメラの「前に」のように見えるしたいと思います。各エンティティは、方法有するgetTransformationMatrix()
戻りMatrix4f
、次にエンティティシェーダーに渡され、。
問題
それは前に常にあるように、カメラの周りにモデルカメラの方向にポイントする必要があるだけでなく、回転、。下の写真に示すように、このような状況ではオブジェクトは、銃と手です。
私の試み
I am aware of basic trigonometry, so I got the object to rotate correctly for pitch and yaw, separately. This is my current implementation:
Yaw
@Override
public Matrix4f getTransformationMatrix() {
modelX = getPosition().x + (radius * (float)Math.sin(Math.toRadians(getYaw())));
modelZ = getPosition().z + (radius * (float)Math.cos(Math.toRadians(getYaw())));
return Transform.createTransformationMatrix(new Vector3f(modelX, getPosition().y - 5, modelZ), new Vector3f(0, getYaw(), 0), getScale());
}
Pitch
@Override
public Matrix4f getTransformationMatrix() {
modelZ = getPosition().z + (radius * (float)Math.sin(Math.toRadians(getPitch())));
modelY = (getPosition().y - 5) + (radius * (float)Math.cos(Math.toRadians(getPitch())));
return Transform.createTransformationMatrix(new Vector3f(getPosition().x, modelY, modelZ), new Vector3f(getPitch(), 0, 0), getScale());
}
I have done some research but I fear I have been stuck on this too long and need some fresh eyes. When I try to combine these 2 calculations, the model seems to move in the shape of a graph when looking at any yaw angle other than 0. Below is my attempt of combining these:
@Override
public Matrix4f getTransformationMatrix() {
float zAxis = (radius * (float)Math.sin(Math.toRadians(getPitch())));
modelY = (getPosition().y - 5) + (radius * (float)Math.cos(Math.toRadians(getPitch())));
modelZ = getPosition().z + (zAxis * (float)Math.cos(Math.toRadians(getYaw())));
modelX = getPosition().x + (radius * (float)Math.sin(Math.toRadians(getYaw())));
return Transform.createTransformationMatrix(new Vector3f(modelX, modelY, modelZ), new Vector3f(getPitch(), getYaw(), 0), getScale());
}
The Transform.createTransformationMatrix()
looks like the following:
public static Matrix4f createTransformationMatrix(Vector3f translation, Vector3f rotation, Vector3f scale) {
transform3d = new Matrix4f();
transform3d.setIdentity();
Matrix4f.translate(translation, transform3d, transform3d);
Matrix4f.rotate((float) Math.toRadians(rotation.x), new Vector3f(1, 0, 0), transform3d, transform3d);
Matrix4f.rotate((float) Math.toRadians(rotation.y), new Vector3f(0, 1, 0), transform3d, transform3d);
Matrix4f.rotate((float) Math.toRadians(rotation.z), new Vector3f(0, 0, 1), transform3d, transform3d);
Matrix4f.scale(scale, transform3d, transform3d);
return transform3d;
}
Thoughts
A friend suggested creating a unit vector that points in the direction of up, (ie. new Vector3f(0, 1, 0)
) rotating the Vector by the pitch and yaw, then multiplying the Vector by the radius and adding it to the camera's position. I tried this, but I don't know how to rotate a Vector by an angle, and there seems to be no Vector3f.rotate()
method in the slick-utils Vector3f class. Any help is is thoroughly appreciated as this has been giving me a headache for the past few days. Thanks!
What we normally do is, yes, take a unit-length vector and use it as our "axis". In 2D rotation we use an axis - the Z axis - all the time.
If you were to look at the axis, like in 2D, you would see something like this
だから、3Dでのポイントを回転させるために、あなたは行列またはベクトルを使用することができます。あなたは3D回転がどのように動作するかのアイデアを得ることができますので、私は最初のベクトルをお勧めします。それはあなたの心を吹きます!
私はtheBennyBoxからVector3fクラスからコードをドロップします。あなたはより多くのYoutubeでtheBennyBoxうち、この数学のチェックのに興味があるなら。
Vector3f
public Vector3F rotate(float angle, Vector3F axis) {
double a = Math.toRadians(angle / 2f);
float hs = (float) Math.sin(a);
float hc = (float) Math.cos(a);
Vector4F r = new Vector4F(axis.getX() * hs, axis.getY() * hs, axis.getZ() * hs, hc);
Vector4F rc = r.conjugate();
r = r.multiplyAsQuat(this).multiplyAsQuat(rc);
return new Vector3F(r.getX(), r.getY(), r.getZ());
}
ベクトル4F
public Vector4F multiplyAsQuat(Vector3F v) {
float o = -x * v.getX() - y * v.getY() - z * v.getZ();
float a = w * v.getX() + y * v.getZ() - z * v.getY();
float b = w * v.getY() + z * v.getX() - x * v.getZ();
float c = w * v.getZ() + x * v.getY() - y * v.getX();
return new Vector4F(a, b, c, o);
}
public Vector4F conjugate() {
return new Vector4F(-x, -y, -z, w);
}
public Vector4F multiplyAsQuat(Vector4F qt) {
float o = w * qt.getW() - x * qt.getX() - y * qt.getY() - z * qt.getZ();
float a = x * qt.getW() + w * qt.getX() + y * qt.getZ() - z * qt.getY();
float b = y * qt.getW() + w * qt.getY() + z * qt.getX() - x * qt.getZ();
float c = z * qt.getW() + w * qt.getZ() + x * qt.getY() - y * qt.getX();
return new Vector4F(a, b, c, o);
}