a b/app/resources/b3d/math3d.py
1
import math
2
3
4
# Converts angle from degree to radian  
5
def to_radian(angle):
6
    return angle / 180.0 * math.pi
7
8
9
# Constructs a quaternion from a rotation of degree 'angle' around vector 'axis'
10
def quaternion(axis, angle):
11
    angle *= 0.5
12
    sinAngle = math.sin(to_radian(angle))
13
    return normalize((axis[0] * sinAngle, axis[1] * sinAngle, axis[2] * sinAngle, math.cos(to_radian(angle))))
14
15
16
# Normalizes quaternion 'q'
17
def normalize(q):
18
    length = math.sqrt(q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3])
19
    return (q[0] / length, q[1] / length, q[2] / length, q[3] / length)
20
21
22
# Multiplies 2 quaternions : 'q1' * 'q2'    
23
def multiply_quat(q1, q2):
24
    return (q1[3] * q2[0] + q1[0] * q2[3] + q1[1] * q2[2] - q1[2] * q2[1],
25
            q1[3] * q2[1] + q1[1] * q2[3] + q1[2] * q2[0] - q1[0] * q2[2],
26
            q1[3] * q2[2] + q1[2] * q2[3] + q1[0] * q2[1] - q1[1] * q2[0],
27
            q1[3] * q2[3] - q1[0] * q2[0] - q1[1] * q2[1] - q1[2] * q2[2])
28
29
30
# Converts quaternion 'q' to a rotation matrix
31
def matrix_from_quat(q):
32
    x2 = q[0] * q[0]
33
    y2 = q[1] * q[1]
34
    z2 = q[2] * q[2]
35
    xy = q[0] * q[1]
36
    xz = q[0] * q[2]
37
    yz = q[1] * q[2]
38
    wx = q[3] * q[0]
39
    wy = q[3] * q[1]
40
    wz = q[3] * q[2]
41
    return (1.0 - 2.0 * (y2 + z2), 2.0 * (xy - wz), 2.0 * (xz + wy), 0.0,
42
            2.0 * (xy + wz), 1.0 - 2.0 * (x2 + z2), 2.0 * (yz - wx), 0.0,
43
            2.0 * (xz - wy), 2.0 * (yz + wx), 1.0 - 2.0 * (x2 + y2), 0.0,
44
            0.0, 0.0, 0.0, 1.0)
45
46
47
# Constructs a translation matrix
48
def matrix_from_trans(trans):
49
    return (1, 0, 0, trans[0],
50
            0, 1, 0, trans[1],
51
            0, 0, 1, trans[2],
52
            0, 0, 0, 1)
53
54
55
# Returns an identity matrix
56
def identity_matrix():
57
    return (1, 0, 0, 0,
58
            0, 1, 0, 0,
59
            0, 0, 1, 0,
60
            0, 0, 0, 1)
61
62
63
# Multiplies 2 Mat4 : 'm1' * 'm2'           
64
def multiply_matrix(m1, m2):
65
    res = []
66
    for i in range(0, 4):
67
        for j in range(0, 4):
68
            res.append(m1[i * 4] * m2[j] + m1[i * 4 + 1] * m2[j + 4] + m1[i * 4 + 2] * m2[j + 8] + m1[i * 4 + 3] * m2[j + 12])
69
    return res
70
71
72
# Multiplies matrix 'm' by vector 'v'
73
def multiply_mat_by_vec(m, v):
74
    w = 1.0
75
    if len(v) == 4:
76
        w = v[3]
77
    return (m[0] * v[0] + m[1] * v[1] + m[2] * v[2] + m[3] * w,
78
            m[4] * v[0] + m[5] * v[1] + m[6] * v[2] + m[7] * w,
79
            m[8] * v[0] + m[9] * v[1] + m[10] * v[2] + m[11] * w,
80
            m[12] * v[0] + m[13] * v[1] + m[14] * v[2] + m[15] * w)
81
82
83
# Transposes matrix 'm'
84
def transpose(m):
85
    return (m[0], m[4], m[8], m[12],
86
            m[1], m[5], m[9], m[13],
87
            m[2], m[6], m[10], m[14],
88
            m[3], m[7], m[11], m[15])
89
90
91
# Calculates inverse of matrix m
92
# Reimplement of gluInvertMatrix
93
def invert_matrix(m):
94
    inv = []
95
    inv.append(m[5] * m[10] * m[15] - m[5] * m[11] * m[14] - m[9] * m[6] * m[15] + m[9] * m[7] * m[14] + m[13] * m[6] * m[11] - m[13] * m[7] * m[10])
96
    inv.append(-m[1] * m[10] * m[15] + m[1] * m[11] * m[14] + m[9] * m[2] * m[15] - m[9] * m[3] * m[14] - m[13] * m[2] * m[11] + m[13] * m[3] * m[10])
97
    inv.append(m[1] * m[6] * m[15] - m[1] * m[7] * m[14] - m[5] * m[2] * m[15] + m[5] * m[3] * m[14] + m[13] * m[2] * m[7] - m[13] * m[3] * m[6])
98
    inv.append(-m[1] * m[6] * m[11] + m[1] * m[7] * m[10] + m[5] * m[2] * m[11] - m[5] * m[3] * m[10] - m[9] * m[2] * m[7] + m[9] * m[3] * m[6])
99
    inv.append(-m[4] * m[10] * m[15] + m[4] * m[11] * m[14] + m[8] * m[6] * m[15] - m[8] * m[7] * m[14] - m[12] * m[6] * m[11] + m[12] * m[7] * m[10])
100
    inv.append(m[0] * m[10] * m[15] - m[0] * m[11] * m[14] - m[8] * m[2] * m[15] + m[8] * m[3] * m[14] + m[12] * m[2] * m[11] - m[12] * m[3] * m[10])
101
    inv.append(-m[0] * m[6] * m[15] + m[0] * m[7] * m[14] + m[4] * m[2] * m[15] - m[4] * m[3] * m[14] - m[12] * m[2] * m[7] + m[12] * m[3] * m[6])
102
    inv.append(m[0] * m[6] * m[11] - m[0] * m[7] * m[10] - m[4] * m[2] * m[11] + m[4] * m[3] * m[10] + m[8] * m[2] * m[7] - m[8] * m[3] * m[6])
103
    inv.append(m[4] * m[9] * m[15] - m[4] * m[11] * m[13] - m[8] * m[5] * m[15] + m[8] * m[7] * m[13] + m[12] * m[5] * m[11] - m[12] * m[7] * m[9])
104
    inv.append(-m[0] * m[9] * m[15] + m[0] * m[11] * m[13] + m[8] * m[1] * m[15] - m[8] * m[3] * m[13] - m[12] * m[1] * m[11] + m[12] * m[3] * m[9])
105
    inv.append(m[0] * m[5] * m[15] - m[0] * m[7] * m[13] - m[4] * m[1] * m[15] + m[4] * m[3] * m[13] + m[12] * m[1] * m[7] - m[12] * m[3] * m[5])
106
    inv.append(-m[0] * m[5] * m[11] + m[0] * m[7] * m[9] + m[4] * m[1] * m[11] - m[4] * m[3] * m[9] - m[8] * m[1] * m[7] + m[8] * m[3] * m[5])
107
    inv.append(-m[4] * m[9] * m[14] + m[4] * m[10] * m[13] + m[8] * m[5] * m[14] - m[8] * m[6] * m[13] - m[12] * m[5] * m[10] + m[12] * m[6] * m[9])
108
    inv.append(m[0] * m[9] * m[14] - m[0] * m[10] * m[13] - m[8] * m[1] * m[14] + m[8] * m[2] * m[13] + m[12] * m[1] * m[10] - m[12] * m[2] * m[9])
109
    inv.append(-m[0] * m[5] * m[14] + m[0] * m[6] * m[13] + m[4] * m[1] * m[14] - m[4] * m[2] * m[13] - m[12] * m[1] * m[6] + m[12] * m[2] * m[5])
110
    inv.append(m[0] * m[5] * m[10] - m[0] * m[6] * m[9] - m[4] * m[1] * m[10] + m[4] * m[2] * m[9] + m[8] * m[1] * m[6] - m[8] * m[2] * m[5])
111
    
112
    det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12]
113
    if det == 0:
114
        return None
115
    
116
    det = 1.0 / det
117
    mOut = []
118
    for i in range(16):
119
        mOut.append(inv[i] * det)
120
    return mOut
121
122
123
# Calculates length^2 of vector 'v' 
124
def length2(v):
125
    return v[0] * v[0] + v[1] * v[1] + v[2] * v[2]
126
127
    
128
# Calculates vector dot product : 'v1' * 'v2'   
129
def dot(v1, v2):
130
    return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]
131
132
    
133
# Calculates vector cross product : 'v1' x 'v2'
134
def cross(v1, v2):
135
    return (v1[1] * v2[2] - v1[2] * v2[1], v1[2] * v2[0] - v1[0] * v2[2], v1[0] * v2[1] - v1[1] * v2[0])
136
137
    
138
# Normalizes vector 'v'
139
def normalize_vec(v):
140
    l2 = length2(v)
141
    if l2 == 0:
142
        return (0, 0, 0)
143
    l = math.sqrt(l2)
144
    return (v[0] / l, v[1] / l, v[2] / l)