bevy_rapier3d/geometry/shape_views/
voxels.rs1use rapier::prelude::{Aabb, VoxelData, VoxelState, Voxels};
2
3use crate::math::{IVect, Vect};
4
5#[cfg(feature = "dim2")]
6use bevy::math::bounding::Aabb2d as BevyAabb;
7#[cfg(feature = "dim3")]
8use bevy::math::bounding::Aabb3d as BevyAabb;
9
10fn aabb_na_from_bevy(aabb: &BevyAabb) -> Aabb {
11 rapier::parry::bounding_volume::Aabb::new(aabb.min.into(), aabb.max.into())
12}
13
14fn aabb_bevy_from_na(aabb: &Aabb) -> BevyAabb {
15 BevyAabb {
16 min: aabb.mins.into(),
17 max: aabb.maxs.into(),
18 }
19}
20
21#[derive(Copy, Clone)]
23pub struct VoxelsView<'a> {
24 pub raw: &'a Voxels,
26}
27
28macro_rules! impl_ref_methods(
30 ($View: ident) => {
31 impl<'a> $View<'a> {
32 pub fn total_memory_size(&self) -> usize {
34 self.raw.total_memory_size()
35 }
36
37 pub fn heap_memory_size(&self) -> usize {
39 self.raw.heap_memory_size()
40 }
41
42 pub fn extents(&self) -> Vect {
44 self.raw.local_aabb().extents().into()
45 }
46
47 pub fn domain_center(&self) -> Vect {
49 self.raw.local_aabb().center().coords.into()
50 }
51
52 pub fn is_voxel_in_bounds(&self, key: IVect) -> bool {
54 let [mins, maxs] = self.raw.domain();
55 #[cfg(feature = "dim2")]
56 {
57 key.x >= mins.x && key.y >= mins.y && key.x < maxs.x && key.y < maxs.y
58 }
59 #[cfg(feature = "dim3")]
60 {
61 key.x >= mins.x
62 && key.y >= mins.y
63 && key.z >= mins.z
64 && key.x < maxs.x
65 && key.y < maxs.y
66 && key.z < maxs.z
67 }
68 }
69
70 pub fn voxel_aabb(&self, key: IVect) -> BevyAabb {
72 aabb_bevy_from_na(&self.raw.voxel_aabb(key.into()))
73 }
74
75 pub fn voxel_state(&self, key: IVect) -> Option<VoxelState> {
77 self.raw.voxel_state(key.into())
78 }
79
80 pub fn voxel_at_point_unchecked(&self, point: Vect) -> IVect {
82 let p = self.raw.voxel_at_point(point.into());
83 #[cfg(feature = "dim2")]
84 {
85 IVect::new(p.x, p.y)
86 }
87 #[cfg(feature = "dim3")]
88 {
89 IVect::new(p.x, p.y, p.z)
90 }
91 }
92
93 pub fn voxel_at_point(&self, pt: Vect) -> Option<IVect> {
95 let voxel = self.voxel_at_point_unchecked(pt);
96 if self.is_voxel_in_bounds(voxel) {
97 Some(voxel)
98 } else {
99 None
100 }
101 }
102
103 pub fn clamp_voxel(&self, key: IVect) -> IVect {
105 let [mins, maxs] = self.raw.domain();
106 #[cfg(feature = "dim2")]
107 {
108 IVect::new(
109 key.x.clamp(mins.x, maxs.x - 1),
110 key.y.clamp(mins.y, maxs.y - 1),
111 )
112 }
113 #[cfg(feature = "dim3")]
114 {
115 IVect::new(
116 key.x.clamp(mins.x, maxs.x - 1),
117 key.y.clamp(mins.y, maxs.y - 1),
118 key.z.clamp(mins.z, maxs.z - 1),
119 )
120 }
121 }
122
123 pub fn voxel_range_intersecting_local_aabb(&self, aabb: &BevyAabb) -> [IVect; 2] {
125 let res = self
126 .raw
127 .voxel_range_intersecting_local_aabb(&aabb_na_from_bevy(aabb));
128 [res[0].into(), res[1].into()]
129 }
130
131 pub fn voxel_range_aabb(&self, mins: IVect, maxs: IVect) -> BevyAabb {
133 aabb_bevy_from_na(&self.raw.voxel_range_aabb(mins.into(), maxs.into()))
134 }
135
136 pub fn align_aabb_to_grid(&self, aabb: &BevyAabb) -> BevyAabb {
138 aabb_bevy_from_na(&self.raw.align_aabb_to_grid(&aabb_na_from_bevy(aabb)))
139 }
140
141 pub fn voxels_intersecting_local_aabb(
143 &self,
144 aabb: &BevyAabb,
145 ) -> impl Iterator<Item = VoxelData> + '_ {
146 self.raw
147 .voxels_intersecting_local_aabb(&aabb_na_from_bevy(aabb))
148 }
149
150 pub fn voxels(&self) -> impl Iterator<Item = VoxelData> + '_ {
152 self.raw.voxels()
153 }
154
155 #[cfg(feature = "dim2")]
157 pub fn split_with_box(&self, aabb: &BevyAabb) -> (Option<Voxels>, Option<Voxels>) {
158 self.raw.split_with_box(&aabb_na_from_bevy(aabb))
159 }
160
161 pub fn voxels_in_range(
163 &self,
164 mins: IVect,
165 maxs: IVect,
166 ) -> impl Iterator<Item = VoxelData> + '_ {
167 self.raw.voxels_in_range(mins.into(), maxs.into())
168 }
169 }
170 }
171);
172
173impl_ref_methods!(VoxelsView);
174
175pub struct VoxelsViewMut<'a> {
177 pub raw: &'a mut Voxels,
179}
180
181impl_ref_methods!(VoxelsViewMut);
182
183impl<'a> VoxelsViewMut<'a> {
184 pub fn try_set_voxel(&mut self, key: IVect, is_filled: bool) -> Option<VoxelState> {
186 if self.is_voxel_in_bounds(key) {
187 Some(self.raw.set_voxel(key.into(), is_filled))
188 } else {
189 None
190 }
191 }
192
193 pub fn set_voxel(&mut self, key: IVect, is_filled: bool) -> VoxelState {
195 self.raw.set_voxel(key.into(), is_filled)
196 }
197
198 pub fn crop(&mut self, domain_mins: IVect, domain_maxs: IVect) {
200 self.raw.crop(domain_mins.into(), domain_maxs.into());
201 }
202}