basilisk-engine 0.1.19__py3-none-any.whl → 0.1.20__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.

Potentially problematic release.


This version of basilisk-engine might be problematic. Click here for more details.

Files changed (87) hide show
  1. basilisk/__init__.py +15 -15
  2. basilisk/audio/sound.py +27 -27
  3. basilisk/bsk_assets/cube.obj +48 -48
  4. basilisk/collisions/broad/broad_aabb.py +102 -102
  5. basilisk/collisions/broad/broad_bvh.py +137 -137
  6. basilisk/collisions/collider.py +95 -95
  7. basilisk/collisions/collider_handler.py +224 -224
  8. basilisk/collisions/narrow/contact_manifold.py +95 -95
  9. basilisk/collisions/narrow/dataclasses.py +34 -34
  10. basilisk/collisions/narrow/deprecated.py +46 -46
  11. basilisk/collisions/narrow/epa.py +91 -91
  12. basilisk/collisions/narrow/gjk.py +66 -66
  13. basilisk/collisions/narrow/graham_scan.py +24 -24
  14. basilisk/collisions/narrow/helper.py +29 -29
  15. basilisk/collisions/narrow/line_intersections.py +106 -106
  16. basilisk/collisions/narrow/sutherland_hodgman.py +75 -75
  17. basilisk/config.py +2 -2
  18. basilisk/draw/draw.py +100 -100
  19. basilisk/draw/draw_handler.py +179 -179
  20. basilisk/draw/font_renderer.py +28 -28
  21. basilisk/engine.py +206 -206
  22. basilisk/generic/abstract_bvh.py +15 -15
  23. basilisk/generic/abstract_custom.py +133 -133
  24. basilisk/generic/collisions.py +72 -72
  25. basilisk/generic/input_validation.py +66 -66
  26. basilisk/generic/math.py +6 -6
  27. basilisk/generic/matrices.py +35 -35
  28. basilisk/generic/meshes.py +72 -72
  29. basilisk/generic/quat.py +142 -142
  30. basilisk/generic/quat_methods.py +7 -7
  31. basilisk/generic/raycast_result.py +26 -26
  32. basilisk/generic/vec3.py +143 -143
  33. basilisk/input/mouse.py +61 -61
  34. basilisk/input/path.py +14 -14
  35. basilisk/mesh/cube.py +33 -33
  36. basilisk/mesh/mesh.py +230 -230
  37. basilisk/mesh/mesh_from_data.py +130 -130
  38. basilisk/mesh/model.py +271 -271
  39. basilisk/mesh/narrow_aabb.py +89 -89
  40. basilisk/mesh/narrow_bvh.py +91 -91
  41. basilisk/mesh/narrow_primative.py +23 -23
  42. basilisk/nodes/helper.py +28 -28
  43. basilisk/nodes/node.py +684 -684
  44. basilisk/nodes/node_handler.py +96 -96
  45. basilisk/particles/particle_handler.py +64 -64
  46. basilisk/particles/particle_renderer.py +92 -92
  47. basilisk/physics/impulse.py +112 -112
  48. basilisk/physics/physics_body.py +43 -43
  49. basilisk/physics/physics_engine.py +35 -35
  50. basilisk/render/batch.py +105 -105
  51. basilisk/render/camera.py +221 -221
  52. basilisk/render/chunk.py +106 -106
  53. basilisk/render/chunk_handler.py +165 -165
  54. basilisk/render/frame.py +101 -101
  55. basilisk/render/framebuffer.py +130 -130
  56. basilisk/render/image.py +87 -87
  57. basilisk/render/image_handler.py +122 -122
  58. basilisk/render/light.py +96 -96
  59. basilisk/render/light_handler.py +58 -58
  60. basilisk/render/material.py +219 -219
  61. basilisk/render/material_handler.py +135 -135
  62. basilisk/render/post_process.py +132 -132
  63. basilisk/render/shader.py +110 -110
  64. basilisk/render/shader_handler.py +80 -80
  65. basilisk/render/sky.py +120 -120
  66. basilisk/scene.py +276 -276
  67. basilisk/shaders/batch.frag +276 -276
  68. basilisk/shaders/batch.vert +115 -115
  69. basilisk/shaders/crt.frag +31 -31
  70. basilisk/shaders/draw.frag +22 -21
  71. basilisk/shaders/draw.vert +25 -21
  72. basilisk/shaders/filter.frag +22 -22
  73. basilisk/shaders/frame.frag +12 -12
  74. basilisk/shaders/frame.vert +13 -13
  75. basilisk/shaders/geometry.frag +8 -8
  76. basilisk/shaders/geometry.vert +41 -41
  77. basilisk/shaders/normal.frag +59 -59
  78. basilisk/shaders/normal.vert +96 -96
  79. basilisk/shaders/particle.frag +71 -71
  80. basilisk/shaders/particle.vert +84 -84
  81. basilisk/shaders/sky.frag +9 -9
  82. basilisk/shaders/sky.vert +13 -13
  83. {basilisk_engine-0.1.19.dist-info → basilisk_engine-0.1.20.dist-info}/METADATA +38 -45
  84. basilisk_engine-0.1.20.dist-info/RECORD +103 -0
  85. {basilisk_engine-0.1.19.dist-info → basilisk_engine-0.1.20.dist-info}/WHEEL +1 -1
  86. basilisk_engine-0.1.19.dist-info/RECORD +0 -103
  87. {basilisk_engine-0.1.19.dist-info → basilisk_engine-0.1.20.dist-info}/top_level.txt +0 -0
@@ -1,134 +1,134 @@
1
- import glm
2
- import numpy as np
3
-
4
-
5
- class Custom():
6
-
7
- def normalize(self):
8
- """
9
- Inplace normalizes the vector
10
- """
11
- self._data = glm.normalize(self._data)
12
- return self
13
-
14
- def apply_function(): ... # will be overridden by child custom classes
15
-
16
- # math functions
17
- def add(self, other):
18
- def func(a, b): return a + b
19
- return self.apply_function(other, func, 'addition')
20
-
21
- def subtract(self, other):
22
- def func(a, b): return a - b
23
- return self.apply_function(other, func, 'subtraction')
24
-
25
- def rhs_subtract(self, other):
26
- def func(a, b): return b - a
27
- return self.apply_function(other, func, 'subtraction')
28
-
29
- def multiply(self, other):
30
- def func(a, b): return a * b
31
- return self.apply_function(other, func, 'multiplication')
32
-
33
- def divide(self, other):
34
- def func(a, b): return a / b
35
- return self.apply_function(other, func, 'division')
36
-
37
- def rhs_divide(self, other):
38
- def func(a, b): return b / a
39
- return self.apply_function(other, func, 'division')
40
-
41
- def floor_divide(self, other):
42
- def func(a, b): return a // b
43
- return self.apply_function(other, func, 'division')
44
-
45
- def rhs_floor_divide(self, other):
46
- def func(a, b): return b // a
47
- return self.apply_function(other, func, 'division')
48
-
49
- def mod(self, other):
50
- def func(a, b): return a % b
51
- return self.apply_function(other, func, 'modulus')
52
-
53
- def rhs_mod(self, other):
54
- def func(a, b): return b % a
55
- return self.apply_function(other, func, 'modulus')
56
-
57
- def pow(self, other):
58
- def func(a, b): return a ** b
59
- return self.apply_function(other, func, 'power')
60
-
61
- def rhs_pow(self, other):
62
- def func(a, b): return b ** a
63
- return self.apply_function(other, func, 'power')
64
-
65
- def __add__(self, other): return self.add(other) # this + that
66
- def __radd__(self, other): return self.add(other) # that + this
67
- def __iadd__(self, other): # this += that
68
- self = self.add(other)
69
- return self
70
-
71
- def __sub__(self, other): return self.subtract(other)
72
- def __rsub__(self, other): return self.rhs_subtract(other) # non-commutative
73
- def __isub__(self, other):
74
- self = self.subtract(other)
75
- return self
76
-
77
- def __mul__(self, other): return self.multiply(other)
78
- def __rmul__(self, other): return self.multiply(other)
79
- def __imul__(self, other):
80
- self = self.multiply(other)
81
- return self
82
-
83
- def __truediv__(self, other): return self.divide(other)
84
- def __rtruediv__(self, other): return self.rhs_divide(other) # non-commutative
85
- def __itruediv__(self, other):
86
- self = self.divide(other)
87
- return self
88
-
89
- def __floordiv__(self, other): return self.floor_divide(other)
90
- def __rfloordiv__(self, other): return self.rhs_floor_divide(other) # non-commutative
91
- def __ifloordiv__(self, other):
92
- self = self.floor_divide(other)
93
- return self
94
-
95
- def __mod__(self, other): return self.mod(other)
96
- def __rmod__(self, other): return self.rhs_mod(other)
97
- def __imod__(self, other):
98
- self = self.mod(other)
99
- return self
100
-
101
- def __pow__(self, other): return self.pow(other)
102
- def __rpow__(self, other): return self.rhs_pow(other)
103
- def __ipow__(self, other):
104
- self = self.pow(other)
105
- return self
106
-
107
- # comparison functions
108
- def __eq__(self, other):
109
- if isinstance(other, Custom): return self.data == other.data
110
- return self.data == other
111
-
112
- def __ne__(self, other):
113
- if isinstance(other, Custom): return self.data != other.data
114
- return self.data != other
115
-
116
- def __lt__(self, other):
117
- if isinstance(other, Custom): return self.data < other.data
118
- return self.data < other
119
-
120
- def __gt__(self, other):
121
- if isinstance(other, Custom): return self.data > other.data
122
- return self.data > other
123
-
124
- def __le__(self, other):
125
- if isinstance(other, Custom): return self.data <= other.data
126
- return self.data <= other
127
-
128
- def __ge__(self, other):
129
- if isinstance(other, Custom): return self.data >= other.data
130
- return self.data >= other
131
-
132
- # unary operators
133
- def __pos__(self):
1
+ import glm
2
+ import numpy as np
3
+
4
+
5
+ class Custom():
6
+
7
+ def normalize(self):
8
+ """
9
+ Inplace normalizes the vector
10
+ """
11
+ self._data = glm.normalize(self._data)
12
+ return self
13
+
14
+ def apply_function(): ... # will be overridden by child custom classes
15
+
16
+ # math functions
17
+ def add(self, other):
18
+ def func(a, b): return a + b
19
+ return self.apply_function(other, func, 'addition')
20
+
21
+ def subtract(self, other):
22
+ def func(a, b): return a - b
23
+ return self.apply_function(other, func, 'subtraction')
24
+
25
+ def rhs_subtract(self, other):
26
+ def func(a, b): return b - a
27
+ return self.apply_function(other, func, 'subtraction')
28
+
29
+ def multiply(self, other):
30
+ def func(a, b): return a * b
31
+ return self.apply_function(other, func, 'multiplication')
32
+
33
+ def divide(self, other):
34
+ def func(a, b): return a / b
35
+ return self.apply_function(other, func, 'division')
36
+
37
+ def rhs_divide(self, other):
38
+ def func(a, b): return b / a
39
+ return self.apply_function(other, func, 'division')
40
+
41
+ def floor_divide(self, other):
42
+ def func(a, b): return a // b
43
+ return self.apply_function(other, func, 'division')
44
+
45
+ def rhs_floor_divide(self, other):
46
+ def func(a, b): return b // a
47
+ return self.apply_function(other, func, 'division')
48
+
49
+ def mod(self, other):
50
+ def func(a, b): return a % b
51
+ return self.apply_function(other, func, 'modulus')
52
+
53
+ def rhs_mod(self, other):
54
+ def func(a, b): return b % a
55
+ return self.apply_function(other, func, 'modulus')
56
+
57
+ def pow(self, other):
58
+ def func(a, b): return a ** b
59
+ return self.apply_function(other, func, 'power')
60
+
61
+ def rhs_pow(self, other):
62
+ def func(a, b): return b ** a
63
+ return self.apply_function(other, func, 'power')
64
+
65
+ def __add__(self, other): return self.add(other) # this + that
66
+ def __radd__(self, other): return self.add(other) # that + this
67
+ def __iadd__(self, other): # this += that
68
+ self = self.add(other)
69
+ return self
70
+
71
+ def __sub__(self, other): return self.subtract(other)
72
+ def __rsub__(self, other): return self.rhs_subtract(other) # non-commutative
73
+ def __isub__(self, other):
74
+ self = self.subtract(other)
75
+ return self
76
+
77
+ def __mul__(self, other): return self.multiply(other)
78
+ def __rmul__(self, other): return self.multiply(other)
79
+ def __imul__(self, other):
80
+ self = self.multiply(other)
81
+ return self
82
+
83
+ def __truediv__(self, other): return self.divide(other)
84
+ def __rtruediv__(self, other): return self.rhs_divide(other) # non-commutative
85
+ def __itruediv__(self, other):
86
+ self = self.divide(other)
87
+ return self
88
+
89
+ def __floordiv__(self, other): return self.floor_divide(other)
90
+ def __rfloordiv__(self, other): return self.rhs_floor_divide(other) # non-commutative
91
+ def __ifloordiv__(self, other):
92
+ self = self.floor_divide(other)
93
+ return self
94
+
95
+ def __mod__(self, other): return self.mod(other)
96
+ def __rmod__(self, other): return self.rhs_mod(other)
97
+ def __imod__(self, other):
98
+ self = self.mod(other)
99
+ return self
100
+
101
+ def __pow__(self, other): return self.pow(other)
102
+ def __rpow__(self, other): return self.rhs_pow(other)
103
+ def __ipow__(self, other):
104
+ self = self.pow(other)
105
+ return self
106
+
107
+ # comparison functions
108
+ def __eq__(self, other):
109
+ if isinstance(other, Custom): return self.data == other.data
110
+ return self.data == other
111
+
112
+ def __ne__(self, other):
113
+ if isinstance(other, Custom): return self.data != other.data
114
+ return self.data != other
115
+
116
+ def __lt__(self, other):
117
+ if isinstance(other, Custom): return self.data < other.data
118
+ return self.data < other
119
+
120
+ def __gt__(self, other):
121
+ if isinstance(other, Custom): return self.data > other.data
122
+ return self.data > other
123
+
124
+ def __le__(self, other):
125
+ if isinstance(other, Custom): return self.data <= other.data
126
+ return self.data <= other
127
+
128
+ def __ge__(self, other):
129
+ if isinstance(other, Custom): return self.data >= other.data
130
+ return self.data >= other
131
+
132
+ # unary operators
133
+ def __pos__(self):
134
134
  return self
@@ -1,73 +1,73 @@
1
- import glm
2
- from ..generic.vec3 import Vec3
3
- from ..generic.quat import Quat
4
-
5
-
6
- def collide_aabb_aabb(top_right1: glm.vec3, bottom_left1: glm.vec3, top_right2: glm.vec3, bottom_left2: glm.vec3, epsilon:float=1e-7) -> bool:
7
- """
8
- Determines if two aabbs are colliding
9
- """
10
- return all(bottom_left1[i] <= top_right2[i] + epsilon and epsilon + top_right1[i] >= bottom_left2[i] for i in range(3))
11
-
12
- def collide_aabb_line(top_right: glm.vec3, bottom_left: glm.vec3, position: glm.vec3, forward: glm.vec3) -> bool: # TODO check algorithm
13
- """
14
- Determines if an infinite line intersects with an AABB
15
- """
16
- tmin, tmax = -1e10, 1e10
17
- for i in range(3):
18
- if forward[i]: # if forward[i] is not 0 to avoid division errors
19
-
20
- deno = 1 / forward[i]
21
- tlow = (bottom_left[i] - position[i]) * deno
22
- thigh = (top_right[i] - position[i]) * deno
23
- if deno < 0: tlow, thigh = thigh, tlow
24
- tmin = max(tmin, tlow)
25
- tmax = min(tmax, thigh)
26
- if tmax <= tmin: return False
27
-
28
- elif position[i] + 1e-7 < bottom_left[i] or position[i] > top_right[i] + 1e-7: return False
29
-
30
- return True
31
-
32
- def moller_trumbore(point:glm.vec3, vec:glm.vec3, triangle:list[glm.vec3], epsilon:float=1e-7) -> glm.vec3:
33
- """
34
- Determines where a line intersects with a triangle and where that intersection occurred
35
- """
36
- edge1, edge2 = triangle[1] - triangle[0], triangle[2] - triangle[0]
37
- ray_cross = glm.cross(vec, edge2)
38
- det = glm.dot(edge1, ray_cross)
39
-
40
- # if the ray is parallel to the triangle
41
- if abs(det) < epsilon: return None
42
-
43
- inv_det = 1 / det
44
- s = point - triangle[0]
45
- u = glm.dot(s, ray_cross) * inv_det
46
-
47
- if (u < 0 and abs(u) > epsilon) or (u > 1 and abs(u - 1) > epsilon): return None
48
-
49
- s_cross = glm.cross(s, edge1)
50
- v = glm.dot(vec, s_cross) * inv_det
51
-
52
- if (v < 0 and abs(v) > epsilon) or (u + v > 1 and abs(u + v - 1) > epsilon): return None
53
-
54
- t = glm.dot(edge2, s_cross) * inv_det
55
- if t > epsilon: return point + vec * t
56
- return None
57
-
58
- def get_sat_axes(rotation1: Quat, rotation2: Quat) -> list[glm.vec3]:
59
- """
60
- Gets the axes for SAT from obb rotation matrices
61
- """
62
- axes = []
63
- axes.extend(glm.transpose(glm.mat3_cast(rotation1.data)))
64
- axes.extend(glm.transpose(glm.mat3_cast(rotation2.data)))
65
-
66
- # crossed roots
67
- for i in range(0, 3):
68
- for j in range(3, 6):
69
- cross = glm.cross(axes[i], axes[j])
70
- if glm.length2(cross) < 1e-6: continue
71
- axes.append(glm.normalize(cross))
72
-
1
+ import glm
2
+ from ..generic.vec3 import Vec3
3
+ from ..generic.quat import Quat
4
+
5
+
6
+ def collide_aabb_aabb(top_right1: glm.vec3, bottom_left1: glm.vec3, top_right2: glm.vec3, bottom_left2: glm.vec3, epsilon:float=1e-7) -> bool:
7
+ """
8
+ Determines if two aabbs are colliding
9
+ """
10
+ return all(bottom_left1[i] <= top_right2[i] + epsilon and epsilon + top_right1[i] >= bottom_left2[i] for i in range(3))
11
+
12
+ def collide_aabb_line(top_right: glm.vec3, bottom_left: glm.vec3, position: glm.vec3, forward: glm.vec3) -> bool: # TODO check algorithm
13
+ """
14
+ Determines if an infinite line intersects with an AABB
15
+ """
16
+ tmin, tmax = -1e10, 1e10
17
+ for i in range(3):
18
+ if forward[i]: # if forward[i] is not 0 to avoid division errors
19
+
20
+ deno = 1 / forward[i]
21
+ tlow = (bottom_left[i] - position[i]) * deno
22
+ thigh = (top_right[i] - position[i]) * deno
23
+ if deno < 0: tlow, thigh = thigh, tlow
24
+ tmin = max(tmin, tlow)
25
+ tmax = min(tmax, thigh)
26
+ if tmax <= tmin: return False
27
+
28
+ elif position[i] + 1e-7 < bottom_left[i] or position[i] > top_right[i] + 1e-7: return False
29
+
30
+ return True
31
+
32
+ def moller_trumbore(point:glm.vec3, vec:glm.vec3, triangle:list[glm.vec3], epsilon:float=1e-7) -> glm.vec3:
33
+ """
34
+ Determines where a line intersects with a triangle and where that intersection occurred
35
+ """
36
+ edge1, edge2 = triangle[1] - triangle[0], triangle[2] - triangle[0]
37
+ ray_cross = glm.cross(vec, edge2)
38
+ det = glm.dot(edge1, ray_cross)
39
+
40
+ # if the ray is parallel to the triangle
41
+ if abs(det) < epsilon: return None
42
+
43
+ inv_det = 1 / det
44
+ s = point - triangle[0]
45
+ u = glm.dot(s, ray_cross) * inv_det
46
+
47
+ if (u < 0 and abs(u) > epsilon) or (u > 1 and abs(u - 1) > epsilon): return None
48
+
49
+ s_cross = glm.cross(s, edge1)
50
+ v = glm.dot(vec, s_cross) * inv_det
51
+
52
+ if (v < 0 and abs(v) > epsilon) or (u + v > 1 and abs(u + v - 1) > epsilon): return None
53
+
54
+ t = glm.dot(edge2, s_cross) * inv_det
55
+ if t > epsilon: return point + vec * t
56
+ return None
57
+
58
+ def get_sat_axes(rotation1: Quat, rotation2: Quat) -> list[glm.vec3]:
59
+ """
60
+ Gets the axes for SAT from obb rotation matrices
61
+ """
62
+ axes = []
63
+ axes.extend(glm.transpose(glm.mat3_cast(rotation1.data)))
64
+ axes.extend(glm.transpose(glm.mat3_cast(rotation2.data)))
65
+
66
+ # crossed roots
67
+ for i in range(0, 3):
68
+ for j in range(3, 6):
69
+ cross = glm.cross(axes[i], axes[j])
70
+ if glm.length2(cross) < 1e-6: continue
71
+ axes.append(glm.normalize(cross))
72
+
73
73
  return axes
@@ -1,67 +1,67 @@
1
- import numpy as np
2
- import glm
3
- from ..render.image import Image
4
-
5
-
6
- def validate_float(module: str, name: str, value: float | int | glm.float32) -> float:
7
- if isinstance(value, float) or isinstance(value, int):
8
- return float(value)
9
- elif isinstance(value, glm.float32):
10
- return float(value.value)
11
- else:
12
- raise TypeError(f"{module}: Invalid {name} value type {type(value)}. Expected float.")
13
-
14
- def validate_glm_vec3(module: str, name: str, value: tuple | list | glm.vec3 | np.ndarray) -> glm.vec3:
15
- if isinstance(value, tuple) or isinstance(value, list) or isinstance(value, np.ndarray):
16
- if len(value) != 3: raise ValueError(f"{module}: Invalid number of values for {name}. Expected 3 values, got {len(value)} values")
17
- return glm.vec3(value)
18
- elif isinstance(value, glm.vec3) or isinstance(value, int) or isinstance(value, float):
19
- return glm.vec3(value)
20
- else:
21
- raise TypeError(f"{module}: Invalid {name} value type {type(value)}. Expected glm.vec3")
22
-
23
- def validate_tuple3(module: str, name: str, value: tuple | list | glm.vec3 | np.ndarray) -> tuple:
24
- if isinstance(value, tuple) or isinstance(value, list) or isinstance(value, np.ndarray):
25
- if len(value) != 3: raise ValueError(f"{module}: Invalid number of values for {name}. Expected 3 values, got {len(value)} values")
26
- return tuple(value)
27
- elif isinstance(value, glm.vec3):
28
- return (value.x, value.y, value.z)
29
- if isinstance(value, int) or isinstance(value, float):
30
- return (value, value, value)
31
- else:
32
- raise TypeError(f"{module}: Invalid {name} value type {type(value)}. Expected tuple of size 3")
33
-
34
- def validate_image(module: str, name: str, value: Image | None) -> Image | None:
35
- """Accepts none as a value for no image"""
36
- if isinstance(value, Image) or isinstance(value, type(None)):
37
- return value
38
- else:
39
- raise TypeError(f"{module}: Invalid {name} value type {type(value)}. Expected bsk.Image or None")
40
-
41
- def validate_color(module: str, name: str, value: tuple | list | np.ndarray | int | float | None) -> tuple:
42
- if isinstance(value, tuple) or isinstance(value, list) or isinstance(value, np.ndarray):
43
- if len(value) == 4:
44
- return tuple(map(lambda x: x / 255, value))
45
- elif len(value) == 3:
46
- return (*tuple(map(lambda x: x / 255, value)), 1.0)
47
- else:
48
- raise TypeError(f"{module}: Invalid number of values for {name}. Expected 3 or 4 values, got {len(value)} values")
49
- elif isinstance(value, int) or isinstance(value, float):
50
- v = value / 255
51
- return (v, v, v, 1.0)
52
- else:
53
- raise TypeError(f"{module}: Invalid {name} value type {type(value)}. Expected tuple of size 3 or 4")
54
-
55
- def validate_rect(rect) -> tuple:
56
- if not (isinstance(rect, tuple) or isinstance(rect, list) or isinstance(rect, np.ndarray)):
57
- raise TypeError(f'Invalid rect type: {type(rect)}. Expected a tuple, list, or numpy array')
58
- if len(rect) != 4:
59
- raise TypeError(f'Invalid number of rect values. Expected 4 values, got {len(rect)}')
60
- return list(rect)
61
-
62
- def validate_point(point) -> tuple:
63
- if not (isinstance(point, tuple) or isinstance(point, list) or isinstance(point, np.ndarray)):
64
- raise TypeError(f'Invalid rect type: {type(point)}. Expected a tuple, list, or numpy array')
65
- if len(point) != 2:
66
- raise TypeError(f'Invalid number of rect values. Expected 2 values, got {len(point)}')
1
+ import numpy as np
2
+ import glm
3
+ from ..render.image import Image
4
+
5
+
6
+ def validate_float(module: str, name: str, value: float | int | glm.float32) -> float:
7
+ if isinstance(value, float) or isinstance(value, int):
8
+ return float(value)
9
+ elif isinstance(value, glm.float32):
10
+ return float(value.value)
11
+ else:
12
+ raise TypeError(f"{module}: Invalid {name} value type {type(value)}. Expected float.")
13
+
14
+ def validate_glm_vec3(module: str, name: str, value: tuple | list | glm.vec3 | np.ndarray) -> glm.vec3:
15
+ if isinstance(value, tuple) or isinstance(value, list) or isinstance(value, np.ndarray):
16
+ if len(value) != 3: raise ValueError(f"{module}: Invalid number of values for {name}. Expected 3 values, got {len(value)} values")
17
+ return glm.vec3(value)
18
+ elif isinstance(value, glm.vec3) or isinstance(value, int) or isinstance(value, float):
19
+ return glm.vec3(value)
20
+ else:
21
+ raise TypeError(f"{module}: Invalid {name} value type {type(value)}. Expected glm.vec3")
22
+
23
+ def validate_tuple3(module: str, name: str, value: tuple | list | glm.vec3 | np.ndarray) -> tuple:
24
+ if isinstance(value, tuple) or isinstance(value, list) or isinstance(value, np.ndarray):
25
+ if len(value) != 3: raise ValueError(f"{module}: Invalid number of values for {name}. Expected 3 values, got {len(value)} values")
26
+ return tuple(value)
27
+ elif isinstance(value, glm.vec3):
28
+ return (value.x, value.y, value.z)
29
+ if isinstance(value, int) or isinstance(value, float):
30
+ return (value, value, value)
31
+ else:
32
+ raise TypeError(f"{module}: Invalid {name} value type {type(value)}. Expected tuple of size 3")
33
+
34
+ def validate_image(module: str, name: str, value: Image | None) -> Image | None:
35
+ """Accepts none as a value for no image"""
36
+ if isinstance(value, Image) or isinstance(value, type(None)):
37
+ return value
38
+ else:
39
+ raise TypeError(f"{module}: Invalid {name} value type {type(value)}. Expected bsk.Image or None")
40
+
41
+ def validate_color(module: str, name: str, value: tuple | list | np.ndarray | int | float | None) -> tuple:
42
+ if isinstance(value, tuple) or isinstance(value, list) or isinstance(value, np.ndarray):
43
+ if len(value) == 4:
44
+ return tuple(map(lambda x: x / 255, value))
45
+ elif len(value) == 3:
46
+ return (*tuple(map(lambda x: x / 255, value)), 1.0)
47
+ else:
48
+ raise TypeError(f"{module}: Invalid number of values for {name}. Expected 3 or 4 values, got {len(value)} values")
49
+ elif isinstance(value, int) or isinstance(value, float):
50
+ v = value / 255
51
+ return (v, v, v, 1.0)
52
+ else:
53
+ raise TypeError(f"{module}: Invalid {name} value type {type(value)}. Expected tuple of size 3 or 4")
54
+
55
+ def validate_rect(rect) -> tuple:
56
+ if not (isinstance(rect, tuple) or isinstance(rect, list) or isinstance(rect, np.ndarray)):
57
+ raise TypeError(f'Invalid rect type: {type(rect)}. Expected a tuple, list, or numpy array')
58
+ if len(rect) != 4:
59
+ raise TypeError(f'Invalid number of rect values. Expected 4 values, got {len(rect)}')
60
+ return list(rect)
61
+
62
+ def validate_point(point) -> tuple:
63
+ if not (isinstance(point, tuple) or isinstance(point, list) or isinstance(point, np.ndarray)):
64
+ raise TypeError(f'Invalid rect type: {type(point)}. Expected a tuple, list, or numpy array')
65
+ if len(point) != 2:
66
+ raise TypeError(f'Invalid number of rect values. Expected 2 values, got {len(point)}')
67
67
  return list(point)
basilisk/generic/math.py CHANGED
@@ -1,7 +1,7 @@
1
- import glm
2
-
3
- def triple_product(vector1, vector2, vector3) -> glm.vec3:
4
- """
5
- Computes (1 x 2) x 3
6
- """
1
+ import glm
2
+
3
+ def triple_product(vector1, vector2, vector3) -> glm.vec3:
4
+ """
5
+ Computes (1 x 2) x 3
6
+ """
7
7
  return glm.cross(glm.cross(vector1, vector2), vector3)
@@ -1,36 +1,36 @@
1
- import glm
2
- from ..generic.vec3 import Vec3
3
- from ..generic.quat import Quat
4
-
5
-
6
- # transform matrices
7
- def get_model_matrix(position: Vec3, scale: Vec3, rotation: Quat) -> glm.mat4x4:
8
- """
9
- Gets projection matrix from object data
10
- """
11
- translation_matrix = glm.translate(glm.mat4(1.0), position.data)
12
- rotation_matrix = glm.mat4_cast(rotation.data)
13
- scale_matrix = glm.scale(glm.mat4(1.0), scale.data)
14
- model_matrix = translation_matrix * glm.transpose(rotation_matrix) * scale_matrix
15
- return model_matrix
16
-
17
- def get_scale_matrix(scale: glm.vec3) -> glm.mat3x3:
18
- """
19
- Gets the scaling matrix from a scale vector
20
- """
21
- return glm.mat3x3(
22
- scale.x, 0, 0,
23
- 0, scale.y, 0,
24
- 0, 0, scale.z
25
- )
26
-
27
- # inertia tensors
28
- def compute_inertia_moment(t:list[glm.vec3], i:int) -> float:
29
- return t[0][i] ** 2 + t[1][i] * t[2][i] + \
30
- t[1][i] ** 2 + t[0][i] * t[2][i] + \
31
- t[2][i] ** 2 + t[0][i] * t[1][i]
32
-
33
- def compute_inertia_product(t:list[glm.vec3], i:int, j:int) -> float:
34
- return 2 * t[0][i] * t[0][j] + t[1][i] * t[2][j] + t[2][i] * t[1][j] + \
35
- 2 * t[1][i] * t[1][j] + t[0][i] * t[2][j] + t[2][i] * t[0][j] + \
1
+ import glm
2
+ from ..generic.vec3 import Vec3
3
+ from ..generic.quat import Quat
4
+
5
+
6
+ # transform matrices
7
+ def get_model_matrix(position: Vec3, scale: Vec3, rotation: Quat) -> glm.mat4x4:
8
+ """
9
+ Gets projection matrix from object data
10
+ """
11
+ translation_matrix = glm.translate(glm.mat4(1.0), position.data)
12
+ rotation_matrix = glm.mat4_cast(rotation.data)
13
+ scale_matrix = glm.scale(glm.mat4(1.0), scale.data)
14
+ model_matrix = translation_matrix * glm.transpose(rotation_matrix) * scale_matrix
15
+ return model_matrix
16
+
17
+ def get_scale_matrix(scale: glm.vec3) -> glm.mat3x3:
18
+ """
19
+ Gets the scaling matrix from a scale vector
20
+ """
21
+ return glm.mat3x3(
22
+ scale.x, 0, 0,
23
+ 0, scale.y, 0,
24
+ 0, 0, scale.z
25
+ )
26
+
27
+ # inertia tensors
28
+ def compute_inertia_moment(t:list[glm.vec3], i:int) -> float:
29
+ return t[0][i] ** 2 + t[1][i] * t[2][i] + \
30
+ t[1][i] ** 2 + t[0][i] * t[2][i] + \
31
+ t[2][i] ** 2 + t[0][i] * t[1][i]
32
+
33
+ def compute_inertia_product(t:list[glm.vec3], i:int, j:int) -> float:
34
+ return 2 * t[0][i] * t[0][j] + t[1][i] * t[2][j] + t[2][i] * t[1][j] + \
35
+ 2 * t[1][i] * t[1][j] + t[0][i] * t[2][j] + t[2][i] * t[0][j] + \
36
36
  2 * t[2][i] * t[2][j] + t[0][i] * t[1][j] + t[1][i] * t[0][j]