0
\$\begingroup\$

I'm using OpenGL on Ubuntu Linux with the Eclipse IDE and the GCC compiler. I am bringing blender models into a homemade renderer/game engine. I parse a text file containing object descriptions to load models.

Example object:

begin_object generic_object
generic_object_name lampost
generic_object_parent_name world
generic_object_position -10.0000 -10.0000 2.000000
generic_object_rotation 90.000000 0.000000 0.000000
generic_object_scale 1.000000 1.000000 1.000000
end_object

begin_object ...

The generic_object_rotation 90.000000 0.000000 0.000000 line describes 3 values:

  • Rotation around Z (XY).
  • Rotation around X (YZ).
  • Rotation around Y (XZ).

After going through all the headaches of Euler angles and their gimbal lock and singularities, I switched all my code to quaternions (highly recommended).

I am told that a counter-clockwise rotation around the Z-axis, looking down the Z-axis toward the origin uses a rotation matrix like:

cos(theta)  -sin(theta)  0  0
sin(theta)  cos(theta)   0  0
0           0            1  0
0           0            0  1

I got this from a document (rotgen.pdf) off the Song-Ho website.

If I replace theta with +90.0 (just like in my input file above), the result is:

  0.0 ,  -1.0 ,  0.0 ,  0.0  
  1.0 ,   0.0 ,  0.0 ,  0.0 
  0.0 ,   0.0 ,  1.0 ,  0.0 
-10.0 , -10.0 ,  2.0 ,  1.0

So, I make a quaternion for +90.0 degrees, turn it into a matrix and then print out the matrix to see if it is the same, and I actually get the same matrix.

  0.0 ,  -1.0 ,  0.0 ,  0.0  
  1.0 ,   0.0 ,  0.0 ,  0.0 
  0.0 ,   0.0 ,  1.0 ,  0.0 
-10.0 , -10.0 ,  2.0 ,  1.0

All is well... Then, I send this matrix to the shader to draw this object and it rotates my object CW instead.

In the shader there's:

gl_Position = projection_matrix * view_matrix * model_matrix * vec4( aPos , 1.0 );

which seems correct.

So, I made a cube in Blender, attached different colour textures to each side of the cube so I could verify that my input data was good and, as long as the model_matrix is the identity matrix, the object is oriented correctly in space. Any time I add rotations, the models rotate in the opposite direction. This happens on all 3 axes.

My current goal/project is the parenting system. I want to be able to extract orientation and position from the model matrix of any object (that data is stored with the object).

Specifically, right now, I want to extract the forward vector from the model_matrix so I can attach a light source to this rotating object. Set its light direction for the fragment shader. That is when I found this error.

What I am seeing:
The rotation of the object is opposite to what I command. When I rotate 0-360 over and over again, the forward vector I am reading from the objects model_matrix diverges from the direction of the object until it gets to 180 degrees, where the face of the object and the forward vector are coincident again; then they diverge again until we reach 360 and they are again coincident.

What I expect (and this may be part of my issue):
I want the rotation part of the model_matrix that rotates the object to be the current orientation of the object. And it looks like it is but the object does not render that way. The object rotates in the opposite direction (which is preventing me from getting the correct light direction vector, i.e. the forward vector).

Is this an OpenGL thing? Is the orientation of an object the transpose of the 3x3 rotation section of the model_matrix?

\$\endgroup\$
2
  • \$\begingroup\$ Could this be because OpenGL and DirectX read matrices in a different way? (Row-major vs Column-major) More details on this question. \$\endgroup\$ – TomTsagk May 5 at 9:19
  • \$\begingroup\$ How do you calculate the projection matrix ? \$\endgroup\$ – user144188 May 7 at 10:32
0
\$\begingroup\$

The solution was to transpose the rotation matrix.

The link TomTsagk provided lead me to the solution.

I was using:

[0][0] , [1][0] , [2][0] as the side vector.
[0][1] , [1][1] , [2][1] as the up vector.
[0][2] , [1][2] , [2][2] as the forward vector.

The correct method was:
[0][0] , [0][1] , [0][2] as the side vector.
[1][0] , [1][1] , [1][2] as the up vector.
[2][0] , [2][1] , [2][2] as the forward vector.

So , position was always correct but rotation was not.

Also , thanks to liggiorgio for editing the original post.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.