qualia_client_core/chora/layers/
mesh_gen.rs1use qualia_core_db::render::assets::Mesh;
2
3pub fn generate_sphere_mesh(segments: u32, rings: u32) -> Mesh {
4 let mut positions = Vec::new();
5 let mut triangles = Vec::new();
6
7 for r in 0..=rings {
8 let phi = std::f32::consts::PI * (r as f32) / (rings as f32);
9 let y = phi.cos();
10 let radius = phi.sin();
11 for s in 0..=segments {
12 let theta = 2.0 * std::f32::consts::PI * (s as f32) / (segments as f32);
13 let x = radius * theta.cos();
14 let z = radius * theta.sin();
15 positions.push([x, y, z]);
16 }
17 }
18
19 for r in 0..rings {
20 for s in 0..segments {
21 let a = r * (segments + 1) + s;
22 let b = a + segments + 1;
23 if r > 0 {
24 triangles.push([a, b, a + 1]);
25 }
26 if r < rings - 1 {
27 triangles.push([a + 1, b, b + 1]);
28 }
29 }
30 }
31
32 let min = [-1.0, -1.0, -1.0];
33 let max = [1.0, 1.0, 1.0];
34 Mesh {
35 positions,
36 triangles,
37 min,
38 max,
39 }
40}
41
42pub fn generate_sphere_mesh_colored(
43 segments: u32,
44 rings: u32,
45 color_sampler: impl Fn(f32, f32) -> [f32; 3],
46) -> (Vec<[f32; 3]>, Vec<[f32; 4]>, Vec<u32>) {
47 let mesh = generate_sphere_mesh(segments, rings);
48 let mut colors = Vec::with_capacity(mesh.positions.len());
49 for &p in &mesh.positions {
50 let lat = p[1].asin().to_degrees();
51 let lon = p[0].atan2(p[2]).to_degrees();
52 let [r, g, b] = color_sampler(lat, lon);
53 colors.push([r, g, b, 1.0]);
54 }
55 let indices: Vec<u32> = mesh
56 .triangles
57 .iter()
58 .flat_map(|t| [t[0], t[1], t[2]])
59 .collect();
60 (mesh.positions, colors, indices)
61}
62
63pub fn generate_starfield_mesh(positions: &[[f32; 3]], colors: &[[f32; 4]]) -> Mesh {
64 let triangles: Vec<[u32; 3]> = (0..positions.len() as u32)
65 .step_by(1)
66 .map(|i| [i, i, i])
67 .collect();
68 let _ = colors;
69 let min = [-1e6, -1e6, -1e6];
70 let max = [1e6, 1e6, 1e6];
71 Mesh {
72 positions: positions.to_vec(),
73 triangles,
74 min,
75 max,
76 }
77}
78
79pub fn generate_terrain_mesh(heightfield: &[f32], width: u32, height: u32, scale: f32) -> Mesh {
80 let mut positions = Vec::with_capacity((width * height) as usize);
81 let mut triangles = Vec::new();
82
83 for y in 0..height {
84 for x in 0..width {
85 let idx = (y * width + x) as usize;
86 let h = heightfield.get(idx).copied().unwrap_or(0.0) * scale;
87 let px = (x as f32 / width as f32 - 0.5) * 2.0;
88 let pz = (y as f32 / height as f32 - 0.5) * 2.0;
89 positions.push([px, h, pz]);
90 }
91 }
92
93 for y in 0..height - 1 {
94 for x in 0..width - 1 {
95 let a = (y * width + x) as u32;
96 let b = a + 1;
97 let c = a + width;
98 let d = c + 1;
99 triangles.push([a, c, b]);
100 triangles.push([b, c, d]);
101 }
102 }
103
104 let min = [-1.0, 0.0, -1.0];
105 let max = [1.0, scale, 1.0];
106 Mesh {
107 positions,
108 triangles,
109 min,
110 max,
111 }
112}