gutter_runner/game/physics/immediate.odin

194 lines
4.7 KiB
Odin

package physics
import "core:log"
import "libs:tracy"
_ :: log
Body_Config_Inertia_Mode :: enum {
From_Shape,
Explicit,
}
immediate_body :: proc(
scene: ^Scene,
state: ^Solver_State,
id: u32,
config: Body_Config,
) -> (
handle: Body_Handle,
) {
sim_state := get_sim_state(scene)
if id in state.immedate_bodies {
body := &state.immedate_bodies[id]
if body.last_ref != state.simulation_frame {
body.last_ref = state.simulation_frame
state.num_referenced_bodies += 1
}
handle = body.handle
update_body_from_config(sim_state, get_body(sim_state, handle), config)
} else {
state.num_referenced_bodies += 1
handle = add_body(sim_state, config)
state.immedate_bodies[id] = {
handle = handle,
last_ref = state.simulation_frame,
}
}
return
}
immediate_suspension_constraint :: proc(
scene: ^Scene,
state: ^Solver_State,
id: u32,
config: Suspension_Constraint_Config,
) -> (
handle: Suspension_Constraint_Handle,
) {
if id in state.immediate_suspension_constraints {
constraint := &state.immediate_suspension_constraints[id]
if constraint.last_ref != state.simulation_frame {
constraint.last_ref = state.simulation_frame
state.num_referenced_suspension_constraints += 1
}
handle = constraint.handle
} else {
state.num_referenced_suspension_constraints += 1
handle = add_suspension_constraint(get_sim_state(scene), {})
state.immediate_suspension_constraints[id] = {
handle = handle,
last_ref = state.simulation_frame,
}
}
update_suspension_constraint_from_config(
get_suspension_constraint(get_sim_state(scene), handle),
config,
)
return
}
immediate_engine :: proc(
scene: ^Scene,
state: ^Solver_State,
id: u32,
config: Engine_Config,
) -> (
handle: Engine_Handle,
) {
sim_state := get_sim_state(scene)
if id in state.immediate_engines {
engine := &state.immediate_engines[id]
if engine.last_ref != state.simulation_frame {
engine.last_ref = state.simulation_frame
state.num_referenced_engines += 1
}
handle = engine.handle
update_engine_from_config(sim_state, get_engine(sim_state, handle), config)
} else {
state.num_referenced_engines += 1
handle = add_engine(sim_state, config)
state.immediate_engines[id] = {
handle = handle,
last_ref = state.simulation_frame,
}
}
return
}
prune_immediate :: proc(scene: ^Scene, state: ^Solver_State) {
tracy.Zone()
prune_immediate_bodies(scene, state)
prune_immediate_suspension_constraints(scene, state)
prune_immediate_engines(scene, state)
}
// TODO: Generic version
prune_immediate_bodies :: proc(scene: ^Scene, state: ^Solver_State) {
if int(state.num_referenced_bodies) == len(state.immedate_bodies) {
return
}
num_unreferenced_bodies := len(state.immedate_bodies) - int(state.num_referenced_bodies)
assert(num_unreferenced_bodies >= 0)
bodies_to_remove := make([]u32, num_unreferenced_bodies, context.temp_allocator)
i := 0
for k, &v in state.immedate_bodies {
if v.last_ref != state.simulation_frame {
bodies_to_remove[i] = k
i += 1
}
}
assert(i == len(bodies_to_remove))
for k in bodies_to_remove {
handle := state.immedate_bodies[k].handle
delete_key(&state.immedate_bodies, k)
remove_body(get_sim_state(scene), handle)
}
}
prune_immediate_suspension_constraints :: proc(scene: ^Scene, state: ^Solver_State) {
if int(state.num_referenced_suspension_constraints) ==
len(state.immediate_suspension_constraints) {
return
}
num_unreferenced_constraints :=
len(state.immediate_suspension_constraints) -
int(state.num_referenced_suspension_constraints)
assert(num_unreferenced_constraints >= 0)
constraints_to_remove := make([]u32, num_unreferenced_constraints, context.temp_allocator)
i := 0
for k, &v in state.immediate_suspension_constraints {
if v.last_ref != state.simulation_frame {
constraints_to_remove[i] = k
i += 1
}
}
assert(i == len(constraints_to_remove))
for k in constraints_to_remove {
handle := state.immediate_suspension_constraints[k].handle
delete_key(&state.immediate_suspension_constraints, k)
remove_suspension_constraint(get_sim_state(scene), handle)
}
}
prune_immediate_engines :: proc(scene: ^Scene, state: ^Solver_State) {
if int(state.num_referenced_engines) == len(state.immediate_engines) {
return
}
num_unreferenced_engines := len(state.immediate_engines) - int(state.num_referenced_engines)
assert(num_unreferenced_engines >= 0)
engines_to_remove := make([]u32, num_unreferenced_engines, context.temp_allocator)
i := 0
for k, &v in state.immediate_engines {
if v.last_ref != state.simulation_frame {
engines_to_remove[i] = k
i += 1
}
}
assert(i == len(engines_to_remove))
for k in engines_to_remove {
handle := state.immediate_engines[k].handle
delete_key(&state.immediate_engines, k)
remove_engine(get_sim_state(scene), handle)
}
}