mod3d_gltf/
buffers_accessors.rs

1//a Imports
2#[cfg(feature = "serde")]
3use serde::{Deserialize, Serialize};
4
5#[cfg(feature = "serde")]
6use crate::{deserialize, serialize};
7
8use crate::{BufferIndex, ViewIndex};
9
10//a GltfBuffer
11//tp GltfBuffer
12/// A buffer description, such as a file path or URI
13///
14/// This includs a byte length, which is the required length of the
15/// data from the file or URI (so that byte offsets may be validated,
16/// for example).
17#[derive(Debug, Default)]
18#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
19#[cfg_attr(feature = "serde", serde(default))]
20pub struct GltfBuffer {
21    /// The URI specified by the buffer; this might be a data:URI containing
22    /// the data itself, or maybe a relative path to a binary data or image
23    uri: String,
24    /// The byte length of the buffer - any provided URI contents must be at
25    /// least this length
26    #[cfg_attr(feature = "serde", serde(rename = "byteLength"))]
27    byte_length: usize,
28}
29
30//ip GltfBuffer
31impl GltfBuffer {
32    //ap uri
33    /// Get a reference to the URI of the buffer
34    pub fn uri(&self) -> &str {
35        &self.uri
36    }
37
38    //ap byte_length
39    /// Get the byte length of the buffer
40    pub fn byte_length(&self) -> usize {
41        self.byte_length
42    }
43
44    //cp of_base64
45    /// Create from a Base64
46    pub fn of_base64<T: AsRef<[u8]>>(data: T) -> Self {
47        use base64::engine::general_purpose;
48        use base64::Engine;
49        let byte_length = data.as_ref().len();
50        let mut uri = general_purpose::STANDARD.encode(data);
51        uri.insert_str(0, "data:application/octet-stream;base64,");
52        Self { uri, byte_length }
53    }
54
55    //mp take_buffer
56    /// Take all the contents of the buffer, leaving a buffer in place with an
57    /// empty URI
58    ///
59    /// This allows for a large data: URI to be dropped from the Gltf JSON when
60    /// the data has been moved into a real buffer
61    pub fn take_buffer(&mut self) -> Self {
62        Self {
63            uri: std::mem::take(&mut self.uri),
64            byte_length: self.byte_length,
65        }
66    }
67}
68
69//tp GltfBufferView
70/// A view onto a buffer (referred to by an index into the Gltf file array of
71/// buffers), referencing a subset of the buffer given by an offset and length
72///
73/// This becomes a BufferDescriptor
74#[derive(Debug, Default)]
75#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
76#[cfg_attr(feature = "serde", serde(default))]
77pub struct GltfBufferView {
78    pub buffer: BufferIndex,
79    #[cfg_attr(feature = "serde", serde(rename = "byteLength"))]
80    pub byte_length: usize,
81    #[cfg_attr(feature = "serde", serde(rename = "byteOffset"))]
82    pub byte_offset: usize,
83    #[cfg_attr(feature = "serde", serde(rename = "byteStride"))]
84    pub byte_stride: Option<usize>,
85}
86
87impl GltfBufferView {
88    //ap buffer
89    pub fn buffer(&self) -> BufferIndex {
90        self.buffer
91    }
92
93    //ap byte_offset
94    pub fn byte_offset(&self) -> usize {
95        self.byte_offset
96    }
97
98    //ap byte_length
99    pub fn byte_length(&self) -> usize {
100        self.byte_length
101    }
102
103    //ap byte_stride
104    pub fn byte_stride(&self, default: usize) -> usize {
105        self.byte_stride.unwrap_or(default)
106    }
107
108    //ap byte_end
109    pub fn byte_end(&self) -> usize {
110        self.byte_offset + self.byte_length
111    }
112}
113
114//tp GltfAccessor
115/// A Gltf accessor which references a buffer view to provide the data for
116/// either indices or an atttribute for a vertex
117///
118/// An Accessor is a stride-separated set of N-element data structures,
119/// providing a list of matrices, vectors, or just scalar sets of floats or ints
120///
121/// The stride is provided by the buffer view itself, as it is common for all
122/// accessors using a buffer view (in Gltf). If the buffer view has a stride of
123/// 0 then the actual stride is the size of the N-element type.
124#[derive(Debug)]
125#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
126// #[cfg_attr(feature = "serde", serde(default))]
127pub struct GltfAccessor {
128    /// The buffer view that contains the data for the accessor
129    ///
130    /// If this is None then zeros are supposed to be used for the accessor
131    /// contents
132    #[cfg_attr(feature = "serde", serde(rename = "bufferView"))]
133    buffer_view: Option<ViewIndex>,
134
135    /// Byte offset from start of the view (or offset+k*stride) for the
136    /// N-element data structure the accessor defines
137    #[cfg_attr(feature = "serde", serde(rename = "byteOffset"))]
138    #[cfg_attr(feature = "serde", serde(default))]
139    byte_offset: usize,
140
141    /// The type of the element; in Gltf JSON this is encoded with a magic
142    /// number; the default value is signed 32-bit integer
143    #[cfg_attr(feature = "serde", serde(rename = "componentType"))]
144    // 5120-5126: s8, u8, s16, u16, s32, u32, f32 else s32
145    #[cfg_attr(
146        feature = "serde",
147        serde(deserialize_with = "deserialize::comp_type_to_ele_type")
148    )]
149    #[cfg_attr(feature = "serde", serde(default = "deserialize::ele_type_s32"))]
150    #[cfg_attr(
151        feature = "serde",
152        serde(serialize_with = "serialize::ele_type_to_comp_type")
153    )]
154    component_type: mod3d_base::BufferElementType,
155
156    /// Count of the number of data
157    // minimum 1
158    #[cfg_attr(feature = "serde", serde(rename = "count"))]
159    count: usize,
160
161    /// Number of elements per data
162    #[cfg_attr(feature = "serde", serde(rename = "type"))]
163    #[cfg_attr(
164        feature = "serde",
165        serde(deserialize_with = "deserialize::type_to_num")
166    )]
167    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize::num_to_type"))]
168    // SCALAR, VEC2, VEC3, VEC5, MAT2, MAT3, MAT4, string
169    elements_per_data: usize,
170    // optional: normalized, max, min, sparse
171    // optional: name, extensions, extras
172}
173
174//ip GltfAccessor
175impl GltfAccessor {
176    pub fn new(
177        buffer_view: ViewIndex,
178        byte_offset: usize,
179        count: usize,
180        component_type: mod3d_base::BufferElementType,
181        elements_per_data: usize,
182    ) -> Self {
183        let buffer_view = Some(buffer_view);
184        Self {
185            buffer_view,
186            byte_offset,
187            count,
188            component_type,
189            elements_per_data,
190        }
191    }
192
193    //ap buffer_view
194    pub fn buffer_view(&self) -> Option<ViewIndex> {
195        self.buffer_view
196    }
197
198    //ap byte_offset
199    pub fn byte_offset(&self) -> usize {
200        self.byte_offset
201    }
202
203    //ap count
204    pub fn count(&self) -> usize {
205        self.count
206    }
207
208    //ap component_type
209    pub fn component_type(&self) -> mod3d_base::BufferElementType {
210        self.component_type
211    }
212
213    //ap ele_byte_size
214    pub fn ele_byte_size(&self) -> usize {
215        self.elements_per_data * self.component_type().byte_length() as usize
216    }
217
218    //ap elements_per_data
219    pub fn elements_per_data(&self) -> usize {
220        self.elements_per_data
221    }
222
223    //ap byte_stride
224    pub fn byte_stride(&self, view_byte_stride: usize) -> usize {
225        if view_byte_stride != 0 {
226            view_byte_stride
227        } else {
228            self.ele_byte_size()
229        }
230    }
231
232    //ap byte_view_end
233    /// Return the byte 1 past the last view byte used
234    pub fn byte_view_end(&self, view_byte_stride: usize) -> usize {
235        let byte_stride = self.byte_stride(view_byte_stride);
236        self.byte_offset + byte_stride * (self.count - 1) + self.ele_byte_size()
237    }
238}