gutter_runner/game/physics/immediate.odin

169 lines
4.3 KiB
Odin

package physics
import rl "vendor:raylib"
// Immediate mode stuff for testing
Body_Config :: struct {
initial_pos: rl.Vector3,
initial_rot: rl.Quaternion,
initial_vel: rl.Vector3,
initial_ang_vel: rl.Vector3,
mass: f32,
// Unit inertia tensor
inertia_tensor: rl.Vector3,
}
Suspension_Constraint_Config :: struct {
rel_pos: rl.Vector3,
rel_dir: rl.Vector3,
body: Body_Handle,
rest: f32,
compliance: f32,
}
initialize_body_from_config :: proc(body: ^Body, config: Body_Config) {
body.x = config.initial_pos
body.q = config.initial_rot
body.v = config.initial_vel
body.w = config.initial_ang_vel
body.inv_mass = 1.0 / config.mass
body.inv_inertia_tensor = 1.0 / (config.inertia_tensor * config.mass)
}
update_body_from_config :: proc(body: Body_Ptr, config: Body_Config) {
body.inv_mass = 1.0 / config.mass
body.inv_inertia_tensor = 1.0 / (config.inertia_tensor * config.mass)
}
update_suspension_constraint_from_config :: proc(
constraint: Suspension_Constraint_Ptr,
config: Suspension_Constraint_Config,
) {
constraint.rel_pos = config.rel_pos
constraint.rel_dir = config.rel_dir
constraint.body = config.body
constraint.rest = config.rest
constraint.compliance = config.compliance
}
immediate_body :: proc(
scene: ^Scene,
state: ^Solver_State,
id: u32,
config: Body_Config,
) -> (
handle: Body_Handle,
) {
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
} else {
new_body: Body
state.num_referenced_bodies += 1
initialize_body_from_config(&new_body, config)
handle = add_body(scene, new_body)
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(scene, {})
state.immediate_suspension_constraints[id] = {
handle = handle,
last_ref = state.simulation_frame,
}
}
update_suspension_constraint_from_config(get_suspension_constraint(scene, handle), config)
return
}
prune_immediate :: proc(scene: ^Scene, state: ^Solver_State) {
prune_immediate_bodies(scene, state)
prune_immediate_suspension_constraints(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(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(scene, handle)
}
}