makepad/libs/sim/tests/landform_world.rs
Admin 5692fabbdf sim: the landform world proves itself — walker through the tunnel included
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-01 22:15:45 +02:00

146 lines
4.7 KiB
Rust

//! Landform + tunnel + dig at world scale: the acceptance shapes of the
//! unified destructible world, meshed to completion, with hard bounds on
//! how far any mesh vertex or heightfield vertex may stand from the ground.
//! Regression net for the "floating curtain wall" class of bug.
use makepad_game_sim::voxel::DigMode;
use makepad_game_sim::*;
use makepad_math::*;
fn rolling_terrain() -> Terrain {
let cells = 97;
let cell_size = 200.0 / 96.0;
let origin = -100.0;
let mut heights = vec![0.0f32; cells * cells];
for gz in 0..cells {
for gx in 0..cells {
let x = origin + gx as f32 * cell_size;
let z = origin + gz as f32 * cell_size;
heights[gz * cells + gx] = 2.0 + (x * 0.03).sin() + (z * 0.025).cos();
}
}
Terrain {
cells,
cell_size,
origin,
heights,
colors: vec![vec4f(0.4, 0.6, 0.4, 1.0); cells * cells],
revision: 1,
}
}
#[test]
fn acceptance_shapes_stay_bounded() {
let mut w = GameWorld::new();
w.terrain = Some(rolling_terrain());
// Mirror of the live acceptance script: dig, mountain, hill, tunnel.
let g_dig = w.surface_height_at(-20.0, 10.0).unwrap();
w.apply_voxel_op(VoxelOp::Dig {
pos: vec3f(-20.0, g_dig, 10.0),
r: 6.0,
mode: DigMode::Carve,
material: 1,
});
w.apply_voxel_op(VoxelOp::Landform {
pos: vec3f(45.0, w.surface_height_at(45.0, -30.0).unwrap(), -30.0),
kind: LandKind::Mountain.to_u8(),
r: 34.0,
height: 22.0,
seed: 9,
});
w.apply_voxel_op(VoxelOp::Landform {
pos: vec3f(-55.0, w.surface_height_at(-55.0, -50.0).unwrap(), -50.0),
kind: LandKind::Hill.to_u8(),
r: 24.0,
height: 12.0,
seed: 4,
});
let my = w.surface_height_at(-55.0, -20.0).unwrap() + 1.4;
w.apply_voxel_op(VoxelOp::Tunnel {
from: vec3f(-55.0, my, -20.0),
to: vec3f(-55.0, my, -80.0),
r: 2.4,
});
// Heights stay within base + mountain reach.
let t = w.terrain.as_ref().unwrap();
let (mut hmin, mut hmax) = (f32::MAX, f32::MIN);
for h in &t.heights {
assert!(h.is_finite(), "non-finite height");
hmin = hmin.min(*h);
hmax = hmax.max(*h);
}
assert!(hmax < 28.0, "heightfield exploded: max {hmax}");
assert!(hmin > -10.0, "heightfield exploded: min {hmin}");
// Mesh everything, then every voxel mesh vertex must hug the ground
// band — no floating curtain walls in the sky.
for _ in 0..4096 {
update_world_voxel(&mut w, true);
if w.voxel.as_deref().map_or(0, |v| v.dirty_len()) == 0 {
break;
}
}
let field = w.voxel.as_deref().unwrap();
let chunks = field.chunk_count();
assert!(chunks > 0, "nothing materialized");
assert!(chunks < 400, "materialization ran away: {chunks} chunks");
let mut vmax = f32::MIN;
let mut vmin = f32::MAX;
for mesh in field.meshes.values() {
for v in mesh.verts.chunks_exact(makepad_game_sim::voxel::MESH_VERTEX_FLOATS) {
vmax = vmax.max(v[1]);
vmin = vmin.min(v[1]);
}
}
println!(
"chunks {chunks}, heights {hmin:.2}..{hmax:.2}, mesh y {vmin:.2}..{vmax:.2}"
);
assert!(vmax < 28.0, "voxel mesh towers into the sky: max y {vmax}");
assert!(vmin > -30.0, "voxel mesh under the world: min y {vmin}");
// The tunnel bore is open air mid-hill.
assert!(
field.is_carved_air(vec3f(-55.0, my, -50.0)),
"tunnel bore closed"
);
// The seam sees the mountain.
let peak = w.surface_height_at(45.0, -30.0).unwrap();
assert!(peak > 10.0, "mountain missing from the seam: {peak}");
// A walker at the mouth strolls INTO the hill through the bore — under
// the raised ground, not over it (the tunnel is the voxel layer's whole
// point).
let id = {
let mut e = Entity::default();
w.next_id += 1;
e.id = w.next_id;
e.kind = BodyKind::Mover;
e.pos = vec3f(-55.0, my + 0.1, -16.0);
e.half = vec3f(0.35, 0.85, 0.35);
e.collide = true;
let id = e.id;
w.push_entity(e);
id
};
let mouth_y = my;
for _ in 0..600 {
if let Some(e) = w.entity_mut(id) {
e.vel.x = 0.0;
e.vel.z = -3.0;
}
step_world(&mut w);
}
let e = w.entity(id).unwrap();
assert!(
e.pos.z < -30.0,
"walker never entered the tunnel (z {})",
e.pos.z
);
let hill_here = w.terrain.as_ref().unwrap().height_at(e.pos.x, e.pos.z).unwrap();
assert!(
e.pos.y < mouth_y + 2.5 && e.pos.y < hill_here - 1.0,
"walker went OVER the hill instead of through it (y {} vs hill {hill_here})",
e.pos.y
);
}