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}