1use std::{fmt, path::PathBuf};
2
3pub(crate) type Vec2 = [f32; 2];
4pub(crate) type Vec3 = [f32; 3];
5pub(crate) type Face = [u32; 3];
6pub(crate) type Color4 = [f32; 4];
7
8pub(crate) const MAX_NUMBER_OF_TEXCOORDS: usize = 2;
10pub(crate) const MAX_NUMBER_OF_COLOR_SETS: usize = 2;
12
13#[derive(Debug, Clone, Default)]
14#[non_exhaustive]
15pub struct Scene {
16 pub materials: Vec<Material>,
17 pub meshes: Vec<Mesh>,
18}
19
20#[derive(Clone, Default)]
22#[non_exhaustive]
23pub struct Mesh {
24 pub name: String,
25 pub vertices: Vec<Vec3>,
26 pub texcoords: [Vec<Vec2>; MAX_NUMBER_OF_TEXCOORDS],
28 pub normals: Vec<Vec3>,
29 pub faces: Vec<Face>,
30 pub colors: [Vec<Color4>; MAX_NUMBER_OF_COLOR_SETS],
31 #[cfg(feature = "obj")]
32 pub(crate) material_index: u32,
33}
34
35impl Mesh {
36 #[inline]
37 #[must_use]
38 pub fn merge(mut meshes: Vec<Self>) -> Self {
39 if meshes.len() <= 1 {
40 return meshes.pop().unwrap_or_default();
41 }
42
43 let num_vertices = meshes.iter().map(|m| m.vertices.len()).sum();
44 let mut vertices = Vec::with_capacity(num_vertices);
45 let mut normals = Vec::with_capacity(num_vertices);
46 let has_colors0 = num_vertices == meshes.iter().map(|m| m.colors[0].len()).sum();
48 let mut colors0 = Vec::with_capacity(if has_colors0 { num_vertices } else { 0 });
49 let has_colors1 = num_vertices == meshes.iter().map(|m| m.colors[1].len()).sum();
50 let mut colors1 = Vec::with_capacity(if has_colors1 { num_vertices } else { 0 });
51 for m in &meshes {
52 vertices.extend_from_slice(&m.vertices);
53 normals.extend_from_slice(&m.normals);
54 if has_colors0 {
55 colors0.extend_from_slice(&m.colors[0]);
56 }
57 if has_colors1 {
58 colors1.extend_from_slice(&m.colors[1]);
59 }
60 }
61 let mut faces = Vec::with_capacity(meshes.iter().map(|m| m.faces.len()).sum());
62 let mut last = 0;
63 for m in &meshes {
64 if m.faces.is_empty() {
65 continue;
66 }
67 faces.extend(
68 m.faces
69 .iter()
70 .map(|f| [f[0] + last, f[1] + last, f[2] + last]),
71 );
72 last = m.faces.last().unwrap()[2] + 1;
73 }
74
75 Self {
76 name: String::new(),
77 vertices,
78 texcoords: Default::default(), normals,
80 faces,
81 colors: [colors0, colors1],
82 #[cfg(feature = "obj")]
83 material_index: u32::MAX,
84 }
85 }
86}
87
88impl fmt::Debug for Mesh {
89 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90 f.debug_struct("Mesh")
91 .field("name", &self.name)
92 .field("num_vertices", &self.vertices.len())
93 .field("num_texcoords0", &self.texcoords[0].len())
94 .field("num_texcoords1", &self.texcoords[1].len())
95 .field("num_normals", &self.normals.len())
96 .field("num_faces", &self.faces.len())
97 .field("num_colors0", &self.colors[0].len())
98 .field("num_colors1", &self.colors[1].len())
99 .finish_non_exhaustive()
100 }
101}
102
103#[derive(Debug, Clone, Default)]
104#[non_exhaustive]
105pub struct Material {
106 pub name: String,
108 pub shading_model: Option<ShadingModel>,
109 pub opacity: Option<f32>,
110 pub shininess: Option<f32>,
111 pub reflectivity: Option<f32>,
112 pub index_of_refraction: Option<f32>,
113
114 pub color: Colors,
115 pub texture: Textures,
116}
117
118#[derive(Debug, Clone, Default)]
120#[non_exhaustive]
121pub struct Colors {
122 pub diffuse: Option<Color4>,
123 pub ambient: Option<Color4>,
124 pub specular: Option<Color4>,
125 pub emissive: Option<Color4>,
126 pub transparent: Option<Color4>,
127 pub reflective: Option<Color4>,
128}
129
130#[derive(Debug, Clone, Default)]
132#[non_exhaustive]
133pub struct Textures {
134 pub diffuse: Option<PathBuf>,
135 pub specular: Option<PathBuf>,
136 pub ambient: Option<PathBuf>,
137 pub emissive: Option<PathBuf>,
138 pub height: Option<PathBuf>,
139 pub normal: Option<PathBuf>,
140 pub shininess: Option<PathBuf>,
141 pub opacity: Option<PathBuf>,
142 pub displacement: Option<PathBuf>,
143 pub lightmap: Option<PathBuf>,
144 pub reflection: Option<PathBuf>,
145}
146
147#[derive(Debug, Clone)]
149#[non_exhaustive]
150pub enum ShadingModel {
151 Flat,
152 Gouraud,
153 Phong,
154 Blinn,
155 NoShading,
156}