[go: up one dir, main page]

gltf/accessor/
mod.rs

1//! # Basic usage
2//!
3//! Visiting the accessors of 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 accessor in gltf.accessors() {
9//!     println!("Accessor #{}", accessor.index());
10//!     println!("offset: {:?}", accessor.offset());
11//!     println!("count: {}", accessor.count());
12//!     println!("data_type: {:?}", accessor.data_type());
13//!     println!("dimensions: {:?}", accessor.dimensions());
14//! }
15//! # Ok(())
16//! # }
17//! # fn main() {
18//! #    let _ = run().expect("runtime error");
19//! # }
20//! ```
21//!
22//! # Utility functions
23//!
24//! Reading the values from the `vec3` accessors of a glTF asset.
25//!
26//! ## Note
27//!
28//! The [`Iter`] utility is a low-level iterator intended for use in special
29//! cases. The average user is expected to use reader abstractions such as
30//! [`mesh::Reader`].
31//!
32//! [`Iter`]: struct.Iter.html
33//! [`mesh::Reader`]: ../mesh/struct.Reader.html
34//!
35//! ```
36//! # fn run() -> Result<(), Box<dyn std::error::Error>> {
37//! # use gltf::accessor::{DataType, Dimensions, Iter};
38//! let (gltf, buffers, _) = gltf::import("examples/Box.gltf")?;
39//! let get_buffer_data = |buffer: gltf::Buffer| buffers.get(buffer.index()).map(|x| &*x.0);
40//! for accessor in gltf.accessors() {
41//!     match (accessor.data_type(), accessor.dimensions()) {
42//!         (DataType::F32, Dimensions::Vec3) => {
43//!             if let Some(iter) = Iter::<[f32; 3]>::new(accessor, get_buffer_data) {
44//!                 for item in iter {
45//!                     println!("{:?}", item);
46//!                 }
47//!             }
48//!         }
49//!         _ => {},
50//!     }
51//! }
52//! # Ok(())
53//! # }
54//! # fn main() {
55//! #    let _ = run().expect("runtime error");
56//! # }
57//! ```
58
59use crate::{buffer, Document};
60
61pub use json::accessor::ComponentType as DataType;
62pub use json::accessor::Type as Dimensions;
63#[cfg(feature = "extensions")]
64use serde_json::{Map, Value};
65
66/// Utility functions.
67#[cfg(feature = "utils")]
68#[cfg_attr(docsrs, doc(cfg(feature = "utils")))]
69pub mod util;
70
71/// Contains data structures for sparse storage.
72pub mod sparse;
73
74#[cfg(feature = "utils")]
75#[doc(inline)]
76pub use self::util::{Item, Iter};
77
78/// A typed view into a buffer view.
79#[derive(Clone, Debug)]
80pub struct Accessor<'a> {
81    /// The parent `Document` struct.
82    document: &'a Document,
83
84    /// The corresponding JSON index.
85    index: usize,
86
87    /// The corresponding JSON struct.
88    json: &'a json::accessor::Accessor,
89}
90
91impl<'a> Accessor<'a> {
92    /// Constructs an `Accessor`.
93    pub(crate) fn new(
94        document: &'a Document,
95        index: usize,
96        json: &'a json::accessor::Accessor,
97    ) -> Self {
98        Self {
99            document,
100            index,
101            json,
102        }
103    }
104
105    /// Returns the internal JSON index.
106    pub fn index(&self) -> usize {
107        self.index
108    }
109
110    /// Returns the size of each component that this accessor describes.
111    pub fn size(&self) -> usize {
112        self.data_type().size() * self.dimensions().multiplicity()
113    }
114
115    /// Returns the buffer view this accessor reads from.
116    ///
117    /// This may be `None` if the corresponding accessor is sparse.
118    pub fn view(&self) -> Option<buffer::View<'a>> {
119        self.json
120            .buffer_view
121            .map(|view| self.document.views().nth(view.value()).unwrap())
122    }
123
124    /// Returns the offset relative to the start of the parent buffer view in bytes.
125    ///
126    /// This will be 0 if the corresponding accessor is sparse.
127    pub fn offset(&self) -> usize {
128        // TODO: Change this function to return Option<usize> in the next
129        // version and return None for sparse accessors.
130        self.json.byte_offset.unwrap_or_default().0 as usize
131    }
132
133    /// Returns the number of components within the buffer view - not to be confused
134    /// with the number of bytes in the buffer view.
135    pub fn count(&self) -> usize {
136        self.json.count.0 as usize
137    }
138
139    /// Returns the data type of components in the attribute.
140    pub fn data_type(&self) -> DataType {
141        self.json.component_type.unwrap().0
142    }
143
144    /// Returns extension data unknown to this crate version.
145    #[cfg(feature = "extensions")]
146    #[cfg_attr(docsrs, doc(cfg(feature = "extensions")))]
147    pub fn extensions(&self) -> Option<&Map<String, Value>> {
148        let ext = self.json.extensions.as_ref()?;
149        Some(&ext.others)
150    }
151
152    /// Queries extension data unknown to this crate version.
153    #[cfg(feature = "extensions")]
154    #[cfg_attr(docsrs, doc(cfg(feature = "extensions")))]
155    pub fn extension_value(&self, ext_name: &str) -> Option<&Value> {
156        let ext = self.json.extensions.as_ref()?;
157        ext.others.get(ext_name)
158    }
159
160    /// Optional application specific data.
161    pub fn extras(&self) -> &'a json::Extras {
162        &self.json.extras
163    }
164
165    /// Specifies if the attribute is a scalar, vector, or matrix.
166    pub fn dimensions(&self) -> Dimensions {
167        self.json.type_.unwrap()
168    }
169
170    /// Returns the minimum value of each component in this attribute.
171    pub fn min(&self) -> Option<json::Value> {
172        self.json.min.clone()
173    }
174
175    /// Returns the maximum value of each component in this attribute.
176    pub fn max(&self) -> Option<json::Value> {
177        self.json.max.clone()
178    }
179
180    /// Optional user-defined name for this object.
181    #[cfg(feature = "names")]
182    #[cfg_attr(docsrs, doc(cfg(feature = "names")))]
183    pub fn name(&self) -> Option<&'a str> {
184        self.json.name.as_deref()
185    }
186
187    /// Specifies whether integer data values should be normalized.
188    pub fn normalized(&self) -> bool {
189        self.json.normalized
190    }
191
192    /// Returns sparse storage of attributes that deviate from their initialization
193    /// value.
194    pub fn sparse(&self) -> Option<sparse::Sparse<'a>> {
195        self.json
196            .sparse
197            .as_ref()
198            .map(|json| sparse::Sparse::new(self.document, json))
199    }
200}