Search code examples
c#opengl3dopentkrotational-matrices

Rotating about a Point in a Voxel Game Engine (C#)


I am continuing to build upon a voxel-based game engine made in OpenTK (a .NET/Mono binding of OpenGL). In this engine, there is a basic class called Volume which possesses traits such as position, rotation and scale, as well as rules to edit these values for animation.

How would I go about providing a function to rotate one point about another point?

I could quite easily rotate an object about its center (by changing its rotation property), but what if I need the object to rotate about origin or a random point in space? This would be useful for grouping blocks together, as I could therefore rotate objects as if they were stuck together - rather than them rotating individually.

I heard I would need to dive in at the deep end and learn about rotation matrices, but honestly it went over my head. The closest resource I have been able to find so far was this link, however it details rotating around an axis. Could somebody adapt these instructions: or even better, give me basic pseudocode for a function that rotates from a position and point of rotation?

EDIT: The following solution doesn't seem to work. My code is as simple as:

void RotateAboutPoint(Vector3 point, Vector3 amount)
{
    v.Translate(point);
    v.Rotate(amount);
    v.Translate(-point);
}

Should this work, and if not, could anyone help further now that the situation is explained properly? As far as I can tell, this may as well just be:

void RotateAboutPoint(Vector3 point, Vector3 amount)
{
    v.Rotate(amount);
}

Which defeats the object of performing this around a point. These co-ordinates are not in relation to the object... Sorry if my poor explanation made this unclear before!


Solution

  • I answered a similar question here: Rotating around a point different from origin

    in the link you provided author put the steps of rotation :

    (1) Translate space so that the rotation axis passes through the origin.
    (2) Rotate space about the z axis so that the rotation axis lies in the xz plane.
    (3) Rotate space about the y axis so that the rotation axis lies along the z axis.
    (4) Perform the desired rotation by θ about the z axis.
    (5) Apply the inverse of step (3).
    (6) Apply the inverse of step (2).
    (7) Apply the inverse of step (1).
    

    Actually in this process (2),(3),(5),(6) are unnecessary if you need to rotate about a point. These steps are the case if you need to rotate your object around a line.

    In your case : lets say you want to rotate your object around (a,b)

      GL.pushmatrix();
      translate your object by (a,b);
      rotate your object;
      translate your object by (-a,-b);
      GL.popmatrix();
    

    EDIT: Sorry I forgot to add encapsulation of your rotation process.(It was on the post I gave the link though)

    Further info:

    What is this encapsulation? why do we need this? Answer is simple. OpenGL stores a 4x4 matrice which is initially an identity matrice. When you perform a translate or rotate operation, opengl updates your matrice and at the final state opengl multiply each vertice with that matrice. (And if you do not perform any operation, vertices multiply with identity matrice give you the same vertice coordinates)

    The problem in your code is when you don't apply an encapsulation to your rotation/translate block, The final matrice will be same for all your objects in the scene. With encapsulation we guaranteed that the updated matrice will be used only inside that block.