diff --git a/game/game.odin b/game/game.odin index 02ad24c..7c2e972 100644 --- a/game/game.odin +++ b/game/game.odin @@ -20,7 +20,6 @@ import "core:hash" import "core:log" import "core:math" import "core:math/linalg" -import "core:slice" import "game:physics" import "game:physics/bvh" import "game:render" @@ -484,10 +483,12 @@ update_world :: proc(world: ^World, dt: f32, config: World_Update_Config) { if true { for x in 0 ..< 10 { for y in 0 ..< 10 { + box_name := name.from_string(fmt.tprintf("box[{},{}]", x, y)) physics.immediate_body( &world.physics_scene, - hash.fnv32a(slice.to_bytes([]int{(x | y << 8)})), + u32(box_name), physics.Body_Config { + name = box_name, initial_pos = {-5, 0.5 + f32(y) * 1.1, f32(x) * 3 + 10}, initial_rot = linalg.QUATERNIONF32_IDENTITY, shapes = { @@ -696,15 +697,20 @@ update_world :: proc(world: ^World, dt: f32, config: World_Update_Config) { { level_model := assets.get_model(&g_mem.assetman, "assets/testblend.glb") - for i in 0 ..< level_model.meshCount { + for i in 0 ..< min(level_model.meshCount, 32) { mesh := &level_model.meshes[i] if mesh.triangleCount > 0 { + assert(mesh.vertexCount <= i32(max(u16))) + m := level_model.transform + pos := physics.Vec3{m[3][0], m[3][1], m[3][2]} + rotation := linalg.quaternion_from_matrix4_f32(auto_cast level_model.transform) physics.immediate_level_geom( &world.physics_scene, hash.fnv32a(transmute([]byte)(fmt.tprintf("level mesh {}", i))), { - rotation = linalg.QUATERNIONF32_IDENTITY, + position = pos, + rotation = rotation, vertices = (cast([^]rl.Vector3)mesh.vertices)[:mesh.vertexCount], indices = mesh.indices[:mesh.triangleCount * 3], }, @@ -1051,7 +1057,7 @@ draw_world :: proc(world: ^World) { sim_state := physics.get_sim_state(&world.physics_scene) - level_model := assets.get_model(&g_mem.assetman, "assets/testblend.glb") + // level_model := assets.get_model(&g_mem.assetman, "assets/testblend.glb") car_body := physics.get_body(sim_state, world.car_handle) car_model := assets.get_model(&g_mem.assetman, "assets/ice_cream_truck.glb") @@ -1127,7 +1133,7 @@ draw_world :: proc(world: ^World) { // .VEC3, // ) - render.draw_model(level_model, {}, 1) + // render.draw_model(level_model, {}, 1) render.draw_model(car_model, {}, car_matrix) diff --git a/game/physics/bvh/bvh.odin b/game/physics/bvh/bvh.odin index ef74022..7fdba0a 100644 --- a/game/physics/bvh/bvh.odin +++ b/game/physics/bvh/bvh.odin @@ -47,6 +47,12 @@ Mesh_BVH :: struct { mesh: Mesh, } +destroy_mesh_bvh :: proc(bvh: ^Mesh_BVH) { + destroy_bvh(&bvh.bvh) + delete(bvh.mesh.vertices) + delete(bvh.mesh.indices) +} + Node :: struct { aabb: AABB, // Index of the left child, right child is left_child + 1 diff --git a/game/physics/bvh/debug.odin b/game/physics/bvh/debug.odin index 598d877..b225a39 100644 --- a/game/physics/bvh/debug.odin +++ b/game/physics/bvh/debug.odin @@ -14,6 +14,12 @@ import "libs:tracy" _ :: fmt _ :: log +@(private = "file") +Traversal :: struct { + node_idx: i32, + should_draw: bool, +} + // Assuming rl.BeginMode3D was called before this debug_draw_bvh_bounds_mesh :: proc(bvh: ^BVH, mesh: Mesh, pos: rl.Vector3, node_index: int) { old_width := rlgl.GetLineWidth() @@ -23,10 +29,6 @@ debug_draw_bvh_bounds_mesh :: proc(bvh: ^BVH, mesh: Mesh, pos: rl.Vector3, node_ temp := runtime.default_temp_allocator_temp_begin() defer runtime.default_temp_allocator_temp_end(temp) - Traversal :: struct { - node_idx: i32, - should_draw: bool, - } nodes_to_process: queue.Queue(Traversal) queue.init(&nodes_to_process, queue.DEFAULT_CAPACITY, context.temp_allocator) @@ -100,10 +102,6 @@ debug_draw_bvh_bounds :: proc(bvh: ^BVH, primitive_bounds: []AABB, node_index: i temp := runtime.default_temp_allocator_temp_begin() defer runtime.default_temp_allocator_temp_end(temp) - Traversal :: struct { - node_idx: i32, - should_draw: bool, - } nodes_to_process: queue.Queue(Traversal) queue.init(&nodes_to_process, queue.DEFAULT_CAPACITY, context.temp_allocator) diff --git a/game/physics/debug.odin b/game/physics/debug.odin index 671afc9..30e5391 100644 --- a/game/physics/debug.odin +++ b/game/physics/debug.odin @@ -54,6 +54,16 @@ draw_debug_scene :: proc(scene: ^Scene) { sim_state := get_sim_state(scene) + // Static_TLAS + if true && sim_state.static_tlas.built { + bvh.debug_draw_bvh_bounds_mesh( + &sim_state.static_tlas.bvh_tree.bvh, + sim_state.static_tlas.bvh_tree.mesh, + 0, + 0, + ) + } + // Dynamic TLAS if true && sim_state.dynamic_tlas.built { bvh.debug_draw_bvh_bounds( @@ -99,20 +109,20 @@ draw_debug_scene :: proc(scene: ^Scene) { } } - if true { - for &level_geom, geom_idx in sim_state.level_geoms { - if level_geom.alive { - vertices, indices := get_level_geom_data(sim_state, level_geom.geometry) + // if true { + // for &level_geom, geom_idx in sim_state.level_geoms { + // if level_geom.alive { + // vertices, indices := get_level_geom_data(sim_state, level_geom.geometry) - for i in 0 ..< len(indices) / 3 { - i1, i2, i3 := indices[i * 3 + 0], indices[i * 3 + 1], indices[i * 3 + 2] - v1, v2, v3 := vertices[i1], vertices[i2], vertices[i3] + // for i in 0 ..< len(indices) / 3 { + // i1, i2, i3 := indices[i * 3 + 0], indices[i * 3 + 1], indices[i * 3 + 2] + // v1, v2, v3 := vertices[i1], vertices[i2], vertices[i3] - rl.DrawTriangle3D(v1, v2, v3, debug.int_to_color(i32(geom_idx + 1))) - } - } - } - } + // rl.DrawTriangle3D(v1, v2, v3, debug.int_to_color(i32(geom_idx + 1))) + // } + // } + // } + // } for _, i in sim_state.suspension_constraints { wheel := &sim_state.suspension_constraints_slice[i] diff --git a/game/physics/helpers.odin b/game/physics/helpers.odin index 9da408d..dd6ec5b 100644 --- a/game/physics/helpers.odin +++ b/game/physics/helpers.odin @@ -5,7 +5,6 @@ import "core:log" import "core:math" import lg "core:math/linalg" import "game:halfedge" -import "game:name" import "libs:tracy" _ :: log @@ -264,9 +263,6 @@ body_get_convex_shape_by_linear_index_world :: proc( mesh: collision.Convex, ) { tracy.Zone() - if shape_linear_idx == 1 { - log.debugf("linear idx: %v, body %v", shape_linear_idx, name.to_string(body.name)) - } shape_idx := get_shape_by_index(sim_state, body.shape, shape_linear_idx) return body_get_convex_shape_world(sim_state, body, sim_state.shapes[shape_idx], allocator) } diff --git a/game/physics/scene.odin b/game/physics/scene.odin index 43095cf..ef82dc7 100644 --- a/game/physics/scene.odin +++ b/game/physics/scene.odin @@ -1,5 +1,6 @@ package physics +import "bvh" import "collision" import lg "core:math/linalg" import "game:container/spanpool" @@ -23,6 +24,7 @@ Contact_Pair_Bodies :: struct { } Contact_Pair_Body_Level :: struct { a: Body_Handle, + b: Level_Geom_Handle, shape_a: i32, tri_idx: i32, } @@ -47,11 +49,12 @@ make_contact_pair_bodies :: proc( } make_contact_pair_body_level :: proc( - body: i32, + body: Body_Handle, + level_geom_handle: Level_Geom_Handle, shape_a: i32, tri_idx: i32, ) -> Contact_Pair_Body_Level { - return {index_to_body_handle(int(body)), shape_a, tri_idx} + return {body, level_geom_handle, shape_a, tri_idx} } Contact_Container :: struct { @@ -107,6 +110,10 @@ Sim_State :: struct { geometry_vertices_pool: spanpool.Span_Pool(Vec3), geometry_indices_pool: spanpool.Span_Pool(u16), + // BLAS for level geom + blas_nodes_pool: spanpool.Span_Pool(bvh.Node), + blas_primitives_pool: spanpool.Span_Pool(u16), + // Temp stuff, kept for one frame, allocated from temp_allocator static_tlas: Static_TLAS, dynamic_tlas: Dynamic_TLAS, @@ -154,6 +161,8 @@ copy_sim_state :: proc(dst: ^Sim_State, src: ^Sim_State) { spanpool.copy(&dst.gear_ratios_pool, src.gear_ratios_pool) spanpool.copy(&dst.geometry_vertices_pool, src.geometry_vertices_pool) spanpool.copy(&dst.geometry_indices_pool, src.geometry_indices_pool) + spanpool.copy(&dst.blas_nodes_pool, src.blas_nodes_pool) + spanpool.copy(&dst.blas_primitives_pool, src.blas_primitives_pool) } copy_physics_scene :: proc(dst, src: ^Scene) { @@ -377,9 +386,16 @@ Geometry_Handle :: struct { indices: spanpool.Handle, } +BLAS_Handle :: struct { + nodes: spanpool.Handle, + primitives: spanpool.Handle, +} + Level_Geom :: struct { alive: bool, + aabb: AABB, geometry: Geometry_Handle, + blas: BLAS_Handle, x: Vec3, q: Quat, next_plus_one: i32, @@ -416,19 +432,19 @@ is_handle_valid :: proc { is_level_geom_handle_valid, } -index_to_body_handle :: proc(idx: int) -> Body_Handle { +index_to_body_handle :: #force_inline proc(idx: int) -> Body_Handle { return Body_Handle(idx + 1) } -index_to_level_geom :: proc(idx: int) -> Level_Geom_Handle { +index_to_level_geom :: #force_inline proc(idx: int) -> Level_Geom_Handle { return Level_Geom_Handle(idx + 1) } -body_handle_to_index :: proc(handle: Body_Handle) -> int { +body_handle_to_index :: #force_inline proc(handle: Body_Handle) -> int { return int(handle) - 1 } -level_geom_handle_to_index :: proc(handle: Level_Geom_Handle) -> int { +level_geom_handle_to_index :: #force_inline proc(handle: Level_Geom_Handle) -> int { return int(handle) - 1 } @@ -913,6 +929,13 @@ get_level_geom_data :: proc( return } +get_level_geom_blas :: proc(sim_state: ^Sim_State, handle: BLAS_Handle) -> (bvh: bvh.BVH) { + bvh.nodes = spanpool.resolve_slice(&sim_state.blas_nodes_pool, handle.nodes) + bvh.primitives = spanpool.resolve_slice(&sim_state.blas_primitives_pool, handle.primitives) + bvh.nodes_used = i32(len(bvh.nodes)) + return +} + update_level_geom_from_config :: proc( sim_state: ^Sim_State, level_geom: Level_Geom_Ptr, @@ -921,6 +944,40 @@ update_level_geom_from_config :: proc( level_geom.x = config.position level_geom.q = config.rotation + // TODO: figure out if asset changed and rebuild only then +} + +add_level_geom :: proc(sim_state: ^Sim_State, config: Level_Geom_Config) -> Level_Geom_Handle { + assert(len(config.vertices) > 0) + assert(len(config.vertices) <= int(max(u16))) + + sim_state.num_level_geoms += 1 + + level_geom: Level_Geom + level_geom.alive = true + update_level_geom_from_config(sim_state, &level_geom, config) + + blas := + bvh.build_bvh_from_mesh(bvh.Mesh{vertices = config.vertices, indices = config.indices}, context.temp_allocator).bvh + + level_geom.blas.nodes = spanpool.allocate_elems( + &sim_state.blas_nodes_pool, + ..blas.nodes[:blas.nodes_used], + ) + level_geom.blas.primitives = spanpool.allocate_elems( + &sim_state.blas_primitives_pool, + ..blas.primitives, + ) + + aabb_min, aabb_max: Vec3 = max(f32), min(f32) + for v in config.vertices { + aabb_min = lg.min(aabb_min, v) + aabb_max = lg.max(aabb_max, v) + } + + level_geom.aabb.center = (aabb_max + aabb_min) * 0.5 + level_geom.aabb.extent = (aabb_max - aabb_min) * 0.5 + if spanpool.is_handle_valid(&sim_state.geometry_vertices_pool, level_geom.geometry.vertices) { spanpool.free(&sim_state.geometry_vertices_pool, level_geom.geometry.vertices) spanpool.free(&sim_state.geometry_indices_pool, level_geom.geometry.indices) @@ -934,14 +991,6 @@ update_level_geom_from_config :: proc( &sim_state.geometry_indices_pool, ..config.indices, ) -} - -add_level_geom :: proc(sim_state: ^Sim_State, config: Level_Geom_Config) -> Level_Geom_Handle { - sim_state.num_level_geoms += 1 - - level_geom: Level_Geom - level_geom.alive = true - update_level_geom_from_config(sim_state, &level_geom, config) if sim_state.first_free_level_geom_plus_one > 0 { index := sim_state.first_free_level_geom_plus_one @@ -962,6 +1011,9 @@ remove_level_geom :: proc(sim_state: ^Sim_State, handle: Level_Geom_Handle) { spanpool.free(&sim_state.geometry_vertices_pool, level_geom.geometry.vertices) spanpool.free(&sim_state.geometry_indices_pool, level_geom.geometry.indices) + + spanpool.free(&sim_state.blas_nodes_pool, level_geom.blas.nodes) + spanpool.free(&sim_state.blas_primitives_pool, level_geom.blas.primitives) } _get_first_free_body :: proc(sim_state: ^Sim_State) -> i32 { @@ -983,6 +1035,7 @@ destry_sim_state :: proc(sim_state: ^Sim_State) { spanpool.destroy_spanpool(&sim_state.geometry_vertices_pool) spanpool.destroy_spanpool(&sim_state.geometry_indices_pool) + static_tlas_destroy(&sim_state.static_tlas) dynamic_tlas_destroy(&sim_state.dynamic_tlas) } diff --git a/game/physics/simulation.odin b/game/physics/simulation.odin index 08b53a0..aabb36f 100644 --- a/game/physics/simulation.odin +++ b/game/physics/simulation.odin @@ -71,8 +71,9 @@ Step_Mode :: enum { } Static_TLAS :: struct { - bvh_tree: bvh.Mesh_BVH, - tri_to_level_geom: []Level_Geom_Handle, + bvh_tree: bvh.BVH, + level_geom_aabbs: []bvh.AABB, + built: bool, } // Top Level Acceleration Structure @@ -82,70 +83,43 @@ Dynamic_TLAS :: struct { built: bool, } -build_static_tlas :: proc(sim_state: ^Sim_State) -> Static_TLAS { +build_static_tlas :: proc(sim_state: ^Sim_State, out_tlas: ^Static_TLAS) { tracy.Zone() - num_vertices, num_indices: int - for i in 0 ..< len(sim_state.level_geoms) { - level_geom := &sim_state.level_geoms[i] + static_tlas_destroy(out_tlas) - if level_geom.alive { - num_vertices += int(level_geom.geometry.vertices.len) - num_indices += int(level_geom.geometry.indices.len) - } - } + level_geom_aabbs := make([]bvh.AABB, len(sim_state.level_geoms)) + level_geom_indices := make([]u16, len(sim_state.level_geoms), context.temp_allocator) - if num_vertices == 0 { - return Static_TLAS{} - } + { + for i in 0 ..< len(sim_state.level_geoms) { + level_geom := &sim_state.level_geoms[i] - vertices := make([]bvh.Vec3, num_vertices, context.temp_allocator) - indices := make([]u16, num_indices, context.temp_allocator) + if level_geom.alive { + aabb := &level_geom_aabbs[i] + level_geom_indices[i] = u16(i) - tri_to_level_geom := make([]Level_Geom_Handle, num_indices / 3, context.temp_allocator) - - num_vertices, num_indices = 0, 0 - - for i in 0 ..< len(sim_state.level_geoms) { - level_geom := &sim_state.level_geoms[i] - - if level_geom.alive { - geom_verts, geom_inds := get_level_geom_data(sim_state, level_geom.geometry) - - base_vertex := num_vertices - copy_slice(vertices[base_vertex:], geom_verts) - num_vertices += len(geom_verts) - - for j in 0 ..< len(geom_inds) { - if num_indices %% 3 == 0 { - tri := num_indices / 3 - tri_to_level_geom[tri] = index_to_level_geom(i) - } - ind := geom_inds[j] - indices[num_indices] = u16(base_vertex + int(ind)) - num_indices += 1 + aabb.min = level_geom.aabb.center - level_geom.aabb.extent + aabb.max = level_geom.aabb.center + level_geom.aabb.extent } } } - log.debugf("num vertices {}, len vertices {}", num_vertices, len(vertices)) - assert(num_vertices == len(vertices)) - assert(num_indices == len(indices)) + sim_state_bvh := bvh.build_bvh_from_aabbs(level_geom_aabbs, level_geom_indices) - // for i in 0 ..< len(indices) / 3 { - // tri := get_triangle(vertices, indices, i) - // rl.DrawTriangle3D(tri[0], tri[1], tri[2], rl.RED) - // } - - result := Static_TLAS { - bvh_tree = bvh.build_bvh_from_mesh( - bvh.Mesh{vertices = vertices, indices = indices}, - context.temp_allocator, - ), - tri_to_level_geom = tri_to_level_geom, + out_tlas^ = Static_TLAS { + built = true, + bvh_tree = sim_state_bvh, + level_geom_aabbs = level_geom_aabbs, } +} - return result +static_tlas_destroy :: proc(static_tlas: ^Static_TLAS) { + if static_tlas.built { + bvh.destroy_bvh(&static_tlas.bvh_tree) + delete(static_tlas.level_geom_aabbs) + static_tlas^ = {} + } } // TODO: free intermediate temp allocs @@ -160,18 +134,16 @@ build_dynamic_tlas :: proc( dynamic_tlas_destroy(out_tlas) - body_aabbs := make([]bvh.AABB, sim_state.num_bodies, allocator) - body_indices := make([]u16, sim_state.num_bodies, context.temp_allocator) + body_aabbs := make([]bvh.AABB, len(sim_state.bodies_slice), allocator) + body_indices := make([]u16, len(sim_state.bodies_slice), context.temp_allocator) { - aabb_index := 0 for i in 0 ..< len(sim_state.bodies_slice) { body := &sim_state.bodies_slice[i] if body.alive { - aabb := &body_aabbs[aabb_index] - body_indices[aabb_index] = u16(i) - aabb_index += 1 + aabb := &body_aabbs[i] + body_indices[i] = u16(i) phys_aabb := body_get_aabb(body) @@ -221,11 +193,24 @@ raycasts_level :: proc( ray.origin = origin ray.dir = dir ray.dir_inv = 1.0 / dir - it := bvh.iterator_intersect_leaf_ray(&tlas.bvh_tree.bvh, ray, distance) + it := bvh.iterator_intersect_leaf_ray(&tlas.bvh_tree, ray, distance) for leaf_node in bvh.iterator_intersect_leaf_next(&it) { for j in 0 ..< leaf_node.prim_len { - tri_idx := tlas.bvh_tree.bvh.primitives[leaf_node.child_or_prim_start + j] + level_geom_handle := index_to_level_geom( + int(tlas.bvh_tree.primitives[leaf_node.child_or_prim_start + j]), + ) + level_geom := get_level_geom(sim_state, level_geom_handle) + blas := get_level_geom_blas(sim_state, level_geom.blas) + vertices, indices := get_level_geom_data(sim_state, level_geom.geometry) + + blas_it := bvh.iterator_intersect_leaf_ray(&blas, ray, distance) + for blas_leaf_node in bvh.iterator_intersect_leaf_next(&it) { + for k in 0 ..< blas_leaf_node.prim_len { + tri_idx := blas.primitives[blas_leaf_node.child_or_prim_start + k] + } + } + tri := get_triangle( tlas.bvh_tree.mesh.vertices, tlas.bvh_tree.mesh.indices, @@ -388,8 +373,8 @@ remove_invalid_contacts :: proc( should_remove |= !get_body(sim_state, Body_Handle(contact.b)).alive if !should_remove { - aabb_a := dyn_tlas.body_aabbs[int(contact.a) - 1] - aabb_b := dyn_tlas.body_aabbs[int(contact.b) - 1] + aabb_a := dyn_tlas.body_aabbs[body_handle_to_index(contact.a)] + aabb_b := dyn_tlas.body_aabbs[body_handle_to_index(Body_Handle(contact.b))] should_remove |= !bvh.test_aabb_vs_aabb(aabb_a, aabb_b) } @@ -398,14 +383,18 @@ remove_invalid_contacts :: proc( should_remove |= !get_body(sim_state, contact.a).alive if !should_remove { - should_remove |= int(contact.tri_idx * 3) > len(static_tlas.bvh_tree.mesh.indices) + level_geom_handle := Level_Geom_Handle(contact.b) + tri_offset := + static_tlas.level_geom_tri_offset[level_geom_handle_to_index(level_geom_handle)] + tri_idx := tri_offset + int(contact.local_tri_idx) + should_remove |= (tri_idx * 3) >= len(static_tlas.bvh_tree.mesh.indices) if !should_remove { - aabb_a := dyn_tlas.body_aabbs[int(contact.a) - 1] + aabb_a := dyn_tlas.body_aabbs[body_handle_to_index(contact.a)] tri := get_triangle( static_tlas.bvh_tree.mesh.vertices, static_tlas.bvh_tree.mesh.indices, - int(contact.tri_idx), + tri_idx, ) aabb_b := get_triangle_aabb(tri) @@ -424,9 +413,10 @@ remove_invalid_contacts :: proc( ) } else { pair = make_contact_pair_body_level( - i32(body_handle_to_index(contact.a)), + Body_Handle(contact.a), + Level_Geom_Handle(contact.b), contact.shape_a, - contact.tri_idx, + contact.local_tri_idx, ) } return @@ -554,11 +544,16 @@ find_new_contacts :: proc( ) prim_aabb := get_triangle_aabb(tri) level_geom_handle := static_tlas.tri_to_level_geom[tri_idx] + local_tri_idx := + int(tri_idx) - + static_tlas.level_geom_tri_offset[level_geom_handle_to_index(level_geom_handle)] + assert(local_tri_idx >= 0) if bvh.test_aabb_vs_aabb(body_aabb, prim_aabb) { shapes_it := shapes_iterator(sim_state, body.shape) - for shape, shape_idx in shapes_iterator_next(&shapes_it) { + for shape in shapes_iterator_next(&shapes_it) { + shape_idx := shapes_it.counter - 1 shape_aabb := shape_get_aabb(shape^) shape_aabb = body_transform_shape_aabb(body, shape_aabb) bvh_shape_aabb := bvh.AABB { @@ -567,9 +562,10 @@ find_new_contacts :: proc( } pair := make_contact_pair_body_level( - i32(body_idx), + index_to_body_handle(int(body_idx)), + level_geom_handle, shape_idx, - i32(tri_idx), + i32(local_tri_idx), ) if bvh.test_aabb_vs_aabb(prim_aabb, bvh_shape_aabb) && @@ -582,11 +578,11 @@ find_new_contacts :: proc( contact := &sim_state.contact_container.contacts[new_contact_idx] contact^ = Contact { - type = .Body_vs_Level, - a = index_to_body_handle(i), - shape_a = shape_idx, - b = i32(level_geom_handle), - tri_idx = i32(tri_idx), + type = .Body_vs_Level, + a = index_to_body_handle(i), + shape_a = shape_idx, + b = i32(level_geom_handle), + local_tri_idx = i32(local_tri_idx), } sim_state.contact_container.lookup[pair] = i32(new_contact_idx) @@ -665,7 +661,7 @@ Contact :: struct { b: i32, // shape index in each body shape_a, shape_b: i32, - tri_idx: i32, + local_tri_idx: i32, prev_x_a, prev_x_b: Vec3, prev_q_a, prev_q_b: Quat, manifold: collision.Contact_Manifold, @@ -737,17 +733,17 @@ update_contacts :: proc(sim_state: ^Sim_State, static_tlas: ^Static_TLAS) { case .Body_vs_Body: m2 = body_get_convex_shape_by_linear_index_world(sim_state, body2, contact.shape_b) case .Body_vs_Level: - // level_geom := get_level_geom(sim_state, Level_Geom_Handle(contact.b)) + level_geom_handle := Level_Geom_Handle(contact.b) + tri_idx := + static_tlas.level_geom_tri_offset[level_geom_handle_to_index(level_geom_handle)] + + int(contact.local_tri_idx) tri := get_triangle( static_tlas.bvh_tree.mesh.vertices, static_tlas.bvh_tree.mesh.indices, - int(contact.tri_idx), + tri_idx, ) - // rl.DrawTriangle3D(tri[0], tri[1], tri[2], rl.BLUE) m2 = collision.double_sided_triangle_to_convex(tri, context.temp_allocator) - // m2 = level_geom_get_convex_shape(sim_state, level_geom, int(contact.tri_idx)) - // he.debug_draw_mesh_wires(m2, rl.BLUE) } // Raw manifold has contact points in world space @@ -818,7 +814,7 @@ pgs_solve_contacts :: proc( inv_dt: f32, apply_bias: bool, ) { - bias_rate, mass_coef, impulse_coef := calculate_soft_constraint_params(16, 1, dt) + bias_rate, mass_coef, impulse_coef := calculate_soft_constraint_params(30, 0.8, dt) if !apply_bias { mass_coef = 1 bias_rate = 0 @@ -1521,7 +1517,7 @@ simulate_step :: proc(scene: ^Scene, sim_state: ^Sim_State, config: Solver_Confi dt := f32(dt_64) inv_dt := f32(inv_dt_64) - sim_state.static_tlas = build_static_tlas(sim_state) + build_static_tlas(sim_state, &sim_state.static_tlas) build_dynamic_tlas(sim_state, config, &sim_state.dynamic_tlas) remove_invalid_contacts(sim_state, sim_state.static_tlas, sim_state.dynamic_tlas)