Skip to main content

modelio/
camera.rs

1use std::ptr;
2
3use crate::error::Result;
4use crate::ffi;
5use crate::handle::ObjectHandle;
6use crate::object::Object;
7use crate::texture::Texture;
8use crate::types::{BoundingBox, CameraInfo, CameraProjection, StereoscopicCameraInfo};
9use crate::util::{parse_json, required_handle};
10
11#[derive(Debug, Clone)]
12/// Wraps the corresponding Model I/O camera counterpart.
13pub struct Camera {
14    handle: ObjectHandle,
15}
16
17impl Camera {
18    /// Builds this wrapper from the retained handle of the wrapped Model I/O camera counterpart.
19    pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
20        Self { handle }
21    }
22
23    /// Wraps the corresponding Model I/O initializer for the wrapped Model I/O camera counterpart.
24    pub fn new() -> Result<Self> {
25        let mut out_camera = ptr::null_mut();
26        let mut out_error = ptr::null_mut();
27        // SAFETY: Output pointers are initialized and managed; FFI function is called safely.
28        let status = unsafe { ffi::mdl_camera_new(&mut out_camera, &mut out_error) };
29        crate::util::status_result(status, out_error)?;
30        Ok(Self::from_handle(required_handle(out_camera, "MDLCamera")?))
31    }
32
33    /// Calls the corresponding Model I/O method on the wrapped Model I/O camera counterpart.
34    pub fn info(&self) -> Result<CameraInfo> {
35        parse_json(
36            // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
37            unsafe { ffi::mdl_camera_info_json(self.handle.as_ptr()) },
38            "MDLCamera",
39        )
40    }
41
42    /// Calls the corresponding Model I/O method on the wrapped Model I/O camera counterpart.
43    pub fn set_projection(&self, projection: CameraProjection) {
44        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
45        unsafe { ffi::mdl_camera_set_projection(self.handle.as_ptr(), projection.as_raw()) };
46    }
47
48    /// Calls the corresponding Model I/O method on the wrapped Model I/O camera counterpart.
49    pub fn set_near_visibility_distance(&self, value: f32) {
50        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
51        unsafe { ffi::mdl_camera_set_near_visibility_distance(self.handle.as_ptr(), value) };
52    }
53
54    /// Calls the corresponding Model I/O method on the wrapped Model I/O camera counterpart.
55    pub fn set_far_visibility_distance(&self, value: f32) {
56        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
57        unsafe { ffi::mdl_camera_set_far_visibility_distance(self.handle.as_ptr(), value) };
58    }
59
60    /// Calls the corresponding Model I/O method on the wrapped Model I/O camera counterpart.
61    pub fn set_world_to_meters_conversion_scale(&self, value: f32) {
62        // SAFETY: The unsafe operation is valid in this context.
63        unsafe {
64            ffi::mdl_camera_set_world_to_meters_conversion_scale(self.handle.as_ptr(), value);
65        };
66    }
67
68    /// Calls the corresponding Model I/O method on the wrapped Model I/O camera counterpart.
69    pub fn set_focal_length(&self, value: f32) {
70        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
71        unsafe { ffi::mdl_camera_set_focal_length(self.handle.as_ptr(), value) };
72    }
73
74    /// Calls the corresponding Model I/O method on the wrapped Model I/O camera counterpart.
75    pub fn set_focus_distance(&self, value: f32) {
76        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
77        unsafe { ffi::mdl_camera_set_focus_distance(self.handle.as_ptr(), value) };
78    }
79
80    /// Calls the corresponding Model I/O method on the wrapped Model I/O camera counterpart.
81    pub fn set_field_of_view(&self, value: f32) {
82        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
83        unsafe { ffi::mdl_camera_set_field_of_view(self.handle.as_ptr(), value) };
84    }
85
86    /// Calls the corresponding Model I/O method on the wrapped Model I/O camera counterpart.
87    pub fn look_at(&self, focus_position: [f32; 3]) {
88        // SAFETY: The unsafe operation is valid in this context.
89        unsafe {
90            ffi::mdl_camera_look_at(
91                self.handle.as_ptr(),
92                focus_position[0],
93                focus_position[1],
94                focus_position[2],
95            );
96        };
97    }
98
99    /// Calls the corresponding Model I/O method on the wrapped Model I/O camera counterpart.
100    pub fn look_at_from(&self, focus_position: [f32; 3], camera_position: [f32; 3]) {
101        // SAFETY: The unsafe operation is valid in this context.
102        unsafe {
103            ffi::mdl_camera_look_at_from(
104                self.handle.as_ptr(),
105                focus_position[0],
106                focus_position[1],
107                focus_position[2],
108                camera_position[0],
109                camera_position[1],
110                camera_position[2],
111            );
112        };
113    }
114
115    /// Calls the corresponding Model I/O method on the wrapped Model I/O camera counterpart.
116    pub fn frame_bounding_box(&self, bounding_box: BoundingBox, set_near_and_far: bool) {
117        // SAFETY: The unsafe operation is valid in this context.
118        unsafe {
119            ffi::mdl_camera_frame_bounding_box(
120                self.handle.as_ptr(),
121                bounding_box.min[0],
122                bounding_box.min[1],
123                bounding_box.min[2],
124                bounding_box.max[0],
125                bounding_box.max[1],
126                bounding_box.max[2],
127                i32::from(set_near_and_far),
128            );
129        };
130    }
131
132    #[must_use]
133    /// Calls the corresponding Model I/O method on the wrapped Model I/O camera counterpart.
134    pub fn ray_to(&self, pixel: [i32; 2], viewport: [i32; 2]) -> [f32; 3] {
135        let mut ray = [0.0_f32; 3];
136        // SAFETY: The unsafe operation is valid in this context.
137        unsafe {
138            ffi::mdl_camera_ray_to(
139                self.handle.as_ptr(),
140                pixel[0],
141                pixel[1],
142                viewport[0],
143                viewport[1],
144                &mut ray[0],
145                &mut ray[1],
146                &mut ray[2],
147            );
148        };
149        ray
150    }
151
152    #[must_use]
153    /// Calls the corresponding Model I/O method on the wrapped Model I/O camera counterpart.
154    pub fn bokeh_kernel(&self, size: [i32; 2]) -> Option<Texture> {
155        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
156        let ptr = unsafe { ffi::mdl_camera_bokeh_kernel(self.handle.as_ptr(), size[0], size[1]) };
157        // SAFETY: The unsafe operation is valid in this context.
158        unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(Texture::from_handle)
159    }
160
161    #[must_use]
162    /// Calls the corresponding Model I/O method on the wrapped Model I/O camera counterpart.
163    pub fn as_object(&self) -> Object {
164        Object::from_handle(self.handle.clone())
165    }
166}
167
168#[derive(Debug, Clone)]
169/// Wraps the corresponding Model I/O stereoscopic camera counterpart.
170pub struct StereoscopicCamera {
171    handle: ObjectHandle,
172}
173
174impl StereoscopicCamera {
175    /// Builds this wrapper from the retained handle of the wrapped Model I/O stereoscopic camera counterpart.
176    pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
177        Self { handle }
178    }
179
180    /// Wraps the corresponding Model I/O initializer for the wrapped Model I/O stereoscopic camera counterpart.
181    pub fn new() -> Result<Self> {
182        let mut out_camera = ptr::null_mut();
183        let mut out_error = ptr::null_mut();
184        // SAFETY: Output pointers are initialized and managed; FFI function is called safely.
185        let status = unsafe { ffi::mdl_stereoscopic_camera_new(&mut out_camera, &mut out_error) };
186        crate::util::status_result(status, out_error)?;
187        Ok(Self::from_handle(required_handle(
188            out_camera,
189            "MDLStereoscopicCamera",
190        )?))
191    }
192
193    /// Calls the corresponding Model I/O method on the wrapped Model I/O stereoscopic camera counterpart.
194    pub fn info(&self) -> Result<StereoscopicCameraInfo> {
195        parse_json(
196            // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
197            unsafe { ffi::mdl_stereoscopic_camera_info_json(self.handle.as_ptr()) },
198            "MDLStereoscopicCamera",
199        )
200    }
201
202    /// Calls the corresponding Model I/O method on the wrapped Model I/O stereoscopic camera counterpart.
203    pub fn set_inter_pupillary_distance(&self, value: f32) {
204        // SAFETY: The unsafe operation is valid in this context.
205        unsafe {
206            ffi::mdl_stereoscopic_camera_set_inter_pupillary_distance(self.handle.as_ptr(), value);
207        };
208    }
209
210    /// Calls the corresponding Model I/O method on the wrapped Model I/O stereoscopic camera counterpart.
211    pub fn set_left_vergence(&self, value: f32) {
212        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
213        unsafe { ffi::mdl_stereoscopic_camera_set_left_vergence(self.handle.as_ptr(), value) };
214    }
215
216    /// Calls the corresponding Model I/O method on the wrapped Model I/O stereoscopic camera counterpart.
217    pub fn set_right_vergence(&self, value: f32) {
218        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
219        unsafe { ffi::mdl_stereoscopic_camera_set_right_vergence(self.handle.as_ptr(), value) };
220    }
221
222    /// Calls the corresponding Model I/O method on the wrapped Model I/O stereoscopic camera counterpart.
223    pub fn set_overlap(&self, value: f32) {
224        // SAFETY: ObjectHandle wraps a valid opaque pointer from Swift; FFI function accepts it safely.
225        unsafe { ffi::mdl_stereoscopic_camera_set_overlap(self.handle.as_ptr(), value) };
226    }
227
228    #[must_use]
229    /// Calls the corresponding Model I/O method on the wrapped Model I/O stereoscopic camera counterpart.
230    pub fn as_camera(&self) -> Camera {
231        Camera::from_handle(self.handle.clone())
232    }
233
234    #[must_use]
235    /// Calls the corresponding Model I/O method on the wrapped Model I/O stereoscopic camera counterpart.
236    pub fn as_object(&self) -> Object {
237        Object::from_handle(self.handle.clone())
238    }
239}