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| {
340 #[cfg(feature = "KHR_mesh_quantization")]
341 {
342 let normalized = accessor.normalized();
343 match accessor.data_type() {
344 json::accessor::ComponentType::I8 => {
345 accessor::Iter::new(accessor, self.get_buffer_data.clone())
347 .map(|iter| util::ReadPositions::I8(iter, normalized))
348 }
349 json::accessor::ComponentType::U8 => {
350 accessor::Iter::new(accessor, self.get_buffer_data.clone())
352 .map(|iter| util::ReadPositions::U8(iter, normalized))
353 }
354 json::accessor::ComponentType::I16 => {
355 accessor::Iter::new(accessor, self.get_buffer_data.clone())
357 .map(|iter| util::ReadPositions::I16(iter, normalized))
358 }
359 json::accessor::ComponentType::U16 => {
360 accessor::Iter::new(accessor, self.get_buffer_data.clone())
362 .map(|iter| util::ReadPositions::U16(iter, normalized))
363 }
364 json::accessor::ComponentType::F32 => {
365 accessor::Iter::new(accessor, self.get_buffer_data.clone())
366 .map(util::ReadPositions::F32)
367 }
368 _ => None, }
370 }
371 #[cfg(not(feature = "KHR_mesh_quantization"))]
372 accessor::Iter::new(accessor, self.get_buffer_data.clone())
373 })
374 }
375
376 pub fn read_normals(&self) -> Option<util::ReadNormals<'s>> {
378 self.primitive.get(&Semantic::Normals).and_then(|accessor| {
379 #[cfg(feature = "KHR_mesh_quantization")]
380 {
381 let normalized = accessor.normalized();
382 match accessor.data_type() {
383 json::accessor::ComponentType::I8 => {
384 if !normalized {
386 return None; }
388 accessor::Iter::new(accessor, self.get_buffer_data.clone())
389 .map(|iter| util::ReadNormals::I8(iter, normalized))
390 }
391 json::accessor::ComponentType::I16 => {
392 if !normalized {
394 return None; }
396 accessor::Iter::new(accessor, self.get_buffer_data.clone())
397 .map(|iter| util::ReadNormals::I16(iter, normalized))
398 }
399 json::accessor::ComponentType::F32 => {
400 accessor::Iter::new(accessor, self.get_buffer_data.clone())
401 .map(util::ReadNormals::F32)
402 }
403 _ => None, }
405 }
406 #[cfg(not(feature = "KHR_mesh_quantization"))]
407 accessor::Iter::new(accessor, self.get_buffer_data.clone())
408 })
409 }
410
411 pub fn read_tangents(&self) -> Option<util::ReadTangents<'s>> {
413 self.primitive
414 .get(&Semantic::Tangents)
415 .and_then(|accessor| {
416 #[cfg(feature = "KHR_mesh_quantization")]
417 {
418 let normalized = accessor.normalized();
419 match accessor.data_type() {
420 json::accessor::ComponentType::I8 => {
421 if !normalized {
423 return None; }
425 accessor::Iter::new(accessor, self.get_buffer_data.clone())
426 .map(|iter| util::ReadTangents::I8(iter, normalized))
427 }
428 json::accessor::ComponentType::I16 => {
429 if !normalized {
431 return None; }
433 accessor::Iter::new(accessor, self.get_buffer_data.clone())
434 .map(|iter| util::ReadTangents::I16(iter, normalized))
435 }
436 json::accessor::ComponentType::F32 => {
437 accessor::Iter::new(accessor, self.get_buffer_data.clone())
438 .map(util::ReadTangents::F32)
439 }
440 _ => None, }
442 }
443 #[cfg(not(feature = "KHR_mesh_quantization"))]
444 accessor::Iter::new(accessor, self.get_buffer_data.clone())
445 })
446 }
447
448 pub fn read_colors(&self, set: u32) -> Option<util::ReadColors<'s>> {
450 use self::util::ReadColors;
451 use accessor::DataType::{F32, U16, U8};
452 use accessor::Dimensions::{Vec3, Vec4};
453 self.primitive
454 .get(&Semantic::Colors(set))
455 .and_then(
456 |accessor| match (accessor.data_type(), accessor.dimensions()) {
457 (U8, Vec3) => accessor::Iter::new(accessor, self.get_buffer_data.clone())
458 .map(ReadColors::RgbU8),
459 (U16, Vec3) => accessor::Iter::new(accessor, self.get_buffer_data.clone())
460 .map(ReadColors::RgbU16),
461 (F32, Vec3) => accessor::Iter::new(accessor, self.get_buffer_data.clone())
462 .map(ReadColors::RgbF32),
463 (U8, Vec4) => accessor::Iter::new(accessor, self.get_buffer_data.clone())
464 .map(ReadColors::RgbaU8),
465 (U16, Vec4) => accessor::Iter::new(accessor, self.get_buffer_data.clone())
466 .map(ReadColors::RgbaU16),
467 (F32, Vec4) => accessor::Iter::new(accessor, self.get_buffer_data.clone())
468 .map(ReadColors::RgbaF32),
469 _ => unreachable!(),
470 },
471 )
472 }
473
474 pub fn read_indices(&self) -> Option<util::ReadIndices<'s>> {
476 use self::util::ReadIndices;
477 use accessor::DataType;
478 self.primitive
479 .indices()
480 .and_then(|accessor| match accessor.data_type() {
481 DataType::U8 => {
482 accessor::Iter::new(accessor, self.get_buffer_data.clone()).map(ReadIndices::U8)
483 }
484 DataType::U16 => accessor::Iter::new(accessor, self.get_buffer_data.clone())
485 .map(ReadIndices::U16),
486 DataType::U32 => accessor::Iter::new(accessor, self.get_buffer_data.clone())
487 .map(ReadIndices::U32),
488 _ => unreachable!(),
489 })
490 }
491
492 pub fn read_joints(&self, set: u32) -> Option<util::ReadJoints<'s>> {
494 use self::util::ReadJoints;
495 use accessor::DataType;
496 self.primitive
497 .get(&Semantic::Joints(set))
498 .and_then(|accessor| match accessor.data_type() {
499 DataType::U8 => {
500 accessor::Iter::new(accessor, self.get_buffer_data.clone()).map(ReadJoints::U8)
501 }
502 DataType::U16 => {
503 accessor::Iter::new(accessor, self.get_buffer_data.clone()).map(ReadJoints::U16)
504 }
505 _ => unreachable!(),
506 })
507 }
508
509 pub fn read_tex_coords(&self, set: u32) -> Option<util::ReadTexCoords<'s>> {
511 use self::util::ReadTexCoords;
512 use accessor::DataType;
513 self.primitive
514 .get(&Semantic::TexCoords(set))
515 .and_then(|accessor| {
516 #[cfg(feature = "KHR_mesh_quantization")]
517 {
518 let normalized = accessor.normalized();
519 match accessor.data_type() {
520 DataType::I8 => {
521 accessor::Iter::new(accessor, self.get_buffer_data.clone())
523 .map(|iter| ReadTexCoords::I8(iter, normalized))
524 }
525 DataType::U8 => {
526 accessor::Iter::new(accessor, self.get_buffer_data.clone())
528 .map(|iter| ReadTexCoords::U8(iter, normalized))
529 }
530 DataType::I16 => {
531 accessor::Iter::new(accessor, self.get_buffer_data.clone())
533 .map(|iter| ReadTexCoords::I16(iter, normalized))
534 }
535 DataType::U16 => {
536 accessor::Iter::new(accessor, self.get_buffer_data.clone())
538 .map(|iter| ReadTexCoords::U16(iter, normalized))
539 }
540 DataType::F32 => {
541 accessor::Iter::new(accessor, self.get_buffer_data.clone())
542 .map(ReadTexCoords::F32)
543 }
544 _ => None, }
546 }
547 #[cfg(not(feature = "KHR_mesh_quantization"))]
548 {
549 match accessor.data_type() {
551 DataType::U8 => accessor::Iter::new(accessor, self.get_buffer_data.clone())
552 .map(|iter| ReadTexCoords::U8(iter, true)),
553 DataType::U16 => {
554 accessor::Iter::new(accessor, self.get_buffer_data.clone())
555 .map(|iter| ReadTexCoords::U16(iter, true))
556 }
557 DataType::F32 => {
558 accessor::Iter::new(accessor, self.get_buffer_data.clone())
559 .map(ReadTexCoords::F32)
560 }
561 _ => unreachable!(),
562 }
563 }
564 })
565 }
566
567 pub fn read_weights(&self, set: u32) -> Option<util::ReadWeights<'s>> {
569 use self::accessor::DataType;
570 use self::util::ReadWeights;
571 self.primitive
572 .get(&Semantic::Weights(set))
573 .and_then(|accessor| match accessor.data_type() {
574 DataType::U8 => {
575 accessor::Iter::new(accessor, self.get_buffer_data.clone()).map(ReadWeights::U8)
576 }
577 DataType::U16 => accessor::Iter::new(accessor, self.get_buffer_data.clone())
578 .map(ReadWeights::U16),
579 DataType::F32 => accessor::Iter::new(accessor, self.get_buffer_data.clone())
580 .map(ReadWeights::F32),
581 _ => unreachable!(),
582 })
583 }
584
585 pub fn read_morph_targets(&self) -> util::ReadMorphTargets<'a, 's, F> {
587 util::ReadMorphTargets {
588 index: 0,
589 reader: self.clone(),
590 }
591 }
592}
593
594impl<'a> MorphTarget<'a> {
595 pub fn positions(&self) -> Option<Accessor<'a>> {
597 self.positions.clone()
598 }
599
600 pub fn normals(&self) -> Option<Accessor<'a>> {
602 self.normals.clone()
603 }
604
605 pub fn tangents(&self) -> Option<Accessor<'a>> {
607 self.tangents.clone()
608 }
609}