ludic/packages/ludic.physics/tests/hull_shape_test.ludic
Orkuncakilkaya f048ffb6ac ludic.physics: queries fill a record the caller keeps, and allocate nothing
phys_pose, phys_ray, phys_push and phys_walker_pose each made a new record per call, some several times a frame, and Ludic never gives one back. They now fill the caller's PhysPose / PhysHit / PhysPush / PhysWalk and return whether they found anything. phys_overlap returns a count; phys_overlap_id(i) reads each id back. The package's own uses (phys_resolve, phys_row, phys_walker_move) read the values buffer directly. Tests take small allocating helpers. physics 20, character 15, vehicles 8.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 23:18:26 +03:00

49 lines
2.1 KiB
Text

# hull_shape_test.ludic - a rock's shape: a convex hull of points, scaled for one boulder and
# turned by its yaw the way a renderer turns an instance (x' = cos x + sin z, z' = -sin x + cos z)
import "ludic.physics"
import "ludic.base"
program HullShapeTest {
numbers float
function ray(physics_st: mut PhysicsState, ox: float, oy: float, oz: float, dx: float, dy: float, dz: float, mask: int) -> PhysHit {
let h = new PhysHit
phys_ray(physics_st, ox, oy, oz, dx, dy, dz, mask, h)
return h
}
# a cube two metres across, its centre two metres along x from its origin
function cube(physics_st: mut PhysicsState) -> int {
let v = floats(8 * 3)
for i in 0 .. 8 {
v[i * 3] = 2.0 + float(i % 2) * 2.0 - 1.0
v[i * 3 + 1] = float((i / 2) % 2) * 2.0 - 1.0
v[i * 3 + 2] = float(i / 4) * 2.0 - 1.0
}
return phys_convex(physics_st, v, 8)
}
function down(physics_st: mut PhysicsState, x: float, z: float) -> PhysHit { return ray(physics_st, x, 10.0, z, 0.0, -20.0, 0.0, PHYS_M_ALL) }
test "a hull stands where its points are, and too few points are no shape" (physics_st: mut PhysicsState) {
expect(phys_open(physics_st, 16, 1))
phys_static_add(physics_st, cube(physics_st), 0.0, 0.0, 0.0, 0.0)
phys_settle(physics_st)
let h = down(physics_st, 2.0, 0.0)
expect(h.body >= 0)
expect(Math.abs(h.y - 1.0) < 0.01)
expect(down(physics_st, 0.0, 0.0).body < 0)
expect_eq(phys_convex(physics_st, floats(9), 3), -1)
phys_close(physics_st)
}
test "scaled twice as big, and turned a quarter the renderer's way" (physics_st: mut PhysicsState) {
expect(phys_open(physics_st, 16, 1))
phys_static_add(physics_st, phys_scaled(physics_st, cube(physics_st), 2.0), 0.0, 0.0, 0.0, 1.5707963)
phys_settle(physics_st)
# (4, 0, 0) turned by +90 degrees about y is (0, 0, -4): x' = cos x + sin z, z' = -sin x + cos z
let h = down(physics_st, 0.0, -4.0)
expect(h.body >= 0)
expect(Math.abs(h.y - 2.0) < 0.01)
expect(down(physics_st, 4.0, 0.0).body < 0)
expect(down(physics_st, 0.0, 4.0).body < 0)
phys_close(physics_st)
}
}