basilisk-engine 0.1.51__py3-none-any.whl → 0.1.53__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 +27 -27
- basilisk/audio/sound.py +40 -40
- 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 +181 -181
- basilisk/draw/font_renderer.py +28 -28
- basilisk/engine.py +168 -168
- 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 +107 -98
- basilisk/particles/particle_handler.py +69 -65
- basilisk/particles/particle_renderer.py +92 -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 +117 -117
- basilisk/render/camera.py +260 -260
- basilisk/render/chunk.py +113 -113
- basilisk/render/chunk_handler.py +167 -167
- basilisk/render/frame.py +130 -130
- basilisk/render/framebuffer.py +192 -192
- basilisk/render/image.py +128 -128
- 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 -135
- basilisk/render/shader_handler.py +109 -109
- basilisk/render/sky.py +119 -119
- basilisk/scene.py +295 -291
- basilisk/shaders/batch.frag +291 -291
- basilisk/shaders/batch.vert +117 -117
- basilisk/shaders/bloom_downsample.frag +23 -23
- 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.51.dist-info → basilisk_engine-0.1.53.dist-info}/METADATA +82 -89
- basilisk_engine-0.1.53.dist-info/RECORD +110 -0
- {basilisk_engine-0.1.51.dist-info → basilisk_engine-0.1.53.dist-info}/WHEEL +1 -1
- basilisk_engine-0.1.51.dist-info/RECORD +0 -110
- {basilisk_engine-0.1.51.dist-info → basilisk_engine-0.1.53.dist-info}/top_level.txt +0 -0
basilisk/nodes/node_handler.py
CHANGED
|
@@ -1,98 +1,107 @@
|
|
|
1
|
-
import glm
|
|
2
|
-
from .node import Node
|
|
3
|
-
from .helper import node_is
|
|
4
|
-
from ..render.chunk_handler import ChunkHandler
|
|
5
|
-
from ..mesh.mesh import Mesh
|
|
6
|
-
from ..render.material import Material
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class NodeHandler():
|
|
10
|
-
scene: ...
|
|
11
|
-
"""Back reference to the scene"""
|
|
12
|
-
nodes: list[Node]
|
|
13
|
-
"""The list of root nodes in the scene"""
|
|
14
|
-
|
|
15
|
-
def __init__(self, scene):
|
|
16
|
-
"""
|
|
17
|
-
Contains all the nodes in the scene.
|
|
18
|
-
Handles chunking and batching of nodes
|
|
19
|
-
"""
|
|
20
|
-
|
|
21
|
-
self.scene = scene
|
|
22
|
-
self.engine = scene.engine
|
|
23
|
-
self.nodes = []
|
|
24
|
-
self.chunk_handler = ChunkHandler(scene)
|
|
25
|
-
|
|
26
|
-
def update(self):
|
|
27
|
-
"""
|
|
28
|
-
Updates the nodes and chunks in the scene
|
|
29
|
-
"""
|
|
30
|
-
dt = self.scene.engine.delta_time
|
|
31
|
-
if dt < 0.5:
|
|
32
|
-
for node in self.nodes:
|
|
33
|
-
# if not node.static: TODO determine better solution to this line
|
|
34
|
-
node.update(dt)
|
|
35
|
-
self.chunk_handler.update()
|
|
36
|
-
|
|
37
|
-
def render(self):
|
|
38
|
-
"""
|
|
39
|
-
Updates the node meshes in the scene
|
|
40
|
-
"""
|
|
41
|
-
|
|
42
|
-
self.chunk_handler.render()
|
|
43
|
-
|
|
44
|
-
def add(self, node: Node) -> Node:
|
|
45
|
-
"""
|
|
46
|
-
Adds a new node to the node handler
|
|
47
|
-
"""
|
|
48
|
-
if node in self.nodes: return
|
|
49
|
-
|
|
50
|
-
for n in node.get_all(): # gets all nodes including the node to be added
|
|
51
|
-
|
|
52
|
-
# Update scene Handlers
|
|
53
|
-
self.engine.shader_handler.add(n.shader)
|
|
54
|
-
if not n.material: n.material = self.engine.material_handler.base
|
|
55
|
-
self.engine.material_handler.add(n.material)
|
|
56
|
-
|
|
57
|
-
# Update the node attributes
|
|
58
|
-
n.init_scene(self.scene)
|
|
59
|
-
|
|
60
|
-
# Add the node to internal data
|
|
61
|
-
self.nodes.append(n)
|
|
62
|
-
self.chunk_handler.add(n)
|
|
63
|
-
|
|
64
|
-
return node
|
|
65
|
-
|
|
66
|
-
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:
|
|
67
|
-
"""
|
|
68
|
-
Returns the first node with the given traits
|
|
69
|
-
"""
|
|
70
|
-
for node in self.nodes:
|
|
71
|
-
if 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
|
|
72
|
-
return None
|
|
73
|
-
|
|
74
|
-
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) -> list[Node]:
|
|
75
|
-
"""
|
|
76
|
-
Returns all nodes with the given traits
|
|
77
|
-
"""
|
|
78
|
-
nodes = []
|
|
79
|
-
for node in self.nodes:
|
|
80
|
-
if 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)
|
|
81
|
-
return nodes
|
|
82
|
-
|
|
83
|
-
def remove(self, node: Node) -> None:
|
|
84
|
-
"""
|
|
85
|
-
Removes a node and all of its children from their handlers
|
|
86
|
-
"""
|
|
87
|
-
|
|
88
|
-
if node == None: return
|
|
89
|
-
|
|
90
|
-
# TODO add support for recursive nodes
|
|
91
|
-
if node in self.nodes:
|
|
92
|
-
if node.physics_body: self.scene.physics_engine.remove(node.physics_body)
|
|
93
|
-
if node.collider: self.scene.collider_handler.remove(node.collider)
|
|
94
|
-
self.chunk_handler.remove(node)
|
|
95
|
-
self.nodes.remove(node)
|
|
96
|
-
node.node_handler = None
|
|
97
|
-
|
|
98
|
-
for child in node.children: self.remove(child)
|
|
1
|
+
import glm
|
|
2
|
+
from .node import Node
|
|
3
|
+
from .helper import node_is
|
|
4
|
+
from ..render.chunk_handler import ChunkHandler
|
|
5
|
+
from ..mesh.mesh import Mesh
|
|
6
|
+
from ..render.material import Material
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class NodeHandler():
|
|
10
|
+
scene: ...
|
|
11
|
+
"""Back reference to the scene"""
|
|
12
|
+
nodes: list[Node]
|
|
13
|
+
"""The list of root nodes in the scene"""
|
|
14
|
+
|
|
15
|
+
def __init__(self, scene):
|
|
16
|
+
"""
|
|
17
|
+
Contains all the nodes in the scene.
|
|
18
|
+
Handles chunking and batching of nodes
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
self.scene = scene
|
|
22
|
+
self.engine = scene.engine
|
|
23
|
+
self.nodes = []
|
|
24
|
+
self.chunk_handler = ChunkHandler(scene)
|
|
25
|
+
|
|
26
|
+
def update(self):
|
|
27
|
+
"""
|
|
28
|
+
Updates the nodes and chunks in the scene
|
|
29
|
+
"""
|
|
30
|
+
dt = self.scene.engine.delta_time
|
|
31
|
+
if dt < 0.5:
|
|
32
|
+
for node in self.nodes:
|
|
33
|
+
# if not node.static: TODO determine better solution to this line
|
|
34
|
+
node.update(dt)
|
|
35
|
+
self.chunk_handler.update()
|
|
36
|
+
|
|
37
|
+
def render(self):
|
|
38
|
+
"""
|
|
39
|
+
Updates the node meshes in the scene
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
self.chunk_handler.render()
|
|
43
|
+
|
|
44
|
+
def add(self, node: Node) -> Node:
|
|
45
|
+
"""
|
|
46
|
+
Adds a new node to the node handler
|
|
47
|
+
"""
|
|
48
|
+
if node in self.nodes: return
|
|
49
|
+
|
|
50
|
+
for n in node.get_all(): # gets all nodes including the node to be added
|
|
51
|
+
|
|
52
|
+
# Update scene Handlers
|
|
53
|
+
self.engine.shader_handler.add(n.shader)
|
|
54
|
+
if not n.material: n.material = self.engine.material_handler.base
|
|
55
|
+
self.engine.material_handler.add(n.material)
|
|
56
|
+
|
|
57
|
+
# Update the node attributes
|
|
58
|
+
n.init_scene(self.scene)
|
|
59
|
+
|
|
60
|
+
# Add the node to internal data
|
|
61
|
+
self.nodes.append(n)
|
|
62
|
+
self.chunk_handler.add(n)
|
|
63
|
+
|
|
64
|
+
return node
|
|
65
|
+
|
|
66
|
+
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:
|
|
67
|
+
"""
|
|
68
|
+
Returns the first node with the given traits
|
|
69
|
+
"""
|
|
70
|
+
for node in self.nodes:
|
|
71
|
+
if 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
|
|
72
|
+
return None
|
|
73
|
+
|
|
74
|
+
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) -> list[Node]:
|
|
75
|
+
"""
|
|
76
|
+
Returns all nodes with the given traits
|
|
77
|
+
"""
|
|
78
|
+
nodes = []
|
|
79
|
+
for node in self.nodes:
|
|
80
|
+
if 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)
|
|
81
|
+
return nodes
|
|
82
|
+
|
|
83
|
+
def remove(self, node: Node) -> None:
|
|
84
|
+
"""
|
|
85
|
+
Removes a node and all of its children from their handlers
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
if node == None: return
|
|
89
|
+
|
|
90
|
+
# TODO add support for recursive nodes
|
|
91
|
+
if node in self.nodes:
|
|
92
|
+
if node.physics_body: self.scene.physics_engine.remove(node.physics_body)
|
|
93
|
+
if node.collider: self.scene.collider_handler.remove(node.collider)
|
|
94
|
+
self.chunk_handler.remove(node)
|
|
95
|
+
self.nodes.remove(node)
|
|
96
|
+
node.node_handler = None
|
|
97
|
+
|
|
98
|
+
for child in node.children: self.remove(child)
|
|
99
|
+
|
|
100
|
+
def clear(self) -> None:
|
|
101
|
+
"""
|
|
102
|
+
Removes all nodes from the scene
|
|
103
|
+
TODO: this is prolly not the optimal solution lmao
|
|
104
|
+
"""
|
|
105
|
+
|
|
106
|
+
while self.nodes:
|
|
107
|
+
self.remove(self.nodes[0])
|
|
@@ -1,65 +1,69 @@
|
|
|
1
|
-
from .particle_renderer import ParticleRenderer
|
|
2
|
-
from ..mesh.mesh import Mesh
|
|
3
|
-
from ..render.material import Material
|
|
4
|
-
from ..generic.input_validation import validate_tuple3, validate_float
|
|
5
|
-
|
|
6
|
-
class ParticleHandler:
|
|
7
|
-
def __init__(self, scene, shader=None):
|
|
8
|
-
"""
|
|
9
|
-
A handler for all particles in a scene
|
|
10
|
-
"""
|
|
11
|
-
|
|
12
|
-
self.scene = scene
|
|
13
|
-
self.shader = shader
|
|
14
|
-
self.cube = Mesh(scene.engine.root + '/bsk_assets/cube.obj')
|
|
15
|
-
self.particle_renderers = {self.cube : ParticleRenderer(scene, self.cube, self.shader)}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
def add(self, mesh: Mesh=None, life: float=1.0, position: tuple|float=0, material: Material=None, scale: float=1.0, velocity: tuple|float=0, acceleration: tuple|float=0) -> bool:
|
|
19
|
-
"""
|
|
20
|
-
Add a new particle to the scene
|
|
21
|
-
Args:
|
|
22
|
-
mesh: Mesh
|
|
23
|
-
The basilisk mesh of the particle
|
|
24
|
-
life: float
|
|
25
|
-
The duration of the particle in seconds
|
|
26
|
-
position: tuple (x, y, z)
|
|
27
|
-
The initial position of the particle
|
|
28
|
-
color: tuple (r, g, b) (components out of 255)
|
|
29
|
-
The color of the particle
|
|
30
|
-
scale: float
|
|
31
|
-
The overall scale factor of the particle
|
|
32
|
-
velocity: tuple (x, y, z)
|
|
33
|
-
The inital velocity of the particle as a vector
|
|
34
|
-
acceleration: tuple (x, y, z)
|
|
35
|
-
The permanent acceleration of the particle as a vector
|
|
36
|
-
"""
|
|
37
|
-
|
|
38
|
-
# Get the mesh and make a new particle renderer if the mesh is new
|
|
39
|
-
if mesh == None: mesh = self.cube
|
|
40
|
-
elif not isinstance(mesh, Mesh): raise ValueError(f'particle_handler.add: invlaid mesh type for particle: {type(mesh)}')
|
|
41
|
-
if mesh not in self.particle_renderers: self.particle_renderers[mesh] = ParticleRenderer(self.scene, mesh, self.shader)
|
|
42
|
-
|
|
43
|
-
# Get material ID
|
|
44
|
-
if material == None: material_index = 0
|
|
45
|
-
elif isinstance(material, Material):
|
|
46
|
-
self.scene.engine.material_handler.add(material)
|
|
47
|
-
material_index = material.index
|
|
48
|
-
else: raise ValueError(f'particle_handler.add: Invalid particle material type: {type(material)}')
|
|
49
|
-
|
|
50
|
-
# Validate the 3-component vectors
|
|
51
|
-
position = validate_tuple3('particle', 'add', position)
|
|
52
|
-
velocity = validate_tuple3('particle', 'add', velocity)
|
|
53
|
-
acceleration = validate_tuple3('particle', 'add', acceleration)
|
|
54
|
-
|
|
55
|
-
# Validate float inputs
|
|
56
|
-
life = validate_float('particle', 'add', life)
|
|
57
|
-
scale = validate_float('particle', 'add', scale)
|
|
58
|
-
|
|
59
|
-
# Add the particle to the renderer
|
|
60
|
-
self.particle_renderers[mesh].add(life, position, material_index, scale, velocity, acceleration)
|
|
61
|
-
|
|
62
|
-
def render(self) -> None:
|
|
63
|
-
for renderer in self.particle_renderers.values(): renderer.render()
|
|
64
|
-
|
|
65
|
-
|
|
1
|
+
from .particle_renderer import ParticleRenderer
|
|
2
|
+
from ..mesh.mesh import Mesh
|
|
3
|
+
from ..render.material import Material
|
|
4
|
+
from ..generic.input_validation import validate_tuple3, validate_float
|
|
5
|
+
|
|
6
|
+
class ParticleHandler:
|
|
7
|
+
def __init__(self, scene, shader=None):
|
|
8
|
+
"""
|
|
9
|
+
A handler for all particles in a scene
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
self.scene = scene
|
|
13
|
+
self.shader = shader
|
|
14
|
+
self.cube = Mesh(scene.engine.root + '/bsk_assets/cube.obj')
|
|
15
|
+
self.particle_renderers = {self.cube : ParticleRenderer(scene, self.cube, self.shader)}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def add(self, mesh: Mesh=None, life: float=1.0, position: tuple|float=0, material: Material=None, scale: float=1.0, velocity: tuple|float=0, acceleration: tuple|float=0) -> bool:
|
|
19
|
+
"""
|
|
20
|
+
Add a new particle to the scene
|
|
21
|
+
Args:
|
|
22
|
+
mesh: Mesh
|
|
23
|
+
The basilisk mesh of the particle
|
|
24
|
+
life: float
|
|
25
|
+
The duration of the particle in seconds
|
|
26
|
+
position: tuple (x, y, z)
|
|
27
|
+
The initial position of the particle
|
|
28
|
+
color: tuple (r, g, b) (components out of 255)
|
|
29
|
+
The color of the particle
|
|
30
|
+
scale: float
|
|
31
|
+
The overall scale factor of the particle
|
|
32
|
+
velocity: tuple (x, y, z)
|
|
33
|
+
The inital velocity of the particle as a vector
|
|
34
|
+
acceleration: tuple (x, y, z)
|
|
35
|
+
The permanent acceleration of the particle as a vector
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
# Get the mesh and make a new particle renderer if the mesh is new
|
|
39
|
+
if mesh == None: mesh = self.cube
|
|
40
|
+
elif not isinstance(mesh, Mesh): raise ValueError(f'particle_handler.add: invlaid mesh type for particle: {type(mesh)}')
|
|
41
|
+
if mesh not in self.particle_renderers: self.particle_renderers[mesh] = ParticleRenderer(self.scene, mesh, self.shader)
|
|
42
|
+
|
|
43
|
+
# Get material ID
|
|
44
|
+
if material == None: material_index = 0
|
|
45
|
+
elif isinstance(material, Material):
|
|
46
|
+
self.scene.engine.material_handler.add(material)
|
|
47
|
+
material_index = material.index
|
|
48
|
+
else: raise ValueError(f'particle_handler.add: Invalid particle material type: {type(material)}')
|
|
49
|
+
|
|
50
|
+
# Validate the 3-component vectors
|
|
51
|
+
position = validate_tuple3('particle', 'add', position)
|
|
52
|
+
velocity = validate_tuple3('particle', 'add', velocity)
|
|
53
|
+
acceleration = validate_tuple3('particle', 'add', acceleration)
|
|
54
|
+
|
|
55
|
+
# Validate float inputs
|
|
56
|
+
life = validate_float('particle', 'add', life)
|
|
57
|
+
scale = validate_float('particle', 'add', scale)
|
|
58
|
+
|
|
59
|
+
# Add the particle to the renderer
|
|
60
|
+
self.particle_renderers[mesh].add(life, position, material_index, scale, velocity, acceleration)
|
|
61
|
+
|
|
62
|
+
def render(self) -> None:
|
|
63
|
+
for renderer in self.particle_renderers.values(): renderer.render()
|
|
64
|
+
|
|
65
|
+
def update(self) -> None:
|
|
66
|
+
for renderer in self.particle_renderers.values(): renderer.update()
|
|
67
|
+
|
|
68
|
+
def clear(self) -> None:
|
|
69
|
+
self.particle_renderers.clear()
|
|
@@ -1,94 +1,93 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
from ..render.shader import Shader
|
|
3
|
-
from ..mesh.mesh import Mesh
|
|
4
|
-
from ..render.material import Material
|
|
5
|
-
from numba import njit
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
@njit
|
|
9
|
-
def update_particle_matrix(particle_instances, dt):
|
|
10
|
-
particle_instances[:,6:9] += particle_instances[:,9:12] * dt
|
|
11
|
-
particle_instances[:,:3] += particle_instances[:,6:9] * dt
|
|
12
|
-
particle_instances[:,5] -= dt
|
|
13
|
-
return particle_instances
|
|
14
|
-
|
|
15
|
-
@njit
|
|
16
|
-
def get_alive(particles):
|
|
17
|
-
return particles[particles[:, 5] >= 0]
|
|
18
|
-
|
|
19
|
-
update_particle_matrix(np.zeros(shape=(2, 12), dtype='f4'), 1)
|
|
20
|
-
get_alive(np.zeros(shape=(2, 12), dtype='f4'))
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
class ParticleRenderer:
|
|
24
|
-
def __init__(self, scene: ..., mesh: Mesh, shader: Shader=None) -> None:
|
|
25
|
-
"""
|
|
26
|
-
Handels and renders the particles of a single mesh type
|
|
27
|
-
"""
|
|
28
|
-
|
|
29
|
-
self.scene = scene
|
|
30
|
-
self.ctx = scene.ctx
|
|
31
|
-
root = scene.engine.root
|
|
32
|
-
if shader: self.shader = shader
|
|
33
|
-
else: self.shader = Shader(scene.engine, vert=root + '/shaders/particle.vert', frag=root + '/shaders/particle.frag')
|
|
34
|
-
|
|
35
|
-
scene.engine.shader_handler.add(self.shader)
|
|
36
|
-
|
|
37
|
-
self.particle_cube_size = 25
|
|
38
|
-
|
|
39
|
-
self.particle_instances = np.zeros(shape=(1, 12), dtype='f4')
|
|
40
|
-
self.instance_buffer = self.ctx.buffer(reserve=(12 * 3) * (self.particle_cube_size ** 3))
|
|
41
|
-
|
|
42
|
-
self.vao = self.ctx.vertex_array( self.shader.program,
|
|
43
|
-
[(self.ctx.buffer(mesh.data), '3f 2f 3f 3f 3f', *['in_position', 'in_uv', 'in_normal', 'in_tangent', 'in_bitangent']),
|
|
44
|
-
(self.instance_buffer, '3f 1f 1f 1f /i', 'in_instance_pos', 'in_instance_mtl', 'scale', 'life')],
|
|
45
|
-
skip_errors=True)
|
|
46
|
-
|
|
47
|
-
def render(self) -> None:
|
|
48
|
-
"""
|
|
49
|
-
Renders the alive particles in the scene
|
|
50
|
-
"""
|
|
51
|
-
|
|
52
|
-
# Get the current particles
|
|
53
|
-
alive_particles = get_alive(self.particle_instances)
|
|
54
|
-
n = len(alive_particles)
|
|
55
|
-
|
|
56
|
-
# Write and render
|
|
57
|
-
self.instance_buffer.write(np.array(alive_particles[:,:6], order='C'))
|
|
58
|
-
self.vao.render(instances=n)
|
|
59
|
-
|
|
60
|
-
def update(self) -> None:
|
|
61
|
-
"""
|
|
62
|
-
Updates the particle positions based on their given properties
|
|
63
|
-
"""
|
|
64
|
-
|
|
65
|
-
self.particle_instances = get_alive(self.particle_instances)
|
|
66
|
-
self.particle_instances = update_particle_matrix(self.particle_instances, self.scene.engine.delta_time)
|
|
67
|
-
|
|
68
|
-
def add(self, life=1.0, position=(0, 0, 0), material: int=0, scale=1.0, velocity=(0, 3, 0), acceleration=(0, -10, 0)) -> bool:
|
|
69
|
-
"""
|
|
70
|
-
Add a new particle to the scene
|
|
71
|
-
Args:
|
|
72
|
-
life: float
|
|
73
|
-
The duration of the particle in seconds
|
|
74
|
-
position: tuple (x, y, z)
|
|
75
|
-
The initial position of the particle
|
|
76
|
-
color: tuple (r, g, b) (components out of 255)
|
|
77
|
-
The color of the particle
|
|
78
|
-
scale: float
|
|
79
|
-
The overall scale factor of the particle
|
|
80
|
-
velocity: tuple (x, y, z)
|
|
81
|
-
The inital velocity of the particle as a vector
|
|
82
|
-
acceleration: tuple (x, y, z)
|
|
83
|
-
The permanent acceleration of the particle as a vector
|
|
84
|
-
"""
|
|
85
|
-
# Check if there is already the max number of particles
|
|
86
|
-
if len(self.particle_instances) >= (self.particle_cube_size ** 3): return False
|
|
87
|
-
# Create and add the particle to the scene
|
|
88
|
-
new_particle = np.array([*position, material, scale, life, *velocity, *acceleration])
|
|
89
|
-
self.particle_instances = np.vstack([new_particle, self.particle_instances], dtype='f4')
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
self.instance_buffer.release()
|
|
1
|
+
import numpy as np
|
|
2
|
+
from ..render.shader import Shader
|
|
3
|
+
from ..mesh.mesh import Mesh
|
|
4
|
+
from ..render.material import Material
|
|
5
|
+
from numba import njit
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@njit
|
|
9
|
+
def update_particle_matrix(particle_instances, dt):
|
|
10
|
+
particle_instances[:,6:9] += particle_instances[:,9:12] * dt
|
|
11
|
+
particle_instances[:,:3] += particle_instances[:,6:9] * dt
|
|
12
|
+
particle_instances[:,5] -= dt
|
|
13
|
+
return particle_instances
|
|
14
|
+
|
|
15
|
+
@njit
|
|
16
|
+
def get_alive(particles):
|
|
17
|
+
return particles[particles[:, 5] >= 0]
|
|
18
|
+
|
|
19
|
+
update_particle_matrix(np.zeros(shape=(2, 12), dtype='f4'), 1)
|
|
20
|
+
get_alive(np.zeros(shape=(2, 12), dtype='f4'))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ParticleRenderer:
|
|
24
|
+
def __init__(self, scene: ..., mesh: Mesh, shader: Shader=None) -> None:
|
|
25
|
+
"""
|
|
26
|
+
Handels and renders the particles of a single mesh type
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
self.scene = scene
|
|
30
|
+
self.ctx = scene.ctx
|
|
31
|
+
root = scene.engine.root
|
|
32
|
+
if shader: self.shader = shader
|
|
33
|
+
else: self.shader = Shader(scene.engine, vert=root + '/shaders/particle.vert', frag=root + '/shaders/particle.frag')
|
|
34
|
+
|
|
35
|
+
scene.engine.shader_handler.add(self.shader)
|
|
36
|
+
|
|
37
|
+
self.particle_cube_size = 25
|
|
38
|
+
|
|
39
|
+
self.particle_instances = np.zeros(shape=(1, 12), dtype='f4')
|
|
40
|
+
self.instance_buffer = self.ctx.buffer(reserve=(12 * 3) * (self.particle_cube_size ** 3))
|
|
41
|
+
|
|
42
|
+
self.vao = self.ctx.vertex_array( self.shader.program,
|
|
43
|
+
[(self.ctx.buffer(mesh.data), '3f 2f 3f 3f 3f', *['in_position', 'in_uv', 'in_normal', 'in_tangent', 'in_bitangent']),
|
|
44
|
+
(self.instance_buffer, '3f 1f 1f 1f /i', 'in_instance_pos', 'in_instance_mtl', 'scale', 'life')],
|
|
45
|
+
skip_errors=True)
|
|
46
|
+
|
|
47
|
+
def render(self) -> None:
|
|
48
|
+
"""
|
|
49
|
+
Renders the alive particles in the scene
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
# Get the current particles
|
|
53
|
+
alive_particles = get_alive(self.particle_instances)
|
|
54
|
+
n = len(alive_particles)
|
|
55
|
+
|
|
56
|
+
# Write and render
|
|
57
|
+
self.instance_buffer.write(np.array(alive_particles[:,:6], order='C'))
|
|
58
|
+
self.vao.render(instances=n)
|
|
59
|
+
|
|
60
|
+
def update(self) -> None:
|
|
61
|
+
"""
|
|
62
|
+
Updates the particle positions based on their given properties
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
self.particle_instances = get_alive(self.particle_instances)
|
|
66
|
+
self.particle_instances = update_particle_matrix(self.particle_instances, self.scene.engine.delta_time)
|
|
67
|
+
|
|
68
|
+
def add(self, life=1.0, position=(0, 0, 0), material: int=0, scale=1.0, velocity=(0, 3, 0), acceleration=(0, -10, 0)) -> bool:
|
|
69
|
+
"""
|
|
70
|
+
Add a new particle to the scene
|
|
71
|
+
Args:
|
|
72
|
+
life: float
|
|
73
|
+
The duration of the particle in seconds
|
|
74
|
+
position: tuple (x, y, z)
|
|
75
|
+
The initial position of the particle
|
|
76
|
+
color: tuple (r, g, b) (components out of 255)
|
|
77
|
+
The color of the particle
|
|
78
|
+
scale: float
|
|
79
|
+
The overall scale factor of the particle
|
|
80
|
+
velocity: tuple (x, y, z)
|
|
81
|
+
The inital velocity of the particle as a vector
|
|
82
|
+
acceleration: tuple (x, y, z)
|
|
83
|
+
The permanent acceleration of the particle as a vector
|
|
84
|
+
"""
|
|
85
|
+
# Check if there is already the max number of particles
|
|
86
|
+
if len(self.particle_instances) >= (self.particle_cube_size ** 3): return False
|
|
87
|
+
# Create and add the particle to the scene
|
|
88
|
+
new_particle = np.array([*position, material, scale, life, *velocity, *acceleration])
|
|
89
|
+
self.particle_instances = np.vstack([new_particle, self.particle_instances], dtype='f4')
|
|
90
|
+
|
|
91
|
+
def __del__(self):
|
|
92
|
+
self.instance_buffer.release()
|
|
94
93
|
self.vao.release()
|