Hi,
I've been working for the last three days extensively on moving JOML (https://github.com/JOML-CI/JOML) forward to reach a broadly usable state and polished it a lot. The goal is to allow JOML to be applicable to any usage patterns that might exist for such a narrow framework.
Hopefully, we succeeded in it.
Notable features:
- lean and mean
- very low requirements (Java 1.4)
- completely allocation-free
- can be used in a multithreaded application
- fluent interface style methods
- resembles very closely the functions of OpenGL and GLU
More information is available at GitHub (https://github.com/JOML-CI/JOML).
If you want, go ahead and use it.
Please make sure to provide us with any feedback, or post any issues you encounter, or change requests you have, on the GitHub Issues section (https://github.com/JOML-CI/JOML/issues)!
Before really using JOML also please make sure to read on the Design entry (https://github.com/JOML-CI/JOML/wiki/Design) in its Wiki, which specifies the operational semantics of JOML, so that you always know what happens. :)
Thanks!
- the JOML team ;)
really nice work, looking forward to using it.
Looking great. One request: Could you make buffer operations use indices relative to the current buffer position? I.e. make it compatible with how LWJGL handles buffer arguments. This way you won't have to rewind/flip after a matrix get/put.
Thanks.
Ah, yes, that would indeed make usage look nicer.
The main purpose for using the position-changing relative put operation is that you can then chain multiple Matrix.get() operations on the same FloatBuffer (for example when filling a UBO with multiple matrices) without the client needing to advance the buffer position in-between calls.
But I think I will add a Matrix4f.get(FloatBuffer, boolean) where the boolean means "should or should not advance the buffer position" and then make the default get(FloatBuffer) use false.
EDIT: Okay, is in. 1.1.1-SNAPSHOT release contains these changes.
I wouldn't use boolean parameters, it's bad API design (especially in Java that doesn't support named parameters). Better have a get(FloatBuffer buffer, int matrixIndex) for that use case, the matrix will be stored at buffer.position() + matrixIndex * 16. Or something equivalent.
Okay.
In 1.1.3-SNAPSHOT (https://github.com/JOML-CI/JOML/releases/tag/1.1.3-SNAPSHOT) there is now Matrix4f.get(FloatBuffer) which stores the matrix at the buffer's current position() and does not advance the buffer position.
Additionally, there is now a Matrix4f.get(int, FloatBuffer) which takes the absolute index/position of the buffer (just like the non-relative put operations in NIO) at which the matrix should be stored, and which also does not advance the buffer position.
Hi, I have a question:
Since lwjgl_util has lost compatibility with lwjgl3 i am now using JOML to load a projection matrix into opengl's projection matrix. The problem now is that glViewport doesn't seem to do anything. How would i solve the aspect ration problem instead?
Also for my own convenience i implemented a method into JOML's source code (in Matrix4f class precisely) that puts the matrix into a FloatBuffer and returns the FloatBuffer. I just thought you may want to use it (or not):
public FloatBuffer asFloatBuffer() {
ByteBuffer bb = ByteBuffer.allocate(4 * 4 * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer fb = bb.asFloatBuffer();
fb.put(new float[] {
this.m00, this.m01, this.m02, this.m03,
this.m10, this.m11, this.m12, this.m13,
this.m20, this.m21, this.m22, this.m23,
this.m30, this.m31, this.m32, this.m33
});
fb.flip();
return fb;
}
public static FloatBuffer asFloatBuffer(Matrix4f mat) {
ByteBuffer bb = ByteBuffer.allocate(4 * 4 * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer fb = bb.asFloatBuffer();
fb.put(new float[] {
mat.m00, mat.m01, mat.m02, mat.m03,
mat.m10, mat.m11, mat.m12, mat.m13,
mat.m20, mat.m21, mat.m22, mat.m23,
mat.m30, mat.m31, mat.m32, mat.m33
});
fb.flip();
return fb;
}
Hello,
there are the Matrix4f.get(FloatBuffer) (https://github.com/JOML-CI/JOML/blob/master/src/org/joml/Matrix4f.java#L778) as well as Matrix4f.get(int, FloatBuffer) (https://github.com/JOML-CI/JOML/blob/master/src/org/joml/Matrix4f.java#L794) methods to "get" the matrix into a FloatBuffer.
I hate to say that your implementations violate an important design goal/principle of JOML, trying to be as efficient as possible with Java.
Part of reaching this goal is to be "allocation-free," which means that no method in JOML ever will allocate anything.
Your methods do allocate three objects: a NIO ByteBuffer, a FloatBuffer view on it and a float array.
In order to remain allocation-free, JOML uses the "parameter as return value pattern".
The Matrix4f.get(FloatBuffer) therefore receives the "destination" FloatBuffer as parameter into which the matrix will be written.
See the JavaDocs of this method.
EDIT:
If you want to have the FloatBuffer returned rather than the Matrix4f when calling get() on it for method chaining to be able to call further methods on FloatBuffer,
you could yourself add another method to Matrix4f like so:
public FloatBuffer toFloatBuffer(FloatBuffer fb) {
get(fb);
return fb;
}
Note that you need not invoke FloatBuffer.rewind() or .flip() or .clear() on the FloatBuffer afterwards, as JOML will not alter its position() (http://docs.oracle.com/javase/7/docs/api/java/nio/Buffer.html#position()).
I have a problem with the aspect ratio. When using LWJGL2 and gluPerspective() from lwjgl_util, if I had an aspect ratio different to 1 everything stretched so I used glViewport to solve this. Now that I am using JOML the glViewport seems to do nothing. Any ideas on how to solve this?
Here is my code to create the projection matrix:
glMatrixMode(GL_PROJECTION);
Matrix4f perspMat = new Matrix4f();
perspMat.perspective(
Graphics.fov,
Game.width / Game.height,
Graphics.znear,
Graphics.zfar
);
FloatBuffer fb = ByteBuffer.allocateDirect(4*4*4)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
perspMat.get(fb);
glViewport(0, 0, Game.width, Game.height); //This seems to do absolutely nothing
glLoadMatrixf(fb);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
Also on this note:
Quote from: Kai on June 01, 2015, 14:18:19
Note that you need not invoke FloatBuffer.rewind() or .flip() or .clear() on the FloatBuffer afterwards, as JOML will not alter its position() (http://docs.oracle.com/javase/7/docs/api/java/nio/Buffer.html#position()).
As you can see in the code above, i am not using any of those two methods. If I do use fb.flip() i get this error:
java.lang.IllegalArgumentException: Number of remaining buffer elements is 0, must be at least 16
glViewport is not meant to correct aspect ratio in the perspective projection.
It is meant to define what parts of the window will receive the OpenGL rendering output.
Or in other words: glViewport defines the transformation from normalized device coordinates to pixel coordiantes.
I am surprised that, as you said, with LWJGL 2 glViewport actually did fix the stretching in the perspective projection due to different aspect ratios. glViewport has nothing to do with the perspective projection matrix or any other matrix stack. It merely defines the transformation between NDC and pixels.
Your usage of Matrix4f.perspective is correct, provided that Game.width and/or Game.height are floating point values. If they are integers, which I assume they were, since they are likely in pixel width/height, you NEED to cast either of the two to float!
Ok, casting Game.width as float fixed the problem. Thank you very much.
JOML now got a Wiki, with the most important entry being about its Design (https://github.com/JOML-CI/JOML/wiki/Design),
which is about to explain the design decisions and the exact operational semantics of JOML, to get a feeling of how to work with JOML.
Are there still plans to upload JOML to maven central, or is it already there somewhere?
I was hoping that Spasi could set up a LWJGL-hosted Nexus OSS repository to hold all of the LWJGL and JOML artifacts.
Uploading to Maven Central directly is quite a cumbersome process, as you first need to have a Sonatype account, then an approved project that you are allowed to upload to Maven central.
Then you must provide PGP signatures with your artifacts, therefore need a PGP client to do that.
And there are a few more steps involved.
Using an organization-hosted Maven repository is a well-established step chosen by many organizations such as Atlassian, SpringSource and Apache.
A client of LWJGL or JOML would then only need to have a <repository> tag either in their settings.xml or in their project's pom.xml to reference that new repository. We could provide that tag definition on the JOML or LWJGL site as a snippet for you to copy-and-paste to make integration for clients as painless as possible, which is also what most other organizations do.
Or we get an approval from Sonatype to have LWJGL's repository being included as a virtual third-party repository, so that effectively LWJGL and JOML would then be found when querying Maven central directly.
This is a good idea and I'll try to make it happen, but I don't know when I'll have time for it.
There is now also a "Migrating from LWJGL 2" (https://github.com/JOML-CI/JOML/wiki/Migrating-from-LWJGL-2) entry in JOML's Wiki.
Everyone coming from LWJGL 2 and trying to port their code to LWJGL 3 and JOML will find help there on what they need to do.
Additionally, if you are wondering how you can use JOML with LWJGL 3 in the first place, there is now a Simple LWJGL 3 Example (https://github.com/JOML-CI/JOML/wiki/Simple-LWJGL-3-example). This example uses OpenGL 1.1.
If you want to know how to use JOML with OpenGL 2.0 and shaders, have a look at JOML with LWJGL 3 and Shaders (https://github.com/JOML-CI/JOML/wiki/JOML-with-LWJGL-3-and-Shaders).
In Vector3f.sub(float, float, float) the values are incremented instead of decremented. This is probably a typo.
/**
* Decrement the components of this vector by the given values.
*
* @return this
*/
public Vector3f sub(float x, float y, float z) {
this.x += x;
this.y += y;
this.z += z;
return this;
}
Thanks a bunch for reporting! It has been fixed in #7c2d9e (https://github.com/JOML-CI/JOML/commit/7c2d9e6d5135c77759e901f44acddab717fe26fe)
If you find more issues or have suggestions, you can use the Issues section (https://github.com/JOML-CI/JOML/issues) on GitHub.
The latest 1.2.0 Release (https://github.com/JOML-CI/JOML/releases/tag/1.2.0) of JOML is ready.
It has been put to real use, especially its quaternion classes, and a few issues have thankfully been found and resolved by @FortressBuilder.
Some new methods have found its way into the matrix and vector classes, such as project() and unproject() known from GLU, as well as angle() and angleCos() (thanks to @FortressBuilder for contribution) as well as methods to obtain a particular matrix row and column (thanks to @zmrodriguez91).
The matrix and vector classes can be considered stable and the API of existing methods will not change anymore in syntax or semantics, so you are encouraged to incorporate it in your own projects.
As always: If you feel that some feature is missing in JOML which holds you back from using JOML, feel free to post an issue (https://github.com/JOML-CI/JOML/issues) or contribute (https://github.com/JOML-CI/JOML/wiki/Contribution).
We are always glad about help from others to drive JOML in directions to make it useful for real projects.
JOML has now two new repositories:
joml-camera (https://github.com/JOML-CI/joml-camera)
Currently, it features an arcball camera with acceleration/velocity/elapsed-time-based movement (i.e. it rotates/moves "smooth").
Hopefully, it will be useful for anyone. For me it is :)
The camera interface is rather ugly right now, but that will improve. See the demo mentioned below.
joml-lwjgl3-demos (https://github.com/JOML-CI/joml-lwjgl3-demos)
This contains some showcases of how to use JOML with LWJGL 3. It also now features a simple OpenGL 1.1 demo using the ArcBallCamera (https://github.com/JOML-CI/joml-lwjgl3-demos/blob/master/src/org/joml/lwjgl/ArcBallCameraDemo.java).
I just tried the demo, nice work :)
I had to tweak one thing to get it to work on my mac, and that was to initialise width and height. Maybe Windows does a resize call at startup that OSX doesnt? I also get a 1/2 second black window before the scene renders, I can't test on my Windows box since I'm on the road at the moment. Peter
Yeah, thanks!
Might sound weird, but I am having a blast right now with JOML. There are a lot of new cool features being added to it, mostly regarding quaternions, while I am trying to hammer that quaternion math into my brain, which is really really hard to grasp! :)
But to hide all that, JOML provides nice interfaces, such as the all-new Quaternion.integrate() function, which allows you to apply angular velocity over a time differential to an existing quaternion in order to make it rotate "more" about a particular vector/axis.
Also new is the nlerp() function to linearly (non-spherically) interpolate rotations between two quaternions.
All this and more is now available in the 1.2.1-SNAPSHOT release (https://github.com/JOML-CI/JOML/releases/tag/1.2.1-SNAPSHOT)
Btw. how are things with the Oculus going along? Could you solve that projection issue?
Sounds fun, and I'm looking forward to trying some of that out soon!
I'm away from my windows oculus dev system, so I was just trying out JOML in a new project, with the aim to replace the current math in my Oculus project. Hopefully that will fix whatever was wrong there and I can get on making something a little more interesting after my travels. Peter.
From the 'joml-camera' readme I see:
"Free Camera: You can freely look around and move the camera in the scene"
Is that something already implemented? or in progress? Is it like a first person view?
If the person in "first person" is a space ship that can accelerate in all three major axes and rotate around, then yes, it is a first person camera. :)
But it is still in the making.
More generally, I am planning the interface of this camera to:
- provide a possibility to accelerate and decelerate the camera along all three axes
- provide the same for angular acceleration
- allow a client to map WASD/mouse or joystick/pad - or whatever input device it uses - to this interface
- maybe just like the ArcBall camera to just set a destination point/orientation and then let the camera figure out how to get there
But in the long run I want to move away from player-controlled cameras towards more parameterized systems allowing you to have a camera automatically move through your scene along a path specified by keyframes of given positions and orientations, just like the paths you can create in Blender, because I am going to need that for another project.
So, it's been about nine days since I posted the last update of JOML. There is still much going on in that project and now I begin to realize how much of a gain in (development) efficiency a code generator would have been. :)
But I guess we are out of the woods now and (existing parts of) the API stabilize.
The last changes have been mostly to refine small parts of the existing API, add a lot of new things regarding quaternions and polishing the JavaDocs.
So far the current snapshot release 1.2.5 (https://github.com/JOML-CI/JOML/releases/tag/1.2.5-SNAPSHOT) contains the latest changes.
where do you find the time :) well done. They seem like they will be well suited for working with the Rift when I get back from my travels.
I don't travel as much. :D
Nah, actually I am quite fed up with traveling. Travelled the last two and a half years through Germany to customers of our consulting company. Now, I am enjoying my stay in Hamburg for awhile. :)
But thanks. I am glad it is useful for you. Tell me if you find that something is missing or buggy.
Hey,
the next snapshot release 1.2.6 (https://github.com/JOML-CI/JOML/releases/tag/1.2.6-SNAPSHOT) of JOML is out and it features new methods to compute a reflection matrix!
This was somewhat the last missing piece of the picture to hopefully complete the matrix class.
With this reflect()/reflection() methods, you can build reflection matrices which (for example) allow you to do OpenGL stencil reflections about arbitrary planes!
And just because all demos out there showcasing stencil reflections always somehow use a simple plane (mostly y=0) which is boring, there is now a joml-lwjgl3-demo (https://github.com/JOML-CI/joml-lwjgl3-demos/blob/master/src/org/joml/lwjgl/ReflectDemo.java) which can use ANY reflection plane.
Check it out! :)
Hello JOML users,
the latest 1.3.0 release (https://github.com/JOML-CI/JOML/releases/tag/1.3.0) is out. It contains a whole host of changes (mostly additions), most important of which is the fix to a bug (https://github.com/JOML-CI/JOML/issues/26) in (set)LookAt and (set)LookAlong in Matrix3 and Matrix4 classes, as well as Quaternion.lookRotate.
People making use of those look-methods are encouraged to switch to the latest release.
Other things include making the double-precision classes more in sync with their single-precision variants.
There is also now a Matrix3/4.normal() computing a normal matrix, which is useful when transforming normals when using shaders when gl_NormalMatrix is not avaiable.
JOML has now a nice auto-generated GitHub Pages site (http://joml-ci.github.io/JOML/) with links to its generated JavaDocs. :)
Also, JOML's current 1.3.2-SNAPSHOT head is now pretty complete and contains full JavaDocs documentation for each method and every parameter/return value, passing JDK 1.8 doclint.
As of now, all snapshots and releases of JOML will be deployed to Sonatype.org.
The current version 1.3.3-SNAPSHOT is now there and can be used with the coordinates org.joml:joml
Since snapshot releases are not synchronized with Maven Central, you have to add a reference to the repository
https://oss.sonatype.org/content/repositories/snapshots (https://oss.sonatype.org/content/repositories/snapshots)
in your pom.xml, like so:
<repositories>
<repository>
<id>Sonatype Snapshots Repository</id>
<snapshots>
<enabled>true</enabled>
</snapshots>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</repository>
</repositories>
However, major releases of JOML (the next being 1.4.0) will be staged and synchronized with Maven Central, so you would not need the above repository declaration.
As part of the process, JOML now also has a domain joml.org (http://joml.org), which header-redirects to http://joml-ci.github.io/JOML/ (http://joml-ci.github.io/JOML/) until we have a web presence.
Instead of the header redirecting, set the domain to your GitHub pages by adding a CNAME record.
https://help.github.com/articles/adding-a-cname-file-to-your-repository/
Quote from: Kai on July 01, 2015, 18:57:38
However, major releases of JOML (the next being 1.4.0) will be staged and synchronized with Maven Central
Great news, and thanks :)
I have finally been able to port my Oculus VR code over to JOML, and the strange matrix issues I was previously having are now gone :)
Glad to hear that.
Also the latest 1.3.4 snapshot (already deployed to sonatype) contains the implementation of an incredibly nifty (http://www.cs.otago.ac.nz/postgrads/alexis/planeExtraction.pdf) way to compute the camera frustum planes (in class GeometryUtils). This insanely clever algorithm is also waaay faster and more accurate than what libGDX is currently doing (i.e. they go the way about unprojecting each of the 8 frustum corner points back from NDC, which requires a matrix inversion, and then building the planes from 3 of the corner points, each).
These can be used for frustum culling on the CPU, which is especially useful to keep the FPS high in very demanding scenes on the Rift. :)
EDIT:
The Matrix4 classes now also have fast and convenient is*InsideFrustum() methods for point, sphere and axis-aligned box tests.
Those are now on the edge towards render engine math utility functions, but JOML wants to provide math for OpenGL rendering calculations and I think this frustum check functions fit into this definition quite nicely.
These functions make use of the aforementioned method to compute the frustum planes (which is now also a part of the Matrix4 classes), and can be used for frustum culling in someone's voxel game, for example, like so:
Matrix4f m = new Matrix4f();
m.perspective(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);
// ...
Vector3f boxMin = new Vector3f(1.0f, 0.0f, 0.0f);
Vector3f boxMax = new Vector3f(2.0f, 1.0f, 1.0f);
boolean inside = m.isAabInsideFrustum(boxMin, boxMax);
// or
boolean inside = m.isAabInsideFrustum(1.0f, 0.0f, 0.0f,
2.0f, 1.0f, 1.0f);
The method directly operates on that view-projection or modelview-projection matrix which is used to transform the scene into clipping space. Therefore, JOML does not require a dedicated "Camera" class with various other parameters but can use the underlying transformation matrix directly.
(On my crappy i3-2120 the isAabInsideFrustum() can perform around 40 million AAB-frustum-intersection tests per second on a generic matrix, without any caching of frustum planes or anything else.)
EDIT2:
There is now also a Matrix4.frustumRayDir() which efficiently computes the direction of a ray starting from the origin and going through the near frustum plane, with interpolation parameters (x, y) to compute rays over the whole view frustum. This is especially useful for computing the eye rays for software raycasting/raytracing.
(it performs at about 30 million ray direction computations per second)
Fantastic progress Kai. Haven't used JOML yet so can't give more feedback, but I'm following the commits and love that you're keeping it simple and super useful.
Thank you Spasi!
Due to most of JOML's users wanting to use radians instead of degrees for angle parameters, starting with JOML's current 1.3.5-SNAPSHOT radians are now being used everywhere instead of degrees.
This also includes Matrix4.perspective, which now differs from the GLU API, so you gonna have to make:
new Matrix4f().perspective((float)Math.toRadians(60.0f), 1.0f, 0.01f, 100.0f);
if you want a 60 degrees vertical field of view angle.
See this issue (https://github.com/JOML-CI/JOML/issues/28) for further info.
Hello everyone,
finally, JOML also has a working and reliable method to compute the eight frustum corner points of any arbitrary projection or combined modelview-projection matrix in Matrix4.frustumCorner.
I was searching for a working way to do this for some time and finally found the 3-planes intersection technique to be the most performant.
It is also far more performant than the usual "transform NDC by the inverse of the matrix" way, which is taken by libGDX, among others.
The method generally is useful if you want to display a mesh representing a camera's view frustum in your scene / model editor, etc.
To obtain all 8 corners of an arbitrary view-projection matrix, first the near plane corners in counter-clockwise order, then the far plane corners in clockwise order, use:
Matrix4f m = new Matrix4f()
.perspective((float) Math.toRadians(90), 1.0f, 0.1f, 100.0f)
.lookAt(0, 3, 10,
0, 0, 0,
0, 1, 0);
Vector3f[] allCorners = new Vector3f[8];
for (int i = 0; i < 8; i++) {
m.frustumCorner(i, allCorners[i] = new Vector3f());
}
Matrix4 also defines convenient constants for the first parameter of frustumCorner(), to know which corner is which.
One example of such a constant is 'CORNER_PXNYNZ'.
The naming convention here follows after what sign the respective corner co-ordinate would have for the identity matrix/transformation (i.e. the default OpenGL clip space coordinate system).
'PX' means "positive X", and 'NY' means "negative Y".
So with the given constant, we would get the corner at (1, -1, -1) with the identity matrix.
This coincidentally is also the right-bottom-near corner in a standard OpenGL/GLU perspective projection matrix.
(The method performs at around 50 million corners per second on my i7-3820QM and can, like all the rest of JOML, be fully multithreaded, so potentially scales very well.)
EDIT:
There are now additional Matrix4 methods to get several properties of a perspective transformation, which are:
- perspectiveOrigin() - computes the origin/eye location of an arbitrary perspective transformation (either combined modelview-projection or just projection)
- perspectiveFov() - computes the vertical field-of-view angle of an arbitrary perspective transformation (either combined modelview-projection or just projection)
Since JOML grows and grows, in order to be equally useful to a wide range of people with slightly differing requirements, as a result the boundary between what is essential/necessary and what is nice to have/convenient/utility is becoming blurrier.
To keep JOML still simple, there will now be a `org.joml:joml-mini` artifact in a new 'mini' git branch (https://github.com/JOML-CI/JOML/tree/mini).
The goal with this is to keep JOML as simple and intelligible for newcomers as possible and sufficient for the 95% percent of 3D OpenGL applications.
It currently only contains 6 classes and its jar distribution only weighs about 38% (49KB) of the original full-feature `org.joml:joml`.
All non-essential but still useful additional stuff will go in the 'master' branch in the future.
The properties of joml-mini:
- only single-precision floating-point classes
- only 3D and 4D vectors
- no AxisAngle4f (use Quaternionf for rotations)
- no 'utility' classes and methods that are not really necessary
- classes are still named identical to the 'master' branch
What _is_ "necessary" is of course always debatable, but I think joml-mini contains all essential stuff right now.
First Maven Central deployed release 1.4.0 of joml and joml-mini are out now!
The coordinates are org.joml:joml:1.4.0 and org.joml:joml-mini:1.4.0.
I am currently preparing another "spin-off" (or variant) of the original JOML, that is called "joml-2d", which will be specifically geared towards 2D applications.
Since 2D applications/games seem so common around Java game developers, I am stripping the 3D classes of JOML off all things that do not apply to 2D, and add other things that do.
Currently, the "2d" branch of JOML's git repository contains only 2 classes: Matrix3f and Vector2f.
The 2D Matrix3f class resembles a bit the 3D Matrix4f class, with one dimension stripped. So the fourth column of Matrix4f becomes the third column in Matrix3f to represent a translation.
With 2D it is also only possible to rotate about the Z axis, so there is no rotateX, rotateY and rotateZ methods anymore, just rotate(). Also quaternions apply no more in 2D.
The general idea is then that with 2D applications you would only build 3x3 transformation matrices, which you also only upload as mat3 uniforms and apply only (x, y, 1.0) vector multiplications on them in your shaders.
The reduced number of arithmetic operations in the 3x3 matrix multiplication and such will also reduce the runtime of JOML-2d.
Altogether, the "ecosystem" of JOML would now be composed of three libraries:
- joml (contains everything for 3D applications, from the fundamentals to useful utility functions)
- joml-mini (contains only the things that 99% of the OpenGL applications would ever need)
- joml-2d (contains only things related to 2D, joml-2d is a spin-off of joml-mini)