Search code examples
pythonopenglgraphicspyopenglcoordinate-transformation

python openGL: translate triangle(global & local) without openGL function


I'm trying to translate a triangle without OpenGL function, such glTranslate*() or glScale*().

My render code is:

def render(T):
    glClear(GL_COLOR_BUFFER_BIT)
    glLoadIdentity()
    # draw coordinate
    glBegin(GL_LINES)
    glColor3ub(255, 0, 0)
    glVertex2fv(np.array([0., 0.]))
    glVertex2fv(np.array([1., 0.]))
    glColor3ub(0, 255, 0)
    glVertex2fv(np.array([0., 0.]))
    glVertex2fv(np.array([0., 1.]))
    glEnd()
    #draw triangle
    glBegin(GL_TRIANGLES)
    glColor3ub(255,255,255)

    #this is the part that I'm trying to modify.
    glVertex2fv(( **T** @ np.array([.0, .5, 1.]))[:-1])
    glVertex2fv(( **T** @ np.array([.0, .0, 1.]))[:-1])
    glVertex2fv(( **T** @ np.array([.5, .0, 1.]))[:-1])
    glEnd()

I know how translate, roate, and scale matrix works; for examples:

T = np.identity(4)
T[:3 ,3] = [-.4, 0., .0]
#this shifts object by -.4 about x-axis.

However, I am not sure how to implement as code. I have a triangle with these coordinate,

glVertex2fv(( **T** @ np.array([.0, .5, 1.]))[:-1])
glVertex2fv(( **T** @ np.array([.0, .0, 1.]))[:-1])
glVertex2fv(( **T** @ np.array([.5, .0, 1.]))[:-1])

T is the part that I need to modify. Do I just need to assign T value as matrix (just like the one I used as an example above), or is there any certain format that I need to follow?

Also, I want it to be transformed if I press a certain key, for example:

global T
def key_callback(window, key, scancode, action, mods):
global T

if key==glfw.KEY_1:
    if action==glfw.PRESS:
        T = 

Should I assign T value here?


Solution

  • You need a vector with 4 components to transform it by a 4x4 matrix. The vertex coordinate is a Homogeneous coordinates:

    glVertex2fv((T @ np.array([.0, .5, 1., 1]))[:-2])
    glVertex2fv((T @ np.array([.0, .0, 1., 1]))[:-2])
    glVertex2fv((T @ np.array([.5, .0, 1., 1]))[:-2])
    

    Minimal example:

    from OpenGL.GLUT import *
    from OpenGL.GLU import *
    from OpenGL.GL import *
    import numpy as np
    import math
    
    def render(T):
        glClear(GL_COLOR_BUFFER_BIT)
        glLoadIdentity()
        # draw coordinate
        glBegin(GL_LINES)
        glColor3ub(255, 0, 0)
        glVertex2fv(np.array([0., 0.]))
        glVertex2fv(np.array([1., 0.]))
        glColor3ub(0, 255, 0)
        glVertex2fv(np.array([0., 0.]))
        glVertex2fv(np.array([0., 1.]))
        glEnd()
    
        #draw triangle
        glBegin(GL_TRIANGLES)
        glColor3ub(255,255,255)
        glVertex2fv((T @ np.array([.0, .5, 1., 1]))[:-2])
        glVertex2fv((T @ np.array([.0, .0, 1., 1]))[:-2])
        glVertex2fv((T @ np.array([.5, .0, 1., 1]))[:-2])
        glEnd()
    
    def display():
        t = glutGet(GLUT_ELAPSED_TIME) / 1000
        T = np.identity(4)
        T[:3 ,3] = [math.sin(t) * 0.5, 0., .0]
        glClearColor(0.2, 0.2, 0.2, 1)
        glLineWidth(5)
        render(T)
        glutSwapBuffers()
        glutPostRedisplay()
    
    glutInit(sys.argv)
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA)
    glutInitWindowSize(200, 200)
    glutCreateWindow(b"OpenGL Window")
    glutDisplayFunc(display)
    glutMainLoop()