ncca-ngl 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ncca/ngl/PrimData/pack_arrays.py +20 -0
- ncca/ngl/__init__.py +100 -0
- ncca/ngl/abstract_vao.py +89 -0
- ncca/ngl/base_mesh.py +170 -0
- ncca/ngl/base_mesh.pyi +11 -0
- ncca/ngl/bbox.py +224 -0
- ncca/ngl/bezier_curve.py +75 -0
- ncca/ngl/first_person_camera.py +174 -0
- ncca/ngl/image.py +94 -0
- ncca/ngl/log.py +44 -0
- ncca/ngl/mat2.py +128 -0
- ncca/ngl/mat3.py +466 -0
- ncca/ngl/mat4.py +456 -0
- ncca/ngl/multi_buffer_vao.py +49 -0
- ncca/ngl/obj.py +416 -0
- ncca/ngl/plane.py +47 -0
- ncca/ngl/primitives.py +706 -0
- ncca/ngl/pyside_event_handling_mixin.py +318 -0
- ncca/ngl/quaternion.py +112 -0
- ncca/ngl/random.py +167 -0
- ncca/ngl/shader.py +229 -0
- ncca/ngl/shader_lib.py +536 -0
- ncca/ngl/shader_program.py +816 -0
- ncca/ngl/simple_index_vao.py +65 -0
- ncca/ngl/simple_vao.py +42 -0
- ncca/ngl/text.py +346 -0
- ncca/ngl/texture.py +75 -0
- ncca/ngl/transform.py +95 -0
- ncca/ngl/util.py +128 -0
- ncca/ngl/vao_factory.py +34 -0
- ncca/ngl/vec2.py +350 -0
- ncca/ngl/vec2_array.py +106 -0
- ncca/ngl/vec3.py +401 -0
- ncca/ngl/vec3_array.py +110 -0
- ncca/ngl/vec4.py +229 -0
- ncca/ngl/vec4_array.py +106 -0
- ncca_ngl-0.1.0.dist-info/METADATA +23 -0
- ncca_ngl-0.1.0.dist-info/RECORD +41 -0
- ncca_ngl-0.1.0.dist-info/WHEEL +5 -0
- ncca_ngl-0.1.0.dist-info/licenses/LICENSE.txt +7 -0
- ncca_ngl-0.1.0.dist-info/top_level.txt +1 -0
ncca/ngl/mat4.py
ADDED
|
@@ -0,0 +1,456 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Simple Mat4 class which can be used with the Vec4 class
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import copy
|
|
6
|
+
import functools
|
|
7
|
+
import math
|
|
8
|
+
import operator
|
|
9
|
+
|
|
10
|
+
import numpy as np
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Mat4Error(Exception):
|
|
14
|
+
"""An exception class for Mat3"""
|
|
15
|
+
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class Mat4NotSquare(Exception):
|
|
20
|
+
"""Make sure we have 3x3"""
|
|
21
|
+
|
|
22
|
+
pass
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
_identity = [
|
|
26
|
+
[1.0, 0.0, 0.0, 0.0],
|
|
27
|
+
[0.0, 1.0, 0.0, 0.0],
|
|
28
|
+
[0.0, 0.0, 1.0, 0.0],
|
|
29
|
+
[0.0, 0.0, 0.0, 1.0],
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class Mat4:
|
|
34
|
+
__slots__ = ["m"]
|
|
35
|
+
|
|
36
|
+
def __init__(self):
|
|
37
|
+
"construct to identity matrix"
|
|
38
|
+
self.m = copy.deepcopy(_identity)
|
|
39
|
+
|
|
40
|
+
def get_matrix(self):
|
|
41
|
+
"return matrix elements as list ideal for OpenGL etc"
|
|
42
|
+
return functools.reduce(operator.concat, self.m)
|
|
43
|
+
|
|
44
|
+
def to_numpy(self):
|
|
45
|
+
"return matrix as a numpy array ideal for WebGPU etc"
|
|
46
|
+
return np.array(self.get_matrix(), dtype=np.float32).reshape([4, 4])
|
|
47
|
+
|
|
48
|
+
@classmethod
|
|
49
|
+
def identity(cls):
|
|
50
|
+
"class method to return a new identity matrix"
|
|
51
|
+
v = Mat4()
|
|
52
|
+
return v
|
|
53
|
+
|
|
54
|
+
@classmethod
|
|
55
|
+
def zero(cls):
|
|
56
|
+
"class method to return a zero matrix"
|
|
57
|
+
v = Mat4()
|
|
58
|
+
v.m = [
|
|
59
|
+
[0.0, 0.0, 0.0, 0.0],
|
|
60
|
+
[0.0, 0.0, 0.0, 0.0],
|
|
61
|
+
[0.0, 0.0, 0.0, 0.0],
|
|
62
|
+
[0.0, 0.0, 0.0, 0.0],
|
|
63
|
+
]
|
|
64
|
+
return v
|
|
65
|
+
|
|
66
|
+
@classmethod
|
|
67
|
+
def from_list(cls, lst):
|
|
68
|
+
"class method to create mat4 from list"
|
|
69
|
+
v = Mat4()
|
|
70
|
+
v.m = lst
|
|
71
|
+
if not v._is_square():
|
|
72
|
+
if len(lst) == 16: # can convert
|
|
73
|
+
v.m = [lst[0:4], lst[4:8], lst[8:12], lst[12:16]]
|
|
74
|
+
return v
|
|
75
|
+
else:
|
|
76
|
+
raise Mat4NotSquare
|
|
77
|
+
else:
|
|
78
|
+
return v
|
|
79
|
+
|
|
80
|
+
def _is_square(self) -> bool:
|
|
81
|
+
"ensure matrix is square"
|
|
82
|
+
return len(self.m) == 4 and all(len(i) == 4 for i in self.m)
|
|
83
|
+
|
|
84
|
+
def to_list(self):
|
|
85
|
+
"convert matrix to list"
|
|
86
|
+
# flatten to single array
|
|
87
|
+
return functools.reduce(operator.concat, self.m)
|
|
88
|
+
|
|
89
|
+
def transpose(self):
|
|
90
|
+
"transpose this matrix"
|
|
91
|
+
self.m = [list(item) for item in zip(*self.m)]
|
|
92
|
+
|
|
93
|
+
def get_transpose(self):
|
|
94
|
+
"return a new matrix as the transpose of ourself"
|
|
95
|
+
m = Mat4()
|
|
96
|
+
m.m = [list(item) for item in zip(*self.m)]
|
|
97
|
+
return m
|
|
98
|
+
|
|
99
|
+
@classmethod
|
|
100
|
+
def scale(cls, x: float, y: float, z: float):
|
|
101
|
+
"return a new matrix as scale"
|
|
102
|
+
a = Mat4() # identity by default
|
|
103
|
+
a.m[0][0] = x
|
|
104
|
+
a.m[1][1] = y
|
|
105
|
+
a.m[2][2] = z
|
|
106
|
+
return a
|
|
107
|
+
|
|
108
|
+
@classmethod
|
|
109
|
+
def translate(cls, x: float, y: float, z: float):
|
|
110
|
+
"return a new matrix as translation"
|
|
111
|
+
a = Mat4() # identity by default
|
|
112
|
+
a.m[3][0] = x
|
|
113
|
+
a.m[3][1] = y
|
|
114
|
+
a.m[3][2] = z
|
|
115
|
+
return a
|
|
116
|
+
|
|
117
|
+
@classmethod
|
|
118
|
+
def rotate_x(cls, angle):
|
|
119
|
+
"return a rotation around the X axis by angle degrees"
|
|
120
|
+
a = Mat4()
|
|
121
|
+
beta = math.radians(angle)
|
|
122
|
+
sr = math.sin(beta)
|
|
123
|
+
cr = math.cos(beta)
|
|
124
|
+
a.m[1][1] = cr
|
|
125
|
+
a.m[1][2] = sr
|
|
126
|
+
a.m[2][1] = -sr
|
|
127
|
+
a.m[2][2] = cr
|
|
128
|
+
return a
|
|
129
|
+
|
|
130
|
+
@classmethod
|
|
131
|
+
def rotate_y(cls, angle):
|
|
132
|
+
"return a rotation around the Y axis by angle degrees"
|
|
133
|
+
a = Mat4()
|
|
134
|
+
beta = math.radians(angle)
|
|
135
|
+
sr = math.sin(beta)
|
|
136
|
+
cr = math.cos(beta)
|
|
137
|
+
a.m[0][0] = cr
|
|
138
|
+
a.m[0][2] = -sr
|
|
139
|
+
a.m[2][0] = sr
|
|
140
|
+
a.m[2][2] = cr
|
|
141
|
+
return a
|
|
142
|
+
|
|
143
|
+
@classmethod
|
|
144
|
+
def rotate_z(cls, angle):
|
|
145
|
+
"return a rotation around the Z axis by angle degrees"
|
|
146
|
+
a = Mat4()
|
|
147
|
+
beta = math.radians(angle)
|
|
148
|
+
sr = math.sin(beta)
|
|
149
|
+
cr = math.cos(beta)
|
|
150
|
+
a.m[0][0] = cr
|
|
151
|
+
a.m[0][1] = sr
|
|
152
|
+
a.m[1][0] = -sr
|
|
153
|
+
a.m[1][1] = cr
|
|
154
|
+
return a
|
|
155
|
+
|
|
156
|
+
def __getitem__(self, idx):
|
|
157
|
+
"access array elements remember this is a list of lists [[4],[4],[4],[4]]"
|
|
158
|
+
return self.m[idx]
|
|
159
|
+
|
|
160
|
+
def __setitem__(self, idx, item):
|
|
161
|
+
"set items remember this is a list of lists [[4],[4],[4],[4]]"
|
|
162
|
+
self.m[idx] = item
|
|
163
|
+
|
|
164
|
+
def __mul__(self, rhs):
|
|
165
|
+
"""Multiply matrix by scalar
|
|
166
|
+
|
|
167
|
+
Parameters
|
|
168
|
+
__________
|
|
169
|
+
rhs : float int
|
|
170
|
+
multiply each matrix element by rhs
|
|
171
|
+
|
|
172
|
+
raises : Mat3Error
|
|
173
|
+
if rhs is not a number
|
|
174
|
+
"""
|
|
175
|
+
if isinstance(rhs, (int, float)):
|
|
176
|
+
for i in range(0, len(self.m)):
|
|
177
|
+
for j in range(0, len(self.m[i])):
|
|
178
|
+
self.m[i][j] *= rhs
|
|
179
|
+
return self
|
|
180
|
+
raise Mat4Error
|
|
181
|
+
|
|
182
|
+
def _mat_mul(self, rhs):
|
|
183
|
+
"matrix mult internal function"
|
|
184
|
+
# fmt: off
|
|
185
|
+
a00 = self.m[0][0] # cache values for speed? (works in C++ not sure about python)
|
|
186
|
+
a01 = self.m[0][1]
|
|
187
|
+
a02 = self.m[0][2]
|
|
188
|
+
a03 = self.m[0][3]
|
|
189
|
+
a10 = self.m[1][0]
|
|
190
|
+
a11 = self.m[1][1]
|
|
191
|
+
a12 = self.m[1][2]
|
|
192
|
+
a13 = self.m[1][3]
|
|
193
|
+
a20 = self.m[2][0]
|
|
194
|
+
a21 = self.m[2][1]
|
|
195
|
+
a22 = self.m[2][2]
|
|
196
|
+
a23 = self.m[2][3]
|
|
197
|
+
a30 = self.m[3][0]
|
|
198
|
+
a31 = self.m[3][1]
|
|
199
|
+
a32 = self.m[3][2]
|
|
200
|
+
a33 = self.m[3][3]
|
|
201
|
+
b00 = rhs.m[0][0]
|
|
202
|
+
b01 = rhs.m[0][1]
|
|
203
|
+
b02 = rhs.m[0][2]
|
|
204
|
+
b03 = rhs.m[0][3]
|
|
205
|
+
b10 = rhs.m[1][0]
|
|
206
|
+
b11 = rhs.m[1][1]
|
|
207
|
+
b12 = rhs.m[1][2]
|
|
208
|
+
b13 = rhs.m[1][3]
|
|
209
|
+
b20 = rhs.m[2][0]
|
|
210
|
+
b21 = rhs.m[2][1]
|
|
211
|
+
b22 = rhs.m[2][2]
|
|
212
|
+
b23 = rhs.m[2][3]
|
|
213
|
+
b30 = rhs.m[3][0]
|
|
214
|
+
b31 = rhs.m[3][1]
|
|
215
|
+
b32 = rhs.m[3][2]
|
|
216
|
+
b33 = rhs.m[3][3]
|
|
217
|
+
ret=Mat4() # result mat4
|
|
218
|
+
ret.m[0][0] = b00 * a00 + b01 * a10 + b02 * a20 + b03 * a30
|
|
219
|
+
ret.m[0][1] = b00 * a01 + b01 * a11 + b02 * a21 + b03 * a31
|
|
220
|
+
ret.m[0][2] = b00 * a02 + b01 * a12 + b02 * a22 + b03 * a32
|
|
221
|
+
ret.m[0][3] = b00 * a03 + b01 * a13 + b02 * a23 + b03 * a33
|
|
222
|
+
ret.m[1][0] = b10 * a00 + b11 * a10 + b12 * a20 + b13 * a30
|
|
223
|
+
ret.m[1][1] = b10 * a01 + b11 * a11 + b12 * a21 + b13 * a31
|
|
224
|
+
ret.m[1][2] = b10 * a02 + b11 * a12 + b12 * a22 + b13 * a32
|
|
225
|
+
ret.m[1][3] = b10 * a03 + b11 * a13 + b12 * a23 + b13 * a33
|
|
226
|
+
ret.m[2][0] = b20 * a00 + b21 * a10 + b22 * a20 + b23 * a30
|
|
227
|
+
ret.m[2][1] = b20 * a01 + b21 * a11 + b22 * a21 + b23 * a31
|
|
228
|
+
ret.m[2][2] = b20 * a02 + b21 * a12 + b22 * a22 + b23 * a32
|
|
229
|
+
ret.m[2][3] = b20 * a03 + b21 * a13 + b22 * a23 + b23 * a33
|
|
230
|
+
ret.m[3][0] = b30 * a00 + b31 * a10 + b32 * a20 + b33 * a30
|
|
231
|
+
ret.m[3][1] = b30 * a01 + b31 * a11 + b32 * a21 + b33 * a31
|
|
232
|
+
ret.m[3][2] = b30 * a02 + b31 * a12 + b32 * a22 + b33 * a32
|
|
233
|
+
ret.m[3][3] = b30 * a03 + b31 * a13 + b32 * a23 + b33 * a33
|
|
234
|
+
return ret
|
|
235
|
+
# fmt: on
|
|
236
|
+
|
|
237
|
+
def __matmul__(self, rhs):
|
|
238
|
+
from .vec4 import Vec4 # note relative import here
|
|
239
|
+
|
|
240
|
+
"multiply matrix by another matrix"
|
|
241
|
+
if isinstance(rhs, Mat4):
|
|
242
|
+
return self._mat_mul(rhs)
|
|
243
|
+
elif isinstance(rhs, (Vec4, Vec4)):
|
|
244
|
+
# fmt: off
|
|
245
|
+
return Vec4(
|
|
246
|
+
rhs.x * self.m[0][0] + rhs.y * self.m[0][1]+ rhs.z * self.m[0][2]+ rhs.w * self.m[0][3],
|
|
247
|
+
rhs.x * self.m[1][0]+ rhs.y * self.m[1][1]+ rhs.z * self.m[1][2]+ rhs.w * self.m[1][3],
|
|
248
|
+
rhs.x * self.m[2][0]+ rhs.y * self.m[2][1]+ rhs.z * self.m[2][2]+ rhs.w * self.m[2][3],
|
|
249
|
+
rhs.x * self.m[3][0]+ rhs.y * self.m[3][1]+ rhs.z * self.m[3][2]+ rhs.w * self.m[3][3])
|
|
250
|
+
# fmt: on
|
|
251
|
+
else:
|
|
252
|
+
raise Mat4Error
|
|
253
|
+
|
|
254
|
+
def __str__(self):
|
|
255
|
+
return f"[{self.m[0]}\n{self.m[1]}\n{self.m[2]}\n{self.m[3]}]"
|
|
256
|
+
|
|
257
|
+
def _addfunc(self, rhs):
|
|
258
|
+
"internal add function"
|
|
259
|
+
temp = Mat4()
|
|
260
|
+
for i in range(0, len(temp.m)):
|
|
261
|
+
temp.m[i] = [a + b for a, b in zip(self.m[i], rhs.m[i])]
|
|
262
|
+
return temp
|
|
263
|
+
|
|
264
|
+
def __add__(self, rhs):
|
|
265
|
+
"piecewise addition of elements"
|
|
266
|
+
return self._addfunc(rhs)
|
|
267
|
+
|
|
268
|
+
def __iadd__(self, rhs):
|
|
269
|
+
"piecewise addition of elements to this"
|
|
270
|
+
return self._addfunc(rhs)
|
|
271
|
+
|
|
272
|
+
def _sub(self, rhs):
|
|
273
|
+
"internal sub function"
|
|
274
|
+
temp = Mat4()
|
|
275
|
+
for i in range(0, len(temp.m)):
|
|
276
|
+
temp.m[i] = [a - b for a, b in zip(self.m[i], rhs.m[i])]
|
|
277
|
+
return temp
|
|
278
|
+
|
|
279
|
+
def __sub__(self, rhs):
|
|
280
|
+
"piecewise subtraction of elements"
|
|
281
|
+
return self._sub(rhs)
|
|
282
|
+
|
|
283
|
+
def __isub__(self, rhs):
|
|
284
|
+
"piecewise subtraction of elements to this"
|
|
285
|
+
return self._sub(rhs)
|
|
286
|
+
|
|
287
|
+
def determinant(self):
|
|
288
|
+
"determinant of matrix"
|
|
289
|
+
# Our matrices are 4.4 only, so we can just write the full formula instead of a complex algorithm.
|
|
290
|
+
return (
|
|
291
|
+
self.m[0][0] * self.m[1][1] * self.m[2][2] * self.m[3][3]
|
|
292
|
+
- self.m[0][0] * self.m[1][1] * self.m[2][3] * self.m[3][2]
|
|
293
|
+
+ self.m[0][0] * self.m[1][2] * self.m[2][3] * self.m[3][1]
|
|
294
|
+
- self.m[0][0] * self.m[1][2] * self.m[2][1] * self.m[3][3]
|
|
295
|
+
+ self.m[0][0] * self.m[1][3] * self.m[2][1] * self.m[3][2]
|
|
296
|
+
- self.m[0][0] * self.m[1][3] * self.m[2][2] * self.m[3][1]
|
|
297
|
+
- self.m[1][0] * self.m[2][1] * self.m[3][2] * self.m[0][3]
|
|
298
|
+
+ self.m[1][0] * self.m[2][1] * self.m[0][2] * self.m[3][3]
|
|
299
|
+
- self.m[1][0] * self.m[3][1] * self.m[0][2] * self.m[2][3]
|
|
300
|
+
+ self.m[1][0] * self.m[3][1] * self.m[2][2] * self.m[0][3]
|
|
301
|
+
- self.m[1][0] * self.m[0][1] * self.m[2][2] * self.m[3][3]
|
|
302
|
+
+ self.m[1][0] * self.m[0][1] * self.m[3][2] * self.m[2][3]
|
|
303
|
+
+ self.m[2][0] * self.m[3][1] * self.m[0][2] * self.m[1][3]
|
|
304
|
+
- self.m[2][0] * self.m[3][1] * self.m[1][2] * self.m[0][3]
|
|
305
|
+
+ self.m[2][0] * self.m[0][1] * self.m[1][2] * self.m[3][3]
|
|
306
|
+
- self.m[2][0] * self.m[0][1] * self.m[3][2] * self.m[1][3]
|
|
307
|
+
+ self.m[2][0] * self.m[1][1] * self.m[3][2] * self.m[0][3]
|
|
308
|
+
- self.m[2][0] * self.m[1][1] * self.m[0][2] * self.m[3][3]
|
|
309
|
+
- self.m[3][0] * self.m[0][1] * self.m[1][2] * self.m[2][3]
|
|
310
|
+
+ self.m[3][0] * self.m[0][1] * self.m[2][2] * self.m[1][3]
|
|
311
|
+
- self.m[3][0] * self.m[1][1] * self.m[2][2] * self.m[0][3]
|
|
312
|
+
+ self.m[3][0] * self.m[1][1] * self.m[0][2] * self.m[2][3]
|
|
313
|
+
- self.m[3][0] * self.m[2][1] * self.m[0][2] * self.m[1][3]
|
|
314
|
+
+ self.m[3][0] * self.m[2][1] * self.m[1][2] * self.m[0][3]
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
def inverse(self):
|
|
318
|
+
"Inverse of matrix raise MatrixError if not calculable"
|
|
319
|
+
try:
|
|
320
|
+
det = self.determinant()
|
|
321
|
+
tmp = Mat4()
|
|
322
|
+
invdet = 1.0 / det
|
|
323
|
+
tmp.m[0][0] = (
|
|
324
|
+
self.m[1][1] * self.m[2][2] * self.m[3][3]
|
|
325
|
+
+ self.m[1][2] * self.m[2][3] * self.m[3][1]
|
|
326
|
+
+ self.m[1][3] * self.m[2][1] * self.m[3][2]
|
|
327
|
+
- self.m[1][1] * self.m[3][2] * self.m[2][3]
|
|
328
|
+
- self.m[1][2] * self.m[2][1] * self.m[3][3]
|
|
329
|
+
- self.m[1][3] * self.m[2][2] * self.m[3][1]
|
|
330
|
+
) * invdet
|
|
331
|
+
tmp.m[0][1] = (
|
|
332
|
+
self.m[0][1] * self.m[2][3] * self.m[3][2]
|
|
333
|
+
+ self.m[0][2] * self.m[2][1] * self.m[3][3]
|
|
334
|
+
+ self.m[0][3] * self.m[2][2] * self.m[3][1]
|
|
335
|
+
- self.m[0][1] * self.m[2][2] * self.m[3][3]
|
|
336
|
+
- self.m[0][2] * self.m[2][3] * self.m[3][1]
|
|
337
|
+
- self.m[0][3] * self.m[2][1] * self.m[3][2]
|
|
338
|
+
) * invdet
|
|
339
|
+
tmp.m[0][2] = (
|
|
340
|
+
self.m[0][1] * self.m[1][2] * self.m[3][3]
|
|
341
|
+
+ self.m[0][2] * self.m[1][3] * self.m[3][1]
|
|
342
|
+
+ self.m[0][3] * self.m[1][1] * self.m[3][2]
|
|
343
|
+
- self.m[0][1] * self.m[1][3] * self.m[3][2]
|
|
344
|
+
- self.m[0][2] * self.m[1][1] * self.m[3][3]
|
|
345
|
+
- self.m[0][3] * self.m[1][2] * self.m[3][1]
|
|
346
|
+
) * invdet
|
|
347
|
+
tmp.m[0][3] = (
|
|
348
|
+
self.m[0][1] * self.m[1][3] * self.m[2][2]
|
|
349
|
+
+ self.m[0][2] * self.m[1][1] * self.m[2][3]
|
|
350
|
+
+ self.m[0][3] * self.m[1][2] * self.m[2][1]
|
|
351
|
+
- self.m[0][1] * self.m[1][2] * self.m[2][3]
|
|
352
|
+
- self.m[0][2] * self.m[1][3] * self.m[2][1]
|
|
353
|
+
- self.m[0][3] * self.m[1][1] * self.m[2][2]
|
|
354
|
+
) * invdet
|
|
355
|
+
tmp.m[1][0] = (
|
|
356
|
+
self.m[1][0] * self.m[2][3] * self.m[3][2]
|
|
357
|
+
+ self.m[1][2] * self.m[2][0] * self.m[3][3]
|
|
358
|
+
+ self.m[1][3] * self.m[2][2] * self.m[3][0]
|
|
359
|
+
- self.m[1][0] * self.m[2][2] * self.m[3][3]
|
|
360
|
+
- self.m[1][2] * self.m[2][3] * self.m[3][0]
|
|
361
|
+
- self.m[1][3] * self.m[2][0] * self.m[3][2]
|
|
362
|
+
) * invdet
|
|
363
|
+
tmp.m[1][1] = (
|
|
364
|
+
self.m[0][0] * self.m[2][2] * self.m[3][3]
|
|
365
|
+
+ self.m[0][2] * self.m[2][3] * self.m[3][0]
|
|
366
|
+
+ self.m[0][3] * self.m[2][0] * self.m[3][2]
|
|
367
|
+
- self.m[0][0] * self.m[2][3] * self.m[3][2]
|
|
368
|
+
- self.m[0][2] * self.m[2][0] * self.m[3][3]
|
|
369
|
+
- self.m[0][3] * self.m[2][2] * self.m[3][0]
|
|
370
|
+
) * invdet
|
|
371
|
+
tmp.m[1][2] = (
|
|
372
|
+
self.m[0][0] * self.m[1][3] * self.m[3][2]
|
|
373
|
+
+ self.m[0][2] * self.m[1][0] * self.m[3][3]
|
|
374
|
+
+ self.m[0][3] * self.m[1][2] * self.m[3][0]
|
|
375
|
+
- self.m[0][0] * self.m[1][2] * self.m[3][3]
|
|
376
|
+
- self.m[0][2] * self.m[1][3] * self.m[3][0]
|
|
377
|
+
- self.m[0][3] * self.m[1][0] * self.m[3][2]
|
|
378
|
+
) * invdet
|
|
379
|
+
tmp.m[1][3] = (
|
|
380
|
+
self.m[0][0] * self.m[1][2] * self.m[2][3]
|
|
381
|
+
+ self.m[0][2] * self.m[1][3] * self.m[2][0]
|
|
382
|
+
+ self.m[0][3] * self.m[1][0] * self.m[2][2]
|
|
383
|
+
- self.m[0][0] * self.m[1][3] * self.m[2][2]
|
|
384
|
+
- self.m[0][2] * self.m[1][0] * self.m[2][3]
|
|
385
|
+
- self.m[0][3] * self.m[1][2] * self.m[2][0]
|
|
386
|
+
) * invdet
|
|
387
|
+
tmp.m[2][0] = (
|
|
388
|
+
self.m[1][0] * self.m[2][1] * self.m[3][3]
|
|
389
|
+
+ self.m[1][1] * self.m[2][3] * self.m[3][0]
|
|
390
|
+
+ self.m[1][3] * self.m[2][0] * self.m[3][1]
|
|
391
|
+
- self.m[1][0] * self.m[2][3] * self.m[3][1]
|
|
392
|
+
- self.m[1][1] * self.m[2][0] * self.m[3][3]
|
|
393
|
+
- self.m[1][3] * self.m[2][1] * self.m[3][0]
|
|
394
|
+
) * invdet
|
|
395
|
+
tmp.m[2][1] = (
|
|
396
|
+
self.m[0][0] * self.m[2][3] * self.m[3][1]
|
|
397
|
+
+ self.m[0][1] * self.m[2][0] * self.m[3][3]
|
|
398
|
+
+ self.m[0][3] * self.m[2][1] * self.m[3][0]
|
|
399
|
+
- self.m[0][0] * self.m[2][1] * self.m[3][3]
|
|
400
|
+
- self.m[0][1] * self.m[2][3] * self.m[3][0]
|
|
401
|
+
- self.m[0][3] * self.m[2][0] * self.m[3][1]
|
|
402
|
+
) * invdet
|
|
403
|
+
tmp.m[2][2] = (
|
|
404
|
+
self.m[0][0] * self.m[1][1] * self.m[3][3]
|
|
405
|
+
+ self.m[0][1] * self.m[1][3] * self.m[3][0]
|
|
406
|
+
+ self.m[0][3] * self.m[1][0] * self.m[3][1]
|
|
407
|
+
- self.m[0][0] * self.m[1][3] * self.m[3][1]
|
|
408
|
+
- self.m[0][1] * self.m[1][0] * self.m[3][3]
|
|
409
|
+
- self.m[0][3] * self.m[1][1] * self.m[3][0]
|
|
410
|
+
) * invdet
|
|
411
|
+
tmp.m[2][3] = (
|
|
412
|
+
self.m[0][0] * self.m[1][3] * self.m[2][1]
|
|
413
|
+
+ self.m[0][1] * self.m[1][0] * self.m[2][3]
|
|
414
|
+
+ self.m[0][3] * self.m[1][1] * self.m[2][0]
|
|
415
|
+
- self.m[0][0] * self.m[1][1] * self.m[2][3]
|
|
416
|
+
- self.m[0][1] * self.m[1][3] * self.m[2][0]
|
|
417
|
+
- self.m[0][3] * self.m[1][0] * self.m[2][1]
|
|
418
|
+
) * invdet
|
|
419
|
+
tmp.m[3][0] = (
|
|
420
|
+
self.m[1][0] * self.m[2][2] * self.m[3][1]
|
|
421
|
+
+ self.m[1][1] * self.m[2][0] * self.m[3][2]
|
|
422
|
+
+ self.m[1][2] * self.m[2][1] * self.m[3][0]
|
|
423
|
+
- self.m[1][0] * self.m[2][1] * self.m[3][2]
|
|
424
|
+
- self.m[1][1] * self.m[2][2] * self.m[3][0]
|
|
425
|
+
- self.m[1][2] * self.m[2][0] * self.m[3][1]
|
|
426
|
+
) * invdet
|
|
427
|
+
tmp.m[3][1] = (
|
|
428
|
+
self.m[0][0] * self.m[2][1] * self.m[3][2]
|
|
429
|
+
+ self.m[0][1] * self.m[2][2] * self.m[3][0]
|
|
430
|
+
+ self.m[0][2] * self.m[2][0] * self.m[3][1]
|
|
431
|
+
- self.m[0][0] * self.m[2][2] * self.m[3][1]
|
|
432
|
+
- self.m[0][1] * self.m[2][0] * self.m[3][2]
|
|
433
|
+
- self.m[0][2] * self.m[2][1] * self.m[3][0]
|
|
434
|
+
) * invdet
|
|
435
|
+
tmp.m[3][2] = (
|
|
436
|
+
self.m[0][0] * self.m[1][2] * self.m[3][1]
|
|
437
|
+
+ self.m[0][1] * self.m[1][0] * self.m[3][2]
|
|
438
|
+
+ self.m[0][2] * self.m[1][1] * self.m[3][0]
|
|
439
|
+
- self.m[0][0] * self.m[1][1] * self.m[3][2]
|
|
440
|
+
- self.m[0][1] * self.m[1][2] * self.m[3][0]
|
|
441
|
+
- self.m[0][2] * self.m[1][0] * self.m[3][1]
|
|
442
|
+
) * invdet
|
|
443
|
+
tmp.m[3][3] = (
|
|
444
|
+
self.m[0][0] * self.m[1][1] * self.m[2][2]
|
|
445
|
+
+ self.m[0][1] * self.m[1][2] * self.m[2][0]
|
|
446
|
+
+ self.m[0][2] * self.m[1][0] * self.m[2][1]
|
|
447
|
+
- self.m[0][0] * self.m[1][2] * self.m[2][1]
|
|
448
|
+
- self.m[0][1] * self.m[1][0] * self.m[2][2]
|
|
449
|
+
- self.m[0][2] * self.m[1][1] * self.m[2][0]
|
|
450
|
+
) * invdet
|
|
451
|
+
return tmp
|
|
452
|
+
except ZeroDivisionError:
|
|
453
|
+
raise Mat4Error
|
|
454
|
+
|
|
455
|
+
def __repr__(self) -> str:
|
|
456
|
+
return f"Mat4({self.m})"
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import OpenGL.GL as gl
|
|
3
|
+
|
|
4
|
+
from .abstract_vao import AbstractVAO, VertexData
|
|
5
|
+
from .log import logger
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class MultiBufferVAO(AbstractVAO):
|
|
9
|
+
def __init__(self, mode=gl.GL_TRIANGLES):
|
|
10
|
+
super().__init__(mode)
|
|
11
|
+
self.vbo_ids = []
|
|
12
|
+
|
|
13
|
+
def draw(self):
|
|
14
|
+
if self.bound and self.allocated:
|
|
15
|
+
gl.glDrawArrays(self.mode, 0, self.indices_count)
|
|
16
|
+
else:
|
|
17
|
+
logger.error("MultiBufferVAO is not bound or not allocated")
|
|
18
|
+
|
|
19
|
+
def set_data(self, data, index=None):
|
|
20
|
+
if not isinstance(data, VertexData):
|
|
21
|
+
logger.error("MultiBufferVAO: Invalid data type")
|
|
22
|
+
raise TypeError("data must be of type VertexData")
|
|
23
|
+
if index is None:
|
|
24
|
+
index = len(self.vbo_ids)
|
|
25
|
+
|
|
26
|
+
if index >= len(self.vbo_ids):
|
|
27
|
+
new_buffers = index - len(self.vbo_ids) + 1
|
|
28
|
+
new_ids = gl.glGenBuffers(new_buffers)
|
|
29
|
+
if isinstance(new_ids, np.ndarray):
|
|
30
|
+
self.vbo_ids.extend(new_ids)
|
|
31
|
+
else:
|
|
32
|
+
self.vbo_ids.append(new_ids)
|
|
33
|
+
|
|
34
|
+
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vbo_ids[index])
|
|
35
|
+
gl.glBufferData(gl.GL_ARRAY_BUFFER, data.data.nbytes, data.data, data.mode)
|
|
36
|
+
self.allocated = True
|
|
37
|
+
if index == 0: # Assume first buffer determines the number of indices
|
|
38
|
+
self.indices_count = data.size
|
|
39
|
+
|
|
40
|
+
def remove_vao(self):
|
|
41
|
+
gl.glDeleteBuffers(len(self.vbo_ids), self.vbo_ids)
|
|
42
|
+
gl.glDeleteVertexArrays(1, [self.id])
|
|
43
|
+
|
|
44
|
+
def get_buffer_id(self, index=0):
|
|
45
|
+
return self.vbo_ids[index]
|
|
46
|
+
|
|
47
|
+
def map_buffer(self, index=0, access_mode=gl.GL_READ_WRITE):
|
|
48
|
+
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vbo_ids[index])
|
|
49
|
+
return gl.glMapBuffer(gl.GL_ARRAY_BUFFER, access_mode)
|