Java OpenGL Math Library (JOML)

Hm, someone got out the wrong side of bed today. Here’s how I would approach this without apparently exploding in rage at the injustice of the universe:

What is the design purpose of this method? Perhaps it is redundant.


public Vector3f with(Vector3f v) {
        return v;
}

Cas :slight_smile:

it’s about chaining.

for example, just as seen here : [icode]q1.slerp(q2, alpha, dest).with(dest).transform(v);[/icode] - slerp returns the quaternion itself - if you want to continue the “chain” with the output vector of the quat.slerp() method you can use … the [icode]with()[/icode] method. methods with multiple arguments and return values breaking the chain. @childofgod : try again.

might look useles when you look on the source but if you like the “chain-sugar” it makes sense. if you dont like it dont use it, if you dont understand it dont bitch.

“Redundant”?! If it was written by mistake or just as a stub for later - I would call that a redundant code. But in this case it’s an ill-minded idea to allow so called “switching contexts”(yuckh) that was planned ahead. So no, your lies and combinations dont work on me.

Haha “chain sugar”, you’re funny.

Oh I guess there should be a method called “with” for every class in the Java library so you can chain for ever and ever:


class Object {
  Object with(Object o) {
    return o;
  }
}

Oh look, now you can chain everything (though you will have to do some casting). But yeah - essentially you got chain-sugar. Chain-sugar for life!

I’m probably a genius and should post that to Oracle as proposal on Java Object class.

Because why just use the simple:


q1.slerp(q2, alpha, dest);
dest.transform(v);


It’s so fucking mainstream!

Seems reasonable to do things either way to me. I’m not a great fan of method chaining though it can produce some prettier looking code; seems like it’s really just making up for some syntax that’s missing from Java generally. All hail LISP etc.

Cas :slight_smile:

public <T> T chain( T t )
{
  return t;
}

i’m not a fan of chaining either.

bzkRVzciAZg

There are people who think, they made something new, but what they did is a retarded way of solving well known problem, that had solutions way before.

And yeah if I was to bring some C++ into the Java , why just dont make the new keyword go away?


class Boo {

  public static void main() {
    Vector3f v = Vector3f(10.0f,15.0f,30.0f); // Who cares about "new" keyword????
    
  }

  public static static Vector3f Vector3f(float x, float y, float z) {
    return new Vector3f(x,y,z);
  }

}


Not to mention I would have to create such methods for every class.

Or create once in a utility class and static import them. I wouldn’t prefer this though, I’m pretty fine with the new keyword.

Nobody said it was particularly useful or was better.
My ‘diagnosis’ is that whoever came up with it didn’t realize it was possible someone would have such strong opinions about such an inconsequential detail and just wanted a method of “switching context” with syntax consistent with how the rest of the library is idiomatically used (i.e. method chains).

Whether or not it was ill-minded or retarded or genius I don’t know, because I don’t actually give a damn.

I await the monster.

Thank you all for your throughout positive, kind and encouraging feedback and constructive criticism!
The JGO community is really great! :wink: It is much appreciated!
If you feel that you can improve JOML’s design or functionality and would like to contribute additions/changes in the form of code that would help you in your projects, you are very welcome to make a contribution.
Just make sure to read about JOML’s design goals first, before investing in some code.
If you instead just want to tell us about enhancements that come to your mind or about bugs you found, you can happily post an issue at GitHub.
Your contributions can only help us improve JOML and reach a wider array of potential users.
We are looking forward to hearing from you over at GitHub!

  • the JOML team
design goals

Get your medicines, quickly.

@childofgod
Please, if you don’t like the chaining, okay, I understand, I don’t like it either. But it in no way destroys the language. If you don’t like it, don’t use it, simple as that. No need to be so darn rude about it. Yes, it may be a stupid idea (no offense, OP), but it’s in no way required of you to use it.

I honestly don’t give a fudge about a command that I don’t have to use (both directly and indirectly), so, yeah. The OP may have wanted to watch the world burn because of the with() command, but I really don’t care.

@childofgod somewhere you may have a valid point, but your attitude sucks so I couldn’t really be bothered reading between the lines to find out! :wink:

I can’t really say it better than @CommanderKeith put it in another recent thread -

PS. I will partly forgive you because I enjoyed the node.js video. :slight_smile:

This looks really interesting. Due to the major flaws of LWJGL’s math library (missing lots of important functions, like slerp for quaternions and vectors) I opted to rip out LibGDX’s math library for We Shall Wake/Insomnia. This has both the advantage and drawback of having native code for certain slow functions (matrix multiplication, matrix inverting, etc), but the additional dependencies and natives inflate the size of the game, and more code means that things can go wrong in more places. In addition, LibGDX’s math library is completely dependent on static temporary variables, making it useless for multithreading, which I’ve had to hack around by replacing certain functions and/or add thread-local temp variables instead. All in all, between those two LibGDX’s lib was the better one despite all its flaws.

JOML seems to offer some really interesting features, but also seems to lack a few extra features I could really use. I took a look at it, and here’s a list of my feedback.

  • Quaternion should be renamed to Quaternionf to follow the same convention as everything else.
  • Generally, AngleAxis is called AxisAngle. AngleAxis just doesn’t ring the same. =P
  • In some rare cases, Insomnia suffers from floating point precision problems in some matrix calculations. Many game engines calculate all matrices at double precision and finally converts everything to single precision when uploading it to OpenGL, but neither LibGDX or LWJGL’s library has support for that. JOML actually does, but it’s incomplete. For this to work, I would need an identical set of functions for both Matrix4f and Matrix4d, but the double version doesn’t have many important functions. Also, a function to store a Matrix4d in a FloatBuffer would be nice.
  • The performance of my skeleton animation is probably THE most performance critical section in the entire engine, and it involves constructing a matrix from a translation, a scale and a quaternion rotation. LibGDX has an excellent extremely fast method for doing this (line 202).
  • I calculate a lot of normal matrices from view matrices. A function that can extract a 3x3 normal matrix from a 4x4 matrix would be nice.
  • Many calculations actually only require a 4x3 matrix (view matrix, object transform matrices, bone matrices). A separate 4x3 matrix class would be overkill, but functions to only store the rotation and translation part of the matrix (12 floats) in a float buffer would be nice. It’s also possible to make an optimized matrix multiplication function if you know that the last row is (0, 0, 0, 1), which could help you beat LibGDX’s native performance in my skeleton calculation.
  • LibGDX doesn’t actually have a Vector4 class, only Vector3. Matrix4s can transform Vector3s by mul() (assumes W is 1.0 and discards the calculated W value) and proj() (assumes W is 1.0 and divides by the calculated W value). Such a function would definitely ease porting from LibGDX and save me a lot of time.

All that’s left after that would be performance, but I strongly believe you can beat LibGDX due to the questionable design choices they made. Matrix multiplication is definitely the slowest part of my engine (taking up a sizeable percentage on the CPU time taken by an entire frame), and an optimized 4x3 matrix multiplication would be able to cut the matrix multiplication cost by a lot. Add the better naming convention, multithreading readiness and double precision calculations and you have a really attractive library for me.

EDIT:
Would also prefer radians instead of degrees. It’s so confusing when I have to mix Java’s Math functions with the library. Also, your rotation functions have this:


        float cos = (float) Math.cos(Math.toRadians(ang));
        float sin = (float) Math.sin(Math.toRadians(ang));

You should cache the radian angle instead of calculating it twice. Not sure if Hotspot takes care of that for you, probably not.

Thanks a lot @theagentd for your very detailed evaluation and assessment of JOML.
We would be very glad to help you with your use cases.

[quote]but the double version doesn’t have many important functions.
[/quote]
That is definitely true. The double-precision classes always somewhat lagged behind, because they were not as important for existing use-cases of JOML, but now that we know that these really are important, we will sync them.

[quote]it involves constructing a matrix from a translation, a scale and a quaternion rotation
[/quote]
Yes, JOML used to have such a method too, but in general, the order of the operations then needs to be defined properly for such a compound method, that’s why JOML only has methods for the primitives, which would then be needed to chain/multiply together.
But again, now that we know that this is an important use-case regarding performance, that compound method will definitely be useful, I agree, and will sure be added in the next JOML release!

[quote]Matrix4s can transform Vector3s by mul()
[/quote]
JOML’s Matrix4f also has this ability with transform(Vector3f).

Thank you again for your time and your valuable input!

  • the JOML team

Another really useful function is setTranslation(), which explicitly sets the translation part of a 4x4 matrix. In some cases it’s a lot faster to just do it that way instead of having to translate the matrix.

EDIT: AND PLEASE, add a multiply-and-add function. Literally the most common thing I do in the engine is (position = position + velocity*delta). Add a function (I usually call it mad for multiply-and-and, which is what we call it for GLSL) that can be used like this


position.mad(velocity, delta);

and I’ll give you my firstborn son when I get him (ETA ~10 years I guess).

Most of your proposed changes made it into JOML now (sync’ing Matrix4f to Matrix4d is still in progress, however). So, thanks for driving JOML!

Regarding radians vs. degrees:
I tried to stick with what existing and common APIs like OpenGL, GLU, Unity and XNA use in their methods taking angles as parameters, which is degrees. I chose this way in order to make migrating between those libraries and JOML as easy as possible, and to comply with the expectations of those users.

Debatable however is the use of degrees in AxisAngle4f, which I am willing to change, since this is inconsistently being used in other libraries (Unity uses degrees, XNA uses radians, …), however mostly radians.
But using radians in AxisAngle4f and degrees in other interface methods in JOML would also be inconsistent, that’s why initially I chose degrees everywhere.
What do you think about it?

(and please, I do not want to get drawn into a discussion of why degrees are or aren’t better than radians. This is of no concern to me, really. Pragmatism and reaching user’s expectations is key for JOML here. :slight_smile:

In my opinion, radians is the way to go, solely because that’s what Java uses. JOML isn’t meant to emulate OpenGL’s legacy matrix system, it’s meant to replace it. There are lots of things that are different between OpenGL and JOML’s matrix management (function names, etc), so it really won’t ease the conversion as OpenGL is the odd one here. It makes more sense to do the same way that Java’s math functions do it or you’ll end up with really weird situations where you want to calculate some camera angle manually using cos() and sin() and need to keep track of if it’s radians or degrees. I’d rather just have one type of angle.

Example: I have cone lights in my game, and the angle of the cone is controlled by an angle variable. The cutoff in the GLSL shader is handled by comparing dot products (cosine of angles), so I compute Math.cos() which uses radians. I then need to compute a perspective matrix for the shadow map, which is done by LibGDX’s Matrix4 class which uses degrees. This leads to some intuition problems. Should the user-controlled cone angle be stored in radians or degrees? No matter which one you choose, it’s not clear for the user which one to use at first glance. I can’t make the entire engine use either degrees or radians as the user is inevitably exposed to both java.lang.Math and the vector library. It ends up being a massive clarity problem which is very prone to potentially hard to detect problems. If JOML uses radians like Math, the entire problem is solved.

Personally prefer degrees over radians, just find them easier to wrap my head round when thinking about rotations. Guess it ultimately boils down to personal preference.

Just curious and not sure how feasible it is, would it be possible to support both? like having a method in the library that can be used to switch all the methods globally in the library to use either DEG or RAD?

Would end the debate over which type of angle measurement to use :slight_smile:

kappa: that would break half of the tutorials, and lead to major confusion when using two tutorials that define different units for their angles.

Hm… I tried to stick as closely as possible to the naming and semantics of OpenGL’s and GLU’s matrix methods.

So, except for the obvious drop of the “gl” prefix, there should not be any other differences between OpenGL’s matrix stack functions and JOML’s methods: They take the same parameters, in the same order, and they have the exact same semantics (post-multiplying transformations).
Okay, JOML also provides ways to write the result to another matrix than to ‘this’, because that came convenient.

In my opinion, JOML does not and should not want to replace OpenGL’s matrix stack by changing the interface, but instead try to make the same functionality accessible to modern OpenGL programs.

This is so that OpenGL programmers comfortable with the legacy matrix stack immediately feel home when using JOML when they decide to switch from OpenGL’s legacy matrix stack to doing the math in Java with JOML.
However, this was the first thing that drove JOML’s design, since many LWJGL 3 users complained about how they would do the math with modern OpenGL and without LWJGL 2’s utility package around anymore.

I’m not saying, that this is the ultimate fix design, but it’s just what drove JOML so far. :slight_smile: