-
Notifications
You must be signed in to change notification settings - Fork 103
Common Pitfalls
Below you will find very common problems and solutions when working the first time with JOML, especially when migrating from other libraries which worked differently.
Any parameter in any method representing an angle will always be in radians. This includes the parameters in methods like Matrix4f.rotate(angle, ...)
and Matrix4f.perspective(fovY, ...)
.
So, the following will not produce the desired result:
Matrix4f m = new Matrix4f().perspective(60.0f, aspect, near, far);
Use Math.toRadians() instead:
Matrix4f m = new Matrix4f().perspective((float) Math.toRadians(60.0f), aspect, near, far);
The following will not produce the desired result:
if (shouldMoveRight)
position = position.add(forward.cross(up).mul(speed));
if (shouldMoveLeft)
position = position.sub(forward.cross(up).mul(speed));
if (shouldMoveUp)
position = position.add(up.mul(speed));
if (shouldMoveDown)
position = position.sub(up.mul(speed));
The problem with the above code is that the forward
and up
vectors are being modified, since the cross
and mul
method calls modify this
and this
in that context is forward
and up
, respectively.
Instead use the overloads with explicit dest
parameters like in following code:
Vector3f forward = new Vector3f(...);
Vector3f up = new Vector3f(...);
Vector3f position = new Vector3f(0);
Vector3f tmp = new Vector3f();
float speed = 2.0f;
if (shouldMoveRight)
position.add(forward.cross(up, tmp).mul(speed));
if (shouldMoveLeft)
position.sub(forward.cross(up, tmp).mul(speed));
if (shouldMoveUp)
position.add(up.mul(speed, tmp));
if (shouldMoveDown)
position.sub(up.mul(speed, tmp));
This prevents forward
and up
from being modified. Here, the result will be written to a temporary tmp
vector which will also be the returned object of the cross
and mul
calls.
Also, the reassignment of position
in every line was superfluous, since the add
and sub
calls operate on position
and return position
(remember that method overloads that do not take a dest
parameter will always modify and return this
).
In the index subscripts of the matrix elements, that is, in the indices/numbers of m00 throught m33 (in a 4x4 matrix) when read from left to right, the first (leftmost) number means the column and the second (rightmost) number means the row of the matrix element. This is different to the notation used in most math books, but aligns better with the column-major memory layout of OpenGL, where a matrix is an array of columns (so the column index comes first), instead of an array of rows.
When using the convention of matrix-vector multiplication M * v
then v
is a column vector and the first column of M
is the column vector (m00, m01, m02, m03)
.
This is different to some other vector/matrix libraries, which treat the first element index as the row and the second as the column (while also using column-vectors and with it the M * v
matrix-vector multiplication).
When it comes to serializing matrix elements into a linear data structure such as an array or a NIO buffer, some matrix/vector math libraries use row-major memory layout and some other libraries use column-major layout. JOML uses the latter. This is also the memory layout expected by OpenGL.
That means, the following code will not do what you intended it to do:
glMatrixUniform4fv(matrixLocation, true, matrix.get(arrayOrBuffer));
Instead, use false
as the transpose
parameter argument:
glMatrixUniform4fv(matrixLocation, false, matrix.get(arrayOrBuffer));