deuxfleurs 0.1.0

Viewer for geometry processing data (surface meshes, point clouds, scalar field...)
Documentation
use crate::ui::UiDataElement;
#[cfg(feature = "saves")]
use serde::{Deserialize, Serialize};
use std::f32::consts::PI;

#[repr(C)]
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
#[cfg_attr(feature = "saves", derive(Serialize, Deserialize))]
pub struct ColorSettings {
    pub color: [f32; 4],
}

fn hash(string: &str) -> u8 {
    let mut res = 0_u32;
    for char in string.as_bytes() {
        res = (res.overflowing_shl(5).0.overflowing_sub(res).0)
            .overflowing_add(*char as u32)
            .0;
    }
    (res % 255) as u8
}

pub fn oklch_to_linear(l: f32, c: f32, h: f32, alpha: f32) -> [f32; 4] {
    let a = c * h.cos();
    let b = c * h.sin();

    let l_ = l + 0.3963377774 * a + 0.2158037573 * b;
    let m_ = l - 0.1055613458 * a - 0.0638541728 * b;
    let s_ = l - 0.0894841775 * a - 1.2914855480 * b;

    let l = l_ * l_ * l_;
    let m = m_ * m_ * m_;
    let s = s_ * s_ * s_;

    [
        4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,
        -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,
        -0.0041960863 * l - 0.7034186147 * m + 1.7076147010 * s,
        alpha,
    ]
}

impl ColorSettings {
    pub fn new(name: &str) -> Self {
        let hash = hash(name);
        Self {
            color: oklch_to_linear(0.6459, 0.1413, (hash as f32) / 256. * 2. * PI, 1.),
        }
    }
}

impl Default for ColorSettings {
    fn default() -> Self {
        Self {
            color: [0.2, 0.2, 0.8, 1.],
        }
    }
}

impl UiDataElement for ColorSettings {
    fn draw_ui(&mut self, ui: &mut egui::Ui) -> bool {
        let mut mesh_color = egui::Rgba::from_rgba_unmultiplied(
            self.color[0],
            self.color[1],
            self.color[2],
            self.color[3],
        );
        let mut changed = false;
        ui.horizontal(|ui| {
            changed = egui::widgets::color_picker::color_edit_button_rgba(
                ui,
                &mut mesh_color,
                egui::widgets::color_picker::Alpha::Opaque,
            )
            .changed();
        });
        self.color = mesh_color.to_array();
        changed
    }
}