Files
wsg/lib/src/mesh/primitives/plane.rs
T
Jérôme Bousquié ab3f056dbb primitive meshes
2026-09-24 14:25:44 +02:00

75 lines
2.4 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! 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);
}
}