qualia_core_db/domains/geospatial/
dem.rs1#[derive(Debug, Clone)]
2pub struct TerrainMesh {
3 pub vertices: Vec<[f32; 3]>,
4 pub indices: Vec<u32>,
5}
6
7pub fn generate_terrain_mesh(
11 heightfield: &[f32],
12 width: usize,
13 height: usize,
14 cell_size: f64,
15) -> TerrainMesh {
16 assert_eq!(
17 heightfield.len(),
18 width * height,
19 "Heightfield length must match width * height"
20 );
21
22 let mut vertices = Vec::with_capacity(width * height);
23 let mut indices = Vec::with_capacity((width - 1) * (height - 1) * 6);
24
25 let offset_x = (width as f64 * cell_size) / 2.0;
27 let offset_y = (height as f64 * cell_size) / 2.0;
28
29 for y in 0..height {
30 for x in 0..width {
31 let px = (x as f64 * cell_size) - offset_x;
32 let py = (y as f64 * cell_size) - offset_y;
33 let pz = heightfield[y * width + x] as f64;
34 vertices.push([px as f32, py as f32, pz as f32]);
35 }
36 }
37
38 for y in 0..(height - 1) {
39 for x in 0..(width - 1) {
40 let i0 = (y * width + x) as u32;
41 let i1 = i0 + 1;
42 let i2 = ((y + 1) * width + x) as u32;
43 let i3 = i2 + 1;
44
45 indices.push(i0);
47 indices.push(i2);
48 indices.push(i1);
49
50 indices.push(i1);
52 indices.push(i2);
53 indices.push(i3);
54 }
55 }
56
57 TerrainMesh { vertices, indices }
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63
64 #[test]
65 fn test_generate_terrain_mesh() {
66 let width = 3;
67 let height = 3;
68 let heights = vec![0.0, 1.0, 0.0, 1.0, 2.0, 1.0, 0.0, 1.0, 0.0];
69
70 let mesh = generate_terrain_mesh(&heights, width, height, 10.0);
71
72 assert_eq!(mesh.vertices.len(), 9);
73 assert_eq!(mesh.indices.len(), 24);
75
76 assert_eq!(mesh.vertices[4][2], 2.0);
78 }
79}