Skip to content

Commit 72a0e8d

Browse files
add an example for intersection plane (#249)
1 parent 381c577 commit 72a0e8d

2 files changed

Lines changed: 157 additions & 0 deletions

File tree

crates/parry3d/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ obj = { version = "0.10.2", optional = true }
8888
oorandom = "11"
8989
ptree = "0.4.0"
9090
rand = { version = "0.8" }
91+
macroquad = "0.4"
9192

9293
[package.metadata.docs.rs]
9394
rustdoc-args = ["-Zunstable-options", "--generate-link-to-definition"]
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
use macroquad::models::Vertex;
2+
use macroquad::prelude::*;
3+
use nalgebra::{Point3, UnitVector3, Vector3};
4+
use parry3d::math::Real;
5+
use parry3d::query::IntersectResult;
6+
use parry3d::shape::{Cuboid, TriMesh};
7+
8+
#[macroquad::main("parry3d::query::PlaneIntersection")]
9+
async fn main() {
10+
let trimesh = Cuboid::new(Vector3::repeat(1.0)).to_trimesh();
11+
12+
let camera_pos = Vec3::new(-1.5f32, 2.5f32, -3f32);
13+
14+
let mesh = mquad_mesh_from_points(&trimesh, camera_pos);
15+
let trimesh = TriMesh::new(trimesh.0, trimesh.1);
16+
17+
for _ in 1.. {
18+
clear_background(BLACK);
19+
20+
let elapsed_time = get_time();
21+
22+
// Animated rotation for the intersection plane.
23+
let bias = -1.2 * (elapsed_time as f32 / 3f32).sin();
24+
let rotation = Quat::from_axis_angle(Vec3::Z, (elapsed_time as f32 * 40f32).to_radians());
25+
let up_plane_vector = rotation * Vec3::Y;
26+
27+
// Get the intersection polyline.
28+
let intersection_result = trimesh.intersection_with_local_plane(
29+
&UnitVector3::new_normalize(Vector3::new(
30+
up_plane_vector.x,
31+
up_plane_vector.y,
32+
up_plane_vector.z,
33+
)),
34+
bias,
35+
0.0005,
36+
);
37+
38+
// Initialize 3D camera.
39+
set_camera(&Camera3D {
40+
position: camera_pos,
41+
up: Vec3::new(0f32, 1f32, 0f32),
42+
target: Vec3::new(0.5f32, 0f32, 0.5f32),
43+
..Default::default()
44+
});
45+
46+
// Draw involved shapes.
47+
let plane_center = up_plane_vector * bias;
48+
draw_line_3d(plane_center, plane_center + up_plane_vector, GREEN);
49+
draw_mesh(&mesh);
50+
draw_grid_ex(10, 0.333, BLUE, RED, plane_center, rotation);
51+
52+
/*
53+
*
54+
* Render the intersection.
55+
*
56+
*/
57+
match intersection_result {
58+
IntersectResult::Intersect(points) => {
59+
draw_polyline(
60+
points
61+
.segments()
62+
.map(|s| (mquad_from_na(s.a), mquad_from_na(s.b)))
63+
.collect(),
64+
Color::new(0f32, 1f32, 0f32, 1f32),
65+
);
66+
set_default_camera();
67+
draw_text("Intersection found!");
68+
}
69+
IntersectResult::Negative => {
70+
set_default_camera();
71+
draw_text("No intersection found, the shape is below the plane.");
72+
}
73+
IntersectResult::Positive => {
74+
set_default_camera();
75+
draw_text("No intersection found, the shape is above the plane.");
76+
}
77+
}
78+
next_frame().await
79+
}
80+
}
81+
82+
fn mquad_mesh_from_points(trimesh: &(Vec<Point3<Real>>, Vec<[u32; 3]>), camera_pos: Vec3) -> Mesh {
83+
let (points, indices) = trimesh;
84+
// Transform the parry mesh into a mquad Mesh
85+
let (mquad_points, mquad_indices) = (
86+
points
87+
.iter()
88+
.map(|p| Vertex {
89+
position: mquad_from_na(*p),
90+
uv: Vec2::new(p.x, p.y),
91+
color: DARKGRAY,
92+
})
93+
.collect(),
94+
indices.iter().flatten().map(|v| *v as u16).collect(),
95+
);
96+
97+
// Macroquad doesn´t support adding normals to vertices, so we'll bake a color into these vertices.
98+
// See https://github.com/not-fl3/macroquad/issues/321.
99+
100+
// Compute the normal of each vertex, making them unique
101+
let vertices: Vec<Vertex> = mquad_compute_normals(&mquad_points, &mquad_indices, camera_pos);
102+
// Regenerate the index for each vertex.
103+
let indices: Vec<u16> = (0..vertices.len() * 3)
104+
.into_iter()
105+
.map(|i| i as u16)
106+
.collect();
107+
let mesh = Mesh {
108+
vertices,
109+
indices,
110+
texture: None,
111+
};
112+
mesh
113+
}
114+
115+
fn mquad_compute_normals(points: &Vec<Vertex>, indices: &Vec<u16>, cam_pos: Vec3) -> Vec<Vertex> {
116+
let mut vertices: Vec<Vertex> = Vec::<Vertex>::new();
117+
for indices in indices.chunks(3) {
118+
let v0 = &points[indices[0] as usize];
119+
let v1 = &points[indices[1] as usize];
120+
let v2 = &points[indices[2] as usize];
121+
let normal = (v0.position - v2.position)
122+
.cross(v1.position - v2.position)
123+
.normalize();
124+
let brightness_mod = 0.2 + (0.8 / 2.) * (normal.dot(cam_pos) + 1.);
125+
126+
for &i in indices.iter() {
127+
let mut color = points[i as usize].color;
128+
color.r *= brightness_mod;
129+
color.g *= brightness_mod;
130+
color.b *= brightness_mod;
131+
132+
vertices.push(Vertex {
133+
position: points[i as usize].position,
134+
uv: Vec2::ZERO,
135+
color: color,
136+
});
137+
}
138+
}
139+
vertices
140+
}
141+
142+
fn draw_polyline(polygon: Vec<(Vec3, Vec3)>, color: Color) {
143+
for i in 0..polygon.len() {
144+
let a = polygon[i].0;
145+
let b = polygon[i].1;
146+
draw_line_3d(a, b, color);
147+
}
148+
}
149+
150+
fn mquad_from_na(a: Point3<Real>) -> Vec3 {
151+
Vec3::new(a.x, a.y, a.z)
152+
}
153+
154+
fn draw_text(text: &str) {
155+
macroquad::text::draw_text(text, 10.0, 48.0 + 18.0, 30.0, WHITE);
156+
}

0 commit comments

Comments
 (0)