basilisk-engine 0.1.13__py3-none-any.whl → 0.1.14__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 +14 -14
  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 +27 -24
  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 +95 -95
  45. basilisk/particles/particle_handler.py +63 -63
  46. basilisk/particles/particle_renderer.py +87 -87
  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 +211 -211
  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 +79 -79
  65. basilisk/render/sky.py +120 -120
  66. basilisk/scene.py +276 -270
  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 +21 -21
  71. basilisk/shaders/draw.vert +21 -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.13.dist-info → basilisk_engine-0.1.14.dist-info}/METADATA +45 -38
  84. basilisk_engine-0.1.14.dist-info/RECORD +103 -0
  85. {basilisk_engine-0.1.13.dist-info → basilisk_engine-0.1.14.dist-info}/WHEEL +1 -1
  86. basilisk_engine-0.1.13.dist-info/RECORD +0 -103
  87. {basilisk_engine-0.1.13.dist-info → basilisk_engine-0.1.14.dist-info}/top_level.txt +0 -0
basilisk/__init__.py CHANGED
@@ -1,15 +1,15 @@
1
- import pygame as pg
2
- from .engine import Engine
3
- from .scene import Scene
4
- from .nodes.node import Node
5
- from .mesh.mesh import Mesh
6
- from .render.image import Image
7
- from .render.material import Material
8
- from .render.shader import Shader
9
- from .render.shader_handler import ShaderHandler
10
- from .draw import draw
11
- from .render.camera import FreeCamera, StaticCamera, FollowCamera, OrbitCamera
12
- from .render.sky import Sky
13
- from .render.post_process import PostProcess
14
- from .render.framebuffer import Framebuffer
1
+ import pygame as pg
2
+ from .engine import Engine
3
+ from .scene import Scene
4
+ from .nodes.node import Node
5
+ from .mesh.mesh import Mesh
6
+ from .render.image import Image
7
+ from .render.material import Material
8
+ from .render.shader import Shader
9
+ from .render.shader_handler import ShaderHandler
10
+ from .draw import draw
11
+ from .render.camera import FreeCamera, StaticCamera, FollowCamera, OrbitCamera
12
+ from .render.sky import Sky
13
+ from .render.post_process import PostProcess
14
+ from .render.framebuffer import Framebuffer
15
15
  from .audio.sound import Sound
basilisk/audio/sound.py CHANGED
@@ -1,28 +1,28 @@
1
- import os
2
- import pygame as pg
3
-
4
- class Sound:
5
- def __init__(self, path: str | os.PathLike):
6
- """
7
- Sound object that can be played
8
- """
9
-
10
- if not (isinstance(path, str) or isinstance(path, os.PathLike)):
11
- raise ValueError(f'bsk.Sound: Invalid source path type {type(path)}. Expected string or os.PathLike')
12
-
13
- self.source = pg.mixer.Sound(path)
14
-
15
- def play(self, volume: float=1.0):
16
- """
17
- Play the sound at the given volume level. Full volume if none given
18
- """
19
-
20
- self.source.set_volume(volume)
21
- self.source.play()
22
-
23
- def stop(self):
24
- """
25
- Stops the sound
26
- """
27
-
1
+ import os
2
+ import pygame as pg
3
+
4
+ class Sound:
5
+ def __init__(self, path: str | os.PathLike):
6
+ """
7
+ Sound object that can be played
8
+ """
9
+
10
+ if not (isinstance(path, str) or isinstance(path, os.PathLike)):
11
+ raise ValueError(f'bsk.Sound: Invalid source path type {type(path)}. Expected string or os.PathLike')
12
+
13
+ self.source = pg.mixer.Sound(path)
14
+
15
+ def play(self, volume: float=1.0):
16
+ """
17
+ Play the sound at the given volume level. Full volume if none given
18
+ """
19
+
20
+ self.source.set_volume(volume)
21
+ self.source.play()
22
+
23
+ def stop(self):
24
+ """
25
+ Stops the sound
26
+ """
27
+
28
28
  self.source.stop()
@@ -1,49 +1,49 @@
1
- # Blender 4.1.0
2
- # www.blender.org
3
- mtllib cube.mtl
4
- o Cube
5
- v -1.000000 -1.000000 1.000000
6
- v -1.000000 1.000000 1.000000
7
- v -1.000000 -1.000000 -1.000000
8
- v -1.000000 1.000000 -1.000000
9
- v 1.000000 -1.000000 1.000000
10
- v 1.000000 1.000000 1.000000
11
- v 1.000000 -1.000000 -1.000000
12
- v 1.000000 1.000000 -1.000000
13
- vn -1.0000 -0.0000 -0.0000
14
- vn -0.0000 -0.0000 -1.0000
15
- vn 1.0000 -0.0000 -0.0000
16
- vn -0.0000 -0.0000 1.0000
17
- vn -0.0000 -1.0000 -0.0000
18
- vn -0.0000 1.0000 -0.0000
19
- vt 0.002191 0.000000
20
- vt 0.997809 0.002461
21
- vt 0.996578 0.998078
22
- vt 0.002191 0.994387
23
- vt 0.002191 0.005152
24
- vt 1.000269 0.001461
25
- vt 0.996578 0.999539
26
- vt 0.003422 0.998309
27
- vt 0.000961 0.000461
28
- vt 0.999039 -0.004461
29
- vt 0.996578 0.996078
30
- vt 0.002191 0.993618
31
- vt 0.003422 -0.001769
32
- vt 1.001500 0.001922
33
- vt 0.996578 0.997539
34
- vt 0.002191 1.001230
35
- vt 0.005652 0.000461
36
- vt 0.997578 0.000461
37
- vt 0.995117 1.001000
38
- vt 0.000730 0.998539
39
- vt 0.001191 -0.000769
40
- vt 1.000000 0.000000
41
- vt 0.997479 0.997489
42
- vt 0.006113 0.997309
43
- s 0
44
- f 1/1/1 2/2/1 4/3/1 3/4/1
45
- f 3/5/2 4/6/2 8/7/2 7/8/2
46
- f 7/9/3 8/10/3 6/11/3 5/12/3
47
- f 5/13/4 6/14/4 2/15/4 1/16/4
48
- f 3/17/5 7/18/5 5/19/5 1/20/5
1
+ # Blender 4.1.0
2
+ # www.blender.org
3
+ mtllib cube.mtl
4
+ o Cube
5
+ v -1.000000 -1.000000 1.000000
6
+ v -1.000000 1.000000 1.000000
7
+ v -1.000000 -1.000000 -1.000000
8
+ v -1.000000 1.000000 -1.000000
9
+ v 1.000000 -1.000000 1.000000
10
+ v 1.000000 1.000000 1.000000
11
+ v 1.000000 -1.000000 -1.000000
12
+ v 1.000000 1.000000 -1.000000
13
+ vn -1.0000 -0.0000 -0.0000
14
+ vn -0.0000 -0.0000 -1.0000
15
+ vn 1.0000 -0.0000 -0.0000
16
+ vn -0.0000 -0.0000 1.0000
17
+ vn -0.0000 -1.0000 -0.0000
18
+ vn -0.0000 1.0000 -0.0000
19
+ vt 0.002191 0.000000
20
+ vt 0.997809 0.002461
21
+ vt 0.996578 0.998078
22
+ vt 0.002191 0.994387
23
+ vt 0.002191 0.005152
24
+ vt 1.000269 0.001461
25
+ vt 0.996578 0.999539
26
+ vt 0.003422 0.998309
27
+ vt 0.000961 0.000461
28
+ vt 0.999039 -0.004461
29
+ vt 0.996578 0.996078
30
+ vt 0.002191 0.993618
31
+ vt 0.003422 -0.001769
32
+ vt 1.001500 0.001922
33
+ vt 0.996578 0.997539
34
+ vt 0.002191 1.001230
35
+ vt 0.005652 0.000461
36
+ vt 0.997578 0.000461
37
+ vt 0.995117 1.001000
38
+ vt 0.000730 0.998539
39
+ vt 0.001191 -0.000769
40
+ vt 1.000000 0.000000
41
+ vt 0.997479 0.997489
42
+ vt 0.006113 0.997309
43
+ s 0
44
+ f 1/1/1 2/2/1 4/3/1 3/4/1
45
+ f 3/5/2 4/6/2 8/7/2 7/8/2
46
+ f 7/9/3 8/10/3 6/11/3 5/12/3
47
+ f 5/13/4 6/14/4 2/15/4 1/16/4
48
+ f 3/17/5 7/18/5 5/19/5 1/20/5
49
49
  f 8/21/6 4/22/6 2/23/6 6/24/6
@@ -1,103 +1,103 @@
1
- import glm
2
- from ...generic.abstract_bvh import AbstractAABB as AABB
3
- from ...generic.collisions import collide_aabb_aabb, collide_aabb_line
4
- from ...generic.meshes import get_aabb_surface_area
5
- from ..collider import Collider
6
-
7
-
8
- class BroadAABB(AABB):
9
- a: AABB | Collider
10
- """The first child of the AABB"""
11
- b: AABB | Collider
12
- """The second child of the AABB"""
13
- top_right: glm.vec3
14
- """furthest positive vertex of the AABB"""
15
- bottom_left: glm.vec3
16
- """furthest negative vertex of the AABB"""
17
- parent: AABB
18
- """Back reference to the parent AABB"""
19
-
20
- def __init__(self, a: AABB | Collider, b: AABB | Collider, parent: AABB) -> None:
21
- self.a = a
22
- self.b = b
23
- self.parent = parent
24
-
25
- # calculate extreme points
26
- self.update_points()
27
-
28
- def update_points(self) -> None:
29
- """
30
- Updates the extreme points of the AABB based on the children
31
- """
32
- self.top_right = glm.max(self.a.top_right, self.b.top_right)
33
- self.bottom_left = glm.min(self.a.bottom_left, self.b.bottom_left)
34
-
35
- def find_sibling(self, collider: Collider, inherited: float) -> tuple[float, AABB | Collider]:
36
- """
37
- Determines the best sibling for inserting a collider into the BVH
38
- """
39
- # compute estimate sa
40
- top_right = glm.max(self.top_right, collider.top_right)
41
- bottom_left = glm.min(self.bottom_left, collider.bottom_left)
42
- union_area = get_aabb_surface_area(top_right, bottom_left)
43
-
44
- # compute lowest cost and determine if children are a viable option
45
- c_best = union_area + inherited
46
-
47
- delta_surface_area = union_area - self.surface_area
48
-
49
- c_low = collider.aabb_surface_area + delta_surface_area + inherited
50
-
51
- # investigate children
52
- best_sibling = self
53
- if c_low >= c_best: return c_best, best_sibling
54
-
55
- for child in (self.a, self.b):
56
- if isinstance(child, BroadAABB): child_c, child_aabb = child.find_sibling(collider, inherited + delta_surface_area)
57
- else:
58
- # compute cost for child
59
- top_right = glm.max(self.top_right, child.top_right)
60
- bottom_left = glm.min(self.bottom_left, child.bottom_left)
61
- union_area = get_aabb_surface_area(top_right, bottom_left)
62
-
63
- child_c, child_aabb = union_area + inherited, child
64
-
65
- if child_c < c_best: c_best, best_sibling = child_c, child_aabb
66
-
67
- return c_best, best_sibling
68
-
69
- def get_collided(self, collider: Collider) -> list[Collider]:
70
- """
71
- Returns which objects may be colliding from the BVH
72
- """
73
- if not collide_aabb_aabb(self.top_right, self.bottom_left, collider.top_right, collider.bottom_left): return []
74
-
75
- # test children
76
- possible = []
77
- if isinstance(self.a, BroadAABB): possible.extend(self.a.get_collided(collider))
78
- elif collide_aabb_aabb(self.a.top_right, self.a.bottom_left, collider.top_right, collider.bottom_left): possible.append(self.a)
79
- if isinstance(self.b, BroadAABB): possible.extend(self.b.get_collided(collider))
80
- elif collide_aabb_aabb(self.b.top_right, self.b.bottom_left, collider.top_right, collider.bottom_left): possible.append(self.b)
81
- return possible
82
-
83
- def get_line_collided(self, position: glm.vec3, forward: glm.vec3) -> list[Collider]:
84
- """
85
- Returns the colliders that may intersect with the given line
86
- """
87
- if not collide_aabb_line(self.top_right, self.bottom_left, position, forward): return []
88
- return (self.a.get_line_collided(position, forward) if isinstance(self.a, BroadAABB) else [self.a]) + (self.b.get_line_collided(position, forward) if isinstance(self.b, BroadAABB) else [self.b])
89
-
90
- def get_all_aabbs(self, layer: int) -> list[tuple[glm.vec3, glm.vec3, int]]: # TODO test function
91
- """
92
- Returns all AABBs, their extreme points, and their layer
93
- """
94
- aabbs = [(self.top_right, self.bottom_left, layer)]
95
- if isinstance(self.a, BroadAABB): aabbs += self.a.get_all_aabbs(layer + 1)
96
- else: aabbs.append((self.a.top_right, self.a.bottom_left, layer + 1))
97
- if isinstance(self.b, BroadAABB): aabbs += self.b.get_all_aabbs(layer + 1)
98
- else: aabbs.append((self.b.top_right, self.b.bottom_left, layer + 1))
99
- return aabbs
100
-
101
- @property
102
- def surface_area(self): return get_aabb_surface_area(self.top_right, self.bottom_left)
1
+ import glm
2
+ from ...generic.abstract_bvh import AbstractAABB as AABB
3
+ from ...generic.collisions import collide_aabb_aabb, collide_aabb_line
4
+ from ...generic.meshes import get_aabb_surface_area
5
+ from ..collider import Collider
6
+
7
+
8
+ class BroadAABB(AABB):
9
+ a: AABB | Collider
10
+ """The first child of the AABB"""
11
+ b: AABB | Collider
12
+ """The second child of the AABB"""
13
+ top_right: glm.vec3
14
+ """furthest positive vertex of the AABB"""
15
+ bottom_left: glm.vec3
16
+ """furthest negative vertex of the AABB"""
17
+ parent: AABB
18
+ """Back reference to the parent AABB"""
19
+
20
+ def __init__(self, a: AABB | Collider, b: AABB | Collider, parent: AABB) -> None:
21
+ self.a = a
22
+ self.b = b
23
+ self.parent = parent
24
+
25
+ # calculate extreme points
26
+ self.update_points()
27
+
28
+ def update_points(self) -> None:
29
+ """
30
+ Updates the extreme points of the AABB based on the children
31
+ """
32
+ self.top_right = glm.max(self.a.top_right, self.b.top_right)
33
+ self.bottom_left = glm.min(self.a.bottom_left, self.b.bottom_left)
34
+
35
+ def find_sibling(self, collider: Collider, inherited: float) -> tuple[float, AABB | Collider]:
36
+ """
37
+ Determines the best sibling for inserting a collider into the BVH
38
+ """
39
+ # compute estimate sa
40
+ top_right = glm.max(self.top_right, collider.top_right)
41
+ bottom_left = glm.min(self.bottom_left, collider.bottom_left)
42
+ union_area = get_aabb_surface_area(top_right, bottom_left)
43
+
44
+ # compute lowest cost and determine if children are a viable option
45
+ c_best = union_area + inherited
46
+
47
+ delta_surface_area = union_area - self.surface_area
48
+
49
+ c_low = collider.aabb_surface_area + delta_surface_area + inherited
50
+
51
+ # investigate children
52
+ best_sibling = self
53
+ if c_low >= c_best: return c_best, best_sibling
54
+
55
+ for child in (self.a, self.b):
56
+ if isinstance(child, BroadAABB): child_c, child_aabb = child.find_sibling(collider, inherited + delta_surface_area)
57
+ else:
58
+ # compute cost for child
59
+ top_right = glm.max(self.top_right, child.top_right)
60
+ bottom_left = glm.min(self.bottom_left, child.bottom_left)
61
+ union_area = get_aabb_surface_area(top_right, bottom_left)
62
+
63
+ child_c, child_aabb = union_area + inherited, child
64
+
65
+ if child_c < c_best: c_best, best_sibling = child_c, child_aabb
66
+
67
+ return c_best, best_sibling
68
+
69
+ def get_collided(self, collider: Collider) -> list[Collider]:
70
+ """
71
+ Returns which objects may be colliding from the BVH
72
+ """
73
+ if not collide_aabb_aabb(self.top_right, self.bottom_left, collider.top_right, collider.bottom_left): return []
74
+
75
+ # test children
76
+ possible = []
77
+ if isinstance(self.a, BroadAABB): possible.extend(self.a.get_collided(collider))
78
+ elif collide_aabb_aabb(self.a.top_right, self.a.bottom_left, collider.top_right, collider.bottom_left): possible.append(self.a)
79
+ if isinstance(self.b, BroadAABB): possible.extend(self.b.get_collided(collider))
80
+ elif collide_aabb_aabb(self.b.top_right, self.b.bottom_left, collider.top_right, collider.bottom_left): possible.append(self.b)
81
+ return possible
82
+
83
+ def get_line_collided(self, position: glm.vec3, forward: glm.vec3) -> list[Collider]:
84
+ """
85
+ Returns the colliders that may intersect with the given line
86
+ """
87
+ if not collide_aabb_line(self.top_right, self.bottom_left, position, forward): return []
88
+ return (self.a.get_line_collided(position, forward) if isinstance(self.a, BroadAABB) else [self.a]) + (self.b.get_line_collided(position, forward) if isinstance(self.b, BroadAABB) else [self.b])
89
+
90
+ def get_all_aabbs(self, layer: int) -> list[tuple[glm.vec3, glm.vec3, int]]: # TODO test function
91
+ """
92
+ Returns all AABBs, their extreme points, and their layer
93
+ """
94
+ aabbs = [(self.top_right, self.bottom_left, layer)]
95
+ if isinstance(self.a, BroadAABB): aabbs += self.a.get_all_aabbs(layer + 1)
96
+ else: aabbs.append((self.a.top_right, self.a.bottom_left, layer + 1))
97
+ if isinstance(self.b, BroadAABB): aabbs += self.b.get_all_aabbs(layer + 1)
98
+ else: aabbs.append((self.b.top_right, self.b.bottom_left, layer + 1))
99
+ return aabbs
100
+
101
+ @property
102
+ def surface_area(self): return get_aabb_surface_area(self.top_right, self.bottom_left)
103
103
 
@@ -1,138 +1,138 @@
1
- import glm
2
- from .broad_aabb import BroadAABB
3
- from ..collider import Collider
4
- from ...generic.abstract_bvh import AbstractBVH as BVH
5
- from ...generic.meshes import get_aabb_surface_area
6
-
7
- class BroadBVH(BVH):
8
- root: BroadAABB
9
- """The root node of the BVH"""
10
- collider_handler: ...
11
- """Back reference to the collider ahndler for accessing colliders"""
12
-
13
- def __init__(self, collider_handler) -> None:
14
- self.collider_handler = collider_handler
15
- self.root = None
16
-
17
- def add(self, collider: Collider) -> None:
18
- """
19
- Adds a single collider to the bvh tree
20
- """
21
- # test if tree needs to be initiated
22
- if not self.root:
23
- self.root = collider # TODO ensure that this is final format for primative
24
- return
25
-
26
- # check if root is primative
27
- if isinstance(self.root, Collider):
28
- sibling = self.root
29
- self.root = BroadAABB(sibling, collider, None)
30
- sibling.parent = collider.parent = self.root
31
- return
32
-
33
- # find the best sibling (c_best only used during the recursion)
34
- c_best, sibling = self.root.find_sibling(collider, 0)
35
- old_parent = sibling.parent
36
- new_parent = BroadAABB(sibling, collider, old_parent)
37
-
38
- # if the sibling was not the root
39
- if old_parent:
40
- if old_parent.a == sibling: old_parent.a = new_parent
41
- else: old_parent.b = new_parent
42
- else: self.root = new_parent
43
-
44
- sibling.parent = new_parent
45
- collider.parent = new_parent
46
-
47
- # walk back up tree and refit TODO add tree rotations
48
- aabb = new_parent
49
- while aabb:
50
- aabb.update_points()
51
- self.rotate(aabb)
52
- aabb = aabb.parent
53
-
54
- def get_all_aabbs(self) -> list[tuple[glm.vec3, glm.vec3, int]]: # TODO test function
55
- """
56
- Returns all AABBs, their extreme points, and their layer
57
- """
58
- if isinstance(self.root, BroadAABB): return self.root.get_all_aabbs(0)
59
- return [(self.root.top_right, self.root.bottom_left, 0)]
60
-
61
- def remove(self, collider: Collider) -> None:
62
- """
63
- Removes a collider from the BVH, refitting the tree and adjusting relations
64
- """
65
- parent: BroadAABB | None = collider.parent
66
-
67
- # if collider is the root, remove the root
68
- if not parent:
69
- self.root = None
70
- return
71
-
72
- # if collider has no grandparent, remove parent and set sibling as root
73
- grand = parent.parent
74
- sibling = parent.b if collider == parent.a else parent.a
75
- if not grand:
76
- self.root = sibling
77
- sibling.parent = None
78
- return
79
-
80
- # if grandparent exists
81
- if parent == grand.a: grand.a = sibling
82
- else: grand.b = sibling
83
- sibling.parent = grand
84
-
85
- # move up and refit tree
86
- aabb = grand
87
- while aabb:
88
- aabb.update_points()
89
- aabb = aabb.parent
90
-
91
- def rotate(self, aabb: BroadAABB) -> None:
92
- """
93
- Rotates the BVH tree to reduce surface area of internal AABBs
94
- """
95
- # determine if rotation is possible
96
- parent: BroadAABB | None = aabb.parent
97
- if not parent: return
98
-
99
- grand = parent.parent
100
- if not grand: return
101
-
102
- # determine if swapping
103
- aunt = grand.b if grand.a == parent else grand.a
104
- sibling = parent.b if parent.a == aabb else parent.a
105
-
106
- top_right = glm.max(aunt.top_right, sibling.top_right)
107
- bottom_left = glm.min(aunt.bottom_left, sibling.bottom_left)
108
- aunt_sibling_area = get_aabb_surface_area(top_right, bottom_left)
109
-
110
- if aunt_sibling_area > parent.surface_area: return
111
-
112
- # rotate tree if necessary
113
- if grand.a == aunt: grand.a = aabb
114
- else: grand.b = aabb
115
-
116
- if parent.a == aabb: parent.a = aunt
117
- else: parent.b = aunt
118
-
119
- # reset parents and update points to resize AABBs
120
- aunt.parent = parent
121
- aabb.parent = grand
122
-
123
- parent.update_points()
124
- grand.update_points()
125
-
126
- def get_collided(self, collider: Collider) -> list[Collider]:
127
- """
128
- Returns which objects may be colliding from the BVH
129
- """
130
- if isinstance(self.root, BroadAABB): return self.root.get_collided(collider)
131
- else: return [] # if there is only one collider in the scene then there is nothing to collide with
132
-
133
- def get_line_collided(self, position: glm.vec3, forward: glm.vec3) -> list[Collider]:
134
- """
135
- Returns the colliders that may intersect with the given line
136
- """
137
- if isinstance(self.root, BroadAABB): return self.root.get_line_collided(position, forward)
1
+ import glm
2
+ from .broad_aabb import BroadAABB
3
+ from ..collider import Collider
4
+ from ...generic.abstract_bvh import AbstractBVH as BVH
5
+ from ...generic.meshes import get_aabb_surface_area
6
+
7
+ class BroadBVH(BVH):
8
+ root: BroadAABB
9
+ """The root node of the BVH"""
10
+ collider_handler: ...
11
+ """Back reference to the collider ahndler for accessing colliders"""
12
+
13
+ def __init__(self, collider_handler) -> None:
14
+ self.collider_handler = collider_handler
15
+ self.root = None
16
+
17
+ def add(self, collider: Collider) -> None:
18
+ """
19
+ Adds a single collider to the bvh tree
20
+ """
21
+ # test if tree needs to be initiated
22
+ if not self.root:
23
+ self.root = collider # TODO ensure that this is final format for primative
24
+ return
25
+
26
+ # check if root is primative
27
+ if isinstance(self.root, Collider):
28
+ sibling = self.root
29
+ self.root = BroadAABB(sibling, collider, None)
30
+ sibling.parent = collider.parent = self.root
31
+ return
32
+
33
+ # find the best sibling (c_best only used during the recursion)
34
+ c_best, sibling = self.root.find_sibling(collider, 0)
35
+ old_parent = sibling.parent
36
+ new_parent = BroadAABB(sibling, collider, old_parent)
37
+
38
+ # if the sibling was not the root
39
+ if old_parent:
40
+ if old_parent.a == sibling: old_parent.a = new_parent
41
+ else: old_parent.b = new_parent
42
+ else: self.root = new_parent
43
+
44
+ sibling.parent = new_parent
45
+ collider.parent = new_parent
46
+
47
+ # walk back up tree and refit TODO add tree rotations
48
+ aabb = new_parent
49
+ while aabb:
50
+ aabb.update_points()
51
+ self.rotate(aabb)
52
+ aabb = aabb.parent
53
+
54
+ def get_all_aabbs(self) -> list[tuple[glm.vec3, glm.vec3, int]]: # TODO test function
55
+ """
56
+ Returns all AABBs, their extreme points, and their layer
57
+ """
58
+ if isinstance(self.root, BroadAABB): return self.root.get_all_aabbs(0)
59
+ return [(self.root.top_right, self.root.bottom_left, 0)]
60
+
61
+ def remove(self, collider: Collider) -> None:
62
+ """
63
+ Removes a collider from the BVH, refitting the tree and adjusting relations
64
+ """
65
+ parent: BroadAABB | None = collider.parent
66
+
67
+ # if collider is the root, remove the root
68
+ if not parent:
69
+ self.root = None
70
+ return
71
+
72
+ # if collider has no grandparent, remove parent and set sibling as root
73
+ grand = parent.parent
74
+ sibling = parent.b if collider == parent.a else parent.a
75
+ if not grand:
76
+ self.root = sibling
77
+ sibling.parent = None
78
+ return
79
+
80
+ # if grandparent exists
81
+ if parent == grand.a: grand.a = sibling
82
+ else: grand.b = sibling
83
+ sibling.parent = grand
84
+
85
+ # move up and refit tree
86
+ aabb = grand
87
+ while aabb:
88
+ aabb.update_points()
89
+ aabb = aabb.parent
90
+
91
+ def rotate(self, aabb: BroadAABB) -> None:
92
+ """
93
+ Rotates the BVH tree to reduce surface area of internal AABBs
94
+ """
95
+ # determine if rotation is possible
96
+ parent: BroadAABB | None = aabb.parent
97
+ if not parent: return
98
+
99
+ grand = parent.parent
100
+ if not grand: return
101
+
102
+ # determine if swapping
103
+ aunt = grand.b if grand.a == parent else grand.a
104
+ sibling = parent.b if parent.a == aabb else parent.a
105
+
106
+ top_right = glm.max(aunt.top_right, sibling.top_right)
107
+ bottom_left = glm.min(aunt.bottom_left, sibling.bottom_left)
108
+ aunt_sibling_area = get_aabb_surface_area(top_right, bottom_left)
109
+
110
+ if aunt_sibling_area > parent.surface_area: return
111
+
112
+ # rotate tree if necessary
113
+ if grand.a == aunt: grand.a = aabb
114
+ else: grand.b = aabb
115
+
116
+ if parent.a == aabb: parent.a = aunt
117
+ else: parent.b = aunt
118
+
119
+ # reset parents and update points to resize AABBs
120
+ aunt.parent = parent
121
+ aabb.parent = grand
122
+
123
+ parent.update_points()
124
+ grand.update_points()
125
+
126
+ def get_collided(self, collider: Collider) -> list[Collider]:
127
+ """
128
+ Returns which objects may be colliding from the BVH
129
+ """
130
+ if isinstance(self.root, BroadAABB): return self.root.get_collided(collider)
131
+ else: return [] # if there is only one collider in the scene then there is nothing to collide with
132
+
133
+ def get_line_collided(self, position: glm.vec3, forward: glm.vec3) -> list[Collider]:
134
+ """
135
+ Returns the colliders that may intersect with the given line
136
+ """
137
+ if isinstance(self.root, BroadAABB): return self.root.get_line_collided(position, forward)
138
138
  return [self.root]