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 {
13 handle: ObjectHandle,
14 length: usize,
15}
16
17impl MeshBufferMap {
18 fn from_handle(handle: ObjectHandle, length: usize) -> Self {
19 Self { handle, length }
20 }
21
22 pub(crate) fn as_ptr(&self) -> *mut core::ffi::c_void {
24 self.handle.as_ptr()
25 }
26
27 #[must_use]
28 pub fn length(&self) -> usize {
30 self.length
31 }
32
33 #[must_use]
34 pub fn bytes(&self) -> Vec<u8> {
36 let mut bytes = vec![0_u8; self.length];
37 if bytes.is_empty() {
38 return bytes;
39 }
40 let written = unsafe {
42 ffi::mdl_mesh_buffer_map_copy_bytes(
43 self.as_ptr(),
44 self.length as u64,
45 bytes.as_mut_ptr(),
46 bytes.len() as u64,
47 )
48 } as usize;
49 bytes.truncate(written);
50 bytes
51 }
52
53 pub fn write(&self, offset: usize, bytes: &[u8]) -> usize {
55 unsafe {
57 ffi::mdl_mesh_buffer_map_write_bytes(
58 self.as_ptr(),
59 self.length as u64,
60 bytes.as_ptr(),
61 bytes.len() as u64,
62 offset as u64,
63 ) as usize
64 }
65 }
66}
67
68#[derive(Debug, Clone)]
69pub struct MeshBufferAllocator {
71 handle: ObjectHandle,
72}
73
74impl MeshBufferAllocator {
75 pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
77 Self { handle }
78 }
79
80 pub(crate) fn as_ptr(&self) -> *mut core::ffi::c_void {
82 self.handle.as_ptr()
83 }
84
85 pub fn new_zone(&self, capacity: usize) -> Result<MeshBufferZone> {
87 let mut out_zone = ptr::null_mut();
88 let mut out_error = ptr::null_mut();
89 let status = unsafe {
91 ffi::mdl_mesh_buffer_allocator_new_zone(
92 self.as_ptr(),
93 capacity as u64,
94 &mut out_zone,
95 &mut out_error,
96 )
97 };
98 crate::util::status_result(status, out_error)?;
99 Ok(MeshBufferZone::from_handle(required_handle(
100 out_zone,
101 "MDLMeshBufferZone",
102 )?))
103 }
104
105 pub fn new_zone_for_buffers(
107 &self,
108 sizes: &[usize],
109 types: &[MeshBufferType],
110 ) -> Result<MeshBufferZone> {
111 if sizes.len() != types.len() {
112 return Err(ModelIoError::new(
113 ffi::status::INVALID_ARGUMENT,
114 "mesh buffer sizes and types must have the same length",
115 ));
116 }
117 let raw_sizes = sizes.iter().map(|size| *size as u64).collect::<Vec<_>>();
118 let raw_types = types
119 .iter()
120 .map(|buffer_type| buffer_type.as_raw())
121 .collect::<Vec<_>>();
122 let mut out_zone = ptr::null_mut();
123 let mut out_error = ptr::null_mut();
124 let status = unsafe {
126 ffi::mdl_mesh_buffer_allocator_new_zone_for_buffers_with_size(
127 self.as_ptr(),
128 raw_sizes.as_ptr(),
129 raw_types.as_ptr(),
130 raw_sizes.len() as u64,
131 &mut out_zone,
132 &mut out_error,
133 )
134 };
135 crate::util::status_result(status, out_error)?;
136 Ok(MeshBufferZone::from_handle(required_handle(
137 out_zone,
138 "MDLMeshBufferZone",
139 )?))
140 }
141
142 pub fn new_buffer(&self, length: usize, buffer_type: MeshBufferType) -> Result<MeshBuffer> {
144 let mut out_buffer = ptr::null_mut();
145 let mut out_error = ptr::null_mut();
146 let status = unsafe {
148 ffi::mdl_mesh_buffer_allocator_new_buffer(
149 self.as_ptr(),
150 length as u64,
151 buffer_type.as_raw(),
152 &mut out_buffer,
153 &mut out_error,
154 )
155 };
156 crate::util::status_result(status, out_error)?;
157 Ok(MeshBuffer::from_handle(required_handle(
158 out_buffer,
159 "MDLMeshBuffer",
160 )?))
161 }
162
163 pub fn new_buffer_with_data(
165 &self,
166 data: &[u8],
167 buffer_type: MeshBufferType,
168 ) -> Result<MeshBuffer> {
169 let mut out_buffer = ptr::null_mut();
170 let mut out_error = ptr::null_mut();
171 let status = unsafe {
173 ffi::mdl_mesh_buffer_allocator_new_buffer_with_data(
174 self.as_ptr(),
175 data.as_ptr(),
176 data.len() 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(MeshBuffer::from_handle(required_handle(
184 out_buffer,
185 "MDLMeshBuffer",
186 )?))
187 }
188
189 pub fn new_buffer_from_zone(
191 &self,
192 zone: Option<&MeshBufferZone>,
193 length: usize,
194 buffer_type: MeshBufferType,
195 ) -> Result<Option<MeshBuffer>> {
196 let mut out_buffer = ptr::null_mut();
197 let mut out_error = ptr::null_mut();
198 let status = unsafe {
200 ffi::mdl_mesh_buffer_allocator_new_buffer_from_zone_length(
201 self.as_ptr(),
202 zone.map_or(ptr::null_mut(), MeshBufferZone::as_ptr),
203 length as u64,
204 buffer_type.as_raw(),
205 &mut out_buffer,
206 &mut out_error,
207 )
208 };
209 crate::util::status_result(status, out_error)?;
210 Ok(unsafe { ObjectHandle::from_retained_ptr(out_buffer) }.map(MeshBuffer::from_handle))
212 }
213
214 pub fn new_buffer_from_zone_with_data(
216 &self,
217 zone: Option<&MeshBufferZone>,
218 data: &[u8],
219 buffer_type: MeshBufferType,
220 ) -> Result<Option<MeshBuffer>> {
221 let mut out_buffer = ptr::null_mut();
222 let mut out_error = ptr::null_mut();
223 let status = unsafe {
225 ffi::mdl_mesh_buffer_allocator_new_buffer_from_zone_data(
226 self.as_ptr(),
227 zone.map_or(ptr::null_mut(), MeshBufferZone::as_ptr),
228 data.as_ptr(),
229 data.len() as u64,
230 buffer_type.as_raw(),
231 &mut out_buffer,
232 &mut out_error,
233 )
234 };
235 crate::util::status_result(status, out_error)?;
236 Ok(unsafe { ObjectHandle::from_retained_ptr(out_buffer) }.map(MeshBuffer::from_handle))
238 }
239}
240
241#[derive(Debug, Clone)]
242pub struct MeshBufferZone {
244 handle: ObjectHandle,
245}
246
247impl MeshBufferZone {
248 pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
250 Self { handle }
251 }
252
253 pub(crate) fn as_ptr(&self) -> *mut core::ffi::c_void {
255 self.handle.as_ptr()
256 }
257
258 #[must_use]
259 pub fn capacity(&self) -> usize {
261 unsafe { ffi::mdl_mesh_buffer_zone_capacity(self.as_ptr()) as usize }
263 }
264
265 #[must_use]
266 pub fn allocator(&self) -> Option<MeshBufferAllocator> {
268 let ptr = unsafe { ffi::mdl_mesh_buffer_zone_allocator(self.as_ptr()) };
270 unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(MeshBufferAllocator::from_handle)
272 }
273
274 #[must_use]
275 pub fn as_default(&self) -> Option<MeshBufferZoneDefault> {
277 (unsafe { ffi::mdl_mesh_buffer_zone_is_default(self.as_ptr()) != 0 })
279 .then(|| MeshBufferZoneDefault::from_handle(self.handle.clone()))
280 }
281}
282
283#[derive(Debug, Clone)]
284pub struct MeshBufferZoneDefault {
286 handle: ObjectHandle,
287}
288
289impl MeshBufferZoneDefault {
290 fn from_handle(handle: ObjectHandle) -> Self {
291 Self { handle }
292 }
293
294 pub fn new() -> Result<Self> {
296 let mut out_zone = ptr::null_mut();
297 let mut out_error = ptr::null_mut();
298 let status =
299 unsafe { ffi::mdl_mesh_buffer_zone_default_new(&mut out_zone, &mut out_error) };
301 crate::util::status_result(status, out_error)?;
302 Ok(Self::from_handle(required_handle(
303 out_zone,
304 "MDLMeshBufferZoneDefault",
305 )?))
306 }
307
308 #[must_use]
309 pub fn capacity(&self) -> usize {
311 unsafe { ffi::mdl_mesh_buffer_zone_capacity(self.handle.as_ptr()) as usize }
313 }
314
315 #[must_use]
316 pub fn allocator(&self) -> Option<MeshBufferAllocator> {
318 let ptr = unsafe { ffi::mdl_mesh_buffer_zone_allocator(self.handle.as_ptr()) };
320 unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(MeshBufferAllocator::from_handle)
322 }
323
324 #[must_use]
325 pub fn as_mesh_buffer_zone(&self) -> MeshBufferZone {
327 MeshBufferZone::from_handle(self.handle.clone())
328 }
329}
330
331#[derive(Debug, Clone)]
332pub struct MeshBufferData {
334 handle: ObjectHandle,
335}
336
337impl MeshBufferData {
338 fn from_handle(handle: ObjectHandle) -> Self {
339 Self { handle }
340 }
341
342 pub fn new(length: usize, buffer_type: MeshBufferType) -> Result<Self> {
344 let mut out_buffer = ptr::null_mut();
345 let mut out_error = ptr::null_mut();
346 let status = unsafe {
348 ffi::mdl_mesh_buffer_data_new(
349 length as u64,
350 buffer_type.as_raw(),
351 &mut out_buffer,
352 &mut out_error,
353 )
354 };
355 crate::util::status_result(status, out_error)?;
356 Ok(Self::from_handle(required_handle(
357 out_buffer,
358 "MDLMeshBufferData",
359 )?))
360 }
361
362 pub fn from_bytes(data: &[u8], buffer_type: MeshBufferType) -> Result<Self> {
364 let mut out_buffer = ptr::null_mut();
365 let mut out_error = ptr::null_mut();
366 let status = unsafe {
368 ffi::mdl_mesh_buffer_data_new_with_bytes(
369 data.as_ptr(),
370 data.len() as u64,
371 buffer_type.as_raw(),
372 &mut out_buffer,
373 &mut out_error,
374 )
375 };
376 crate::util::status_result(status, out_error)?;
377 Ok(Self::from_handle(required_handle(
378 out_buffer,
379 "MDLMeshBufferData",
380 )?))
381 }
382
383 #[must_use]
384 pub fn data(&self) -> Vec<u8> {
386 let info = self.as_mesh_buffer().info().ok();
387 let mut bytes = vec![0_u8; info.map_or(0, |buffer| buffer.length)];
388 if bytes.is_empty() {
389 return bytes;
390 }
391 let written = unsafe {
393 ffi::mdl_mesh_buffer_data_copy_data(
394 self.handle.as_ptr(),
395 bytes.as_mut_ptr(),
396 bytes.len() as u64,
397 )
398 } as usize;
399 bytes.truncate(written);
400 bytes
401 }
402
403 pub fn map(&self) -> Result<MeshBufferMap> {
405 self.as_mesh_buffer().map()
406 }
407
408 #[must_use]
409 pub fn as_mesh_buffer(&self) -> MeshBuffer {
411 MeshBuffer::from_handle(self.handle.clone())
412 }
413}
414
415#[derive(Debug, Clone)]
416pub struct MeshBufferDataAllocator {
418 handle: ObjectHandle,
419}
420
421impl MeshBufferDataAllocator {
422 pub fn new() -> Result<Self> {
424 let mut out_allocator = ptr::null_mut();
425 let mut out_error = ptr::null_mut();
426 let status =
427 unsafe { ffi::mdl_mesh_buffer_data_allocator_new(&mut out_allocator, &mut out_error) };
429 crate::util::status_result(status, out_error)?;
430 Ok(Self {
431 handle: required_handle(out_allocator, "MDLMeshBufferDataAllocator")?,
432 })
433 }
434
435 #[must_use]
436 pub fn as_mesh_buffer_allocator(&self) -> MeshBufferAllocator {
438 MeshBufferAllocator::from_handle(self.handle.clone())
439 }
440
441 pub fn new_default_zone(&self, capacity: usize) -> Result<MeshBufferZoneDefault> {
443 self.as_mesh_buffer_allocator()
444 .new_zone(capacity)?
445 .as_default()
446 .ok_or_else(|| {
447 ModelIoError::new(
448 ffi::status::NULL_RESULT,
449 "MDLMeshBufferDataAllocator zone was not MDLMeshBufferZoneDefault",
450 )
451 })
452 }
453}
454
455impl MeshBuffer {
456 pub fn fill_data(&self, data: &[u8], offset: usize) {
458 unsafe {
460 ffi::mdl_mesh_buffer_fill_data(
461 self.as_ptr(),
462 data.as_ptr(),
463 data.len() as u64,
464 offset as u64,
465 );
466 }
467 }
468
469 pub fn map(&self) -> Result<MeshBufferMap> {
471 let length = self.info()?.length;
472 let ptr = unsafe { ffi::mdl_mesh_buffer_map(self.as_ptr()) };
474 Ok(MeshBufferMap::from_handle(
475 required_handle(ptr, "MDLMeshBufferMap")?,
476 length,
477 ))
478 }
479
480 #[must_use]
481 pub fn allocator(&self) -> Option<MeshBufferAllocator> {
483 let ptr = unsafe { ffi::mdl_mesh_buffer_allocator(self.as_ptr()) };
485 unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(MeshBufferAllocator::from_handle)
487 }
488
489 #[must_use]
490 pub fn zone(&self) -> Option<MeshBufferZone> {
492 let ptr = unsafe { ffi::mdl_mesh_buffer_zone(self.as_ptr()) };
494 unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(MeshBufferZone::from_handle)
496 }
497
498 #[must_use]
499 pub fn as_data_buffer(&self) -> Option<MeshBufferData> {
501 if unsafe { ffi::mdl_mesh_buffer_is_data(self.as_ptr()) == 0 } {
503 return None;
504 }
505 let retained = unsafe { ffi::mdl_object_retain(self.as_ptr()) };
507 unsafe { ObjectHandle::from_retained_ptr(retained) }.map(MeshBufferData::from_handle)
509 }
510}