pub use ndshape;
use ndshape::Shape;
#[derive(Default)]
pub struct HeightMeshBuffer {
pub positions: Vec<[f32; 3]>,
pub normals: Vec<[f32; 3]>,
pub indices: Vec<u32>,
pub stride_to_index: Vec<u32>,
}
impl HeightMeshBuffer {
pub fn reset(&mut self, array_size: usize) {
self.positions.clear();
self.normals.clear();
self.indices.clear();
self.stride_to_index.resize(array_size, 0);
}
}
pub fn height_mesh<S: Shape<u32, 2>>(
height_map: &[f32],
map_shape: &S,
min: [u32; 2],
max: [u32; 2],
output: &mut HeightMeshBuffer,
) {
assert!((map_shape.linearize(min) as usize) < height_map.len());
assert!((map_shape.linearize(max) as usize) < height_map.len());
output.reset(height_map.len());
let [minx, miny] = min;
let [maxx, maxy] = max;
let iminx = minx + 1;
let iminy = miny + 1;
let imaxx = maxx - 1;
let imaxy = maxy - 1;
let x_stride = map_shape.linearize([1, 0]);
let y_stride = map_shape.linearize([0, 1]);
for z in iminy..=imaxy {
for x in iminx..=imaxx {
let stride = map_shape.linearize([x, z]);
let y = height_map[stride as usize];
output.stride_to_index[stride as usize] = output.positions.len() as u32;
output.positions.push([x as f32, y, z as f32]);
let l_stride = stride - x_stride;
let r_stride = stride + x_stride;
let b_stride = stride - y_stride;
let t_stride = stride + y_stride;
let l_y = unsafe { height_map.get_unchecked(l_stride as usize) };
let r_y = unsafe { height_map.get_unchecked(r_stride as usize) };
let b_y = unsafe { height_map.get_unchecked(b_stride as usize) };
let t_y = unsafe { height_map.get_unchecked(t_stride as usize) };
let dy_dx = (r_y - l_y) / 2.0;
let dy_dz = (t_y - b_y) / 2.0;
output.normals.push([-dy_dx, 1.0, -dy_dz]);
}
}
let imaxx = imaxx - 1;
let imaxy = imaxy - 1;
for z in iminy..=imaxy {
for x in iminx..=imaxx {
let bl_stride = map_shape.linearize([x, z]);
let br_stride = bl_stride + x_stride;
let tl_stride = bl_stride + y_stride;
let tr_stride = bl_stride + x_stride + y_stride;
let bl_index = output.stride_to_index[bl_stride as usize];
let br_index = output.stride_to_index[br_stride as usize];
let tl_index = output.stride_to_index[tl_stride as usize];
let tr_index = output.stride_to_index[tr_stride as usize];
output
.indices
.extend_from_slice(&[bl_index, tl_index, tr_index, bl_index, tr_index, br_index]);
}
}
}