mic4ael
mic4ael

Reputation: 8310

OpenGL sequence of triangle rotations

I have a triangle that I would like to rotate clockwise around its center of mass as well as the center of the coordinate system (counterclockwise). The problem is that both movements are counterclockwise and I can't figure out the solution.

from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *


def init():
    glClearColor(0.0, 0.0, 0.0, 0.0)
    glClearDepth(1.0)
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluOrtho2D(0.0, 640.0, 0.0, 480.0)

rotation = 1


def display():
    global rotation

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glLoadIdentity()

    glMatrixMode(GL_MODELVIEW)
    glPushMatrix()
    glRotate(rotation, 0.0, 0.0, 0.1)
    glTranslatef(0.0, 0.0, -0.1)
    glTranslatef(0.17, 0.17, 0.0)
    glRotate(rotation, 0.0, 0.0, 0.1)
    glTranslatef(-0.17, -0.17, 0.0)
    glBegin(GL_TRIANGLES)
    glColor3f(0.5, 0.5, 0.9)
    glVertex3f(0.5, 0.0, 0.0)
    glVertex3f(0.0, 0.5, 0.0)
    glVertex3f(0.0, 0.0, 0.0)
    glEnd()
    glPopMatrix()

    rotation += 1
    if rotation >= 360:
        rotation = 0
    glFlush()


if __name__ == '__main__':
    glutInit()
    glutCreateWindow('Rotating triangles')
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH)
    glutInitWindowSize(640, 480)
    glutDisplayFunc(display)
    glutIdleFunc(display)
    init()
    glutMainLoop()

Upvotes: 1

Views: 528

Answers (1)

CodeSurgeon
CodeSurgeon

Reputation: 2465

The key thing to understand about OpenGL's transformation stack is its order. Given the order of transformation matrix multiplication in OpenGL, the transformation commands are performed in reverse! Here is how I would think about performing the transformation that you had requested:

  1. Translate object so that center of mass is at center of world.
  2. Rotate object at desired speed about the center of world (which happens to be equivalent to the center of mass due to #1).
  3. Perform the reverse transformation of #1.
  4. Perform an additional transformation to change position of the object to desired world position (OPTIONAL in the case of your question).
  5. Rotate object at desired speed about the center of the world (which != the center of mass anymore).

In addition to making those relevant changes to your code, I did the following:

  • Added a primitive delay between frames so it does not tax the cpu with what was basically an infinite while loop (check the difference with a task manager).
  • Removed the glPushMatrix and glPopMatrix calls. They were unneeded here as you are only working with one object. You would typically push, then do an object transformation, then pop and repeat the process for each object.
  • Replaced rotation if statement with modulo operator (handles positive and negative rotations now in one line).
  • Commented out the gluOrtho call. The coordinates you were using were all between -1 and 1 (i.e. the default projection).

Here is the modified code below, with some helpful comments:

from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *
import time


def init():
    glClearColor(0.0, 0.0, 0.0, 0.0)
    glClearDepth(1.0)
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    #commented gluOrtho2D out since its inclusion would require different vertex coordinates (i.e. not between -1 and 1)
    #gluOrtho2D(0.0, 640.0, 0.0, 480.0)


obj_rot = 0.0
world_rot = 0.0
obj_rot_speed = 5.0
world_rot_speed = -1.0

def display():
    global obj_rot
    global world_rot
    global obj_rot_speed
    global world_rot_speed

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()#not needed here, but good practice to reset state!

    glRotate(world_rot, 0.0, 0.0, 1.0)#this transformation is peformed last (STEP 5)
    glTranslatef(0.3, 0.3, 0.0)#OPTIONAL (GLOBAL) TRANSLATION OF THE TRIANGLE
    glTranslatef(0.17, 0.17, 0.0)
    glRotate(obj_rot, 0.0, 0.0, 1.0)
    glTranslatef(-0.17, -0.17, 0.0)#this transformation is performed first (STEP 1)

    glBegin(GL_TRIANGLES)
    glColor3f(0.5, 0.5, 0.9)
    glVertex3f(0.5, 0.0, 0.0)
    glVertex3f(0.0, 0.5, 0.0)
    glVertex3f(0.0, 0.0, 0.0)
    glEnd()

    obj_rot += obj_rot_speed
    world_rot += world_rot_speed
    obj_rot %= 360#simpler approach than if statement, which did not address negative rotation
    world_rot %= 360

    glFlush()
    time.sleep(1/60.0)#VERY simplistically run the app at ~60 fps, avoids high CPU usage!

if __name__ == '__main__':
    glutInit()
    glutCreateWindow('Rotating triangles')
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH)
    glutInitWindowSize(640, 480)
    glutDisplayFunc(display)
    glutIdleFunc(display)
    init()
    glutMainLoop()

Let me know if any of this is unclear!

Upvotes: 2

Related Questions