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::shape::Aabb2d as BevyAabb;
7#[cfg(feature = "dim3")]
8use bevy::shape::Aabb3d as BevyAabb;
9
10#[cfg(feature = "dim2")]
11fn aabb_na_from_bevy(aabb: &BevyAabb) -> Aabb {
12 rapier::parry::bounding_volume::Aabb::new(aabb.min, aabb.max)
13}
14
15#[cfg(feature = "dim3")]
16fn aabb_na_from_bevy(aabb: &BevyAabb) -> Aabb {
17 rapier::parry::bounding_volume::Aabb::new(aabb.min.into(), aabb.max.into())
18}
19
20#[cfg(feature = "dim2")]
21fn aabb_bevy_from_na(aabb: &Aabb) -> BevyAabb {
22 BevyAabb {
23 min: aabb.mins,
24 max: aabb.maxs,
25 }
26}
27
28#[cfg(feature = "dim3")]
29fn aabb_bevy_from_na(aabb: &Aabb) -> BevyAabb {
30 BevyAabb {
31 min: aabb.mins.into(),
32 max: aabb.maxs.into(),
33 }
34}
35
36#[derive(Copy, Clone)]
38pub struct VoxelsView<'a> {
39 pub raw: &'a Voxels,
41}
42
43macro_rules! impl_ref_methods(
45 ($View: ident) => {
46 impl<'a> $View<'a> {
47 pub fn total_memory_size(&self) -> usize {
49 self.raw.total_memory_size()
50 }
51
52 pub fn heap_memory_size(&self) -> usize {
54 self.raw.heap_memory_size()
55 }
56
57 pub fn voxel_size(&self) -> Vect {
59 self.raw.voxel_size()
60 }
61
62 pub fn voxel_center(&self, key: IVect) -> Vect {
64 self.raw.voxel_center(key)
65 }
66
67 pub fn cropped(&self, domain_mins: IVect, domain_maxs: IVect) -> Option<Voxels> {
71 self.raw.cropped(domain_mins, domain_maxs)
72 }
73
74 pub fn extents(&self) -> Vect {
76 self.raw.local_aabb().extents()
77 }
78
79 pub fn domain_center(&self) -> Vect {
81 self.raw.local_aabb().center()
82 }
83
84 pub fn is_voxel_in_bounds(&self, key: IVect) -> bool {
86 let [mins, maxs] = self.raw.domain();
87 #[cfg(feature = "dim2")]
88 {
89 key.x >= mins.x && key.y >= mins.y && key.x < maxs.x && key.y < maxs.y
90 }
91 #[cfg(feature = "dim3")]
92 {
93 key.x >= mins.x
94 && key.y >= mins.y
95 && key.z >= mins.z
96 && key.x < maxs.x
97 && key.y < maxs.y
98 && key.z < maxs.z
99 }
100 }
101
102 pub fn voxel_aabb(&self, key: IVect) -> BevyAabb {
104 aabb_bevy_from_na(&self.raw.voxel_aabb(key.into()))
105 }
106
107 pub fn voxel_state(&self, key: IVect) -> Option<VoxelState> {
109 self.raw.voxel_state(key.into())
110 }
111
112 pub fn voxel_at_point_unchecked(&self, point: Vect) -> IVect {
114 self.raw.voxel_at_point(point)
115 }
116
117 pub fn voxel_at_point(&self, pt: Vect) -> Option<IVect> {
119 let voxel = self.voxel_at_point_unchecked(pt);
120 if self.is_voxel_in_bounds(voxel) {
121 Some(voxel)
122 } else {
123 None
124 }
125 }
126
127 pub fn clamp_voxel(&self, key: IVect) -> IVect {
129 let [mins, maxs] = self.raw.domain();
130 #[cfg(feature = "dim2")]
131 {
132 IVect::new(
133 key.x.clamp(mins.x, maxs.x - 1),
134 key.y.clamp(mins.y, maxs.y - 1),
135 )
136 }
137 #[cfg(feature = "dim3")]
138 {
139 IVect::new(
140 key.x.clamp(mins.x, maxs.x - 1),
141 key.y.clamp(mins.y, maxs.y - 1),
142 key.z.clamp(mins.z, maxs.z - 1),
143 )
144 }
145 }
146
147 pub fn voxel_range_intersecting_local_aabb(&self, aabb: &BevyAabb) -> [IVect; 2] {
149 let res = self
150 .raw
151 .voxel_range_intersecting_local_aabb(&aabb_na_from_bevy(aabb));
152 [res[0].into(), res[1].into()]
153 }
154
155 pub fn voxel_range_aabb(&self, mins: IVect, maxs: IVect) -> BevyAabb {
157 aabb_bevy_from_na(&self.raw.voxel_range_aabb(mins.into(), maxs.into()))
158 }
159
160 pub fn align_aabb_to_grid(&self, aabb: &BevyAabb) -> BevyAabb {
162 aabb_bevy_from_na(&self.raw.align_aabb_to_grid(&aabb_na_from_bevy(aabb)))
163 }
164
165 pub fn voxels_intersecting_local_aabb(
167 &self,
168 aabb: &BevyAabb,
169 ) -> impl Iterator<Item = VoxelData> + '_ {
170 self.raw
171 .voxels_intersecting_local_aabb(&aabb_na_from_bevy(aabb))
172 }
173
174 pub fn voxels(&self) -> impl Iterator<Item = VoxelData> + '_ {
176 self.raw.voxels()
177 }
178
179 pub fn split_with_box(&self, aabb: &BevyAabb) -> (Option<Voxels>, Option<Voxels>) {
181 self.raw.split_with_box(&aabb_na_from_bevy(aabb))
182 }
183
184 pub fn voxels_in_range(
186 &self,
187 mins: IVect,
188 maxs: IVect,
189 ) -> impl Iterator<Item = VoxelData> + '_ {
190 self.raw.voxels_in_range(mins.into(), maxs.into())
191 }
192 }
193 }
194);
195
196impl_ref_methods!(VoxelsView);
197
198pub struct VoxelsViewMut<'a> {
200 pub raw: &'a mut Voxels,
202}
203
204impl_ref_methods!(VoxelsViewMut);
205
206impl<'a> VoxelsViewMut<'a> {
207 pub fn try_set_voxel(&mut self, key: IVect, is_filled: bool) -> Option<VoxelState> {
209 if self.is_voxel_in_bounds(key) {
210 Some(self.raw.set_voxel(key, is_filled))
211 } else {
212 None
213 }
214 }
215
216 pub fn set_voxel(&mut self, key: IVect, is_filled: bool) -> VoxelState {
218 self.raw.set_voxel(key, is_filled)
219 }
220
221 pub fn crop(&mut self, domain_mins: IVect, domain_maxs: IVect) {
223 self.raw.crop(domain_mins, domain_maxs);
224 }
225
226 pub fn set_voxel_size(&mut self, new_size: Vect) {
228 self.raw.set_voxel_size(new_size);
229 }
230
231 pub fn combine_voxel_states(&mut self, other: &mut VoxelsViewMut<'_>, origin_shift: IVect) {
237 self.raw.combine_voxel_states(other.raw, origin_shift);
238 }
239
240 pub fn propagate_voxel_change(
245 &mut self,
246 other: &mut VoxelsViewMut<'_>,
247 voxel: IVect,
248 origin_shift: IVect,
249 ) {
250 self.raw
251 .propagate_voxel_change(other.raw, voxel, origin_shift);
252 }
253}