# shapes.ludic - the world opened and closed, and shapes: made in C, kept here, named by an int. # A shape may be used by any number of bodies; phys_close frees them all. # a world for up to max_bodies (threads 0: the cores less one, at most four); false if C refused export function phys_open(physics_st: mut PhysicsState, max_bodies: int, threads: int) -> bool { phys_close(physics_st) ph_buffers(physics_st) physics_st.ph_world = jph_world_new(max_bodies, threads) physics_st.ph_acc = 0.0 physics_st.ph_steps = 0 return physics_st.ph_world != null } export function phys_is_open(physics_st: PhysicsState) -> bool { return physics_st.ph_world != null } # everything let go: the world, every body in it and every shape (a world swap, a quit) export function phys_close(physics_st: mut PhysicsState) -> void { if physics_st.ph_world != null { jph_world_free(physics_st.ph_world) } physics_st.ph_world = null if physics_st.ph_shapes != null { for i in 0 .. len(physics_st.ph_shapes) { if physics_st.ph_shapes[i] != null { jph_shape_free(physics_st.ph_shapes[i]) } } } physics_st.ph_shapes = new []pointer physics_st.ph_floats = new []int physics_st.ph_float_k = new []float if physics_st.ph_facts != null { q_clear(physics_st.ph_facts) } } function ph_keep(physics_st: mut PhysicsState, s: pointer) -> int { if s == null { return -1 } ph_buffers(physics_st) push(physics_st.ph_shapes, s) return len(physics_st.ph_shapes) - 1 } function ph_shape(physics_st: PhysicsState, id: int) -> pointer { if physics_st.ph_shapes == null or id < 0 or id >= len(physics_st.ph_shapes) { return null } return physics_st.ph_shapes[id] } # a crate: half extents in metres export function phys_box(physics_st: mut PhysicsState, hx: float, hy: float, hz: float) -> int { return ph_keep(physics_st, jph_shape_box(hx, hy, hz)) } export function phys_sphere(physics_st: mut PhysicsState, r: float) -> int { return ph_keep(physics_st, jph_shape_sphere(r)) } # a trunk or a body: upright, its straight part 2 * half_h tall, centred on its origin export function phys_capsule(physics_st: mut PhysicsState, half_h: float, r: float) -> int { return ph_keep(physics_st, jph_shape_capsule(half_h, r)) } # a post: upright, 2 * half_h tall, centred on its origin export function phys_cylinder(physics_st: mut PhysicsState, half_h: float, r: float) -> int { return ph_keep(physics_st, jph_shape_cylinder(half_h, r)) } # a boulder: a dome r across and h tall, standing on its origin export function phys_dome(physics_st: mut PhysicsState, r: float, h: float) -> int { return ph_keep(physics_st, jph_shape_dome(r, h)) } # another shape moved and turned about y inside its body (a post whose foot is its origin) export function phys_offset(physics_st: mut PhysicsState, shape: int, x: float, y: float, z: float, yaw: float) -> int { let s = ph_shape(physics_st, shape) if s == null { return -1 } return ph_keep(physics_st, jph_shape_offset(s, x, y, z, yaw)) } # n x n heights, row by row along z, the first at (ox, oz), cell metres apart; PHYS_HOLE is none export const PHYS_HOLE: float = 340282346638528859811704183484516925440.0 export function phys_heightfield(physics_st: mut PhysicsState, h: []float, n: int, ox: float, oz: float, cell: float) -> int { if len(h) < n * n { return -1 } return ph_keep(physics_st, jph_shape_heightfield(h, n, ox, oz, cell)) } # a dock or a cabin: v holds nv points (x, y, z), tri holds nt triangles (i, j, k) export function phys_mesh(physics_st: mut PhysicsState, v: []float, nv: int, tri: []int, nt: int) -> int { if len(v) < nv * 3 or len(tri) < nt * 3 { return -1 } return ph_keep(physics_st, jph_shape_mesh(v, nv, tri, nt)) }