primitive meshes

This commit is contained in:
Jérôme Bousquié
2026-09-24 14:25:44 +02:00
parent 805babe53d
commit ab3f056dbb
36 changed files with 1531 additions and 808 deletions
+74
View File
@@ -0,0 +1,74 @@
//! Plane primitive — horizontal plane in XZ with subdivisions.
use crate::core::geometry::Geometry;
/// Generates a horizontal plane in the XZ plane (normal +Y), centered at (0, 0, 0), with
/// `width` × `depth` dimensions, subdivided into `seg_x` × `seg_z` cells.
pub fn plane(width: f32, depth: f32, seg_x: u32, seg_z: u32) -> Geometry {
let sx = seg_x.max(1);
let sz = seg_z.max(1);
let (mut positions, mut normals, mut uvs, mut indices) = (
Vec::<[f32; 3]>::new(),
Vec::<[f32; 3]>::new(),
Vec::<[f32; 2]>::new(),
Vec::<u16>::new(),
);
for z in 0..=sz {
let vz = z as f32 / sz as f32;
for x in 0..=sx {
let vx = x as f32 / sx as f32;
positions.push([(vx - 0.5) * width, 0.0, (vz - 0.5) * depth]);
normals.push([0.0, 1.0, 0.0]);
uvs.push([vx, vz]);
}
}
for z in 0..sz {
for x in 0..sx {
let a = z * (sx + 1) + x;
let b = a + 1;
let c = (z + 1) * (sx + 1) + x;
let d = c + 1;
indices
.extend_from_slice(&[a as u16, c as u16, b as u16, b as u16, c as u16, d as u16]);
}
}
Geometry::new(positions)
.with_normals(normals)
.with_uvs(uvs)
.with_indices(indices)
}
#[cfg(test)]
mod tests {
use super::*;
use glam::Vec3;
fn assert_valid(geo: &Geometry) {
geo.validate().expect("generated geometry must validate");
let positions = &geo.positions;
let normals = geo.normals.as_ref().expect("normals present");
let uvs = geo.uvs.as_ref().expect("uvs present");
let indices = geo.indices.as_ref().expect("indices present");
assert_eq!(normals.len(), positions.len());
assert_eq!(uvs.len(), positions.len());
for n in normals {
let len = Vec3::from_array(*n).length();
assert!((len - 1.0).abs() < 1e-3);
}
for &i in indices {
assert!((i as usize) < positions.len());
}
}
#[test]
fn plane_counts() {
let g = plane(2.0, 3.0, 1, 1);
assert_eq!(g.positions.len(), 4);
assert_eq!(g.indices.as_ref().unwrap().len(), 6);
assert_valid(&g);
assert!(g.positions.iter().all(|p| p[1] == 0.0));
let g2 = plane(2.0, 3.0, 4, 5);
assert_eq!(g2.positions.len(), (4 + 1) * (5 + 1));
assert_valid(&g2);
}
}