bevy_rapier2d/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
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 extents(&self) -> Vect {
59 self.raw.local_aabb().extents()
60 }
61
62 pub fn domain_center(&self) -> Vect {
64 self.raw.local_aabb().center()
65 }
66
67 pub fn is_voxel_in_bounds(&self, key: IVect) -> bool {
69 let [mins, maxs] = self.raw.domain();
70 #[cfg(feature = "dim2")]
71 {
72 key.x >= mins.x && key.y >= mins.y && key.x < maxs.x && key.y < maxs.y
73 }
74 #[cfg(feature = "dim3")]
75 {
76 key.x >= mins.x
77 && key.y >= mins.y
78 && key.z >= mins.z
79 && key.x < maxs.x
80 && key.y < maxs.y
81 && key.z < maxs.z
82 }
83 }
84
85 pub fn voxel_aabb(&self, key: IVect) -> BevyAabb {
87 aabb_bevy_from_na(&self.raw.voxel_aabb(key.into()))
88 }
89
90 pub fn voxel_state(&self, key: IVect) -> Option<VoxelState> {
92 self.raw.voxel_state(key.into())
93 }
94
95 pub fn voxel_at_point_unchecked(&self, point: Vect) -> IVect {
97 self.raw.voxel_at_point(point)
98 }
99
100 pub fn voxel_at_point(&self, pt: Vect) -> Option<IVect> {
102 let voxel = self.voxel_at_point_unchecked(pt);
103 if self.is_voxel_in_bounds(voxel) {
104 Some(voxel)
105 } else {
106 None
107 }
108 }
109
110 pub fn clamp_voxel(&self, key: IVect) -> IVect {
112 let [mins, maxs] = self.raw.domain();
113 #[cfg(feature = "dim2")]
114 {
115 IVect::new(
116 key.x.clamp(mins.x, maxs.x - 1),
117 key.y.clamp(mins.y, maxs.y - 1),
118 )
119 }
120 #[cfg(feature = "dim3")]
121 {
122 IVect::new(
123 key.x.clamp(mins.x, maxs.x - 1),
124 key.y.clamp(mins.y, maxs.y - 1),
125 key.z.clamp(mins.z, maxs.z - 1),
126 )
127 }
128 }
129
130 pub fn voxel_range_intersecting_local_aabb(&self, aabb: &BevyAabb) -> [IVect; 2] {
132 let res = self
133 .raw
134 .voxel_range_intersecting_local_aabb(&aabb_na_from_bevy(aabb));
135 [res[0].into(), res[1].into()]
136 }
137
138 pub fn voxel_range_aabb(&self, mins: IVect, maxs: IVect) -> BevyAabb {
140 aabb_bevy_from_na(&self.raw.voxel_range_aabb(mins.into(), maxs.into()))
141 }
142
143 pub fn align_aabb_to_grid(&self, aabb: &BevyAabb) -> BevyAabb {
145 aabb_bevy_from_na(&self.raw.align_aabb_to_grid(&aabb_na_from_bevy(aabb)))
146 }
147
148 pub fn voxels_intersecting_local_aabb(
150 &self,
151 aabb: &BevyAabb,
152 ) -> impl Iterator<Item = VoxelData> + '_ {
153 self.raw
154 .voxels_intersecting_local_aabb(&aabb_na_from_bevy(aabb))
155 }
156
157 pub fn voxels(&self) -> impl Iterator<Item = VoxelData> + '_ {
159 self.raw.voxels()
160 }
161
162 #[cfg(feature = "dim2")]
164 pub fn split_with_box(&self, aabb: &BevyAabb) -> (Option<Voxels>, Option<Voxels>) {
165 self.raw.split_with_box(&aabb_na_from_bevy(aabb))
166 }
167
168 pub fn voxels_in_range(
170 &self,
171 mins: IVect,
172 maxs: IVect,
173 ) -> impl Iterator<Item = VoxelData> + '_ {
174 self.raw.voxels_in_range(mins.into(), maxs.into())
175 }
176 }
177 }
178);
179
180impl_ref_methods!(VoxelsView);
181
182pub struct VoxelsViewMut<'a> {
184 pub raw: &'a mut Voxels,
186}
187
188impl_ref_methods!(VoxelsViewMut);
189
190impl<'a> VoxelsViewMut<'a> {
191 pub fn try_set_voxel(&mut self, key: IVect, is_filled: bool) -> Option<VoxelState> {
193 if self.is_voxel_in_bounds(key) {
194 Some(self.raw.set_voxel(key, is_filled))
195 } else {
196 None
197 }
198 }
199
200 pub fn set_voxel(&mut self, key: IVect, is_filled: bool) -> VoxelState {
202 self.raw.set_voxel(key, is_filled)
203 }
204
205 pub fn crop(&mut self, domain_mins: IVect, domain_maxs: IVect) {
207 self.raw.crop(domain_mins, domain_maxs);
208 }
209}