ncca-ngl 0.2.1__tar.gz → 0.2.3__tar.gz

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 (66) hide show
  1. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/PKG-INFO +1 -1
  2. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/pyproject.toml +1 -1
  3. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/__init__.py +3 -0
  4. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/mat2.py +12 -2
  5. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/mat3.py +34 -44
  6. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/mat4.py +14 -4
  7. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/prim_data.py +8 -0
  8. ncca_ngl-0.2.3/src/ncca/ngl/primitives.py +121 -0
  9. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/vec2.py +4 -7
  10. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/vec3.py +11 -25
  11. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/vec4.py +5 -17
  12. ncca_ngl-0.2.1/src/ncca/ngl/primitives.py +0 -219
  13. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/LICENSE.txt +0 -0
  14. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/.ruff_cache/.gitignore +0 -0
  15. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/.ruff_cache/0.13.0/10564494386971134025 +0 -0
  16. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/.ruff_cache/0.13.0/7783445477288392980 +0 -0
  17. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/.ruff_cache/CACHEDIR.TAG +0 -0
  18. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/PrimData/Primitives.npz +0 -0
  19. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/PrimData/buddah.npy +0 -0
  20. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/PrimData/bunny.npy +0 -0
  21. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/PrimData/cube.npy +0 -0
  22. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/PrimData/dodecahedron.npy +0 -0
  23. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/PrimData/dragon.npy +0 -0
  24. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/PrimData/football.npy +0 -0
  25. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/PrimData/icosahedron.npy +0 -0
  26. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/PrimData/octahedron.npy +0 -0
  27. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/PrimData/pack_arrays.py +0 -0
  28. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/PrimData/teapot.npy +0 -0
  29. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/PrimData/tetrahedron.npy +0 -0
  30. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/PrimData/troll.npy +0 -0
  31. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/abstract_vao.py +0 -0
  32. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/base_mesh.py +0 -0
  33. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/base_mesh.pyi +0 -0
  34. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/bbox.py +0 -0
  35. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/bezier_curve.py +0 -0
  36. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/first_person_camera.py +0 -0
  37. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/image.py +0 -0
  38. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/log.py +0 -0
  39. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/multi_buffer_vao.py +0 -0
  40. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/obj.py +0 -0
  41. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/plane.py +0 -0
  42. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/pyside_event_handling_mixin.py +0 -0
  43. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/quaternion.py +0 -0
  44. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/random.py +0 -0
  45. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/shader.py +0 -0
  46. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/shader_lib.py +0 -0
  47. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/shader_program.py +0 -0
  48. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/shaders/checker_fragment.glsl +0 -0
  49. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/shaders/checker_vertex.glsl +0 -0
  50. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/shaders/colour_fragment.glsl +0 -0
  51. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/shaders/colour_vertex.glsl +0 -0
  52. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/shaders/diffuse_fragment.glsl +0 -0
  53. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/shaders/diffuse_vertex.glsl +0 -0
  54. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/shaders/text_fragment.glsl +0 -0
  55. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/shaders/text_geometry.glsl +0 -0
  56. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/shaders/text_vertex.glsl +0 -0
  57. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/simple_index_vao.py +0 -0
  58. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/simple_vao.py +0 -0
  59. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/text.py +0 -0
  60. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/texture.py +0 -0
  61. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/transform.py +0 -0
  62. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/util.py +0 -0
  63. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/vao_factory.py +0 -0
  64. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/vec2_array.py +0 -0
  65. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/vec3_array.py +0 -0
  66. {ncca_ngl-0.2.1 → ncca_ngl-0.2.3}/src/ncca/ngl/vec4_array.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: ncca-ngl
3
- Version: 0.2.1
3
+ Version: 0.2.3
4
4
  Summary: A Python version of the NGL graphics library.
5
5
  Author: Jon Macey
6
6
  Author-email: Jon Macey <jmacey@bournemouth.ac.uk>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "ncca-ngl"
3
- version = "0.2.1"
3
+ version = "0.2.3"
4
4
  description = "A Python version of the NGL graphics library."
5
5
  authors = [{ name = "Jon Macey", email = "jmacey@bournemouth.ac.uk" }]
6
6
  requires-python = ">=3.13"
@@ -6,6 +6,9 @@ try:
6
6
  except PackageNotFoundError:
7
7
  __version__ = "0.0.0"
8
8
 
9
+ __author__ = "Jon Macey jmacey@bournemouth.ac.uk"
10
+ __license__ = "MIT"
11
+
9
12
  from .abstract_vao import AbstractVAO, VertexData
10
13
  from .base_mesh import BaseMesh, Face
11
14
  from .bbox import BBox
@@ -45,7 +45,7 @@ class Mat2:
45
45
  Returns:
46
46
  list[float]: A flat list of floats.
47
47
  """
48
- return [item for sublist in zip(*self.m) for item in sublist]
48
+ return [item for sublist in zip(*self.m, strict=False) for item in sublist]
49
49
 
50
50
  def to_numpy(self):
51
51
  """
@@ -125,4 +125,14 @@ class Mat2:
125
125
  def to_list(self):
126
126
  "convert matrix to list in column-major order"
127
127
  # flatten to single array
128
- return [item for sublist in zip(*self.m) for item in sublist]
128
+ return [item for sublist in zip(*self.m, strict=False) for item in sublist]
129
+
130
+ def copy(self) -> "Mat2":
131
+ """Create a copy of the matrix.
132
+
133
+ Returns:
134
+ A new Mat2 instance with the same values.
135
+ """
136
+ new_mat = Mat2()
137
+ new_mat.m = copy.deepcopy(self.m)
138
+ return new_mat
@@ -132,7 +132,7 @@ class Mat3:
132
132
 
133
133
  def transpose(self):
134
134
  """transpose this matrix"""
135
- self.m = [list(item) for item in zip(*self.m)]
135
+ self.m = [list(item) for item in zip(*self.m, strict=False)]
136
136
 
137
137
  def get_transpose(self):
138
138
  """return a new matrix as the transpose of ourself
@@ -143,7 +143,7 @@ class Mat3:
143
143
  The transpose of the current matrix
144
144
  """
145
145
  m = Mat3()
146
- m.m = [list(item) for item in zip(*self.m)]
146
+ m.m = [list(item) for item in zip(*self.m, strict=False)]
147
147
  return m
148
148
 
149
149
  @classmethod
@@ -360,7 +360,7 @@ class Mat3:
360
360
  "internal add function"
361
361
  temp = Mat3()
362
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])]
363
+ temp.m[i] = [a + b for a, b in zip(self.m[i], rhs.m[i], strict=False)]
364
364
  return temp
365
365
 
366
366
  def __add__(self, rhs):
@@ -375,7 +375,7 @@ class Mat3:
375
375
  "internal subtract function"
376
376
  temp = Mat3()
377
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])]
378
+ temp.m[i] = [a - b for a, b in zip(self.m[i], rhs.m[i], strict=False)]
379
379
  return temp
380
380
 
381
381
  def __sub__(self, rhs):
@@ -399,6 +399,16 @@ class Mat3:
399
399
  # flatten to single array
400
400
  return functools.reduce(operator.concat, self.m)
401
401
 
402
+ def copy(self) -> "Mat3":
403
+ """Create a copy of the matrix.
404
+
405
+ Returns:
406
+ A new Mat3 instance with the same values.
407
+ """
408
+ new_mat = Mat3()
409
+ new_mat.m = copy.deepcopy(self.m)
410
+ return new_mat
411
+
402
412
  def inverse(self):
403
413
  "Inverse of matrix raise MatrixError if not calculable"
404
414
  det = self.determinant()
@@ -406,35 +416,17 @@ class Mat3:
406
416
  invdet = 1 / det
407
417
  tmp = Mat3()
408
418
  # 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
- )
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
418
422
 
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
- )
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
428
426
 
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
- )
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
438
430
 
439
431
  return tmp
440
432
  except ZeroDivisionError:
@@ -451,16 +443,14 @@ class Mat3:
451
443
  @classmethod
452
444
  def from_mat4(cls, mat4):
453
445
  """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
- )
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
+ ])
@@ -86,14 +86,24 @@ class Mat4:
86
86
  # flatten to single array
87
87
  return functools.reduce(operator.concat, self.m)
88
88
 
89
+ def copy(self) -> "Mat4":
90
+ """Create a copy of the matrix.
91
+
92
+ Returns:
93
+ A new Mat4 instance with the same values.
94
+ """
95
+ new_mat = Mat4()
96
+ new_mat.m = copy.deepcopy(self.m)
97
+ return new_mat
98
+
89
99
  def transpose(self):
90
100
  "transpose this matrix"
91
- self.m = [list(item) for item in zip(*self.m)]
101
+ self.m = [list(item) for item in zip(*self.m, strict=False)]
92
102
 
93
103
  def get_transpose(self):
94
104
  "return a new matrix as the transpose of ourself"
95
105
  m = Mat4()
96
- m.m = [list(item) for item in zip(*self.m)]
106
+ m.m = [list(item) for item in zip(*self.m, strict=False)]
97
107
  return m
98
108
 
99
109
  @classmethod
@@ -258,7 +268,7 @@ class Mat4:
258
268
  "internal add function"
259
269
  temp = Mat4()
260
270
  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])]
271
+ temp.m[i] = [a + b for a, b in zip(self.m[i], rhs.m[i], strict=False)]
262
272
  return temp
263
273
 
264
274
  def __add__(self, rhs):
@@ -273,7 +283,7 @@ class Mat4:
273
283
  "internal sub function"
274
284
  temp = Mat4()
275
285
  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])]
286
+ temp.m[i] = [a - b for a, b in zip(self.m[i], rhs.m[i], strict=False)]
277
287
  return temp
278
288
 
279
289
  def __sub__(self, rhs):
@@ -21,6 +21,14 @@ class Prims(enum.Enum):
21
21
  TEAPOT = "teapot"
22
22
  TETRAHEDRON = "tetrahedron"
23
23
  TROLL = "troll"
24
+ SPHERE = "sphere"
25
+ TORUS = "torus"
26
+ LINE_GRID = "line_grid"
27
+ TRIANGLE_PLANE = "triangle_plane"
28
+ CONE = "cone"
29
+ CAPSULE = "capsule"
30
+ CYLINDER = "cylinder"
31
+ DISK = "disk"
24
32
 
25
33
 
26
34
  def _circle_table(n: int) -> np.ndarray:
@@ -0,0 +1,121 @@
1
+ """
2
+ OpenGL primitive generation and drawing functions
3
+ In this class we can generate a pipeline for drawing our data for the most part it will be
4
+ x,y,z nx,ny,nz and u,v data in a flat numpy array.
5
+ We need to create the data first which is stored in a map as part of the class, we can then call draw
6
+ which will generate a pipeline for this object and draw into the current context.
7
+ """
8
+
9
+ from typing import Dict, Union
10
+
11
+ import numpy as np
12
+ import OpenGL.GL as gl
13
+
14
+ from .log import logger
15
+ from .prim_data import PrimData, Prims
16
+ from .simple_vao import VertexData
17
+ from .vao_factory import VAOFactory, VAOType # noqa
18
+ from .vec3 import Vec3
19
+
20
+
21
+ class _primitive:
22
+ """A private class to hold VAO data for a primitive."""
23
+
24
+ def __init__(self, prim_data: np.ndarray):
25
+ """
26
+ Initializes the primitive with the given data.
27
+
28
+ Args:
29
+ prim_data: A numpy array containing the vertex data (x,y,z,nx,ny,nz,u,v).
30
+ """
31
+ self.vao = VAOFactory.create_vao(VAOType.SIMPLE, gl.GL_TRIANGLES)
32
+ with self.vao:
33
+ data = VertexData(data=prim_data.data, size=prim_data.size)
34
+ self.vao.set_data(data)
35
+ vert_data_size = 8 * 4 # 4 is sizeof float and 8 is x,y,z,nx,ny,nz,uv
36
+ self.vao.set_vertex_attribute_pointer(0, 3, gl.GL_FLOAT, vert_data_size, 0)
37
+ self.vao.set_vertex_attribute_pointer(1, 3, gl.GL_FLOAT, vert_data_size, Vec3.sizeof())
38
+ self.vao.set_vertex_attribute_pointer(2, 2, gl.GL_FLOAT, vert_data_size, 2 * Vec3.sizeof())
39
+ self.vao.set_num_indices(prim_data.size // 8)
40
+
41
+
42
+ class Primitives:
43
+ """A static class for creating and drawing primitives."""
44
+
45
+ # this is effectively a static class so we can use it to store data
46
+ # and generate pipelines for drawing
47
+ _primitives: Dict[str, _primitive] = {}
48
+ _loaded: bool = False
49
+
50
+ @classmethod
51
+ def create(cls, type: str, name: str, *args: object, **kwargs: object) -> None:
52
+ """
53
+ Creates and stores a primitive object of the specified type from :-
54
+ Prims.SPHERE : (radius: float, precision: int).
55
+ Prims.TORUS : (radius: float, tube_radius: float, precision: int).
56
+ Prims.LINE_GRID : (width: float, depth: float, steps: int).
57
+ Prims.TRIANGLE_PLANE : ( width: float, depth: float, w_p: int, d_p: int, v_n: Vec3).
58
+ Prims.CYLINDER : (radius: float, height: float, slices: int, stacks: int).
59
+ Prims.CAPSULE : (radius: float, height: float, slices: int, stacks: int).
60
+ Prims.CONE : (radius: float, height: float, slices: int, stacks: int).
61
+
62
+ Args:
63
+ type (str): The primitive type, typically from the Prims enum (e.g., Prims.SPHERE).
64
+ name (str): The name to associate with the created primitive.
65
+ *args: Positional arguments to pass to the primitive creation function (e.g., radius, precision).
66
+ **kwargs: Keyword arguments to pass to the primitive creation function.
67
+
68
+ Raises:
69
+ ValueError: If the primitive type is not recognized.
70
+
71
+ Example:
72
+ Primitives.create(Prims.SPHERE, "sphere", 0.3, 32)
73
+ Primitives.create(Prims.SPHERE, "sphere", radius=0.3, precision=32)
74
+ """
75
+ prim_methods = {
76
+ Prims.SPHERE: PrimData.sphere,
77
+ Prims.TORUS: PrimData.torus,
78
+ Prims.LINE_GRID: PrimData.line_grid,
79
+ Prims.TRIANGLE_PLANE: PrimData.triangle_plane,
80
+ Prims.CYLINDER: PrimData.cylinder,
81
+ Prims.DISK: PrimData.disk,
82
+ Prims.CAPSULE: PrimData.capsule,
83
+ Prims.CONE: PrimData.cone,
84
+ }
85
+ try:
86
+ method = prim_methods[type]
87
+ except KeyError:
88
+ raise ValueError(f"Unknown primitive: {name}")
89
+
90
+ cls._primitives[name] = _primitive(method(*args, **kwargs))
91
+
92
+ @classmethod
93
+ def load_default_primitives(cls) -> None:
94
+ """Loads the default primitives from the PrimData directory."""
95
+ logger.info("Loading default primitives...")
96
+ if not cls._loaded:
97
+ for p in Prims:
98
+ try:
99
+ prim_data = PrimData.primitive(p.value)
100
+ prim = _primitive(prim_data)
101
+ cls._primitives[p.value] = prim
102
+ except Exception:
103
+ pass
104
+ cls._loaded = True
105
+
106
+ @classmethod
107
+ def draw(cls, name: Union[str, Prims]) -> None:
108
+ """
109
+ Draws the specified primitive.
110
+
111
+ Args:
112
+ name: The name of the primitive to draw, either as a string or a Prims enum.
113
+ """
114
+ key = name.value if isinstance(name, Prims) else name
115
+ try:
116
+ prim = cls._primitives[key]
117
+ with prim.vao:
118
+ prim.vao.draw()
119
+ except KeyError:
120
+ logger.error(f"Failed to draw primitive {key}")
121
+ return
@@ -42,7 +42,7 @@ class Vec2:
42
42
  yield self.x
43
43
  yield self.y
44
44
 
45
- def clone(self) -> "Vec2":
45
+ def copy(self) -> "Vec2":
46
46
  """
47
47
  Create a copy of the vector.
48
48
  Returns:
@@ -305,9 +305,7 @@ class Vec2:
305
305
  if isinstance(rhs, (float, int)):
306
306
  return Vec2(self.x * rhs, self.y * rhs)
307
307
  else:
308
- raise ValueError(
309
- f"can only do piecewise multiplication with a scalar {rhs=}"
310
- )
308
+ raise ValueError(f"can only do piecewise multiplication with a scalar {rhs=}")
311
309
 
312
310
  def __rmul__(self, rhs):
313
311
  """
@@ -330,9 +328,8 @@ class Vec2:
330
328
  Vec2: A new vector that is the result of multiplying this vector by the matrix.
331
329
  """
332
330
  return Vec2(
333
- self.x * rhs.m[0][0] + self.y * rhs.m[1][0] + self.z * rhs.m[2][0],
334
- self.x * rhs.m[0][1] + self.y * rhs.m[1][1] + self.z * rhs.m[2][1],
335
- self.x * rhs.m[0][2] + self.y * rhs.m[1][2] + self.z * rhs.m[2][2],
331
+ self.x * rhs.m[0][0] + self.y * rhs.m[1][0],
332
+ self.x * rhs.m[0][1] + self.y * rhs.m[1][1],
336
333
  )
337
334
 
338
335
 
@@ -78,9 +78,9 @@ class Vec3:
78
78
  else:
79
79
  setattr(self, name, v)
80
80
 
81
- def clone(self) -> "Vec3":
81
+ def copy(self) -> "Vec3":
82
82
  """
83
- Create a clone of the current vector.
83
+ Create a copy of the current vector.
84
84
  Returns:
85
85
  Vec3: A new instance of Vec3 with the same x, y, and z values.
86
86
  """
@@ -156,11 +156,7 @@ class Vec3:
156
156
 
157
157
  if not isinstance(rhs, Vec3):
158
158
  return NotImplemented
159
- return (
160
- math.isclose(self.x, rhs.x)
161
- and math.isclose(self.y, rhs.y)
162
- and math.isclose(self.z, rhs.z)
163
- )
159
+ return math.isclose(self.x, rhs.x) and math.isclose(self.y, rhs.y) and math.isclose(self.z, rhs.z)
164
160
 
165
161
  def __neq__(self, rhs):
166
162
  """
@@ -173,11 +169,7 @@ class Vec3:
173
169
  """
174
170
  if not isinstance(rhs, Vec3):
175
171
  return NotImplemented
176
- return not (
177
- math.isclose(self.x, rhs.x)
178
- and math.isclose(self.y, rhs.y)
179
- and math.isclose(self.z, rhs.z)
180
- )
172
+ return not (math.isclose(self.x, rhs.x) and math.isclose(self.y, rhs.y) and math.isclose(self.z, rhs.z))
181
173
 
182
174
  def __neg__(self):
183
175
  """
@@ -290,9 +282,7 @@ class Vec3:
290
282
  """
291
283
  d = self.dot(n)
292
284
  # I - 2.0 * dot(N, I) * N
293
- return Vec3(
294
- self.x - 2.0 * d * n.x, self.y - 2.0 * d * n.y, self.z - 2.0 * d * n.z
295
- )
285
+ return Vec3(self.x - 2.0 * d * n.x, self.y - 2.0 * d * n.y, self.z - 2.0 * d * n.z)
296
286
 
297
287
  def clamp(self, low, high):
298
288
  """
@@ -324,13 +314,11 @@ class Vec3:
324
314
  """
325
315
  from .mat3 import Mat3
326
316
 
327
- return Mat3.from_list(
328
- [
329
- [self.x * rhs.x, self.x * rhs.y, self.x * rhs.z],
330
- [self.y * rhs.x, self.y * rhs.y, self.y * rhs.z],
331
- [self.z * rhs.x, self.z * rhs.y, self.z * rhs.z],
332
- ]
333
- )
317
+ return Mat3.from_list([
318
+ [self.x * rhs.x, self.x * rhs.y, self.x * rhs.z],
319
+ [self.y * rhs.x, self.y * rhs.y, self.y * rhs.z],
320
+ [self.z * rhs.x, self.z * rhs.y, self.z * rhs.z],
321
+ ])
334
322
 
335
323
  def __mul__(self, rhs):
336
324
  """
@@ -345,9 +333,7 @@ class Vec3:
345
333
  if isinstance(rhs, (float, int)):
346
334
  return Vec3(self.x * rhs, self.y * rhs, self.z * rhs)
347
335
  else:
348
- raise ValueError(
349
- f"can only do piecewise multiplication with a scalar {rhs=}"
350
- )
336
+ raise ValueError(f"can only do piecewise multiplication with a scalar {rhs=}")
351
337
 
352
338
  def __rmul__(self, rhs):
353
339
  """
@@ -65,7 +65,7 @@ class Vec4:
65
65
  except IndexError:
66
66
  raise IndexError("Index out of range. Valid indices are 0, 1, 2, and 3.")
67
67
 
68
- def clone(self) -> "Vec4":
68
+ def copy(self) -> "Vec4":
69
69
  """
70
70
  Create a copy of the vector.
71
71
  Returns:
@@ -192,22 +192,10 @@ class Vec4:
192
192
  def __matmul__(self, rhs):
193
193
  "Vec4 @ Mat4 matrix multiplication"
194
194
  return Vec4(
195
- self.x * rhs.m[0][0]
196
- + self.y * rhs.m[1][0]
197
- + self.z * rhs.m[2][0]
198
- + self.w * rhs.m[3][0],
199
- self.x * rhs.m[0][1]
200
- + self.y * rhs.m[1][1]
201
- + self.z * rhs.m[2][1]
202
- + self.w * rhs.m[3][1],
203
- self.x * rhs.m[0][2]
204
- + self.y * rhs.m[1][2]
205
- + self.z * rhs.m[2][2]
206
- + self.w * rhs.m[3][2],
207
- self.x * rhs.m[0][3]
208
- + self.y * rhs.m[1][3]
209
- + self.z * rhs.m[2][3]
210
- + self.w * rhs.m[3][3],
195
+ self.x * rhs.m[0][0] + self.y * rhs.m[1][0] + self.z * rhs.m[2][0] + self.w * rhs.m[3][0],
196
+ self.x * rhs.m[0][1] + self.y * rhs.m[1][1] + self.z * rhs.m[2][1] + self.w * rhs.m[3][1],
197
+ self.x * rhs.m[0][2] + self.y * rhs.m[1][2] + self.z * rhs.m[2][2] + self.w * rhs.m[3][2],
198
+ self.x * rhs.m[0][3] + self.y * rhs.m[1][3] + self.z * rhs.m[2][3] + self.w * rhs.m[3][3],
211
199
  )
212
200
 
213
201
  def __repr__(self):
@@ -1,219 +0,0 @@
1
- """
2
- OpenGL primitive generation and drawing functions
3
- In this class we can generate a pipeline for drawing our data for the most part it will be
4
- x,y,z nx,ny,nz and u,v data in a flat numpy array.
5
- We need to create the data first which is stored in a map as part of the class, we can then call draw
6
- which will generate a pipeline for this object and draw into the current context.
7
- """
8
-
9
- from typing import Dict, Union
10
-
11
- import numpy as np
12
- import OpenGL.GL as gl
13
-
14
- from .log import logger
15
- from .prim_data import PrimData, Prims
16
- from .simple_vao import VertexData
17
- from .vao_factory import VAOFactory, VAOType # noqa
18
- from .vec3 import Vec3
19
-
20
-
21
- class _primitive:
22
- """A private class to hold VAO data for a primitive."""
23
-
24
- def __init__(self, prim_data: np.ndarray):
25
- """
26
- Initializes the primitive with the given data.
27
-
28
- Args:
29
- prim_data: A numpy array containing the vertex data (x,y,z,nx,ny,nz,u,v).
30
- """
31
- self.vao = VAOFactory.create_vao(VAOType.SIMPLE, gl.GL_TRIANGLES)
32
- with self.vao:
33
- data = VertexData(data=prim_data.data, size=prim_data.size)
34
- self.vao.set_data(data)
35
- vert_data_size = 8 * 4 # 4 is sizeof float and 8 is x,y,z,nx,ny,nz,uv
36
- self.vao.set_vertex_attribute_pointer(0, 3, gl.GL_FLOAT, vert_data_size, 0)
37
- self.vao.set_vertex_attribute_pointer(1, 3, gl.GL_FLOAT, vert_data_size, Vec3.sizeof())
38
- self.vao.set_vertex_attribute_pointer(2, 2, gl.GL_FLOAT, vert_data_size, 2 * Vec3.sizeof())
39
- self.vao.set_num_indices(prim_data.size // 8)
40
-
41
-
42
- class Primitives:
43
- """A static class for creating and drawing primitives."""
44
-
45
- # this is effectively a static class so we can use it to store data
46
- # and generate pipelines for drawing
47
- _primitives: Dict[str, _primitive] = {}
48
- _loaded: bool = False
49
-
50
- @classmethod
51
- def load_default_primitives(cls) -> None:
52
- """Loads the default primitives from the PrimData directory."""
53
- logger.info("Loading default primitives...")
54
- if not cls._loaded:
55
- for p in Prims:
56
- prim_data = PrimData.primitive(p.value)
57
- prim = _primitive(prim_data)
58
- cls._primitives[p.value] = prim
59
- cls._loaded = True
60
-
61
- @classmethod
62
- def create_line_grid(cls, name: str, width: float, depth: float, steps: int) -> None:
63
- """
64
- Creates a line grid primitive.
65
-
66
- Args:
67
- name: The name of the primitive to create.
68
- width: The width of the grid.
69
- depth: The depth of the grid.
70
- steps: The number of steps in the grid.
71
- """
72
- # Convert the list to a NumPy array
73
- data_array = PrimData.line_grid(width, depth, steps)
74
- prim = _primitive(data_array)
75
- cls._primitives[name] = prim
76
-
77
- @classmethod
78
- def create_triangle_plane(cls, name: str, width: float, depth: float, w_p: int, d_p: int, v_n: Vec3) -> None:
79
- """
80
- Creates a triangle plane primitive.
81
-
82
- Args:
83
- name: The name of the primitive.
84
- width: The width of the plane.
85
- depth: The depth of the plane.
86
- w_p: The number of width partitions.
87
- d_p: The number of depth partitions.
88
- v_n: The normal vector for the plane.
89
- """
90
-
91
- data_array = PrimData.triangle_plane(width, depth, w_p, d_p, v_n)
92
- prim = _primitive(data_array)
93
- cls._primitives[name] = prim
94
-
95
- @classmethod
96
- def draw(cls, name: Union[str, Prims]) -> None:
97
- """
98
- Draws the specified primitive.
99
-
100
- Args:
101
- name: The name of the primitive to draw, either as a string or a Prims enum.
102
- """
103
- key = name.value if isinstance(name, Prims) else name
104
- try:
105
- prim = cls._primitives[key]
106
- with prim.vao:
107
- prim.vao.draw()
108
- except KeyError:
109
- logger.error(f"Failed to draw primitive {key}")
110
- return
111
-
112
- @classmethod
113
- def create_sphere(cls, name: str, radius: float, precision: int) -> None:
114
- """
115
- Creates a sphere primitive.
116
-
117
- Args:
118
- name: The name of the primitive.
119
- radius: The radius of the sphere.
120
- precision: The precision of the sphere (number of slices).
121
- """
122
-
123
- data_array = PrimData.sphere(radius, precision)
124
- prim = _primitive(data_array)
125
- cls._primitives[name] = prim
126
-
127
- @classmethod
128
- def create_cone(cls, name: str, base: float, height: float, slices: int, stacks: int) -> None:
129
- """
130
- Creates a cone primitive.
131
-
132
- Args:
133
- name: The name of the primitive.
134
- base: The radius of the cone's base.
135
- height: The height of the cone.
136
- slices: The number of divisions around the cone.
137
- stacks: The number of divisions along the cone's height.
138
- """
139
- data_array = PrimData.cone(base, height, slices, stacks)
140
- prim = _primitive(data_array)
141
- cls._primitives[name] = prim
142
-
143
- @classmethod
144
- def create_capsule(cls, name: str, radius: float, height: float, precision: int) -> None:
145
- """
146
- Creates a capsule primitive.
147
- The capsule is aligned along the y-axis.
148
- It is composed of a cylinder and two hemispherical caps.
149
- based on code from here https://code.google.com/p/rgine/source/browse/trunk/RGine/opengl/src/RGLShapes.cpp
150
- and adapted
151
-
152
- Args:
153
- name: The name of the primitive.
154
- radius: The radius of the capsule.
155
- height: The height of the capsule.
156
- precision: The precision of the capsule.
157
- """
158
-
159
- data_array = PrimData.capsule(radius, height, precision)
160
- prim = _primitive(data_array)
161
- cls._primitives[name] = prim
162
-
163
- @classmethod
164
- def create_cylinder(cls, name: str, radius: float, height: float, slices: int, stacks: int) -> None:
165
- """
166
- Creates a cylinder primitive.
167
- The cylinder is aligned along the y-axis.
168
- This method generates the cylinder walls, but not the top and bottom caps.
169
-
170
- Args:
171
- name: The name of the primitive.
172
- radius: The radius of the cylinder.
173
- height: The height of the cylinder.
174
- slices: The number of slices.
175
- stacks: The number of stacks.
176
- """
177
-
178
- data_array = PrimData.cylinder(radius, height, slices, stacks)
179
- prim = _primitive(data_array)
180
- cls._primitives[name] = prim
181
-
182
- @classmethod
183
- def create_disk(cls, name: str, radius: float, slices: int) -> None:
184
- """
185
- Creates a disk primitive.
186
-
187
- Args:
188
- name: The name of the primitive.
189
- radius: The radius of the disk.
190
- slices: The number of slices to divide the disk into.
191
- """
192
-
193
- data_array = PrimData.disk(radius, slices)
194
- prim = _primitive(data_array)
195
- cls._primitives[name] = prim
196
-
197
- @classmethod
198
- def create_torus(
199
- cls,
200
- name: str,
201
- minor_radius: float,
202
- major_radius: float,
203
- sides: int,
204
- rings: int,
205
- ) -> None:
206
- """
207
- Creates a torus primitive.
208
-
209
- Args:
210
- name: The name of the primitive.
211
- minor_radius: The minor radius of the torus.
212
- major_radius: The major radius of the torus.
213
- sides: The number of sides for each ring.
214
- rings: The number of rings for the torus.
215
- """
216
-
217
- data_array = PrimData.torus(minor_radius, major_radius, sides, rings)
218
- prim = _primitive(data_array)
219
- cls._primitives[name] = prim
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes