basilisk-engine 0.0.1__py3-none-any.whl → 0.0.3__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 (62) hide show
  1. basilisk/bsk_assets/__init__.py +0 -0
  2. basilisk/collisions/__init__.py +0 -0
  3. basilisk/collisions/broad/__init__.py +0 -0
  4. basilisk/collisions/broad/broad_aabb.py +96 -0
  5. basilisk/collisions/broad/broad_bvh.py +102 -0
  6. basilisk/collisions/collider.py +75 -0
  7. basilisk/collisions/collider_handler.py +163 -0
  8. basilisk/collisions/narrow/__init__.py +0 -0
  9. basilisk/collisions/narrow/epa.py +86 -0
  10. basilisk/collisions/narrow/gjk.py +66 -0
  11. basilisk/collisions/narrow/helper.py +23 -0
  12. basilisk/draw/__init__.py +0 -0
  13. basilisk/draw/draw.py +101 -0
  14. basilisk/draw/draw_handler.py +208 -0
  15. basilisk/draw/font_renderer.py +28 -0
  16. basilisk/generic/__init__.py +0 -0
  17. basilisk/generic/abstract_bvh.py +16 -0
  18. basilisk/generic/collisions.py +26 -0
  19. basilisk/generic/input_validation.py +28 -0
  20. basilisk/generic/math.py +7 -0
  21. basilisk/generic/matrices.py +34 -0
  22. basilisk/generic/meshes.py +73 -0
  23. basilisk/generic/quat.py +119 -0
  24. basilisk/generic/quat_methods.py +8 -0
  25. basilisk/generic/vec3.py +112 -0
  26. basilisk/input/__init__.py +0 -0
  27. basilisk/input/mouse.py +60 -0
  28. basilisk/mesh/__init__.py +0 -0
  29. basilisk/mesh/built-in/__init__.py +0 -0
  30. basilisk/mesh/cube.py +20 -0
  31. basilisk/mesh/mesh.py +216 -0
  32. basilisk/mesh/mesh_from_data.py +48 -0
  33. basilisk/mesh/model.py +272 -0
  34. basilisk/mesh/narrow_aabb.py +81 -0
  35. basilisk/mesh/narrow_bvh.py +84 -0
  36. basilisk/mesh/narrow_primative.py +24 -0
  37. basilisk/nodes/__init__.py +0 -0
  38. basilisk/nodes/node.py +508 -0
  39. basilisk/nodes/node_handler.py +94 -0
  40. basilisk/physics/__init__.py +0 -0
  41. basilisk/physics/physics_body.py +36 -0
  42. basilisk/physics/physics_engine.py +37 -0
  43. basilisk/render/__init__.py +0 -0
  44. basilisk/render/batch.py +85 -0
  45. basilisk/render/camera.py +166 -0
  46. basilisk/render/chunk.py +85 -0
  47. basilisk/render/chunk_handler.py +139 -0
  48. basilisk/render/frame.py +182 -0
  49. basilisk/render/image.py +76 -0
  50. basilisk/render/image_handler.py +119 -0
  51. basilisk/render/light.py +97 -0
  52. basilisk/render/light_handler.py +54 -0
  53. basilisk/render/material.py +196 -0
  54. basilisk/render/material_handler.py +123 -0
  55. basilisk/render/shader_handler.py +95 -0
  56. basilisk/render/sky.py +118 -0
  57. basilisk/shaders/__init__.py +0 -0
  58. {basilisk_engine-0.0.1.dist-info → basilisk_engine-0.0.3.dist-info}/METADATA +1 -1
  59. basilisk_engine-0.0.3.dist-info/RECORD +65 -0
  60. basilisk_engine-0.0.1.dist-info/RECORD +0 -8
  61. {basilisk_engine-0.0.1.dist-info → basilisk_engine-0.0.3.dist-info}/WHEEL +0 -0
  62. {basilisk_engine-0.0.1.dist-info → basilisk_engine-0.0.3.dist-info}/top_level.txt +0 -0
basilisk/mesh/model.py ADDED
@@ -0,0 +1,272 @@
1
+ import numpy as np
2
+ import glm
3
+
4
+
5
+ class Model:
6
+ """
7
+ Instance of a loaded model. Contains all objects, groups, and vertex data
8
+ model.vertex_data contains all vertex data
9
+ Objects stored in the model.objects dictionary, where keys are the object names (marked by 'o') in the .obj
10
+ Default object key is '0'
11
+ """
12
+
13
+ def __init__(self) -> None:
14
+ self.objects = {0 : VertexObject()}
15
+
16
+ self.vertex_data = []
17
+ """All vertex data in the obj. Use this for buffer data"""
18
+ self.tangent_data = []
19
+ """Tangents and bitangents"""
20
+ self.format = None
21
+ self.attribs = None
22
+
23
+ self.vertex_points = []
24
+ """The unique points given by the file"""
25
+ self.vertex_uv = []
26
+ """The unique texture coordinates given by the file"""
27
+ self.vertex_normals = []
28
+ """The unique normals given by the file"""
29
+
30
+ self.point_indices = []
31
+ """Indices of to vertex_points to construct triangles. Grouped in three."""
32
+ self.uv_indices = []
33
+ """Indices of to vertex_uv to construct triangles. Grouped in three."""
34
+ self.normal_indices = []
35
+ """Indices of to vertex_normals to construct triangles. Grouped in three."""
36
+
37
+
38
+ def __repr__(self) -> str:
39
+ return_string = '<Model | objects: {'
40
+ for vertex_object in self.objects.keys():
41
+ return_string += str(vertex_object) + ', '
42
+ return_string = return_string[:-2] + '}>'
43
+ return return_string
44
+
45
+
46
+ class VertexObject:
47
+ """
48
+ Object conataining groups of vertices.
49
+ Groups stored in the vertex_object.groups dictionary, where keys are the group names (marked by 'g') in the .obj
50
+ Default group key is '0'
51
+ """
52
+
53
+ def __init__(self) -> None:
54
+ self.groups = {0 : VertexGroup()}
55
+
56
+ def __repr__(self) -> str:
57
+ return_string = '<Vertex Object | groups: {'
58
+ for vertex_group in self.groups.keys():
59
+ return_string += str(vertex_group) + ', '
60
+ return_string = return_string[:-2] + '}>'
61
+ return return_string
62
+
63
+
64
+ class VertexGroup:
65
+ """
66
+ Groups containing the vertex data
67
+ vertex_group.vertex_data will be a numpy array of vertices
68
+ """
69
+
70
+ def __init__(self) -> None:
71
+ self.vertex_data = []
72
+ self.tangent_data = []
73
+
74
+ def __repr__(self) -> str:
75
+ return f'<Vertex Group | {self.vertex_data}>'
76
+
77
+
78
+ def load_model(obj_file: str, calculate_tangents=False) -> Model:
79
+ """
80
+ Loads an obj model. Returns a model class instance
81
+ model.vertex_data contains all vertex data combined in a single numpy array
82
+ Args:
83
+ file:
84
+ Path to the .obj file to load
85
+ calculate_tangents:
86
+ Calculates the tangent and bitangent vectors for normal mapping
87
+ """
88
+
89
+ model = Model()
90
+ current_object = 0
91
+ current_group = 0
92
+
93
+ vertex_format = None
94
+ vertex_attribs = None
95
+
96
+ with open(obj_file, 'r') as file:
97
+ line = file.readline()
98
+ while line:
99
+ line = line.strip()
100
+
101
+ # Add object
102
+ if line.startswith('o '):
103
+ if line[2:].strip() not in model.objects:
104
+ model.objects[line[2:].strip()] = VertexObject()
105
+ current_object = line[2:].strip()
106
+
107
+ # Add group
108
+ elif line.startswith('g '):
109
+ if line[2:].strip() not in model.objects[current_object].groups:
110
+ model.objects[current_object].groups[line[2:].strip()] = VertexGroup()
111
+ current_group = line[2:].strip()
112
+
113
+ # Add vertex point
114
+ elif line.startswith('v '):
115
+ points = list(map(float, line[2:].strip().split(' ')))
116
+ model.vertex_points.append(points)
117
+
118
+ # Add vertex UV
119
+ elif line.startswith('vt '):
120
+ uvs = list(map(float, line[3:].strip().split(' ')))
121
+ model.vertex_uv.append(uvs[:2])
122
+
123
+ # Add vertex normals
124
+ elif line.startswith('vn '):
125
+ normals = list(map(float, line[3:].strip().split(' ')))
126
+ model.vertex_normals.append(normals)
127
+
128
+ # Create faces
129
+ elif line.startswith('f '):
130
+ corners = line[2:].strip().split(' ')
131
+ # The index of the position, uv, and normal in each vertex
132
+ vertex_indices = [[0, 0, 0] for i in range(len(corners))]
133
+ for corner_index, corner in enumerate(corners):
134
+ corner = corner.split('/')
135
+
136
+ if not vertex_format:
137
+ if len(corner) == 1:
138
+ vertex_format = '3f'
139
+ vertex_attribs = ['in_position']
140
+ elif not corner[1]:
141
+ vertex_format = '3f 3f'
142
+ vertex_attribs = ['in_position', 'in_normal']
143
+ else:
144
+ vertex_format = '3f 2f 3f'
145
+ vertex_attribs = ['in_position', 'in_uv', 'in_normal']
146
+
147
+ vertex = []
148
+
149
+ # Add each attribute to the vertex
150
+ for attribute, index in enumerate(corner):
151
+ if attribute == 0 and index:
152
+ vertex += model.vertex_points[int(index) - 1]
153
+ vertex_indices[corner_index][0] = int(index) - 1
154
+ if attribute == 1 and index:
155
+ vertex += model.vertex_uv[int(index) - 1]
156
+ vertex_indices[corner_index][1] = int(index) - 1
157
+ if attribute == 2 and index:
158
+ vertex += model.vertex_normals[int(index) - 1]
159
+ vertex_indices[corner_index][2] = int(index) - 1
160
+
161
+ # Replace the vertex data
162
+ corners[corner_index] = vertex
163
+
164
+ # Add each triangle to the objects vertex array
165
+ for triangle in range(len(corners) - 2):
166
+ if 'in_normal' not in vertex_attribs: # If the model doesnt have normals, calculate face normals
167
+ p1 = glm.vec3(corners[0])
168
+ p2 = glm.vec3(corners[1 + triangle])
169
+ p3 = glm.vec3(corners[2 + triangle])
170
+ normal = glm.normalize(glm.cross(p2 - p1, p3 - p1))
171
+ normal = list(normal.xyz)
172
+ model.vertex_normals.append(normal)
173
+ model.objects[current_object].groups[current_group].vertex_data.append(corners[0] + normal)
174
+ model.objects[current_object].groups[current_group].vertex_data.append(corners[1 + triangle] + normal)
175
+ model.objects[current_object].groups[current_group].vertex_data.append(corners[2 + triangle] + normal)
176
+
177
+ # Add the triangle to the indices
178
+ model.point_indices.append([vertex_indices[0][0], vertex_indices[1 + triangle][0], vertex_indices[2 + triangle][0]])
179
+ model.normal_indices.append([len(model.vertex_normals) - 1] * 3)
180
+ else: # Standard reading
181
+ model.objects[current_object].groups[current_group].vertex_data.append(corners[0])
182
+ model.objects[current_object].groups[current_group].vertex_data.append(corners[1 + triangle])
183
+ model.objects[current_object].groups[current_group].vertex_data.append(corners[2 + triangle])
184
+
185
+ # Add the triangle to the indices
186
+ model.point_indices.append([vertex_indices[0][0], vertex_indices[1 + triangle][0], vertex_indices[2 + triangle][0]])
187
+ model.uv_indices.append([vertex_indices[0][1], vertex_indices[1 + triangle][1], vertex_indices[2 + triangle][1]])
188
+ model.normal_indices.append([vertex_indices[0][2], vertex_indices[1 + triangle][2], vertex_indices[2 + triangle][2]])
189
+
190
+ # Calculate the tangents and bitangents
191
+ if calculate_tangents and 'in_uv' in vertex_attribs:
192
+ v1 = corners[0]
193
+ v2 = corners[1 + triangle]
194
+ v3 = corners[2 + triangle]
195
+
196
+ x1 = v2[0] - v1[0]
197
+ x2 = v3[0] - v1[0]
198
+ y1 = v2[1] - v1[1]
199
+ y2 = v3[1] - v1[1]
200
+ z1 = v2[2] - v1[2]
201
+ z2 = v3[2] - v1[2]
202
+
203
+ s1 = v2[3] - v1[3]
204
+ s2 = v3[3] - v1[3]
205
+ t1 = v2[4] - v1[4]
206
+ t2 = v3[4] - v1[4]
207
+
208
+ if (s1 * t2 - s2 * t1): r = 1.0 / (s1 * t2 - s2 * t1)
209
+ else: r = 1
210
+
211
+ tangent = glm.normalize(((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r))
212
+ bitangent = glm.normalize(((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r))
213
+
214
+ T = np.array(tangent)
215
+ U = np.array(bitangent)
216
+ N1 = np.array(corners[0][5:8])
217
+ N2 = np.array(corners[1 + triangle][5:8])
218
+ N3 = np.array(corners[2 + triangle][5:8])
219
+
220
+ T1 = T - np.dot(N1, T) * N1
221
+ T2 = T - np.dot(N2, T) * N2
222
+ T3 = T - np.dot(N3, T) * N3
223
+ U1 = U - np.dot(N1, U) * N1 - np.dot(T1, U) * T1
224
+ U2 = U - np.dot(N2, U) * N2 - np.dot(T2, U) * T2
225
+ U3 = U - np.dot(N3, U) * N3 - np.dot(T3, U) * T3
226
+
227
+ data = [[*T1, *U1], [*T2, *U2], [*T3, *U3]]
228
+
229
+ model.objects[current_object].groups[current_group].tangent_data.extend(data)
230
+
231
+ line = file.readline()
232
+
233
+ vertex_groups = []
234
+ tangent_groups = []
235
+
236
+ # Loop through all vertex objects and groups in the model
237
+ for object in model.objects.values():
238
+ for group in object.groups.values():
239
+ # Ignore empty groups
240
+ if not len(group.vertex_data): continue
241
+ # Convert to a numpy array
242
+ group.vertex_data = np.array(group.vertex_data, dtype='f4')
243
+ # Add to the vertex_groups list to be stacked
244
+ vertex_groups.append(group.vertex_data)
245
+ tangent_groups.append(group.tangent_data)
246
+
247
+ # Array of all vertices from all the model's groups combined
248
+ vertices = np.vstack(vertex_groups, dtype='f4')
249
+ tangents = np.vstack(tangent_groups, dtype='f4')
250
+
251
+ # Save the model's combined vertices
252
+ model.vertex_data = vertices
253
+ model.tangent_data = tangents
254
+
255
+ # Convert the points and indices to array for convenience with C-like buffers
256
+ model.vertex_points = np.array(model.vertex_points, dtype="f4")
257
+ model.vertex_uv = np.array(model.vertex_uv, dtype="f4")
258
+ model.vertex_normals = np.array(model.vertex_normals, dtype="f4")
259
+ model.point_indices = np.array(model.point_indices, dtype="i4")
260
+ model.uv_indices = np.array(model.uv_indices, dtype="i4")
261
+ model.normal_indices = np.array(model.normal_indices, dtype="i4")
262
+
263
+ # Add normals to position only models
264
+ if vertex_format == '3f':
265
+ vertex_format = '3f 3f'
266
+ vertex_attribs = ['in_position', 'in_normal']
267
+
268
+ # Save the model vertex format and attribs
269
+ model.format = vertex_format
270
+ model.attribs = vertex_attribs
271
+
272
+ return model
@@ -0,0 +1,81 @@
1
+ import glm
2
+ from .narrow_primative import NarrowPrimative
3
+ from ..generic.abstract_bvh import AbstractAABB as AABB
4
+ from ..generic.meshes import get_aabb_line_collision
5
+
6
+ class NarrowAABB(AABB):
7
+ top_right: glm.vec3
8
+ """The furthest positive corner of the AABB"""
9
+ bottom_left: glm.vec3
10
+ """The furthest negative corner of the AABB"""
11
+ geometric_center: glm.vec3
12
+ """The center of the object calculated from its extreme points"""
13
+ a: AABB | NarrowPrimative
14
+ """Child AABB or Collider 1"""
15
+ b: AABB | NarrowPrimative
16
+ """Child AABB or Collider 2"""
17
+
18
+ def __init__(self, top_right:glm.vec3, bottom_left:glm.vec3, a: AABB, b: AABB) -> None:
19
+ self.top_right = top_right
20
+ self.bottom_left = bottom_left
21
+ self.geometric_center = (top_right + bottom_left) / 2
22
+ self.a = a
23
+ self.b = b
24
+
25
+ def get_possible_triangles(self, point: glm.vec3, vec: glm.vec3) -> list[int]:
26
+ """
27
+ Determines the closest intersecting on the bvh
28
+ """
29
+ indices = []
30
+ if not get_aabb_line_collision(self.top_right, self.bottom_left, point, vec): return indices
31
+
32
+ for child in (self.a, self.b):
33
+
34
+ # if child is another AABB
35
+ if isinstance(child, NarrowAABB):
36
+ indices += child.get_possible_triangles(point, vec)
37
+ continue
38
+
39
+ # if child is a primative
40
+ index = child.is_possible_triangle(point, vec)
41
+ if index == -1: continue
42
+ indices.append(index)
43
+
44
+ return indices
45
+
46
+ def get_best_dot(self, vec: glm.vec3) -> int:
47
+ """
48
+ Returns the best triangle with the highest dot product with the vector from the geometric center to its AABB
49
+ """
50
+ c = max(self.a, self.b, key=lambda x: glm.dot(x.geometric_center, vec))
51
+ if isinstance(c, NarrowAABB): return c.get_best_dot(vec)
52
+ return c.index
53
+
54
+ def get_all_aabbs(self, layer: int) -> list[tuple[glm.vec3, glm.vec3, int]]:
55
+ """
56
+ Returns all AABBs, their extreme points, and their layer
57
+ """
58
+ aabbs = [(self.top_right, self.bottom_left, layer)]
59
+ if isinstance(self.a, NarrowAABB): aabbs += self.a.get_all_aabbs(layer + 1)
60
+ else: aabbs.append((self.a.top_right, self.a.bottom_left, layer + 1))
61
+ if isinstance(self.b, NarrowAABB): aabbs += self.b.get_all_aabbs(layer + 1)
62
+ else: aabbs.append((self.b.top_right, self.b.bottom_left, layer + 1))
63
+ return aabbs
64
+
65
+ def get_tested_aabbs(self, point: glm.vec3, vec: glm.vec3, layer: int) -> list[tuple[glm.vec3, glm.vec3, int]]:
66
+ """
67
+ Returns all AABBs, their extreme points, and their layer
68
+ """
69
+ aabbs = [(self.top_right, self.bottom_left, layer)]
70
+
71
+ if isinstance(self.a, NarrowAABB):
72
+
73
+ aabbs += self.a.get_all_aabbs(layer + 1)
74
+ else: aabbs.append((self.a.top_right, self.a.bottom_left, layer + 1))
75
+
76
+ if isinstance(self.b, NarrowAABB):
77
+
78
+ aabbs += self.b.get_all_aabbs(layer + 1)
79
+ else: aabbs.append((self.b.top_right, self.b.bottom_left, layer + 1))
80
+
81
+ return aabbs
@@ -0,0 +1,84 @@
1
+ import glm
2
+ from .narrow_aabb import NarrowAABB
3
+ from .narrow_primative import NarrowPrimative
4
+ from ..generic.abstract_bvh import AbstractAABB as BVH
5
+ from ..generic.meshes import get_extreme_points_np, get_aabb_surface_area
6
+
7
+
8
+ class NarrowBVH(BVH):
9
+ root: NarrowAABB | NarrowPrimative
10
+ """Root aabb used for the start of all collisions"""
11
+ primatives: list[NarrowPrimative]
12
+ """All of the primatives in the BVH associated with triangles in the mesh"""
13
+ mesh: ...
14
+ """Back reference to the parent mesh"""
15
+
16
+ def __init__(self, mesh) -> None:
17
+ self.mesh = mesh
18
+ self.primatives = []
19
+ for index, triangle in enumerate(self.mesh.indices):
20
+ points = [self.mesh.points[t] for t in triangle] # TODO check np array accessing
21
+ top_right, bottom_left = get_extreme_points_np(points)
22
+ self.primatives.append(NarrowPrimative(top_right, bottom_left, index))
23
+
24
+ top_right = mesh.geometric_center + mesh.half_dimensions
25
+ bottom_left = mesh.geometric_center - mesh.half_dimensions
26
+ self.root = self.build_bvh(self.primatives, top_right, bottom_left)
27
+
28
+ def build_bvh(self, primatives: list[NarrowPrimative], top_right: glm.vec3, bottom_left: glm.vec3) -> NarrowAABB | NarrowPrimative:
29
+ """
30
+ Creates a root node for the BVH with the given primatives and bounds
31
+ """
32
+ best_cost = -1
33
+ best_split = primatives
34
+ best_aabb = []
35
+ count = len(primatives) // 2
36
+
37
+ # return primative if it is a leaf
38
+ if not count: return primatives[0]
39
+
40
+ for axis in range(3):
41
+ # sort primatives along axis and determine if it is lowest cost
42
+ primatives.sort(key=lambda p: p.geometric_center[axis])
43
+ aabb = self.calculate_primative_aabb(primatives[:count]) + self.calculate_primative_aabb(primatives[count:])
44
+ cost = get_aabb_surface_area(aabb[0], aabb[1]) + get_aabb_surface_area(aabb[2], aabb[3])
45
+
46
+ if best_cost < 0 or cost < best_cost:
47
+ best_cost = cost
48
+ best_split = list(primatives) # TODO ensure that this is a shallow copy
49
+ best_aabb = aabb
50
+
51
+ a = self.build_bvh(best_split[:count], best_aabb[0], best_aabb[1])
52
+ b = self.build_bvh(best_split[count:], best_aabb[2], best_aabb[3])
53
+ return NarrowAABB(top_right, bottom_left, a, b)
54
+
55
+ def calculate_primative_aabb(self, primatives: list[NarrowPrimative]) -> float:
56
+ """
57
+ Computes the aabb surface area of the primatives
58
+ """
59
+ points = set()
60
+ for primative in primatives:
61
+ points.update([tuple(self.mesh.points[t]) for t in self.mesh.indices[primative.index]])
62
+ return list(get_extreme_points_np(list(points)))
63
+
64
+ def get_possible_triangles(self, point: glm.vec3, vec: glm.vec3) -> list[int]:
65
+ """
66
+ Determines the closest intersecting on the bvh
67
+ """
68
+ if isinstance(self.root, NarrowAABB): return self.root.get_possible_triangles(point, vec)
69
+ index = self.root.is_possible_triangle(point, vec)
70
+ return [index] if index != -1 else []
71
+
72
+ def get_best_dot(self, vec: glm.vec3) -> int:
73
+ """
74
+ Returns the best triangle with the highest dot product with the vector from the geometric center to its AABB
75
+ """
76
+ if isinstance(self.root, NarrowAABB): return self.root.get_best_dot(vec)
77
+ return self.root.index
78
+
79
+ def get_all_aabbs(self) -> list[tuple[glm.vec3, glm.vec3, int]]:
80
+ """
81
+ Returns all AABBs, their extreme points, and their layer
82
+ """
83
+ if isinstance(self.root, NarrowAABB): return self.root.get_all_aabbs(0)
84
+ return [(self.root.top_right, self.root.bottom_left, 0)]
@@ -0,0 +1,24 @@
1
+ import glm
2
+ from ..generic.meshes import get_aabb_line_collision
3
+
4
+ class NarrowPrimative():
5
+ top_right: glm.vec3
6
+ """The furthest positive corner of the AABB"""
7
+ bottom_left: glm.vec3
8
+ """The furthest negative corner of the AABB"""
9
+ geometric_center: glm.vec3
10
+ """The centroid of the primative"""
11
+ index: int
12
+ """the index of the triangle in the mesh"""
13
+
14
+ def __init__(self, top_right:glm.vec3, bottom_left:glm.vec3, index: int) -> None:
15
+ self.top_right = top_right
16
+ self.bottom_left = bottom_left
17
+ self.geometric_center = (self.top_right + self.bottom_left) / 2
18
+ self.index = index
19
+
20
+ def is_possible_triangle(self, point: glm.vec3, vec: glm.vec3) -> int:
21
+ """
22
+ Determines if this triangle's AABB intersects with the line
23
+ """
24
+ return self.index if get_aabb_line_collision(self.top_right, self.bottom_left, point, vec) else -1
File without changes