ncca-ngl 0.3.4__py3-none-any.whl → 0.5.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.
Files changed (56) hide show
  1. ncca/ngl/PrimData/pack_arrays.py +2 -3
  2. ncca/ngl/__init__.py +3 -4
  3. ncca/ngl/base_mesh.py +28 -20
  4. ncca/ngl/image.py +1 -3
  5. ncca/ngl/mat2.py +79 -53
  6. ncca/ngl/mat3.py +104 -185
  7. ncca/ngl/mat4.py +144 -309
  8. ncca/ngl/prim_data.py +42 -36
  9. ncca/ngl/primitives.py +2 -2
  10. ncca/ngl/pyside_event_handling_mixin.py +0 -108
  11. ncca/ngl/quaternion.py +69 -36
  12. ncca/ngl/shader.py +0 -116
  13. ncca/ngl/shader_program.py +94 -117
  14. ncca/ngl/texture.py +5 -2
  15. ncca/ngl/util.py +7 -0
  16. ncca/ngl/vec2.py +58 -292
  17. ncca/ngl/vec2_array.py +79 -28
  18. ncca/ngl/vec3.py +59 -340
  19. ncca/ngl/vec3_array.py +76 -23
  20. ncca/ngl/vec4.py +90 -190
  21. ncca/ngl/vec4_array.py +78 -27
  22. ncca/ngl/vector_base.py +542 -0
  23. ncca/ngl/webgpu/__init__.py +20 -0
  24. ncca/ngl/webgpu/__main__.py +640 -0
  25. ncca/ngl/webgpu/__main__.py.backup +640 -0
  26. ncca/ngl/webgpu/base_webgpu_pipeline.py +354 -0
  27. ncca/ngl/webgpu/custom_shader_pipeline.py +288 -0
  28. ncca/ngl/webgpu/instanced_geometry_pipeline.py +594 -0
  29. ncca/ngl/webgpu/line_pipeline.py +405 -0
  30. ncca/ngl/webgpu/pipeline_factory.py +190 -0
  31. ncca/ngl/webgpu/pipeline_shaders.py +497 -0
  32. ncca/ngl/webgpu/point_list_pipeline.py +349 -0
  33. ncca/ngl/webgpu/point_pipeline.py +336 -0
  34. ncca/ngl/webgpu/triangle_pipeline.py +419 -0
  35. ncca/ngl/webgpu/webgpu_constants.py +31 -0
  36. ncca/ngl/webgpu/webgpu_widget.py +322 -0
  37. ncca/ngl/webgpu/wip/REFACTORING_SUMMARY.md +82 -0
  38. ncca/ngl/webgpu/wip/UNIFIED_SYSTEM.md +314 -0
  39. ncca/ngl/webgpu/wip/buffer_manager.py +396 -0
  40. ncca/ngl/webgpu/wip/pipeline_config.py +463 -0
  41. ncca/ngl/webgpu/wip/shader_constants.py +328 -0
  42. ncca/ngl/webgpu/wip/shader_templates.py +563 -0
  43. ncca/ngl/webgpu/wip/unified_examples.py +390 -0
  44. ncca/ngl/webgpu/wip/unified_factory.py +449 -0
  45. ncca/ngl/webgpu/wip/unified_pipeline.py +469 -0
  46. ncca/ngl/widgets/__init__.py +18 -2
  47. ncca/ngl/widgets/__main__.py +2 -1
  48. ncca/ngl/widgets/lookatwidget.py +2 -1
  49. ncca/ngl/widgets/mat4widget.py +2 -2
  50. ncca/ngl/widgets/vec2widget.py +1 -1
  51. ncca/ngl/widgets/vec3widget.py +1 -0
  52. {ncca_ngl-0.3.4.dist-info → ncca_ngl-0.5.0.dist-info}/METADATA +3 -2
  53. ncca_ngl-0.5.0.dist-info/RECORD +105 -0
  54. ncca/ngl/widgets/transformation_widget.py +0 -299
  55. ncca_ngl-0.3.4.dist-info/RECORD +0 -82
  56. {ncca_ngl-0.3.4.dist-info → ncca_ngl-0.5.0.dist-info}/WHEEL +0 -0
ncca/ngl/mat3.py CHANGED
@@ -1,15 +1,6 @@
1
1
  """
2
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
-
3
+ NumPy-based implementation
13
4
  """
14
5
 
15
6
  import copy
@@ -32,9 +23,6 @@ class Mat3NotSquare(Exception):
32
23
  pass
33
24
 
34
25
 
35
- _identity = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]
36
-
37
-
38
26
  class Mat3:
39
27
  """Simple Mat3 class for basic affine transforms"""
40
28
 
@@ -45,7 +33,7 @@ class Mat3:
45
33
 
46
34
  def __init__(self):
47
35
  """construct to identity matrix"""
48
- self.m = copy.deepcopy(_identity)
36
+ self.m = np.eye(3, dtype=np.float64)
49
37
 
50
38
  def get_matrix(self):
51
39
  """return matrix elements as list ideal for OpenGL
@@ -56,12 +44,11 @@ class Mat3:
56
44
  the 9 float elements of the matrix, ideal
57
45
  for OpenGL or Renderman consumption
58
46
  """
59
-
60
- return functools.reduce(operator.concat, self.m)
47
+ return self.m.flatten("C").tolist()
61
48
 
62
49
  def to_numpy(self):
63
50
  "return matrix as a numpy array ideal for WebGPU etc"
64
- return np.array(self.get_matrix()).reshape([3, 3])
51
+ return self.m.astype(np.float32)
65
52
 
66
53
  @classmethod
67
54
  def identity(cls):
@@ -87,63 +74,35 @@ class Mat3:
87
74
 
88
75
  """
89
76
  v = Mat3()
90
- v.m = [[0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]]
77
+ v.m = np.zeros((3, 3), dtype=np.float64)
91
78
  return v
92
79
 
93
80
  @classmethod
94
81
  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
- """
82
+ "class method to create mat3 from list"
118
83
  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:]]
84
+ if isinstance(lst, list) and len(lst) == 3 and all(isinstance(row, list) for row in lst):
85
+ # 2D list
86
+ if all(len(row) == 3 for row in lst):
87
+ v.m = np.array(lst, dtype=np.float64)
123
88
  return v
124
- else:
89
+ elif any(len(row) != 3 for row in lst):
125
90
  raise Mat3NotSquare
126
- else:
91
+ elif isinstance(lst, list) and len(lst) == 9:
92
+ # flat list - reshape to 3x3 in row-major order
93
+ v.m = np.array(lst, dtype=np.float64).reshape(3, 3, order="C")
127
94
  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)
95
+ else:
96
+ raise Mat3NotSquare
132
97
 
133
98
  def transpose(self):
134
99
  """transpose this matrix"""
135
- self.m = [list(item) for item in zip(*self.m, strict=False)]
100
+ self.m = self.m.T
136
101
 
137
102
  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
- """
103
+ "return a new matrix as the transpose of ourself"
145
104
  m = Mat3()
146
- m.m = [list(item) for item in zip(*self.m, strict=False)]
105
+ m.m = self.m.T.copy()
147
106
  return m
148
107
 
149
108
  @classmethod
@@ -170,11 +129,11 @@ class Mat3:
170
129
  matrix with diagonals set to the scale
171
130
 
172
131
  """
173
- s = Mat3()
174
- s.m[0][0] = x
175
- s.m[1][1] = y
176
- s.m[2][2] = z
177
- return s
132
+ a = Mat3()
133
+ a.m[0, 0] = x
134
+ a.m[1, 1] = y
135
+ a.m[2, 2] = z
136
+ return a
178
137
 
179
138
  @classmethod
180
139
  def rotate_x(cls, angle: float):
@@ -196,15 +155,15 @@ class Mat3:
196
155
  Mat3
197
156
  rotation matrix
198
157
  """
199
- x = Mat3()
158
+ a = Mat3()
200
159
  beta = math.radians(angle)
201
160
  sr = math.sin(beta)
202
161
  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
162
+ a.m[1, 1] = cr
163
+ a.m[1, 2] = sr
164
+ a.m[2, 1] = -sr
165
+ a.m[2, 2] = cr
166
+ return a
208
167
 
209
168
  @classmethod
210
169
  def rotate_y(cls, angle: float):
@@ -226,15 +185,15 @@ class Mat3:
226
185
  Mat3
227
186
  rotation matrix
228
187
  """
229
- y = Mat3()
188
+ a = Mat3()
230
189
  beta = math.radians(angle)
231
190
  sr = math.sin(beta)
232
191
  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
192
+ a.m[0, 0] = cr
193
+ a.m[0, 2] = -sr
194
+ a.m[2, 0] = sr
195
+ a.m[2, 2] = cr
196
+ return a
238
197
 
239
198
  @classmethod
240
199
  def rotate_z(cls, angle: float):
@@ -256,15 +215,15 @@ class Mat3:
256
215
  Mat3
257
216
  rotation matrix
258
217
  """
259
- z = Mat3()
218
+ a = Mat3()
260
219
  beta = math.radians(angle)
261
220
  sr = math.sin(beta)
262
221
  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
222
+ a.m[0, 0] = cr
223
+ a.m[0, 1] = sr
224
+ a.m[1, 0] = -sr
225
+ a.m[1, 1] = cr
226
+ return a
268
227
 
269
228
  def __getitem__(self, idx):
270
229
  """access array elements remember this is a list of lists [[3],[3],[3]]
@@ -275,7 +234,7 @@ class Mat3:
275
234
 
276
235
 
277
236
  """
278
- return self.m[idx]
237
+ return self.m[idx].tolist()
279
238
 
280
239
  def __setitem__(self, idx, item):
281
240
  """set array elements remember this is a list of lists [[3],[3],[3]]
@@ -299,105 +258,65 @@ class Mat3:
299
258
  if rhs is not a number
300
259
  """
301
260
  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
261
+ result = Mat3()
262
+ result.m = self.m * rhs
263
+ return result
306
264
  raise Mat3Error
307
265
 
308
266
  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
267
+ "matrix mult for 3D OpenGL style graphics"
268
+ result = Mat3()
269
+ # Use numpy's @ operator which does standard matrix multiplication
270
+ result.m = rhs.m @ self.m
271
+ return result
343
272
 
344
273
  def __matmul__(self, rhs):
345
274
  "multiply matrix by another matrix"
346
- from .vec3 import Vec3 # note relative import
275
+ from .vec3 import Vec3
347
276
 
277
+ "multiply matrix by another matrix or vector"
348
278
  if isinstance(rhs, Mat3):
349
279
  return self._mat_mul(rhs)
350
280
  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
- )
281
+ # Vector transformation
282
+ vec = np.array([rhs.x, rhs.y, rhs.z], dtype=np.float64)
283
+ res = self.m @ vec
284
+ return Vec3(res[0], res[1], res[2])
356
285
  else:
357
286
  raise Mat3Error
358
287
 
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], strict=False)]
364
- return temp
365
-
366
288
  def __add__(self, rhs):
367
289
  "piecewise addition of elements"
368
- return self._add(rhs)
290
+ result = Mat3()
291
+ result.m = self.m + rhs.m
292
+ return result
369
293
 
370
294
  def __iadd__(self, rhs):
371
295
  "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], strict=False)]
379
- return temp
296
+ result = Mat3()
297
+ result.m = self.m + rhs.m
298
+ return result
380
299
 
381
300
  def __sub__(self, rhs):
382
301
  "piecewise subtraction of elements"
383
- return self._sub(rhs)
302
+ result = Mat3()
303
+ result.m = self.m - rhs.m
304
+ return result
384
305
 
385
306
  def __isub__(self, rhs):
386
307
  "piecewise subtraction of elements to this"
387
- return self._sub(rhs)
308
+ result = Mat3()
309
+ result.m = self.m - rhs.m
310
+ return result
388
311
 
389
312
  def determinant(self):
390
313
  "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
- )
314
+ return np.linalg.det(self.m)
396
315
 
397
316
  def to_list(self):
398
317
  "convert matrix to list"
399
318
  # flatten to single array
400
- return functools.reduce(operator.concat, self.m)
319
+ return self.m.flatten("C").tolist()
401
320
 
402
321
  def copy(self) -> "Mat3":
403
322
  """Create a copy of the matrix.
@@ -411,46 +330,46 @@ class Mat3:
411
330
 
412
331
  def inverse(self):
413
332
  "Inverse of matrix raise MatrixError if not calculable"
414
- det = self.determinant()
415
333
  try:
416
- invdet = 1 / det
417
- tmp = Mat3()
418
- # minor matrix + co-factor
419
- tmp.m[0][0] = +(self.m[1][1] * self.m[2][2] - self.m[1][2] * self.m[2][1]) * invdet
420
- tmp.m[1][0] = -(self.m[1][0] * self.m[2][2] - self.m[1][2] * self.m[2][0]) * invdet
421
- tmp.m[2][0] = +(self.m[1][0] * self.m[2][1] - self.m[1][1] * self.m[2][0]) * invdet
422
-
423
- tmp.m[0][1] = -(self.m[0][1] * self.m[2][2] - self.m[0][2] * self.m[2][1]) * invdet
424
- tmp.m[1][1] = +(self.m[0][0] * self.m[2][2] - self.m[0][2] * self.m[2][0]) * invdet
425
- tmp.m[2][1] = -(self.m[0][0] * self.m[2][1] - self.m[0][1] * self.m[2][0]) * invdet
426
-
427
- tmp.m[0][2] = +(self.m[0][1] * self.m[1][2] - self.m[0][2] * self.m[1][1]) * invdet
428
- tmp.m[1][2] = -(self.m[0][0] * self.m[1][2] - self.m[0][2] * self.m[1][0]) * invdet
429
- tmp.m[2][2] = +(self.m[0][0] * self.m[1][1] - self.m[0][1] * self.m[1][0]) * invdet
430
-
431
- return tmp
432
- except ZeroDivisionError:
334
+ result = Mat3()
335
+ result.m = np.linalg.inv(self.m)
336
+ return result
337
+ except np.linalg.LinAlgError:
433
338
  raise Mat3Error
434
339
 
435
340
  def __str__(self):
436
- """return string representation"""
437
- return f"[{self.m[0]}\n{self.m[1]}\n{self.m[2]}]"
341
+ rows = [self.m[i].tolist() for i in range(3)]
342
+ return f"[{rows[0]}\n{rows[1]}\n{rows[2]}]"
438
343
 
439
344
  def __repr__(self):
440
- """return string representation"""
441
- return f"Mat3({self.m})"
345
+ rows = [self.m[i].tolist() for i in range(3)]
346
+ return f"Mat3({rows})"
442
347
 
443
348
  @classmethod
444
349
  def from_mat4(cls, mat4):
445
350
  """Create a Mat3 from a Mat4"""
446
- return Mat3.from_list([
447
- mat4.m[0][0],
448
- mat4.m[0][1],
449
- mat4.m[0][2],
450
- mat4.m[1][0],
451
- mat4.m[1][1],
452
- mat4.m[1][2],
453
- mat4.m[2][0],
454
- mat4.m[2][1],
455
- mat4.m[2][2],
456
- ])
351
+ m = Mat3()
352
+ m.m = mat4.m[:3, :3].copy()
353
+ return m
354
+
355
+ def __eq__(self, other):
356
+ """Value-based equality for Mat3: compare underlying matrices numerically.
357
+
358
+ Returns NotImplemented for non-Mat3 types so Python can try reflected comparisons
359
+ or handle it appropriately.
360
+ """
361
+ if not isinstance(other, Mat3):
362
+ return NotImplemented
363
+ # self.m and other.m should be numpy arrays; compare with tolerance
364
+ return np.allclose(self.m, other.m, rtol=1e-8, atol=1e-12)
365
+
366
+ def __ne__(self, other):
367
+ """Value-based inequality for Mat3: compare underlying matrices numerically.
368
+
369
+ Returns NotImplemented for non-Mat3 types so Python can try reflected comparisons
370
+ or handle it appropriately.
371
+ """
372
+ if not isinstance(other, Mat3):
373
+ return NotImplemented
374
+ # Return the negation of equality
375
+ return not np.allclose(self.m, other.m, rtol=1e-8, atol=1e-12)