JOML

JOML provides easy-to-use, feature-rich and efficient linear algebra operations, needed by any 3D application. At the same time, JOML tries to pose the lowest possible requirements to an execution environment by being compatible with Java 1.4 and not making use of JNI.

You can use it on for desktop/android/GWT apps.

JOML on GitHub

vectors

Vector3f v = new Vector3f(0.0f, 1.0f, 0.0f);
Vector3f a = new Vector3f(1.0f, 0.0f, 0.0f);
v.add(a); // v = v + a
a.cross(v); // a = a x v
a.normalize(); // a = a/|a|

matrices

You can easily define transformation matrix and to transform vectors. Below example, how to rotate about a given axis using a specific rotation center.

Vector3f center = new Vector3f(0.0f, 3.0f, 4.0f);
Vector3f pointToRotate = new Vector3f(0.0f, 4.0f, 4.0f);
new Matrix4f().translate(center)
              .rotate((float) Math.toRadians(90.0f), 1.0f, 0.0f, 0.0f)
              .translate(center.negate())
              .transformPosition(pointToRotate); 
              // pointToRotate will now represent (0, 3, 5)

JOML support projections matrices by methods

  • perspective() - perspective projection
  • ortho()- orthographic projection
  • frustum() - defines frustum
  • lookAt() - mimics a camera looking at a given point
Matrix4f m = new Matrix4f()
     .perspective((float) Math.toRadians(45.0f), 1.0f, 0.01f, 100.0f)
     .lookAt(0.0f, 0.0f, 10.0f,
             0.0f, 0.0f, 0.0f,
             0.0f, 1.0f, 0.0f);
     // the camera transformation is now in m

matrix stack

JOML also features an interface that resembles the matrix stack from legacy OpenGL.

Matrix4fStack s = new Matrix4fStack(2);
s.translate(2.0f, 0.0f, 0.0f);
s.pushMatrix();
{
  s.scale(0.5f, 0.5f, 0.5f);
  // do something with the Matrix4f of 's'
}
s.popMatrix();
s.rotate((float) Math.toRadians(45.0f), 0.0f, 0.0f, 1.0f);
// do something with the Matrix4f of 's'

LWJGL

The following example shows a typical usecase with LWJGL:

FloatBuffer fb;
Matrix4f m;

void init() {
  fb = MemoryUtil.memAllocFloat(16);
  m = new Matrix4f();
  ...
}
void destroy() {
  MemoryUtil.memFree(fb);
}

void frame() {
  ...
  // compute view-projection matrix
  m.identity()
   .perspective((float) Math.toRadians(45.0f), (float)width/height, 0.01f, 100.0f)
   .lookAt(0.0f, 0.0f, 10.0f,
           0.0f, 0.0f, 0.0f,
           0.0f, 1.0f, 0.0f);
  // possibly apply more model transformations
  m.rotateY(angle);
  // get matrix into FloatBuffer and upload to OpenGL
  glUniformMatrix4fv(mat4Location, false, m.get(fb));
  ...
}

If you are not reusing FloatBuffer you can use the following snippet

try (MemoryStack stack = MemoryStack.stackPush()) {
  FloatBuffer fb = new Matrix4f()
    .perspective((float) Math.toRadians(45.0f), 1.0f, 0.01f, 100.0f)
    .lookAt(0.0f, 0.0f, 10.0f,
            0.0f, 0.0f, 0.0f,
            0.0f, 1.0f, 0.0f)
    .get(stack.mallocFloat(16));
  glUniformMatrix4fv(mat4Location, false, fb);
}