basilisk-engine 0.1.42__py3-none-any.whl → 0.1.43__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.
- basilisk/__init__.py +26 -26
- basilisk/audio/sound.py +27 -27
- basilisk/bsk_assets/cube.obj +48 -48
- basilisk/collisions/broad/broad_aabb.py +102 -102
- basilisk/collisions/broad/broad_bvh.py +137 -137
- basilisk/collisions/collider.py +95 -95
- basilisk/collisions/collider_handler.py +225 -225
- basilisk/collisions/narrow/contact_manifold.py +95 -95
- basilisk/collisions/narrow/dataclasses.py +34 -34
- basilisk/collisions/narrow/deprecated.py +46 -46
- basilisk/collisions/narrow/epa.py +91 -91
- basilisk/collisions/narrow/gjk.py +66 -66
- basilisk/collisions/narrow/graham_scan.py +24 -24
- basilisk/collisions/narrow/helper.py +29 -29
- basilisk/collisions/narrow/line_intersections.py +106 -106
- basilisk/collisions/narrow/sutherland_hodgman.py +75 -75
- basilisk/config.py +53 -53
- basilisk/draw/draw.py +100 -100
- basilisk/draw/draw_handler.py +178 -178
- basilisk/draw/font_renderer.py +28 -28
- basilisk/engine.py +169 -171
- basilisk/generic/abstract_bvh.py +15 -15
- basilisk/generic/abstract_custom.py +133 -133
- basilisk/generic/collisions.py +70 -70
- basilisk/generic/input_validation.py +82 -82
- basilisk/generic/math.py +17 -17
- basilisk/generic/matrices.py +35 -35
- basilisk/generic/meshes.py +72 -72
- basilisk/generic/quat.py +142 -142
- basilisk/generic/quat_methods.py +7 -7
- basilisk/generic/raycast_result.py +26 -26
- basilisk/generic/vec3.py +143 -143
- basilisk/input_output/IO_handler.py +91 -91
- basilisk/input_output/clock.py +49 -49
- basilisk/input_output/keys.py +43 -43
- basilisk/input_output/mouse.py +90 -90
- basilisk/input_output/path.py +14 -14
- basilisk/mesh/cube.py +33 -33
- basilisk/mesh/mesh.py +233 -233
- basilisk/mesh/mesh_from_data.py +150 -150
- basilisk/mesh/model.py +271 -271
- basilisk/mesh/narrow_aabb.py +89 -89
- basilisk/mesh/narrow_bvh.py +91 -91
- basilisk/mesh/narrow_primative.py +23 -23
- basilisk/nodes/helper.py +28 -28
- basilisk/nodes/node.py +709 -709
- basilisk/nodes/node_handler.py +97 -97
- basilisk/particles/particle_handler.py +64 -64
- basilisk/particles/particle_renderer.py +93 -93
- basilisk/physics/impulse.py +112 -112
- basilisk/physics/physics_body.py +43 -43
- basilisk/physics/physics_engine.py +35 -35
- basilisk/render/batch.py +103 -103
- basilisk/render/bloom.py +118 -124
- basilisk/render/camera.py +260 -260
- basilisk/render/chunk.py +113 -108
- basilisk/render/chunk_handler.py +167 -167
- basilisk/render/frame.py +130 -128
- basilisk/render/framebuffer.py +192 -212
- basilisk/render/image.py +120 -120
- basilisk/render/image_handler.py +120 -120
- basilisk/render/light.py +96 -96
- basilisk/render/light_handler.py +58 -58
- basilisk/render/material.py +232 -232
- basilisk/render/material_handler.py +133 -133
- basilisk/render/post_process.py +180 -180
- basilisk/render/shader.py +135 -134
- basilisk/render/shader_handler.py +109 -94
- basilisk/render/sky.py +119 -121
- basilisk/scene.py +287 -288
- basilisk/shaders/batch.frag +293 -293
- basilisk/shaders/batch.vert +117 -117
- basilisk/shaders/bloom_downsample.frag +23 -42
- basilisk/shaders/bloom_upsample.frag +33 -33
- basilisk/shaders/crt.frag +34 -34
- basilisk/shaders/draw.frag +27 -27
- basilisk/shaders/draw.vert +25 -25
- basilisk/shaders/filter.frag +22 -22
- basilisk/shaders/frame.frag +13 -13
- basilisk/shaders/frame.vert +13 -13
- basilisk/shaders/frame_hdr.frag +27 -27
- basilisk/shaders/geometry.frag +10 -10
- basilisk/shaders/geometry.vert +41 -41
- basilisk/shaders/normal.frag +62 -62
- basilisk/shaders/normal.vert +96 -96
- basilisk/shaders/particle.frag +81 -81
- basilisk/shaders/particle.vert +86 -86
- basilisk/shaders/sky.frag +23 -23
- basilisk/shaders/sky.vert +13 -13
- {basilisk_engine-0.1.42.dist-info → basilisk_engine-0.1.43.dist-info}/METADATA +89 -89
- basilisk_engine-0.1.43.dist-info/RECORD +111 -0
- {basilisk_engine-0.1.42.dist-info → basilisk_engine-0.1.43.dist-info}/WHEEL +1 -1
- basilisk/input/__init__.py +0 -0
- basilisk/input/mouse.py +0 -62
- basilisk/input/path.py +0 -14
- basilisk/shaders/bloom_frame.frag +0 -25
- basilisk_engine-0.1.42.dist-info/RECORD +0 -115
- {basilisk_engine-0.1.42.dist-info → basilisk_engine-0.1.43.dist-info}/top_level.txt +0 -0
basilisk/generic/collisions.py
CHANGED
|
@@ -1,71 +1,71 @@
|
|
|
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
|
-
# based on Smit's algorithm
|
|
17
|
-
inv_dir = glm.vec3([1 / i if i != 0 else float('inf') for i in forward])
|
|
18
|
-
|
|
19
|
-
t1 = (bottom_left - position) * inv_dir
|
|
20
|
-
t2 = (top_right - position) * inv_dir
|
|
21
|
-
|
|
22
|
-
t_min = glm.min(t1, t2) # entry point along each axis
|
|
23
|
-
t_max = glm.max(t1, t2) # exit point along each axis
|
|
24
|
-
|
|
25
|
-
t_entry = max(t_min.x, t_min.y, t_min.z) # furthest entry time
|
|
26
|
-
t_exit = min(t_max.x, t_max.y, t_max.z) # earliest exit time
|
|
27
|
-
|
|
28
|
-
return t_entry <= t_exit and t_exit >= 0
|
|
29
|
-
|
|
30
|
-
def moller_trumbore(point:glm.vec3, vec:glm.vec3, triangle:list[glm.vec3], epsilon:float=1e-7) -> glm.vec3:
|
|
31
|
-
"""
|
|
32
|
-
Determines where a line intersects with a triangle and where that intersection occurred
|
|
33
|
-
"""
|
|
34
|
-
edge1, edge2 = triangle[1] - triangle[0], triangle[2] - triangle[0]
|
|
35
|
-
ray_cross = glm.cross(vec, edge2)
|
|
36
|
-
det = glm.dot(edge1, ray_cross)
|
|
37
|
-
|
|
38
|
-
# if the ray is parallel to the triangle
|
|
39
|
-
if abs(det) < epsilon: return None
|
|
40
|
-
|
|
41
|
-
inv_det = 1 / det
|
|
42
|
-
s = point - triangle[0]
|
|
43
|
-
u = glm.dot(s, ray_cross) * inv_det
|
|
44
|
-
|
|
45
|
-
if (u < 0 and abs(u) > epsilon) or (u > 1 and abs(u - 1) > epsilon): return None
|
|
46
|
-
|
|
47
|
-
s_cross = glm.cross(s, edge1)
|
|
48
|
-
v = glm.dot(vec, s_cross) * inv_det
|
|
49
|
-
|
|
50
|
-
if (v < 0 and abs(v) > epsilon) or (u + v > 1 and abs(u + v - 1) > epsilon): return None
|
|
51
|
-
|
|
52
|
-
t = glm.dot(edge2, s_cross) * inv_det
|
|
53
|
-
if t > epsilon: return point + vec * t
|
|
54
|
-
return None
|
|
55
|
-
|
|
56
|
-
def get_sat_axes(rotation1: Quat, rotation2: Quat) -> list[glm.vec3]:
|
|
57
|
-
"""
|
|
58
|
-
Gets the axes for SAT from obb rotation matrices
|
|
59
|
-
"""
|
|
60
|
-
axes = []
|
|
61
|
-
axes.extend(glm.transpose(glm.mat3_cast(rotation1.data)))
|
|
62
|
-
axes.extend(glm.transpose(glm.mat3_cast(rotation2.data)))
|
|
63
|
-
|
|
64
|
-
# crossed roots
|
|
65
|
-
for i in range(0, 3):
|
|
66
|
-
for j in range(3, 6):
|
|
67
|
-
cross = glm.cross(axes[i], axes[j])
|
|
68
|
-
if glm.length2(cross) < 1e-6: continue
|
|
69
|
-
axes.append(glm.normalize(cross))
|
|
70
|
-
|
|
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
|
+
# based on Smit's algorithm
|
|
17
|
+
inv_dir = glm.vec3([1 / i if i != 0 else float('inf') for i in forward])
|
|
18
|
+
|
|
19
|
+
t1 = (bottom_left - position) * inv_dir
|
|
20
|
+
t2 = (top_right - position) * inv_dir
|
|
21
|
+
|
|
22
|
+
t_min = glm.min(t1, t2) # entry point along each axis
|
|
23
|
+
t_max = glm.max(t1, t2) # exit point along each axis
|
|
24
|
+
|
|
25
|
+
t_entry = max(t_min.x, t_min.y, t_min.z) # furthest entry time
|
|
26
|
+
t_exit = min(t_max.x, t_max.y, t_max.z) # earliest exit time
|
|
27
|
+
|
|
28
|
+
return t_entry <= t_exit and t_exit >= 0
|
|
29
|
+
|
|
30
|
+
def moller_trumbore(point:glm.vec3, vec:glm.vec3, triangle:list[glm.vec3], epsilon:float=1e-7) -> glm.vec3:
|
|
31
|
+
"""
|
|
32
|
+
Determines where a line intersects with a triangle and where that intersection occurred
|
|
33
|
+
"""
|
|
34
|
+
edge1, edge2 = triangle[1] - triangle[0], triangle[2] - triangle[0]
|
|
35
|
+
ray_cross = glm.cross(vec, edge2)
|
|
36
|
+
det = glm.dot(edge1, ray_cross)
|
|
37
|
+
|
|
38
|
+
# if the ray is parallel to the triangle
|
|
39
|
+
if abs(det) < epsilon: return None
|
|
40
|
+
|
|
41
|
+
inv_det = 1 / det
|
|
42
|
+
s = point - triangle[0]
|
|
43
|
+
u = glm.dot(s, ray_cross) * inv_det
|
|
44
|
+
|
|
45
|
+
if (u < 0 and abs(u) > epsilon) or (u > 1 and abs(u - 1) > epsilon): return None
|
|
46
|
+
|
|
47
|
+
s_cross = glm.cross(s, edge1)
|
|
48
|
+
v = glm.dot(vec, s_cross) * inv_det
|
|
49
|
+
|
|
50
|
+
if (v < 0 and abs(v) > epsilon) or (u + v > 1 and abs(u + v - 1) > epsilon): return None
|
|
51
|
+
|
|
52
|
+
t = glm.dot(edge2, s_cross) * inv_det
|
|
53
|
+
if t > epsilon: return point + vec * t
|
|
54
|
+
return None
|
|
55
|
+
|
|
56
|
+
def get_sat_axes(rotation1: Quat, rotation2: Quat) -> list[glm.vec3]:
|
|
57
|
+
"""
|
|
58
|
+
Gets the axes for SAT from obb rotation matrices
|
|
59
|
+
"""
|
|
60
|
+
axes = []
|
|
61
|
+
axes.extend(glm.transpose(glm.mat3_cast(rotation1.data)))
|
|
62
|
+
axes.extend(glm.transpose(glm.mat3_cast(rotation2.data)))
|
|
63
|
+
|
|
64
|
+
# crossed roots
|
|
65
|
+
for i in range(0, 3):
|
|
66
|
+
for j in range(3, 6):
|
|
67
|
+
cross = glm.cross(axes[i], axes[j])
|
|
68
|
+
if glm.length2(cross) < 1e-6: continue
|
|
69
|
+
axes.append(glm.normalize(cross))
|
|
70
|
+
|
|
71
71
|
return axes
|
|
@@ -1,83 +1,83 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
import glm
|
|
3
|
-
from ..render.image import Image
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def validate_int(module: str, name: str, value: int | float | glm.int32) -> float:
|
|
7
|
-
if isinstance(value, int) or isinstance(value, float):
|
|
8
|
-
return int(round(value))
|
|
9
|
-
elif isinstance(value, glm.int32):
|
|
10
|
-
return int(value.value)
|
|
11
|
-
else:
|
|
12
|
-
raise TypeError(f"{module}: Invalid {name} value type {type(value)}. Expected float.")
|
|
13
|
-
|
|
14
|
-
def validate_float(module: str, name: str, value: float | int | glm.float32) -> float:
|
|
15
|
-
if isinstance(value, float) or isinstance(value, int):
|
|
16
|
-
return float(value)
|
|
17
|
-
elif isinstance(value, glm.float32):
|
|
18
|
-
return float(value.value)
|
|
19
|
-
else:
|
|
20
|
-
raise TypeError(f"{module}: Invalid {name} value type {type(value)}. Expected float.")
|
|
21
|
-
|
|
22
|
-
def validate_glm_float(module: str, name: str, value: float | int | glm.float32) -> glm.float32:
|
|
23
|
-
if isinstance(value, float) or isinstance(value, int):
|
|
24
|
-
return glm.float32(value)
|
|
25
|
-
elif isinstance(value, glm.float32):
|
|
26
|
-
return value
|
|
27
|
-
else:
|
|
28
|
-
raise TypeError(f"{module}: Invalid {name} value type {type(value)}. Expected glm.float32 or convertable value.")
|
|
29
|
-
|
|
30
|
-
def validate_glm_vec3(module: str, name: str, value: tuple | list | glm.vec3 | np.ndarray) -> glm.vec3:
|
|
31
|
-
if isinstance(value, tuple) or isinstance(value, list) or isinstance(value, np.ndarray):
|
|
32
|
-
if len(value) != 3: raise ValueError(f"{module}: Invalid number of values for {name}. Expected 3 values, got {len(value)} values")
|
|
33
|
-
return glm.vec3(value)
|
|
34
|
-
elif isinstance(value, glm.vec3) or isinstance(value, int) or isinstance(value, float):
|
|
35
|
-
return glm.vec3(value)
|
|
36
|
-
else:
|
|
37
|
-
raise TypeError(f"{module}: Invalid {name} value type {type(value)}. Expected glm.vec3")
|
|
38
|
-
|
|
39
|
-
def validate_tuple3(module: str, name: str, value: tuple | list | glm.vec3 | np.ndarray) -> tuple:
|
|
40
|
-
if isinstance(value, tuple) or isinstance(value, list) or isinstance(value, np.ndarray):
|
|
41
|
-
if len(value) != 3: raise ValueError(f"{module}: Invalid number of values for {name}. Expected 3 values, got {len(value)} values")
|
|
42
|
-
return tuple(value)
|
|
43
|
-
elif isinstance(value, glm.vec3):
|
|
44
|
-
return (value.x, value.y, value.z)
|
|
45
|
-
if isinstance(value, int) or isinstance(value, float):
|
|
46
|
-
return (value, value, value)
|
|
47
|
-
else:
|
|
48
|
-
raise TypeError(f"{module}: Invalid {name} value type {type(value)}. Expected tuple of size 3")
|
|
49
|
-
|
|
50
|
-
def validate_image(module: str, name: str, value: Image | None) -> Image | None:
|
|
51
|
-
"""Accepts none as a value for no image"""
|
|
52
|
-
if isinstance(value, Image) or isinstance(value, type(None)):
|
|
53
|
-
return value
|
|
54
|
-
else:
|
|
55
|
-
raise TypeError(f"{module}: Invalid {name} value type {type(value)}. Expected bsk.Image or None")
|
|
56
|
-
|
|
57
|
-
def validate_color(module: str, name: str, value: tuple | list | np.ndarray | int | float | None) -> tuple:
|
|
58
|
-
if isinstance(value, tuple) or isinstance(value, list) or isinstance(value, np.ndarray):
|
|
59
|
-
if len(value) == 4:
|
|
60
|
-
return tuple(map(lambda x: x / 255, value))
|
|
61
|
-
elif len(value) == 3:
|
|
62
|
-
return (*tuple(map(lambda x: x / 255, value)), 1.0)
|
|
63
|
-
else:
|
|
64
|
-
raise TypeError(f"{module}: Invalid number of values for {name}. Expected 3 or 4 values, got {len(value)} values")
|
|
65
|
-
elif isinstance(value, int) or isinstance(value, float):
|
|
66
|
-
v = value / 255
|
|
67
|
-
return (v, v, v, 1.0)
|
|
68
|
-
else:
|
|
69
|
-
raise TypeError(f"{module}: Invalid {name} value type {type(value)}. Expected tuple of size 3 or 4")
|
|
70
|
-
|
|
71
|
-
def validate_rect(rect) -> tuple:
|
|
72
|
-
if not (isinstance(rect, tuple) or isinstance(rect, list) or isinstance(rect, np.ndarray)):
|
|
73
|
-
raise TypeError(f'Invalid rect type: {type(rect)}. Expected a tuple, list, or numpy array')
|
|
74
|
-
if len(rect) != 4:
|
|
75
|
-
raise TypeError(f'Invalid number of rect values. Expected 4 values, got {len(rect)}')
|
|
76
|
-
return list(rect)
|
|
77
|
-
|
|
78
|
-
def validate_point(point) -> tuple:
|
|
79
|
-
if not (isinstance(point, tuple) or isinstance(point, list) or isinstance(point, np.ndarray)):
|
|
80
|
-
raise TypeError(f'Invalid rect type: {type(point)}. Expected a tuple, list, or numpy array')
|
|
81
|
-
if len(point) != 2:
|
|
82
|
-
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_int(module: str, name: str, value: int | float | glm.int32) -> float:
|
|
7
|
+
if isinstance(value, int) or isinstance(value, float):
|
|
8
|
+
return int(round(value))
|
|
9
|
+
elif isinstance(value, glm.int32):
|
|
10
|
+
return int(value.value)
|
|
11
|
+
else:
|
|
12
|
+
raise TypeError(f"{module}: Invalid {name} value type {type(value)}. Expected float.")
|
|
13
|
+
|
|
14
|
+
def validate_float(module: str, name: str, value: float | int | glm.float32) -> float:
|
|
15
|
+
if isinstance(value, float) or isinstance(value, int):
|
|
16
|
+
return float(value)
|
|
17
|
+
elif isinstance(value, glm.float32):
|
|
18
|
+
return float(value.value)
|
|
19
|
+
else:
|
|
20
|
+
raise TypeError(f"{module}: Invalid {name} value type {type(value)}. Expected float.")
|
|
21
|
+
|
|
22
|
+
def validate_glm_float(module: str, name: str, value: float | int | glm.float32) -> glm.float32:
|
|
23
|
+
if isinstance(value, float) or isinstance(value, int):
|
|
24
|
+
return glm.float32(value)
|
|
25
|
+
elif isinstance(value, glm.float32):
|
|
26
|
+
return value
|
|
27
|
+
else:
|
|
28
|
+
raise TypeError(f"{module}: Invalid {name} value type {type(value)}. Expected glm.float32 or convertable value.")
|
|
29
|
+
|
|
30
|
+
def validate_glm_vec3(module: str, name: str, value: tuple | list | glm.vec3 | np.ndarray) -> glm.vec3:
|
|
31
|
+
if isinstance(value, tuple) or isinstance(value, list) or isinstance(value, np.ndarray):
|
|
32
|
+
if len(value) != 3: raise ValueError(f"{module}: Invalid number of values for {name}. Expected 3 values, got {len(value)} values")
|
|
33
|
+
return glm.vec3(value)
|
|
34
|
+
elif isinstance(value, glm.vec3) or isinstance(value, int) or isinstance(value, float):
|
|
35
|
+
return glm.vec3(value)
|
|
36
|
+
else:
|
|
37
|
+
raise TypeError(f"{module}: Invalid {name} value type {type(value)}. Expected glm.vec3")
|
|
38
|
+
|
|
39
|
+
def validate_tuple3(module: str, name: str, value: tuple | list | glm.vec3 | np.ndarray) -> tuple:
|
|
40
|
+
if isinstance(value, tuple) or isinstance(value, list) or isinstance(value, np.ndarray):
|
|
41
|
+
if len(value) != 3: raise ValueError(f"{module}: Invalid number of values for {name}. Expected 3 values, got {len(value)} values")
|
|
42
|
+
return tuple(value)
|
|
43
|
+
elif isinstance(value, glm.vec3):
|
|
44
|
+
return (value.x, value.y, value.z)
|
|
45
|
+
if isinstance(value, int) or isinstance(value, float):
|
|
46
|
+
return (value, value, value)
|
|
47
|
+
else:
|
|
48
|
+
raise TypeError(f"{module}: Invalid {name} value type {type(value)}. Expected tuple of size 3")
|
|
49
|
+
|
|
50
|
+
def validate_image(module: str, name: str, value: Image | None) -> Image | None:
|
|
51
|
+
"""Accepts none as a value for no image"""
|
|
52
|
+
if isinstance(value, Image) or isinstance(value, type(None)):
|
|
53
|
+
return value
|
|
54
|
+
else:
|
|
55
|
+
raise TypeError(f"{module}: Invalid {name} value type {type(value)}. Expected bsk.Image or None")
|
|
56
|
+
|
|
57
|
+
def validate_color(module: str, name: str, value: tuple | list | np.ndarray | int | float | None) -> tuple:
|
|
58
|
+
if isinstance(value, tuple) or isinstance(value, list) or isinstance(value, np.ndarray):
|
|
59
|
+
if len(value) == 4:
|
|
60
|
+
return tuple(map(lambda x: x / 255, value))
|
|
61
|
+
elif len(value) == 3:
|
|
62
|
+
return (*tuple(map(lambda x: x / 255, value)), 1.0)
|
|
63
|
+
else:
|
|
64
|
+
raise TypeError(f"{module}: Invalid number of values for {name}. Expected 3 or 4 values, got {len(value)} values")
|
|
65
|
+
elif isinstance(value, int) or isinstance(value, float):
|
|
66
|
+
v = value / 255
|
|
67
|
+
return (v, v, v, 1.0)
|
|
68
|
+
else:
|
|
69
|
+
raise TypeError(f"{module}: Invalid {name} value type {type(value)}. Expected tuple of size 3 or 4")
|
|
70
|
+
|
|
71
|
+
def validate_rect(rect) -> tuple:
|
|
72
|
+
if not (isinstance(rect, tuple) or isinstance(rect, list) or isinstance(rect, np.ndarray)):
|
|
73
|
+
raise TypeError(f'Invalid rect type: {type(rect)}. Expected a tuple, list, or numpy array')
|
|
74
|
+
if len(rect) != 4:
|
|
75
|
+
raise TypeError(f'Invalid number of rect values. Expected 4 values, got {len(rect)}')
|
|
76
|
+
return list(rect)
|
|
77
|
+
|
|
78
|
+
def validate_point(point) -> tuple:
|
|
79
|
+
if not (isinstance(point, tuple) or isinstance(point, list) or isinstance(point, np.ndarray)):
|
|
80
|
+
raise TypeError(f'Invalid rect type: {type(point)}. Expected a tuple, list, or numpy array')
|
|
81
|
+
if len(point) != 2:
|
|
82
|
+
raise TypeError(f'Invalid number of rect values. Expected 2 values, got {len(point)}')
|
|
83
83
|
return list(point)
|
basilisk/generic/math.py
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import glm
|
|
2
|
-
|
|
3
|
-
def triple_product(vector1, vector2, vector3) -> glm.vec3:
|
|
4
|
-
"""
|
|
5
|
-
Computes (1 x 2) x 3
|
|
6
|
-
"""
|
|
7
|
-
return glm.cross(glm.cross(vector1, vector2), vector3)
|
|
8
|
-
|
|
9
|
-
def relative_transforms(parent, child) -> tuple[glm.vec3, glm.vec3, glm.quat]:
|
|
10
|
-
"""
|
|
11
|
-
Calculates the relative transforms for position, scale, and rotation for the parent and child. parent and child are Nodes
|
|
12
|
-
"""
|
|
13
|
-
relative = glm.inverse(parent.model_matrix) * child.model_matrix
|
|
14
|
-
position = glm.vec3(relative[3])
|
|
15
|
-
scale = glm.vec3([glm.length(relative[i]) for i in range(3)])
|
|
16
|
-
rotation = child.rotation.data * glm.inverse(parent.rotation.data)
|
|
17
|
-
|
|
1
|
+
import glm
|
|
2
|
+
|
|
3
|
+
def triple_product(vector1, vector2, vector3) -> glm.vec3:
|
|
4
|
+
"""
|
|
5
|
+
Computes (1 x 2) x 3
|
|
6
|
+
"""
|
|
7
|
+
return glm.cross(glm.cross(vector1, vector2), vector3)
|
|
8
|
+
|
|
9
|
+
def relative_transforms(parent, child) -> tuple[glm.vec3, glm.vec3, glm.quat]:
|
|
10
|
+
"""
|
|
11
|
+
Calculates the relative transforms for position, scale, and rotation for the parent and child. parent and child are Nodes
|
|
12
|
+
"""
|
|
13
|
+
relative = glm.inverse(parent.model_matrix) * child.model_matrix
|
|
14
|
+
position = glm.vec3(relative[3])
|
|
15
|
+
scale = glm.vec3([glm.length(relative[i]) for i in range(3)])
|
|
16
|
+
rotation = child.rotation.data * glm.inverse(parent.rotation.data)
|
|
17
|
+
|
|
18
18
|
return position, scale, rotation
|
basilisk/generic/matrices.py
CHANGED
|
@@ -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]
|
basilisk/generic/meshes.py
CHANGED
|
@@ -1,73 +1,73 @@
|
|
|
1
|
-
import glm
|
|
2
|
-
import numpy as np
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
# transformations
|
|
6
|
-
def transform_points(points: np.ndarray, model_matrix: glm.mat4x4) -> list[glm.vec3]:
|
|
7
|
-
"""
|
|
8
|
-
Transforms the mesh points to world space
|
|
9
|
-
"""
|
|
10
|
-
return [model_matrix * pt for pt in points]
|
|
11
|
-
|
|
12
|
-
# bvh
|
|
13
|
-
def get_aabb_surface_area(top_right: glm.vec3, bottom_left: glm.vec3) -> float:
|
|
14
|
-
"""
|
|
15
|
-
Returns the surface area of the AABB
|
|
16
|
-
"""
|
|
17
|
-
diagonal = top_right - bottom_left
|
|
18
|
-
return 2 * (diagonal.x * diagonal.y + diagonal.y * diagonal.z + diagonal.x * diagonal.z)
|
|
19
|
-
|
|
20
|
-
def get_extreme_points_np(points: np.ndarray) -> tuple[glm.vec3, glm.vec3]:
|
|
21
|
-
"""
|
|
22
|
-
Returns the top right and bottom left points of the aabb encapsulating the points
|
|
23
|
-
"""
|
|
24
|
-
top_right = glm.vec3(-1e10)
|
|
25
|
-
bottom_left = glm.vec3(1e10)
|
|
26
|
-
for pt in points:
|
|
27
|
-
for i in range(3):
|
|
28
|
-
if top_right[i] < pt[i]: top_right[i] = pt[i]
|
|
29
|
-
if bottom_left[i] > pt[i]: bottom_left[i] = pt[i]
|
|
30
|
-
return top_right, bottom_left
|
|
31
|
-
|
|
32
|
-
def get_aabb_line_collision(top_right:glm.vec3, bottom_left:glm.vec3, point:glm.vec3, vec:glm.vec3) -> bool:
|
|
33
|
-
"""
|
|
34
|
-
Determines if a line has collided with an aabb
|
|
35
|
-
"""
|
|
36
|
-
tmin, tmax = -1e10, 1e10
|
|
37
|
-
for i in range(3):
|
|
38
|
-
if vec[i] != 0:
|
|
39
|
-
inv_dir = 1.0 / vec[i]
|
|
40
|
-
t1 = (bottom_left[i] - point[i]) * inv_dir
|
|
41
|
-
t2 = (top_right[i] - point[i]) * inv_dir
|
|
42
|
-
t1, t2 = min(t1, t2), max(t1, t2)
|
|
43
|
-
tmin = max(tmin, t1)
|
|
44
|
-
tmax = min(tmax, t2)
|
|
45
|
-
if tmin > tmax: return False
|
|
46
|
-
elif point[i] < bottom_left[i] or point[i] > top_right[i]: return False
|
|
47
|
-
return tmax >= 0 and tmin <= 1
|
|
48
|
-
|
|
49
|
-
def moller_trumbore(point:glm.vec3, vec:glm.vec3, triangle:list[glm.vec3], epsilon:float=1e-7) -> glm.vec3 | None:
|
|
50
|
-
"""
|
|
51
|
-
Determines where a line intersects with a triangle and where that intersection occurred
|
|
52
|
-
"""
|
|
53
|
-
edge1, edge2 = triangle[1] - triangle[0], triangle[2] - triangle[0]
|
|
54
|
-
ray_cross = glm.cross(vec, edge2)
|
|
55
|
-
det = glm.dot(edge1, ray_cross)
|
|
56
|
-
|
|
57
|
-
# if the ray is parallel to the triangle
|
|
58
|
-
if abs(det) < epsilon: return None
|
|
59
|
-
|
|
60
|
-
inv_det = 1 / det
|
|
61
|
-
s = point - triangle[0]
|
|
62
|
-
u = glm.dot(s, ray_cross) * inv_det
|
|
63
|
-
|
|
64
|
-
if (u < 0 and abs(u) > epsilon) or (u > 1 and abs(u - 1) > epsilon): return None
|
|
65
|
-
|
|
66
|
-
s_cross = glm.cross(s, edge1)
|
|
67
|
-
v = glm.dot(vec, s_cross) * inv_det
|
|
68
|
-
|
|
69
|
-
if (v < 0 and abs(v) > epsilon) or (u + v > 1 and abs(u + v - 1) > epsilon): return None
|
|
70
|
-
|
|
71
|
-
t = glm.dot(edge2, s_cross) * inv_det
|
|
72
|
-
if t > epsilon: return point + vec * t
|
|
1
|
+
import glm
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
# transformations
|
|
6
|
+
def transform_points(points: np.ndarray, model_matrix: glm.mat4x4) -> list[glm.vec3]:
|
|
7
|
+
"""
|
|
8
|
+
Transforms the mesh points to world space
|
|
9
|
+
"""
|
|
10
|
+
return [model_matrix * pt for pt in points]
|
|
11
|
+
|
|
12
|
+
# bvh
|
|
13
|
+
def get_aabb_surface_area(top_right: glm.vec3, bottom_left: glm.vec3) -> float:
|
|
14
|
+
"""
|
|
15
|
+
Returns the surface area of the AABB
|
|
16
|
+
"""
|
|
17
|
+
diagonal = top_right - bottom_left
|
|
18
|
+
return 2 * (diagonal.x * diagonal.y + diagonal.y * diagonal.z + diagonal.x * diagonal.z)
|
|
19
|
+
|
|
20
|
+
def get_extreme_points_np(points: np.ndarray) -> tuple[glm.vec3, glm.vec3]:
|
|
21
|
+
"""
|
|
22
|
+
Returns the top right and bottom left points of the aabb encapsulating the points
|
|
23
|
+
"""
|
|
24
|
+
top_right = glm.vec3(-1e10)
|
|
25
|
+
bottom_left = glm.vec3(1e10)
|
|
26
|
+
for pt in points:
|
|
27
|
+
for i in range(3):
|
|
28
|
+
if top_right[i] < pt[i]: top_right[i] = pt[i]
|
|
29
|
+
if bottom_left[i] > pt[i]: bottom_left[i] = pt[i]
|
|
30
|
+
return top_right, bottom_left
|
|
31
|
+
|
|
32
|
+
def get_aabb_line_collision(top_right:glm.vec3, bottom_left:glm.vec3, point:glm.vec3, vec:glm.vec3) -> bool:
|
|
33
|
+
"""
|
|
34
|
+
Determines if a line has collided with an aabb
|
|
35
|
+
"""
|
|
36
|
+
tmin, tmax = -1e10, 1e10
|
|
37
|
+
for i in range(3):
|
|
38
|
+
if vec[i] != 0:
|
|
39
|
+
inv_dir = 1.0 / vec[i]
|
|
40
|
+
t1 = (bottom_left[i] - point[i]) * inv_dir
|
|
41
|
+
t2 = (top_right[i] - point[i]) * inv_dir
|
|
42
|
+
t1, t2 = min(t1, t2), max(t1, t2)
|
|
43
|
+
tmin = max(tmin, t1)
|
|
44
|
+
tmax = min(tmax, t2)
|
|
45
|
+
if tmin > tmax: return False
|
|
46
|
+
elif point[i] < bottom_left[i] or point[i] > top_right[i]: return False
|
|
47
|
+
return tmax >= 0 and tmin <= 1
|
|
48
|
+
|
|
49
|
+
def moller_trumbore(point:glm.vec3, vec:glm.vec3, triangle:list[glm.vec3], epsilon:float=1e-7) -> glm.vec3 | None:
|
|
50
|
+
"""
|
|
51
|
+
Determines where a line intersects with a triangle and where that intersection occurred
|
|
52
|
+
"""
|
|
53
|
+
edge1, edge2 = triangle[1] - triangle[0], triangle[2] - triangle[0]
|
|
54
|
+
ray_cross = glm.cross(vec, edge2)
|
|
55
|
+
det = glm.dot(edge1, ray_cross)
|
|
56
|
+
|
|
57
|
+
# if the ray is parallel to the triangle
|
|
58
|
+
if abs(det) < epsilon: return None
|
|
59
|
+
|
|
60
|
+
inv_det = 1 / det
|
|
61
|
+
s = point - triangle[0]
|
|
62
|
+
u = glm.dot(s, ray_cross) * inv_det
|
|
63
|
+
|
|
64
|
+
if (u < 0 and abs(u) > epsilon) or (u > 1 and abs(u - 1) > epsilon): return None
|
|
65
|
+
|
|
66
|
+
s_cross = glm.cross(s, edge1)
|
|
67
|
+
v = glm.dot(vec, s_cross) * inv_det
|
|
68
|
+
|
|
69
|
+
if (v < 0 and abs(v) > epsilon) or (u + v > 1 and abs(u + v - 1) > epsilon): return None
|
|
70
|
+
|
|
71
|
+
t = glm.dot(edge2, s_cross) * inv_det
|
|
72
|
+
if t > epsilon: return point + vec * t
|
|
73
73
|
return None
|