# How to use quaternions with JOML and LWJGL3

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) {
right.cross(forward, up);
}

public void roll(double angle) {
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);

// 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);

// 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?

Sorry you've been waiting so long for an answer. Learning quaternions was a huge headache for me, but it was definitely worth it. Here is my code. I don't fully understand it some times, but the more I play with it the better I get.

Just play around with it and you'll see what's going on.

import org.joml.Matrix4f;
import org.joml.Quaternionf;
import org.joml.Vector3f;

Quaternionf dest1 = new Quaternionf();
Quaternionf dest2 = new Quaternionf();
Vector3f v = new Vector3f();

// verticesModel is the initial position of my vertices
//before the 3D transformations are done
// Vector3f[] verticesModel

for(int i = 0 ; i < verticesModel.length;i++)
{

// I have a global variable 'v' just to avoid making a new Vector3f object 60 times every second when the draw() method is run
v.x = verticesModel[i].x;
v.y = verticesModel[i].y;
v.z = verticesModel[i].z;

// blank out my quaternions
dest1.w = 1f;
dest1.x = 0f;
dest1.y = 0f;
dest1.z = 0f;

dest2.w = 1f;
dest2.x = 0f;
dest2.y = 0f;
dest2.z = 0f;

// I keep my pitch/yaw/roll in another Vector3F called rotationXYZ as degrees
float x, y, z;
x = rotationXYZ.x;// + rotationXYZ.x;// testX;
y = rotationXYZ.y;// + rotationXYZ.y;//testY;
z = rotationXYZ.z;// + rotationXYZ.z;//testZ;

// just make sure the degrees values don't get bigger than they need to be
x = x % 360.0f;
y = y % 360.0f;
z = z % 360.0f;

// convert to radians and start transforming

dest1.transform(v);

// vv is the new value for v after the transformations
// Vector3f[] vertices is the array of vertices I use to draw
Vector3f vv = vertices[i];

vv.x = v.x;
vv.y = v.y;
vv.z = v.z;


}

• Wauwzor, thanks for your answer! :D I did actually solve my problem some time afterwards (a month or so) when taking a look at it again. I don't know exactly how a quaternion work mathematically, but I understand how to use it at least. It's super-sweet, not only because you can do a lot with it, but also because it requires less data. It certainly did make my multiplayer implementation a whole lot easier and data-packets more compact. Mar 16, 2018 at 13:58
• Congrats man! Let us know how the game turns out. Mar 17, 2018 at 10:13