Raycast against level geom

This commit is contained in:
sergeypdev 2025-05-12 11:27:16 +04:00
parent 735c61fd05
commit 6e2ad6a3b0
3 changed files with 97 additions and 12 deletions

View File

@ -359,8 +359,6 @@ World_Update_Config :: struct {
}
update_world :: proc(world: ^World, dt: f32, config: World_Update_Config) {
rl.BeginDrawing()
rl.BeginMode3D(game_camera_3d())
if !world.pause {
car_model := assets.get_model(&g_mem.assetman, "assets/toyota_corolla_ae86_trueno.glb")
car_bounds := rl.GetModelBoundingBox(car_model)
@ -1043,6 +1041,7 @@ draw_world :: proc(world: ^World) {
draw :: proc() {
tracy.Zone()
rl.BeginDrawing()
defer rl.EndDrawing()
rl.ClearBackground(rl.GRAY)
render.clear_stencil()
@ -1061,6 +1060,7 @@ draw :: proc() {
// )
{
rl.BeginMode3D(camera)
defer rl.EndMode3D()
draw_world(world)

View File

@ -69,7 +69,7 @@ draw_debug_scene :: proc(scene: ^Scene) {
}
}
if false {
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)

View File

@ -1,6 +1,5 @@
package physics
import rl " libs:raylib"
import "base:runtime"
import "bvh"
import "collision"
@ -180,6 +179,52 @@ build_dynamic_tlas :: proc(sim_state: ^Sim_State, config: Solver_Config) -> Dyna
return Dynamic_TLAS{bvh_tree = sim_state_bvh, body_aabbs = body_aabbs}
}
raycasts_level :: proc(
sim_state: ^Sim_State,
tlas: ^Static_TLAS,
origin, dir: Vec3,
distance := max(f32),
) -> (
t: f32,
normal: Vec3,
hit: bool,
) {
temp := runtime.default_temp_allocator_temp_begin()
defer runtime.default_temp_allocator_temp_end(temp)
t = distance
ray: bvh.Ray
ray.origin = origin
ray.dir = dir
ray.dir_inv = 1.0 / dir
it := bvh.iterator_intersect_leaf_ray(&tlas.bvh_tree.bvh, 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]
tri := get_triangle(
tlas.bvh_tree.mesh.vertices,
tlas.bvh_tree.mesh.indices,
int(tri_idx),
)
hit_t, tmp_normal, _, ok := collision.intersect_ray_triangle(
{origin, origin + dir},
tri,
)
if ok && (!hit || hit_t < t) {
t = hit_t
normal = tmp_normal
hit = true
}
}
}
return
}
raycast_bodies :: proc(
sim_state: ^Sim_State,
tlas: ^Dynamic_TLAS,
@ -226,6 +271,43 @@ raycast_bodies :: proc(
return
}
raycast :: proc(
sim_state: ^Sim_State,
static_tlas: ^Static_TLAS,
dyn_tlas: ^Dynamic_TLAS,
origin, dir: Vec3,
distance := max(f32),
) -> (
t: f32,
normal: Vec3,
hit: bool,
) {
t = distance
t1, normal1, hit1 := raycasts_level(sim_state, static_tlas, origin, dir, t)
t2, normal2, hit2 := raycast_bodies(sim_state, dyn_tlas, origin, dir, t)
hit = hit1 || hit2
if hit1 && hit2 {
if t1 < t2 {
t = t1
normal = normal1
} else {
t = t2
normal = normal2
}
} else if hit1 {
t = t1
normal = normal1
} else if hit2 {
t = t2
normal = normal2
}
return
}
get_triangle :: proc(vertices: []Vec3, indices: []u16, tri_idx: int) -> (tri: [3]Vec3) {
i1, i2, i3 := indices[tri_idx * 3 + 0], indices[tri_idx * 3 + 1], indices[tri_idx * 3 + 2]
tri[0], tri[1], tri[2] = vertices[i1], vertices[i2], vertices[i3]
@ -557,7 +639,7 @@ update_contacts :: proc(sim_state: ^Sim_State, static_tlas: ^Static_TLAS) {
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)
// he.debug_draw_mesh_wires(m2, rl.BLUE)
}
// Raw manifold has contact points in world space
@ -955,7 +1037,8 @@ calculate_ground_vel :: proc(
pgs_solve_suspension :: proc(
sim_state: ^Sim_State,
tlas: ^Dynamic_TLAS,
static_tlas: ^Static_TLAS,
dyn_tlas: ^Dynamic_TLAS,
config: Solver_Config,
dt: f32,
inv_dt: f32,
@ -969,9 +1052,10 @@ pgs_solve_suspension :: proc(
if body.alive {
wheel_world_pos := body_local_to_world(body, v.rel_pos)
dir := body_local_to_world_vec(body, v.rel_dir)
v.hit_t, v.hit_normal, v.hit = raycast_bodies(
v.hit_t, v.hit_normal, v.hit = raycast(
sim_state,
tlas,
static_tlas,
dyn_tlas,
wheel_world_pos,
dir,
v.rest,
@ -1159,7 +1243,8 @@ pgs_solve_suspension :: proc(
pgs_substep :: proc(
sim_state: ^Sim_State,
tlas: ^Dynamic_TLAS,
static_tlas: ^Static_TLAS,
dyn_tlas: ^Dynamic_TLAS,
config: Solver_Config,
dt: f32,
inv_dt: f32,
@ -1272,7 +1357,7 @@ pgs_substep :: proc(
apply_bias := true
pgs_solve_contacts(sim_state, config, dt, inv_dt, apply_bias)
pgs_solve_engines(sim_state, config, dt, inv_dt)
pgs_solve_suspension(sim_state, tlas, config, dt, inv_dt)
pgs_solve_suspension(sim_state, static_tlas, dyn_tlas, config, dt, inv_dt)
for i in 0 ..< len(sim_state.bodies_slice) {
body := &sim_state.bodies_slice[i]
@ -1345,7 +1430,7 @@ simulate_step :: proc(scene: ^Scene, sim_state: ^Sim_State, config: Solver_Confi
}
case .PGS:
for _ in 0 ..< substeps {
pgs_substep(sim_state, &dyn_tlas, config, dt, inv_dt)
pgs_substep(sim_state, &static_tlas, &dyn_tlas, config, dt, inv_dt)
}
}