mod3d_base/
types.rs

1//a Imports
2#[cfg(feature = "serde")]
3use serde::{Deserialize, Serialize};
4
5//a Basic types
6//tp Vec3
7/// 3-dimensional vector
8pub type Vec3 = [f32; 3];
9
10//tp Vec4
11/// 3-dimensional vector with extra coord (1 for position, 0 for direction)
12pub type Vec4 = [f32; 4];
13
14//tp Mat3
15/// 3-by-3 matrix for transformation of Vec3
16pub type Mat3 = [f32; 9];
17
18//tp Mat4
19/// 4-by-4 matrix for transformation of Vec4
20pub type Mat4 = [f32; 16];
21
22//tp Quat - Quaternion
23/// Quaternion
24pub type Quat = [f32; 4];
25
26//a Buffer
27//tp BufferElementType
28/// The type of an element in a buffer
29///
30/// This deliberately does not implement Default
31#[derive(Debug, Clone, Copy, PartialEq, Eq)]
32#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
33#[repr(u8)]
34pub enum BufferElementType {
35    /// 32-bit floating point
36    Float32,
37    /// 16-bit floating point
38    Float16,
39    /// Signed 8-bit integers
40    SInt8,
41    /// Signed 16-bit integers
42    SInt16,
43    /// Signed 32-bit integers
44    SInt32,
45    /// Unsigned 8-bit integers
46    UInt8,
47    /// Unsigned 16-bit integers
48    UInt16,
49    /// Unsigned 32-bit integers
50    UInt32,
51}
52
53//ip BufferElementType
54impl BufferElementType {
55    /// Create a 16-bit float type
56    pub const fn float16() -> Self {
57        Self::Float16
58    }
59    /// Create a 32-bit float type
60    pub const fn float32() -> Self {
61        Self::Float32
62    }
63    /// Create a signed/unsigned int type
64    pub const fn new_int(signed: bool, bits: usize) -> Self {
65        match bits {
66            8 => {
67                if signed {
68                    Self::SInt8
69                } else {
70                    Self::UInt8
71                }
72            }
73            16 => {
74                if signed {
75                    Self::SInt16
76                } else {
77                    Self::UInt16
78                }
79            }
80            32 => {
81                if signed {
82                    Self::SInt32
83                } else {
84                    Self::UInt32
85                }
86            }
87            _ => {
88                panic!("An int value must be 8, 16 or 32 bits");
89            }
90        }
91    }
92
93    /// Get the length in bytes of the element type
94    pub fn byte_length(self) -> u32 {
95        use BufferElementType::*;
96        match self {
97            Float32 => 4,
98            Float16 => 2,
99            SInt8 => 1,
100            SInt16 => 2,
101            SInt32 => 4,
102            UInt8 => 1,
103            UInt16 => 2,
104            UInt32 => 4,
105        }
106    }
107}
108
109//tp VertexDesc
110/// A descriptor of the contents of one aspect of data for a Vertex;
111/// in essence a 'field' of a Vertex structure
112///
113/// Such an field is a scalar, vector, or matrix of
114/// [BufferElementType], starting at a byte offset within the parent
115/// structure, and it has a target [VertexAttr] usage
116#[derive(Clone, Copy)]
117#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
118pub struct VertexDesc {
119    /// Vertex attribute that this describes, e.g. Position, TexCoordsN, Joints
120    attr: VertexAttr,
121
122    /// Byte offset within the parent to the first element
123    byte_offset: u16,
124
125    /// Dimensions, e.g. [0, 0] for a scalar, [3,0] for a Vec3, [4,4] for a Mat4
126    dims: [u8; 2],
127
128    /// Type of each element, e.g. Float32, SInt16, UInt8
129    ele_type: BufferElementType,
130}
131
132//ip Display for VertexDesc
133impl std::fmt::Debug for VertexDesc {
134    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
135        if self.dims[0] == 0 {
136            write!(
137                fmt,
138                "VertexDesc{{{:?}: {:?} @ {}}}",
139                self.attr, self.ele_type, self.byte_offset
140            )
141        } else if self.dims[1] == 0 {
142            write!(
143                fmt,
144                "VertexDesc{{{:?}: {:?}[{}] @ {}}}",
145                self.attr, self.ele_type, self.dims[0], self.byte_offset
146            )
147        } else {
148            write!(
149                fmt,
150                "VertexDesc{{{:?}: {:?}[{}, {}] @ {}}}",
151                self.attr, self.ele_type, self.dims[0], self.dims[1], self.byte_offset
152            )
153        }
154    }
155}
156
157//ip VertexDesc
158impl VertexDesc {
159    //cp scalar
160    /// Create a scalar [VertexDescr] for a [VertexAttr] of a given
161    /// [BufferElementType], at an offset within its parent data.
162    pub fn scalar(attr: VertexAttr, ele_type: BufferElementType, byte_offset: u16) -> Self {
163        Self {
164            attr,
165            byte_offset,
166            dims: [0, 0],
167            ele_type,
168        }
169    }
170
171    //cp vec
172    /// Create a vector of 'len' [VertexDescr] for a [VertexAttr] of a given
173    /// [BufferElementType], at an offset within its parent data.
174    pub fn vec(attr: VertexAttr, ele_type: BufferElementType, len: u8, byte_offset: u16) -> Self {
175        Self {
176            attr,
177            byte_offset,
178            dims: [len, 0],
179            ele_type,
180        }
181    }
182
183    //cp mat
184    /// Create a matrix of 'dims' [VertexDescr] for a [VertexAttr] of a given
185    /// [BufferElementType], at an offset within its parent data.
186    pub fn mat(
187        attr: VertexAttr,
188        ele_type: BufferElementType,
189        dims: [u8; 2],
190        byte_offset: u16,
191    ) -> Self {
192        Self {
193            attr,
194            byte_offset,
195            dims,
196            ele_type,
197        }
198    }
199
200    //cp new
201    /// Create a new of 'dims' [VertexDescr] for a [VertexAttr] of a given
202    /// [BufferElementType], at an offset within its parent data.
203    pub fn new(
204        attr: VertexAttr,
205        ele_type: BufferElementType,
206        dims: [u8; 2],
207        byte_offset: u16,
208    ) -> Self {
209        Self {
210            attr,
211            byte_offset,
212            dims,
213            ele_type,
214        }
215    }
216
217    //ap vertex_attr
218    /// Retrieve the vertex attribute this field is for
219    #[inline]
220    pub fn vertex_attr(&self) -> VertexAttr {
221        self.attr
222    }
223
224    //ap byte_offset
225    /// Retrieve the byte_offset within the parent structure for this field
226    #[inline]
227    pub fn byte_offset(&self) -> u16 {
228        self.byte_offset
229    }
230
231    //ap dims
232    /// Retrieve the dimensions of this field - if scalar, for example, this is [0,0]
233    #[inline]
234    pub fn dims(&self) -> [u8; 2] {
235        self.dims
236    }
237
238    //ap ele_type
239    /// Retrieve the [BufferElementType] of the field
240    #[inline]
241    pub fn ele_type(&self) -> BufferElementType {
242        self.ele_type
243    }
244
245    //ap count
246    /// Get the count of the number of elements in the field
247    #[inline]
248    pub fn count(&self) -> u32 {
249        if self.dims[0] == 0 {
250            1
251        } else if self.dims[1] == 0 {
252            self.dims[0] as u32
253        } else {
254            (self.dims[0] as u32) * (self.dims[1] as u32)
255        }
256    }
257
258    //ap byte_length
259    /// Get the byte length of the field
260    pub fn byte_length(&self) -> u32 {
261        self.count() * self.ele_type.byte_length()
262    }
263}
264
265//a Drawing - VertexAttr, PrimitiveType, MaterialAspect, etc
266//tp VertexAttr
267/// A [VertexAttr] is a possible vertex attribute that can be used by
268/// a renderer; a vertex always has a position attribute, but
269/// additional attributes may or maynot be provided by a model
270#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
271#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
272#[repr(u8)]
273pub enum VertexAttr {
274    /// Position (3xf32) of the point
275    Position,
276    /// Normal (3xf32) at the point
277    Normal,
278    /// Color at the point (4xf32)
279    Color,
280    /// Tangent at the point (4xf32?)
281    Tangent,
282    /// A set of joints (n x int)
283    Joints,
284    /// Weights (n x f16?) to apply to each bone\[joint\[i\]\]
285    Weights,
286    /// Texture coordinates (2 x f32)
287    TexCoords0,
288    /// Texture coordinates (2 x f32)
289    TexCoords1,
290    /// Texture coordinates (2 x f32)
291    TexCoords2,
292}
293
294//tp PrimitiveType
295/// Type of a primitive
296///
297/// This is set to match the GLTF
298#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
299#[repr(u8)]
300pub enum PrimitiveType {
301    /// Points (of an indeterminate size?)
302    Points,
303    /// Lines (n-1) (ab, cd, ef, ...)
304    Lines,
305    /// Close loop of (n) lines (ab, cd, ef, ..., za)
306    LineLoop,
307    /// Connected (n-1) lines (ab, bc, cd, de, ...)
308    LineStrip,
309    /// Individual (n/3) triangles (one for every three indices)
310    #[default]
311    Triangles,
312    /// Strip of (n-2) triangles (abc, bcd, cde, def, ...)
313    TriangleStrip,
314    /// Fan of (n-2) triangles (abc, acd, ade, aef, ...)
315    TriangleFan,
316}
317
318//tp MaterialAspect
319/// The aspect of a material
320#[derive(Debug, Clone, Copy, PartialEq, Eq)]
321pub enum MaterialAspect {
322    /// Color (notionally RGBA as 4xf32)
323    Color,
324    /// Normal
325    Normal,
326    /// MetallicRoughness (notionally MR as 2xf32)
327    MetallicRoughness,
328    /// Occlusion (as f32)
329    Occlusion,
330    /// Emission (as f32)
331    Emission,
332}
333
334//tp ShortIndex
335/// An optional index used within the model system, that is up to 65000
336///
337/// It can be, effectively, 'None' or Some(usize less than 65000)
338///
339/// The purpose is to keep the size of indexed structures small and
340/// permit the optional aspect; it is used to index Vec of textures,
341/// vertices descriptor sets, etc
342///
343/// It has implementations of From<> to map a [usize] into a
344/// [ShortIndex], and to map from [ShortIndex] to Option<usize>; plus
345/// to map from Option<usize> (or anything that is Into<usize>) to a
346/// ShortIndex, to ease use.
347///
348/// These extra implementations remove some of the type safety one
349/// might have, but make it simpler to use the index
350#[derive(Debug, Clone, Copy, PartialEq, Eq)]
351pub struct ShortIndex(u16);
352
353//ip Default for ShortIndex
354impl std::default::Default for ShortIndex {
355    fn default() -> Self {
356        Self(65535)
357    }
358}
359
360//ip ShortIndex
361impl ShortIndex {
362    ///cp none
363    /// Create a 'None' value
364    #[inline]
365    pub fn none() -> Self {
366        Default::default()
367    }
368
369    ///ap as_usize
370    /// Return the value - if it is effectively None, then panic
371    #[inline]
372    pub fn as_usize(self) -> usize {
373        assert!(self.0 != 65535);
374        self.0 as usize
375    }
376
377    ///ap is_none
378    /// Return true if the index is None
379    #[inline]
380    pub fn is_none(self) -> bool {
381        self.0 == 65535
382    }
383
384    ///ap is_some
385    /// Return true if the index is not None
386    #[inline]
387    pub fn is_some(self) -> bool {
388        self.0 != 65535
389    }
390}
391
392//ip From<usize> for ShortIndex
393impl From<usize> for ShortIndex {
394    fn from(index: usize) -> Self {
395        assert!(index < 65535);
396        Self(index as u16)
397    }
398}
399
400//ip From<ShortIndex> for Option<usize>
401impl From<ShortIndex> for Option<usize> {
402    fn from(index: ShortIndex) -> Option<usize> {
403        if index.is_none() {
404            None
405        } else {
406            Some(index.as_usize())
407        }
408    }
409}
410
411//ip From<Option<into usize >> for ShortIndex
412impl<I: Into<usize>> From<Option<I>> for ShortIndex {
413    fn from(opt_index: Option<I>) -> Self {
414        if let Some(index) = opt_index {
415            let index: usize = index.into();
416            assert!(index < 65535);
417            Self(index as u16)
418        } else {
419            Self(65535_u16)
420        }
421    }
422}