diff --git a/all-is-cubes/build.rs b/all-is-cubes/build.rs index dfc5b186d..38e062028 100644 --- a/all-is-cubes/build.rs +++ b/all-is-cubes/build.rs @@ -147,14 +147,7 @@ mod chart_schema { let face_cosines = face_cosines.map(|_, cosine| (cosine * 255.0).round() as u8); Self { direction: direction.map(TargetEndian::from).into(), - face_cosines: [ - face_cosines.nx, - face_cosines.ny, - face_cosines.nz, - face_cosines.px, - face_cosines.py, - face_cosines.pz, - ], + face_cosines: face_cosines.into(), _padding: [0; 2], } } diff --git a/all-is-cubes/src/space/light/chart/local.rs b/all-is-cubes/src/space/light/chart/local.rs index f267969ae..1daf01dd6 100644 --- a/all-is-cubes/src/space/light/chart/local.rs +++ b/all-is-cubes/src/space/light/chart/local.rs @@ -6,16 +6,7 @@ use crate::space::light::chart; impl chart::OneRay { pub fn face_cosines(&self) -> FaceMap { - let [nx, ny, nz, px, py, pz] = self.face_cosines; - FaceMap { - nx, - ny, - nz, - px, - py, - pz, - } - .map(|_, byte| f32::from(byte) / 255.0f32) + FaceMap::from(self.face_cosines).map(|_, byte| f32::from(byte) / 255.0f32) } } diff --git a/all-is-cubes/src/space/light/chart/shared.rs b/all-is-cubes/src/space/light/chart/shared.rs index 585f7f3bf..d1e2f8329 100644 --- a/all-is-cubes/src/space/light/chart/shared.rs +++ b/all-is-cubes/src/space/light/chart/shared.rs @@ -4,7 +4,7 @@ //! This is the most efficient way I could think of to store and transfer the //! pre-computed light ray chart data. -use all_is_cubes_base::math::Face7; +use all_is_cubes_base::math::{Face7, FaceMap}; // conditionally defined to be equal to f32 except in the build script use super::TargetEndian; @@ -19,7 +19,7 @@ pub(crate) struct OneRay { /// `FaceMap` data which stores the cosine (rescaled to 0-255) /// between each face normal and this ray. - pub face_cosines: [u8; 6], + pub face_cosines: PodFaceMap, /// Guaranteed zero padding to make up a multiple of 4 bytes. pub _padding: [u8; 2], @@ -106,6 +106,33 @@ impl From for Face7Safe { } } +/// Variant of [`FaceMap`] that can implement `bytemuck::Pod` because it is `repr(packed)`. +/// (The regular `FaceMap` could too, *unsafely*, but I don't want to do that unsafe yet.) +#[derive(Clone, Copy, Debug, bytemuck::Pod, bytemuck::Zeroable)] +#[repr(C, packed)] +pub(crate) struct PodFaceMap { + nx: T, + ny: T, + nz: T, + pz: T, + py: T, + px: T, +} +impl From> for PodFaceMap { + #[rustfmt::skip] + fn from(value: FaceMap) -> Self { + let FaceMap { nx, ny, nz, px, py, pz } = value; + Self { nx, ny, nz, pz, py, px } + } +} +impl From> for FaceMap { + #[rustfmt::skip] + fn from(value: PodFaceMap) -> Self { + let PodFaceMap { nx, ny, nz, pz, py, px } = value; + FaceMap { nx, ny, nz, px, py, pz } + } +} + // Note: Most of the methods are either only used for reading or only used for writing, // so they're defined in the respective crates to reduce complications like what they depend on, // how `TargetEndian` is defined, and dead code warnings.