parry3d/transformation/to_outline/
voxels_to_outline.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
use crate::bounding_volume::Aabb;
use crate::math::{Point, Real};
use crate::shape::{VoxelType, Voxels};
use alloc::{vec, vec::Vec};

impl Voxels {
    /// Outlines this voxels shape as a set of polylines.
    ///
    /// The outline is such that only convex edges are output in the polyline.
    pub fn to_outline(&self) -> (Vec<Point<Real>>, Vec<[u32; 2]>) {
        let mut points = vec![];
        self.iter_outline(|a, b| {
            points.push(a);
            points.push(b);
        });
        let indices = (0..points.len() as u32 / 2)
            .map(|i| [i * 2, i * 2 + 1])
            .collect();
        (points, indices)
    }

    /// Outlines this voxels shape using segments.
    ///
    /// The outline is such that only convex edges are output in the polyline.
    pub fn iter_outline(&self, mut f: impl FnMut(Point<Real>, Point<Real>)) {
        // TODO: move this as a new method: Voxels::to_outline?
        let radius = self.voxel_size() / 2.0;
        let aabb = Aabb::from_half_extents(Point::origin(), radius);
        let vtx = aabb.vertices();

        for vox in self.voxels() {
            match vox.state.voxel_type() {
                VoxelType::Vertex => {
                    let mask = vox.state.feature_mask();

                    for edge in Aabb::EDGES_VERTEX_IDS {
                        if mask & (1 << edge.0) != 0 || mask & (1 << edge.1) != 0 {
                            f(
                                vox.center + vtx[edge.0].coords,
                                vox.center + vtx[edge.1].coords,
                            );
                        }
                    }
                }
                VoxelType::Edge => {
                    let vtx = aabb.vertices();
                    let mask = vox.state.feature_mask();

                    for (i, edge) in Aabb::EDGES_VERTEX_IDS.iter().enumerate() {
                        if mask & (1 << i) != 0 {
                            f(
                                vox.center + vtx[edge.0].coords,
                                vox.center + vtx[edge.1].coords,
                            );
                        }
                    }
                }
                _ => {}
            }
        }
    }
}