How can glPushMatrix affect the rotation of an object around a rotating object?

41 Views Asked by At

I have been practicing matrix transformations for a while with a simple 2D solar system. I'm not concerned with the details about the size proportions, orbits, or distances each planet has. What I'm trying to understand is how OpenGl handles the commands glPushMatrix() and glPopMatrix() in the sense you can get a satellite (little object) orbit an orbiting planet (large object).

I made a planet orbit simulation program using as reference [this post].(Making a Solar System in OpenGL)

This is how my program looks when running: Simple 2D solar system

I'm mostly intrigued about this section of the program. Here, I'll provide a brief description of what it does, focusing just on three of the four objects displayed on the screen (The Sun, Earth, and moon):

Firstly, the program places the sun at the center of the screen. After that, the Earth is set to rotate around the sun in a circle with a radius of 4 units. As the Earth rotates around the sun, a moon orbits it in a circle with a radius of 1.5 units away from the Earth.

        # Sun
        plot_circle(radius=1, color=[180 / 255, 180 / 255, 16 / 255])
        glPushMatrix()
        # This code makes Earth spin around the sun.
        glRotate(angles[0], 0, 0, 1)
        glTranslate(4, 0, 0)
        # Earth
        plot_circle(radius=0.75, color=[0 / 255, 59 / 255, 174 / 255])
        glPushMatrix()
        # This somehow makes the moon spin around the earth.
        glRotate(angles[2], 0, 0, 1)
        glTranslate(0, 1.5, 0)
        # Moon
        plot_circle(radius=0.25, color=[128 / 255, 128 / 255, 128 / 255])
        glPopMatrix()
        glPopMatrix()

I understand the first glPushMatrix(). It performs a translation followed by a rotation to make the earth spin around the sun. However, my question has to do with the second glPushMatrix(), and why it makes the moon orbit the Earth as it orbits the Sun with perfect synchrony.

I believe the second glPushMatrix() uses the previous transformation matrix left after applying translation-rotation. Since this matrix has been transformed, the center/origin must have been transformed as well. In other words, the moon will have its origin point located at Earth's current position. So, given that the rotation point of the moon will be whatever position Earth has at the moment, the moon can orbit earth as it orbits the sun because the transformation matrix takes into account the translation-rotation operations applied before.

I would like to confirm if what I'm getting at is exactly what's going on? Is what I just explained the purpose of glPushMatrix()?

2

There are 2 best solutions below

0
fana On
  • glPushMatrix() just pushes the current matrix value onto the stack existing somewhere.
    • This is used to saving the current matrix value.
    • This function does not cause any changes to the current matrix.
  • glPopMatrix() pops the matrix value from top of the stack, and current matrix value is overwritten with this popped value.
    • This is used to loading the matrix value previously pushed.

This is the all.

They are useful to make local transformation.
In your code, they surround:

  1. local transformation for {Earth and Moon} only
  2. local transformation for Moon only.
plot_circle(radius=1, color=[180 / 255, 180 / 255, 16 / 255])

//vvv  [Start of local transformation(1) : for Earth and Moon]  vvv
glPushMatrix()

  glRotate(angles[0], 0, 0, 1)
  glTranslate(4, 0, 0)

  plot_circle(radius=0.75, color=[0 / 255, 59 / 255, 174 / 255])

  //vvv  [Start of local transformation(2) : for Moon only]  vvv
  glPushMatrix()

    glRotate(angles[2], 0, 0, 1)
    glTranslate(0, 1.5, 0)

    plot_circle(radius=0.25, color=[128 / 255, 128 / 255, 128 / 255])

  glPopMatrix()  //End of local transformation(2) : for Moon only
  //^^^  [End of local transformation(2) : for Moon only]  ^^^

glPopMatrix()
//^^^  [End of local transformation(1) : for Earth and Moon]  ^^^
0
Erdal Küçük On

For simplicity, let's only look at a translation.

For that we assume a scenario where the sun sits at the origin, the planet earth one unit to the right on the x-axis and the moon one unit further right of the earth.

If we want to render the sun, planet and the moon we typically would render the sun first, translate one unit to the right, render the earth and lastly translate again one unit to the right and render the moon.

If the planet would have two ore more moons instead of one, for each moon we would have to translate to the position of the moon and then back to be again at the origin of the planet. The same goes for many planets orbiting the sun.

Remember that any transformation operation requires matrix multiplication. For many moons orbiting the planet and many planets orbiting the sun, that will become costly very fast.

Therefore, instead of transforming back, we store the current matrix (glPushMatrix) and operate on the copy. To revert back we simply discard the copy and go back to the stored matrix (glPopMatrix).

From glPushMatrix/glPopMatrix

glPushMatrix pushes the current matrix stack down by one, duplicating the current matrix. That is, after a glPushMatrix call, the matrix on top of the stack is identical to the one below it.

glPopMatrix pops the current matrix stack, replacing the current matrix with the one below it on the stack.