2
\$\begingroup\$

I was recently writing a simple 3D maze FPP game. Once I was done fiddling with planes in OpenGL, I wanted to add support for importing Blender objects. The approach I used was triangulization of the object, then using Three.js to export the points to plaintext and then parsing the result JSON in my app.

The example file can be seen here: https://github.com/d33tah/tinyfpp/blob/master/Data/Models/cross.txt The numbers represent x,y,z,u,v of a single vertex, which combined in three make a triangle.

Then I rendered such an object triangle-by-triangle and played with it. I could move it back and forth and sideways, but I still have no idea how to rotate it by some axis. Let's say I'd like to rotate all the points by five degrees to the left, how would a code doing it look like?

\$\endgroup\$
3
  • \$\begingroup\$ Look up polar coordinates. \$\endgroup\$
    – jcora
    Nov 13, 2012 at 18:29
  • \$\begingroup\$ @Bane OpenGL has functions to rotate the object as shown in Apahidean's answer. No need to make it more complicated than it is :) \$\endgroup\$ Nov 13, 2012 at 18:57
  • \$\begingroup\$ Yeah, I know, but I guess it's always cool to know the math behind it (if that's the case). \$\endgroup\$
    – jcora
    Nov 13, 2012 at 20:08

2 Answers 2

2
\$\begingroup\$

I think the easiest way to rotate a vertex around an axis is using the Rodrigues Rotation Formula.

Here is my implementation of it using C++ and the library GLM:

(Note: it may not be the most efficient way, but I use it for learning purpose :3. Also, I'm using row major order (not the way GLM do things), so the multiplication is inverse later. Also, rotation are counter-clockwise :3)

glm::mat3 rodriguesMatrix(const double degrees, const glm::vec3& axis) {
glm::mat3 v = glm::mat3(
    axis.x*axis.x, axis.x*axis.y, axis.x*axis.z,
    axis.x*axis.y, axis.y*axis.y, axis.y*axis.z,
    axis.x*axis.z, axis.y*axis.z, axis.z*axis.z
    );

glm::mat3 v2 = glm::mat3(
    0, -axis.z, axis.y,
    axis.z, 0, -axis.x,
    -axis.y, axis.x, 0
    );

glm::mat3 rotation = cos(degrees * M_PI/180.f) * glm::mat3(1.0f) + (1-cos(degrees * M_PI/180.f)) * v + sin(degrees * M_PI/180.f) * v2;

return rotation;
}

So, let's say you want to rotate the vertice (3.866185 -0.996761 -1.366355)(first of your example) by 5 degress along the y axis. You can do it by doing something like:

glm::vec3 y_unit = glm::vec3(0, 1.f, 0);

glm::mat3 rotationMatrix = rodriguesMatrix(5, y_unit);

glm::vec3 myVertice = glm::vec3(3.866185,-0.996761,-1.366355);

glm::vec3 myVerticeRotated = myVertice*rotationMatrix;
\$\endgroup\$
6
  • \$\begingroup\$ -1 It's a very bad advice to use glm in in row major form instead of OpenGL's native column major form. Especially if the asker seems to be not fluent with it, it will make it much harder for him. Just use the plain glm matrix rotation functions, then you can also use them for OpenGL as they are. \$\endgroup\$ Nov 13, 2012 at 18:25
  • \$\begingroup\$ The Row Major form is how this formula is present in the literature, and I found it easier to learn this way. Also, I did not post plain calls to rotations, but instead an actual implementation so the OP can implement it in others languages without GLM if he decides to use modern OpenGL. \$\endgroup\$ Nov 13, 2012 at 19:25
  • \$\begingroup\$ IT WORKED! Thanks a lot, mate! :) Now, the question is... I implemented it, how do I change the center point? Here's the code in my version: github.com/d33tah/tinyfpp/compare/… \$\endgroup\$
    – d33tah
    Nov 13, 2012 at 23:14
  • \$\begingroup\$ @d33tah What this algorithm is doing is rotating each of your vertices around one vector (in your code, it is the y axis, declared by the y_unit variable). To change the center of the rotation, you have to translate your vertices to a new position, apply rotation, then translate back by the same distance. I highly recommend watching those videos, they are very, very, very good :) \$\endgroup\$ Nov 13, 2012 at 23:41
  • \$\begingroup\$ @d33tah you can combine all those operation in one matrix, and then only transform your points once using that matrix. No need for multiple matrix*point operations on the same point. \$\endgroup\$ Nov 14, 2012 at 15:56
5
\$\begingroup\$
glPushMatrix();

// Translate our object in  (x,y,z) position
glTranslatef(x, y, z); 

// Rotates the object around a rotation axis
// i.e. glRotatef(45.0, 0.0, 1.0, 0.0) rotates 45 degrees around the y-axis
glRotatef(angle, rot_axis_x, rot_axis_y, rot_axis_z);  

// Create a function for drawing the object
Draw();   

glPopMatrix();

You need to draw you're object preferably in the origin, because every rotation that you apply will be done around a position vector (vector that starts from the origin), and than you can translate it. OpenGl will first rotate your object and then it will translate it, so it will call the functions in reverse order. If you change the order, you will first translate the object and then rotate it around the position vector.

\$\endgroup\$
4
  • \$\begingroup\$ Not really what I asked for. \$\endgroup\$
    – d33tah
    Nov 13, 2012 at 16:08
  • 1
    \$\begingroup\$ @d33tah actually that is the correct answer and exactly what you asked for. This is the OpenGL way of doing what you were asking. +1 \$\endgroup\$ Nov 13, 2012 at 18:27
  • \$\begingroup\$ @Apahidean Iancu you might want to look at the format options for answers, it makes your answer much more readable. I edited your answer :) \$\endgroup\$ Nov 13, 2012 at 18:32
  • \$\begingroup\$ Well, if I wanted to render a rotated object, that would be perfect. The point is, I wanted to rotate a set of points and it was AranHase that helped me out here. Thanks for sharing anyway ^^ \$\endgroup\$
    – d33tah
    Nov 13, 2012 at 23:40

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .