use sciforge::hub::prelude::constants::EARTH_RADIUS;
#[derive(Debug, Clone, Copy)]
pub struct Vertex {
pub position: [f64; 3],
pub normal: [f64; 3],
pub uv: [f64; 2],
pub tangent: [f64; 4],
}
pub struct TerrainMesh {
pub vertices: Vec<Vertex>,
pub indices: Vec<u32>,
}
impl TerrainMesh {
pub fn from_region(
lat_min: f64,
lat_max: f64,
lon_min: f64,
lon_max: f64,
subdivisions: u32,
elevation_fn: &dyn Fn(f64, f64) -> f64,
) -> Self {
let mut vertices = Vec::new();
let mut indices = Vec::new();
let steps = subdivisions + 1;
for j in 0..steps {
for i in 0..steps {
let u = i as f64 / subdivisions as f64;
let v = j as f64 / subdivisions as f64;
let lat = lat_min + (lat_max - lat_min) * v;
let lon = lon_min + (lon_max - lon_min) * u;
let lat_rad = lat.to_radians();
let lon_rad = lon.to_radians();
let r = EARTH_RADIUS + elevation_fn(lat, lon);
let x = r * lat_rad.cos() * lon_rad.cos();
let y = r * lat_rad.cos() * lon_rad.sin();
let z = r * lat_rad.sin();
let nx = lat_rad.cos() * lon_rad.cos();
let ny = lat_rad.cos() * lon_rad.sin();
let nz = lat_rad.sin();
let tx = -lon_rad.sin();
let ty = lon_rad.cos();
vertices.push(Vertex {
position: [x, y, z],
normal: [nx, ny, nz],
uv: [u, v],
tangent: [tx, ty, 0.0, 1.0],
});
}
}
for j in 0..subdivisions {
for i in 0..subdivisions {
let a = j * steps + i;
let b = a + 1;
let c = a + steps;
let d = c + 1;
indices.extend_from_slice(&[a, c, b, b, c, d]);
}
}
Self { vertices, indices }
}
pub fn vertex_count(&self) -> usize {
self.vertices.len()
}
pub fn triangle_count(&self) -> usize {
self.indices.len() / 3
}
}