Skip to main content

pybevy_math/bounding/
raycast.rs

1use bevy::math::{
2    Ray3d, Vec2, Vec3,
3    bounding::{IntersectsVolume, RayCast2d, RayCast3d},
4};
5use pyo3::prelude::*;
6
7use super::{
8    aabb2d::PyAabb2d, aabb3d::PyAabb3d, bounding_circle::PyBoundingCircle,
9    bounding_sphere::PyBoundingSphere,
10};
11use crate::{
12    dir2::PyDir2,
13    dir3::PyDir3,
14    ray::{PyRay2d, PyRay3d},
15    vec2::PyVec2,
16    vec3::PyVec3,
17};
18
19#[pyclass(name = "RayCast2d")]
20#[derive(Debug, Clone)]
21pub struct PyRayCast2d {
22    ray_cast: RayCast2d,
23}
24
25impl From<PyRayCast2d> for RayCast2d {
26    fn from(py_raycast: PyRayCast2d) -> Self {
27        py_raycast.ray_cast
28    }
29}
30
31impl From<&PyRayCast2d> for RayCast2d {
32    fn from(py_raycast: &PyRayCast2d) -> Self {
33        py_raycast.ray_cast.clone()
34    }
35}
36
37impl From<RayCast2d> for PyRayCast2d {
38    fn from(ray_cast: RayCast2d) -> Self {
39        PyRayCast2d { ray_cast }
40    }
41}
42
43#[pymethods]
44impl PyRayCast2d {
45    #[new]
46    pub fn new(origin: PyVec2, direction: PyDir2, max: f32) -> Self {
47        let origin_vec: Vec2 = origin.into();
48        let dir = direction.get();
49        PyRayCast2d {
50            ray_cast: RayCast2d::new(origin_vec, dir, max),
51        }
52    }
53
54    #[staticmethod]
55    pub fn from_ray(ray: &PyRay2d, max: f32) -> Self {
56        PyRayCast2d {
57            ray_cast: RayCast2d::from_ray(ray.to_ray2d(), max),
58        }
59    }
60
61    #[getter]
62    pub fn ray(&self) -> PyRay2d {
63        PyRay2d::from_ray2d(self.ray_cast.ray)
64    }
65
66    #[getter]
67    pub fn max(&self) -> f32 {
68        self.ray_cast.max
69    }
70
71    pub fn intersects_aabb(&self, aabb: &PyAabb2d) -> bool {
72        let aabb_2d: bevy::math::bounding::Aabb2d = aabb.into();
73        self.ray_cast.intersects(&aabb_2d)
74    }
75
76    pub fn intersects_circle(&self, circle: &PyBoundingCircle) -> bool {
77        let bounding_circle: bevy::math::bounding::BoundingCircle = circle.into();
78        self.ray_cast.intersects(&bounding_circle)
79    }
80
81    pub fn aabb_intersection_at(&self, aabb: &PyAabb2d) -> Option<f32> {
82        let aabb_2d: bevy::math::bounding::Aabb2d = aabb.into();
83        self.ray_cast.aabb_intersection_at(&aabb_2d)
84    }
85
86    pub fn circle_intersection_at(&self, circle: &PyBoundingCircle) -> Option<f32> {
87        let bounding_circle: bevy::math::bounding::BoundingCircle = circle.into();
88        self.ray_cast.circle_intersection_at(&bounding_circle)
89    }
90
91    pub fn direction_recip(&self) -> PyVec2 {
92        PyVec2::from_vec2(self.ray_cast.direction_recip())
93    }
94
95    fn __repr__(&self) -> String {
96        format!(
97            "RayCast2d(ray={:?}, max={})",
98            self.ray_cast.ray, self.ray_cast.max
99        )
100    }
101}
102
103#[pyclass(name = "RayCast3d")]
104#[derive(Debug, Clone)]
105pub struct PyRayCast3d {
106    ray_cast: RayCast3d,
107}
108
109impl From<PyRayCast3d> for RayCast3d {
110    fn from(py_raycast: PyRayCast3d) -> Self {
111        py_raycast.ray_cast
112    }
113}
114
115impl From<&PyRayCast3d> for RayCast3d {
116    fn from(py_raycast: &PyRayCast3d) -> Self {
117        py_raycast.ray_cast.clone()
118    }
119}
120
121impl From<RayCast3d> for PyRayCast3d {
122    fn from(ray_cast: RayCast3d) -> Self {
123        PyRayCast3d { ray_cast }
124    }
125}
126
127#[pymethods]
128impl PyRayCast3d {
129    #[new]
130    pub fn new(origin: PyVec3, direction: PyDir3, max: f32) -> Self {
131        let origin_vec: Vec3 = origin.into();
132        let dir = direction.get();
133        PyRayCast3d {
134            ray_cast: RayCast3d::new(origin_vec, dir, max),
135        }
136    }
137
138    #[staticmethod]
139    pub fn from_ray(ray: &PyRay3d, max: f32) -> Self {
140        PyRayCast3d {
141            ray_cast: RayCast3d::from_ray(ray.to_ray3d(), max),
142        }
143    }
144
145    #[getter]
146    pub fn ray(&self) -> PyRay3d {
147        let dir3: bevy::math::Dir3 = self.ray_cast.direction.into();
148        let ray = Ray3d::new(self.ray_cast.origin.into(), dir3);
149        PyRay3d::from_ray3d(ray)
150    }
151
152    #[getter]
153    pub fn max(&self) -> f32 {
154        self.ray_cast.max
155    }
156
157    pub fn intersects_aabb(&self, aabb: &PyAabb3d) -> bool {
158        let aabb_3d: bevy::math::bounding::Aabb3d = aabb.into();
159        self.ray_cast.intersects(&aabb_3d)
160    }
161
162    pub fn intersects_sphere(&self, sphere: &PyBoundingSphere) -> bool {
163        let bounding_sphere: bevy::math::bounding::BoundingSphere = sphere.into();
164        self.ray_cast.intersects(&bounding_sphere)
165    }
166
167    pub fn aabb_intersection_at(&self, aabb: &PyAabb3d) -> Option<f32> {
168        let aabb_3d: bevy::math::bounding::Aabb3d = aabb.into();
169        self.ray_cast.aabb_intersection_at(&aabb_3d)
170    }
171
172    pub fn sphere_intersection_at(&self, sphere: &PyBoundingSphere) -> Option<f32> {
173        let bounding_sphere: bevy::math::bounding::BoundingSphere = sphere.into();
174        self.ray_cast.sphere_intersection_at(&bounding_sphere)
175    }
176
177    pub fn direction_recip(&self) -> PyVec3 {
178        PyVec3::from_vec3(self.ray_cast.direction_recip().into())
179    }
180
181    fn __repr__(&self) -> String {
182        format!(
183            "RayCast3d(origin={:?}, direction={:?}, max={})",
184            self.ray_cast.origin, self.ray_cast.direction, self.ray_cast.max
185        )
186    }
187}