Skip to main content

mtl_gpu/acceleration/motion_geometry/
bounding_box.rs

1//! Motion bounding box geometry descriptor for acceleration structures.
2
3use std::ffi::c_void;
4use std::ptr::NonNull;
5
6use mtl_foundation::{Referencing, UInteger};
7use mtl_sys::{msg_send_0, msg_send_1, sel};
8
9use crate::Buffer;
10
11/// Descriptor for motion bounding box geometry in acceleration structures.
12///
13/// C++ equivalent: `MTL::AccelerationStructureMotionBoundingBoxGeometryDescriptor`
14#[repr(transparent)]
15pub struct AccelerationStructureMotionBoundingBoxGeometryDescriptor(pub(crate) NonNull<c_void>);
16
17impl AccelerationStructureMotionBoundingBoxGeometryDescriptor {
18    /// Create a new motion bounding box geometry descriptor.
19    ///
20    /// C++ equivalent: `static AccelerationStructureMotionBoundingBoxGeometryDescriptor* alloc()->init()`
21    pub fn new() -> Option<Self> {
22        unsafe {
23            let class = mtl_sys::Class::get(
24                "MTLAccelerationStructureMotionBoundingBoxGeometryDescriptor",
25            )?;
26            let ptr: *mut c_void = msg_send_0(class.as_ptr(), sel!(alloc));
27            if ptr.is_null() {
28                return None;
29            }
30            let ptr: *mut c_void = msg_send_0(ptr, sel!(init));
31            Self::from_raw(ptr)
32        }
33    }
34
35    /// Create from a raw pointer.
36    ///
37    /// # Safety
38    ///
39    /// The pointer must be a valid Metal motion bounding box geometry descriptor.
40    #[inline]
41    pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
42        NonNull::new(ptr).map(Self)
43    }
44
45    /// Get the raw pointer.
46    #[inline]
47    pub fn as_raw(&self) -> *mut c_void {
48        self.0.as_ptr()
49    }
50
51    // Inherited properties from AccelerationStructureGeometryDescriptor
52
53    /// Get whether duplicate intersection function invocation is allowed.
54    #[inline]
55    pub fn allow_duplicate_intersection_function_invocation(&self) -> bool {
56        unsafe {
57            msg_send_0(
58                self.as_ptr(),
59                sel!(allowDuplicateIntersectionFunctionInvocation),
60            )
61        }
62    }
63
64    /// Set whether duplicate intersection function invocation is allowed.
65    #[inline]
66    pub fn set_allow_duplicate_intersection_function_invocation(&self, allow: bool) {
67        unsafe {
68            msg_send_1::<(), bool>(
69                self.as_ptr(),
70                sel!(setAllowDuplicateIntersectionFunctionInvocation:),
71                allow,
72            );
73        }
74    }
75
76    /// Get the intersection function table offset.
77    #[inline]
78    pub fn intersection_function_table_offset(&self) -> UInteger {
79        unsafe { msg_send_0(self.as_ptr(), sel!(intersectionFunctionTableOffset)) }
80    }
81
82    /// Set the intersection function table offset.
83    #[inline]
84    pub fn set_intersection_function_table_offset(&self, offset: UInteger) {
85        unsafe {
86            msg_send_1::<(), UInteger>(
87                self.as_ptr(),
88                sel!(setIntersectionFunctionTableOffset:),
89                offset,
90            );
91        }
92    }
93
94    /// Get whether geometry is opaque.
95    #[inline]
96    pub fn opaque(&self) -> bool {
97        unsafe { msg_send_0(self.as_ptr(), sel!(opaque)) }
98    }
99
100    /// Set whether geometry is opaque.
101    #[inline]
102    pub fn set_opaque(&self, opaque: bool) {
103        unsafe {
104            msg_send_1::<(), bool>(self.as_ptr(), sel!(setOpaque:), opaque);
105        }
106    }
107
108    /// Get the label.
109    pub fn label(&self) -> Option<String> {
110        unsafe {
111            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(label));
112            if ptr.is_null() {
113                return None;
114            }
115            let utf8_ptr: *const std::ffi::c_char =
116                mtl_sys::msg_send_0(ptr as *const c_void, sel!(UTF8String));
117            if utf8_ptr.is_null() {
118                return None;
119            }
120            let c_str = std::ffi::CStr::from_ptr(utf8_ptr);
121            Some(c_str.to_string_lossy().into_owned())
122        }
123    }
124
125    /// Set the label.
126    pub fn set_label(&self, label: &str) {
127        if let Some(ns_label) = mtl_foundation::String::from_str(label) {
128            unsafe {
129                msg_send_1::<(), *const c_void>(self.as_ptr(), sel!(setLabel:), ns_label.as_ptr());
130            }
131        }
132    }
133
134    /// Get the primitive data buffer.
135    pub fn primitive_data_buffer(&self) -> Option<Buffer> {
136        unsafe {
137            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(primitiveDataBuffer));
138            if ptr.is_null() {
139                return None;
140            }
141            let _: *mut c_void = msg_send_0(ptr, sel!(retain));
142            Buffer::from_raw(ptr)
143        }
144    }
145
146    /// Set the primitive data buffer.
147    pub fn set_primitive_data_buffer(&self, buffer: Option<&Buffer>) {
148        unsafe {
149            msg_send_1::<(), *const c_void>(
150                self.as_ptr(),
151                sel!(setPrimitiveDataBuffer:),
152                buffer.map_or(std::ptr::null(), |b| b.as_ptr()),
153            );
154        }
155    }
156
157    /// Get the primitive data buffer offset.
158    #[inline]
159    pub fn primitive_data_buffer_offset(&self) -> UInteger {
160        unsafe { msg_send_0(self.as_ptr(), sel!(primitiveDataBufferOffset)) }
161    }
162
163    /// Set the primitive data buffer offset.
164    #[inline]
165    pub fn set_primitive_data_buffer_offset(&self, offset: UInteger) {
166        unsafe {
167            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setPrimitiveDataBufferOffset:), offset);
168        }
169    }
170
171    /// Get the primitive data element size.
172    #[inline]
173    pub fn primitive_data_element_size(&self) -> UInteger {
174        unsafe { msg_send_0(self.as_ptr(), sel!(primitiveDataElementSize)) }
175    }
176
177    /// Set the primitive data element size.
178    #[inline]
179    pub fn set_primitive_data_element_size(&self, size: UInteger) {
180        unsafe {
181            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setPrimitiveDataElementSize:), size);
182        }
183    }
184
185    /// Get the primitive data stride.
186    #[inline]
187    pub fn primitive_data_stride(&self) -> UInteger {
188        unsafe { msg_send_0(self.as_ptr(), sel!(primitiveDataStride)) }
189    }
190
191    /// Set the primitive data stride.
192    #[inline]
193    pub fn set_primitive_data_stride(&self, stride: UInteger) {
194        unsafe {
195            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setPrimitiveDataStride:), stride);
196        }
197    }
198
199    // Motion bounding box-specific properties
200
201    /// Get the bounding box count.
202    ///
203    /// C++ equivalent: `NS::UInteger boundingBoxCount() const`
204    #[inline]
205    pub fn bounding_box_count(&self) -> UInteger {
206        unsafe { msg_send_0(self.as_ptr(), sel!(boundingBoxCount)) }
207    }
208
209    /// Set the bounding box count.
210    ///
211    /// C++ equivalent: `void setBoundingBoxCount(NS::UInteger)`
212    #[inline]
213    pub fn set_bounding_box_count(&self, count: UInteger) {
214        unsafe {
215            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setBoundingBoxCount:), count);
216        }
217    }
218
219    /// Get the bounding box stride.
220    ///
221    /// C++ equivalent: `NS::UInteger boundingBoxStride() const`
222    #[inline]
223    pub fn bounding_box_stride(&self) -> UInteger {
224        unsafe { msg_send_0(self.as_ptr(), sel!(boundingBoxStride)) }
225    }
226
227    /// Set the bounding box stride.
228    ///
229    /// C++ equivalent: `void setBoundingBoxStride(NS::UInteger)`
230    #[inline]
231    pub fn set_bounding_box_stride(&self, stride: UInteger) {
232        unsafe {
233            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setBoundingBoxStride:), stride);
234        }
235    }
236
237    /// Get the bounding box buffers as a raw NS::Array pointer.
238    ///
239    /// C++ equivalent: `NS::Array* boundingBoxBuffers() const`
240    ///
241    /// # Safety
242    ///
243    /// The returned pointer is an NS::Array containing MotionKeyframeData objects.
244    /// The caller must manage the memory appropriately.
245    #[inline]
246    pub fn bounding_box_buffers_ptr(&self) -> *const c_void {
247        unsafe { msg_send_0(self.as_ptr(), sel!(boundingBoxBuffers)) }
248    }
249
250    /// Set the bounding box buffers from a raw NS::Array pointer.
251    ///
252    /// C++ equivalent: `void setBoundingBoxBuffers(const NS::Array*)`
253    ///
254    /// # Safety
255    ///
256    /// The bounding_box_buffers pointer must be a valid NS::Array or null.
257    pub unsafe fn set_bounding_box_buffers_ptr(&self, bounding_box_buffers: *const c_void) {
258        unsafe {
259            msg_send_1::<(), *const c_void>(
260                self.as_ptr(),
261                sel!(setBoundingBoxBuffers:),
262                bounding_box_buffers,
263            );
264        }
265    }
266}
267
268impl Default for AccelerationStructureMotionBoundingBoxGeometryDescriptor {
269    fn default() -> Self {
270        Self::new().expect("failed to create motion bounding box geometry descriptor")
271    }
272}
273
274impl Clone for AccelerationStructureMotionBoundingBoxGeometryDescriptor {
275    fn clone(&self) -> Self {
276        unsafe {
277            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(copy));
278            Self::from_raw(ptr).expect("failed to copy motion bounding box geometry descriptor")
279        }
280    }
281}
282
283impl Drop for AccelerationStructureMotionBoundingBoxGeometryDescriptor {
284    fn drop(&mut self) {
285        unsafe {
286            msg_send_0::<()>(self.as_ptr(), sel!(release));
287        }
288    }
289}
290
291impl Referencing for AccelerationStructureMotionBoundingBoxGeometryDescriptor {
292    #[inline]
293    fn as_ptr(&self) -> *const c_void {
294        self.0.as_ptr()
295    }
296}
297
298unsafe impl Send for AccelerationStructureMotionBoundingBoxGeometryDescriptor {}
299unsafe impl Sync for AccelerationStructureMotionBoundingBoxGeometryDescriptor {}