I’m implementing a space fps game (there is no up or down in space!) using LWJGL3 and JOML (math library).
Entities in my game have a rotation based on the Forward, Up and Right vectors. I use pitch, yaw and roll methods to rotate my entities. The methods can be seen in the pseudo code further down.
When I construct the model matrix for an entity I calculate a rotation matrix based on the 3 vectors described above and apply it. It can be seen in the pseudo code further down.
I also use angular and linear acceleration and velocity to rotate and move an entity. It can be seen in the pseudo code further down.
Entity:
Vector3f position Vector3f scale Vector3f forward Vector3f up Vector3f right private Vector3f linearAcc private Vector3f linearVel private Vector3f angularAcc private Vector3f angularVel public void pitch(double angle) { forward.mul((float) Math.cos(angle), tempVector1).add(up.mul((float) Math.sin(angle), tempVector2)).normalize(forward); right.cross(forward, up); } public void roll(double angle) { right.mul((float) Math.cos(angle), tempVector1).add(up.mul((float) Math.sin(angle), tempVector2)).normalize(right); right.cross(forward, up); } public void yaw(double angle) { right.mul((float) Math.cos(angle), tempVector1).add(forward.mul((float) Math.sin(angle), tempVector2), right); up.cross(right, forward); } public Matrix4f getRotationMatrix(Matrix4f dest) { dest.set( right.x, right.y, right.z, 0, forward.x, forward.y, forward.z, 0, up.x, up.y, up.z, 0, 0, 0, 0, 1); return dest; }
Model matrix:
public static Matrix4f createModelMatrix(Vector3f position, Matrix4f rotationMatrix, Vector3f scale) { Matrix4f modelMatrix = new Matrix4f(); modelMatrix.translate(position); modelMatrix.mul(rotationMatrix); modelMatrix.scale(scale); return modelMatrix; }
Basic logic for rotating and moving an entity:
// Angular acceleration: // Angular acceleration is reset every update entity.getAngularAcc().zero(); // Components may rotate an entity by applying angular acceleration Vector3f someAngularThrust = new Vector3f(0, 0, 0.025f); entity.getAngularAcc().add(someAngularThrust ); // The accumulated angular acceleration is added to the angular velocity entity.getAngularVel().fma(dt, movement.getAngularAcc()); // Finally, the entity is rotated by the angular velocity entity.pitch(dt * entity.getAngularVel().x); entity.yaw(dt * entity.getAngularVel().y); entity.roll(dt * entity.getAngularVel().z); // The basic logic applies for linear movement: // Linear acceleration is reset every update entity.getLinearAcc().zero(); // Components may move an entity by applying linear acceleration Vector3f someLinearThrust = entity.getForward().mul(5); entity.getLinearAcc().add(someLinearThrust ); // The accumulated linear acceleration is added to the linear velocity entity.getLinearVel().fma(dt, entity.getLinearAcc()); // Finally, the entity is moved by the linear velocity entity.getPosition().fma(dt, entity.getLinearVel());
So far it seems that this setup works, but it does not give me all the functionality I need in my game:
-
I want an alternative way of setting/modifying the rotation of an entity – right now it can only be done by setting the Forward, Up and Right vectors or using the pitch, yaw and roll methods.
-
I want to be able to represent the rotation of an entity with a smaller unit (a rotation vector / axis?). It is a multiplayer game where I need to send the orientation of entities. Sending 2 or more 3d vectors to represent the orientation is not optimal.
From what I understand quaternions can do all that I want. I tried to use it in my game (Quaternionf in JOML), but couldn’t get it to work properly:
- I couldn’t get the pitch, yaw and roll methods to work.
- The model matrix didn’t work. The facing direction of the entities did not match the direction they were moving – they were supposed to move in the direction they were facing.
- The movement logic didn’t seem to work either (even when not using pitch, yaw and roll). Could have got something to do with the above point.
Any ideas how I should go on about to use quaternions in my code?