ncca-ngl 0.1.4__py3-none-any.whl → 0.2.1__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.
@@ -105,7 +105,9 @@ class ShaderProgram:
105
105
  if is_array:
106
106
  for element_idx in range(size):
107
107
  element_name = f"{base_name}[{element_idx}]"
108
- element_location = gl.glGetUniformLocation(self._id, element_name.encode("utf-8"))
108
+ element_location = gl.glGetUniformLocation(
109
+ self._id, element_name.encode("utf-8")
110
+ )
109
111
  if element_location != -1:
110
112
  # Store individual array element: (location, shader_type, 1, False)
111
113
  self._uniforms[element_name] = (
@@ -120,7 +122,9 @@ class ShaderProgram:
120
122
  logger.info(
121
123
  f"Registered array uniform: {base_name}[{size}] (type: {self.get_gl_type_string(shader_type)}, location: {location})"
122
124
  )
123
- logger.info(f" Also registered individual elements: {base_name}[0] to {base_name}[{size - 1}]")
125
+ logger.info(
126
+ f" Also registered individual elements: {base_name}[0] to {base_name}[{size - 1}]"
127
+ )
124
128
  else:
125
129
  logger.info(
126
130
  f"Registered uniform: {base_name} (type: {self.get_gl_type_string(shader_type)}, location: {location})"
@@ -143,8 +147,14 @@ class ShaderProgram:
143
147
  name_buffer = (ctypes.c_char * 256)()
144
148
  length = ctypes.c_int()
145
149
 
146
- gl.glGetActiveUniformBlockName(self._id, i, 256, ctypes.byref(length), name_buffer)
147
- name_str = name_buffer.value.decode("utf-8") if name_buffer.value else f"UniformBlock_{i}"
150
+ gl.glGetActiveUniformBlockName(
151
+ self._id, i, 256, ctypes.byref(length), name_buffer
152
+ )
153
+ name_str = (
154
+ name_buffer.value.decode("utf-8")
155
+ if name_buffer.value
156
+ else f"UniformBlock_{i}"
157
+ )
148
158
 
149
159
  # Create uniform block data structure
150
160
  data = {
@@ -242,7 +252,9 @@ class ShaderProgram:
242
252
  bool: True if successful, False otherwise
243
253
  """
244
254
  if uniform_block_name not in self._registered_uniform_blocks:
245
- logger.error(f"Uniform block '{uniform_block_name}' not found in shader '{self._name}'")
255
+ logger.error(
256
+ f"Uniform block '{uniform_block_name}' not found in shader '{self._name}'"
257
+ )
246
258
  return False
247
259
 
248
260
  block = self._registered_uniform_blocks[uniform_block_name]
@@ -295,11 +307,17 @@ class ShaderProgram:
295
307
  elif isinstance(val, float):
296
308
  gl.glUniform1f(loc, val)
297
309
  elif isinstance(val, Mat2):
298
- gl.glUniformMatrix2fv(loc, 1, gl.GL_FALSE, (ctypes.c_float * 4)(*val.get_matrix()))
310
+ gl.glUniformMatrix2fv(
311
+ loc, 1, gl.GL_FALSE, (ctypes.c_float * 4)(*val.get_matrix())
312
+ )
299
313
  elif isinstance(val, Mat3):
300
- gl.glUniformMatrix3fv(loc, 1, gl.GL_FALSE, (ctypes.c_float * 9)(*val.get_matrix()))
314
+ gl.glUniformMatrix3fv(
315
+ loc, 1, gl.GL_FALSE, (ctypes.c_float * 9)(*val.get_matrix())
316
+ )
301
317
  elif isinstance(val, Mat4):
302
- gl.glUniformMatrix4fv(loc, 1, gl.GL_FALSE, (ctypes.c_float * 16)(*val.get_matrix()))
318
+ gl.glUniformMatrix4fv(
319
+ loc, 1, gl.GL_FALSE, (ctypes.c_float * 16)(*val.get_matrix())
320
+ )
303
321
  elif isinstance(val, Vec2):
304
322
  gl.glUniform2f(loc, *val)
305
323
  elif isinstance(val, Vec3):
@@ -310,13 +328,21 @@ class ShaderProgram:
310
328
  try:
311
329
  val = list(value[0])
312
330
  if len(val) == 4:
313
- gl.glUniformMatrix2fv(loc, 1, gl.GL_FALSE, (ctypes.c_float * 4)(*val))
331
+ gl.glUniformMatrix2fv(
332
+ loc, 1, gl.GL_FALSE, (ctypes.c_float * 4)(*val)
333
+ )
314
334
  elif len(val) == 9:
315
- gl.glUniformMatrix3fv(loc, 1, gl.GL_FALSE, (ctypes.c_float * 9)(*val))
335
+ gl.glUniformMatrix3fv(
336
+ loc, 1, gl.GL_FALSE, (ctypes.c_float * 9)(*val)
337
+ )
316
338
  elif len(val) == 16:
317
- gl.glUniformMatrix4fv(loc, 1, gl.GL_FALSE, (ctypes.c_float * 16)(*val))
339
+ gl.glUniformMatrix4fv(
340
+ loc, 1, gl.GL_FALSE, (ctypes.c_float * 16)(*val)
341
+ )
318
342
  except TypeError:
319
- logger.warning(f"Warning: uniform '{name}' has unknown type: {type(val)}")
343
+ logger.warning(
344
+ f"Warning: uniform '{name}' has unknown type: {type(val)}"
345
+ )
320
346
 
321
347
  elif len(value) == 2:
322
348
  if isinstance(value[0], int):
@@ -359,7 +385,9 @@ class ShaderProgram:
359
385
  loc = self.get_uniform_location(name)
360
386
  if loc != -1:
361
387
  flat_values = [item for vec in values for item in vec]
362
- gl.glUniform2fv(loc, len(values), (ctypes.c_float * len(flat_values))(*flat_values))
388
+ gl.glUniform2fv(
389
+ loc, len(values), (ctypes.c_float * len(flat_values))(*flat_values)
390
+ )
363
391
 
364
392
  def set_uniform_3fv(self, name: str, values: List[List[float]]) -> None:
365
393
  """
@@ -373,7 +401,9 @@ class ShaderProgram:
373
401
  loc = self.get_uniform_location(name)
374
402
  if loc != -1:
375
403
  flat_values = [item for vec in values for item in vec]
376
- gl.glUniform3fv(loc, len(values), (ctypes.c_float * len(flat_values))(*flat_values))
404
+ gl.glUniform3fv(
405
+ loc, len(values), (ctypes.c_float * len(flat_values))(*flat_values)
406
+ )
377
407
 
378
408
  def set_uniform_4fv(self, name: str, values: List[List[float]]) -> None:
379
409
  """
@@ -387,7 +417,9 @@ class ShaderProgram:
387
417
  loc = self.get_uniform_location(name)
388
418
  if loc != -1:
389
419
  flat_values = [item for vec in values for item in vec]
390
- gl.glUniform4fv(loc, len(values), (ctypes.c_float * len(flat_values))(*flat_values))
420
+ gl.glUniform4fv(
421
+ loc, len(values), (ctypes.c_float * len(flat_values))(*flat_values)
422
+ )
391
423
 
392
424
  def set_uniform_1iv(self, name: str, values: List[int]) -> None:
393
425
  """
@@ -696,19 +728,121 @@ class ShaderProgram:
696
728
  str: Human-readable type string
697
729
  """
698
730
  type_map = {
731
+ # Scalars
699
732
  gl.GL_FLOAT: "float",
700
- gl.GL_FLOAT_VEC2: "vec2",
701
- gl.GL_FLOAT_VEC3: "vec3",
702
- gl.GL_FLOAT_VEC4: "vec4",
703
733
  gl.GL_DOUBLE: "double",
704
734
  gl.GL_INT: "int",
705
- gl.GL_UNSIGNED_INT: "unsigned int",
735
+ gl.GL_UNSIGNED_INT: "uint",
706
736
  gl.GL_BOOL: "bool",
737
+ # Float vectors
738
+ gl.GL_FLOAT_VEC2: "vec2",
739
+ gl.GL_FLOAT_VEC3: "vec3",
740
+ gl.GL_FLOAT_VEC4: "vec4",
741
+ # Double vectors
742
+ gl.GL_DOUBLE_VEC2: "dvec2",
743
+ gl.GL_DOUBLE_VEC3: "dvec3",
744
+ gl.GL_DOUBLE_VEC4: "dvec4",
745
+ # Integer vectors
746
+ gl.GL_INT_VEC2: "ivec2",
747
+ gl.GL_INT_VEC3: "ivec3",
748
+ gl.GL_INT_VEC4: "ivec4",
749
+ # Unsigned int vectors
750
+ gl.GL_UNSIGNED_INT_VEC2: "uvec2",
751
+ gl.GL_UNSIGNED_INT_VEC3: "uvec3",
752
+ gl.GL_UNSIGNED_INT_VEC4: "uvec4",
753
+ # Bool vectors
754
+ gl.GL_BOOL_VEC2: "bvec2",
755
+ gl.GL_BOOL_VEC3: "bvec3",
756
+ gl.GL_BOOL_VEC4: "bvec4",
757
+ # Float matrices
707
758
  gl.GL_FLOAT_MAT2: "mat2",
708
759
  gl.GL_FLOAT_MAT3: "mat3",
709
760
  gl.GL_FLOAT_MAT4: "mat4",
761
+ gl.GL_FLOAT_MAT2x3: "mat2x3",
762
+ gl.GL_FLOAT_MAT2x4: "mat2x4",
763
+ gl.GL_FLOAT_MAT3x2: "mat3x2",
764
+ gl.GL_FLOAT_MAT3x4: "mat3x4",
765
+ gl.GL_FLOAT_MAT4x2: "mat4x2",
766
+ gl.GL_FLOAT_MAT4x3: "mat4x3",
767
+ # Double matrices
768
+ gl.GL_DOUBLE_MAT2: "dmat2",
769
+ gl.GL_DOUBLE_MAT3: "dmat3",
770
+ gl.GL_DOUBLE_MAT4: "dmat4",
771
+ gl.GL_DOUBLE_MAT2x3: "dmat2x3",
772
+ gl.GL_DOUBLE_MAT2x4: "dmat2x4",
773
+ gl.GL_DOUBLE_MAT3x2: "dmat3x2",
774
+ gl.GL_DOUBLE_MAT3x4: "dmat3x4",
775
+ gl.GL_DOUBLE_MAT4x2: "dmat4x2",
776
+ gl.GL_DOUBLE_MAT4x3: "dmat4x3",
777
+ # Samplers (float)
778
+ gl.GL_SAMPLER_1D: "sampler1D",
710
779
  gl.GL_SAMPLER_2D: "sampler2D",
780
+ gl.GL_SAMPLER_3D: "sampler3D",
711
781
  gl.GL_SAMPLER_CUBE: "samplerCube",
782
+ gl.GL_SAMPLER_1D_SHADOW: "sampler1DShadow",
783
+ gl.GL_SAMPLER_2D_SHADOW: "sampler2DShadow",
784
+ gl.GL_SAMPLER_1D_ARRAY: "sampler1DArray",
785
+ gl.GL_SAMPLER_2D_ARRAY: "sampler2DArray",
786
+ gl.GL_SAMPLER_1D_ARRAY_SHADOW: "sampler1DArrayShadow",
787
+ gl.GL_SAMPLER_2D_ARRAY_SHADOW: "sampler2DArrayShadow",
788
+ gl.GL_SAMPLER_CUBE_SHADOW: "samplerCubeShadow",
789
+ gl.GL_SAMPLER_BUFFER: "samplerBuffer",
790
+ gl.GL_SAMPLER_2D_RECT: "sampler2DRect",
791
+ gl.GL_SAMPLER_2D_RECT_SHADOW: "sampler2DRectShadow",
792
+ # Samplers (int)
793
+ gl.GL_INT_SAMPLER_1D: "isampler1D",
794
+ gl.GL_INT_SAMPLER_2D: "isampler2D",
795
+ gl.GL_INT_SAMPLER_3D: "isampler3D",
796
+ gl.GL_INT_SAMPLER_CUBE: "isamplerCube",
797
+ gl.GL_INT_SAMPLER_1D_ARRAY: "isampler1DArray",
798
+ gl.GL_INT_SAMPLER_2D_ARRAY: "isampler2DArray",
799
+ gl.GL_INT_SAMPLER_BUFFER: "isamplerBuffer",
800
+ gl.GL_INT_SAMPLER_2D_RECT: "isampler2DRect",
801
+ # Samplers (unsigned int)
802
+ gl.GL_UNSIGNED_INT_SAMPLER_1D: "usampler1D",
803
+ gl.GL_UNSIGNED_INT_SAMPLER_2D: "usampler2D",
804
+ gl.GL_UNSIGNED_INT_SAMPLER_3D: "usampler3D",
805
+ gl.GL_UNSIGNED_INT_SAMPLER_CUBE: "usamplerCube",
806
+ gl.GL_UNSIGNED_INT_SAMPLER_1D_ARRAY: "usampler1DArray",
807
+ gl.GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: "usampler2DArray",
808
+ gl.GL_UNSIGNED_INT_SAMPLER_BUFFER: "usamplerBuffer",
809
+ gl.GL_UNSIGNED_INT_SAMPLER_2D_RECT: "usampler2DRect",
810
+ # Images (float)
811
+ gl.GL_IMAGE_1D: "image1D",
812
+ gl.GL_IMAGE_2D: "image2D",
813
+ gl.GL_IMAGE_3D: "image3D",
814
+ gl.GL_IMAGE_2D_RECT: "image2DRect",
815
+ gl.GL_IMAGE_CUBE: "imageCube",
816
+ gl.GL_IMAGE_BUFFER: "imageBuffer",
817
+ gl.GL_IMAGE_1D_ARRAY: "image1DArray",
818
+ gl.GL_IMAGE_2D_ARRAY: "image2DArray",
819
+ gl.GL_IMAGE_CUBE_MAP_ARRAY: "imageCubeArray",
820
+ gl.GL_IMAGE_2D_MULTISAMPLE: "image2DMS",
821
+ gl.GL_IMAGE_2D_MULTISAMPLE_ARRAY: "image2DMSArray",
822
+ # Images (int)
823
+ gl.GL_INT_IMAGE_1D: "iimage1D",
824
+ gl.GL_INT_IMAGE_2D: "iimage2D",
825
+ gl.GL_INT_IMAGE_3D: "iimage3D",
826
+ gl.GL_INT_IMAGE_2D_RECT: "iimage2DRect",
827
+ gl.GL_INT_IMAGE_CUBE: "iimageCube",
828
+ gl.GL_INT_IMAGE_BUFFER: "iimageBuffer",
829
+ gl.GL_INT_IMAGE_1D_ARRAY: "iimage1DArray",
830
+ gl.GL_INT_IMAGE_2D_ARRAY: "iimage2DArray",
831
+ gl.GL_INT_IMAGE_CUBE_MAP_ARRAY: "iimageCubeArray",
832
+ gl.GL_INT_IMAGE_2D_MULTISAMPLE: "iimage2DMS",
833
+ gl.GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY: "iimage2DMSArray",
834
+ # Images (unsigned int)
835
+ gl.GL_UNSIGNED_INT_IMAGE_1D: "uimage1D",
836
+ gl.GL_UNSIGNED_INT_IMAGE_2D: "uimage2D",
837
+ gl.GL_UNSIGNED_INT_IMAGE_3D: "uimage3D",
838
+ gl.GL_UNSIGNED_INT_IMAGE_2D_RECT: "uimage2DRect",
839
+ gl.GL_UNSIGNED_INT_IMAGE_CUBE: "uimageCube",
840
+ gl.GL_UNSIGNED_INT_IMAGE_BUFFER: "uimageBuffer",
841
+ gl.GL_UNSIGNED_INT_IMAGE_1D_ARRAY: "uimage1DArray",
842
+ gl.GL_UNSIGNED_INT_IMAGE_2D_ARRAY: "uimage2DArray",
843
+ gl.GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY: "uimageCubeArray",
844
+ gl.GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE: "uimage2DMS",
845
+ gl.GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY: "uimage2DMSArray",
712
846
  }
713
847
  return type_map.get(gl_type, f"Unknown type {gl_type}")
714
848
 
@@ -727,7 +861,9 @@ class ShaderProgram:
727
861
  base_name = name.split("[")[0]
728
862
  if base_name not in array_elements:
729
863
  array_elements[base_name] = []
730
- array_elements[base_name].append((name, location, uniform_type, size, is_array))
864
+ array_elements[base_name].append(
865
+ (name, location, uniform_type, size, is_array)
866
+ )
731
867
  else:
732
868
  base_uniforms[name] = (location, uniform_type, size, is_array)
733
869
 
@@ -735,7 +871,9 @@ class ShaderProgram:
735
871
  for name, (location, uniform_type, size, is_array) in base_uniforms.items():
736
872
  type_str = self.get_gl_type_string(uniform_type)
737
873
  if is_array:
738
- logger.info(f" {name}[{size}] (type: {type_str}, location: {location})")
874
+ logger.info(
875
+ f" {name}[{size}] (type: {type_str}, location: {location})"
876
+ )
739
877
  else:
740
878
  logger.info(f" {name} (type: {type_str}, location: {location})")
741
879
 
@@ -744,7 +882,9 @@ class ShaderProgram:
744
882
  logger.info(f" Array elements for {base_name}:")
745
883
  for element_name, location, uniform_type, size, is_array in elements:
746
884
  type_str = self.get_gl_type_string(uniform_type)
747
- logger.info(f" {element_name} (type: {type_str}, location: {location})")
885
+ logger.info(
886
+ f" {element_name} (type: {type_str}, location: {location})"
887
+ )
748
888
 
749
889
  def print_registered_uniform_blocks(self) -> None:
750
890
  """
@@ -782,4 +922,6 @@ class ShaderProgram:
782
922
  if self._registered_uniform_blocks:
783
923
  logger.info(" Registered uniform blocks:")
784
924
  for name, data in self._registered_uniform_blocks.items():
785
- logger.info(f" {name} (index: {data['loc']}, buffer: {data['buffer']})")
925
+ logger.info(
926
+ f" {name} (index: {data['loc']}, buffer: {data['buffer']})"
927
+ )
ncca/ngl/text.py CHANGED
@@ -227,7 +227,9 @@ class _Text:
227
227
  ShaderLib.set_uniform("fontSize", 1.0)
228
228
  ShaderLib.set_uniform("textColour", 1.0, 1.0, 1.0, 1.0)
229
229
 
230
- def render_text(self, font: str, x: int, y: int, text: str, colour: Vec3 = Vec3(1.0, 1.0, 1.0)) -> None:
230
+ def render_text(
231
+ self, font: str, x: int, y: int, text: str, colour: Vec3 = Vec3(1.0, 1.0, 1.0)
232
+ ) -> None:
231
233
  """
232
234
  Renders a string of text to the screen.
233
235
 
@@ -274,7 +276,9 @@ class _Text:
274
276
  gl.glActiveTexture(gl.GL_TEXTURE0)
275
277
  gl.glBindTexture(gl.GL_TEXTURE_2D, atlas.texture)
276
278
  ShaderLib.use(DefaultShader.TEXT)
277
- ShaderLib.set_uniform("textColour", float(colour.x), float(colour.y), float(colour.z), 1.0)
279
+ ShaderLib.set_uniform(
280
+ "textColour", float(colour.x), float(colour.y), float(colour.z), 1.0
281
+ )
278
282
  # We are drawing one point per character
279
283
  vao.set_num_indices(len(render_data) // 8)
280
284
  vao.draw()
@@ -286,7 +290,9 @@ class _Text:
286
290
  if polygon_mode != gl.GL_FILL:
287
291
  gl.glPolygonMode(gl.GL_FRONT_AND_BACK, polygon_mode)
288
292
 
289
- def _build_instances(self, font: str, text: str, start_x: int, start_y: int) -> List[float]:
293
+ def _build_instances(
294
+ self, font: str, text: str, start_x: int, start_y: int
295
+ ) -> List[float]:
290
296
  """
291
297
  Generates vertex attribute data for each character in a string.
292
298
 
ncca/ngl/util.py CHANGED
@@ -3,6 +3,7 @@
3
3
  Most of these functions are based on functions found in other libraries such as GLM, NGL or GLU
4
4
  """
5
5
 
6
+ import enum
6
7
  import math
7
8
 
8
9
  from .mat4 import Mat4
@@ -44,7 +45,32 @@ def look_at(eye, look, up):
44
45
  return result
45
46
 
46
47
 
47
- def perspective(fov, aspect, near, far):
48
+ class PerspMode(enum.Enum):
49
+ OpenGL = "OpenGL"
50
+ WebGPU = "WebGPU"
51
+ Vulkan = "Vulkan"
52
+
53
+
54
+ def perspective(
55
+ fov: float,
56
+ aspect: float,
57
+ near: float,
58
+ far: float,
59
+ mode: PerspMode = PerspMode.OpenGL,
60
+ ) -> Mat4:
61
+ """
62
+ Calculate a perspective matrix for various 3D graphics API's default mode is OpenGL but will covert for Vulkan and Web GPU if
63
+ required.
64
+
65
+ Args :
66
+ fov : float - Field of view angle in degrees.
67
+ aspect : float - Aspect ratio of the viewport.
68
+ near : float - Near clipping plane distance.
69
+ far : float - Far clipping plane distance.
70
+
71
+ Returns:
72
+ Mat4 - The perspective matrix.
73
+ """
48
74
  m = Mat4.zero() # as per glm
49
75
  _range = math.tan(math.radians(fov / 2.0)) * near
50
76
  left = -_range * aspect
@@ -53,34 +79,36 @@ def perspective(fov, aspect, near, far):
53
79
  top = _range
54
80
  m.m[0][0] = (2.0 * near) / (right - left)
55
81
  m.m[1][1] = (2.0 * near) / (top - bottom)
56
- m.m[2][2] = -(far + near) / (far - near)
57
- m.m[2][3] = -1.0
58
- m.m[3][2] = -(2.0 * far * near) / (far - near)
82
+ match mode:
83
+ case PerspMode.OpenGL:
84
+ m.m[2][2] = -(far + near) / (far - near)
85
+ m.m[2][3] = -1.0
86
+ m.m[3][2] = -(2.0 * far * near) / (far - near)
87
+
88
+ # This ensures the clip space Z range is [0, 1] as required by Vulkan and WebGPU.
89
+ case PerspMode.WebGPU | PerspMode.Vulkan:
90
+ m.m[2][2] = -far / (far - near)
91
+ m.m[2][3] = -1.0
92
+ m.m[3][2] = -(far * near) / (far - near)
59
93
  return m
60
94
 
61
95
 
62
- def ortho(left, right, bottom, top, near, far):
63
- """Create an orthographic projection matrix."""
96
+ def ortho(left, right, bottom, top, near, far, mode=PerspMode.OpenGL):
64
97
  m = Mat4.identity()
65
98
  m.m[0][0] = 2.0 / (right - left)
66
99
  m.m[1][1] = 2.0 / (top - bottom)
67
- m.m[2][2] = -2.0 / (far - near)
100
+ match mode:
101
+ case PerspMode.OpenGL:
102
+ m.m[2][2] = -2.0 / (far - near)
103
+ m.m[3][2] = -(far + near) / (far - near)
104
+ case PerspMode.WebGPU | PerspMode.Vulkan:
105
+ m.m[2][2] = -1.0 / (far - near)
106
+ m.m[3][2] = -near / (far - near)
68
107
  m.m[3][0] = -(right + left) / (right - left)
69
108
  m.m[3][1] = -(top + bottom) / (top - bottom)
70
- m.m[3][2] = -(far + near) / (far - near)
71
109
  return m
72
110
 
73
111
 
74
- # Mat4 result(1.0f);
75
- # result.m_00= 2.0f / (_right - _left);
76
- # result.m_11= 2.0f / (_top - _bottom);
77
- # result.m_22= - 2.0f / (_zFar - _zNear);
78
- # result.m_30= - (_right + _left) / (_right - _left);
79
- # result.m_31= - (_top + _bottom) / (_top - _bottom);
80
- # result.m_32= - (_zFar + _zNear) / (_zFar - _zNear);
81
- # return result;
82
-
83
-
84
112
  def frustum(left, right, bottom, top, near, far):
85
113
  """Create a frustum projection matrix."""
86
114
  m = Mat4.zero()
ncca/ngl/vec2.py CHANGED
@@ -305,7 +305,9 @@ 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(f"can only do piecewise multiplication with a scalar {rhs=}")
308
+ raise ValueError(
309
+ f"can only do piecewise multiplication with a scalar {rhs=}"
310
+ )
309
311
 
310
312
  def __rmul__(self, rhs):
311
313
  """
ncca/ngl/vec3.py CHANGED
@@ -156,7 +156,11 @@ class Vec3:
156
156
 
157
157
  if not isinstance(rhs, Vec3):
158
158
  return NotImplemented
159
- return math.isclose(self.x, rhs.x) and math.isclose(self.y, rhs.y) and math.isclose(self.z, rhs.z)
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
+ )
160
164
 
161
165
  def __neq__(self, rhs):
162
166
  """
@@ -169,7 +173,11 @@ class Vec3:
169
173
  """
170
174
  if not isinstance(rhs, Vec3):
171
175
  return NotImplemented
172
- return not (math.isclose(self.x, rhs.x) and math.isclose(self.y, rhs.y) and math.isclose(self.z, rhs.z))
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
+ )
173
181
 
174
182
  def __neg__(self):
175
183
  """
@@ -282,7 +290,9 @@ class Vec3:
282
290
  """
283
291
  d = self.dot(n)
284
292
  # I - 2.0 * dot(N, I) * N
285
- return Vec3(self.x - 2.0 * d * n.x, self.y - 2.0 * d * n.y, self.z - 2.0 * d * n.z)
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
+ )
286
296
 
287
297
  def clamp(self, low, high):
288
298
  """
@@ -314,11 +324,13 @@ class Vec3:
314
324
  """
315
325
  from .mat3 import Mat3
316
326
 
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
- ])
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
+ )
322
334
 
323
335
  def __mul__(self, rhs):
324
336
  """
@@ -333,7 +345,9 @@ class Vec3:
333
345
  if isinstance(rhs, (float, int)):
334
346
  return Vec3(self.x * rhs, self.y * rhs, self.z * rhs)
335
347
  else:
336
- raise ValueError(f"can only do piecewise multiplication with a scalar {rhs=}")
348
+ raise ValueError(
349
+ f"can only do piecewise multiplication with a scalar {rhs=}"
350
+ )
337
351
 
338
352
  def __rmul__(self, rhs):
339
353
  """
ncca/ngl/vec4.py CHANGED
@@ -192,10 +192,22 @@ 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] + 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],
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],
199
211
  )
200
212
 
201
213
  def __repr__(self):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: ncca-ngl
3
- Version: 0.1.4
3
+ Version: 0.2.1
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>
@@ -15,8 +15,8 @@ ncca/ngl/PrimData/pack_arrays.py,sha256=aWShJX8QPHXKTj66C8yu1DskmD3VEzFXyaADcxw6
15
15
  ncca/ngl/PrimData/teapot.npy,sha256=fiOfYtB5SkegO7uTSitpjl_HmnS_iIy0sXAGfxCXXjY,1350560
16
16
  ncca/ngl/PrimData/tetrahedron.npy,sha256=_KCSpflFXhYB4gGVxFmF5Cv6pQyPHuUlCj9xfL2oyEM,512
17
17
  ncca/ngl/PrimData/troll.npy,sha256=ohgGgxLCJrmsFdNrlfRY2Rg9eJgcmvArf6IAspO2BKA,3505280
18
- ncca/ngl/__init__.py,sha256=i01MBdh814MrDmPDvG4dPI6azBWZWTq212cfVNnKkR8,2308
19
- ncca/ngl/abstract_vao.py,sha256=fi7-BIfw1jefcXe09Qj2gGmnqqA9kzJK-hAwfG14Hrc,2068
18
+ ncca/ngl/__init__.py,sha256=tyDe5m-1jd51kIOU-f2m1kU0XU10mebwrQ3td0Wdhko,2543
19
+ ncca/ngl/abstract_vao.py,sha256=VLKp3pmPYK_dQgEImMOAQ0DufAswK_0H4DR4r8flp2U,2104
20
20
  ncca/ngl/base_mesh.py,sha256=2JmVT5_bvgLHra1VnwRld-mh-20IqqekgEu1dbGU1a4,5736
21
21
  ncca/ngl/base_mesh.pyi,sha256=kobLuNnCSZlRRobIgVopQaS7Bjg0tJ3m4M64WXt5I-M,173
22
22
  ncca/ngl/bbox.py,sha256=PylB6ju_bkdDUqQkzO1n2E-jsmxiviNkyBLY-sN59n8,6578
@@ -30,13 +30,14 @@ ncca/ngl/mat4.py,sha256=eGvmLfw_wwKuuVh29wAKrvSZJB41jgmcYV5EufzyXbo,17273
30
30
  ncca/ngl/multi_buffer_vao.py,sha256=cuNE6gSrqkNcYvfIOYOZp4MVnpCvChUgnzsf7b60pWg,1752
31
31
  ncca/ngl/obj.py,sha256=AGldNouHrkrDs2UhATClGkgo4dzr6lzArR4YeCxQKmo,13667
32
32
  ncca/ngl/plane.py,sha256=96WuGzexYKhoeRVevGP2pZcustt9fzyyAjuwJHT25tk,1299
33
- ncca/ngl/primitives.py,sha256=G4X5kPROgcO2hZf8YkYvviS5C2kPLXrlSerJUdD6Fog,22575
33
+ ncca/ngl/prim_data.py,sha256=Y-Y748_3-VgimuUlbengPyJvZIJQAPBFmnlMbsLPCVU,18853
34
+ ncca/ngl/primitives.py,sha256=YitjEsxDKo94mLeYclDOeG41ZVr9VM9TGhMCiKqGAgs,7651
34
35
  ncca/ngl/pyside_event_handling_mixin.py,sha256=L8obXeTp-g2Va2eXyd1hnmSp-sY7p4GX6EcFYRnH1F4,10588
35
- ncca/ngl/quaternion.py,sha256=MeQ-oxufo96TJ1GusRdpaHJsjfD6hG1ADsqTiBbHxlM,3814
36
+ ncca/ngl/quaternion.py,sha256=agmbW8i125FyLOV2Z9SpTY5yQwmnnm0rxQawwHqq1YI,3858
36
37
  ncca/ngl/random.py,sha256=wX1R2rMpb76TP4rk44NUp5XoVuMisH9d-eBG5kFBZsM,5579
37
38
  ncca/ngl/shader.py,sha256=fEz8R_itsQssIxQp1E8-PhY3aOaTdm7sXpyFYoARSic,7696
38
39
  ncca/ngl/shader_lib.py,sha256=YmF3EJM9roTEt5OI5sHonAVN_ydIseyiOUBFZTX4KdA,18627
39
- ncca/ngl/shader_program.py,sha256=Yuq7RMsa__MWWZWDFz1J7g9Z9Gi2CjTq9y2F0Qf9rhk,27959
40
+ ncca/ngl/shader_program.py,sha256=WNEUOl4N4giC6caC0uMXm5ikDUtzCuZl7dqZl4M7p6k,33655
40
41
  ncca/ngl/shaders/checker_fragment.glsl,sha256=2hJH8yOJxLH5DdDdS15C3uom4o4YsiBle0fIYLkx9jI,640
41
42
  ncca/ngl/shaders/checker_vertex.glsl,sha256=G90GDAY5yEsdYMHhpZhWTmFFx_jfpDUexam-vpuVrXo,411
42
43
  ncca/ngl/shaders/colour_fragment.glsl,sha256=Y8CeWyDyQAK7u3-rQhURO6Ee3ibturZR3B75e5vcb2U,118
@@ -48,17 +49,17 @@ ncca/ngl/shaders/text_geometry.glsl,sha256=OTLdn4pdZj2BOMh33rE6JBfQ9SHQ1L1e8qn3H
48
49
  ncca/ngl/shaders/text_vertex.glsl,sha256=uPym1x87SJOd0E3zPN1Fx44warJ6IYfvhzPQEtLOO3w,289
49
50
  ncca/ngl/simple_index_vao.py,sha256=1IVy1WQH4V8_viZbRoIMbDRJsiH7iAhw0GEWUV9KpAU,2338
50
51
  ncca/ngl/simple_vao.py,sha256=jfU2O3yliaM6iWNvfcRbjQ6o2_IVSPrOR3GthDiul6Q,1419
51
- ncca/ngl/text.py,sha256=6vIfMKuP3WWSehR9RDK7YF_jgxKz_istVv8dSlPMjYo,13550
52
+ ncca/ngl/text.py,sha256=yWNfKHnuWn0bxbwhW1H-EkRZ7bEM9DAyjES16cxTnME,13608
52
53
  ncca/ngl/texture.py,sha256=OgBBEItgUDohCsVWgmjEWcQWBJaXl9w070PTOOywPx4,2303
53
54
  ncca/ngl/transform.py,sha256=_PibgtFoU_exfvQUWucmts0WF5OreSTNbftvSa3zT8g,2938
54
- ncca/ngl/util.py,sha256=RLgGmxTq4gzlMKdAfLrO3gtV8VUSP5WtQK4hyLV6waQ,3558
55
+ ncca/ngl/util.py,sha256=8jp5vTVuGfVHMSktFEubtoaQ8SvLIQtM2UNbUeMTOFk,4372
55
56
  ncca/ngl/vao_factory.py,sha256=v87VfrUMaoqcsE-CS9kM7h5Fyk_e0LGl_iA6xqaomPg,930
56
- ncca/ngl/vec2.py,sha256=hJ0RWBxmeh-OOro_Y9lKocgiuu0f9vxp6L2_6vKfwUQ,10331
57
+ ncca/ngl/vec2.py,sha256=3bhd03y5E3HRnBdXJZ4xMsTMMAte5IEr6u4qqWT_UL4,10361
57
58
  ncca/ngl/vec2_array.py,sha256=7QRgXh75fORsmNnSnNxNQWk6_rnDgfmRX3tmJZ4ES9E,3420
58
- ncca/ngl/vec3.py,sha256=q4HI4y4Xk3lTdlB8YdF4T2mCdwK2jXRattjDHlJi7vg,12265
59
+ ncca/ngl/vec3.py,sha256=ntgqB3sc_jzcGO5vlHKgDqloOoMkykVcWPxpYdWFy5Q,12449
59
60
  ncca/ngl/vec3_array.py,sha256=fLRC8k0TwcaU7CnR2GmJ0prud4dcvvUX0JTbQH_2W3Y,3535
60
- ncca/ngl/vec4.py,sha256=zF0zw5EO4UE7EmqN30LPR3QQfaMcA1VcMID8CZALDiU,6740
61
+ ncca/ngl/vec4.py,sha256=95b7yr82JtC3FqVDC8Hwn3wzPmVzSYTDCR1A6h_w9RM,6884
61
62
  ncca/ngl/vec4_array.py,sha256=PSJXfG0g2AT4oQCLHiVAP6EC5n7vMXRQy0N1rGvv1iw,3426
62
- ncca_ngl-0.1.4.dist-info/WHEEL,sha256=NHRAbdxxzyL9K3IO2LjmlNqKSyPZnKv2BD16YYVKo18,79
63
- ncca_ngl-0.1.4.dist-info/METADATA,sha256=KYfa9uhviMmF1MyM6yabGza0uQAuDpXm1N6BFSUKK1I,1596
64
- ncca_ngl-0.1.4.dist-info/RECORD,,
63
+ ncca_ngl-0.2.1.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
64
+ ncca_ngl-0.2.1.dist-info/METADATA,sha256=DvVhD66ulcT-u9WQEmfkzZtGy2iaQstB_9dEM_xK_Xo,1596
65
+ ncca_ngl-0.2.1.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: uv 0.8.14
2
+ Generator: uv 0.8.24
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any