1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
pub mod list;

use l3d::mat::Material;
pub use list::*;
use rfw_math::*;
use std::fmt::Display;

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone)]
#[repr(C)]
pub struct MaterialFlags {
    bits: u32,
}

impl Into<u32> for MaterialFlags {
    fn into(self) -> u32 {
        self.bits
    }
}

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone)]
#[repr(C)]
pub enum MaterialProps {
    HasDiffuseMap = 0,
    HasNormalMap = 1,
    HasRoughnessMap = 2,
    HasMetallicMap = 3,
    HasEmissiveMap = 4,
    HasSheenMap = 5,
}

impl Default for MaterialFlags {
    fn default() -> Self {
        Self { bits: 0 }
    }
}

impl Display for MaterialFlags {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "MaterialFlags {{ HasDiffuseMap: {}, HasNormalMap: {}, HasRoughnessMap: {}, HasMetallicMap: {}, HasEmissiveMap: {}, HasSheenMap: {} }}",
            self.get(MaterialProps::HasDiffuseMap),
            self.get(MaterialProps::HasNormalMap),
            self.get(MaterialProps::HasRoughnessMap),
            self.get(MaterialProps::HasMetallicMap),
            self.get(MaterialProps::HasEmissiveMap),
            self.get(MaterialProps::HasSheenMap),
        )
    }
}

#[allow(dead_code)]
impl MaterialFlags {
    pub fn set(&mut self, prop: MaterialProps, value: bool) {
        let offset = prop as u32;
        if value {
            let mask = 1 << offset;
            self.bits |= mask;
        } else {
            let mask = !(1 << offset);
            self.bits &= mask;
        }
    }

    pub fn get(&self, prop: MaterialProps) -> bool {
        (self.bits.overflowing_shr(prop as u32).0 & 1) == 1
    }
}

pub trait Emissive {
    fn is_emissive(&self) -> bool;
}

impl Emissive for Material {
    fn is_emissive(&self) -> bool {
        let color: Vec3A = Vec4::from(self.color).into();
        color.cmpgt(Vec3A::ONE).any()
    }
}