Using javax.vecmath for matrices

Started by Andrew_3ds, April 22, 2015, 02:15:46

Previous topic - Next topic

Andrew_3ds

I just switched from using the lwjgl_util to using java's own vecmath, but now nothing is working. I'm guessing it's the matrices that work differently, because now nothing appears on the screen using the javax Matrix4f. Does anyone know why it's not working?

Neoptolemus

It's possible that the Javax class stores the Matrix classes as row-major rather than column-major as OpenGL expects. Try transposing the matrix before calling glUniformMatrix4fv, or setting the second parameter to true (which I think tells OpenGL to automatically transpose).

Alternatively, you can use a library I put together with Kai called JOML (Java OpenGL Math Library). You can find it here:

https://github.com/JOML-CI/Java-OpenGL-Math-Library

It also has some useful helper functions including perspective, ortho, lookAt and so on. This is what I'm using and so far not had any issues.

Andrew_3ds

I tried using transpose, it doesn't do anything but make it look distorted in a different way. I just want to use vecmath because jBullet uses it and I don't want to have excess libraries, only ones that I need. Is there a way that it could be something else?

Neoptolemus

How are you storing your matrices into the floatbuffer? Perhaps there could be an issue with that? If you're 100% sure the formula you're using to calculate your projection/view/model matrices is correct (and it should be if it was working fine with the old LWJGL classes), then it's the only other thing I can think of.

Alternatively, to try and debug a little, try printing out the matrices that have been calculated and compare them to what they should look like. I'm not sure if javax provides a toString override for their classes, but if not you can just print out each value separately. That way you can definitely rule out the formula being wrong or the values within the Matrix4f class being stored oddly.

If it helps, you're free to crib anything you like from my library, as those formula are proven to work so you at least have a point of reference.

Andrew_3ds

I just decided to use your math library  :). One question though, how do I rotate matrices with JOML? I can't find a 'rotate' method in the class.

McFlyboy

I tried using JOML, but had troubles with the rotation. When I used createTransformationMatrix() in MatrixUtils, the more I rotated it the more it scaled up. After that, I gave up JOML and started making my own vecmath, which was hard until I discovered a site where you can find the sourcecode for Matrix4f from LWJGL 2. So I just copied functions from there.

You can find the sourcecode here: http://grepcode.com/file/repo1.maven.org/maven2/org.lwjgl.lwjgl/lwjgl_util/2.8.0/org/lwjgl/util/vector/Matrix4f.java

Kai

Quote...After that, I gave up JOML
Sorry to hear that. But thanks for giving it a try and testing it! Much appreciated.
If you want, you are very welcome to contribute anything you have to JOML.
You see, JOML was introduced by people in order to help those out there with a vector library, because LWJGL 3 does not feature such a library.
It may very well be that at some points JOML does not produce correct results, especially with such complex methods as createTranformationMatrix, which also lacks definite semantics as to what the expected result matrix would be and in which order the transformations (rotation, scaling translation) are being applied. JOML mostly is tested, but not all of it due to the lack of time.
If you want you can at any time contribute a fix or introduce new functionality that you see fits.
Just do a pull request.
Thanks again for trying JOML out!

Kai

There are now the three basic transformation operations scaling(), translation() and rotation() in the Matrix4x classes which set the matrix to be a simple scaling, translation or rotation matrix.
You can use them instead of the MatrixUtils (which got removed now) by building separate translation, rotation and scaling matrices and mul() them together in the order that suits you.
Since I fear that the order of operations can be individual to everyone, it is better to stick to the simple bare methods in JOML and let the user decide what she/he wants.
If you need more sophisticated rotation capabilities than just "rotate radians about vector" then the Quaternion class is for you, which features "correct" rotation about euler angles with two different rotation orders.

McFlyboy

Nice! Right now I'm trying to learn more about GLFW, but as soon as I get back to vecmath I'll give the new JOML-version a try :)

Kai

Glad to hear.
I was thinking about also adding a legacy-OpenGL-like matrix interface.
You know, where you simply do:
MatrixStack stack = new MatrixStack();
stack.pushMatrix();
stack.loadIdentity();
stack.translate(1.0f, 0.0f, 0.0f);
stack.rotate(45.0f, 0.0f, 1.0f, 0.0f);
stack.scale(0.5f, 0.5f, 0.5f);
Matrix4f mat = stack.popMatrix();

Don't know how useful that would be, though.
But it would help people accustomed to legacy OpenGL to continue using their "style of math."
I would also do not want to "gl"-prefix those methods since they have nothing to do with OpenGL/LWJGL.
And I would also not like to make them static, but instead have them as instance methods on MatrixStack,
since otherwise you would have multithreading issues and having to handle ThreadLocal and all sorts.
What do you think?

EDIT:

Legacy-OpenGL-like matrix stack is available now via the MatrixStack class.
The methods have the same semantics as their OpenGL counterparts.
This is essentially the case with any transformations via translate(), rotate() and scale(), meaning that those are being applied first when transforming a vector with this.
The JavaDoc of those methods should indicate that clearly.

One example. Here, we want to obtain a matrix that first scales all axes by 0.5 and then translates x by 2.0:
Matrix4f result = new Matrix4f();
MatrixStack stack = new MatrixStack();
stack.translate(2.0f, 0.0f, 0.0f);
stack.scale(0.5f, 0.5f, 0.5f);
stack.get(result);

McFlyboy

Its an interesting concept which could help newcomers start in the small learning modern OpenGL. It could be useful for bridging ones knowledge of the fixed function-pipeline to the programmable pipeline.
However the difference between using MatrixStack, and multiplying 3 matrices (translation, rotation and scaling) together isn't that big, thus making it seem a little redundant, unless one REALLY wants to use an interface with a legacy-style.

EDIT: The way it looks now is much better than the example you showed previously.

Kai

Quote from: McFlyboy on May 28, 2015, 09:59:08
However the difference between using MatrixStack, and multiplying 3 matrices (translation, rotation and scaling) together isn't that big, thus making it seem a little redundant, unless one REALLY wants to use an interface with a legacy-style.
Yepp, that's true.

Just thought about that using the matrix stack interface allows the concatenation of the transformations to be performed more efficiently, since they need not be implemented as matrix multiplications but rather as some very small number of scalar multiplications, because most of the matrix elements are known to be zero anyways for translate, scale and rotate.
It is however very questionable whether this really will pose a significant bottleneck in any application.
But I guess I will add it.

EDIT:

Okay, added it. Now the matrix stack operations are implemented in the most efficient way possible. :)
Benchmarked it and I can execute around
- 650,000,000 translate()
- 10,000,000 rotate()
- 10,000,000 scale()
operations per second on my crappy i3-2120 CPU.
Now try to do that with the native GL methods... :)

Kai

I lifted the "apply" translate, scale and rotate methods from the MatrixStack to the Matrix4x classes.
EDITED: ...a lot of text...
Just have a look at the Github repository description

kappa

You've done a really nice job with JOML, really love the simplicity and minimalism of it.

Kai

Thank you, kappa!
Much appreciated. :)