File size: 2,809 Bytes
41d2103
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import numpy as np


def vec3(x, y, z):
    return np.array([x, y, z], dtype=np.float32)


def radians(v):
    return np.radians(v)


def identity():
    return np.identity(4, dtype=np.float32)


def empty():
    return np.zeros([4, 4], dtype=np.float32)


def magnitude(v):
    return np.linalg.norm(v)


def normalize(v):
    m = magnitude(v)
    return v if m == 0 else v / m


def dot(u, v):
    return np.sum(u * v)


def cross(u, v):
    res = vec3(0, 0, 0)
    res[0] = u[1] * v[2] - u[2] * v[1]
    res[1] = u[2] * v[0] - u[0] * v[2]
    res[2] = u[0] * v[1] - u[1] * v[0]
    return res


# below functions can be optimized

def translate(m, v):
    res = np.copy(m)
    res[:, 3] = m[:, 0] * v[0] + m[:, 1] * v[1] + m[:, 2] * v[2] + m[:, 3]
    return res


def rotate(m, angle, v):
    a = angle
    c = np.cos(a)
    s = np.sin(a)

    axis = normalize(v)
    temp = (1 - c) * axis

    rot = empty()
    rot[0][0] = c + temp[0] * axis[0]
    rot[0][1] = temp[0] * axis[1] + s * axis[2]
    rot[0][2] = temp[0] * axis[2] - s * axis[1]

    rot[1][0] = temp[1] * axis[0] - s * axis[2]
    rot[1][1] = c + temp[1] * axis[1]
    rot[1][2] = temp[1] * axis[2] + s * axis[0]

    rot[2][0] = temp[2] * axis[0] + s * axis[1]
    rot[2][1] = temp[2] * axis[1] - s * axis[0]
    rot[2][2] = c + temp[2] * axis[2]

    res = empty()
    res[:, 0] = m[:, 0] * rot[0][0] + m[:, 1] * rot[0][1] + m[:, 2] * rot[0][2]
    res[:, 1] = m[:, 0] * rot[1][0] + m[:, 1] * rot[1][1] + m[:, 2] * rot[1][2]
    res[:, 2] = m[:, 0] * rot[2][0] + m[:, 1] * rot[2][1] + m[:, 2] * rot[2][2]
    res[:, 3] = m[:, 3]
    return res


def perspective(fovy, aspect, zNear, zFar):
    tanHalfFovy = np.tan(fovy / 2)

    res = empty()
    res[0][0] = 1 / (aspect * tanHalfFovy)
    res[1][1] = 1 / (tanHalfFovy)
    res[2][3] = -1
    res[2][2] = - (zFar + zNear) / (zFar - zNear)
    res[3][2] = -(2 * zFar * zNear) / (zFar - zNear)

    return res.T


def ortho(left, right, bottom, top, zNear, zFar):
    # res = np.ones([4, 4], dtype=np.float32)
    res = identity()
    res[0][0] = 2 / (right - left)
    res[1][1] = 2 / (top - bottom)
    res[2][2] = - 2 / (zFar - zNear)
    res[3][0] = - (right + left) / (right - left)
    res[3][1] = - (top + bottom) / (top - bottom)
    res[3][2] = - (zFar + zNear) / (zFar - zNear)
    return res.T


def lookat(eye, center, up):
    f = normalize(center - eye)
    s = normalize(cross(f, up))
    u = cross(s, f)

    res = identity()
    res[0][0] = s[0]
    res[1][0] = s[1]
    res[2][0] = s[2]
    res[0][1] = u[0]
    res[1][1] = u[1]
    res[2][1] = u[2]
    res[0][2] = -f[0]
    res[1][2] = -f[1]
    res[2][2] = -f[2]
    res[3][0] = -dot(s, eye)
    res[3][1] = -dot(u, eye)
    res[3][2] = -dot(f, eye)
    return res.T


def transform(d, m):
    return np.dot(m, d.T).T