Skip to main content

molgfx_math/
types.rs

1//! Project-owned math types plus the packed color used in GPU-facing records.
2//!
3//! Everything here is plain data, byte-castable for direct GPU upload.
4
5use serde::{Deserialize, Serialize};
6
7mod matrix;
8mod vector;
9
10#[cfg(test)]
11#[path = "types_tests.rs"]
12mod tests;
13
14pub use matrix::{Mat3, Mat4, Quat};
15pub use vector::{Vec2, Vec3, Vec4};
16
17/// A color packed as four 8-bit channels, in memory order red, green, blue,
18/// alpha. Exactly four bytes, so a per-atom color column stays compact and
19/// uploads without conversion.
20#[repr(C)]
21#[derive(
22    Clone,
23    Copy,
24    PartialEq,
25    Eq,
26    Debug,
27    Default,
28    Serialize,
29    Deserialize,
30    bytemuck::Pod,
31    bytemuck::Zeroable,
32)]
33pub struct Rgba8 {
34    /// Red channel, 0–255.
35    pub r: u8,
36    /// Green channel, 0–255.
37    pub g: u8,
38    /// Blue channel, 0–255.
39    pub b: u8,
40    /// Alpha channel, 0–255; 255 is opaque.
41    pub a: u8,
42}
43
44impl Rgba8 {
45    /// Opaque white.
46    pub const WHITE: Self = Self::new(255, 255, 255, 255);
47
48    /// Builds a color from four channel values.
49    #[must_use]
50    pub const fn new(r: u8, g: u8, b: u8, a: u8) -> Self {
51        Self { r, g, b, a }
52    }
53
54    /// Builds an opaque color from three channel values.
55    #[must_use]
56    pub const fn opaque(r: u8, g: u8, b: u8) -> Self {
57        Self::new(r, g, b, 255)
58    }
59
60    /// Converts to normalized floating-point channels in [0, 1].
61    #[must_use]
62    pub fn to_f32(self) -> [f32; 4] {
63        [
64            f32::from(self.r) / 255.0,
65            f32::from(self.g) / 255.0,
66            f32::from(self.b) / 255.0,
67            f32::from(self.a) / 255.0,
68        ]
69    }
70}