1pub mod iter;
53
54#[cfg(feature = "utils")]
56#[cfg_attr(docsrs, doc(cfg(feature = "utils")))]
57pub mod util;
58
59use crate::{Accessor, Buffer, Document, Material};
60
61#[cfg(feature = "utils")]
62use crate::accessor;
63
64pub use json::mesh::{Mode, Semantic};
65use json::validation::Checked;
66#[cfg(feature = "extensions")]
67use serde_json::{Map, Value};
68
69pub type Attribute<'a> = (Semantic, Accessor<'a>);
71
72pub type BoundingBox = Bounds<[f32; 3]>;
74
75#[derive(Clone, Debug, PartialEq)]
77pub struct Bounds<T> {
78 pub min: T,
80
81 pub max: T,
83}
84
85#[derive(Clone, Debug)]
87pub struct Mesh<'a> {
88 document: &'a Document,
90
91 index: usize,
93
94 json: &'a json::mesh::Mesh,
96}
97
98#[derive(Clone, Debug)]
100pub struct MorphTarget<'a> {
101 positions: Option<Accessor<'a>>,
103
104 normals: Option<Accessor<'a>>,
106
107 tangents: Option<Accessor<'a>>,
109}
110
111#[derive(Clone, Debug)]
113pub struct Primitive<'a> {
114 mesh: Mesh<'a>,
116
117 index: usize,
119
120 json: &'a json::mesh::Primitive,
122}
123
124#[derive(Clone, Debug)]
126pub struct Reader<'a, 's, F>
127where
128 F: Clone + Fn(Buffer<'a>) -> Option<&'s [u8]>,
129{
130 #[allow(dead_code)]
131 pub(crate) primitive: &'a Primitive<'a>,
132 #[allow(dead_code)]
133 pub(crate) get_buffer_data: F,
134}
135
136impl<'a> Mesh<'a> {
137 pub(crate) fn new(document: &'a Document, index: usize, json: &'a json::mesh::Mesh) -> Self {
139 Self {
140 document,
141 index,
142 json,
143 }
144 }
145
146 pub fn index(&self) -> usize {
148 self.index
149 }
150
151 #[cfg(feature = "extensions")]
153 #[cfg_attr(docsrs, doc(cfg(feature = "extensions")))]
154 pub fn extensions(&self) -> Option<&Map<String, Value>> {
155 let ext = self.json.extensions.as_ref()?;
156 Some(&ext.others)
157 }
158
159 #[cfg(feature = "extensions")]
161 #[cfg_attr(docsrs, doc(cfg(feature = "extensions")))]
162 pub fn extension_value(&self, ext_name: &str) -> Option<&Value> {
163 let ext = self.json.extensions.as_ref()?;
164 ext.others.get(ext_name)
165 }
166
167 pub fn extras(&self) -> &'a json::Extras {
169 &self.json.extras
170 }
171
172 #[cfg(feature = "names")]
174 #[cfg_attr(docsrs, doc(cfg(feature = "names")))]
175 pub fn name(&self) -> Option<&'a str> {
176 self.json.name.as_deref()
177 }
178
179 pub fn primitives(&self) -> iter::Primitives<'a> {
181 iter::Primitives {
182 mesh: self.clone(),
183 iter: self.json.primitives.iter().enumerate(),
184 }
185 }
186
187 pub fn weights(&self) -> Option<&'a [f32]> {
189 self.json.weights.as_deref()
190 }
191}
192
193impl<'a> Primitive<'a> {
194 pub(crate) fn new(mesh: Mesh<'a>, index: usize, json: &'a json::mesh::Primitive) -> Self {
196 Self { mesh, index, json }
197 }
198
199 pub fn bounding_box(&self) -> BoundingBox {
201 let pos_accessor_index = self
203 .json
204 .attributes
205 .get(&Checked::Valid(Semantic::Positions))
206 .unwrap();
207 let pos_accessor = self
208 .mesh
209 .document
210 .accessors()
211 .nth(pos_accessor_index.value())
212 .unwrap();
213 let min: [f32; 3] = json::deserialize::from_value(pos_accessor.min().unwrap()).unwrap();
214 let max: [f32; 3] = json::deserialize::from_value(pos_accessor.max().unwrap()).unwrap();
215 Bounds { min, max }
216 }
217
218 #[cfg(feature = "extensions")]
220 #[cfg_attr(docsrs, doc(cfg(feature = "extensions")))]
221 pub fn extensions(&self) -> Option<&Map<String, Value>> {
222 let ext = self.json.extensions.as_ref()?;
223 Some(&ext.others)
224 }
225
226 #[cfg(feature = "extensions")]
228 #[cfg_attr(docsrs, doc(cfg(feature = "extensions")))]
229 pub fn extension_value(&self, ext_name: &str) -> Option<&Value> {
230 let ext = self.json.extensions.as_ref()?;
231 ext.others.get(ext_name)
232 }
233
234 pub fn extras(&self) -> &'a json::Extras {
236 &self.json.extras
237 }
238
239 pub fn get(&self, semantic: &Semantic) -> Option<Accessor<'a>> {
241 self.json
242 .attributes
243 .get(&json::validation::Checked::Valid(semantic.clone()))
244 .map(|index| self.mesh.document.accessors().nth(index.value()).unwrap())
245 }
246
247 pub fn index(&self) -> usize {
249 self.index
250 }
251
252 pub fn indices(&self) -> Option<Accessor<'a>> {
254 self.json
255 .indices
256 .as_ref()
257 .map(|index| self.mesh.document.accessors().nth(index.value()).unwrap())
258 }
259
260 pub fn attributes(&self) -> iter::Attributes<'a> {
262 iter::Attributes {
263 document: self.mesh.document,
264 prim: self.clone(),
265 iter: self.json.attributes.iter(),
266 }
267 }
268
269 pub fn material(&self) -> Material<'a> {
271 self.json
272 .material
273 .as_ref()
274 .map(|index| self.mesh.document.materials().nth(index.value()).unwrap())
275 .unwrap_or_else(|| Material::default(self.mesh.document))
276 }
277
278 pub fn mode(&self) -> Mode {
280 self.json.mode.unwrap()
281 }
282
283 pub fn morph_targets(&self) -> iter::MorphTargets<'a> {
285 if let Some(slice) = self.json.targets.as_ref() {
286 iter::MorphTargets {
287 document: self.mesh.document,
288 iter: slice.iter(),
289 }
290 } else {
291 iter::MorphTargets {
292 document: self.mesh.document,
293 iter: ([]).iter(),
294 }
295 }
296 }
297
298 #[cfg(feature = "KHR_materials_variants")]
300 #[cfg_attr(docsrs, doc(cfg(feature = "KHR_materials_variants")))]
301 pub fn mappings(&self) -> iter::Mappings<'a> {
302 let iter = self
303 .json
304 .extensions
305 .as_ref()
306 .and_then(|extensions| extensions.khr_materials_variants.as_ref())
307 .map(|variants| variants.mappings.iter())
308 .unwrap_or_else(|| ([]).iter());
309
310 iter::Mappings {
311 document: self.mesh.document,
312 iter,
313 }
314 }
315
316 #[cfg(feature = "utils")]
318 #[cfg_attr(docsrs, doc(cfg(feature = "utils")))]
319 pub fn reader<'s, F>(&'a self, get_buffer_data: F) -> Reader<'a, 's, F>
320 where
321 F: Clone + Fn(Buffer<'a>) -> Option<&'s [u8]>,
322 {
323 Reader {
324 primitive: self,
325 get_buffer_data,
326 }
327 }
328}
329
330#[cfg(feature = "utils")]
331impl<'a, 's, F> Reader<'a, 's, F>
332where
333 F: Clone + Fn(Buffer<'a>) -> Option<&'s [u8]>,
334{
335 pub fn read_positions(&self) -> Option<util::ReadPositions<'s>> {
337 self.primitive
338 .get(&Semantic::Positions)
339 .and_then(|accessor| accessor::Iter::new(accessor, self.get_buffer_data.clone()))
340 }
341
342 pub fn read_normals(&self) -> Option<util::ReadNormals<'s>> {
344 self.primitive
345 .get(&Semantic::Normals)
346 .and_then(|accessor| accessor::Iter::new(accessor, self.get_buffer_data.clone()))
347 }
348
349 pub fn read_tangents(&self) -> Option<util::ReadTangents<'s>> {
351 self.primitive
352 .get(&Semantic::Tangents)
353 .and_then(|accessor| accessor::Iter::new(accessor, self.get_buffer_data.clone()))
354 }
355
356 pub fn read_colors(&self, set: u32) -> Option<util::ReadColors<'s>> {
358 use self::util::ReadColors;
359 use accessor::DataType::{F32, U16, U8};
360 use accessor::Dimensions::{Vec3, Vec4};
361 self.primitive
362 .get(&Semantic::Colors(set))
363 .and_then(
364 |accessor| match (accessor.data_type(), accessor.dimensions()) {
365 (U8, Vec3) => accessor::Iter::new(accessor, self.get_buffer_data.clone())
366 .map(ReadColors::RgbU8),
367 (U16, Vec3) => accessor::Iter::new(accessor, self.get_buffer_data.clone())
368 .map(ReadColors::RgbU16),
369 (F32, Vec3) => accessor::Iter::new(accessor, self.get_buffer_data.clone())
370 .map(ReadColors::RgbF32),
371 (U8, Vec4) => accessor::Iter::new(accessor, self.get_buffer_data.clone())
372 .map(ReadColors::RgbaU8),
373 (U16, Vec4) => accessor::Iter::new(accessor, self.get_buffer_data.clone())
374 .map(ReadColors::RgbaU16),
375 (F32, Vec4) => accessor::Iter::new(accessor, self.get_buffer_data.clone())
376 .map(ReadColors::RgbaF32),
377 _ => unreachable!(),
378 },
379 )
380 }
381
382 pub fn read_indices(&self) -> Option<util::ReadIndices<'s>> {
384 use self::util::ReadIndices;
385 use accessor::DataType;
386 self.primitive
387 .indices()
388 .and_then(|accessor| match accessor.data_type() {
389 DataType::U8 => {
390 accessor::Iter::new(accessor, self.get_buffer_data.clone()).map(ReadIndices::U8)
391 }
392 DataType::U16 => accessor::Iter::new(accessor, self.get_buffer_data.clone())
393 .map(ReadIndices::U16),
394 DataType::U32 => accessor::Iter::new(accessor, self.get_buffer_data.clone())
395 .map(ReadIndices::U32),
396 _ => unreachable!(),
397 })
398 }
399
400 pub fn read_joints(&self, set: u32) -> Option<util::ReadJoints<'s>> {
402 use self::util::ReadJoints;
403 use accessor::DataType;
404 self.primitive
405 .get(&Semantic::Joints(set))
406 .and_then(|accessor| match accessor.data_type() {
407 DataType::U8 => {
408 accessor::Iter::new(accessor, self.get_buffer_data.clone()).map(ReadJoints::U8)
409 }
410 DataType::U16 => {
411 accessor::Iter::new(accessor, self.get_buffer_data.clone()).map(ReadJoints::U16)
412 }
413 _ => unreachable!(),
414 })
415 }
416
417 pub fn read_tex_coords(&self, set: u32) -> Option<util::ReadTexCoords<'s>> {
419 use self::util::ReadTexCoords;
420 use accessor::DataType;
421 self.primitive
422 .get(&Semantic::TexCoords(set))
423 .and_then(|accessor| match accessor.data_type() {
424 DataType::U8 => accessor::Iter::new(accessor, self.get_buffer_data.clone())
425 .map(ReadTexCoords::U8),
426 DataType::U16 => accessor::Iter::new(accessor, self.get_buffer_data.clone())
427 .map(ReadTexCoords::U16),
428 DataType::F32 => accessor::Iter::new(accessor, self.get_buffer_data.clone())
429 .map(ReadTexCoords::F32),
430 _ => unreachable!(),
431 })
432 }
433
434 pub fn read_weights(&self, set: u32) -> Option<util::ReadWeights<'s>> {
436 use self::accessor::DataType;
437 use self::util::ReadWeights;
438 self.primitive
439 .get(&Semantic::Weights(set))
440 .and_then(|accessor| match accessor.data_type() {
441 DataType::U8 => {
442 accessor::Iter::new(accessor, self.get_buffer_data.clone()).map(ReadWeights::U8)
443 }
444 DataType::U16 => accessor::Iter::new(accessor, self.get_buffer_data.clone())
445 .map(ReadWeights::U16),
446 DataType::F32 => accessor::Iter::new(accessor, self.get_buffer_data.clone())
447 .map(ReadWeights::F32),
448 _ => unreachable!(),
449 })
450 }
451
452 pub fn read_morph_targets(&self) -> util::ReadMorphTargets<'a, 's, F> {
454 util::ReadMorphTargets {
455 index: 0,
456 reader: self.clone(),
457 }
458 }
459}
460
461impl<'a> MorphTarget<'a> {
462 pub fn positions(&self) -> Option<Accessor<'a>> {
464 self.positions.clone()
465 }
466
467 pub fn normals(&self) -> Option<Accessor<'a>> {
469 self.normals.clone()
470 }
471
472 pub fn tangents(&self) -> Option<Accessor<'a>> {
474 self.tangents.clone()
475 }
476}