1use std::ptr;
2
3use crate::error::{ModelIoError, Result};
4use crate::ffi;
5use crate::handle::ObjectHandle;
6use crate::mesh::MeshBuffer;
7use crate::types::MeshBufferType;
8use crate::util::required_handle;
9
10#[derive(Debug, Clone)]
11pub struct MeshBufferMap {
12 handle: ObjectHandle,
13 length: usize,
14}
15
16impl MeshBufferMap {
17 fn from_handle(handle: ObjectHandle, length: usize) -> Self {
18 Self { handle, length }
19 }
20
21 pub(crate) fn as_ptr(&self) -> *mut core::ffi::c_void {
22 self.handle.as_ptr()
23 }
24
25 #[must_use]
26 pub fn length(&self) -> usize {
27 self.length
28 }
29
30 #[must_use]
31 pub fn bytes(&self) -> Vec<u8> {
32 let mut bytes = vec![0_u8; self.length];
33 if bytes.is_empty() {
34 return bytes;
35 }
36 let written = unsafe {
37 ffi::mdl_mesh_buffer_map_copy_bytes(
38 self.as_ptr(),
39 self.length as u64,
40 bytes.as_mut_ptr(),
41 bytes.len() as u64,
42 )
43 } as usize;
44 bytes.truncate(written);
45 bytes
46 }
47
48 pub fn write(&self, offset: usize, bytes: &[u8]) -> usize {
49 unsafe {
50 ffi::mdl_mesh_buffer_map_write_bytes(
51 self.as_ptr(),
52 self.length as u64,
53 bytes.as_ptr(),
54 bytes.len() as u64,
55 offset as u64,
56 ) as usize
57 }
58 }
59}
60
61#[derive(Debug, Clone)]
62pub struct MeshBufferAllocator {
63 handle: ObjectHandle,
64}
65
66impl MeshBufferAllocator {
67 pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
68 Self { handle }
69 }
70
71 pub(crate) fn as_ptr(&self) -> *mut core::ffi::c_void {
72 self.handle.as_ptr()
73 }
74
75 pub fn new_zone(&self, capacity: usize) -> Result<MeshBufferZone> {
76 let mut out_zone = ptr::null_mut();
77 let mut out_error = ptr::null_mut();
78 let status = unsafe {
79 ffi::mdl_mesh_buffer_allocator_new_zone(
80 self.as_ptr(),
81 capacity as u64,
82 &mut out_zone,
83 &mut out_error,
84 )
85 };
86 crate::util::status_result(status, out_error)?;
87 Ok(MeshBufferZone::from_handle(required_handle(
88 out_zone,
89 "MDLMeshBufferZone",
90 )?))
91 }
92
93 pub fn new_zone_for_buffers(
94 &self,
95 sizes: &[usize],
96 types: &[MeshBufferType],
97 ) -> Result<MeshBufferZone> {
98 if sizes.len() != types.len() {
99 return Err(ModelIoError::new(
100 ffi::status::INVALID_ARGUMENT,
101 "mesh buffer sizes and types must have the same length",
102 ));
103 }
104 let raw_sizes = sizes.iter().map(|size| *size as u64).collect::<Vec<_>>();
105 let raw_types = types.iter().map(|buffer_type| buffer_type.as_raw()).collect::<Vec<_>>();
106 let mut out_zone = ptr::null_mut();
107 let mut out_error = ptr::null_mut();
108 let status = unsafe {
109 ffi::mdl_mesh_buffer_allocator_new_zone_for_buffers_with_size(
110 self.as_ptr(),
111 raw_sizes.as_ptr(),
112 raw_types.as_ptr(),
113 raw_sizes.len() as u64,
114 &mut out_zone,
115 &mut out_error,
116 )
117 };
118 crate::util::status_result(status, out_error)?;
119 Ok(MeshBufferZone::from_handle(required_handle(
120 out_zone,
121 "MDLMeshBufferZone",
122 )?))
123 }
124
125 pub fn new_buffer(&self, length: usize, buffer_type: MeshBufferType) -> Result<MeshBuffer> {
126 let mut out_buffer = ptr::null_mut();
127 let mut out_error = ptr::null_mut();
128 let status = unsafe {
129 ffi::mdl_mesh_buffer_allocator_new_buffer(
130 self.as_ptr(),
131 length as u64,
132 buffer_type.as_raw(),
133 &mut out_buffer,
134 &mut out_error,
135 )
136 };
137 crate::util::status_result(status, out_error)?;
138 Ok(MeshBuffer::from_handle(required_handle(
139 out_buffer,
140 "MDLMeshBuffer",
141 )?))
142 }
143
144 pub fn new_buffer_with_data(&self, data: &[u8], buffer_type: MeshBufferType) -> Result<MeshBuffer> {
145 let mut out_buffer = ptr::null_mut();
146 let mut out_error = ptr::null_mut();
147 let status = unsafe {
148 ffi::mdl_mesh_buffer_allocator_new_buffer_with_data(
149 self.as_ptr(),
150 data.as_ptr(),
151 data.len() as u64,
152 buffer_type.as_raw(),
153 &mut out_buffer,
154 &mut out_error,
155 )
156 };
157 crate::util::status_result(status, out_error)?;
158 Ok(MeshBuffer::from_handle(required_handle(
159 out_buffer,
160 "MDLMeshBuffer",
161 )?))
162 }
163
164 pub fn new_buffer_from_zone(
165 &self,
166 zone: Option<&MeshBufferZone>,
167 length: usize,
168 buffer_type: MeshBufferType,
169 ) -> Result<Option<MeshBuffer>> {
170 let mut out_buffer = ptr::null_mut();
171 let mut out_error = ptr::null_mut();
172 let status = unsafe {
173 ffi::mdl_mesh_buffer_allocator_new_buffer_from_zone_length(
174 self.as_ptr(),
175 zone.map_or(ptr::null_mut(), MeshBufferZone::as_ptr),
176 length as u64,
177 buffer_type.as_raw(),
178 &mut out_buffer,
179 &mut out_error,
180 )
181 };
182 crate::util::status_result(status, out_error)?;
183 Ok(unsafe { ObjectHandle::from_retained_ptr(out_buffer) }.map(MeshBuffer::from_handle))
184 }
185
186 pub fn new_buffer_from_zone_with_data(
187 &self,
188 zone: Option<&MeshBufferZone>,
189 data: &[u8],
190 buffer_type: MeshBufferType,
191 ) -> Result<Option<MeshBuffer>> {
192 let mut out_buffer = ptr::null_mut();
193 let mut out_error = ptr::null_mut();
194 let status = unsafe {
195 ffi::mdl_mesh_buffer_allocator_new_buffer_from_zone_data(
196 self.as_ptr(),
197 zone.map_or(ptr::null_mut(), MeshBufferZone::as_ptr),
198 data.as_ptr(),
199 data.len() as u64,
200 buffer_type.as_raw(),
201 &mut out_buffer,
202 &mut out_error,
203 )
204 };
205 crate::util::status_result(status, out_error)?;
206 Ok(unsafe { ObjectHandle::from_retained_ptr(out_buffer) }.map(MeshBuffer::from_handle))
207 }
208}
209
210#[derive(Debug, Clone)]
211pub struct MeshBufferZone {
212 handle: ObjectHandle,
213}
214
215impl MeshBufferZone {
216 pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
217 Self { handle }
218 }
219
220 pub(crate) fn as_ptr(&self) -> *mut core::ffi::c_void {
221 self.handle.as_ptr()
222 }
223
224 #[must_use]
225 pub fn capacity(&self) -> usize {
226 unsafe { ffi::mdl_mesh_buffer_zone_capacity(self.as_ptr()) as usize }
227 }
228
229 #[must_use]
230 pub fn allocator(&self) -> Option<MeshBufferAllocator> {
231 let ptr = unsafe { ffi::mdl_mesh_buffer_zone_allocator(self.as_ptr()) };
232 unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(MeshBufferAllocator::from_handle)
233 }
234
235 #[must_use]
236 pub fn as_default(&self) -> Option<MeshBufferZoneDefault> {
237 (unsafe { ffi::mdl_mesh_buffer_zone_is_default(self.as_ptr()) != 0 })
238 .then(|| MeshBufferZoneDefault::from_handle(self.handle.clone()))
239 }
240}
241
242#[derive(Debug, Clone)]
243pub struct MeshBufferZoneDefault {
244 handle: ObjectHandle,
245}
246
247impl MeshBufferZoneDefault {
248 fn from_handle(handle: ObjectHandle) -> Self {
249 Self { handle }
250 }
251
252 pub fn new() -> Result<Self> {
253 let mut out_zone = ptr::null_mut();
254 let mut out_error = ptr::null_mut();
255 let status = unsafe { ffi::mdl_mesh_buffer_zone_default_new(&mut out_zone, &mut out_error) };
256 crate::util::status_result(status, out_error)?;
257 Ok(Self::from_handle(required_handle(
258 out_zone,
259 "MDLMeshBufferZoneDefault",
260 )?))
261 }
262
263 #[must_use]
264 pub fn capacity(&self) -> usize {
265 unsafe { ffi::mdl_mesh_buffer_zone_capacity(self.handle.as_ptr()) as usize }
266 }
267
268 #[must_use]
269 pub fn allocator(&self) -> Option<MeshBufferAllocator> {
270 let ptr = unsafe { ffi::mdl_mesh_buffer_zone_allocator(self.handle.as_ptr()) };
271 unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(MeshBufferAllocator::from_handle)
272 }
273
274 #[must_use]
275 pub fn as_mesh_buffer_zone(&self) -> MeshBufferZone {
276 MeshBufferZone::from_handle(self.handle.clone())
277 }
278}
279
280#[derive(Debug, Clone)]
281pub struct MeshBufferData {
282 handle: ObjectHandle,
283}
284
285impl MeshBufferData {
286 fn from_handle(handle: ObjectHandle) -> Self {
287 Self { handle }
288 }
289
290 pub fn new(length: usize, buffer_type: MeshBufferType) -> Result<Self> {
291 let mut out_buffer = ptr::null_mut();
292 let mut out_error = ptr::null_mut();
293 let status = unsafe {
294 ffi::mdl_mesh_buffer_data_new(
295 length as u64,
296 buffer_type.as_raw(),
297 &mut out_buffer,
298 &mut out_error,
299 )
300 };
301 crate::util::status_result(status, out_error)?;
302 Ok(Self::from_handle(required_handle(
303 out_buffer,
304 "MDLMeshBufferData",
305 )?))
306 }
307
308 pub fn from_bytes(data: &[u8], buffer_type: MeshBufferType) -> Result<Self> {
309 let mut out_buffer = ptr::null_mut();
310 let mut out_error = ptr::null_mut();
311 let status = unsafe {
312 ffi::mdl_mesh_buffer_data_new_with_bytes(
313 data.as_ptr(),
314 data.len() as u64,
315 buffer_type.as_raw(),
316 &mut out_buffer,
317 &mut out_error,
318 )
319 };
320 crate::util::status_result(status, out_error)?;
321 Ok(Self::from_handle(required_handle(
322 out_buffer,
323 "MDLMeshBufferData",
324 )?))
325 }
326
327 #[must_use]
328 pub fn data(&self) -> Vec<u8> {
329 let info = self.as_mesh_buffer().info().ok();
330 let mut bytes = vec![0_u8; info.map_or(0, |buffer| buffer.length)];
331 if bytes.is_empty() {
332 return bytes;
333 }
334 let written = unsafe {
335 ffi::mdl_mesh_buffer_data_copy_data(
336 self.handle.as_ptr(),
337 bytes.as_mut_ptr(),
338 bytes.len() as u64,
339 )
340 } as usize;
341 bytes.truncate(written);
342 bytes
343 }
344
345 pub fn map(&self) -> Result<MeshBufferMap> {
346 self.as_mesh_buffer().map()
347 }
348
349 #[must_use]
350 pub fn as_mesh_buffer(&self) -> MeshBuffer {
351 MeshBuffer::from_handle(self.handle.clone())
352 }
353}
354
355#[derive(Debug, Clone)]
356pub struct MeshBufferDataAllocator {
357 handle: ObjectHandle,
358}
359
360impl MeshBufferDataAllocator {
361 pub fn new() -> Result<Self> {
362 let mut out_allocator = ptr::null_mut();
363 let mut out_error = ptr::null_mut();
364 let status = unsafe {
365 ffi::mdl_mesh_buffer_data_allocator_new(&mut out_allocator, &mut out_error)
366 };
367 crate::util::status_result(status, out_error)?;
368 Ok(Self {
369 handle: required_handle(out_allocator, "MDLMeshBufferDataAllocator")?,
370 })
371 }
372
373 #[must_use]
374 pub fn as_mesh_buffer_allocator(&self) -> MeshBufferAllocator {
375 MeshBufferAllocator::from_handle(self.handle.clone())
376 }
377
378 pub fn new_default_zone(&self, capacity: usize) -> Result<MeshBufferZoneDefault> {
379 self.as_mesh_buffer_allocator()
380 .new_zone(capacity)?
381 .as_default()
382 .ok_or_else(|| {
383 ModelIoError::new(
384 ffi::status::NULL_RESULT,
385 "MDLMeshBufferDataAllocator zone was not MDLMeshBufferZoneDefault",
386 )
387 })
388 }
389}
390
391impl MeshBuffer {
392 pub fn fill_data(&self, data: &[u8], offset: usize) {
393 unsafe {
394 ffi::mdl_mesh_buffer_fill_data(
395 self.as_ptr(),
396 data.as_ptr(),
397 data.len() as u64,
398 offset as u64,
399 );
400 }
401 }
402
403 pub fn map(&self) -> Result<MeshBufferMap> {
404 let length = self.info()?.length;
405 let ptr = unsafe { ffi::mdl_mesh_buffer_map(self.as_ptr()) };
406 Ok(MeshBufferMap::from_handle(required_handle(ptr, "MDLMeshBufferMap")?, length))
407 }
408
409 #[must_use]
410 pub fn allocator(&self) -> Option<MeshBufferAllocator> {
411 let ptr = unsafe { ffi::mdl_mesh_buffer_allocator(self.as_ptr()) };
412 unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(MeshBufferAllocator::from_handle)
413 }
414
415 #[must_use]
416 pub fn zone(&self) -> Option<MeshBufferZone> {
417 let ptr = unsafe { ffi::mdl_mesh_buffer_zone(self.as_ptr()) };
418 unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(MeshBufferZone::from_handle)
419 }
420
421 #[must_use]
422 pub fn as_data_buffer(&self) -> Option<MeshBufferData> {
423 if unsafe { ffi::mdl_mesh_buffer_is_data(self.as_ptr()) == 0 } {
424 return None;
425 }
426 let retained = unsafe { ffi::mdl_object_retain(self.as_ptr()) };
427 unsafe { ObjectHandle::from_retained_ptr(retained) }.map(MeshBufferData::from_handle)
428 }
429}