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/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)