Skip to main content

mtl_gpu/acceleration/motion_geometry/
curve.rs

1//! Motion curve 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, CurveBasis, CurveEndCaps, CurveType, IndexType};
11
12/// Descriptor for motion curve geometry in acceleration structures.
13///
14/// C++ equivalent: `MTL::AccelerationStructureMotionCurveGeometryDescriptor`
15#[repr(transparent)]
16pub struct AccelerationStructureMotionCurveGeometryDescriptor(pub(crate) NonNull<c_void>);
17
18impl AccelerationStructureMotionCurveGeometryDescriptor {
19    /// Create a new motion curve geometry descriptor.
20    ///
21    /// C++ equivalent: `static AccelerationStructureMotionCurveGeometryDescriptor* alloc()->init()`
22    pub fn new() -> Option<Self> {
23        unsafe {
24            let class =
25                mtl_sys::Class::get("MTLAccelerationStructureMotionCurveGeometryDescriptor")?;
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 curve 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 curve-specific properties
200
201    /// Get the control point count.
202    ///
203    /// C++ equivalent: `NS::UInteger controlPointCount() const`
204    #[inline]
205    pub fn control_point_count(&self) -> UInteger {
206        unsafe { msg_send_0(self.as_ptr(), sel!(controlPointCount)) }
207    }
208
209    /// Set the control point count.
210    ///
211    /// C++ equivalent: `void setControlPointCount(NS::UInteger)`
212    #[inline]
213    pub fn set_control_point_count(&self, count: UInteger) {
214        unsafe {
215            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setControlPointCount:), count);
216        }
217    }
218
219    /// Get the control point format.
220    ///
221    /// C++ equivalent: `AttributeFormat controlPointFormat() const`
222    #[inline]
223    pub fn control_point_format(&self) -> AttributeFormat {
224        unsafe { msg_send_0(self.as_ptr(), sel!(controlPointFormat)) }
225    }
226
227    /// Set the control point format.
228    ///
229    /// C++ equivalent: `void setControlPointFormat(AttributeFormat)`
230    #[inline]
231    pub fn set_control_point_format(&self, format: AttributeFormat) {
232        unsafe {
233            msg_send_1::<(), AttributeFormat>(self.as_ptr(), sel!(setControlPointFormat:), format);
234        }
235    }
236
237    /// Get the control point stride.
238    ///
239    /// C++ equivalent: `NS::UInteger controlPointStride() const`
240    #[inline]
241    pub fn control_point_stride(&self) -> UInteger {
242        unsafe { msg_send_0(self.as_ptr(), sel!(controlPointStride)) }
243    }
244
245    /// Set the control point stride.
246    ///
247    /// C++ equivalent: `void setControlPointStride(NS::UInteger)`
248    #[inline]
249    pub fn set_control_point_stride(&self, stride: UInteger) {
250        unsafe {
251            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setControlPointStride:), stride);
252        }
253    }
254
255    /// Get the curve basis.
256    ///
257    /// C++ equivalent: `CurveBasis curveBasis() const`
258    #[inline]
259    pub fn curve_basis(&self) -> CurveBasis {
260        unsafe { msg_send_0(self.as_ptr(), sel!(curveBasis)) }
261    }
262
263    /// Set the curve basis.
264    ///
265    /// C++ equivalent: `void setCurveBasis(CurveBasis)`
266    #[inline]
267    pub fn set_curve_basis(&self, basis: CurveBasis) {
268        unsafe {
269            msg_send_1::<(), CurveBasis>(self.as_ptr(), sel!(setCurveBasis:), basis);
270        }
271    }
272
273    /// Get the curve end caps.
274    ///
275    /// C++ equivalent: `CurveEndCaps curveEndCaps() const`
276    #[inline]
277    pub fn curve_end_caps(&self) -> CurveEndCaps {
278        unsafe { msg_send_0(self.as_ptr(), sel!(curveEndCaps)) }
279    }
280
281    /// Set the curve end caps.
282    ///
283    /// C++ equivalent: `void setCurveEndCaps(CurveEndCaps)`
284    #[inline]
285    pub fn set_curve_end_caps(&self, end_caps: CurveEndCaps) {
286        unsafe {
287            msg_send_1::<(), CurveEndCaps>(self.as_ptr(), sel!(setCurveEndCaps:), end_caps);
288        }
289    }
290
291    /// Get the curve type.
292    ///
293    /// C++ equivalent: `CurveType curveType() const`
294    #[inline]
295    pub fn curve_type(&self) -> CurveType {
296        unsafe { msg_send_0(self.as_ptr(), sel!(curveType)) }
297    }
298
299    /// Set the curve type.
300    ///
301    /// C++ equivalent: `void setCurveType(CurveType)`
302    #[inline]
303    pub fn set_curve_type(&self, curve_type: CurveType) {
304        unsafe {
305            msg_send_1::<(), CurveType>(self.as_ptr(), sel!(setCurveType:), curve_type);
306        }
307    }
308
309    /// Get the index buffer.
310    ///
311    /// C++ equivalent: `Buffer* indexBuffer() const`
312    pub fn index_buffer(&self) -> Option<Buffer> {
313        unsafe {
314            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(indexBuffer));
315            if ptr.is_null() {
316                return None;
317            }
318            let _: *mut c_void = msg_send_0(ptr, sel!(retain));
319            Buffer::from_raw(ptr)
320        }
321    }
322
323    /// Set the index buffer.
324    ///
325    /// C++ equivalent: `void setIndexBuffer(Buffer*)`
326    pub fn set_index_buffer(&self, buffer: Option<&Buffer>) {
327        unsafe {
328            msg_send_1::<(), *const c_void>(
329                self.as_ptr(),
330                sel!(setIndexBuffer:),
331                buffer.map_or(std::ptr::null(), |b| b.as_ptr()),
332            );
333        }
334    }
335
336    /// Get the index buffer offset.
337    ///
338    /// C++ equivalent: `NS::UInteger indexBufferOffset() const`
339    #[inline]
340    pub fn index_buffer_offset(&self) -> UInteger {
341        unsafe { msg_send_0(self.as_ptr(), sel!(indexBufferOffset)) }
342    }
343
344    /// Set the index buffer offset.
345    ///
346    /// C++ equivalent: `void setIndexBufferOffset(NS::UInteger)`
347    #[inline]
348    pub fn set_index_buffer_offset(&self, offset: UInteger) {
349        unsafe {
350            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setIndexBufferOffset:), offset);
351        }
352    }
353
354    /// Get the index type.
355    ///
356    /// C++ equivalent: `IndexType indexType() const`
357    #[inline]
358    pub fn index_type(&self) -> IndexType {
359        unsafe { msg_send_0(self.as_ptr(), sel!(indexType)) }
360    }
361
362    /// Set the index type.
363    ///
364    /// C++ equivalent: `void setIndexType(IndexType)`
365    #[inline]
366    pub fn set_index_type(&self, index_type: IndexType) {
367        unsafe {
368            msg_send_1::<(), IndexType>(self.as_ptr(), sel!(setIndexType:), index_type);
369        }
370    }
371
372    /// Get the radius format.
373    ///
374    /// C++ equivalent: `AttributeFormat radiusFormat() const`
375    #[inline]
376    pub fn radius_format(&self) -> AttributeFormat {
377        unsafe { msg_send_0(self.as_ptr(), sel!(radiusFormat)) }
378    }
379
380    /// Set the radius format.
381    ///
382    /// C++ equivalent: `void setRadiusFormat(AttributeFormat)`
383    #[inline]
384    pub fn set_radius_format(&self, format: AttributeFormat) {
385        unsafe {
386            msg_send_1::<(), AttributeFormat>(self.as_ptr(), sel!(setRadiusFormat:), format);
387        }
388    }
389
390    /// Get the radius stride.
391    ///
392    /// C++ equivalent: `NS::UInteger radiusStride() const`
393    #[inline]
394    pub fn radius_stride(&self) -> UInteger {
395        unsafe { msg_send_0(self.as_ptr(), sel!(radiusStride)) }
396    }
397
398    /// Set the radius stride.
399    ///
400    /// C++ equivalent: `void setRadiusStride(NS::UInteger)`
401    #[inline]
402    pub fn set_radius_stride(&self, stride: UInteger) {
403        unsafe {
404            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setRadiusStride:), stride);
405        }
406    }
407
408    /// Get the segment control point count.
409    ///
410    /// C++ equivalent: `NS::UInteger segmentControlPointCount() const`
411    #[inline]
412    pub fn segment_control_point_count(&self) -> UInteger {
413        unsafe { msg_send_0(self.as_ptr(), sel!(segmentControlPointCount)) }
414    }
415
416    /// Set the segment control point count.
417    ///
418    /// C++ equivalent: `void setSegmentControlPointCount(NS::UInteger)`
419    #[inline]
420    pub fn set_segment_control_point_count(&self, count: UInteger) {
421        unsafe {
422            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setSegmentControlPointCount:), count);
423        }
424    }
425
426    /// Get the segment count.
427    ///
428    /// C++ equivalent: `NS::UInteger segmentCount() const`
429    #[inline]
430    pub fn segment_count(&self) -> UInteger {
431        unsafe { msg_send_0(self.as_ptr(), sel!(segmentCount)) }
432    }
433
434    /// Set the segment count.
435    ///
436    /// C++ equivalent: `void setSegmentCount(NS::UInteger)`
437    #[inline]
438    pub fn set_segment_count(&self, count: UInteger) {
439        unsafe {
440            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setSegmentCount:), count);
441        }
442    }
443
444    /// Get the control point buffers as a raw NS::Array pointer.
445    ///
446    /// C++ equivalent: `NS::Array* controlPointBuffers() const`
447    ///
448    /// # Safety
449    ///
450    /// The returned pointer is an NS::Array containing MotionKeyframeData objects.
451    /// The caller must manage the memory appropriately.
452    #[inline]
453    pub fn control_point_buffers_ptr(&self) -> *const c_void {
454        unsafe { msg_send_0(self.as_ptr(), sel!(controlPointBuffers)) }
455    }
456
457    /// Set the control point buffers from a raw NS::Array pointer.
458    ///
459    /// C++ equivalent: `void setControlPointBuffers(const NS::Array*)`
460    ///
461    /// # Safety
462    ///
463    /// The control_point_buffers pointer must be a valid NS::Array or null.
464    pub unsafe fn set_control_point_buffers_ptr(&self, control_point_buffers: *const c_void) {
465        unsafe {
466            msg_send_1::<(), *const c_void>(
467                self.as_ptr(),
468                sel!(setControlPointBuffers:),
469                control_point_buffers,
470            );
471        }
472    }
473
474    /// Get the radius buffers as a raw NS::Array pointer.
475    ///
476    /// C++ equivalent: `NS::Array* radiusBuffers() const`
477    ///
478    /// # Safety
479    ///
480    /// The returned pointer is an NS::Array containing MotionKeyframeData objects.
481    /// The caller must manage the memory appropriately.
482    #[inline]
483    pub fn radius_buffers_ptr(&self) -> *const c_void {
484        unsafe { msg_send_0(self.as_ptr(), sel!(radiusBuffers)) }
485    }
486
487    /// Set the radius buffers from a raw NS::Array pointer.
488    ///
489    /// C++ equivalent: `void setRadiusBuffers(const NS::Array*)`
490    ///
491    /// # Safety
492    ///
493    /// The radius_buffers pointer must be a valid NS::Array or null.
494    pub unsafe fn set_radius_buffers_ptr(&self, radius_buffers: *const c_void) {
495        unsafe {
496            msg_send_1::<(), *const c_void>(self.as_ptr(), sel!(setRadiusBuffers:), radius_buffers);
497        }
498    }
499}
500
501impl Default for AccelerationStructureMotionCurveGeometryDescriptor {
502    fn default() -> Self {
503        Self::new().expect("failed to create motion curve geometry descriptor")
504    }
505}
506
507impl Clone for AccelerationStructureMotionCurveGeometryDescriptor {
508    fn clone(&self) -> Self {
509        unsafe {
510            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(copy));
511            Self::from_raw(ptr).expect("failed to copy motion curve geometry descriptor")
512        }
513    }
514}
515
516impl Drop for AccelerationStructureMotionCurveGeometryDescriptor {
517    fn drop(&mut self) {
518        unsafe {
519            msg_send_0::<()>(self.as_ptr(), sel!(release));
520        }
521    }
522}
523
524impl Referencing for AccelerationStructureMotionCurveGeometryDescriptor {
525    #[inline]
526    fn as_ptr(&self) -> *const c_void {
527        self.0.as_ptr()
528    }
529}
530
531unsafe impl Send for AccelerationStructureMotionCurveGeometryDescriptor {}
532unsafe impl Sync for AccelerationStructureMotionCurveGeometryDescriptor {}