Compare commits
2 Commits
5f61c04912
...
1fe051d275
| Author | SHA1 | Date | |
|---|---|---|---|
| 1fe051d275 | |||
| d5a21cb3ee |
@@ -79,9 +79,6 @@ Entity :: struct {
|
|||||||
animator: Animator; @DontSerialize
|
animator: Animator; @DontSerialize
|
||||||
|
|
||||||
// Physics
|
// Physics
|
||||||
body : Physics_Body;
|
|
||||||
collider : Collider;
|
|
||||||
|
|
||||||
physx_handle: PhysX_Handle;
|
physx_handle: PhysX_Handle;
|
||||||
velocity: Vector3;
|
velocity: Vector3;
|
||||||
|
|
||||||
@@ -209,10 +206,6 @@ entity_should_be_rendered :: (e: *Entity) -> bool {
|
|||||||
destroy_entity :: (e: *Entity) {
|
destroy_entity :: (e: *Entity) {
|
||||||
call_correct_deinit_entity(e);
|
call_correct_deinit_entity(e);
|
||||||
|
|
||||||
if e.collider.mesh.vertices.data != null {
|
|
||||||
array_free(e.collider.mesh.vertices);
|
|
||||||
}
|
|
||||||
|
|
||||||
for 0..e.renderable.num_nodes-1 {
|
for 0..e.renderable.num_nodes-1 {
|
||||||
node_data := e.renderable.nodes[it];
|
node_data := e.renderable.nodes[it];
|
||||||
|
|
||||||
|
|||||||
@@ -7,11 +7,13 @@ Mesh_Entity :: struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init_entity :: (e: *Mesh_Entity) {
|
init_entity :: (e: *Mesh_Entity) {
|
||||||
|
log_error("Missing collision on Mesh Entities\n");
|
||||||
|
assert(false);
|
||||||
if e.model_path.count > 0 {
|
if e.model_path.count > 0 {
|
||||||
load_model_into_entity(e, get_or_load_model(e.model_path));
|
load_model_into_entity(e, get_or_load_model(e.model_path));
|
||||||
e.flags |= .COLLISION | .STATIC;
|
//e.flags |= .COLLISION | .STATIC;
|
||||||
e.collider.type = .MESH;
|
//e.collider.type = .MESH;
|
||||||
e.collider.bake_mode = .FULL_MESH;
|
//e.collider.bake_mode = .FULL_MESH;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -76,8 +76,6 @@ load_scene :: (name: string, make_current: bool = true) -> *Scene {
|
|||||||
next_entity_id = cast(Entity_Id)(highest + 1);
|
next_entity_id = cast(Entity_Id)(highest + 1);
|
||||||
|
|
||||||
update_transforms(scene);
|
update_transforms(scene);
|
||||||
calculate_aabbs(scene);
|
|
||||||
make_sure_nothing_collides(scene);
|
|
||||||
|
|
||||||
if engine.procs.on_scene_loaded != null {
|
if engine.procs.on_scene_loaded != null {
|
||||||
engine.procs.on_scene_loaded(scene, engine.mode);
|
engine.procs.on_scene_loaded(scene, engine.mode);
|
||||||
|
|||||||
@@ -157,8 +157,11 @@ coven_run :: (game_update_proc: (float), game_editor_update_proc: (float), game_
|
|||||||
|
|
||||||
if engine.current_scene != null && !engine.paused {
|
if engine.current_scene != null && !engine.paused {
|
||||||
update_animators(clamped_dt);
|
update_animators(clamped_dt);
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
update_mesh_colliders(engine.current_scene);
|
update_mesh_colliders(engine.current_scene);
|
||||||
update_physics(engine.current_scene, clamped_dt);
|
update_physics(engine.current_scene, clamped_dt);
|
||||||
|
>>>>>>> 5f61c0491241b1f62266e0d521c2e315b2c5b8e3
|
||||||
|
|
||||||
pre_physx_sync(engine.current_scene);
|
pre_physx_sync(engine.current_scene);
|
||||||
tick_physx(*engine.current_scene.physx_scene, clamped_dt);
|
tick_physx(*engine.current_scene.physx_scene, clamped_dt);
|
||||||
@@ -170,7 +173,7 @@ coven_run :: (game_update_proc: (float), game_editor_update_proc: (float), game_
|
|||||||
game_editor_update_proc(clamped_dt);
|
game_editor_update_proc(clamped_dt);
|
||||||
|
|
||||||
if engine.current_scene != null {
|
if engine.current_scene != null {
|
||||||
update_trigger_mesh_colliders(engine.current_scene);
|
//update_trigger_mesh_colliders(engine.current_scene);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,7 +227,6 @@ switch_engine_mode :: (to_mode: Engine_Mode) {
|
|||||||
#load "renderer/engine_buffers.jai";
|
#load "renderer/engine_buffers.jai";
|
||||||
#load "renderer/renderer.jai";
|
#load "renderer/renderer.jai";
|
||||||
#load "windowing/window.jai";
|
#load "windowing/window.jai";
|
||||||
#load "physics/physics.jai";
|
|
||||||
|
|
||||||
#load "core/mesh_entity.jai";
|
#load "core/mesh_entity.jai";
|
||||||
#load "core/string_helpers.jai";
|
#load "core/string_helpers.jai";
|
||||||
|
|||||||
@@ -1,511 +0,0 @@
|
|||||||
#load "gjk.jai";
|
|
||||||
|
|
||||||
WORLD_UP :: Vector3.{0,1,0};
|
|
||||||
GRAVITY :: -20.8;
|
|
||||||
|
|
||||||
Collider_Type :: enum {
|
|
||||||
AABB;
|
|
||||||
SPHERE;
|
|
||||||
MESH;
|
|
||||||
BOX;
|
|
||||||
}
|
|
||||||
|
|
||||||
Sphere :: struct {
|
|
||||||
radius: float;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mesh_Collider :: struct {
|
|
||||||
vertices : [..] Vector3;
|
|
||||||
is_baked: bool;
|
|
||||||
}
|
|
||||||
|
|
||||||
Trigger_Overlap :: struct {
|
|
||||||
entity: *Entity;
|
|
||||||
frame_index: u64;
|
|
||||||
}
|
|
||||||
|
|
||||||
MAX_TRIGGER_OVERLAPS :: 16;
|
|
||||||
|
|
||||||
Collision_Layers :: enum_flags {
|
|
||||||
NONE;
|
|
||||||
|
|
||||||
LAYER1;
|
|
||||||
LAYER2;
|
|
||||||
LAYER3;
|
|
||||||
LAYER4;
|
|
||||||
LAYER5;
|
|
||||||
LAYER6;
|
|
||||||
LAYER7;
|
|
||||||
LAYER8;
|
|
||||||
LAYER9;
|
|
||||||
LAYER10;
|
|
||||||
|
|
||||||
ALL :: .LAYER1 | LAYER2 | .LAYER3 | .LAYER4 | .LAYER5 | .LAYER6 | .LAYER7 | .LAYER8 | .LAYER9 | .LAYER10;
|
|
||||||
}
|
|
||||||
|
|
||||||
Collider_Bake_Mode :: enum {
|
|
||||||
AABB;
|
|
||||||
|
|
||||||
FULL_MESH;
|
|
||||||
|
|
||||||
ONLY_FACING_UP;
|
|
||||||
}
|
|
||||||
|
|
||||||
Collider :: struct {
|
|
||||||
type : Collider_Type;
|
|
||||||
|
|
||||||
bake_mode: Collider_Bake_Mode;
|
|
||||||
|
|
||||||
layer: Collision_Layers = .LAYER1;
|
|
||||||
collides_with_layers: Collision_Layers = .LAYER1;
|
|
||||||
|
|
||||||
override_aabb: bool;
|
|
||||||
render_aabb: bool;
|
|
||||||
aabb_color: Vector4 = .{0,1,0,1};
|
|
||||||
aabb: AABB;
|
|
||||||
|
|
||||||
union {
|
|
||||||
sphere: Sphere; @DontSerialize
|
|
||||||
mesh : Mesh_Collider; @DontSerialize
|
|
||||||
}
|
|
||||||
|
|
||||||
overlaps: [MAX_TRIGGER_OVERLAPS] Trigger_Overlap; @DontSerialize
|
|
||||||
num_overlaps: s64; @DontSerialize
|
|
||||||
|
|
||||||
ignore: bool; @DontSerialize
|
|
||||||
}
|
|
||||||
|
|
||||||
Physics_Body :: struct {
|
|
||||||
enabled: bool = true;
|
|
||||||
velocity: Vector3; @DontSerialize
|
|
||||||
|
|
||||||
friction : float = 0.0; @DontSerialize
|
|
||||||
bounciness : float = 0.0; @DontSerialize
|
|
||||||
linear_damping : float = 0.0; @DontSerialize
|
|
||||||
|
|
||||||
check_for_grounded: bool; @DontSerialize
|
|
||||||
grounded: bool; @DontSerialize
|
|
||||||
}
|
|
||||||
|
|
||||||
update_mesh_collider :: (e: *Entity) {
|
|
||||||
if e.collider.bake_mode == {
|
|
||||||
case .AABB; {
|
|
||||||
if e.collider.mesh.vertices.count == 0 {
|
|
||||||
array_resize(*e.collider.mesh.vertices, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
m := e.transform.model_matrix;
|
|
||||||
e.collider.mesh.vertices[0] = transform_position(e.collider.aabb.min, m);
|
|
||||||
e.collider.mesh.vertices[1] = transform_position(e.collider.aabb.max, m);
|
|
||||||
e.collider.mesh.vertices[2] = transform_position(.{e.collider.aabb.min.x, e.collider.aabb.min.y, e.collider.aabb.max.z}, m);
|
|
||||||
e.collider.mesh.vertices[3] = transform_position(.{e.collider.aabb.max.x, e.collider.aabb.min.y, e.collider.aabb.max.z}, m);
|
|
||||||
e.collider.mesh.vertices[4] = transform_position(.{e.collider.aabb.max.x, e.collider.aabb.min.y, e.collider.aabb.min.z}, m);
|
|
||||||
e.collider.mesh.vertices[5] = transform_position(.{e.collider.aabb.min.x, e.collider.aabb.max.y, e.collider.aabb.max.z}, m);
|
|
||||||
e.collider.mesh.vertices[6] = transform_position(.{e.collider.aabb.max.x, e.collider.aabb.max.y, e.collider.aabb.min.z}, m);
|
|
||||||
e.collider.mesh.vertices[7] = transform_position(.{e.collider.aabb.min.x, e.collider.aabb.max.y, e.collider.aabb.min.z}, m);
|
|
||||||
}
|
|
||||||
case .FULL_MESH; {
|
|
||||||
//update_entity_transform(e);
|
|
||||||
|
|
||||||
model := get_model_by_handle(e.renderable.model);
|
|
||||||
if model {
|
|
||||||
for i: 0..e.renderable.num_nodes-1 {
|
|
||||||
render_node := e.renderable.nodes[i];
|
|
||||||
model_node := model.nodes[i];
|
|
||||||
|
|
||||||
for mesh_handle: model_node.meshes {
|
|
||||||
mesh := parray_get(*engine.renderer.meshes, mesh_handle);
|
|
||||||
|
|
||||||
for p: mesh.positions {
|
|
||||||
position := transform_position(p, render_node.transform.world_matrix);
|
|
||||||
array_add(*e.collider.mesh.vertices, position);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
e.collider.mesh.is_baked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
update_trigger_mesh_colliders :: (scene: *Scene) {
|
|
||||||
for e: scene.entities {
|
|
||||||
if e.flags & .TRIGGER {
|
|
||||||
if e.collider.type == .MESH {
|
|
||||||
update_mesh_collider(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
update_mesh_colliders :: (scene: *Scene) {
|
|
||||||
for e: scene.entities {
|
|
||||||
if e.flags & .COLLISION {
|
|
||||||
if e.collider.type == .MESH {
|
|
||||||
if e.flags & .STATIC && e.collider.mesh.is_baked continue;
|
|
||||||
|
|
||||||
update_mesh_collider(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
make_sure_entity_does_not_collide :: (e: *Entity, scene: *Scene) {
|
|
||||||
if e.flags & .PHYSICS {
|
|
||||||
aabb := e.collider.aabb;
|
|
||||||
aabb.min += e.transform.position;
|
|
||||||
aabb.max += e.transform.position;
|
|
||||||
|
|
||||||
for other_e: scene.entities {
|
|
||||||
if e == other_e continue;
|
|
||||||
|
|
||||||
if other_e.flags & .COLLISION {
|
|
||||||
other_aabb := other_e.collider.aabb;
|
|
||||||
other_aabb.min += other_e.transform.position;
|
|
||||||
other_aabb.max += other_e.transform.position;
|
|
||||||
if aabb_vs_aabb(aabb, other_aabb) {
|
|
||||||
offset := resolve_aabb_vs_aabb(aabb, other_aabb);
|
|
||||||
set_position(*e.transform, e.transform.position + offset * 1.0001);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
make_sure_nothing_collides :: (scene: *Scene) {
|
|
||||||
for e: scene.entities {
|
|
||||||
make_sure_entity_does_not_collide(e, scene);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
update_gravity :: (scene: *Scene, dt: float) {
|
|
||||||
for e: scene.entities {
|
|
||||||
if !e.enabled continue;
|
|
||||||
if !e.body.enabled continue;
|
|
||||||
|
|
||||||
if e.flags & .PHYSICS {
|
|
||||||
#if NETWORKING { if e.is_proxy continue; }
|
|
||||||
|
|
||||||
if e.collider.ignore continue;
|
|
||||||
e.body.velocity.y += GRAVITY * dt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
update_positions :: (scene: *Scene, dt: float) {
|
|
||||||
for e: scene.entities {
|
|
||||||
if !e.enabled continue;
|
|
||||||
if !e.body.enabled continue;
|
|
||||||
|
|
||||||
#if NETWORKING { if e.is_proxy continue; }
|
|
||||||
|
|
||||||
if e.collider.ignore continue;
|
|
||||||
|
|
||||||
if e.flags & .PHYSICS {
|
|
||||||
delta := e.body.velocity * dt;
|
|
||||||
set_position(*e.transform, e.transform.position + delta);
|
|
||||||
|
|
||||||
// @Speed: Only do this, if we actually moved
|
|
||||||
m := e.transform.model_matrix;
|
|
||||||
if e.collider.mesh.vertices.count < 8 continue;
|
|
||||||
|
|
||||||
e.collider.mesh.vertices[0] = transform_position(e.collider.aabb.min, m);
|
|
||||||
e.collider.mesh.vertices[1] = transform_position(e.collider.aabb.max, m);
|
|
||||||
e.collider.mesh.vertices[2] = transform_position(.{e.collider.aabb.min.x, e.collider.aabb.min.y, e.collider.aabb.max.z}, m);
|
|
||||||
e.collider.mesh.vertices[3] = transform_position(.{e.collider.aabb.max.x, e.collider.aabb.min.y, e.collider.aabb.max.z}, m);
|
|
||||||
e.collider.mesh.vertices[4] = transform_position(.{e.collider.aabb.max.x, e.collider.aabb.min.y, e.collider.aabb.min.z}, m);
|
|
||||||
e.collider.mesh.vertices[5] = transform_position(.{e.collider.aabb.min.x, e.collider.aabb.max.y, e.collider.aabb.max.z}, m);
|
|
||||||
e.collider.mesh.vertices[6] = transform_position(.{e.collider.aabb.max.x, e.collider.aabb.max.y, e.collider.aabb.min.z}, m);
|
|
||||||
e.collider.mesh.vertices[7] = transform_position(.{e.collider.aabb.min.x, e.collider.aabb.max.y, e.collider.aabb.min.z}, m);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
add_trigger_overlap_if_new :: (triggered_entity: *Entity, triggered_by_entity: *Entity) {
|
|
||||||
for 0..triggered_entity.collider.num_overlaps-1 {
|
|
||||||
overlap := *triggered_entity.collider.overlaps[it];
|
|
||||||
if overlap.entity == triggered_by_entity {
|
|
||||||
overlap.frame_index = frame_index;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if engine.procs.on_trigger_enter != null {
|
|
||||||
engine.procs.on_trigger_enter(triggered_entity, triggered_by_entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
triggered_entity.collider.overlaps[triggered_entity.collider.num_overlaps] = .{ triggered_by_entity, frame_index };
|
|
||||||
triggered_entity.collider.num_overlaps += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
can_collide :: (e: *Entity, other: *Entity) -> bool {
|
|
||||||
return xx (e.collider.collides_with_layers & other.collider.layer);
|
|
||||||
}
|
|
||||||
|
|
||||||
physics_step :: (scene: *Scene, timestep: float) {
|
|
||||||
update_gravity(scene, timestep);
|
|
||||||
update_positions(scene, timestep);
|
|
||||||
|
|
||||||
for e: scene.entities {
|
|
||||||
if !e.enabled continue;
|
|
||||||
if !e.body.enabled continue;
|
|
||||||
#if NETWORKING { if e.is_proxy continue;}
|
|
||||||
if e.collider.ignore continue;
|
|
||||||
|
|
||||||
if e.flags & .PHYSICS {
|
|
||||||
if e.body.check_for_grounded {
|
|
||||||
e.body.grounded = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for other_e: scene.entities {
|
|
||||||
if e == other_e continue;
|
|
||||||
if other_e.collider.ignore continue;
|
|
||||||
if !other_e.enabled continue;
|
|
||||||
if !other_e.body.enabled continue;
|
|
||||||
if !can_collide(e, other_e) continue;
|
|
||||||
|
|
||||||
if other_e.flags & .COLLISION {
|
|
||||||
if other_e.collider.type == .AABB {
|
|
||||||
success :, inv_matrix := inverse(other_e.transform.model_matrix);
|
|
||||||
aabb := other_e.collider.aabb;
|
|
||||||
if point_inside_aabb(aabb, transform_position(e.transform.position, inv_matrix)) {
|
|
||||||
add_trigger_overlap_if_new(other_e, e);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
point := gjk(e.collider, other_e.collider);
|
|
||||||
|
|
||||||
if point.has_collision {
|
|
||||||
if other_e.flags & .TRIGGER {
|
|
||||||
// TRIGGER CALLBACK
|
|
||||||
add_trigger_overlap_if_new(other_e, e);
|
|
||||||
} else {
|
|
||||||
n := -point.normal;
|
|
||||||
speed_along_normal := dot(e.body.velocity, n);
|
|
||||||
|
|
||||||
restitution := e.body.bounciness;
|
|
||||||
impulse := n * (-(1.0 + restitution) * speed_along_normal);
|
|
||||||
e.body.velocity += impulse;
|
|
||||||
|
|
||||||
percent := 0.1;
|
|
||||||
slop := 0.005;
|
|
||||||
correction := n * max(point.penetration_depth - slop, 0.0) / (1.0 / percent);
|
|
||||||
set_position(*e.transform, e.transform.position + correction);
|
|
||||||
|
|
||||||
if e.body.check_for_grounded {
|
|
||||||
e.body.grounded = dot(n, WORLD_UP) > 0.6; // @Incomplete: Add allowed angle variable at some point?
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Incomplete: This shouldn't be in here
|
|
||||||
//if e.type == Diamond && length(impulse) > 2.0 {
|
|
||||||
// play_audio_event(sfx_diamond_hit);
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
update_physics :: (scene: *Scene, dt: float) {
|
|
||||||
for scene.entities {
|
|
||||||
if it.collider.type == .MESH {
|
|
||||||
if !it.collider.mesh.is_baked {
|
|
||||||
update_mesh_collider(it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
iterations := 4;
|
|
||||||
step_time := dt / cast(float)iterations;
|
|
||||||
for 0..iterations-1 {
|
|
||||||
physics_step(scene, step_time);
|
|
||||||
|
|
||||||
for e: scene.entities {
|
|
||||||
if e.flags & .PHYSICS {
|
|
||||||
//if e.body.friction > 0.0 {
|
|
||||||
// e.body.velocity *= 1.0 - (e.body.friction / cast(float)iterations);
|
|
||||||
//}
|
|
||||||
|
|
||||||
e.body.velocity *= (1.0 - e.body.linear_damping / cast(float)iterations);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for e: scene.entities {
|
|
||||||
index := 0;
|
|
||||||
while index < e.collider.num_overlaps {
|
|
||||||
defer index += 1;
|
|
||||||
|
|
||||||
if e.collider.overlaps[index].frame_index < frame_index {
|
|
||||||
if engine.procs.on_trigger_exit != null {
|
|
||||||
engine.procs.on_trigger_exit(e, e.collider.overlaps[index].entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
if e.collider.num_overlaps > 1 {
|
|
||||||
e.collider.overlaps[index] = e.collider.overlaps[e.collider.num_overlaps-1];
|
|
||||||
}
|
|
||||||
|
|
||||||
e.collider.num_overlaps -= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DISCRETE
|
|
||||||
aabb_vs_aabb :: (box1: AABB, box2: AABB) -> bool {
|
|
||||||
// Check for no overlap along any axis
|
|
||||||
if box1.max.x < box2.min.x || box1.min.x > box2.max.x return false;
|
|
||||||
if box1.max.y < box2.min.y || box1.min.y > box2.max.y return false;
|
|
||||||
if box1.max.z < box2.min.z || box1.min.z > box2.max.z return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve_aabb_vs_aabb :: (moving_box: AABB, static_box: AABB) -> Vector3 {
|
|
||||||
overlap_x := min(moving_box.max.x, static_box.max.x) - max(moving_box.min.x, static_box.min.x);
|
|
||||||
overlap_y := min(moving_box.max.y, static_box.max.y) - max(moving_box.min.y, static_box.min.y);
|
|
||||||
overlap_z := min(moving_box.max.z, static_box.max.z) - max(moving_box.min.z, static_box.min.z);
|
|
||||||
|
|
||||||
offset : Vector3;
|
|
||||||
|
|
||||||
// Resolve overlap on each axis
|
|
||||||
if (overlap_x > 0 && overlap_y > 0 && overlap_z > 0) {
|
|
||||||
// Determine which axis has the smallest overlap
|
|
||||||
if (overlap_x <= overlap_y && overlap_x <= overlap_z) {
|
|
||||||
// Resolve overlap on X-axis
|
|
||||||
if (moving_box.max.x < static_box.max.x) {
|
|
||||||
offset.x -= overlap_x;
|
|
||||||
} else {
|
|
||||||
offset.x += overlap_x;
|
|
||||||
}
|
|
||||||
} else if (overlap_y <= overlap_x && overlap_y <= overlap_z) {
|
|
||||||
// Resolve overlap on Y-axis
|
|
||||||
if (moving_box.max.y < static_box.max.y) {
|
|
||||||
offset.y -= overlap_y;
|
|
||||||
} else {
|
|
||||||
offset.y += overlap_y;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Resolve overlap on Z-axis
|
|
||||||
if (moving_box.max.z < static_box.max.z) {
|
|
||||||
offset.z -= overlap_z;
|
|
||||||
} else {
|
|
||||||
offset.z += overlap_z;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
// SWEPT
|
|
||||||
// Check for collision between two AABBs over a specified time interval
|
|
||||||
swept_aabb_collision :: (box1: AABB, box2: AABB, delta: Vector3) -> bool, t_enter: float, t_exit: float {
|
|
||||||
d_inv := 1.0 / delta;
|
|
||||||
|
|
||||||
tx_enter, tx_exit, ty_enter, ty_exit, tz_enter, tz_exit : float;
|
|
||||||
|
|
||||||
if (delta.x >= 0) {
|
|
||||||
tx_enter = (box2.min.x - box1.max.x) * d_inv.x;
|
|
||||||
tx_exit = (box2.max.x - box1.min.x) * d_inv.x;
|
|
||||||
} else {
|
|
||||||
tx_enter = (box2.max.x - box1.min.x) * d_inv.x;
|
|
||||||
tx_exit = (box2.min.x - box1.max.x) * d_inv.x;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (delta.y >= 0) {
|
|
||||||
ty_enter = (box2.min.y - box1.max.y) * d_inv.y;
|
|
||||||
ty_exit = (box2.max.y - box1.min.y) * d_inv.y;
|
|
||||||
} else {
|
|
||||||
ty_enter = (box2.max.y - box1.min.y) * d_inv.y;
|
|
||||||
ty_exit = (box2.min.y - box1.max.y) * d_inv.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (delta.z >= 0) {
|
|
||||||
tz_enter = (box2.min.z - box1.max.z) * d_inv.z;
|
|
||||||
tz_exit = (box2.max.z - box1.min.z) * d_inv.z;
|
|
||||||
} else {
|
|
||||||
tz_enter = (box2.max.z - box1.min.z) * d_inv.z;
|
|
||||||
tz_exit = (box2.min.z - box1.max.z) * d_inv.z;
|
|
||||||
}
|
|
||||||
|
|
||||||
t_enter := max(max(tx_enter, ty_enter), tz_enter);
|
|
||||||
t_exit := min(min(tx_exit, ty_exit), tz_exit);
|
|
||||||
|
|
||||||
return t_enter <= t_exit && t_exit >= 0 && t_enter <= 1, t_enter, t_exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
calculate_aabbs :: (scene: *Scene) {
|
|
||||||
for e: scene.entities {
|
|
||||||
if e.flags & .COLLISION && e.flags & .RENDERABLE {
|
|
||||||
if e.collider.override_aabb continue;
|
|
||||||
if e.renderable.model == 0 continue;
|
|
||||||
|
|
||||||
aabb : AABB;
|
|
||||||
model := get_model_by_handle(e.renderable.model);
|
|
||||||
|
|
||||||
for n : model.nodes {
|
|
||||||
if n.parent == 0 {
|
|
||||||
bake_aabb(*aabb, Matrix4_Identity, e, n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
e.collider.aabb = aabb;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bake_aabb :: (aabb: *AABB, parent_matrix: Matrix4, e: *Entity, n: Node) {
|
|
||||||
update_matrix(*n.transform);
|
|
||||||
node_matrix := parent_matrix * n.transform.model_matrix;
|
|
||||||
|
|
||||||
for handle : n.meshes {
|
|
||||||
index := 0;
|
|
||||||
m := parray_get(*engine.renderer.meshes, handle);
|
|
||||||
if m.indices.count > 0 {
|
|
||||||
while index < m.indices.count {
|
|
||||||
i1 := m.indices[index];
|
|
||||||
i2 := m.indices[index + 1];
|
|
||||||
i3 := m.indices[index + 2];
|
|
||||||
p0 := to_v3(node_matrix * to_v4(m.positions[i1]));
|
|
||||||
p1 := to_v3(node_matrix * to_v4(m.positions[i2]));
|
|
||||||
p2 := to_v3(node_matrix * to_v4(m.positions[i3]));
|
|
||||||
|
|
||||||
apply_min_max(*aabb.min, *aabb.max, p0);
|
|
||||||
apply_min_max(*aabb.min, *aabb.max, p1);
|
|
||||||
apply_min_max(*aabb.min, *aabb.max, p2);
|
|
||||||
|
|
||||||
index += 3;
|
|
||||||
}
|
|
||||||
// assert("Meshes with indices currently for aabb collision baking." && false);
|
|
||||||
} else {
|
|
||||||
while index < m.positions.count - 1 {
|
|
||||||
p0 := to_v3(node_matrix * to_v4(m.positions[index]));
|
|
||||||
p1 := to_v3(node_matrix * to_v4(m.positions[index + 1]));
|
|
||||||
p2 := to_v3(node_matrix * to_v4(m.positions[index + 2]));
|
|
||||||
|
|
||||||
apply_min_max(*aabb.min, *aabb.max, p0);
|
|
||||||
apply_min_max(*aabb.min, *aabb.max, p1);
|
|
||||||
apply_min_max(*aabb.min, *aabb.max, p2);
|
|
||||||
|
|
||||||
index += 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
model := get_model_by_handle(e.renderable.model);
|
|
||||||
|
|
||||||
for n.children {
|
|
||||||
child := *model.nodes[it - 1];
|
|
||||||
bake_aabb(aabb, node_matrix, e, child);
|
|
||||||
}
|
|
||||||
|
|
||||||
if abs(aabb.min.y - aabb.max.y) < 0.00001 {
|
|
||||||
aabb.min.y -= 0.001;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,8 +1,17 @@
|
|||||||
PHYSX_TEST :: false;
|
PHYSX_TEST :: false; PHYSX_DEFAULT_SHAPE_FLAGS :: cast(u8)(PhysX.PxShapeFlags.Visualization | PhysX.PxShapeFlags.SceneQueryShape | PhysX.PxShapeFlags.SimulationShape);
|
||||||
PHYSX_DEFAULT_SHAPE_FLAGS :: cast(u8)(PhysX.PxShapeFlags.Visualization | PhysX.PxShapeFlags.SceneQueryShape | PhysX.PxShapeFlags.SimulationShape);
|
|
||||||
|
|
||||||
PhysX_Handle :: #type, distinct u32;
|
PhysX_Handle :: #type, distinct u32;
|
||||||
|
|
||||||
|
PhysX_Actor_Type :: enum {
|
||||||
|
STATIC;
|
||||||
|
DYNAMIC;
|
||||||
|
}
|
||||||
|
|
||||||
PhysX_Actor :: struct {
|
PhysX_Actor :: struct {
|
||||||
|
type : PhysX_Actor_Type;
|
||||||
|
|
||||||
|
sync_rotation_from_physx: bool = true;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
static: *PhysX.PxRigidStatic;
|
static: *PhysX.PxRigidStatic;
|
||||||
dynamic: *PhysX.PxRigidDynamic;
|
dynamic: *PhysX.PxRigidDynamic;
|
||||||
@@ -30,11 +39,11 @@ init_physx :: () {
|
|||||||
|
|
||||||
tolerance_scale : PhysX.PxTolerancesScale;
|
tolerance_scale : PhysX.PxTolerancesScale;
|
||||||
tolerance_scale.length = 1;
|
tolerance_scale.length = 1;
|
||||||
tolerance_scale.speed = 981;
|
tolerance_scale.speed = 10;
|
||||||
physics = PhysX.PxCreatePhysics(PhysX.PX_PHYSICS_VERSION, foundation, *tolerance_scale, true, pvd, null);
|
physics = PhysX.PxCreatePhysics(PhysX.PX_PHYSICS_VERSION, foundation, *tolerance_scale, true, pvd, null);
|
||||||
|
|
||||||
dispatcher = PhysX.PxDefaultCpuDispatcherCreate(2);
|
dispatcher = PhysX.PxDefaultCpuDispatcherCreate(2);
|
||||||
material = PhysX.PxPhysics_createMaterial(physics, 0.5, 0.5, 0.6);
|
material = PhysX.PxPhysics_createMaterial(physics, 0.0, 0.0, 0.6);
|
||||||
}
|
}
|
||||||
|
|
||||||
tick_physx :: (scene: *PhysX_Scene, dt: float) {
|
tick_physx :: (scene: *PhysX_Scene, dt: float) {
|
||||||
@@ -63,33 +72,6 @@ init_physx_scene :: (game_scene: *Scene) {
|
|||||||
PhysX.PxPvdSceneClient_setScenePvdFlag(pvd_client, xx PhysX.PxPvdSceneFlag.TRANSMIT_SCENEQUERIES, true);
|
PhysX.PxPvdSceneClient_setScenePvdFlag(pvd_client, xx PhysX.PxPvdSceneFlag.TRANSMIT_SCENEQUERIES, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
plane_point := Vector3.{0,10.5,0};
|
|
||||||
plane_normal := Vector3.{0,1,0};
|
|
||||||
plane := PhysX.PxPlane_new(*plane_point, *plane_normal);
|
|
||||||
ground_plane := PhysX.PxCreatePlane(physics, *plane, material);
|
|
||||||
PhysX.PxScene_addActor(scene, ground_plane, null);
|
|
||||||
}
|
|
||||||
#if PHYSX_TEST {
|
|
||||||
|
|
||||||
stack_z := 0.0;
|
|
||||||
for i: 0..4 {
|
|
||||||
stack_pos := Vector3.{0,10,stack_z};
|
|
||||||
stack_z -= 10.0;
|
|
||||||
create_stack(scene, PhysX.PxTransform_new(*stack_pos), 10, 2.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
pos := Vector3.{0,20,100};
|
|
||||||
geo := PhysX.PxSphereGeometry_new(5);
|
|
||||||
vel := Vector3.{0,-25,-100};
|
|
||||||
|
|
||||||
ball := create_dynamic(scene, PhysX.PxTransform_new(*pos), *geo, vel);
|
|
||||||
density := 1000.0;
|
|
||||||
PhysX.PxRigidBodyExt_updateMassAndInertia(ball, density, null, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
physx_scene : PhysX_Scene;
|
physx_scene : PhysX_Scene;
|
||||||
physx_scene.scene = scene;
|
physx_scene.scene = scene;
|
||||||
physx_scene.actors.data.allocator = game_scene.allocator;
|
physx_scene.actors.data.allocator = game_scene.allocator;
|
||||||
@@ -107,7 +89,9 @@ pre_physx_sync :: (game_scene: *Scene) {
|
|||||||
if it.physx_handle != 0 {
|
if it.physx_handle != 0 {
|
||||||
// @Incomplete: Update the transform!
|
// @Incomplete: Update the transform!
|
||||||
physx_actor := parray_get(*game_scene.physx_scene.actors, it.physx_handle);
|
physx_actor := parray_get(*game_scene.physx_scene.actors, it.physx_handle);
|
||||||
PhysX.PxRigidDynamic_setLinearVelocity(physx_actor.dynamic, *it.velocity, true);
|
if physx_actor.type == .DYNAMIC {
|
||||||
|
PhysX.PxRigidDynamic_setLinearVelocity(physx_actor.dynamic, *it.velocity, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,23 +100,40 @@ post_physx_sync :: (game_scene: *Scene) {
|
|||||||
for game_scene.entities {
|
for game_scene.entities {
|
||||||
if it.physx_handle != 0 {
|
if it.physx_handle != 0 {
|
||||||
physx_actor := parray_get(*game_scene.physx_scene.actors, it.physx_handle);
|
physx_actor := parray_get(*game_scene.physx_scene.actors, it.physx_handle);
|
||||||
vel := PhysX.PxRigidDynamic_getLinearVelocity(physx_actor.dynamic);
|
if physx_actor.type == .DYNAMIC {
|
||||||
transform := PhysX.PxRigidActor_getGlobalPose(physx_actor.dynamic);
|
vel := PhysX.PxRigidDynamic_getLinearVelocity(physx_actor.dynamic);
|
||||||
it.velocity = vel;
|
it.velocity = vel;
|
||||||
set_position_rotation(it, transform.p, transform.q);
|
|
||||||
|
transform := PhysX.PxRigidActor_getGlobalPose(physx_actor.dynamic);
|
||||||
|
|
||||||
|
if physx_actor.sync_rotation_from_physx {
|
||||||
|
set_position_rotation(it, transform.p, transform.q);
|
||||||
|
} else {
|
||||||
|
set_position(it, transform.p);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
add_physx_capsule :: (entity: *Entity, half_height: float, radius: float) -> PhysX_Handle {
|
add_physx_capsule :: (entity: *Entity, half_height: float, radius: float) -> PhysX_Handle {
|
||||||
geo := PhysX.PxCapsuleGeometry_new(radius, half_height);
|
geo := PhysX.PxCapsuleGeometry_new(radius, half_height-radius);
|
||||||
transform := PhysX.PxTransform_new(*entity.transform.position);
|
|
||||||
|
angle := PI * 0.5;
|
||||||
|
half_angle := angle * 0.5;
|
||||||
|
|
||||||
|
sin_half := sin(half_angle);
|
||||||
|
cos_half := cos(half_angle);
|
||||||
|
|
||||||
|
rotation := Quaternion.{0, 0, sin(-PI * 0.25), cos(-PI * 0.25)};
|
||||||
|
|
||||||
|
transform := PhysX.PxTransform_new(*entity.transform.position, *rotation);
|
||||||
actor := PhysX.PxPhysics_createRigidDynamic(physics, *transform);
|
actor := PhysX.PxPhysics_createRigidDynamic(physics, *transform);
|
||||||
PhysX.PxRigidDynamic_setRigidDynamicLockFlag(actor, xx PhysX.PxRigidDynamicLockFlags.LockAngularX, true);
|
PhysX.PxRigidDynamic_setRigidDynamicLockFlag(actor, xx PhysX.PxRigidDynamicLockFlags.LockAngularX, true);
|
||||||
PhysX.PxRigidDynamic_setRigidDynamicLockFlag(actor, xx PhysX.PxRigidDynamicLockFlags.LockAngularY, true);
|
PhysX.PxRigidDynamic_setRigidDynamicLockFlag(actor, xx PhysX.PxRigidDynamicLockFlags.LockAngularY, true);
|
||||||
PhysX.PxRigidDynamic_setRigidDynamicLockFlag(actor, xx PhysX.PxRigidDynamicLockFlags.LockAngularZ, true);
|
PhysX.PxRigidDynamic_setRigidDynamicLockFlag(actor, xx PhysX.PxRigidDynamicLockFlags.LockAngularZ, true);
|
||||||
|
|
||||||
material := PhysX.PxPhysics_createMaterial(physics, 0.5, 0.5, 0.0);
|
material := PhysX.PxPhysics_createMaterial(physics, 0.0, 0.0, 0.0);
|
||||||
|
|
||||||
PhysX.PxMaterial_setRestitutionCombineMode(material,1); // Turn off restitution no matter the other material
|
PhysX.PxMaterial_setRestitutionCombineMode(material,1); // Turn off restitution no matter the other material
|
||||||
|
|
||||||
@@ -140,7 +141,7 @@ add_physx_capsule :: (entity: *Entity, half_height: float, radius: float) -> Phy
|
|||||||
PhysX.PxRigidActor_attachShape(actor, shape);
|
PhysX.PxRigidActor_attachShape(actor, shape);
|
||||||
|
|
||||||
|
|
||||||
PhysX.PxRigidBodyExt_updateMassAndInertia(actor, 10, null, false);
|
PhysX.PxRigidBodyExt_updateMassAndInertia(actor, 0.1, null, false);
|
||||||
PhysX.PxScene_addActor(entity.scene.physx_scene.scene, actor, null);
|
PhysX.PxScene_addActor(entity.scene.physx_scene.scene, actor, null);
|
||||||
|
|
||||||
PhysX.PxShape_release(shape);
|
PhysX.PxShape_release(shape);
|
||||||
@@ -148,12 +149,33 @@ add_physx_capsule :: (entity: *Entity, half_height: float, radius: float) -> Phy
|
|||||||
//PhysX.PxMaterial_release(material);
|
//PhysX.PxMaterial_release(material);
|
||||||
|
|
||||||
physics_actor : PhysX_Actor;
|
physics_actor : PhysX_Actor;
|
||||||
|
physics_actor.type = .DYNAMIC;
|
||||||
|
physics_actor.sync_rotation_from_physx = false;
|
||||||
physics_actor.dynamic = actor;
|
physics_actor.dynamic = actor;
|
||||||
|
|
||||||
entity.physx_handle = parray_add(*entity.scene.physx_scene.actors, physics_actor);
|
entity.physx_handle = parray_add(*entity.scene.physx_scene.actors, physics_actor);
|
||||||
return entity.physx_handle;
|
return entity.physx_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
add_physx_box :: (entity: *Entity, half_extent: Vector3) -> PhysX_Handle {
|
||||||
|
shape := PhysX.PxPhysics_createShape(physics, PhysX.PxBoxGeometry_new(half_extent), material, false, PHYSX_DEFAULT_SHAPE_FLAGS);
|
||||||
|
t := PhysX.PxTransform_new(*entity.transform.position);
|
||||||
|
|
||||||
|
body := PhysX.PxPhysics_createRigidStatic(physics, *t);
|
||||||
|
PhysX.PxRigidActor_attachShape(body, shape);
|
||||||
|
PhysX.PxScene_addActor(entity.scene.physx_scene.scene, body, null);
|
||||||
|
|
||||||
|
PhysX.PxShape_release(shape);
|
||||||
|
|
||||||
|
physics_actor : PhysX_Actor;
|
||||||
|
physics_actor.type = .STATIC;
|
||||||
|
physics_actor.static = body;
|
||||||
|
|
||||||
|
entity.physx_handle = parray_add(*entity.scene.physx_scene.actors, physics_actor);
|
||||||
|
return entity.physx_handle;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
create_stack :: (scene: *PhysX.PxScene, t: PhysX.PxTransform, size: u32, half_extent: float) {
|
create_stack :: (scene: *PhysX.PxScene, t: PhysX.PxTransform, size: u32, half_extent: float) {
|
||||||
shape := PhysX.PxPhysics_createShape(physics, PhysX.PxBoxGeometry_new(half_extent, half_extent, half_extent), material, false, PHYSX_DEFAULT_SHAPE_FLAGS);
|
shape := PhysX.PxPhysics_createShape(physics, PhysX.PxBoxGeometry_new(half_extent, half_extent, half_extent), material, false, PHYSX_DEFAULT_SHAPE_FLAGS);
|
||||||
for i: 0..size-1 {
|
for i: 0..size-1 {
|
||||||
@@ -170,6 +192,16 @@ create_stack :: (scene: *PhysX.PxScene, t: PhysX.PxTransform, size: u32, half_ex
|
|||||||
//shape->release();
|
//shape->release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Hit :: struct {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
physx_raycast :: (origin: Vector3, direction: Vector3, max_distance: float = 1000.0) -> bool, Hit {
|
||||||
|
hit : PhysX.PxRaycastHit;
|
||||||
|
filter_data := PhysX.PxQueryFilterData_new();
|
||||||
|
has_hit := PhysX.PxSceneQueryExt_raycastSingle(engine.current_scene.physx_scene.scene, *origin, *direction, max_distance, 0, *hit, *filter_data, null, null);
|
||||||
|
return has_hit, .{};
|
||||||
|
}
|
||||||
|
|
||||||
create_dynamic :: (scene: *PhysX.PxScene, t: PhysX.PxTransform, geometry: *PhysX.PxGeometry, velocity: Vector3 = .{}) -> *PhysX.PxRigidDynamic {
|
create_dynamic :: (scene: *PhysX.PxScene, t: PhysX.PxTransform, geometry: *PhysX.PxGeometry, velocity: Vector3 = .{}) -> *PhysX.PxRigidDynamic {
|
||||||
p := Vector3.{0,0,0};
|
p := Vector3.{0,0,0};
|
||||||
|
|||||||
Reference in New Issue
Block a user