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};
9use crate::util::{parse_json, required_handle};
10
11#[derive(Debug, Clone)]
12pub struct Camera {
13    handle: ObjectHandle,
14}
15
16impl Camera {
17    pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
18        Self { handle }
19    }
20
21    pub fn new() -> Result<Self> {
22        let mut out_camera = ptr::null_mut();
23        let mut out_error = ptr::null_mut();
24        let status = unsafe { ffi::mdl_camera_new(&mut out_camera, &mut out_error) };
25        crate::util::status_result(status, out_error)?;
26        Ok(Self::from_handle(required_handle(out_camera, "MDLCamera")?))
27    }
28
29    pub fn info(&self) -> Result<CameraInfo> {
30        parse_json(
31            unsafe { ffi::mdl_camera_info_json(self.handle.as_ptr()) },
32            "MDLCamera",
33        )
34    }
35
36    pub fn set_projection(&self, projection: CameraProjection) {
37        unsafe { ffi::mdl_camera_set_projection(self.handle.as_ptr(), projection.as_raw()) };
38    }
39
40    pub fn set_near_visibility_distance(&self, value: f32) {
41        unsafe { ffi::mdl_camera_set_near_visibility_distance(self.handle.as_ptr(), value) };
42    }
43
44    pub fn set_far_visibility_distance(&self, value: f32) {
45        unsafe { ffi::mdl_camera_set_far_visibility_distance(self.handle.as_ptr(), value) };
46    }
47
48    pub fn set_world_to_meters_conversion_scale(&self, value: f32) {
49        unsafe {
50            ffi::mdl_camera_set_world_to_meters_conversion_scale(self.handle.as_ptr(), value);
51        };
52    }
53
54    pub fn set_focal_length(&self, value: f32) {
55        unsafe { ffi::mdl_camera_set_focal_length(self.handle.as_ptr(), value) };
56    }
57
58    pub fn set_focus_distance(&self, value: f32) {
59        unsafe { ffi::mdl_camera_set_focus_distance(self.handle.as_ptr(), value) };
60    }
61
62    pub fn set_field_of_view(&self, value: f32) {
63        unsafe { ffi::mdl_camera_set_field_of_view(self.handle.as_ptr(), value) };
64    }
65
66    pub fn look_at(&self, focus_position: [f32; 3]) {
67        unsafe {
68            ffi::mdl_camera_look_at(
69                self.handle.as_ptr(),
70                focus_position[0],
71                focus_position[1],
72                focus_position[2],
73            );
74        };
75    }
76
77    pub fn look_at_from(&self, focus_position: [f32; 3], camera_position: [f32; 3]) {
78        unsafe {
79            ffi::mdl_camera_look_at_from(
80                self.handle.as_ptr(),
81                focus_position[0],
82                focus_position[1],
83                focus_position[2],
84                camera_position[0],
85                camera_position[1],
86                camera_position[2],
87            );
88        };
89    }
90
91    pub fn frame_bounding_box(&self, bounding_box: BoundingBox, set_near_and_far: bool) {
92        unsafe {
93            ffi::mdl_camera_frame_bounding_box(
94                self.handle.as_ptr(),
95                bounding_box.min[0],
96                bounding_box.min[1],
97                bounding_box.min[2],
98                bounding_box.max[0],
99                bounding_box.max[1],
100                bounding_box.max[2],
101                i32::from(set_near_and_far),
102            );
103        };
104    }
105
106    #[must_use]
107    pub fn ray_to(&self, pixel: [i32; 2], viewport: [i32; 2]) -> [f32; 3] {
108        let mut ray = [0.0_f32; 3];
109        unsafe {
110            ffi::mdl_camera_ray_to(
111                self.handle.as_ptr(),
112                pixel[0],
113                pixel[1],
114                viewport[0],
115                viewport[1],
116                &mut ray[0],
117                &mut ray[1],
118                &mut ray[2],
119            );
120        };
121        ray
122    }
123
124    #[must_use]
125    pub fn bokeh_kernel(&self, size: [i32; 2]) -> Option<Texture> {
126        let ptr = unsafe { ffi::mdl_camera_bokeh_kernel(self.handle.as_ptr(), size[0], size[1]) };
127        unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(Texture::from_handle)
128    }
129
130    #[must_use]
131    pub fn as_object(&self) -> Object {
132        Object::from_handle(self.handle.clone())
133    }
134}