[go: up one dir, main page]

gltf/
buffer.rs

1#[cfg(feature = "import")]
2use std::ops;
3
4use crate::Document;
5
6pub use json::buffer::Target;
7#[cfg(feature = "extensions")]
8use serde_json::{Map, Value};
9
10/// A buffer points to binary data representing geometry, animations, or skins.
11#[derive(Clone, Debug)]
12pub struct Buffer<'a> {
13    /// The parent `Document` struct.
14    #[allow(dead_code)]
15    document: &'a Document,
16
17    /// The corresponding JSON index.
18    index: usize,
19
20    /// The corresponding JSON struct.
21    json: &'a json::buffer::Buffer,
22}
23
24/// A view into a buffer generally representing a subset of the buffer.
25#[derive(Clone, Debug)]
26pub struct View<'a> {
27    /// The parent `Document` struct.
28    document: &'a Document,
29
30    /// The corresponding JSON index.
31    index: usize,
32
33    /// The corresponding JSON struct.
34    json: &'a json::buffer::View,
35
36    /// The parent `Buffer`.
37    #[allow(dead_code)]
38    parent: Buffer<'a>,
39}
40
41/// Describes a buffer data source.
42#[derive(Clone, Debug)]
43pub enum Source<'a> {
44    /// Buffer data is contained in the `BIN` section of binary glTF.
45    Bin,
46
47    /// Buffer data is contained in an external data source.
48    Uri(&'a str),
49}
50
51/// Buffer data belonging to an imported glTF asset.
52#[cfg(feature = "import")]
53#[cfg_attr(docsrs, doc(cfg(feature = "import")))]
54#[derive(Clone, Debug)]
55pub struct Data(pub Vec<u8>);
56
57#[cfg(feature = "import")]
58#[cfg_attr(docsrs, doc(cfg(feature = "import")))]
59impl ops::Deref for Data {
60    type Target = [u8];
61    fn deref(&self) -> &Self::Target {
62        self.0.as_slice()
63    }
64}
65
66impl<'a> Buffer<'a> {
67    /// Constructs a `Buffer`.
68    pub(crate) fn new(
69        document: &'a Document,
70        index: usize,
71        json: &'a json::buffer::Buffer,
72    ) -> Self {
73        Self {
74            document,
75            index,
76            json,
77        }
78    }
79
80    /// Returns the internal JSON index.
81    pub fn index(&self) -> usize {
82        self.index
83    }
84
85    /// Returns the buffer data source.
86    pub fn source(&self) -> Source<'a> {
87        if let Some(uri) = self.json.uri.as_deref() {
88            Source::Uri(uri)
89        } else {
90            Source::Bin
91        }
92    }
93
94    /// The length of the buffer in bytes.
95    pub fn length(&self) -> usize {
96        self.json.byte_length.0 as usize
97    }
98
99    /// Optional user-defined name for this object.
100    #[cfg(feature = "names")]
101    #[cfg_attr(docsrs, doc(cfg(feature = "names")))]
102    pub fn name(&self) -> Option<&'a str> {
103        self.json.name.as_deref()
104    }
105
106    /// Returns extension data unknown to this crate version.
107    #[cfg(feature = "extensions")]
108    #[cfg_attr(docsrs, doc(cfg(feature = "extensions")))]
109    pub fn extensions(&self) -> Option<&Map<String, Value>> {
110        let ext = self.json.extensions.as_ref()?;
111        Some(&ext.others)
112    }
113
114    /// Queries extension data unknown to this crate version.
115    #[cfg(feature = "extensions")]
116    #[cfg_attr(docsrs, doc(cfg(feature = "extensions")))]
117    pub fn extension_value(&self, ext_name: &str) -> Option<&Value> {
118        let ext = self.json.extensions.as_ref()?;
119        ext.others.get(ext_name)
120    }
121
122    /// Optional application specific data.
123    pub fn extras(&self) -> &'a json::Extras {
124        &self.json.extras
125    }
126}
127
128impl<'a> View<'a> {
129    /// Constructs a `View`.
130    pub(crate) fn new(document: &'a Document, index: usize, json: &'a json::buffer::View) -> Self {
131        let parent = document.buffers().nth(json.buffer.value()).unwrap();
132        Self {
133            document,
134            index,
135            json,
136            parent,
137        }
138    }
139
140    /// Returns the internal JSON index.
141    pub fn index(&self) -> usize {
142        self.index
143    }
144
145    /// Returns the parent `Buffer`.
146    pub fn buffer(&self) -> Buffer<'a> {
147        self.document
148            .buffers()
149            .nth(self.json.buffer.value())
150            .unwrap()
151    }
152
153    /// Returns the length of the buffer view in bytes.
154    pub fn length(&self) -> usize {
155        self.json.byte_length.0 as usize
156    }
157
158    /// Returns the offset into the parent buffer in bytes.
159    pub fn offset(&self) -> usize {
160        self.json.byte_offset.unwrap_or_default().0 as usize
161    }
162
163    /// Returns the stride in bytes between vertex attributes or other interleavable
164    /// data. When `None`, data is assumed to be tightly packed.
165    pub fn stride(&self) -> Option<usize> {
166        self.json.byte_stride.and_then(|x| {
167            // Treat byte_stride == 0 same as not specifying stride.
168            // This is technically a validation error, but best way we can handle it here
169            if x.0 == 0 {
170                None
171            } else {
172                Some(x.0)
173            }
174        })
175    }
176
177    /// Optional user-defined name for this object.
178    #[cfg(feature = "names")]
179    #[cfg_attr(docsrs, doc(cfg(feature = "names")))]
180    pub fn name(&self) -> Option<&'a str> {
181        self.json.name.as_deref()
182    }
183
184    /// Optional target the buffer should be bound to.
185    pub fn target(&self) -> Option<Target> {
186        self.json.target.map(|target| target.unwrap())
187    }
188
189    /// Returns extension data unknown to this crate version.
190    #[cfg(feature = "extensions")]
191    #[cfg_attr(docsrs, doc(cfg(feature = "extensions")))]
192    pub fn extensions(&self) -> Option<&Map<String, Value>> {
193        let ext = self.json.extensions.as_ref()?;
194        Some(&ext.others)
195    }
196
197    /// Queries extension data unknown to this crate version.
198    #[cfg(feature = "extensions")]
199    #[cfg_attr(docsrs, doc(cfg(feature = "extensions")))]
200    pub fn extension_value(&self, ext_name: &str) -> Option<&Value> {
201        let ext = self.json.extensions.as_ref()?;
202        ext.others.get(ext_name)
203    }
204
205    /// Optional application specific data.
206    pub fn extras(&self) -> &'a json::Extras {
207        &self.json.extras
208    }
209}