plane_intersection/
plane_intersection.rs

1mod utils3d;
2
3use kiss3d::prelude::*;
4use parry3d::query::IntersectResult;
5use parry3d::shape::{Cuboid, TriMesh};
6use utils3d::{create_mesh_from_trimesh, draw_polyline, draw_text};
7
8#[kiss3d::main]
9async fn main() {
10    let mut window = Window::new("plane_intersection").await;
11    let mut camera = OrbitCamera3d::new(Vec3::new(-1.5, 2.5, -3.0), Vec3::new(0.5, 0.0, 0.5));
12    let mut scene = SceneNode3d::empty();
13    scene
14        .add_light(Light::point(100.0))
15        .set_position(Vec3::new(-1.0, 3.5, -3.0));
16
17    let font = Font::default();
18
19    let (points, indices) = Cuboid::new(Vec3::splat(1.0)).to_trimesh();
20    let trimesh = TriMesh::new(points.clone(), indices.clone()).unwrap();
21
22    // Add mesh to scene
23    let mesh = create_mesh_from_trimesh(points, indices);
24    scene
25        .add_mesh(mesh, Vec3::splat(1.0))
26        .set_color(Color::new(0.3, 0.3, 0.3, 1.0));
27
28    let start_time = web_time::Instant::now();
29
30    while window.render_3d(&mut scene, &mut camera).await {
31        let elapsed_time = start_time.elapsed().as_secs_f64();
32
33        // Animated rotation for the intersection plane.
34        let bias = -1.2 * (elapsed_time as f32 / 3f32).sin();
35        let rotation = Quat::from_axis_angle(Vec3::Z, (elapsed_time as f32 * 40f32).to_radians());
36        let up_plane_vector = rotation * Vec3::Y;
37
38        // Get the intersection polyline.
39        let intersection_result =
40            trimesh.intersection_with_local_plane(up_plane_vector.normalize(), bias, 0.0005);
41
42        // Draw the plane normal
43        let plane_center = up_plane_vector * bias;
44        window.draw_line(
45            plane_center,
46            plane_center + up_plane_vector,
47            GREEN,
48            4.0,
49            false,
50        );
51
52        // Draw a grid to represent the plane
53        draw_grid(&mut window, plane_center, rotation, 10, 0.333);
54
55        /*
56         *
57         * Render the intersection.
58         *
59         */
60        match intersection_result {
61            IntersectResult::Intersect(points) => {
62                draw_polyline(
63                    &mut window,
64                    points.segments().map(|s| (s.a, s.b)).collect(),
65                    Color::new(0f32, 1f32, 0f32, 1f32),
66                );
67                draw_text(&mut window, &font, "Intersection found!");
68            }
69            IntersectResult::Negative => {
70                draw_text(
71                    &mut window,
72                    &font,
73                    "No intersection found, the shape is below the plane.",
74                );
75            }
76            IntersectResult::Positive => {
77                draw_text(
78                    &mut window,
79                    &font,
80                    "No intersection found, the shape is above the plane.",
81                );
82            }
83        }
84    }
85}
86
87fn draw_grid(window: &mut Window, center: Vec3, rotation: Quat, subdivisions: i32, spacing: f32) {
88    let half_size = subdivisions as f32 * spacing / 2.0;
89
90    for i in 0..=subdivisions {
91        let offset = -half_size + i as f32 * spacing;
92
93        // Lines along X axis
94        let start = rotation * Vec3::new(-half_size, 0.0, offset) + center;
95        let end = rotation * Vec3::new(half_size, 0.0, offset) + center;
96        let color = if i == subdivisions / 2 { RED } else { BLUE };
97        window.draw_line(start, end, color, 2.0, false);
98
99        // Lines along Z axis
100        let start = rotation * Vec3::new(offset, 0.0, -half_size) + center;
101        let end = rotation * Vec3::new(offset, 0.0, half_size) + center;
102        let color = if i == subdivisions / 2 { RED } else { BLUE };
103        window.draw_line(start, end, color, 2.0, false);
104    }
105}