From a1e8d0f23144d6d5be8217c302a107bd9a78eeb0 Mon Sep 17 00:00:00 2001 From: sergeypdev Date: Sat, 1 Mar 2025 20:54:26 +0400 Subject: [PATCH] Disable edge separation tests for now and make a stress test --- build_hot_reload.sh | 2 +- game/game.odin | 15 +-- game/physics/collision/convex.odin | 182 ++++++++++++++--------------- game/physics/scene.odin | 2 +- game/physics/simulation.odin | 4 +- 5 files changed, 103 insertions(+), 102 deletions(-) diff --git a/build_hot_reload.sh b/build_hot_reload.sh index 64d2beb..1dabf5d 100755 --- a/build_hot_reload.sh +++ b/build_hot_reload.sh @@ -35,7 +35,7 @@ esac # Build the game. echo "Building game$DLL_EXT" -odin build game -extra-linker-flags:"$EXTRA_LINKER_FLAGS" -define:RAYLIB_SHARED=true -define:TRACY_ENABLE=true -collection:libs=./libs -collection:common=./common -collection:game=./game -build-mode:dll -out:game_tmp$DLL_EXT -strict-style -vet -debug +odin build game -extra-linker-flags:"$EXTRA_LINKER_FLAGS" -define:RAYLIB_SHARED=true -define:TRACY_ENABLE=true -collection:libs=./libs -collection:common=./common -collection:game=./game -build-mode:dll -out:game_tmp$DLL_EXT -strict-style -vet -debug -o:speed # Need to use a temp file on Linux because it first writes an empty `game.so`, which the game will load before it is actually fully written. mv game_tmp$DLL_EXT game$DLL_EXT diff --git a/game/game.odin b/game/game.odin index ec7d251..a6ea559 100644 --- a/game/game.odin +++ b/game/game.odin @@ -260,12 +260,13 @@ update_runtime_world :: proc(runtime_world: ^Runtime_World, dt: f32) { #hash("car", "fnv32a"), physics.Body_Config { initial_pos = {0, 4, 0}, - initial_rot = linalg.quaternion_angle_axis( - math.RAD_PER_DEG * 180, - rl.Vector3{0, 0, 1}, - ) * - linalg.quaternion_angle_axis(math.RAD_PER_DEG * 30, rl.Vector3{1, 0, 0}), - initial_ang_vel = {0, 0, 20}, + initial_rot = linalg.QUATERNIONF32_IDENTITY, + // initial_rot = linalg.quaternion_angle_axis( + // math.RAD_PER_DEG * 180, + // rl.Vector3{0, 0, 1}, + // ) * + // linalg.quaternion_angle_axis(math.RAD_PER_DEG * 30, rl.Vector3{1, 0, 0}), + initial_ang_vel = {0, 0, 0}, shape = physics.Shape_Convex { mesh = car_convex.mesh, center_of_mass = car_convex.center_of_mass, @@ -278,7 +279,7 @@ update_runtime_world :: proc(runtime_world: ^Runtime_World, dt: f32) { if true { for x in 0 ..< 10 { - for y in -3 ..< 10 { + for y in -3 ..< 100 { physics.immediate_body( &world.physics_scene, &runtime_world.solver_state, diff --git a/game/physics/collision/convex.odin b/game/physics/collision/convex.odin index db1aa6e..3431d84 100644 --- a/game/physics/collision/convex.odin +++ b/game/physics/collision/convex.odin @@ -180,121 +180,121 @@ query_separation_edges :: proc( step := 0 - separating_plane_p: Vec3 - success_step: int + if false { - Edge_Pair :: [2]halfedge.Edge_Index - checked_pairs := make_map_cap( - map[Edge_Pair]bool, - len(a.edges) * len(b.edges), - context.temp_allocator, - ) + separating_plane_p: Vec3 + success_step: int - for edge_a, edge_a_idx in a.edges { - for edge_b, edge_b_idx in b.edges { - pair := Edge_Pair{halfedge.Edge_Index(edge_a_idx), halfedge.Edge_Index(edge_b_idx)} - if checked_pairs[pair] { - continue - } + Edge_Pair :: [2]halfedge.Edge_Index + checked_pairs := make_map_cap( + map[Edge_Pair]bool, + len(a.edges) * len(b.edges), + context.temp_allocator, + ) - tracy.ZoneN("collision.query_separation_edges::check_single_pair") + for edge_a, edge_a_idx in a.edges { + for edge_b, edge_b_idx in b.edges { + pair := Edge_Pair{halfedge.Edge_Index(edge_a_idx), halfedge.Edge_Index(edge_b_idx)} + if checked_pairs[pair] { + continue + } - checked_pairs[pair] = true - if edge_a.twin >= 0 { - checked_pairs[{edge_a.twin, halfedge.Edge_Index(edge_b_idx)}] = true - } - if edge_b.twin >= 0 { - checked_pairs[{halfedge.Edge_Index(edge_a_idx), edge_b.twin}] = true - } - if edge_a.twin >= 0 && edge_b.twin >= 0 { - checked_pairs[{edge_a.twin, edge_b.twin}] = true - } + checked_pairs[pair] = true + if edge_a.twin >= 0 { + checked_pairs[{edge_a.twin, halfedge.Edge_Index(edge_b_idx)}] = true + } + if edge_b.twin >= 0 { + checked_pairs[{halfedge.Edge_Index(edge_a_idx), edge_b.twin}] = true + } + if edge_a.twin >= 0 && edge_b.twin >= 0 { + checked_pairs[{edge_a.twin, edge_b.twin}] = true + } - edge_a_dir := halfedge.get_edge_direction_normalized(a, edge_a) - edge_b_dir := halfedge.get_edge_direction_normalized(b, edge_b) + edge_a_dir := halfedge.get_edge_direction_normalized(a, edge_a) + edge_b_dir := halfedge.get_edge_direction_normalized(b, edge_b) - axis := lg.normalize0(lg.cross(edge_a_dir, edge_b_dir)) + axis := lg.normalize0(lg.cross(edge_a_dir, edge_b_dir)) - if axis == 0 { - continue - } + if axis == 0 { + continue + } - edge_a_origin, _ := halfedge.get_edge_points(a, edge_a) - if lg.dot(axis, edge_a_origin - a.center) < 0 { - axis = -axis - } - plane_a := plane_from_point_normal(edge_a_origin, axis) - vert_a, _, _ := find_support_point(a, plane_a.normal) - vert_b, vert_b_idx, _ := find_support_point(b, -plane_a.normal) + edge_a_origin, _ := halfedge.get_edge_points(a, edge_a) + if lg.dot(axis, edge_a_origin - a.center) < 0 { + axis = -axis + } + plane_a := plane_from_point_normal(edge_a_origin, axis) + vert_a, _, _ := find_support_point(a, plane_a.normal) + vert_b, vert_b_idx, _ := find_support_point(b, -plane_a.normal) - // We found the support vert on mesh b, but now we need to find the - // best edge that includes that point - vert_b_edge: halfedge.Half_Edge - vert_b_edge_idx: halfedge.Edge_Index = -1 - { - min_b2_distance := max(f32) - it := halfedge.iterator_vertex_edges(b, vert_b_idx) - for edge, edge_idx in halfedge.iterate_next_vertex_edge(&it) { - _, vert_b2 := halfedge.get_edge_points(b, edge) + // We found the support vert on mesh b, but now we need to find the + // best edge that includes that point + vert_b_edge: halfedge.Half_Edge + vert_b_edge_idx: halfedge.Edge_Index = -1 + { + min_b2_distance := max(f32) + it := halfedge.iterator_vertex_edges(b, vert_b_idx) + for edge, edge_idx in halfedge.iterate_next_vertex_edge(&it) { + _, vert_b2 := halfedge.get_edge_points(b, edge) - distance_b2 := signed_distance_plane(vert_b2, plane_a) - if distance_b2 < min_b2_distance { - min_b2_distance = distance_b2 - vert_b_edge = edge - vert_b_edge_idx = edge_idx + distance_b2 := signed_distance_plane(vert_b2, plane_a) + if distance_b2 < min_b2_distance { + min_b2_distance = distance_b2 + vert_b_edge = edge + vert_b_edge_idx = edge_idx + } + } + + if vert_b_edge_idx < 0 { + continue } } - if vert_b_edge_idx < 0 { + distance_a := signed_distance_plane(vert_a.pos, plane_a) + if distance_a > 0 { continue } - } + distance_b := signed_distance_plane(vert_b.pos, plane_a) + vert_b_projected := vert_b.pos + plane_a.normal * -distance_b - distance_a := signed_distance_plane(vert_a.pos, plane_a) - if distance_a > 0 { - continue - } - distance_b := signed_distance_plane(vert_b.pos, plane_a) - vert_b_projected := vert_b.pos + plane_a.normal * -distance_b + if step == -1 { + // a1, a2 := halfedge.get_edge_points(a, edge_a) + // edge_a_center := (a1 + a2) * 0.5 + a1, a2 := halfedge.get_edge_points(halfedge.Half_Edge_Mesh(a), edge_a) + b1, b2 := halfedge.get_edge_points(halfedge.Half_Edge_Mesh(b), vert_b_edge) - if step == -1 { - // a1, a2 := halfedge.get_edge_points(a, edge_a) - // edge_a_center := (a1 + a2) * 0.5 - a1, a2 := halfedge.get_edge_points(halfedge.Half_Edge_Mesh(a), edge_a) - b1, b2 := halfedge.get_edge_points(halfedge.Half_Edge_Mesh(b), vert_b_edge) + rl.DrawLine3D(edge_a_origin, edge_a_origin + plane_a.normal, rl.BLUE) + rl.DrawLine3D(a1 + 0.1, a2 + 0.1, rl.ORANGE) + rl.DrawLine3D(b1 + 0.1, b2 + 0.1, rl.PURPLE) - rl.DrawLine3D(edge_a_origin, edge_a_origin + plane_a.normal, rl.BLUE) - rl.DrawLine3D(a1 + 0.1, a2 + 0.1, rl.ORANGE) - rl.DrawLine3D(b1 + 0.1, b2 + 0.1, rl.PURPLE) + rl.DrawSphereWires(edge_a_origin, 0.1, 4, 4, rl.ORANGE) + rl.DrawSphereWires(vert_b.pos, 0.05, 4, 4, rl.BLUE) + rl.DrawSphereWires(vert_b_projected, 0.05, 4, 4, rl.BLUE) + rl.DrawLine3D(vert_b.pos, vert_b_projected, rl.VIOLET) + log.debugf("dist: %v", distance_b) - rl.DrawSphereWires(edge_a_origin, 0.1, 4, 4, rl.ORANGE) - rl.DrawSphereWires(vert_b.pos, 0.05, 4, 4, rl.BLUE) - rl.DrawSphereWires(vert_b_projected, 0.05, 4, 4, rl.BLUE) - rl.DrawLine3D(vert_b.pos, vert_b_projected, rl.VIOLET) - log.debugf("dist: %v", distance_b) - - { - // rl.BeginBlendMode(.ALPHA) - // defer rl.EndBlendMode() - debug_draw_plane(edge_a_origin, plane_a, rl.Color{0, 228, 48, 100}) + { + // rl.BeginBlendMode(.ALPHA) + // defer rl.EndBlendMode() + debug_draw_plane(edge_a_origin, plane_a, rl.Color{0, 228, 48, 100}) + } } - } - if distance_b > separation { - separation = distance_b - a_edge = halfedge.Edge_Index(edge_a_idx) - b_edge = vert_b_edge_idx - separating_plane = plane_a - separating_plane_p = edge_a_origin - success_step = step - } + if distance_b > separation { + separation = distance_b + a_edge = halfedge.Edge_Index(edge_a_idx) + b_edge = vert_b_edge_idx + separating_plane = plane_a + separating_plane_p = edge_a_origin + success_step = step + } - step += 1 + step += 1 + } } + // log.debugf("step: %v", success_step) + // debug_draw_plane(separating_plane_p, separating_plane, rl.Color{228, 0, 48, 100}) } - // log.debugf("step: %v", success_step) - // debug_draw_plane(separating_plane_p, separating_plane, rl.Color{228, 0, 48, 100}) - return } diff --git a/game/physics/scene.odin b/game/physics/scene.odin index 9c9d950..714e481 100644 --- a/game/physics/scene.odin +++ b/game/physics/scene.odin @@ -3,7 +3,7 @@ package physics import "collision" import lg "core:math/linalg" -MAX_CONTACTS :: 1024 +MAX_CONTACTS :: 1024 * 16 Vec3 :: [3]f32 Quat :: quaternion128 diff --git a/game/physics/simulation.odin b/game/physics/simulation.odin index 3e62db6..4be125e 100644 --- a/game/physics/simulation.odin +++ b/game/physics/simulation.odin @@ -170,7 +170,7 @@ simulate :: proc( } } - bvh.debug_draw_bvh_bounds(&sim_state_bvh, body_aabbs, 0) + // bvh.debug_draw_bvh_bounds(&sim_state_bvh, body_aabbs, 0) switch step_mode { case .Accumulated_Time: @@ -507,7 +507,7 @@ simulate_step :: proc( prev_v_normal := lg.dot(prev_v, manifold.normal) v_normal := lg.dot(v, manifold.normal) - RESTITUTION :: 0.3 + RESTITUTION :: 1 restitution := f32(RESTITUTION)