Background
I'm trying to create a FPS game in Java using LWJGL 3.0. I've set up a camera class, that has a pitch and yaw (roll is not being used). The camera itself extends Entity, as it has a model. This model I would like to appear to always be "in front" of the camera, wherever the camera is pointing. Each Entity has a method getTransformationMatrix()
which returns a Matrix4f
, that is then passed into the entity shader.
Problem
The model needs to point in the direction of the camera, as well as rotate around the camera, such that it is always in front. The object in this situation is hands with a gun, as shown in the photo below.
My Attempt
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!