Skip to main content

mtl_gpu/acceleration/motion_geometry/
triangle.rs

1//! Motion triangle 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;
10use crate::enums::{AttributeFormat, IndexType, MatrixLayout};
11
12/// Descriptor for motion triangle geometry in acceleration structures.
13///
14/// C++ equivalent: `MTL::AccelerationStructureMotionTriangleGeometryDescriptor`
15#[repr(transparent)]
16pub struct AccelerationStructureMotionTriangleGeometryDescriptor(pub(crate) NonNull<c_void>);
17
18impl AccelerationStructureMotionTriangleGeometryDescriptor {
19    /// Create a new motion triangle geometry descriptor.
20    ///
21    /// C++ equivalent: `static AccelerationStructureMotionTriangleGeometryDescriptor* alloc()->init()`
22    pub fn new() -> Option<Self> {
23        unsafe {
24            let class =
25                mtl_sys::Class::get("MTLAccelerationStructureMotionTriangleGeometryDescriptor")?;
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 triangle 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 triangle-specific properties
200
201    /// Get the index buffer.
202    ///
203    /// C++ equivalent: `Buffer* indexBuffer() const`
204    pub fn index_buffer(&self) -> Option<Buffer> {
205        unsafe {
206            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(indexBuffer));
207            if ptr.is_null() {
208                return None;
209            }
210            let _: *mut c_void = msg_send_0(ptr, sel!(retain));
211            Buffer::from_raw(ptr)
212        }
213    }
214
215    /// Set the index buffer.
216    ///
217    /// C++ equivalent: `void setIndexBuffer(Buffer*)`
218    pub fn set_index_buffer(&self, buffer: Option<&Buffer>) {
219        unsafe {
220            msg_send_1::<(), *const c_void>(
221                self.as_ptr(),
222                sel!(setIndexBuffer:),
223                buffer.map_or(std::ptr::null(), |b| b.as_ptr()),
224            );
225        }
226    }
227
228    /// Get the index buffer offset.
229    ///
230    /// C++ equivalent: `NS::UInteger indexBufferOffset() const`
231    #[inline]
232    pub fn index_buffer_offset(&self) -> UInteger {
233        unsafe { msg_send_0(self.as_ptr(), sel!(indexBufferOffset)) }
234    }
235
236    /// Set the index buffer offset.
237    ///
238    /// C++ equivalent: `void setIndexBufferOffset(NS::UInteger)`
239    #[inline]
240    pub fn set_index_buffer_offset(&self, offset: UInteger) {
241        unsafe {
242            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setIndexBufferOffset:), offset);
243        }
244    }
245
246    /// Get the index type.
247    ///
248    /// C++ equivalent: `IndexType indexType() const`
249    #[inline]
250    pub fn index_type(&self) -> IndexType {
251        unsafe { msg_send_0(self.as_ptr(), sel!(indexType)) }
252    }
253
254    /// Set the index type.
255    ///
256    /// C++ equivalent: `void setIndexType(IndexType)`
257    #[inline]
258    pub fn set_index_type(&self, index_type: IndexType) {
259        unsafe {
260            msg_send_1::<(), IndexType>(self.as_ptr(), sel!(setIndexType:), index_type);
261        }
262    }
263
264    /// Get the vertex format.
265    ///
266    /// C++ equivalent: `AttributeFormat vertexFormat() const`
267    #[inline]
268    pub fn vertex_format(&self) -> AttributeFormat {
269        unsafe { msg_send_0(self.as_ptr(), sel!(vertexFormat)) }
270    }
271
272    /// Set the vertex format.
273    ///
274    /// C++ equivalent: `void setVertexFormat(AttributeFormat)`
275    #[inline]
276    pub fn set_vertex_format(&self, format: AttributeFormat) {
277        unsafe {
278            msg_send_1::<(), AttributeFormat>(self.as_ptr(), sel!(setVertexFormat:), format);
279        }
280    }
281
282    /// Get the vertex stride.
283    ///
284    /// C++ equivalent: `NS::UInteger vertexStride() const`
285    #[inline]
286    pub fn vertex_stride(&self) -> UInteger {
287        unsafe { msg_send_0(self.as_ptr(), sel!(vertexStride)) }
288    }
289
290    /// Set the vertex stride.
291    ///
292    /// C++ equivalent: `void setVertexStride(NS::UInteger)`
293    #[inline]
294    pub fn set_vertex_stride(&self, stride: UInteger) {
295        unsafe {
296            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setVertexStride:), stride);
297        }
298    }
299
300    /// Get the triangle count.
301    ///
302    /// C++ equivalent: `NS::UInteger triangleCount() const`
303    #[inline]
304    pub fn triangle_count(&self) -> UInteger {
305        unsafe { msg_send_0(self.as_ptr(), sel!(triangleCount)) }
306    }
307
308    /// Set the triangle count.
309    ///
310    /// C++ equivalent: `void setTriangleCount(NS::UInteger)`
311    #[inline]
312    pub fn set_triangle_count(&self, count: UInteger) {
313        unsafe {
314            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setTriangleCount:), count);
315        }
316    }
317
318    /// Get the transformation matrix buffer.
319    ///
320    /// C++ equivalent: `Buffer* transformationMatrixBuffer() const`
321    pub fn transformation_matrix_buffer(&self) -> Option<Buffer> {
322        unsafe {
323            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(transformationMatrixBuffer));
324            if ptr.is_null() {
325                return None;
326            }
327            let _: *mut c_void = msg_send_0(ptr, sel!(retain));
328            Buffer::from_raw(ptr)
329        }
330    }
331
332    /// Set the transformation matrix buffer.
333    ///
334    /// C++ equivalent: `void setTransformationMatrixBuffer(Buffer*)`
335    pub fn set_transformation_matrix_buffer(&self, buffer: Option<&Buffer>) {
336        unsafe {
337            msg_send_1::<(), *const c_void>(
338                self.as_ptr(),
339                sel!(setTransformationMatrixBuffer:),
340                buffer.map_or(std::ptr::null(), |b| b.as_ptr()),
341            );
342        }
343    }
344
345    /// Get the transformation matrix buffer offset.
346    ///
347    /// C++ equivalent: `NS::UInteger transformationMatrixBufferOffset() const`
348    #[inline]
349    pub fn transformation_matrix_buffer_offset(&self) -> UInteger {
350        unsafe { msg_send_0(self.as_ptr(), sel!(transformationMatrixBufferOffset)) }
351    }
352
353    /// Set the transformation matrix buffer offset.
354    ///
355    /// C++ equivalent: `void setTransformationMatrixBufferOffset(NS::UInteger)`
356    #[inline]
357    pub fn set_transformation_matrix_buffer_offset(&self, offset: UInteger) {
358        unsafe {
359            msg_send_1::<(), UInteger>(
360                self.as_ptr(),
361                sel!(setTransformationMatrixBufferOffset:),
362                offset,
363            );
364        }
365    }
366
367    /// Get the transformation matrix layout.
368    ///
369    /// C++ equivalent: `MatrixLayout transformationMatrixLayout() const`
370    #[inline]
371    pub fn transformation_matrix_layout(&self) -> MatrixLayout {
372        unsafe { msg_send_0(self.as_ptr(), sel!(transformationMatrixLayout)) }
373    }
374
375    /// Set the transformation matrix layout.
376    ///
377    /// C++ equivalent: `void setTransformationMatrixLayout(MatrixLayout)`
378    #[inline]
379    pub fn set_transformation_matrix_layout(&self, layout: MatrixLayout) {
380        unsafe {
381            msg_send_1::<(), MatrixLayout>(
382                self.as_ptr(),
383                sel!(setTransformationMatrixLayout:),
384                layout,
385            );
386        }
387    }
388
389    /// Get the vertex buffers as a raw NS::Array pointer.
390    ///
391    /// C++ equivalent: `NS::Array* vertexBuffers() const`
392    ///
393    /// # Safety
394    ///
395    /// The returned pointer is an NS::Array containing MotionKeyframeData objects.
396    /// The caller must manage the memory appropriately.
397    #[inline]
398    pub fn vertex_buffers_ptr(&self) -> *const c_void {
399        unsafe { msg_send_0(self.as_ptr(), sel!(vertexBuffers)) }
400    }
401
402    /// Set the vertex buffers from a raw NS::Array pointer.
403    ///
404    /// C++ equivalent: `void setVertexBuffers(const NS::Array*)`
405    ///
406    /// # Safety
407    ///
408    /// The vertex_buffers pointer must be a valid NS::Array or null.
409    pub unsafe fn set_vertex_buffers_ptr(&self, vertex_buffers: *const c_void) {
410        unsafe {
411            msg_send_1::<(), *const c_void>(self.as_ptr(), sel!(setVertexBuffers:), vertex_buffers);
412        }
413    }
414}
415
416impl Default for AccelerationStructureMotionTriangleGeometryDescriptor {
417    fn default() -> Self {
418        Self::new().expect("failed to create motion triangle geometry descriptor")
419    }
420}
421
422impl Clone for AccelerationStructureMotionTriangleGeometryDescriptor {
423    fn clone(&self) -> Self {
424        unsafe {
425            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(copy));
426            Self::from_raw(ptr).expect("failed to copy motion triangle geometry descriptor")
427        }
428    }
429}
430
431impl Drop for AccelerationStructureMotionTriangleGeometryDescriptor {
432    fn drop(&mut self) {
433        unsafe {
434            msg_send_0::<()>(self.as_ptr(), sel!(release));
435        }
436    }
437}
438
439impl Referencing for AccelerationStructureMotionTriangleGeometryDescriptor {
440    #[inline]
441    fn as_ptr(&self) -> *const c_void {
442        self.0.as_ptr()
443    }
444}
445
446unsafe impl Send for AccelerationStructureMotionTriangleGeometryDescriptor {}
447unsafe impl Sync for AccelerationStructureMotionTriangleGeometryDescriptor {}