LWJGL Forum

Please login or register.

Login with username, password and session length

Author Topic: MVP matrix in JOML  (Read 1262 times)

josephdoss

  • Newbie
  • *
  • Offline Offline
  • Posts: 6
MVP matrix in JOML
« on: July 26, 2016, 20:49:11 »

Hey Bros,

Yesterday I just got so sick of C++ dependency problems that I decided to move my video game to Java. It's actually been a pretty good move. Already the external library situation has gone from 12 to 1 and I have way less files to keep track of. And no more makefile! My problem though is I can't figure out how to do the MVP matrix the way I had it in C++. Apparently, lwjgl was overhauled and rereleased just last month, which is probably why I can't find any tutorials or examples for lwjgl 3.0 out here on the net.

So, I need some help. Below is the C++ code. The facing, eyeXYZ, character(), and other variables I can get already in Java. What I can't do is get the whole matrix situation acting right. I'm using Matrix4f and Vector3f and Matrix4f.mul/flip and FloatBuffers and .... I don't even know. Apparently Linear Algebra is the one area where C++ is actually simpler than Java.

What I need is to input the desired camera positiion ( eyeXYZ ) and the characterXYZ and get them MVP matrix back.
I'll then pass the MVP matrix as a uniform into the vertex shader and then be able to follow my character around, RPG style.

Can anyone help?

//C++ code that does exactly what I need
       
float facing = getCharacterFacing();
facing = (float) ( ( (int) (facing + 180) ) % 360 ) ;
float eyeX = getCharacterX() + CAMERA_DISTANCE_BEHIND * cos( facing * PI / 180.0);
float eyeY = getCharacterY() + CAMERA_DISTANCE_BEHIND * sin( facing * PI / 180.0 );
float eyeZ = getCharacterZ() + 4.0;
               
glm::mat4 Projection = glm::perspective(45.0f, (float)640/480, 0.1f, 100.0f);

glm::mat4 View       = glm::lookAt(
    glm::vec3(eyeX,eyeY,eyeZ),                          // Camera is at (4,3,3), in World Space
    glm::vec3(getCharacterX(),getCharacterY(),getCharacterZ()), // and looks at the character
    glm::vec3(0,0,getCharacterZ()+20.0)             // Up is positive Z, 20 units above character so it's guaranteed to be above character
);

glm::mat4 Model      =  glm::mat4(1.0f); 

glm::mat4 MVP        = Projection * View * Model;

Logged

Kai

  • Nerdus Imperius
  • *****
  • Offline Offline
  • Posts: 899
Re: MVP matrix in JOML
« Reply #1 on: July 29, 2016, 17:27:39 »

Quote
Apparently Linear Algebra is the one area where C++ is actually simpler than Java.
Nope. :) Not when done right. JOML's API is actually more "fluent" than GLM's. And using a lookat transformation when computing an "arcball" camera, like you did, is more complicated than doing it the direct way with translate/rotate. So your complete shown code becomes:
Code: [Select]
float CAMERA_DISTANCE_BEHIND = 8.0f;
float HEIGHT_ABOVE_PLAYER = 4.0f;
float facingInRad = (float)Math.toRadians(facing);
// Compute angle above player from "opposite leg" / "adjacent leg"
float angle = (float) Math.atan(HEIGHT_ABOVE_PLAYER / CAMERA_DISTANCE_BEHIND);
// Build transformation matrix (using +Z as up)
mvp.setPerspective((float)Math.toRadians(45), 640.0f/480.0f, 0.1f, 100.0f)
   .translate(0, 0, -CAMERA_DISTANCE_BEHIND) // <- move camera away from player
   .rotateX(angle - (float)Math.PI * 0.5f) // <- keep an angle 'above' the player and make +Z point upwards
   .rotateZ(facingInRad) // <- rotate to correct facing
   .translate(-player.x, -player.y, -player.z); // <- move camera target/center to player position
Though it is unusual to have +Z being up. Usually with OpenGL and Direct3D +Y is up. So if you choose to use +Y as up, then the rotations of above code become:
Code: [Select]
   .rotateX(angle) // <- keep an angle 'above' the player
   .rotateY(facingInRad) // <- rotate to correct facing
Additionally, when you use +Y as up, you can use the Matrix4f.arcball() method, which makes your code more readable. The above complete code with +Y up then becomes:
Code: [Select]
float CAMERA_DISTANCE_BEHIND = 8.0f;
float HEIGHT_ABOVE_PLAYER = 4.0f;
float facingInRad = (float)Math.toRadians(facing);
// Compute angle from "opposite leg" / "adjacent leg"
float angle = (float) Math.atan(HEIGHT_ABOVE_PLAYER / CAMERA_DISTANCE_BEHIND);
// Build transformation matrix (using +Y as up)
mvp.setPerspective((float)Math.toRadians(45), 640.0f/480.0f, 0.1f, 100.0f)
   .arcball(CAMERA_DISTANCE_BEHIND, player.x, player.y, player.z, angle, facingInRad);
If you still want to use Matrix4f.lookAt() and compute the camera position like you did, then have a look at: https://github.com/JOML-CI/JOML#building-a-camera-transformation
Mayor take-aways from this: Matrix multiplications are simple concatenations of transformation methods in JOML. See https://github.com/JOML-CI/JOML/wiki/Design#post-multiplied-transformations for more detail.
Also: All angles are in radians. This includes the field-of-view angle in Matrix4f.setPerspective(). This convention differs from GLU and GLM (if GLM_FORCE_RADIANS is not used).
Logged

josephdoss

  • Newbie
  • *
  • Offline Offline
  • Posts: 6
Re: MVP matrix in JOML
« Reply #2 on: July 29, 2016, 20:51:11 »

Thanks man,
That would have taken me a million years to work out on my own.

Cheers,
JD
Logged

josephdoss

  • Newbie
  • *
  • Offline Offline
  • Posts: 6
Re: MVP matrix in JOML
« Reply #3 on: September 29, 2016, 11:25:28 »

Hey Kai,

I know it's been a few months and you probably don't still have the code, but if you're still around, would you show me how you made the mvp object in your java code? Is that a joml array or something?
Logged

Kai

  • Nerdus Imperius
  • *****
  • Offline Offline
  • Posts: 899
Re: MVP matrix in JOML
« Reply #4 on: September 29, 2016, 12:25:06 »

Hey JD,
I have plenty of code creating model-view-projection matrices around, that you can also have a look at. See all the demos in these repositories:
- https://github.com/JOML-CI/joml-lwjgl3-demos/tree/master/src/org/joml/lwjgl
- https://github.com/LWJGL/lwjgl3-demos/tree/master/src/org/lwjgl/demo/opengl

I'd start with the former, because it focuses more on the JOML-side of things and not so much on OpenGL.

Quote
...you made the mvp object in your java code? Is that a joml array or something?
I don't quite know what you mean by 'mvp object' and by 'joml array'.

The code that you see in my posts in this thread create mvp matrices. They assume that there is a variable (field or local) called 'mvp' of the type Matrix4f.
Logged

josephdoss

  • Newbie
  • *
  • Offline Offline
  • Posts: 6
Re: MVP matrix in JOML
« Reply #5 on: September 29, 2016, 12:41:36 »

Thanks man, that helped!

Now I just have to pass mvp to my shader and I think I'm in business.

Thanks for all your help,
JD
Logged