parry3d/query/point/
point_voxels.rs1use crate::math::{Real, Vector};
2use crate::query::{PointProjection, PointQuery};
3use crate::shape::{Cuboid, FeatureId, Voxels, VoxelsChunkRef};
4
5impl PointQuery for Voxels {
6 #[inline]
7 fn project_local_point(&self, pt: Vector, solid: bool) -> PointProjection {
8 self.chunk_bvh()
9 .project_point(pt, Real::MAX, |chunk_id, _| {
10 let chunk = self.chunk_ref(chunk_id);
11 chunk
12 .project_local_point_and_get_vox_id(pt, solid)
13 .map(|(proj, _)| proj)
14 })
15 .map(|res| res.1 .1)
16 .unwrap_or(PointProjection::new(false, Vector::splat(Real::MAX)))
17 }
18
19 #[inline]
20 fn project_local_point_and_get_feature(&self, pt: Vector) -> (PointProjection, FeatureId) {
21 self.chunk_bvh()
22 .project_point_and_get_feature(pt, Real::MAX, |chunk_id, _| {
23 let chunk = self.chunk_ref(chunk_id);
24 chunk
26 .project_local_point_and_get_vox_id(pt, false)
27 .map(|(proj, vox)| (proj, FeatureId::Face(vox)))
28 })
29 .map(|res| res.1 .1)
30 .unwrap_or((
31 PointProjection::new(false, Vector::splat(Real::MAX)),
32 FeatureId::Unknown,
33 ))
34 }
35}
36
37impl<'a> VoxelsChunkRef<'a> {
38 #[inline]
39 fn project_local_point_and_get_vox_id(
40 &self,
41 pt: Vector,
42 solid: bool,
43 ) -> Option<(PointProjection, u32)> {
44 let base_cuboid = Cuboid::new(self.parent.voxel_size() / 2.0);
47 let mut smallest_dist = Real::MAX;
48 let mut result = PointProjection::new(false, pt);
49 let mut result_vox_id = 0;
50
51 for vox in self.voxels() {
52 let mut candidate = base_cuboid.project_local_point(pt - vox.center, solid);
53 candidate.point += vox.center;
54
55 let candidate_dist = (candidate.point - pt).length();
56 if candidate_dist < smallest_dist {
57 result = candidate;
58 result_vox_id = vox.linear_id.flat_id();
59 smallest_dist = candidate_dist;
60 }
61 }
62
63 (smallest_dist < Real::MAX).then_some((result, result_vox_id as u32))
64 }
65}