[go: up one dir, main page]

gltf/mesh/
mod.rs

1//! # Basic usage
2//!
3//! Listing the attributes of each mesh primitive in a glTF asset.
4//!
5//! ```
6//! # fn run() -> Result<(), Box<dyn std::error::Error>> {
7//! # let gltf = gltf::Gltf::open("examples/Box.gltf")?;
8//! for mesh in gltf.meshes() {
9//!    println!("Mesh #{}", mesh.index());
10//!    for primitive in mesh.primitives() {
11//!        println!("- Primitive #{}", primitive.index());
12//!        for (semantic, _) in primitive.attributes() {
13//!            println!("-- {:?}", semantic);
14//!        }
15//!    }
16//! }
17//! # Ok(())
18//! # }
19//! # fn main() {
20//! #    let _ = run().expect("runtime error");
21//! # }
22//! ```
23//!
24//! # Reader utility
25//!
26//! Printing the vertex positions of each primitive of each mesh in
27//! a glTF asset.
28//!
29//! ```
30//! # fn run() -> Result<(), Box<dyn std::error::Error>> {
31//! let (gltf, buffers, _) = gltf::import("examples/Box.gltf")?;
32//! for mesh in gltf.meshes() {
33//!    println!("Mesh #{}", mesh.index());
34//!    for primitive in mesh.primitives() {
35//!        println!("- Primitive #{}", primitive.index());
36//!        let reader = primitive.reader(|buffer| Some(&buffers[buffer.index()]));
37//!        if let Some(iter) = reader.read_positions() {
38//!            for vertex_position in iter {
39//!                println!("{:?}", vertex_position);
40//!            }
41//!        }
42//!    }
43//! }
44//! # Ok(())
45//! # }
46//! # fn main() {
47//! #    let _ = run().expect("runtime error");
48//! # }
49//! ```
50
51/// Iterators.
52pub mod iter;
53
54/// Utility functions.
55#[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
69/// Vertex attribute data.
70pub type Attribute<'a> = (Semantic, Accessor<'a>);
71
72/// Vertex position bounding box.
73pub type BoundingBox = Bounds<[f32; 3]>;
74
75/// The minimum and maximum values for a generic accessor.
76#[derive(Clone, Debug, PartialEq)]
77pub struct Bounds<T> {
78    /// Minimum value.
79    pub min: T,
80
81    /// Maximum value.
82    pub max: T,
83}
84
85/// A set of primitives to be rendered.
86#[derive(Clone, Debug)]
87pub struct Mesh<'a> {
88    /// The parent `Document` struct.
89    document: &'a Document,
90
91    /// The corresponding JSON index.
92    index: usize,
93
94    /// The corresponding JSON struct.
95    json: &'a json::mesh::Mesh,
96}
97
98/// A single morph target for a mesh primitive.
99#[derive(Clone, Debug)]
100pub struct MorphTarget<'a> {
101    /// XYZ vertex position displacements.
102    positions: Option<Accessor<'a>>,
103
104    /// XYZ vertex normal displacements.
105    normals: Option<Accessor<'a>>,
106
107    /// XYZ vertex tangent displacements.
108    tangents: Option<Accessor<'a>>,
109}
110
111/// Geometry to be rendered with the given material.
112#[derive(Clone, Debug)]
113pub struct Primitive<'a> {
114    /// The parent `Mesh` struct.
115    mesh: Mesh<'a>,
116
117    /// The corresponding JSON index.
118    index: usize,
119
120    /// The corresponding JSON struct.
121    json: &'a json::mesh::Primitive,
122}
123
124/// Mesh primitive reader.
125#[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    /// Constructs a `Mesh`.
138    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    /// Returns the internal JSON index.
147    pub fn index(&self) -> usize {
148        self.index
149    }
150
151    /// Returns extension data unknown to this crate version.
152    #[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    /// Queries extension data unknown to this crate version.
160    #[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    /// Optional application specific data.
168    pub fn extras(&self) -> &'a json::Extras {
169        &self.json.extras
170    }
171
172    /// Optional user-defined name for this object.
173    #[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    /// Defines the geometry to be renderered with a material.
180    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    /// Defines the weights to be applied to the morph targets.
188    pub fn weights(&self) -> Option<&'a [f32]> {
189        self.json.weights.as_deref()
190    }
191}
192
193impl<'a> Primitive<'a> {
194    /// Constructs a `Primitive`.
195    pub(crate) fn new(mesh: Mesh<'a>, index: usize, json: &'a json::mesh::Primitive) -> Self {
196        Self { mesh, index, json }
197    }
198
199    /// Returns the bounds of the `POSITION` vertex attribute.
200    pub fn bounding_box(&self) -> BoundingBox {
201        // NOTE: cannot panic if validated "minimally"
202        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    /// Returns extension data unknown to this crate version.
219    #[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    /// Queries extension data unknown to this crate version.
227    #[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    /// Optional application specific data.
235    pub fn extras(&self) -> &'a json::Extras {
236        &self.json.extras
237    }
238
239    /// Return the accessor with the given semantic.
240    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    /// Returns the internal JSON index.
248    pub fn index(&self) -> usize {
249        self.index
250    }
251
252    /// Returns the accessor containing the primitive indices, if provided.
253    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    /// Returns an `Iterator` that visits the vertex attributes.
261    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    /// Returns the material to apply to this primitive when rendering
270    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    /// The type of primitives to render.
279    pub fn mode(&self) -> Mode {
280        self.json.mode.unwrap()
281    }
282
283    /// Returns an `Iterator` that visits the morph targets of the primitive.
284    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    /// Get the material variants.
299    #[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    /// Constructs the primitive reader.
317    #[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    /// Visits the vertex positions of a primitive.
336    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    /// Visits the vertex normals of a primitive.
343    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    /// Visits the vertex tangents of a primitive.
350    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    /// Visits the vertex colors of a primitive.
357    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    /// Visits the vertex draw sequence of a primitive.
383    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    /// Visits the joint indices of the primitive.
401    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    /// Visits the vertex texture co-ordinates of a primitive.
418    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    /// Visits the joint weights of the primitive.
435    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    /// Visits the morph targets of the primitive.
453    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    /// Returns the XYZ vertex position displacements.
463    pub fn positions(&self) -> Option<Accessor<'a>> {
464        self.positions.clone()
465    }
466
467    /// Returns the XYZ vertex normal displacements.
468    pub fn normals(&self) -> Option<Accessor<'a>> {
469        self.normals.clone()
470    }
471
472    /// Returns the XYZ vertex tangent displacements.
473    pub fn tangents(&self) -> Option<Accessor<'a>> {
474        self.tangents.clone()
475    }
476}