rust_raylib/
math.rs

1use crate::ffi;
2use static_assertions::{assert_eq_align, assert_eq_size};
3use std::mem::transmute;
4
5pub use crate::ffi::{CameraMode, CameraProjection};
6
7/// Vector2, 2x f32 components
8pub type Vector2 = mint::Vector2<f32>;
9assert_eq_size!(Vector2, ffi::Vector2);
10assert_eq_align!(Vector2, ffi::Vector2);
11
12impl From<Vector2> for ffi::Vector2 {
13    #[inline]
14    fn from(val: Vector2) -> Self {
15        unsafe { transmute(val) }
16    }
17}
18
19impl From<ffi::Vector2> for Vector2 {
20    #[inline]
21    fn from(value: ffi::Vector2) -> Self {
22        unsafe { transmute(value) }
23    }
24}
25
26/// Vector3, 3x f32 components
27pub type Vector3 = mint::Vector3<f32>;
28assert_eq_size!(Vector3, ffi::Vector3);
29assert_eq_align!(Vector3, ffi::Vector3);
30
31impl From<Vector3> for ffi::Vector3 {
32    #[inline]
33    fn from(val: Vector3) -> Self {
34        unsafe { transmute(val) }
35    }
36}
37
38impl From<ffi::Vector3> for Vector3 {
39    #[inline]
40    fn from(value: ffi::Vector3) -> Self {
41        unsafe { transmute(value) }
42    }
43}
44
45/// Vector4, 4x f32 components
46pub type Vector4 = mint::Vector4<f32>;
47assert_eq_size!(Vector4, ffi::Vector4);
48assert_eq_align!(Vector4, ffi::Vector4);
49
50impl From<Vector4> for ffi::Vector4 {
51    #[inline]
52    fn from(val: Vector4) -> Self {
53        unsafe { transmute(val) }
54    }
55}
56
57impl From<ffi::Vector4> for Vector4 {
58    #[inline]
59    fn from(value: ffi::Vector4) -> Self {
60        unsafe { transmute(value) }
61    }
62}
63
64/// Quaternion, 4x f32 components
65pub type Quaternion = mint::Quaternion<f32>;
66assert_eq_size!(Quaternion, ffi::Quaternion);
67assert_eq_align!(Quaternion, ffi::Quaternion);
68
69impl From<Quaternion> for ffi::Vector4 {
70    #[inline]
71    fn from(val: Quaternion) -> Self {
72        unsafe { transmute(val) }
73    }
74}
75
76impl From<ffi::Vector4> for Quaternion {
77    #[inline]
78    fn from(value: ffi::Vector4) -> Self {
79        unsafe { transmute(value) }
80    }
81}
82
83/// Matrix, 4x4 f32 components, column major
84pub type Matrix = mint::ColumnMatrix4<f32>;
85assert_eq_size!(Matrix, ffi::Matrix);
86assert_eq_align!(Matrix, ffi::Matrix);
87
88impl From<Matrix> for ffi::Matrix {
89    #[inline]
90    fn from(val: Matrix) -> Self {
91        unsafe { transmute(val) }
92    }
93}
94
95impl From<ffi::Matrix> for Matrix {
96    #[inline]
97    fn from(value: ffi::Matrix) -> Self {
98        unsafe { transmute(value) }
99    }
100}
101
102/// Rectangle, 4 components
103#[repr(C)]
104#[derive(Clone, Copy, Debug, PartialEq)]
105#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
106pub struct Rectangle {
107    /// Rectangle top-left corner position x
108    pub x: f32,
109    /// Rectangle top-left corner position y
110    pub y: f32,
111    /// Rectangle width
112    pub width: f32,
113    /// Rectangle height
114    pub height: f32,
115}
116
117assert_eq_size!(Rectangle, ffi::Rectangle);
118assert_eq_align!(Rectangle, ffi::Rectangle);
119
120impl Rectangle {
121    /// Create new rectangle
122    #[inline]
123    pub const fn new(x: f32, y: f32, width: f32, height: f32) -> Self {
124        Self {
125            x,
126            y,
127            width,
128            height,
129        }
130    }
131}
132
133impl From<Rectangle> for ffi::Rectangle {
134    #[inline]
135    fn from(val: Rectangle) -> Self {
136        unsafe { transmute(val) }
137    }
138}
139
140impl From<ffi::Rectangle> for Rectangle {
141    #[inline]
142    fn from(value: ffi::Rectangle) -> Self {
143        unsafe { transmute(value) }
144    }
145}
146
147/// Ray, ray for raycasting
148#[repr(C)]
149#[derive(Clone, Copy, Debug, PartialEq)]
150pub struct Ray {
151    /// Ray position (origin)
152    pub position: Vector3,
153    /// Ray direction
154    pub direction: Vector3,
155}
156
157assert_eq_size!(Ray, ffi::Ray);
158assert_eq_align!(Ray, ffi::Ray);
159
160impl From<Ray> for ffi::Ray {
161    #[inline]
162    fn from(val: Ray) -> Self {
163        unsafe { transmute(val) }
164    }
165}
166
167impl From<ffi::Ray> for Ray {
168    #[inline]
169    fn from(value: ffi::Ray) -> Self {
170        unsafe { transmute(value) }
171    }
172}
173
174/// RayCollision, ray hit information
175#[repr(C)]
176#[derive(Clone, Copy, Debug, PartialEq)]
177pub struct RayCollision {
178    /// Did the ray hit something?
179    pub hit: bool,
180    /// Distance to the nearest hit
181    pub distance: f32,
182    /// Point of the nearest hit
183    pub point: Vector3,
184    /// Surface normal of hit
185    pub normal: Vector3,
186}
187
188assert_eq_size!(RayCollision, ffi::RayCollision);
189assert_eq_align!(RayCollision, ffi::RayCollision);
190
191impl From<RayCollision> for ffi::RayCollision {
192    #[inline]
193    fn from(val: RayCollision) -> Self {
194        unsafe { transmute(val) }
195    }
196}
197
198impl From<ffi::RayCollision> for RayCollision {
199    #[inline]
200    fn from(value: ffi::RayCollision) -> Self {
201        unsafe { transmute(value) }
202    }
203}
204
205/// BoundingBox
206#[repr(C)]
207#[derive(Clone, Copy, Debug, PartialEq)]
208pub struct BoundingBox {
209    /// Minimum vertex box-corner
210    pub min: Vector3,
211    /// Maximum vertex box-corner
212    pub max: Vector3,
213}
214
215assert_eq_size!(Ray, ffi::BoundingBox);
216assert_eq_align!(Ray, ffi::BoundingBox);
217
218impl From<BoundingBox> for ffi::BoundingBox {
219    #[inline]
220    fn from(val: BoundingBox) -> Self {
221        unsafe { transmute(val) }
222    }
223}
224
225impl From<ffi::BoundingBox> for BoundingBox {
226    #[inline]
227    fn from(value: ffi::BoundingBox) -> Self {
228        unsafe { transmute(value) }
229    }
230}
231
232/// Transform, vertex transformation data
233#[repr(C)]
234#[derive(Clone, Copy, Debug, PartialEq)]
235pub struct Transform {
236    /// Translation
237    pub translation: Vector3,
238    /// Rotation
239    pub rotation: Quaternion,
240    /// Scale
241    pub scale: Vector3,
242}
243
244assert_eq_size!(Transform, ffi::Transform);
245assert_eq_align!(Transform, ffi::Transform);
246
247impl From<Transform> for ffi::Transform {
248    #[inline]
249    fn from(val: Transform) -> Self {
250        unsafe { transmute(val) }
251    }
252}
253
254impl From<ffi::Transform> for Transform {
255    #[inline]
256    fn from(value: ffi::Transform) -> Self {
257        unsafe { transmute(value) }
258    }
259}
260
261/// Camera2D, defines position/orientation in 2d space
262#[repr(C)]
263#[derive(Clone, Copy, Debug, PartialEq)]
264#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
265pub struct Camera2D {
266    /// Camera offset (displacement from target)
267    pub offset: Vector2,
268    /// Camera target (rotation and zoom origin)
269    pub target: Vector2,
270    /// Camera rotation in degrees
271    pub rotation: f32,
272    /// Camera zoom (scaling), should be 1.0f by default
273    pub zoom: f32,
274}
275
276assert_eq_size!(Camera2D, ffi::Camera2D);
277assert_eq_align!(Camera2D, ffi::Camera2D);
278
279impl Camera2D {
280    /// Get camera 2d transform matrix
281    #[inline]
282    pub fn get_matrix(&self) -> Matrix {
283        unsafe { ffi::GetCameraMatrix2D((*self).into()).into() }
284    }
285
286    /// Get the world space position for a 2d camera screen space position
287    #[inline]
288    pub fn screen_to_world(&self, position: Vector2) -> Vector2 {
289        unsafe { ffi::GetScreenToWorld2D(position.into(), (*self).into()).into() }
290    }
291
292    /// Get the screen space position for a 2d camera world space position
293    #[inline]
294    pub fn world_to_screen(&self, position: Vector2) -> Vector2 {
295        unsafe { ffi::GetWorldToScreen2D(position.into(), (*self).into()).into() }
296    }
297}
298
299impl From<Camera2D> for ffi::Camera2D {
300    #[inline]
301    fn from(val: Camera2D) -> Self {
302        unsafe { transmute(val) }
303    }
304}
305
306impl From<ffi::Camera2D> for Camera2D {
307    #[inline]
308    fn from(value: ffi::Camera2D) -> Self {
309        unsafe { transmute(value) }
310    }
311}
312
313/// Camera, defines position/orientation in 3d space
314#[repr(C)]
315#[derive(Clone, Copy, Debug, PartialEq)]
316#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
317pub struct Camera3D {
318    /// Camera position
319    pub position: Vector3,
320    /// Camera target it looks-at
321    pub target: Vector3,
322    /// Camera up vector (rotation over its axis)
323    pub up: Vector3,
324    /// Camera field-of-view aperture in Y (degrees) in perspective, used as near plane width in orthographic
325    pub fovy: f32,
326    /// Camera projection: CAMERA_PERSPECTIVE or CAMERA_ORTHOGRAPHIC
327    pub projection: CameraProjection,
328}
329
330assert_eq_size!(Camera3D, ffi::Camera3D);
331assert_eq_align!(Camera3D, ffi::Camera3D);
332
333impl Camera3D {
334    /// Update camera position for selected mode
335    #[inline]
336    pub fn update(&mut self, mode: CameraMode) {
337        unsafe { ffi::UpdateCamera(self as *mut Camera3D as *mut ffi::Camera3D, mode as _) }
338    }
339
340    /// Update camera movement/rotation
341    #[inline]
342    pub fn update_pro(&mut self, movement: Vector3, rotation: Vector3, zoom: f32) {
343        unsafe {
344            ffi::UpdateCameraPro(
345                self as *mut Camera3D as *mut ffi::Camera3D,
346                movement.into(),
347                rotation.into(),
348                zoom,
349            )
350        }
351    }
352
353    /// Get a ray trace from mouse position
354    #[inline]
355    pub fn get_mouse_ray(&self, mouse_position: Vector2) -> Ray {
356        unsafe { ffi::GetMouseRay(mouse_position.into(), (*self).into()).into() }
357    }
358
359    /// Get camera transform matrix (view matrix)
360    #[inline]
361    pub fn get_matrix(&self) -> Matrix {
362        unsafe { ffi::GetCameraMatrix((*self).into()).into() }
363    }
364
365    /// Get the screen space position for a 3d world space position
366    #[inline]
367    pub fn world_to_screen(&self, position: Vector3) -> Vector2 {
368        unsafe { ffi::GetWorldToScreen(position.into(), (*self).into()).into() }
369    }
370
371    /// Get size position for a 3d world space position
372    #[inline]
373    pub fn world_to_screen_ex(&self, position: Vector3, width: u32, height: u32) -> Vector2 {
374        unsafe {
375            ffi::GetWorldToScreenEx(
376                position.into(),
377                (*self).into(),
378                width as _,
379                height as _,
380            )
381            .into()
382        }
383    }
384}
385
386impl From<Camera3D> for ffi::Camera3D {
387    #[inline]
388    fn from(val: Camera3D) -> Self {
389        unsafe { transmute(val) }
390    }
391}
392
393impl From<ffi::Camera3D> for Camera3D {
394    #[inline]
395    fn from(value: ffi::Camera3D) -> Self {
396        if value.projection != CameraProjection::Orthographic as i32
397            && value.projection != CameraProjection::Perspective as i32
398        {
399            panic!(
400                "Attempted to convert a ffi::Camera3D with an invalid projection value: {}",
401                value.projection
402            );
403        }
404
405        unsafe { transmute(value) }
406    }
407}
408
409/// Camera type fallback, defaults to Camera3D
410pub type Camera = Camera3D;