use alloc::vec::Vec;
use super::Vert;
type SkyboxFace = (
[f32; 3],
[f32; 3],
[f32; 3],
[f32; 3],
[f32; 3],
[[f32; 2]; 4],
);
pub fn build_skybox(size: f32) -> (Vec<Vert>, Vec<u16>) {
let s = size;
let color = [1.0f32, 1.0, 2.0];
let mut verts: Vec<Vert> = Vec::new();
let mut idxs: Vec<u16> = Vec::new();
let faces: &[SkyboxFace] = &[
(
[-s, s, s],
[-s, s, -s],
[s, s, -s],
[s, s, s],
[0.0, -1.0, 0.0],
[[0.0, 0.0], [0.0, 1.0], [1.0, 1.0], [1.0, 0.0]],
),
(
[-s, -s, -s],
[-s, -s, s],
[s, -s, s],
[s, -s, -s],
[0.0, 1.0, 0.0],
[[0.0, 0.0], [0.0, 1.0], [1.0, 1.0], [1.0, 0.0]],
),
(
[s, -s, s],
[-s, -s, s],
[-s, s, s],
[s, s, s],
[0.0, 0.0, -1.0],
[[0.0, 1.0], [1.0, 1.0], [1.0, 0.0], [0.0, 0.0]],
),
(
[-s, -s, -s],
[s, -s, -s],
[s, s, -s],
[-s, s, -s],
[0.0, 0.0, 1.0],
[[0.0, 1.0], [1.0, 1.0], [1.0, 0.0], [0.0, 0.0]],
),
(
[s, -s, -s],
[s, -s, s],
[s, s, s],
[s, s, -s],
[-1.0, 0.0, 0.0],
[[0.0, 1.0], [1.0, 1.0], [1.0, 0.0], [0.0, 0.0]],
),
(
[-s, -s, s],
[-s, -s, -s],
[-s, s, -s],
[-s, s, s],
[1.0, 0.0, 0.0],
[[0.0, 1.0], [1.0, 1.0], [1.0, 0.0], [0.0, 0.0]],
),
];
for (a, b, c, d, normal, uvs) in faces {
let base = verts.len() as u16;
verts.extend_from_slice(&[
(*a, *normal, color, uvs[0]),
(*b, *normal, color, uvs[1]),
(*c, *normal, color, uvs[2]),
(*d, *normal, color, uvs[3]),
]);
idxs.extend_from_slice(&[base, base + 1, base + 2, base + 2, base + 3, base]);
}
(verts, idxs)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn skybox_is_six_quads_at_the_requested_half_extent() {
let (verts, idxs) = build_skybox(490.0);
assert_eq!(verts.len(), 6 * 4);
assert_eq!(idxs.len(), 6 * 6);
assert!(idxs.iter().all(|&i| (i as usize) < verts.len()));
for (pos, ..) in &verts {
for axis in pos {
assert_eq!(axis.abs(), 490.0, "corner off the cube: {pos:?}");
}
}
}
#[test]
fn skybox_normals_face_the_interior() {
let (verts, _) = build_skybox(4.0);
for (pos, normal, ..) in &verts {
let dot = pos[0] * normal[0] + pos[1] * normal[1] + pos[2] * normal[2];
assert_eq!(dot, -4.0, "normal {normal:?} is not inward at {pos:?}");
}
}
#[test]
fn skybox_vertex_colour_flags_sky_with_an_out_of_range_blue() {
let (verts, _) = build_skybox(1.0);
assert!(
verts
.iter()
.all(|(_, _, color, _)| *color == [1.0, 1.0, 2.0])
);
}
}