# ==========================================================
# A quick and dirty calculation for Task 1 (cg1-makeup-exam)
# 
# Written by
# Changkun Ou <changkun.ou at ifi.lmu.de>
# Dec 29, 2020
# ==========================================================

import numpy as np
import math
np.set_printoptions(precision=4,suppress=True)

sq2 = math.sqrt(2)

a1 = np.array([
    [1,  0, 0, 0], 
    [0, -1, 0, 0], 
    [0,  0, 1, 0], 
    [0,  0, 0, 1]
])
a2 = np.array([
    [ sq2/2, 0, sq2/2, 0], 
    [     0, 1,     0, 0], 
    [-sq2/2, 0, sq2/2, 0], 
    [     0, 0,     0, 1],
])
a3 = np.array([
    [sq2/2,  0,      0, 0], 
    [    0, -1,      0, 0], 
    [    0,  0, -sq2/2, 0], 
    [    0,  0,      0, 1]
])
a4 = np.array([
    [1, 0, 0, 1], 
    [0, 1, 0, 1], 
    [0, 0, 1, 1], 
    [0, 0, 0, 1],
])

print('Version A:')

A = np.array([
    [3],
    [0],
    [0],
    [1],
])
B = np.array([
    [5],
    [-1],
    [3],
    [1],
])
C = np.array([
    [2],
    [2],
    [1],
    [1],
])

print(f'a1) {a1@A}, {a1@B}, {a1@C}')
print(f'a2) {a2@a1@A}, {a2@a1@B}, {a2@a1@C}')
print(f'a3) {a3@a2@a1@A}, {a3@a2@a1@B}, {a3@a2@a1@C}')
print(f'a4) {a4@a3@a2@a1@A}, {a4@a3@a2@a1@B}, {a4@a3@a2@a1@C}')

Tmodel = a4@a3@a2@a1
print(f'b) {Tmodel}')

Rview = np.array([
 [0, 0, 1, 0],
 [0, 1, 0, 0],
 [-1, 0, 0, 0],
 [0, 0, 0, 1],
])
Tview = np.array([
 [1, 0, 0, -1],
 [0, 1, 0, -1],
 [0, 0, 1, -1],
 [0, 0, 0, 1],
])
Tcamera = Rview  @ Tview
print(f'c) {Tcamera}')

Tmodelview = Tcamera @ Tmodel
print(f'd) {Tmodelview @ A}, {Tmodelview @ B}, {Tmodelview @ C}')

l = -10
r = 10
b = -5
t = 5
n = -5
f = -10
Tortho = np.array([
    [2/(r-l), 0, 0, (l+r)/(l-r)],
    [0, 2/(t-b), 0, (b+t)/(b-t)],
    [0, 0, 2/(n-f), (f+n)/(f-n)],
    [0, 0, 0, 1],
])
Tmvp = Tortho @ Tmodelview
print(f'e) {Tmvp}')

n=-5
f=-10
fov=45
aspect=2
Tpersp = np.array([
    [-1/(aspect*math.tan(fov*math.pi/360)), 0, 0, 0],
    [0, -1/(math.tan(fov*math.pi/360)), 0, 0],
    [0, 0, (n+f)/(n-f), (2*n*f)/(f-n)],
    [0, 0, 1, 0],
])
Tmvp = Tpersp @ Tmodelview
print(f'f) {Tmvp}')

w = 1920
h = 1080
Tviewport = np.array([
    [w/2, 0, 0, w/2],
    [0, h/2, 0, h/2],
    [0, 0, 1, 0],
    [0, 0, 0, 1],
])

Tfinal = Tviewport @ Tmvp

AA = Tfinal@A
BB = Tfinal@B
CC = Tfinal@C
print(f'g) {AA/AA[3]}, {BB/BB[3]}, {CC/CC[3]}')


# =============================================


print('Version B:')

A = np.array([
    [5],
    [0],
    [0],
    [1],
])
B = np.array([
    [4],
    [-2],
    [5],
    [1],
])
C = np.array([
    [2],
    [3],
    [3],
    [1],
])

print(f'a1) {a1@A}, {a1@B}, {a1@C}')
print(f'a2) {a2@a1@A}, {a2@a1@B}, {a2@a1@C}')
print(f'a3) {a3@a2@a1@A}, {a3@a2@a1@B}, {a3@a2@a1@C}')
print(f'a4) {a4@a3@a2@a1@A}, {a4@a3@a2@a1@B}, {a4@a3@a2@a1@C}')

Tmodel = a4@a3@a2@a1
print(f'b) {Tmodel}')

Rview = np.array([
 [0, 0, 1, 0],
 [-1, 0, 0, 0],
 [0, -1, 0, 0],
 [0, 0, 0, 1],
])
Tview = np.array([
 [1, 0, 0, -1],
 [0, 1, 0, 1],
 [0, 0, 1, -1],
 [0, 0, 0, 1],
])
Tcamera = Rview  @ Tview
print(f'c) {Tcamera}')

Tmodelview = Tcamera @ Tmodel
print(f'd) {Tmodelview @ A}, {Tmodelview @ B}, {Tmodelview @ C}')

l = -10
r = 10
b = -5
t = 5
n = -5
f = -10
Tortho = np.array([
    [2/(r-l), 0, 0, (l+r)/(l-r)],
    [0, 2/(t-b), 0, (b+t)/(b-t)],
    [0, 0, 2/(n-f), (f+n)/(f-n)],
    [0, 0, 0, 1],
])
Tmvp = Tortho @ Tmodelview
print(f'e) {Tmvp}')

n=-5
f=-10
fov=45
aspect=2
Tpersp = np.array([
    [-1/(aspect*math.tan(fov*math.pi/360)), 0, 0, 0],
    [0, -1/(math.tan(fov*math.pi/360)), 0, 0],
    [0, 0, (n+f)/(n-f), (2*n*f)/(f-n)],
    [0, 0, 1, 0],
])
Tmvp = Tpersp @ Tmodelview
print(f'f) {Tmvp}')

w = 1920
h = 1080
Tviewport = np.array([
    [w/2, 0, 0, w/2],
    [0, h/2, 0, h/2],
    [0, 0, 1, 0],
    [0, 0, 0, 1],
])

Tfinal = Tviewport @ Tmvp

AA = Tfinal@A
BB = Tfinal@B
CC = Tfinal@C
print(f'g) {AA/AA[3]}, {BB/BB[3]}, {CC/CC[3]}')