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>
This commit is contained in:
parent
b6c4d703a2
commit
f048ffb6ac
11 changed files with 140 additions and 87 deletions
|
|
@ -4,6 +4,11 @@ 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 {
|
||||
|
|
@ -15,7 +20,7 @@ program HullShapeTest {
|
|||
}
|
||||
return phys_convex(physics_st, v, 8)
|
||||
}
|
||||
function down(physics_st: mut PhysicsState, x: float, z: float) -> PhysHit { return phys_ray(physics_st, x, 10.0, z, 0.0, -20.0, 0.0, PHYS_M_ALL) }
|
||||
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))
|
||||
|
|
|
|||
|
|
@ -5,6 +5,11 @@ import "ludic.physics"
|
|||
import "ludic.base"
|
||||
program MotionTest {
|
||||
numbers float
|
||||
function pose(physics_st: mut PhysicsState, id: int) -> PhysPose {
|
||||
let p = new PhysPose
|
||||
if not phys_pose(physics_st, id, p) { return null }
|
||||
return p
|
||||
}
|
||||
|
||||
function lake_h(x: float, z: float) -> float {
|
||||
if x > 20.0 { return 0.0 }
|
||||
|
|
@ -45,7 +50,7 @@ program MotionTest {
|
|||
let crate = phys_body_add(physics_st, phys_box(physics_st, 0.5, 0.25, 0.5), 30.0, 2.0, 0.0, 0.0, 60.0)
|
||||
phys_float(physics_st, crate, 1.2, 2.0, 2.0)
|
||||
sim(physics_st, 8.0)
|
||||
let p = phys_pose(physics_st, crate)
|
||||
let p = pose(physics_st, crate)
|
||||
expect(p.y > -0.4)
|
||||
expect(p.y < 0.4)
|
||||
expect(Math.abs(p.vy) < 0.2)
|
||||
|
|
@ -55,7 +60,7 @@ program MotionTest {
|
|||
phys_sink(physics_st, crate)
|
||||
expect(not phys_floating(physics_st, crate))
|
||||
sim(physics_st, 4.0)
|
||||
expect(phys_pose(physics_st, crate).y < -2.5)
|
||||
expect(pose(physics_st, crate).y < -2.5)
|
||||
phys_close(physics_st)
|
||||
}
|
||||
|
||||
|
|
@ -87,7 +92,7 @@ program MotionTest {
|
|||
phys_set_kinematic_target(physics_st, me, 2.0 + float(i + 1) * 0.03, 0.95, 0.0, 0.0)
|
||||
phys_step(physics_st)
|
||||
}
|
||||
expect(phys_pose(physics_st, crate).x > 5.0)
|
||||
expect(pose(physics_st, crate).x > 5.0)
|
||||
phys_close(physics_st)
|
||||
}
|
||||
|
||||
|
|
@ -114,7 +119,7 @@ program MotionTest {
|
|||
for i in 0 .. 12 { last = phys_body_add(physics_st, b, 3.0 + float(i % 3) * 0.3, 2.0 + float(i) * 0.7, float(i % 2) * 0.2, float(i) * 0.4, 8.0) }
|
||||
phys_impulse(physics_st, last, 20.0, 0.0, 5.0)
|
||||
sim(physics_st, 4.0)
|
||||
let p = phys_pose(physics_st, last)
|
||||
let p = pose(physics_st, last)
|
||||
phys_close(physics_st)
|
||||
return p
|
||||
}
|
||||
|
|
@ -132,21 +137,21 @@ program MotionTest {
|
|||
world(physics_st)
|
||||
let b = phys_hull_add(physics_st, 40.0, 0.5, 0.0, 1.5707963, 0.6, 0.25, 1.9, 180.0, 4.0, 1.0)
|
||||
sim(physics_st, 4.0)
|
||||
let p0 = phys_pose(physics_st, b)
|
||||
let p0 = pose(physics_st, b)
|
||||
expect(p0.y > -0.2)
|
||||
expect(p0.y < 0.2)
|
||||
for i in 0 .. 240 {
|
||||
phys_row(physics_st, b, 420.0, 0.0)
|
||||
phys_step(physics_st)
|
||||
}
|
||||
let p1 = phys_pose(physics_st, b)
|
||||
let p1 = pose(physics_st, b)
|
||||
expect(p1.x < 34.0)
|
||||
expect(phys_bow_speed(p1) > 1.0)
|
||||
for i in 0 .. 120 {
|
||||
phys_row(physics_st, b, 0.0, 520.0)
|
||||
phys_step(physics_st)
|
||||
}
|
||||
expect(Math.abs(phys_yaw_of(phys_pose(physics_st, b)) - phys_yaw_of(p1)) > 0.5)
|
||||
expect(Math.abs(phys_yaw_of(pose(physics_st, b)) - phys_yaw_of(p1)) > 0.5)
|
||||
phys_close(physics_st)
|
||||
world(physics_st)
|
||||
let c = phys_hull_add(physics_st, 24.0, 0.5, 0.0, 1.5707963, 0.6, 0.25, 1.9, 180.0, 4.0, 1.0)
|
||||
|
|
@ -154,7 +159,7 @@ program MotionTest {
|
|||
phys_row(physics_st, c, 420.0, 0.0)
|
||||
phys_step(physics_st)
|
||||
}
|
||||
expect(phys_pose(physics_st, c).x > 19.5)
|
||||
expect(pose(physics_st, c).x > 19.5)
|
||||
phys_close(physics_st)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,21 @@ import "ludic.physics"
|
|||
import "ludic.base"
|
||||
program PhysicsTest {
|
||||
numbers float
|
||||
function pose(physics_st: mut PhysicsState, id: int) -> PhysPose {
|
||||
let p = new PhysPose
|
||||
if not phys_pose(physics_st, id, p) { return null }
|
||||
return p
|
||||
}
|
||||
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
|
||||
}
|
||||
function push_of(physics_st: mut PhysicsState, x: float, z: float, r: float, y0: float, y1: float, mask: int) -> PhysPush {
|
||||
let p = new PhysPush
|
||||
phys_push(physics_st, x, z, r, y0, y1, mask, p)
|
||||
return p
|
||||
}
|
||||
|
||||
# the lake: everything east of x = 20, its surface at y = 0, drifting north at 0.5 m/s
|
||||
function lake_h(x: float, z: float) -> float {
|
||||
|
|
@ -38,15 +53,15 @@ program PhysicsTest {
|
|||
let id = phys_body_add(physics_st, b, 0.0, 4.0, 0.0, 0.0, 20.0)
|
||||
expect(id != -1)
|
||||
sim(physics_st, 3.0)
|
||||
let p = phys_pose(physics_st, id)
|
||||
let p = pose(physics_st, id)
|
||||
expect(p != null)
|
||||
expect(Math.abs(p.y - 0.5) < 0.05)
|
||||
expect(Math.abs(p.vy) < 0.05)
|
||||
let h = phys_ray(physics_st, 0.0, 10.0, 0.0, 0.0, -20.0, 0.0, PHYS_M_ALL)
|
||||
let h = ray(physics_st, 0.0, 10.0, 0.0, 0.0, -20.0, 0.0, PHYS_M_ALL)
|
||||
expect_eq(h.body, id)
|
||||
expect(Math.abs(h.y - 1.0) < 0.05)
|
||||
expect(h.ny > 0.9)
|
||||
let g = phys_ray(physics_st, 5.0, 10.0, 5.0, 0.0, -20.0, 0.0, PHYS_M_ALL)
|
||||
let g = ray(physics_st, 5.0, 10.0, 5.0, 0.0, -20.0, 0.0, PHYS_M_ALL)
|
||||
expect(g.body != -1)
|
||||
expect(g.body != id)
|
||||
expect(Math.abs(g.y) < 0.01)
|
||||
|
|
@ -59,14 +74,13 @@ program PhysicsTest {
|
|||
let id = phys_static_add(physics_st, post, 2.0, 0.0, 2.0, 0.0)
|
||||
phys_settle(physics_st)
|
||||
let n = phys_count(physics_st)
|
||||
let near = phys_overlap(physics_st, 2.0, 1.0, 2.0, 0.5, PHYS_M_STATIC)
|
||||
expect_eq(len(near), 1)
|
||||
expect_eq(near[0], id)
|
||||
expect_eq(len(phys_overlap(physics_st, 2.0, 1.0, 2.0, 0.5, PHYS_M_GROUND)), 0)
|
||||
expect_eq(phys_overlap(physics_st, 2.0, 1.0, 2.0, 0.5, PHYS_M_STATIC), 1)
|
||||
expect_eq(phys_overlap_id(physics_st, 0), id)
|
||||
expect_eq(phys_overlap(physics_st, 2.0, 1.0, 2.0, 0.5, PHYS_M_GROUND), 0)
|
||||
phys_remove(physics_st, id)
|
||||
expect_eq(phys_count(physics_st), n - 1)
|
||||
expect_eq(len(phys_overlap(physics_st, 2.0, 1.0, 2.0, 0.5, PHYS_M_STATIC)), 0)
|
||||
expect(phys_pose(physics_st, id) == null)
|
||||
expect_eq(phys_overlap(physics_st, 2.0, 1.0, 2.0, 0.5, PHYS_M_STATIC), 0)
|
||||
expect(pose(physics_st, id) == null)
|
||||
phys_close(physics_st)
|
||||
}
|
||||
|
||||
|
|
@ -86,11 +100,11 @@ program PhysicsTest {
|
|||
let post = phys_offset(physics_st, phys_cylinder(physics_st, 1.0, 0.3), 0.0, 1.0, 0.0, 0.0)
|
||||
phys_static_add(physics_st, post, 0.0, 0.0, 0.0, 0.0)
|
||||
phys_settle(physics_st)
|
||||
let p = phys_push(physics_st, 0.5, 0.0, 0.4, 0.1, 1.8, PHYS_M_STATIC)
|
||||
let p = push_of(physics_st, 0.5, 0.0, 0.4, 0.1, 1.8, PHYS_M_STATIC)
|
||||
expect_eq(p.n, 1)
|
||||
expect(p.x > 0.1)
|
||||
expect(Math.abs(p.z) < 0.05)
|
||||
let clear = phys_push(physics_st, 3.0, 0.0, 0.4, 0.1, 1.8, PHYS_M_STATIC)
|
||||
let clear = push_of(physics_st, 3.0, 0.0, 0.4, 0.1, 1.8, PHYS_M_STATIC)
|
||||
expect_eq(clear.n, 0)
|
||||
phys_close(physics_st)
|
||||
}
|
||||
|
|
@ -141,8 +155,8 @@ program PhysicsTest {
|
|||
expect(g >= 0)
|
||||
phys_ground_add(physics_st, g)
|
||||
phys_settle(physics_st)
|
||||
let odd = phys_ray(physics_st, 5.5, 50.0, 10.5, 0.0, -100.0, 0.0, PHYS_M_GROUND)
|
||||
let even = phys_ray(physics_st, 6.5, 50.0, 10.5, 0.0, -100.0, 0.0, PHYS_M_GROUND)
|
||||
let odd = ray(physics_st, 5.5, 50.0, 10.5, 0.0, -100.0, 0.0, PHYS_M_GROUND)
|
||||
let even = ray(physics_st, 6.5, 50.0, 10.5, 0.0, -100.0, 0.0, PHYS_M_GROUND)
|
||||
expect(Math.abs(odd.y - 2.0) < 0.01)
|
||||
expect(Math.abs(even.y - 1.0) < 0.01)
|
||||
phys_close(physics_st)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,16 @@ import "ludic.physics"
|
|||
import "ludic.base"
|
||||
program WalkerTest {
|
||||
numbers float
|
||||
function pose(physics_st: mut PhysicsState, id: int) -> PhysPose {
|
||||
let p = new PhysPose
|
||||
if not phys_pose(physics_st, id, p) { return null }
|
||||
return p
|
||||
}
|
||||
function wpose(physics_st: mut PhysicsState, id: int) -> PhysWalk {
|
||||
let p = new PhysWalk
|
||||
if not phys_walker_pose(physics_st, id, p) { return null }
|
||||
return p
|
||||
}
|
||||
|
||||
function flat(physics_st: mut PhysicsState) -> void {
|
||||
expect(phys_open(physics_st, 1024, 1))
|
||||
|
|
@ -20,11 +30,11 @@ program WalkerTest {
|
|||
flat(physics_st)
|
||||
let me = phys_walker_add(physics_st, 0.35, 1.8, 0.0, 1.0, 0.0, 50.0, 70.0)
|
||||
walk(physics_st, me, 1.0, 0.0, 0.0)
|
||||
let p = phys_walker_pose(physics_st, me)
|
||||
let p = wpose(physics_st, me)
|
||||
expect_eq(p.ground, PHYS_ON_GROUND)
|
||||
expect(Math.abs(p.y) < 0.05)
|
||||
walk(physics_st, me, 2.0, 3.0, 0.0)
|
||||
let q = phys_walker_pose(physics_st, me)
|
||||
let q = wpose(physics_st, me)
|
||||
expect(Math.abs(q.x - 6.0) < 0.2)
|
||||
expect(q.body >= 0)
|
||||
phys_close(physics_st)
|
||||
|
|
@ -40,12 +50,12 @@ program WalkerTest {
|
|||
let a = phys_walker_add(physics_st, 0.35, 1.8, 0.0, 0.0, 0.0, 50.0, 70.0)
|
||||
phys_walker_limits(physics_st, a, 0.55, 0.5, 50.0)
|
||||
walk(physics_st, a, 1.5, 2.0, 0.0)
|
||||
let pa = phys_walker_pose(physics_st, a)
|
||||
let pa = wpose(physics_st, a)
|
||||
expect(pa.x > 2.5)
|
||||
expect(Math.abs(pa.y - 0.3) < 0.05)
|
||||
let b = phys_walker_add(physics_st, 0.35, 1.8, 0.0, 0.0, 10.0, 50.0, 70.0)
|
||||
walk(physics_st, b, 2.0, 2.0, 0.0)
|
||||
let pb = phys_walker_pose(physics_st, b)
|
||||
let pb = wpose(physics_st, b)
|
||||
expect(pb.x < 1.7)
|
||||
expect(Math.abs(pb.y) < 0.05)
|
||||
phys_close(physics_st)
|
||||
|
|
@ -57,11 +67,11 @@ program WalkerTest {
|
|||
walk(physics_st, me, 0.5, 0.0, 0.0)
|
||||
phys_walker_step(physics_st, me, 1.0 / 60.0, 0.0, 0.0, 5.0)
|
||||
walk(physics_st, me, 0.25, 0.0, 0.0)
|
||||
let up = phys_walker_pose(physics_st, me)
|
||||
let up = wpose(physics_st, me)
|
||||
expect_eq(up.ground, PHYS_IN_AIR)
|
||||
expect(up.y > 0.5)
|
||||
walk(physics_st, me, 1.5, 0.0, 0.0)
|
||||
let down = phys_walker_pose(physics_st, me)
|
||||
let down = wpose(physics_st, me)
|
||||
expect_eq(down.ground, PHYS_ON_GROUND)
|
||||
expect(Math.abs(down.y) < 0.05)
|
||||
phys_close(physics_st)
|
||||
|
|
@ -75,12 +85,12 @@ program WalkerTest {
|
|||
phys_walker_step(physics_st, me, 1.0 / 60.0, 2.0, 0.0, 0.0)
|
||||
phys_step(physics_st)
|
||||
}
|
||||
expect(phys_pose(physics_st, crate).x > 2.5)
|
||||
expect(pose(physics_st, crate).x > 2.5)
|
||||
phys_walker_place(physics_st, me, -10.0, 0.0, -10.0)
|
||||
let p = phys_walker_pose(physics_st, me)
|
||||
let p = wpose(physics_st, me)
|
||||
expect(Math.abs(p.x + 10.0) < 0.01)
|
||||
phys_walker_remove(physics_st, me)
|
||||
expect(phys_walker_pose(physics_st, me) == null)
|
||||
expect(wpose(physics_st, me) == null)
|
||||
phys_close(physics_st)
|
||||
}
|
||||
|
||||
|
|
@ -94,11 +104,11 @@ program WalkerTest {
|
|||
phys_step(physics_st)
|
||||
}
|
||||
expect(phys_spin_y(physics_st, hull) > 0.1)
|
||||
expect(phys_pose(physics_st, hull).z > 0.5)
|
||||
let p = phys_pose(physics_st, hull)
|
||||
expect(pose(physics_st, hull).z > 0.5)
|
||||
let p = pose(physics_st, hull)
|
||||
p.x = 5.0
|
||||
phys_set_pose(physics_st, hull, p)
|
||||
expect(Math.abs(phys_pose(physics_st, hull).x - 5.0) < 0.01)
|
||||
expect(Math.abs(pose(physics_st, hull).x - 5.0) < 0.01)
|
||||
phys_close(physics_st)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue