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/mat3.py
ADDED
|
@@ -0,0 +1,466 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Simple Mat3 class which can be used with the Vec3 class. By default it will be set to the identity matrix
|
|
3
|
+
|
|
4
|
+
all matrix values are stored in a 3x3 list in the format
|
|
5
|
+
|
|
6
|
+
.. highlight:: python
|
|
7
|
+
.. code-block:: python
|
|
8
|
+
|
|
9
|
+
m=[[1.0,0.0,0.0],
|
|
10
|
+
[0.0,1.0,0.0],
|
|
11
|
+
[0.0,1.0,0.0]]
|
|
12
|
+
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import copy
|
|
16
|
+
import functools
|
|
17
|
+
import math
|
|
18
|
+
import operator
|
|
19
|
+
|
|
20
|
+
import numpy as np
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class Mat3Error(Exception):
|
|
24
|
+
"""This exception will be raised if we have issues with matrix multiplication or other mathematical operations"""
|
|
25
|
+
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class Mat3NotSquare(Exception):
|
|
30
|
+
"""If we try to construct from a non square (3x3) value or 9 elements this exception will be thrown"""
|
|
31
|
+
|
|
32
|
+
pass
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
_identity = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class Mat3:
|
|
39
|
+
"""Simple Mat3 class for basic affine transforms"""
|
|
40
|
+
|
|
41
|
+
__slots__ = ["m"]
|
|
42
|
+
"""m : list
|
|
43
|
+
the matrix values
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
def __init__(self):
|
|
47
|
+
"""construct to identity matrix"""
|
|
48
|
+
self.m = copy.deepcopy(_identity)
|
|
49
|
+
|
|
50
|
+
def get_matrix(self):
|
|
51
|
+
"""return matrix elements as list ideal for OpenGL
|
|
52
|
+
|
|
53
|
+
Returns
|
|
54
|
+
-------
|
|
55
|
+
list
|
|
56
|
+
the 9 float elements of the matrix, ideal
|
|
57
|
+
for OpenGL or Renderman consumption
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
return functools.reduce(operator.concat, self.m)
|
|
61
|
+
|
|
62
|
+
def to_numpy(self):
|
|
63
|
+
"return matrix as a numpy array ideal for WebGPU etc"
|
|
64
|
+
return np.array(self.get_matrix()).reshape([3, 3])
|
|
65
|
+
|
|
66
|
+
@classmethod
|
|
67
|
+
def identity(cls):
|
|
68
|
+
"""class method to return a new identity matrix
|
|
69
|
+
|
|
70
|
+
Returns
|
|
71
|
+
-------
|
|
72
|
+
Mat3
|
|
73
|
+
new Mat3 matrix as Identity
|
|
74
|
+
|
|
75
|
+
"""
|
|
76
|
+
v = Mat3()
|
|
77
|
+
return v
|
|
78
|
+
|
|
79
|
+
@classmethod
|
|
80
|
+
def zero(cls):
|
|
81
|
+
"""class method to return a new zero matrix
|
|
82
|
+
|
|
83
|
+
Returns
|
|
84
|
+
-------
|
|
85
|
+
Mat3
|
|
86
|
+
new Mat3 matrix as all zeros
|
|
87
|
+
|
|
88
|
+
"""
|
|
89
|
+
v = Mat3()
|
|
90
|
+
v.m = [[0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]]
|
|
91
|
+
return v
|
|
92
|
+
|
|
93
|
+
@classmethod
|
|
94
|
+
def from_list(cls, lst):
|
|
95
|
+
"""class method to create Mat3 from list
|
|
96
|
+
|
|
97
|
+
Parameters
|
|
98
|
+
----------
|
|
99
|
+
lst : list
|
|
100
|
+
|
|
101
|
+
list of 9 numbers to construct a new Mat3 from, we will accept either 9 floats or 3 lists of size 3
|
|
102
|
+
|
|
103
|
+
.. highlight:: python
|
|
104
|
+
.. code-block:: python
|
|
105
|
+
|
|
106
|
+
a=Mat3.from_list([1,2,3,4,5,6,7,8,9])
|
|
107
|
+
b=Mat3.from_list([1,2,3],[4,5,6],[7,8,9])
|
|
108
|
+
|
|
109
|
+
Returns
|
|
110
|
+
-------
|
|
111
|
+
Mat3
|
|
112
|
+
new Mat3 from list elements
|
|
113
|
+
|
|
114
|
+
:raises:
|
|
115
|
+
Mat3NotSquare : if we don't get a 3x3 we raise this
|
|
116
|
+
|
|
117
|
+
"""
|
|
118
|
+
v = Mat3()
|
|
119
|
+
v.m = lst
|
|
120
|
+
if not v._is_square():
|
|
121
|
+
if len(lst) == 9: # can convert
|
|
122
|
+
v.m = [lst[0:3], lst[3:6], lst[6:]]
|
|
123
|
+
return v
|
|
124
|
+
else:
|
|
125
|
+
raise Mat3NotSquare
|
|
126
|
+
else:
|
|
127
|
+
return v
|
|
128
|
+
|
|
129
|
+
def _is_square(self) -> bool:
|
|
130
|
+
"""ensure matrix is square"""
|
|
131
|
+
return len(self.m) == 3 and all(len(i) == 3 for i in self.m)
|
|
132
|
+
|
|
133
|
+
def transpose(self):
|
|
134
|
+
"""transpose this matrix"""
|
|
135
|
+
self.m = [list(item) for item in zip(*self.m)]
|
|
136
|
+
|
|
137
|
+
def get_transpose(self):
|
|
138
|
+
"""return a new matrix as the transpose of ourself
|
|
139
|
+
|
|
140
|
+
Returns
|
|
141
|
+
-------
|
|
142
|
+
Mat3
|
|
143
|
+
The transpose of the current matrix
|
|
144
|
+
"""
|
|
145
|
+
m = Mat3()
|
|
146
|
+
m.m = [list(item) for item in zip(*self.m)]
|
|
147
|
+
return m
|
|
148
|
+
|
|
149
|
+
@classmethod
|
|
150
|
+
def scale(cls, x: float, y: float, z: float):
|
|
151
|
+
"""return a scale matrix resetting to identity first
|
|
152
|
+
|
|
153
|
+
Parameters
|
|
154
|
+
----------
|
|
155
|
+
x : float
|
|
156
|
+
uniform scale in the x axis
|
|
157
|
+
y : float
|
|
158
|
+
uniform scale in the y axis
|
|
159
|
+
z : float
|
|
160
|
+
uniform scale in the z axis
|
|
161
|
+
|
|
162
|
+
.. highlight:: python
|
|
163
|
+
.. code-block:: python
|
|
164
|
+
|
|
165
|
+
scale=Mat3.scale(2.0,1.0,3.0)
|
|
166
|
+
|
|
167
|
+
Returns
|
|
168
|
+
-------
|
|
169
|
+
Mat3
|
|
170
|
+
matrix with diagonals set to the scale
|
|
171
|
+
|
|
172
|
+
"""
|
|
173
|
+
s = Mat3()
|
|
174
|
+
s.m[0][0] = x
|
|
175
|
+
s.m[1][1] = y
|
|
176
|
+
s.m[2][2] = z
|
|
177
|
+
return s
|
|
178
|
+
|
|
179
|
+
@classmethod
|
|
180
|
+
def rotate_x(cls, angle: float):
|
|
181
|
+
"""return a matrix as the rotation around the Cartesian X axis by angle degrees
|
|
182
|
+
|
|
183
|
+
Parameters
|
|
184
|
+
----------
|
|
185
|
+
|
|
186
|
+
angle : float
|
|
187
|
+
the angle in degrees to rotate
|
|
188
|
+
|
|
189
|
+
.. highlight:: python
|
|
190
|
+
.. code-block:: python
|
|
191
|
+
|
|
192
|
+
rotx=Mat3.rotateX(45.0)
|
|
193
|
+
|
|
194
|
+
Returns
|
|
195
|
+
-------
|
|
196
|
+
Mat3
|
|
197
|
+
rotation matrix
|
|
198
|
+
"""
|
|
199
|
+
x = Mat3()
|
|
200
|
+
beta = math.radians(angle)
|
|
201
|
+
sr = math.sin(beta)
|
|
202
|
+
cr = math.cos(beta)
|
|
203
|
+
x.m[1][1] = cr
|
|
204
|
+
x.m[1][2] = sr
|
|
205
|
+
x.m[2][1] = -sr
|
|
206
|
+
x.m[2][2] = cr
|
|
207
|
+
return x
|
|
208
|
+
|
|
209
|
+
@classmethod
|
|
210
|
+
def rotate_y(cls, angle: float):
|
|
211
|
+
"""return a matrix as the rotation around the Cartesian Y axis by angle degrees
|
|
212
|
+
|
|
213
|
+
Parameters
|
|
214
|
+
----------
|
|
215
|
+
|
|
216
|
+
angle : float
|
|
217
|
+
the angle in degrees to rotate
|
|
218
|
+
|
|
219
|
+
.. highlight:: python
|
|
220
|
+
.. code-block:: python
|
|
221
|
+
|
|
222
|
+
roty=Mat3.rotateY(45.0)
|
|
223
|
+
|
|
224
|
+
Returns
|
|
225
|
+
-------
|
|
226
|
+
Mat3
|
|
227
|
+
rotation matrix
|
|
228
|
+
"""
|
|
229
|
+
y = Mat3()
|
|
230
|
+
beta = math.radians(angle)
|
|
231
|
+
sr = math.sin(beta)
|
|
232
|
+
cr = math.cos(beta)
|
|
233
|
+
y.m[0][0] = cr
|
|
234
|
+
y.m[0][2] = -sr
|
|
235
|
+
y.m[2][0] = sr
|
|
236
|
+
y.m[2][2] = cr
|
|
237
|
+
return y
|
|
238
|
+
|
|
239
|
+
@classmethod
|
|
240
|
+
def rotate_z(cls, angle: float):
|
|
241
|
+
"""return a matrix as the rotation around the Cartesian Z axis by angle degrees
|
|
242
|
+
|
|
243
|
+
Parameters
|
|
244
|
+
----------
|
|
245
|
+
|
|
246
|
+
angle : float
|
|
247
|
+
the angle in degrees to rotate
|
|
248
|
+
|
|
249
|
+
.. highlight:: python
|
|
250
|
+
.. code-block:: python
|
|
251
|
+
|
|
252
|
+
rotz=Mat3.rotateZ(45.0)
|
|
253
|
+
|
|
254
|
+
Returns
|
|
255
|
+
-------
|
|
256
|
+
Mat3
|
|
257
|
+
rotation matrix
|
|
258
|
+
"""
|
|
259
|
+
z = Mat3()
|
|
260
|
+
beta = math.radians(angle)
|
|
261
|
+
sr = math.sin(beta)
|
|
262
|
+
cr = math.cos(beta)
|
|
263
|
+
z.m[0][0] = cr
|
|
264
|
+
z.m[0][1] = sr
|
|
265
|
+
z.m[1][0] = -sr
|
|
266
|
+
z.m[1][1] = cr
|
|
267
|
+
return z
|
|
268
|
+
|
|
269
|
+
def __getitem__(self, idx):
|
|
270
|
+
"""access array elements remember this is a list of lists [[3],[3],[3]]
|
|
271
|
+
Parameters
|
|
272
|
+
----------
|
|
273
|
+
idx : int
|
|
274
|
+
the index into the list to get the sub list
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
"""
|
|
278
|
+
return self.m[idx]
|
|
279
|
+
|
|
280
|
+
def __setitem__(self, idx, item):
|
|
281
|
+
"""set array elements remember this is a list of lists [[3],[3],[3]]
|
|
282
|
+
|
|
283
|
+
Parameters
|
|
284
|
+
----------
|
|
285
|
+
idx : int
|
|
286
|
+
the index into the list to set the sub list
|
|
287
|
+
"""
|
|
288
|
+
self.m[idx] = item
|
|
289
|
+
|
|
290
|
+
def __mul__(self, rhs):
|
|
291
|
+
"""Multiply matrix by scalar
|
|
292
|
+
|
|
293
|
+
Parameters
|
|
294
|
+
__________
|
|
295
|
+
rhs : float int
|
|
296
|
+
multiply each matrix element by rhs
|
|
297
|
+
|
|
298
|
+
raises : Mat3Error
|
|
299
|
+
if rhs is not a number
|
|
300
|
+
"""
|
|
301
|
+
if isinstance(rhs, (int, float)):
|
|
302
|
+
for i in range(0, len(self.m)):
|
|
303
|
+
for j in range(0, len(self.m[i])):
|
|
304
|
+
self.m[i][j] *= rhs
|
|
305
|
+
return self
|
|
306
|
+
raise Mat3Error
|
|
307
|
+
|
|
308
|
+
def _mat_mul(self, rhs):
|
|
309
|
+
"matrix mult internal function"
|
|
310
|
+
# fmt: off
|
|
311
|
+
a00 = self.m[0][0] # cache values for speed? (works in C++ not sure about python)
|
|
312
|
+
a01 = self.m[0][1]
|
|
313
|
+
a02 = self.m[0][2]
|
|
314
|
+
a10 = self.m[1][0]
|
|
315
|
+
a11 = self.m[1][1]
|
|
316
|
+
a12 = self.m[1][2]
|
|
317
|
+
a20 = self.m[2][0]
|
|
318
|
+
a21 = self.m[2][1]
|
|
319
|
+
a22 = self.m[2][2]
|
|
320
|
+
|
|
321
|
+
b00 = rhs.m[0][0]
|
|
322
|
+
b01 = rhs.m[0][1]
|
|
323
|
+
b02 = rhs.m[0][2]
|
|
324
|
+
b10 = rhs.m[1][0]
|
|
325
|
+
b11 = rhs.m[1][1]
|
|
326
|
+
b12 = rhs.m[1][2]
|
|
327
|
+
b20 = rhs.m[2][0]
|
|
328
|
+
b21 = rhs.m[2][1]
|
|
329
|
+
b22 = rhs.m[2][2]
|
|
330
|
+
|
|
331
|
+
ret=Mat3() # result mat4
|
|
332
|
+
ret.m[0][0] = b00 * a00 + b01 * a10 + b02 * a20
|
|
333
|
+
ret.m[0][1] = b00 * a01 + b01 * a11 + b02 * a21
|
|
334
|
+
ret.m[0][2] = b00 * a02 + b01 * a12 + b02 * a22
|
|
335
|
+
ret.m[1][0] = b10 * a00 + b11 * a10 + b12 * a20
|
|
336
|
+
ret.m[1][1] = b10 * a01 + b11 * a11 + b12 * a21
|
|
337
|
+
ret.m[1][2] = b10 * a02 + b11 * a12 + b12 * a22
|
|
338
|
+
ret.m[2][0] = b20 * a00 + b21 * a10 + b22 * a20
|
|
339
|
+
ret.m[2][1] = b20 * a01 + b21 * a11 + b22 * a21
|
|
340
|
+
ret.m[2][2] = b20 * a02 + b21 * a12 + b22 * a22
|
|
341
|
+
return ret
|
|
342
|
+
# fmt: on
|
|
343
|
+
|
|
344
|
+
def __matmul__(self, rhs):
|
|
345
|
+
"multiply matrix by another matrix"
|
|
346
|
+
from .vec3 import Vec3 # note relative import
|
|
347
|
+
|
|
348
|
+
if isinstance(rhs, Mat3):
|
|
349
|
+
return self._mat_mul(rhs)
|
|
350
|
+
elif isinstance(rhs, Vec3):
|
|
351
|
+
return Vec3(
|
|
352
|
+
rhs.x * self.m[0][0] + rhs.y * self.m[0][1] + rhs.z * self.m[0][2],
|
|
353
|
+
rhs.x * self.m[1][0] + rhs.y * self.m[1][1] + rhs.z * self.m[1][2],
|
|
354
|
+
rhs.x * self.m[2][0] + rhs.y * self.m[2][1] + rhs.z * self.m[2][2],
|
|
355
|
+
)
|
|
356
|
+
else:
|
|
357
|
+
raise Mat3Error
|
|
358
|
+
|
|
359
|
+
def _add(self, rhs):
|
|
360
|
+
"internal add function"
|
|
361
|
+
temp = Mat3()
|
|
362
|
+
for i in range(0, len(temp.m)):
|
|
363
|
+
temp.m[i] = [a + b for a, b in zip(self.m[i], rhs.m[i])]
|
|
364
|
+
return temp
|
|
365
|
+
|
|
366
|
+
def __add__(self, rhs):
|
|
367
|
+
"piecewise addition of elements"
|
|
368
|
+
return self._add(rhs)
|
|
369
|
+
|
|
370
|
+
def __iadd__(self, rhs):
|
|
371
|
+
"piecewise addition of elements to this"
|
|
372
|
+
return self._add(rhs)
|
|
373
|
+
|
|
374
|
+
def _sub(self, rhs):
|
|
375
|
+
"internal subtract function"
|
|
376
|
+
temp = Mat3()
|
|
377
|
+
for i in range(0, len(temp.m)):
|
|
378
|
+
temp.m[i] = [a - b for a, b in zip(self.m[i], rhs.m[i])]
|
|
379
|
+
return temp
|
|
380
|
+
|
|
381
|
+
def __sub__(self, rhs):
|
|
382
|
+
"piecewise subtraction of elements"
|
|
383
|
+
return self._sub(rhs)
|
|
384
|
+
|
|
385
|
+
def __isub__(self, rhs):
|
|
386
|
+
"piecewise subtraction of elements to this"
|
|
387
|
+
return self._sub(rhs)
|
|
388
|
+
|
|
389
|
+
def determinant(self):
|
|
390
|
+
"determinant of matrix"
|
|
391
|
+
return (
|
|
392
|
+
+self.m[0][0] * (self.m[1][1] * self.m[2][2] - self.m[2][1] * self.m[1][2])
|
|
393
|
+
- self.m[0][1] * (self.m[1][0] * self.m[2][2] - self.m[1][2] * self.m[2][0])
|
|
394
|
+
+ self.m[0][2] * (self.m[1][0] * self.m[2][1] - self.m[1][1] * self.m[2][0])
|
|
395
|
+
)
|
|
396
|
+
|
|
397
|
+
def to_list(self):
|
|
398
|
+
"convert matrix to list"
|
|
399
|
+
# flatten to single array
|
|
400
|
+
return functools.reduce(operator.concat, self.m)
|
|
401
|
+
|
|
402
|
+
def inverse(self):
|
|
403
|
+
"Inverse of matrix raise MatrixError if not calculable"
|
|
404
|
+
det = self.determinant()
|
|
405
|
+
try:
|
|
406
|
+
invdet = 1 / det
|
|
407
|
+
tmp = Mat3()
|
|
408
|
+
# minor matrix + co-factor
|
|
409
|
+
tmp.m[0][0] = (
|
|
410
|
+
+(self.m[1][1] * self.m[2][2] - self.m[1][2] * self.m[2][1]) * invdet
|
|
411
|
+
)
|
|
412
|
+
tmp.m[1][0] = (
|
|
413
|
+
-(self.m[1][0] * self.m[2][2] - self.m[1][2] * self.m[2][0]) * invdet
|
|
414
|
+
)
|
|
415
|
+
tmp.m[2][0] = (
|
|
416
|
+
+(self.m[1][0] * self.m[2][1] - self.m[1][1] * self.m[2][0]) * invdet
|
|
417
|
+
)
|
|
418
|
+
|
|
419
|
+
tmp.m[0][1] = (
|
|
420
|
+
-(self.m[0][1] * self.m[2][2] - self.m[0][2] * self.m[2][1]) * invdet
|
|
421
|
+
)
|
|
422
|
+
tmp.m[1][1] = (
|
|
423
|
+
+(self.m[0][0] * self.m[2][2] - self.m[0][2] * self.m[2][0]) * invdet
|
|
424
|
+
)
|
|
425
|
+
tmp.m[2][1] = (
|
|
426
|
+
-(self.m[0][0] * self.m[2][1] - self.m[0][1] * self.m[2][0]) * invdet
|
|
427
|
+
)
|
|
428
|
+
|
|
429
|
+
tmp.m[0][2] = (
|
|
430
|
+
+(self.m[0][1] * self.m[1][2] - self.m[0][2] * self.m[1][1]) * invdet
|
|
431
|
+
)
|
|
432
|
+
tmp.m[1][2] = (
|
|
433
|
+
-(self.m[0][0] * self.m[1][2] - self.m[0][2] * self.m[1][0]) * invdet
|
|
434
|
+
)
|
|
435
|
+
tmp.m[2][2] = (
|
|
436
|
+
+(self.m[0][0] * self.m[1][1] - self.m[0][1] * self.m[1][0]) * invdet
|
|
437
|
+
)
|
|
438
|
+
|
|
439
|
+
return tmp
|
|
440
|
+
except ZeroDivisionError:
|
|
441
|
+
raise Mat3Error
|
|
442
|
+
|
|
443
|
+
def __str__(self):
|
|
444
|
+
"""return string representation"""
|
|
445
|
+
return f"[{self.m[0]}\n{self.m[1]}\n{self.m[2]}]"
|
|
446
|
+
|
|
447
|
+
def __repr__(self):
|
|
448
|
+
"""return string representation"""
|
|
449
|
+
return f"Mat3({self.m})"
|
|
450
|
+
|
|
451
|
+
@classmethod
|
|
452
|
+
def from_mat4(cls, mat4):
|
|
453
|
+
"""Create a Mat3 from a Mat4"""
|
|
454
|
+
return Mat3.from_list(
|
|
455
|
+
[
|
|
456
|
+
mat4.m[0][0],
|
|
457
|
+
mat4.m[0][1],
|
|
458
|
+
mat4.m[0][2],
|
|
459
|
+
mat4.m[1][0],
|
|
460
|
+
mat4.m[1][1],
|
|
461
|
+
mat4.m[1][2],
|
|
462
|
+
mat4.m[2][0],
|
|
463
|
+
mat4.m[2][1],
|
|
464
|
+
mat4.m[2][2],
|
|
465
|
+
]
|
|
466
|
+
)
|