basilisk-engine 0.1.41__py3-none-any.whl → 0.1.43__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of basilisk-engine might be problematic. Click here for more details.
- basilisk/__init__.py +26 -26
- basilisk/audio/sound.py +27 -27
- basilisk/bsk_assets/cube.obj +48 -48
- basilisk/collisions/broad/broad_aabb.py +102 -102
- basilisk/collisions/broad/broad_bvh.py +137 -137
- basilisk/collisions/collider.py +95 -95
- basilisk/collisions/collider_handler.py +225 -225
- basilisk/collisions/narrow/contact_manifold.py +95 -95
- basilisk/collisions/narrow/dataclasses.py +34 -34
- basilisk/collisions/narrow/deprecated.py +46 -46
- basilisk/collisions/narrow/epa.py +91 -91
- basilisk/collisions/narrow/gjk.py +66 -66
- basilisk/collisions/narrow/graham_scan.py +24 -24
- basilisk/collisions/narrow/helper.py +29 -29
- basilisk/collisions/narrow/line_intersections.py +106 -106
- basilisk/collisions/narrow/sutherland_hodgman.py +75 -75
- basilisk/config.py +53 -53
- basilisk/draw/draw.py +100 -100
- basilisk/draw/draw_handler.py +178 -178
- basilisk/draw/font_renderer.py +28 -28
- basilisk/engine.py +169 -171
- basilisk/generic/abstract_bvh.py +15 -15
- basilisk/generic/abstract_custom.py +133 -133
- basilisk/generic/collisions.py +70 -70
- basilisk/generic/input_validation.py +82 -82
- basilisk/generic/math.py +17 -17
- basilisk/generic/matrices.py +35 -35
- basilisk/generic/meshes.py +72 -72
- basilisk/generic/quat.py +142 -142
- basilisk/generic/quat_methods.py +7 -7
- basilisk/generic/raycast_result.py +26 -26
- basilisk/generic/vec3.py +143 -143
- basilisk/input_output/IO_handler.py +91 -91
- basilisk/input_output/clock.py +49 -49
- basilisk/input_output/keys.py +43 -43
- basilisk/input_output/mouse.py +90 -90
- basilisk/input_output/path.py +14 -14
- basilisk/mesh/cube.py +33 -33
- basilisk/mesh/mesh.py +233 -233
- basilisk/mesh/mesh_from_data.py +150 -150
- basilisk/mesh/model.py +271 -271
- basilisk/mesh/narrow_aabb.py +89 -89
- basilisk/mesh/narrow_bvh.py +91 -91
- basilisk/mesh/narrow_primative.py +23 -23
- basilisk/nodes/helper.py +28 -28
- basilisk/nodes/node.py +709 -709
- basilisk/nodes/node_handler.py +97 -97
- basilisk/particles/particle_handler.py +64 -64
- basilisk/particles/particle_renderer.py +93 -93
- basilisk/physics/impulse.py +112 -112
- basilisk/physics/physics_body.py +43 -43
- basilisk/physics/physics_engine.py +35 -35
- basilisk/render/batch.py +103 -103
- basilisk/render/bloom.py +118 -124
- basilisk/render/camera.py +260 -260
- basilisk/render/chunk.py +113 -108
- basilisk/render/chunk_handler.py +167 -167
- basilisk/render/frame.py +130 -128
- basilisk/render/framebuffer.py +192 -212
- basilisk/render/image.py +120 -120
- basilisk/render/image_handler.py +120 -120
- basilisk/render/light.py +96 -96
- basilisk/render/light_handler.py +58 -58
- basilisk/render/material.py +232 -232
- basilisk/render/material_handler.py +133 -133
- basilisk/render/post_process.py +180 -180
- basilisk/render/shader.py +135 -134
- basilisk/render/shader_handler.py +109 -94
- basilisk/render/sky.py +119 -121
- basilisk/scene.py +287 -288
- basilisk/shaders/batch.frag +293 -293
- basilisk/shaders/batch.vert +117 -117
- basilisk/shaders/bloom_downsample.frag +23 -42
- basilisk/shaders/bloom_upsample.frag +33 -33
- basilisk/shaders/crt.frag +34 -34
- basilisk/shaders/draw.frag +27 -27
- basilisk/shaders/draw.vert +25 -25
- basilisk/shaders/filter.frag +22 -22
- basilisk/shaders/frame.frag +13 -13
- basilisk/shaders/frame.vert +13 -13
- basilisk/shaders/frame_hdr.frag +27 -27
- basilisk/shaders/geometry.frag +10 -10
- basilisk/shaders/geometry.vert +41 -41
- basilisk/shaders/normal.frag +62 -62
- basilisk/shaders/normal.vert +96 -96
- basilisk/shaders/particle.frag +81 -81
- basilisk/shaders/particle.vert +86 -86
- basilisk/shaders/sky.frag +23 -23
- basilisk/shaders/sky.vert +13 -13
- {basilisk_engine-0.1.41.dist-info → basilisk_engine-0.1.43.dist-info}/METADATA +89 -89
- basilisk_engine-0.1.43.dist-info/RECORD +111 -0
- {basilisk_engine-0.1.41.dist-info → basilisk_engine-0.1.43.dist-info}/WHEEL +1 -1
- basilisk_engine-0.1.41.dist-info/RECORD +0 -111
- {basilisk_engine-0.1.41.dist-info → basilisk_engine-0.1.43.dist-info}/top_level.txt +0 -0
basilisk/physics/impulse.py
CHANGED
|
@@ -1,113 +1,113 @@
|
|
|
1
|
-
import glm
|
|
2
|
-
from ..nodes.node import Node
|
|
3
|
-
|
|
4
|
-
def calculate_collisions(normal:glm.vec3, node1: Node, node2: Node, contact_points:list[glm.vec3], inv_inertia1:glm.mat3x3, inv_inertia2:glm.mat3x3, center1:glm.vec3, center2:glm.vec3) -> None:
|
|
5
|
-
"""
|
|
6
|
-
Resolve the collisions between two objects with multiple contact points
|
|
7
|
-
"""
|
|
8
|
-
physics_body1 = node1.physics_body
|
|
9
|
-
physics_body2 = node2.physics_body
|
|
10
|
-
collider1 = node1.collider
|
|
11
|
-
collider2 = node2.collider
|
|
12
|
-
|
|
13
|
-
# determine whether or not the colliders have physics
|
|
14
|
-
has_physics1, has_physics2 = physics_body1 is not None, physics_body2 is not None
|
|
15
|
-
|
|
16
|
-
# get physics data from valid bodies
|
|
17
|
-
if has_physics1: inv_mass1 = 1 / physics_body1.mass
|
|
18
|
-
if has_physics2: inv_mass2 = 1 / physics_body2.mass
|
|
19
|
-
|
|
20
|
-
# gets coefficients
|
|
21
|
-
elasticity = max(collider1.elasticity, collider2.elasticity)
|
|
22
|
-
kinetic = min(collider1.kinetic_friction, collider2.kinetic_friction)
|
|
23
|
-
static = min(collider1.static_friction, collider2.static_friction)
|
|
24
|
-
|
|
25
|
-
# calculate impulses from contact points
|
|
26
|
-
if has_physics1 and has_physics2:
|
|
27
|
-
for contact_point in contact_points:
|
|
28
|
-
|
|
29
|
-
# apply impulse based reduced by total points
|
|
30
|
-
radius1, radius2 = contact_point - center1, contact_point - center2
|
|
31
|
-
impulse = calculate_impulse2(node1, node2, inv_mass1, inv_mass2, node1.rotational_velocity, node2.rotational_velocity, radius1, radius2, inv_inertia1, inv_inertia2, elasticity, kinetic, static, normal)
|
|
32
|
-
|
|
33
|
-
# apply impulses
|
|
34
|
-
apply_impulse(radius1, impulse, inv_inertia1, inv_mass1, node1)
|
|
35
|
-
apply_impulse(radius2, -impulse, inv_inertia2, inv_mass2, node2)
|
|
36
|
-
|
|
37
|
-
elif has_physics1:
|
|
38
|
-
for contact_point in contact_points:
|
|
39
|
-
radius = contact_point - center1
|
|
40
|
-
impulse = calculate_impluse1(node1, inv_mass1, node1.rotational_velocity, radius, inv_inertia1, elasticity, kinetic, static, normal)
|
|
41
|
-
|
|
42
|
-
# apply impulses
|
|
43
|
-
apply_impulse(radius, impulse, inv_inertia1, inv_mass1, node1)
|
|
44
|
-
|
|
45
|
-
else: # only physics body 2
|
|
46
|
-
for contact_point in contact_points:
|
|
47
|
-
radius = contact_point - center2
|
|
48
|
-
impulse = calculate_impluse1(node2, inv_mass2, node2.rotational_velocity, radius, inv_inertia2, elasticity, kinetic, static, normal)
|
|
49
|
-
|
|
50
|
-
# apply impulse
|
|
51
|
-
apply_impulse(radius, impulse, inv_inertia2, inv_mass2, node2)
|
|
52
|
-
|
|
53
|
-
def calculate_impluse1(node: Node, inv_mass, omega, radius, inv_inertia, elasticity, kinetic, static, normal) -> glm.vec3:
|
|
54
|
-
"""
|
|
55
|
-
Calculates the impulse from a collision including friction from the impulse
|
|
56
|
-
"""
|
|
57
|
-
# determine if mass needs to be calculated TODO determine if this is a good check
|
|
58
|
-
if glm.dot(radius, node.velocity) < 0: return glm.vec3(0, 0, 0)
|
|
59
|
-
|
|
60
|
-
# normal impulse
|
|
61
|
-
relative_velocity = node.velocity + glm.cross(omega, radius)
|
|
62
|
-
relative_normal_velocity = glm.dot(relative_velocity, normal)
|
|
63
|
-
|
|
64
|
-
# calculate denominator
|
|
65
|
-
denominator = inv_mass + glm.dot(normal, glm.cross(inv_inertia * glm.cross(radius, normal), radius))
|
|
66
|
-
|
|
67
|
-
# calculate normal impulse
|
|
68
|
-
normal_impulse_magnitude = -(1 + elasticity) * relative_normal_velocity / denominator
|
|
69
|
-
normal_impulse = normal_impulse_magnitude * normal
|
|
70
|
-
|
|
71
|
-
# friction impulse
|
|
72
|
-
rel_tan_vel = relative_velocity - glm.dot(relative_velocity, normal) * normal
|
|
73
|
-
rel_tan_vel_len = glm.length(rel_tan_vel)
|
|
74
|
-
|
|
75
|
-
if rel_tan_vel_len < 1e-7: friction_impulse = glm.vec3(0, 0, 0) # no friction
|
|
76
|
-
elif rel_tan_vel_len < 1e-2: friction_impulse = -static * glm.length(normal_impulse) * glm.normalize(rel_tan_vel) # static friction
|
|
77
|
-
else: friction_impulse = -kinetic * glm.length(normal_impulse) * glm.normalize(rel_tan_vel) # kinetic friction
|
|
78
|
-
|
|
79
|
-
# return total impulse
|
|
80
|
-
return normal_impulse + friction_impulse
|
|
81
|
-
|
|
82
|
-
def calculate_impulse2(node1: Node, node2: Node, inv_mass1, inv_mass2, omega1, omega2, radius1, radius2, inv_inertia1, inv_inertia2, elasticity, kinetic, static, normal) -> glm.vec3:
|
|
83
|
-
"""
|
|
84
|
-
Calculates the impulse from a collision including friction from the impulse
|
|
85
|
-
"""
|
|
86
|
-
# normal impulse
|
|
87
|
-
relative_velocity = node1.velocity + glm.cross(omega1, radius1) - (node2.velocity + glm.cross(omega2, radius2))
|
|
88
|
-
relative_normal_velocity = glm.dot(relative_velocity, normal)
|
|
89
|
-
# calculate denominator
|
|
90
|
-
term1 = inv_mass1 + inv_mass2
|
|
91
|
-
term2 = glm.dot(normal, glm.cross(inv_inertia1 * glm.cross(radius1, normal), radius1) + glm.cross(inv_inertia2 * glm.cross(radius2, normal), radius2))
|
|
92
|
-
# calculate normal impulse
|
|
93
|
-
normal_impulse = -(1 + elasticity) * relative_normal_velocity / (term1 + term2) * normal
|
|
94
|
-
|
|
95
|
-
# friction impulse
|
|
96
|
-
rel_tan_vel = relative_velocity - glm.dot(relative_velocity, normal) * normal
|
|
97
|
-
rel_tan_vel_len = glm.length(rel_tan_vel)
|
|
98
|
-
if rel_tan_vel_len < 1e-7: friction_impulse = glm.vec3(0, 0, 0)
|
|
99
|
-
elif rel_tan_vel_len < 1e-2: friction_impulse = -static * glm.length(normal_impulse) * glm.normalize(rel_tan_vel)
|
|
100
|
-
else: friction_impulse = -kinetic * glm.length(normal_impulse) * glm.normalize(rel_tan_vel)
|
|
101
|
-
# return total impulse
|
|
102
|
-
return normal_impulse + friction_impulse
|
|
103
|
-
|
|
104
|
-
def apply_impulse(radius, impulse_signed, inv_inertia, inv_mass, node: Node) -> None:
|
|
105
|
-
"""
|
|
106
|
-
Applies the given impulse to the physics body, changing translational and rotational velcoity.
|
|
107
|
-
"""
|
|
108
|
-
|
|
109
|
-
# Update linear velocity
|
|
110
|
-
node.velocity += impulse_signed * inv_mass
|
|
111
|
-
|
|
112
|
-
# update rotational velcoity
|
|
1
|
+
import glm
|
|
2
|
+
from ..nodes.node import Node
|
|
3
|
+
|
|
4
|
+
def calculate_collisions(normal:glm.vec3, node1: Node, node2: Node, contact_points:list[glm.vec3], inv_inertia1:glm.mat3x3, inv_inertia2:glm.mat3x3, center1:glm.vec3, center2:glm.vec3) -> None:
|
|
5
|
+
"""
|
|
6
|
+
Resolve the collisions between two objects with multiple contact points
|
|
7
|
+
"""
|
|
8
|
+
physics_body1 = node1.physics_body
|
|
9
|
+
physics_body2 = node2.physics_body
|
|
10
|
+
collider1 = node1.collider
|
|
11
|
+
collider2 = node2.collider
|
|
12
|
+
|
|
13
|
+
# determine whether or not the colliders have physics
|
|
14
|
+
has_physics1, has_physics2 = physics_body1 is not None, physics_body2 is not None
|
|
15
|
+
|
|
16
|
+
# get physics data from valid bodies
|
|
17
|
+
if has_physics1: inv_mass1 = 1 / physics_body1.mass
|
|
18
|
+
if has_physics2: inv_mass2 = 1 / physics_body2.mass
|
|
19
|
+
|
|
20
|
+
# gets coefficients
|
|
21
|
+
elasticity = max(collider1.elasticity, collider2.elasticity)
|
|
22
|
+
kinetic = min(collider1.kinetic_friction, collider2.kinetic_friction)
|
|
23
|
+
static = min(collider1.static_friction, collider2.static_friction)
|
|
24
|
+
|
|
25
|
+
# calculate impulses from contact points
|
|
26
|
+
if has_physics1 and has_physics2:
|
|
27
|
+
for contact_point in contact_points:
|
|
28
|
+
|
|
29
|
+
# apply impulse based reduced by total points
|
|
30
|
+
radius1, radius2 = contact_point - center1, contact_point - center2
|
|
31
|
+
impulse = calculate_impulse2(node1, node2, inv_mass1, inv_mass2, node1.rotational_velocity, node2.rotational_velocity, radius1, radius2, inv_inertia1, inv_inertia2, elasticity, kinetic, static, normal)
|
|
32
|
+
|
|
33
|
+
# apply impulses
|
|
34
|
+
apply_impulse(radius1, impulse, inv_inertia1, inv_mass1, node1)
|
|
35
|
+
apply_impulse(radius2, -impulse, inv_inertia2, inv_mass2, node2)
|
|
36
|
+
|
|
37
|
+
elif has_physics1:
|
|
38
|
+
for contact_point in contact_points:
|
|
39
|
+
radius = contact_point - center1
|
|
40
|
+
impulse = calculate_impluse1(node1, inv_mass1, node1.rotational_velocity, radius, inv_inertia1, elasticity, kinetic, static, normal)
|
|
41
|
+
|
|
42
|
+
# apply impulses
|
|
43
|
+
apply_impulse(radius, impulse, inv_inertia1, inv_mass1, node1)
|
|
44
|
+
|
|
45
|
+
else: # only physics body 2
|
|
46
|
+
for contact_point in contact_points:
|
|
47
|
+
radius = contact_point - center2
|
|
48
|
+
impulse = calculate_impluse1(node2, inv_mass2, node2.rotational_velocity, radius, inv_inertia2, elasticity, kinetic, static, normal)
|
|
49
|
+
|
|
50
|
+
# apply impulse
|
|
51
|
+
apply_impulse(radius, impulse, inv_inertia2, inv_mass2, node2)
|
|
52
|
+
|
|
53
|
+
def calculate_impluse1(node: Node, inv_mass, omega, radius, inv_inertia, elasticity, kinetic, static, normal) -> glm.vec3:
|
|
54
|
+
"""
|
|
55
|
+
Calculates the impulse from a collision including friction from the impulse
|
|
56
|
+
"""
|
|
57
|
+
# determine if mass needs to be calculated TODO determine if this is a good check
|
|
58
|
+
if glm.dot(radius, node.velocity) < 0: return glm.vec3(0, 0, 0)
|
|
59
|
+
|
|
60
|
+
# normal impulse
|
|
61
|
+
relative_velocity = node.velocity + glm.cross(omega, radius)
|
|
62
|
+
relative_normal_velocity = glm.dot(relative_velocity, normal)
|
|
63
|
+
|
|
64
|
+
# calculate denominator
|
|
65
|
+
denominator = inv_mass + glm.dot(normal, glm.cross(inv_inertia * glm.cross(radius, normal), radius))
|
|
66
|
+
|
|
67
|
+
# calculate normal impulse
|
|
68
|
+
normal_impulse_magnitude = -(1 + elasticity) * relative_normal_velocity / denominator
|
|
69
|
+
normal_impulse = normal_impulse_magnitude * normal
|
|
70
|
+
|
|
71
|
+
# friction impulse
|
|
72
|
+
rel_tan_vel = relative_velocity - glm.dot(relative_velocity, normal) * normal
|
|
73
|
+
rel_tan_vel_len = glm.length(rel_tan_vel)
|
|
74
|
+
|
|
75
|
+
if rel_tan_vel_len < 1e-7: friction_impulse = glm.vec3(0, 0, 0) # no friction
|
|
76
|
+
elif rel_tan_vel_len < 1e-2: friction_impulse = -static * glm.length(normal_impulse) * glm.normalize(rel_tan_vel) # static friction
|
|
77
|
+
else: friction_impulse = -kinetic * glm.length(normal_impulse) * glm.normalize(rel_tan_vel) # kinetic friction
|
|
78
|
+
|
|
79
|
+
# return total impulse
|
|
80
|
+
return normal_impulse + friction_impulse
|
|
81
|
+
|
|
82
|
+
def calculate_impulse2(node1: Node, node2: Node, inv_mass1, inv_mass2, omega1, omega2, radius1, radius2, inv_inertia1, inv_inertia2, elasticity, kinetic, static, normal) -> glm.vec3:
|
|
83
|
+
"""
|
|
84
|
+
Calculates the impulse from a collision including friction from the impulse
|
|
85
|
+
"""
|
|
86
|
+
# normal impulse
|
|
87
|
+
relative_velocity = node1.velocity + glm.cross(omega1, radius1) - (node2.velocity + glm.cross(omega2, radius2))
|
|
88
|
+
relative_normal_velocity = glm.dot(relative_velocity, normal)
|
|
89
|
+
# calculate denominator
|
|
90
|
+
term1 = inv_mass1 + inv_mass2
|
|
91
|
+
term2 = glm.dot(normal, glm.cross(inv_inertia1 * glm.cross(radius1, normal), radius1) + glm.cross(inv_inertia2 * glm.cross(radius2, normal), radius2))
|
|
92
|
+
# calculate normal impulse
|
|
93
|
+
normal_impulse = -(1 + elasticity) * relative_normal_velocity / (term1 + term2) * normal
|
|
94
|
+
|
|
95
|
+
# friction impulse
|
|
96
|
+
rel_tan_vel = relative_velocity - glm.dot(relative_velocity, normal) * normal
|
|
97
|
+
rel_tan_vel_len = glm.length(rel_tan_vel)
|
|
98
|
+
if rel_tan_vel_len < 1e-7: friction_impulse = glm.vec3(0, 0, 0)
|
|
99
|
+
elif rel_tan_vel_len < 1e-2: friction_impulse = -static * glm.length(normal_impulse) * glm.normalize(rel_tan_vel)
|
|
100
|
+
else: friction_impulse = -kinetic * glm.length(normal_impulse) * glm.normalize(rel_tan_vel)
|
|
101
|
+
# return total impulse
|
|
102
|
+
return normal_impulse + friction_impulse
|
|
103
|
+
|
|
104
|
+
def apply_impulse(radius, impulse_signed, inv_inertia, inv_mass, node: Node) -> None:
|
|
105
|
+
"""
|
|
106
|
+
Applies the given impulse to the physics body, changing translational and rotational velcoity.
|
|
107
|
+
"""
|
|
108
|
+
|
|
109
|
+
# Update linear velocity
|
|
110
|
+
node.velocity += impulse_signed * inv_mass
|
|
111
|
+
|
|
112
|
+
# update rotational velcoity
|
|
113
113
|
node.rotational_velocity += inv_inertia * glm.cross(radius, impulse_signed)
|
basilisk/physics/physics_body.py
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
import glm
|
|
2
|
-
|
|
3
|
-
class PhysicsBody():
|
|
4
|
-
physics_engine: ...
|
|
5
|
-
"""Back reference to the parent physics engine"""
|
|
6
|
-
mass: float
|
|
7
|
-
"""The mass of the physics body in kg"""
|
|
8
|
-
|
|
9
|
-
def __init__(self, mass:float=1.0) -> None:
|
|
10
|
-
self.physics_engine = None
|
|
11
|
-
self.mass = mass
|
|
12
|
-
|
|
13
|
-
def get_delta_velocity(self, dt: float) -> glm.vec3:
|
|
14
|
-
"""
|
|
15
|
-
Returns the chnage in translational velocity from constant accelerations and forces
|
|
16
|
-
"""
|
|
17
|
-
if not self.physics_engine: return None
|
|
18
|
-
|
|
19
|
-
dv = glm.vec3(0, 0, 0)
|
|
20
|
-
for acceleration in self.physics_engine.accelerations: dv += acceleration * dt
|
|
21
|
-
for force in self.physics_engine.forces: dv += force / self.mass * dt
|
|
22
|
-
return dv
|
|
23
|
-
|
|
24
|
-
def get_delta_rotational_velocity(self, dt: float) -> glm.quat:
|
|
25
|
-
"""
|
|
26
|
-
Returns the delta rotation quaternion from constant accelerations and forces
|
|
27
|
-
"""
|
|
28
|
-
if not self.physics_engine: return None
|
|
29
|
-
|
|
30
|
-
dw = glm.vec3(0, 0, 0)
|
|
31
|
-
for rotational_acceleration in self.physics_engine.rotational_accelerations: dw += rotational_acceleration * dt
|
|
32
|
-
# TODO add torques
|
|
33
|
-
return dw
|
|
34
|
-
|
|
35
|
-
@property
|
|
36
|
-
def physics_engine(self): return self._physics_engine
|
|
37
|
-
|
|
38
|
-
@physics_engine.setter
|
|
39
|
-
def physics_engine(self, value):
|
|
40
|
-
self._physics_engine = value
|
|
41
|
-
if value: value.add(self)
|
|
42
|
-
|
|
43
|
-
def __repr__(self) -> str:
|
|
1
|
+
import glm
|
|
2
|
+
|
|
3
|
+
class PhysicsBody():
|
|
4
|
+
physics_engine: ...
|
|
5
|
+
"""Back reference to the parent physics engine"""
|
|
6
|
+
mass: float
|
|
7
|
+
"""The mass of the physics body in kg"""
|
|
8
|
+
|
|
9
|
+
def __init__(self, mass:float=1.0) -> None:
|
|
10
|
+
self.physics_engine = None
|
|
11
|
+
self.mass = mass
|
|
12
|
+
|
|
13
|
+
def get_delta_velocity(self, dt: float) -> glm.vec3:
|
|
14
|
+
"""
|
|
15
|
+
Returns the chnage in translational velocity from constant accelerations and forces
|
|
16
|
+
"""
|
|
17
|
+
if not self.physics_engine: return None
|
|
18
|
+
|
|
19
|
+
dv = glm.vec3(0, 0, 0)
|
|
20
|
+
for acceleration in self.physics_engine.accelerations: dv += acceleration * dt
|
|
21
|
+
for force in self.physics_engine.forces: dv += force / self.mass * dt
|
|
22
|
+
return dv
|
|
23
|
+
|
|
24
|
+
def get_delta_rotational_velocity(self, dt: float) -> glm.quat:
|
|
25
|
+
"""
|
|
26
|
+
Returns the delta rotation quaternion from constant accelerations and forces
|
|
27
|
+
"""
|
|
28
|
+
if not self.physics_engine: return None
|
|
29
|
+
|
|
30
|
+
dw = glm.vec3(0, 0, 0)
|
|
31
|
+
for rotational_acceleration in self.physics_engine.rotational_accelerations: dw += rotational_acceleration * dt
|
|
32
|
+
# TODO add torques
|
|
33
|
+
return dw
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def physics_engine(self): return self._physics_engine
|
|
37
|
+
|
|
38
|
+
@physics_engine.setter
|
|
39
|
+
def physics_engine(self, value):
|
|
40
|
+
self._physics_engine = value
|
|
41
|
+
if value: value.add(self)
|
|
42
|
+
|
|
43
|
+
def __repr__(self) -> str:
|
|
44
44
|
return f'<Physics Body| {self.mass}>'
|
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
import glm
|
|
2
|
-
from .physics_body import PhysicsBody
|
|
3
|
-
|
|
4
|
-
class PhysicsEngine():
|
|
5
|
-
physics_bodies: list[PhysicsBody]
|
|
6
|
-
"""Contains all the physics bodies controlled by this physics engine"""
|
|
7
|
-
accelerations: list[glm.vec3]
|
|
8
|
-
"""Contains constant accelerations to be applied to physics bodies"""
|
|
9
|
-
rotational_accelerations: list[glm.vec3]
|
|
10
|
-
"""Contains constant rotational accelerations to be applied to physics bodies"""
|
|
11
|
-
forces: list[glm.vec3]
|
|
12
|
-
"""Contains constant forces to be applied to physics bodies"""
|
|
13
|
-
torques: list[glm.vec3]
|
|
14
|
-
"""Contains constant rotational accelerations to be applied to physics bodies"""
|
|
15
|
-
|
|
16
|
-
def __init__(self, accelerations: list[glm.vec3] = None, rotational_accelerations: list[glm.vec3] = None, forces: list[glm.vec3] = None, torques: list[glm.vec3] = None) -> None:
|
|
17
|
-
self.physics_bodies = []
|
|
18
|
-
self.accelerations = accelerations if accelerations else [glm.vec3(0, -9.8, 0)]
|
|
19
|
-
self.rotational_accelerations = rotational_accelerations if rotational_accelerations else []
|
|
20
|
-
self.forces = forces if forces else []
|
|
21
|
-
self.torques = torques if torques else []
|
|
22
|
-
|
|
23
|
-
def add(self, physics_body: PhysicsBody) -> PhysicsBody:
|
|
24
|
-
"""
|
|
25
|
-
Adds a physics body to the physics engine and returns it
|
|
26
|
-
"""
|
|
27
|
-
self.physics_bodies.append(physics_body)
|
|
28
|
-
return physics_body
|
|
29
|
-
|
|
30
|
-
def remove(self, physics_body: PhysicsBody) -> None:
|
|
31
|
-
"""
|
|
32
|
-
Removes the physics body from the physics engine and disconnects it from the engine
|
|
33
|
-
"""
|
|
34
|
-
if physics_body in self.physics_bodies:
|
|
35
|
-
self.physics_bodies.remove(physics_body)
|
|
1
|
+
import glm
|
|
2
|
+
from .physics_body import PhysicsBody
|
|
3
|
+
|
|
4
|
+
class PhysicsEngine():
|
|
5
|
+
physics_bodies: list[PhysicsBody]
|
|
6
|
+
"""Contains all the physics bodies controlled by this physics engine"""
|
|
7
|
+
accelerations: list[glm.vec3]
|
|
8
|
+
"""Contains constant accelerations to be applied to physics bodies"""
|
|
9
|
+
rotational_accelerations: list[glm.vec3]
|
|
10
|
+
"""Contains constant rotational accelerations to be applied to physics bodies"""
|
|
11
|
+
forces: list[glm.vec3]
|
|
12
|
+
"""Contains constant forces to be applied to physics bodies"""
|
|
13
|
+
torques: list[glm.vec3]
|
|
14
|
+
"""Contains constant rotational accelerations to be applied to physics bodies"""
|
|
15
|
+
|
|
16
|
+
def __init__(self, accelerations: list[glm.vec3] = None, rotational_accelerations: list[glm.vec3] = None, forces: list[glm.vec3] = None, torques: list[glm.vec3] = None) -> None:
|
|
17
|
+
self.physics_bodies = []
|
|
18
|
+
self.accelerations = accelerations if accelerations else [glm.vec3(0, -9.8, 0)]
|
|
19
|
+
self.rotational_accelerations = rotational_accelerations if rotational_accelerations else []
|
|
20
|
+
self.forces = forces if forces else []
|
|
21
|
+
self.torques = torques if torques else []
|
|
22
|
+
|
|
23
|
+
def add(self, physics_body: PhysicsBody) -> PhysicsBody:
|
|
24
|
+
"""
|
|
25
|
+
Adds a physics body to the physics engine and returns it
|
|
26
|
+
"""
|
|
27
|
+
self.physics_bodies.append(physics_body)
|
|
28
|
+
return physics_body
|
|
29
|
+
|
|
30
|
+
def remove(self, physics_body: PhysicsBody) -> None:
|
|
31
|
+
"""
|
|
32
|
+
Removes the physics body from the physics engine and disconnects it from the engine
|
|
33
|
+
"""
|
|
34
|
+
if physics_body in self.physics_bodies:
|
|
35
|
+
self.physics_bodies.remove(physics_body)
|
|
36
36
|
physics_body.physics_engine = None
|
basilisk/render/batch.py
CHANGED
|
@@ -1,104 +1,104 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
import moderngl as mgl
|
|
3
|
-
from .shader import Shader
|
|
4
|
-
|
|
5
|
-
class Batch():
|
|
6
|
-
chunk: ...
|
|
7
|
-
"""Reference to the parent chunk of the batch"""
|
|
8
|
-
ctx: mgl.Context
|
|
9
|
-
"""Reference to the context of the parent engine"""
|
|
10
|
-
shader: Shader
|
|
11
|
-
"""Reference to the bsk.Shader used by batches"""
|
|
12
|
-
vao: mgl.VertexArray
|
|
13
|
-
"""The vertex array of the batch. Used for rendering"""
|
|
14
|
-
vbo: mgl.Buffer
|
|
15
|
-
"""Buffer containing all the batch data"""
|
|
16
|
-
|
|
17
|
-
def __init__(self, chunk) -> None:
|
|
18
|
-
"""
|
|
19
|
-
Basilik batch object
|
|
20
|
-
Contains all the data for a chunk batch to be stored and rendered
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
# Back references
|
|
24
|
-
self.chunk = chunk
|
|
25
|
-
self.ctx = chunk.chunk_handler.engine.ctx
|
|
26
|
-
self.shader = self.chunk.get_shader()
|
|
27
|
-
|
|
28
|
-
# Set intial values
|
|
29
|
-
self.vbo = None
|
|
30
|
-
self.vao = None
|
|
31
|
-
|
|
32
|
-
def batch(self) -> bool:
|
|
33
|
-
"""
|
|
34
|
-
Batches all the node meshes in the chunks bounds.
|
|
35
|
-
Returns True if batch was successful.
|
|
36
|
-
"""
|
|
37
|
-
|
|
38
|
-
self.shader = self.chunk.get_shader()
|
|
39
|
-
|
|
40
|
-
# Empty list to contain all vertex data of models in the chunk
|
|
41
|
-
batch_data = []
|
|
42
|
-
|
|
43
|
-
# Loop through each node in the chunk, adding the nodes's mesh to batch_data
|
|
44
|
-
index = 0
|
|
45
|
-
for node in self.chunk.nodes:
|
|
46
|
-
# Check that the node should be used
|
|
47
|
-
if not node.mesh: continue
|
|
48
|
-
if node.static != self.chunk.static: continue
|
|
49
|
-
|
|
50
|
-
# Get the data from the node
|
|
51
|
-
node_data = node.get_data()
|
|
52
|
-
# Update the index
|
|
53
|
-
node.data_index = index
|
|
54
|
-
index += len(node_data)
|
|
55
|
-
# Add to the chunk mesh
|
|
56
|
-
batch_data.append(node_data)
|
|
57
|
-
|
|
58
|
-
# Combine all meshes into a single array
|
|
59
|
-
if len(batch_data) > 1: batch_data = np.vstack(batch_data)
|
|
60
|
-
else: batch_data = np.array(batch_data, dtype='f4')
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
# If there are no verticies, delete the chunk
|
|
64
|
-
if len(batch_data) == 0: return False
|
|
65
|
-
|
|
66
|
-
if self.vbo: self.vbo.release()
|
|
67
|
-
if self.vao: self.vao.release()
|
|
68
|
-
|
|
69
|
-
# Create the vbo and the vao from mesh data
|
|
70
|
-
self.vbo = self.ctx.buffer(batch_data)
|
|
71
|
-
self.vao = self.ctx.vertex_array(self.shader.program, [(self.vbo, self.shader.fmt, *self.shader.attributes)], skip_errors=True)
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
return True
|
|
75
|
-
|
|
76
|
-
def swap_shader(self, shader):
|
|
77
|
-
"""
|
|
78
|
-
Swap the shader without rebatching
|
|
79
|
-
"""
|
|
80
|
-
|
|
81
|
-
# Check there is actually something to swap
|
|
82
|
-
if not self.vao: return
|
|
83
|
-
|
|
84
|
-
# Release old data
|
|
85
|
-
self.vao.release()
|
|
86
|
-
|
|
87
|
-
# Make new vao with old data
|
|
88
|
-
self.program = shader.program
|
|
89
|
-
self.vao = self.ctx.vertex_array(self.program, [(self.vbo,
|
|
90
|
-
'3f 2f 3f 3f 3f 3f 4f 3f 1f',
|
|
91
|
-
*['in_position', 'in_uv', 'in_normal', 'in_tangent', 'in_bitangent', 'obj_position', 'obj_rotation', 'obj_scale', 'obj_material'])],
|
|
92
|
-
skip_errors=True)
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
def __repr__(self) -> str:
|
|
96
|
-
return f'<Basilisk Batch | {self.chunk.chunk_key}, {self.vbo.size / 1024 / 1024} mb>'
|
|
97
|
-
|
|
98
|
-
def __del__(self) -> None:
|
|
99
|
-
"""
|
|
100
|
-
Deallocates the mesh vbo and vao
|
|
101
|
-
"""
|
|
102
|
-
|
|
103
|
-
if self.vbo: self.vbo.release()
|
|
1
|
+
import numpy as np
|
|
2
|
+
import moderngl as mgl
|
|
3
|
+
from .shader import Shader
|
|
4
|
+
|
|
5
|
+
class Batch():
|
|
6
|
+
chunk: ...
|
|
7
|
+
"""Reference to the parent chunk of the batch"""
|
|
8
|
+
ctx: mgl.Context
|
|
9
|
+
"""Reference to the context of the parent engine"""
|
|
10
|
+
shader: Shader
|
|
11
|
+
"""Reference to the bsk.Shader used by batches"""
|
|
12
|
+
vao: mgl.VertexArray
|
|
13
|
+
"""The vertex array of the batch. Used for rendering"""
|
|
14
|
+
vbo: mgl.Buffer
|
|
15
|
+
"""Buffer containing all the batch data"""
|
|
16
|
+
|
|
17
|
+
def __init__(self, chunk) -> None:
|
|
18
|
+
"""
|
|
19
|
+
Basilik batch object
|
|
20
|
+
Contains all the data for a chunk batch to be stored and rendered
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
# Back references
|
|
24
|
+
self.chunk = chunk
|
|
25
|
+
self.ctx = chunk.chunk_handler.engine.ctx
|
|
26
|
+
self.shader = self.chunk.get_shader()
|
|
27
|
+
|
|
28
|
+
# Set intial values
|
|
29
|
+
self.vbo = None
|
|
30
|
+
self.vao = None
|
|
31
|
+
|
|
32
|
+
def batch(self) -> bool:
|
|
33
|
+
"""
|
|
34
|
+
Batches all the node meshes in the chunks bounds.
|
|
35
|
+
Returns True if batch was successful.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
self.shader = self.chunk.get_shader()
|
|
39
|
+
|
|
40
|
+
# Empty list to contain all vertex data of models in the chunk
|
|
41
|
+
batch_data = []
|
|
42
|
+
|
|
43
|
+
# Loop through each node in the chunk, adding the nodes's mesh to batch_data
|
|
44
|
+
index = 0
|
|
45
|
+
for node in self.chunk.nodes:
|
|
46
|
+
# Check that the node should be used
|
|
47
|
+
if not node.mesh: continue
|
|
48
|
+
if node.static != self.chunk.static: continue
|
|
49
|
+
|
|
50
|
+
# Get the data from the node
|
|
51
|
+
node_data = node.get_data()
|
|
52
|
+
# Update the index
|
|
53
|
+
node.data_index = index
|
|
54
|
+
index += len(node_data)
|
|
55
|
+
# Add to the chunk mesh
|
|
56
|
+
batch_data.append(node_data)
|
|
57
|
+
|
|
58
|
+
# Combine all meshes into a single array
|
|
59
|
+
if len(batch_data) > 1: batch_data = np.vstack(batch_data)
|
|
60
|
+
else: batch_data = np.array(batch_data, dtype='f4')
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
# If there are no verticies, delete the chunk
|
|
64
|
+
if len(batch_data) == 0: return False
|
|
65
|
+
|
|
66
|
+
if self.vbo: self.vbo.release()
|
|
67
|
+
if self.vao: self.vao.release()
|
|
68
|
+
|
|
69
|
+
# Create the vbo and the vao from mesh data
|
|
70
|
+
self.vbo = self.ctx.buffer(batch_data)
|
|
71
|
+
self.vao = self.ctx.vertex_array(self.shader.program, [(self.vbo, self.shader.fmt, *self.shader.attributes)], skip_errors=True)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
return True
|
|
75
|
+
|
|
76
|
+
def swap_shader(self, shader):
|
|
77
|
+
"""
|
|
78
|
+
Swap the shader without rebatching
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
# Check there is actually something to swap
|
|
82
|
+
if not self.vao: return
|
|
83
|
+
|
|
84
|
+
# Release old data
|
|
85
|
+
self.vao.release()
|
|
86
|
+
|
|
87
|
+
# Make new vao with old data
|
|
88
|
+
self.program = shader.program
|
|
89
|
+
self.vao = self.ctx.vertex_array(self.program, [(self.vbo,
|
|
90
|
+
'3f 2f 3f 3f 3f 3f 4f 3f 1f',
|
|
91
|
+
*['in_position', 'in_uv', 'in_normal', 'in_tangent', 'in_bitangent', 'obj_position', 'obj_rotation', 'obj_scale', 'obj_material'])],
|
|
92
|
+
skip_errors=True)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def __repr__(self) -> str:
|
|
96
|
+
return f'<Basilisk Batch | {self.chunk.chunk_key}, {self.vbo.size / 1024 / 1024} mb>'
|
|
97
|
+
|
|
98
|
+
def __del__(self) -> None:
|
|
99
|
+
"""
|
|
100
|
+
Deallocates the mesh vbo and vao
|
|
101
|
+
"""
|
|
102
|
+
|
|
103
|
+
if self.vbo: self.vbo.release()
|
|
104
104
|
if self.vao: self.vao.release()
|