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}