###################################################
# [Review] 3D Transformations
import glfw
from OpenGL.GL import *
from OpenGL.GLU import *
import numpy as np

def render(M, camAng):
    # enable depth test (we'll see details later)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glEnable(GL_DEPTH_TEST)

    glLoadIdentity()

    # use orthogonal projection (we'll see details later)
    glOrtho(-1,1, -1,1, -1,1)

    # rotate "camera" position to see this 3D space better (we'll see details later)
    gluLookAt(.1*np.sin(camAng),.1, .1*np.cos(camAng), 0,0,0, 0,1,0)

     # draw coordinate: x in red, y in green, z in blue
    glBegin(GL_LINES)
    glColor3ub(255, 0, 0)
    glVertex3fv(np.array([0.,0.,0.]))
    glVertex3fv(np.array([1.,0.,0.]))
    glColor3ub(0, 255, 0)
    glVertex3fv(np.array([0.,0.,0.]))
    glVertex3fv(np.array([0.,1.,0.]))
    glColor3ub(0, 0, 255)
    glVertex3fv(np.array([0.,0.,0]))
    glVertex3fv(np.array([0.,0.,1.]))
    glEnd()

    # draw triangle
    glBegin(GL_TRIANGLES)
    glColor3ub(255, 255, 255)
    glVertex3fv((M @ np.array([.0,.5,0.,1.]))[:-1])
    glVertex3fv((M @ np.array([.0,.0,0.,1.]))[:-1])
    glVertex3fv((M @ np.array([.5,.0,0.,1.]))[:-1])
    glEnd()

def main():
    if not glfw.init():
        return
    window = glfw.create_window(640,640,"3D Trans", None,None)
    if not window:
        glfw.terminate()
        return
    glfw.make_context_current(window)
    glfw.swap_interval(1)
    count = 0
    while not glfw.window_should_close(window):
        glfw.poll_events()

        # rotate 60 deg about x axis
        th = np.radians(-60)
        R = np.identity(4)
        R[:3,:3] = [[1.,0.,0.],
             [0., np.cos(th), -np.sin(th)],
             [0., np.sin(th), np.cos(th)]]

        # translate by (.4, 0., .2)
        T = np.identity(4)
        T[:3,3] = [.4, 0., .2]

        camAng = np.radians(count% 360)
        #render(R, camAng)
        #render(T, camAng)
        render(T @ R, camAng)
        # render(R @ T, camAng)
        count += 1

        glfw.swap_buffers(window)

    glfw.terminate()

if __name__ == "__main__":
    main()

###################################################
# [Practice] OpenGL Trans. Functions
# import glfw
# from OpenGL.GL import *
# from OpenGL.GLU import *
# import numpy as np

# gCamAng = 0.

# def drawTriangleTransformedBy(M):
#     glBegin(GL_TRIANGLES)
#     glVertex3fv((M @ np.array([.0,.5,0.,1.]))[:-1])
#     glVertex3fv((M @ np.array([.0,.0,0.,1.]))[:-1])
#     glVertex3fv((M @ np.array([.5,.0,0.,1.]))[:-1])
#     glEnd()

# def drawTriangle():
#     glBegin(GL_TRIANGLES)
#     glVertex3fv(np.array([.0,.5,0.]))
#     glVertex3fv(np.array([.0,.0,0.]))
#     glVertex3fv(np.array([.5,.0,0.]))
#     glEnd()

# def render(camAng):
#     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
#     glEnable(GL_DEPTH_TEST)

#     # set the current matrix to the identity matrix
#     glLoadIdentity()

#     # use orthogonal projection (multiply the current matrix by "projection" matrix - we'll see details later)
#     glOrtho(-1,1, -1,1, -1,1)

#     # rotate "camera" position (multiply the current matrix by "camera" matrix - we'll see details later)
#     gluLookAt(.1*np.sin(camAng),.1,.1*np.cos(camAng), 0,0,0, 0,1,0)

#     # draw coordinates 
#     glBegin(GL_LINES)
#     glColor3ub(255, 0, 0)
#     glVertex3fv(np.array([0.,0.,0.]))
#     glVertex3fv(np.array([1.,0.,0.]))
#     glColor3ub(0, 255, 0)
#     glVertex3fv(np.array([0.,0.,0.]))
#     glVertex3fv(np.array([0.,1.,0.]))
#     glColor3ub(0, 0, 255)
#     glVertex3fv(np.array([0.,0.,0]))
#     glVertex3fv(np.array([0.,0.,1.]))
#     glEnd()

#     ##############################
#     # edit here

	
# def key_callback(window, key, scancode, action, mods):
#     global gCamAng
#     # rotate the camera when 1 or 3 key is pressed or repeated
#     if action==glfw.PRESS or action==glfw.REPEAT:
#         if key==glfw.KEY_1:
#             gCamAng += np.radians(-10)
#         elif key==glfw.KEY_3:
#             gCamAng += np.radians(10)

# def main():
#     if not glfw.init():
#         return
#     window = glfw.create_window(640,640,'Lecture8', None,None)
#     if not window:
#         glfw.terminate()
#         return
#     glfw.make_context_current(window)
#     glfw.set_key_callback(window, key_callback)

#     while not glfw.window_should_close(window):
#         glfw.poll_events()
#         render(gCamAng)
#         glfw.swap_buffers(window)

#     glfw.terminate()

# if __name__ == "__main__":
#     main()
