basilisk-engine 0.0.9__py3-none-any.whl → 0.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of basilisk-engine might be problematic. Click here for more details.
- basilisk/__init__.py +3 -1
- basilisk/collisions/broad/broad_aabb.py +8 -1
- basilisk/collisions/broad/broad_bvh.py +38 -2
- basilisk/collisions/collider.py +20 -10
- basilisk/collisions/collider_handler.py +97 -32
- basilisk/collisions/narrow/contact_manifold.py +91 -0
- basilisk/collisions/narrow/dataclasses.py +27 -0
- basilisk/collisions/narrow/deprecated.py +47 -0
- basilisk/collisions/narrow/epa.py +21 -15
- basilisk/collisions/narrow/gjk.py +15 -14
- basilisk/collisions/narrow/graham_scan.py +25 -0
- basilisk/collisions/narrow/helper.py +14 -7
- basilisk/collisions/narrow/line_intersections.py +107 -0
- basilisk/collisions/narrow/sutherland_hodgman.py +76 -0
- basilisk/draw/draw_handler.py +7 -5
- basilisk/engine.py +28 -6
- basilisk/generic/abstract_custom.py +134 -0
- basilisk/generic/collisions.py +47 -2
- basilisk/generic/quat.py +84 -65
- basilisk/generic/vec3.py +99 -67
- basilisk/input/mouse.py +3 -3
- basilisk/mesh/cube.py +20 -2
- basilisk/mesh/mesh.py +69 -54
- basilisk/mesh/mesh_from_data.py +106 -21
- basilisk/mesh/narrow_aabb.py +10 -1
- basilisk/mesh/narrow_bvh.py +9 -1
- basilisk/nodes/node.py +211 -101
- basilisk/nodes/node_handler.py +58 -33
- basilisk/particles/__init__.py +0 -0
- basilisk/particles/particle_handler.py +55 -0
- basilisk/particles/particle_renderer.py +87 -0
- basilisk/physics/impulse.py +113 -0
- basilisk/physics/physics_body.py +10 -2
- basilisk/physics/physics_engine.py +2 -3
- basilisk/render/batch.py +3 -1
- basilisk/render/camera.py +35 -1
- basilisk/render/chunk.py +19 -4
- basilisk/render/chunk_handler.py +39 -23
- basilisk/render/image.py +1 -1
- basilisk/render/image_handler.py +17 -14
- basilisk/render/light_handler.py +16 -11
- basilisk/render/material.py +38 -14
- basilisk/render/material_handler.py +31 -18
- basilisk/render/shader.py +110 -0
- basilisk/render/shader_handler.py +20 -35
- basilisk/render/sky.py +8 -5
- basilisk/scene.py +116 -33
- basilisk/shaders/batch.frag +40 -11
- basilisk/shaders/batch.vert +14 -7
- basilisk/shaders/geometry.frag +9 -0
- basilisk/shaders/geometry.vert +42 -0
- basilisk/shaders/normal.frag +60 -0
- basilisk/shaders/normal.vert +97 -0
- basilisk/shaders/particle.frag +72 -0
- basilisk/shaders/particle.vert +85 -0
- {basilisk_engine-0.0.9.dist-info → basilisk_engine-0.1.1.dist-info}/METADATA +5 -5
- basilisk_engine-0.1.1.dist-info/RECORD +95 -0
- basilisk/shaders/image.png +0 -0
- basilisk_engine-0.0.9.dist-info/RECORD +0 -78
- {basilisk_engine-0.0.9.dist-info → basilisk_engine-0.1.1.dist-info}/WHEEL +0 -0
- {basilisk_engine-0.0.9.dist-info → basilisk_engine-0.1.1.dist-info}/top_level.txt +0 -0
basilisk/nodes/node.py
CHANGED
|
@@ -8,6 +8,7 @@ from ..render.material import Material
|
|
|
8
8
|
from ..physics.physics_body import PhysicsBody
|
|
9
9
|
from ..collisions.collider import Collider
|
|
10
10
|
from ..render.chunk import Chunk
|
|
11
|
+
from ..render.shader import Shader
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
class Node():
|
|
@@ -17,6 +18,12 @@ class Node():
|
|
|
17
18
|
"""The scale of the node in meters in each direction"""
|
|
18
19
|
rotation: Quat
|
|
19
20
|
"""The rotation of the node"""
|
|
21
|
+
position_relative: bool
|
|
22
|
+
"""The position of this node relative to the parent node"""
|
|
23
|
+
scale_relative: bool
|
|
24
|
+
"""The scale of this node relative to the parent node"""
|
|
25
|
+
rotation_relative: bool
|
|
26
|
+
"""The rotation of this node relative to the parent node"""
|
|
20
27
|
forward: glm.vec3
|
|
21
28
|
"""The forward facing vector of the node"""
|
|
22
29
|
mesh: Mesh
|
|
@@ -53,11 +60,16 @@ class Node():
|
|
|
53
60
|
"""""" # TODO Jonah description
|
|
54
61
|
children: list
|
|
55
62
|
"""List of nodes that this node is a parent of"""
|
|
63
|
+
shader: Shader
|
|
64
|
+
"""Shader that is used to render the node. If none is given, engine default will be used"""
|
|
56
65
|
|
|
57
|
-
def __init__(self,
|
|
66
|
+
def __init__(self,
|
|
58
67
|
position: glm.vec3=None,
|
|
59
68
|
scale: glm.vec3=None,
|
|
60
69
|
rotation: glm.quat=None,
|
|
70
|
+
relative_position: bool=True,
|
|
71
|
+
relative_scale: bool=True,
|
|
72
|
+
relative_rotation: bool=True,
|
|
61
73
|
forward: glm.vec3=None,
|
|
62
74
|
mesh: Mesh=None,
|
|
63
75
|
material: Material=None,
|
|
@@ -73,7 +85,8 @@ class Node():
|
|
|
73
85
|
collision_group : float=None,
|
|
74
86
|
name: str='',
|
|
75
87
|
tags: list[str]=None,
|
|
76
|
-
static: bool=
|
|
88
|
+
static: bool=None,
|
|
89
|
+
shader: Shader=None
|
|
77
90
|
) -> None:
|
|
78
91
|
"""
|
|
79
92
|
Basilisk node object.
|
|
@@ -82,32 +95,42 @@ class Node():
|
|
|
82
95
|
"""
|
|
83
96
|
|
|
84
97
|
# parents
|
|
85
|
-
self.node_handler =
|
|
98
|
+
self.node_handler = None
|
|
99
|
+
self.scene = None
|
|
86
100
|
self.chunk = None
|
|
101
|
+
self.parent = None
|
|
87
102
|
|
|
88
103
|
# lazy update variables
|
|
89
|
-
self.needs_geometric_center = True
|
|
90
|
-
self.needs_model_matrix = True
|
|
104
|
+
self.needs_geometric_center = True # pos
|
|
105
|
+
self.needs_model_matrix = True # pos, scale, rot
|
|
91
106
|
|
|
92
107
|
# node data
|
|
93
108
|
self.internal_position: Vec3 = Vec3(position) if position else Vec3(0, 0, 0)
|
|
94
109
|
self.internal_scale : Vec3 = Vec3(scale) if scale else Vec3(1, 1, 1)
|
|
95
110
|
self.internal_rotation: Quat = Quat(rotation) if rotation else Quat(1, 0, 0, 0)
|
|
111
|
+
|
|
112
|
+
# relative transformations
|
|
113
|
+
self.relative_position = glm.vec3(0, 0, 0) if relative_position else None
|
|
114
|
+
self.relative_scale = glm.vec3(0, 0, 0) if relative_scale else None
|
|
115
|
+
self.relative_rotation = glm.quat(1, 0, 0, 0) if relative_rotation else None
|
|
116
|
+
|
|
96
117
|
self.forward = forward if forward else glm.vec3(1, 0, 0)
|
|
97
|
-
self.mesh = mesh
|
|
98
|
-
self.
|
|
118
|
+
self.mesh = mesh
|
|
119
|
+
self._mtl_list = material if isinstance(material, list) else [material]
|
|
120
|
+
self.material = material if material else None
|
|
99
121
|
self.velocity = velocity if velocity else glm.vec3(0, 0, 0)
|
|
100
122
|
self.rotational_velocity = rotational_velocity if rotational_velocity else glm.vec3(0, 0, 0)
|
|
101
123
|
|
|
102
|
-
|
|
103
|
-
|
|
124
|
+
self.static = static if static != None else not(physics or any(self.velocity) or any(self.rotational_velocity))
|
|
125
|
+
|
|
126
|
+
# Physics updates
|
|
127
|
+
if physics: self.physics_body = PhysicsBody(mass = mass if mass else 1.0)
|
|
104
128
|
elif mass: raise ValueError('Node: cannot have mass if it does not have physics')
|
|
105
129
|
else: self.physics_body = None
|
|
106
130
|
|
|
107
131
|
# collider
|
|
108
132
|
if collisions:
|
|
109
|
-
|
|
110
|
-
self.collider: Collider = self.node_handler.scene.collider_handler.add(
|
|
133
|
+
self.collider = Collider(
|
|
111
134
|
node = self,
|
|
112
135
|
box_mesh = True if collider == 'box' else False,
|
|
113
136
|
static_friction = static_friction,
|
|
@@ -121,63 +144,105 @@ class Node():
|
|
|
121
144
|
elif elasticity: raise ValueError('Node: cannot have elasticity if it does not allow collisions')
|
|
122
145
|
elif collision_group: raise ValueError('Node: cannot have collider group if it does not allow collisions')
|
|
123
146
|
else: self.collider = None
|
|
124
|
-
|
|
147
|
+
|
|
125
148
|
# information and recursion
|
|
126
149
|
self.name = name
|
|
127
150
|
self.tags = tags if tags else []
|
|
128
|
-
|
|
151
|
+
|
|
129
152
|
self.data_index = 0
|
|
130
153
|
self.children = []
|
|
154
|
+
|
|
155
|
+
# Shader given by user or none for default
|
|
156
|
+
self.shader = shader
|
|
131
157
|
|
|
132
158
|
# default callback functions for node transform
|
|
133
159
|
self.previous_position: Vec3 = Vec3(position) if position else Vec3(0, 0, 0)
|
|
134
160
|
self.previous_scale : Vec3 = Vec3(scale) if scale else Vec3(1, 1, 1)
|
|
135
161
|
self.previous_rotation: Quat = Quat(rotation) if rotation else Quat(1, 0, 0, 0) # TODO Do these need to be the callback class or can they just be glm?
|
|
136
|
-
|
|
137
|
-
self.position_updated = False
|
|
138
|
-
self.scale_updated = False
|
|
139
|
-
self.rotation_updated = False
|
|
140
|
-
|
|
162
|
+
|
|
141
163
|
# callback function to be added to the custom Vec3 and Quat classes
|
|
142
164
|
def position_callback():
|
|
143
|
-
|
|
144
|
-
|
|
165
|
+
self.chunk.node_update_callback(self)
|
|
166
|
+
|
|
167
|
+
# update variables
|
|
168
|
+
self.needs_geometric_center = True
|
|
169
|
+
self.needs_model_matrix = True
|
|
170
|
+
if self.collider:
|
|
171
|
+
self.collider.needs_bvh = True
|
|
172
|
+
self.collider.needs_obb = True
|
|
145
173
|
|
|
146
174
|
def scale_callback():
|
|
147
|
-
|
|
148
|
-
|
|
175
|
+
self.chunk.node_update_callback(self)
|
|
176
|
+
|
|
177
|
+
# update variables
|
|
178
|
+
self.needs_model_matrix = True
|
|
179
|
+
if self.collider:
|
|
180
|
+
self.collider.needs_bvh = True
|
|
181
|
+
self.collider.needs_obb = True
|
|
182
|
+
self.collider.needs_half_dimensions = True
|
|
149
183
|
|
|
150
184
|
def rotation_callback():
|
|
151
|
-
|
|
152
|
-
|
|
185
|
+
self.chunk.node_update_callback(self)
|
|
186
|
+
|
|
187
|
+
# update variables
|
|
188
|
+
self.needs_model_matrix = True
|
|
189
|
+
if self.collider:
|
|
190
|
+
self.collider.needs_bvh = True
|
|
191
|
+
self.collider.needs_obb = True
|
|
192
|
+
self.collider.needs_half_dimensions = True
|
|
153
193
|
|
|
154
194
|
self.internal_position.callback = position_callback
|
|
155
195
|
self.internal_scale.callback = scale_callback
|
|
156
196
|
self.internal_rotation.callback = rotation_callback
|
|
157
|
-
|
|
197
|
+
|
|
198
|
+
def init_scene(self, scene):
|
|
199
|
+
"""
|
|
200
|
+
Updates the scene of the node
|
|
201
|
+
"""
|
|
202
|
+
self.scene = scene
|
|
203
|
+
self.node_handler = scene.node_handler
|
|
204
|
+
|
|
205
|
+
# Update materials
|
|
206
|
+
self.write_materials()
|
|
207
|
+
|
|
208
|
+
# Update the mesh
|
|
209
|
+
self.mesh = self.mesh if self.mesh else self.scene.engine.cube
|
|
210
|
+
|
|
211
|
+
# Update physics and collider
|
|
212
|
+
if self.physics_body: self.physics_body.physics_engine = scene.physics_engine
|
|
213
|
+
if self.collider: self.collider.collider_handler = scene.collider_handler
|
|
214
|
+
|
|
158
215
|
def update(self, dt: float) -> None:
|
|
159
216
|
"""
|
|
160
217
|
Updates the node's movement variables based on the delta time
|
|
161
218
|
"""
|
|
162
|
-
# update
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
# reset updates
|
|
166
|
-
self.position_updated = False
|
|
167
|
-
self.scale_updated = False
|
|
168
|
-
self.rotation_updated = False
|
|
169
|
-
|
|
170
|
-
self.position += dt * self.velocity
|
|
171
|
-
self.rotation += 0.5 * dt * self.rotation * glm.quat(0, *self.rotational_velocity)
|
|
172
|
-
self.rotation = glm.normalize(self.rotation)
|
|
173
|
-
self.scale = self.scale
|
|
219
|
+
# update based on physical properties
|
|
220
|
+
if any(self.velocity): self.position += dt * self.velocity
|
|
221
|
+
if any(self.rotational_velocity): self.rotation = glm.normalize(self.rotation - dt / 2 * self.rotation * glm.quat(0, *self.rotational_velocity))
|
|
174
222
|
|
|
175
223
|
if self.physics_body:
|
|
176
224
|
self.velocity += self.physics_body.get_delta_velocity(dt)
|
|
177
225
|
self.rotational_velocity += self.physics_body.get_delta_rotational_velocity(dt)
|
|
226
|
+
|
|
227
|
+
# update children transforms
|
|
228
|
+
for child in self.children: child.sync_data()
|
|
178
229
|
|
|
179
|
-
def sync_data(self
|
|
180
|
-
|
|
230
|
+
def sync_data(self) -> None:
|
|
231
|
+
"""
|
|
232
|
+
Syncronizes this node with the parent node based on its relative positioning
|
|
233
|
+
"""
|
|
234
|
+
# calculate transform matrix with the given input
|
|
235
|
+
transform = glm.mat4x4()
|
|
236
|
+
if self.relative_position: transform = glm.translate(transform, self.parent.position)
|
|
237
|
+
if self.relative_rotation: transform *= glm.transpose(glm.mat4_cast(self.parent.rotation))
|
|
238
|
+
if self.relative_scale: transform = glm.scale(transform, self.parent.scale)
|
|
239
|
+
|
|
240
|
+
# set this node's transforms based on the parent
|
|
241
|
+
self.position = transform * self.relative_position
|
|
242
|
+
self.scale = self.relative_scale * self.parent.scale
|
|
243
|
+
self.rotation = self.relative_rotation * self.parent.rotation
|
|
244
|
+
|
|
245
|
+
for child in self.children: child.sync_data()
|
|
181
246
|
|
|
182
247
|
def get_nodes(self,
|
|
183
248
|
require_mesh: bool=False,
|
|
@@ -203,13 +268,33 @@ class Node():
|
|
|
203
268
|
|
|
204
269
|
# adds children to nodes list if they match the criteria
|
|
205
270
|
for node in self.children: nodes.extend(node.get_nodes(require_mesh, require_collider, require_physics_body, filter_material, filter_tags))
|
|
206
|
-
return
|
|
271
|
+
return nodes
|
|
207
272
|
|
|
208
|
-
|
|
209
|
-
|
|
273
|
+
# tree functions for managing children
|
|
274
|
+
def add(self, child: ..., relative_position: bool=None, relative_scale: bool=None, relative_rotation: glm.vec3=None) -> None:
|
|
275
|
+
"""
|
|
276
|
+
Adopts a node as a child. Relative transforms can be changed, if left bank they will not be chnaged from the current child nodes settings.
|
|
277
|
+
"""
|
|
278
|
+
if child in self.children: return
|
|
279
|
+
|
|
280
|
+
# compute relative transformations
|
|
281
|
+
if relative_position or (relative_position is None and child.relative_position): child.relative_position = child.position - self.position
|
|
282
|
+
if relative_scale or (relative_scale is None and child.relative_scale): child.relative_scale = child.scale / self.scale
|
|
283
|
+
if relative_rotation or (relative_rotation is None and child.relative_rotation): child.relative_rotation = child.rotation * glm.inverse(self.rotation)
|
|
284
|
+
|
|
285
|
+
# add as a child to by synchronized and controlled
|
|
286
|
+
if self.node_handler: self.node_handler.add(child)
|
|
287
|
+
child.parent = self
|
|
288
|
+
self.children.append(child)
|
|
210
289
|
|
|
211
|
-
def
|
|
212
|
-
|
|
290
|
+
def remove(self, child: ...) -> None:
|
|
291
|
+
"""
|
|
292
|
+
Removes a child node from this nodes chlid list.
|
|
293
|
+
"""
|
|
294
|
+
if child in self.children:
|
|
295
|
+
if self.node_handler: self.node_handler.remove(child)
|
|
296
|
+
child.parent = None
|
|
297
|
+
self.children.remove(child)
|
|
213
298
|
|
|
214
299
|
def apply_force(self, force: glm.vec3, dt: float) -> None:
|
|
215
300
|
"""
|
|
@@ -242,16 +327,22 @@ class Node():
|
|
|
242
327
|
Transforms the mesh inertia tensor and inverts it
|
|
243
328
|
"""
|
|
244
329
|
if not (self.mesh and self.physics_body): return None
|
|
245
|
-
inertia_tensor = self.mesh.get_inertia_tensor(self.scale)
|
|
330
|
+
inertia_tensor = self.mesh.get_inertia_tensor(self.scale) / 2
|
|
246
331
|
|
|
247
332
|
# mass
|
|
248
333
|
if self.physics_body: inertia_tensor *= self.physics_body.mass
|
|
249
334
|
|
|
250
335
|
# rotation
|
|
251
336
|
rotation_matrix = glm.mat3_cast(self.rotation)
|
|
252
|
-
inertia_tensor
|
|
337
|
+
inertia_tensor = rotation_matrix * inertia_tensor * glm.transpose(rotation_matrix)
|
|
253
338
|
|
|
254
339
|
return glm.inverse(inertia_tensor)
|
|
340
|
+
|
|
341
|
+
def get_vertex(self, index) -> glm.vec3:
|
|
342
|
+
"""
|
|
343
|
+
Gets the world space position of a vertex indicated by the index in the mesh
|
|
344
|
+
"""
|
|
345
|
+
return glm.vec3(self.model_matrix * glm.vec4(*self.mesh.points[index], 1))
|
|
255
346
|
|
|
256
347
|
def get_data(self) -> np.ndarray:
|
|
257
348
|
"""
|
|
@@ -260,15 +351,41 @@ class Node():
|
|
|
260
351
|
|
|
261
352
|
# Get data from the mesh node
|
|
262
353
|
mesh_data = self.mesh.data
|
|
263
|
-
node_data = np.array([*self.position, *self.rotation, *self.scale,
|
|
354
|
+
node_data = np.array([*self.position, *self.rotation, *self.scale, 0])
|
|
355
|
+
|
|
356
|
+
per_vertex_mtl = isinstance(self.material, list)
|
|
357
|
+
|
|
358
|
+
if not per_vertex_mtl: node_data[-1] = self.material.index
|
|
264
359
|
|
|
265
360
|
# Create an array to hold the node's data
|
|
266
361
|
data = np.zeros(shape=(mesh_data.shape[0], 25), dtype='f4')
|
|
362
|
+
|
|
363
|
+
|
|
267
364
|
data[:,:14] = mesh_data
|
|
268
365
|
data[:,14:] = node_data
|
|
269
366
|
|
|
367
|
+
if per_vertex_mtl: data[:,24] = self.material
|
|
368
|
+
|
|
270
369
|
return data
|
|
271
370
|
|
|
371
|
+
def write_materials(self):
|
|
372
|
+
"""
|
|
373
|
+
Internal function to write the material list to the material handler and get the material ids
|
|
374
|
+
"""
|
|
375
|
+
|
|
376
|
+
if isinstance(self.material, list):
|
|
377
|
+
mtl_index_list = []
|
|
378
|
+
for mtl in self._mtl_list:
|
|
379
|
+
self.node_handler.scene.material_handler.add(mtl)
|
|
380
|
+
mtl_index_list.append(mtl.index)
|
|
381
|
+
mtl_index_list.append(mtl.index)
|
|
382
|
+
mtl_index_list.append(mtl.index)
|
|
383
|
+
self._material = mtl_index_list
|
|
384
|
+
|
|
385
|
+
if isinstance(self.material, type(None)):
|
|
386
|
+
self.material = self.scene.material_handler.base
|
|
387
|
+
|
|
388
|
+
|
|
272
389
|
def __repr__(self) -> str:
|
|
273
390
|
"""
|
|
274
391
|
Returns a string representation of the node
|
|
@@ -284,7 +401,8 @@ class Node():
|
|
|
284
401
|
def rotation(self): return self.internal_rotation.data
|
|
285
402
|
@property
|
|
286
403
|
def forward(self): return self._forward
|
|
287
|
-
|
|
404
|
+
@property
|
|
405
|
+
def mesh(self): return self._mesh
|
|
288
406
|
@property
|
|
289
407
|
def material(self): return self._material
|
|
290
408
|
@property
|
|
@@ -347,21 +465,25 @@ class Node():
|
|
|
347
465
|
|
|
348
466
|
@position.setter
|
|
349
467
|
def position(self, value: tuple | list | glm.vec3 | np.ndarray):
|
|
350
|
-
if isinstance(value, glm.vec3): self.internal_position.data =
|
|
468
|
+
if isinstance(value, glm.vec3): self.internal_position.data = value
|
|
351
469
|
elif isinstance(value, tuple) or isinstance(value, list) or isinstance(value, np.ndarray):
|
|
352
470
|
if len(value) != 3: raise ValueError(f'Node: Invalid number of values for position. Expected 3, got {len(value)}')
|
|
353
471
|
self.internal_position.data = glm.vec3(value)
|
|
354
472
|
else: raise TypeError(f'Node: Invalid position value type {type(value)}')
|
|
355
|
-
|
|
473
|
+
|
|
474
|
+
# # compute relative position if all cases passed
|
|
475
|
+
# if self.parent and self.relative_position: self.relative_position = self.internal_position.data - self.parent.position
|
|
356
476
|
|
|
357
477
|
@scale.setter
|
|
358
478
|
def scale(self, value: tuple | list | glm.vec3 | np.ndarray):
|
|
359
|
-
if isinstance(value, glm.vec3): self.internal_scale.data =
|
|
479
|
+
if isinstance(value, glm.vec3): self.internal_scale.data = value
|
|
360
480
|
elif isinstance(value, tuple) or isinstance(value, list) or isinstance(value, np.ndarray):
|
|
361
481
|
if len(value) != 3: raise ValueError(f'Node: Invalid number of values for scale. Expected 3, got {len(value)}')
|
|
362
482
|
self.internal_scale.data = glm.vec3(value)
|
|
363
483
|
else: raise TypeError(f'Node: Invalid scale value type {type(value)}')
|
|
364
|
-
|
|
484
|
+
|
|
485
|
+
# # compute relative scale
|
|
486
|
+
# if self.parent and self.relative_scale: self.relative_scale = self.internal_scale.data / self.parent.scale
|
|
365
487
|
|
|
366
488
|
@rotation.setter
|
|
367
489
|
def rotation(self, value: tuple | list | glm.vec3 | glm.quat | glm.vec4 | np.ndarray):
|
|
@@ -371,66 +493,54 @@ class Node():
|
|
|
371
493
|
elif len(value) == 4: self.internal_rotation.data = glm.quat(*value)
|
|
372
494
|
else: raise ValueError(f'Node: Invalid number of values for rotation. Expected 3 or 4, got {len(value)}')
|
|
373
495
|
else: raise TypeError(f'Node: Invalid rotation value type {type(value)}')
|
|
374
|
-
self.update_rotation()
|
|
375
|
-
|
|
376
|
-
def update_position(self): # TODO Could these be repeated in a Vec3/Quat Callback function?
|
|
377
|
-
"""
|
|
378
|
-
Updates the rotation
|
|
379
|
-
"""
|
|
380
496
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
prev = self.previous_position
|
|
384
|
-
|
|
385
|
-
if self.chunk and (abs(cur.x - prev.x) > thresh or abs(cur.y - prev.y) > thresh or abs(cur.z - prev.z) > thresh):
|
|
386
|
-
self.chunk.node_update_callback(self)
|
|
387
|
-
self.previous_position = self.position
|
|
388
|
-
|
|
389
|
-
def update_scale(self):
|
|
390
|
-
"""
|
|
391
|
-
Updates the rotation
|
|
392
|
-
"""
|
|
393
|
-
|
|
394
|
-
thresh = 0.01
|
|
395
|
-
cur = self.scale
|
|
396
|
-
prev = self.previous_scale
|
|
397
|
-
|
|
398
|
-
if self.chunk and (abs(cur.x - prev.x) > thresh or abs(cur.y - prev.y) > thresh or abs(cur.z - prev.z) > thresh):
|
|
399
|
-
self.chunk.node_update_callback(self)
|
|
400
|
-
self.previous_scale = self.scale
|
|
401
|
-
|
|
402
|
-
def update_rotation(self):
|
|
403
|
-
"""
|
|
404
|
-
Updates the rotation
|
|
405
|
-
"""
|
|
406
|
-
|
|
407
|
-
thresh = 0.01
|
|
408
|
-
cur = self.rotation
|
|
409
|
-
prev = self.previous_rotation
|
|
410
|
-
|
|
411
|
-
if self.chunk and (abs(cur.x - prev.x) > thresh or abs(cur.y - prev.y) > thresh or abs(cur.z - prev.z) > thresh or abs(cur.w - prev.w) > thresh):
|
|
412
|
-
self.chunk.node_update_callback(self)
|
|
413
|
-
self.previous_rotation = self.rotation
|
|
414
|
-
|
|
497
|
+
# # compute relative rotation
|
|
498
|
+
# if self.parent and self.relative_rotation: self.relative_rotation = self.rotation * glm.inverse(self.parent.rotation)
|
|
415
499
|
|
|
416
500
|
@forward.setter
|
|
417
501
|
def forward(self, value: tuple | list | glm.vec3 | np.ndarray):
|
|
418
|
-
if isinstance(value, glm.vec3): self._forward =
|
|
502
|
+
if isinstance(value, glm.vec3): self._forward = value
|
|
419
503
|
elif isinstance(value, tuple) or isinstance(value, list) or isinstance(value, np.ndarray):
|
|
420
504
|
if len(value) != 3: raise ValueError(f'Node: Invalid number of values for forward. Expected 3, got {len(value)}')
|
|
421
505
|
self._forward = glm.vec3(value)
|
|
422
506
|
else: raise TypeError(f'Node: Invalid forward value type {type(value)}')
|
|
423
507
|
|
|
424
|
-
|
|
508
|
+
@mesh.setter
|
|
509
|
+
def mesh(self, value: Mesh | None):
|
|
510
|
+
if isinstance(value, Mesh):
|
|
511
|
+
self._mesh = value
|
|
512
|
+
if self.chunk: self.chunk.update()
|
|
513
|
+
elif isinstance(value, type(None)):
|
|
514
|
+
self._mesh = None
|
|
515
|
+
if not self.chunk: return
|
|
516
|
+
self.chunk.remove(self)
|
|
517
|
+
self.chunk.update()
|
|
518
|
+
else: raise TypeError(f'Node: Invalid mesh value type {type(value)}')
|
|
425
519
|
|
|
426
520
|
@material.setter
|
|
427
521
|
def material(self, value: Material):
|
|
428
|
-
if isinstance(value,
|
|
522
|
+
if isinstance(value, list):
|
|
523
|
+
self._mtl_list = value
|
|
524
|
+
if not self.node_handler:
|
|
525
|
+
self._material = value
|
|
526
|
+
else:
|
|
527
|
+
mtl_index_list = []
|
|
528
|
+
for mtl in self._mtl_list:
|
|
529
|
+
self.node_handler.scene.material_handler.add(mtl)
|
|
530
|
+
mtl_index_list.append(mtl.index)
|
|
531
|
+
mtl_index_list.append(mtl.index)
|
|
532
|
+
mtl_index_list.append(mtl.index)
|
|
533
|
+
self._material = mtl_index_list
|
|
534
|
+
elif isinstance(value, Material):
|
|
429
535
|
self._material = value
|
|
430
|
-
self.node_handler.scene.material_handler.add(value)
|
|
431
|
-
|
|
432
|
-
self.
|
|
536
|
+
if self.node_handler: self.node_handler.scene.material_handler.add(value)
|
|
537
|
+
elif isinstance(value, type(None)):
|
|
538
|
+
if self.scene: self._material = self.scene.material_handler.base
|
|
539
|
+
else: self._material = None
|
|
540
|
+
|
|
433
541
|
else: raise TypeError(f'Node: Invalid material value type {type(value)}')
|
|
542
|
+
if not self.chunk: return
|
|
543
|
+
self.chunk.node_update_callback(self)
|
|
434
544
|
|
|
435
545
|
@velocity.setter
|
|
436
546
|
def velocity(self, value: tuple | list | glm.vec3 | np.ndarray):
|
|
@@ -493,15 +603,15 @@ class Node():
|
|
|
493
603
|
|
|
494
604
|
@x.setter
|
|
495
605
|
def x(self, value: int | float):
|
|
496
|
-
if isinstance(value, int) or isinstance(value, float): self.internal_position.
|
|
606
|
+
if isinstance(value, int) or isinstance(value, float): self.internal_position.x = value
|
|
497
607
|
else: raise TypeError(f'Node: Invalid positional x value type {type(value)}')
|
|
498
608
|
|
|
499
609
|
@y.setter
|
|
500
610
|
def y(self, value: int | float):
|
|
501
|
-
if isinstance(value, int) or isinstance(value, float): self.internal_position.
|
|
611
|
+
if isinstance(value, int) or isinstance(value, float): self.internal_position.y = value
|
|
502
612
|
else: raise TypeError(f'Node: Invalid positional y value type {type(value)}')
|
|
503
613
|
|
|
504
614
|
@z.setter
|
|
505
615
|
def z(self, value: int | float):
|
|
506
|
-
if isinstance(value, int) or isinstance(value, float): self.internal_position.
|
|
616
|
+
if isinstance(value, int) or isinstance(value, float): self.internal_position.z = value
|
|
507
617
|
else: raise TypeError(f'Node: Invalid positional z value type {type(value)}')
|
basilisk/nodes/node_handler.py
CHANGED
|
@@ -25,7 +25,9 @@ class NodeHandler():
|
|
|
25
25
|
"""
|
|
26
26
|
Updates the nodes and chunks in the scene
|
|
27
27
|
"""
|
|
28
|
-
for node in self.nodes:
|
|
28
|
+
for node in self.nodes:
|
|
29
|
+
if node.static: continue
|
|
30
|
+
node.update(self.scene.engine.delta_time)
|
|
29
31
|
self.chunk_handler.update()
|
|
30
32
|
|
|
31
33
|
def render(self):
|
|
@@ -35,60 +37,83 @@ class NodeHandler():
|
|
|
35
37
|
|
|
36
38
|
self.chunk_handler.render()
|
|
37
39
|
|
|
38
|
-
def add(self,
|
|
39
|
-
position: glm.vec3=None,
|
|
40
|
-
scale: glm.vec3=None,
|
|
41
|
-
rotation: glm.quat=None,
|
|
42
|
-
forward: glm.vec3=None,
|
|
43
|
-
mesh: Mesh=None,
|
|
44
|
-
material: Material=None,
|
|
45
|
-
velocity: glm.vec3=None,
|
|
46
|
-
rotational_velocity: glm.quat=None,
|
|
47
|
-
physics: bool=False,
|
|
48
|
-
mass: float=None,
|
|
49
|
-
collisions: bool=False,
|
|
50
|
-
collider: str=None,
|
|
51
|
-
static_friction: float=None,
|
|
52
|
-
kinetic_friction: float=None,
|
|
53
|
-
elasticity: float=None,
|
|
54
|
-
collision_group : float=None,
|
|
55
|
-
name: str='',
|
|
56
|
-
tags: list[str]=None,
|
|
57
|
-
static: bool=True
|
|
58
|
-
) -> Node:
|
|
40
|
+
def add(self, node: Node) -> Node:
|
|
59
41
|
"""
|
|
60
42
|
Adds a new node to the node handler
|
|
61
43
|
"""
|
|
44
|
+
if node in self.nodes: return
|
|
62
45
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
46
|
+
for n in node.get_nodes(): # gets all nodes including the node to be added
|
|
47
|
+
|
|
48
|
+
# Update scene Handlers
|
|
49
|
+
self.scene.shader_handler.add(n.shader)
|
|
50
|
+
if not n.material: n.material = self.scene.material_handler.base
|
|
51
|
+
self.scene.material_handler.add(n.material)
|
|
52
|
+
|
|
53
|
+
# Update the node attributes
|
|
54
|
+
n.init_scene(self.scene)
|
|
55
|
+
|
|
56
|
+
# Add the node to internal data
|
|
57
|
+
self.nodes.append(n)
|
|
58
|
+
self.chunk_handler.add(n)
|
|
67
59
|
|
|
68
60
|
return node
|
|
61
|
+
|
|
62
|
+
def node_is(self, node: Node, position: glm.vec3=None, scale: glm.vec3=None, rotation: glm.quat=None, forward: glm.vec3=None, mesh: Mesh=None, material: Material=None, velocity: glm.vec3=None, rotational_velocity: glm.quat=None, physics: bool=None, mass: float=None, collisions: bool=None, static_friction: float=None, kinetic_friction: float=None, elasticity: float=None, collision_group: float=None, name: str=None, tags: list[str]=None,static: bool=None) -> bool:
|
|
63
|
+
"""
|
|
64
|
+
Determine if a node meets the requirements given by the parameters. If a parameter is None, then the filter is not applied.
|
|
65
|
+
"""
|
|
66
|
+
return all([
|
|
67
|
+
position is None or position == node.position,
|
|
68
|
+
scale is None or scale == node.scale,
|
|
69
|
+
rotation is None or rotation == node.rotation,
|
|
70
|
+
forward is None or forward == node.forward,
|
|
71
|
+
mesh is None or mesh == node.mesh,
|
|
72
|
+
material is None or material == node.material,
|
|
73
|
+
velocity is None or velocity == node.velocity,
|
|
74
|
+
rotational_velocity is None or rotational_velocity == node.rotational_velocity,
|
|
75
|
+
physics is None or bool(node.physics_body) == physics,
|
|
76
|
+
mass is None or (node.physics_body and mass == node.physics_body.mass),
|
|
77
|
+
collisions is None or bool(node.collider) == collisions,
|
|
78
|
+
static_friction is None or (node.collider and node.collider.static_friction == static_friction),
|
|
79
|
+
kinetic_friction is None or (node.collider and node.collider.kinetic_friction == kinetic_friction),
|
|
80
|
+
elasticity is None or (node.collider and node.collider.elasticity == elasticity),
|
|
81
|
+
collision_group is None or (node.collider and node.collider.collision_group == collision_group),
|
|
82
|
+
name is None or node.name == name,
|
|
83
|
+
tags is None or all([tag in node.tags for tag in tags]),
|
|
84
|
+
static is None or node.static == static
|
|
85
|
+
])
|
|
69
86
|
|
|
70
|
-
def get(self,
|
|
87
|
+
def get(self, position: glm.vec3=None, scale: glm.vec3=None, rotation: glm.quat=None, forward: glm.vec3=None, mesh: Mesh=None, material: Material=None, velocity: glm.vec3=None, rotational_velocity: glm.quat=None, physics: bool=None, mass: float=None, collisions: bool=None, static_friction: float=None, kinetic_friction: float=None, elasticity: float=None, collision_group: float=None, name: str=None, tags: list[str]=None,static: bool=None) -> Node:
|
|
71
88
|
"""
|
|
72
89
|
Returns the first node with the given traits
|
|
73
90
|
"""
|
|
74
91
|
for node in self.nodes:
|
|
75
|
-
if node
|
|
92
|
+
if self.node_is(node, position, scale, rotation, forward, mesh, material, velocity, rotational_velocity, physics, mass, collisions, static_friction, kinetic_friction, elasticity, collision_group, name, tags, static): return node
|
|
76
93
|
return None
|
|
77
94
|
|
|
78
|
-
def get_all(self, name: str) -> Node:
|
|
95
|
+
def get_all(self, position: glm.vec3=None, scale: glm.vec3=None, rotation: glm.quat=None, forward: glm.vec3=None, mesh: Mesh=None, material: Material=None, velocity: glm.vec3=None, rotational_velocity: glm.quat=None, physics: bool=None, mass: float=None, collisions: bool=None, static_friction: float=None, kinetic_friction: float=None, elasticity: float=None, collision_group: float=None, name: str=None, tags: list[str]=None,static: bool=None) -> Node:
|
|
79
96
|
"""
|
|
80
97
|
Returns all nodes with the given traits
|
|
81
98
|
"""
|
|
82
99
|
nodes = []
|
|
83
100
|
for node in self.nodes:
|
|
84
|
-
if node
|
|
101
|
+
if self.node_is(node, position, scale, rotation, forward, mesh, material, velocity, rotational_velocity, physics, mass, collisions, static_friction, kinetic_friction, elasticity, collision_group, name, tags, static): nodes.append(node)
|
|
85
102
|
return nodes
|
|
86
103
|
|
|
87
104
|
def remove(self, node: Node) -> None:
|
|
88
105
|
"""
|
|
89
106
|
Removes a node and all of its children from their handlers
|
|
90
107
|
"""
|
|
108
|
+
|
|
109
|
+
if node == None: return
|
|
110
|
+
|
|
91
111
|
# TODO add support for recursive nodes
|
|
92
|
-
if node
|
|
93
|
-
|
|
94
|
-
|
|
112
|
+
if node in self.nodes:
|
|
113
|
+
if node.physics_body: self.scene.physics_engine.remove(node.physics_body)
|
|
114
|
+
if node.collider: self.scene.collider_handler.remove(node.collider)
|
|
115
|
+
self.chunk_handler.remove(node)
|
|
116
|
+
self.nodes.remove(node)
|
|
117
|
+
node.node_handler = None
|
|
118
|
+
|
|
119
|
+
for child in node.children: self.remove(child)
|
|
File without changes
|