From 1bf510f866c9b44407b013c30c47cee539964fa4 Mon Sep 17 00:00:00 2001 From: Thierry Berger Date: Wed, 4 Sep 2024 10:49:10 +0200 Subject: [PATCH] bounding sphere example using macroquad --- crates/parry2d/examples/bounding_sphere2d.rs | 148 +++++++++++++++---- 1 file changed, 118 insertions(+), 30 deletions(-) diff --git a/crates/parry2d/examples/bounding_sphere2d.rs b/crates/parry2d/examples/bounding_sphere2d.rs index a5551dad..66bd4de6 100644 --- a/crates/parry2d/examples/bounding_sphere2d.rs +++ b/crates/parry2d/examples/bounding_sphere2d.rs @@ -1,36 +1,124 @@ +mod common_macroquad; + extern crate nalgebra as na; +use common_macroquad::{draw_polyline, lissajous_2d, mquad_from_na, na_from_mquad}; +use macroquad::prelude::*; use na::{Isometry2, Vector2}; -use parry2d::bounding_volume::BoundingVolume; +use parry2d::bounding_volume::{Aabb, BoundingVolume}; +use parry2d::shape::Ball; use parry2d::shape::Cuboid; -fn main() { - /* - * Initialize the shapes. - */ - let cube1 = Cuboid::new(Vector2::repeat(0.5)); - let cube2 = Cuboid::new(Vector2::new(1.0, 0.5)); - - let cube1_pos = Isometry2::translation(0.0, 1.0); - let cube2_pos = Isometry2::identity(); - - /* - * Compute their bounding spheres. - */ - let bounding_sphere_cube1 = cube1.bounding_sphere(&cube1_pos); - let bounding_sphere_cube2 = cube2.bounding_sphere(&cube2_pos); - - // Merge the two spheres. - let bounding_bounding_sphere = bounding_sphere_cube1.merged(&bounding_sphere_cube2); - - // Enlarge the cube2 bounding sphere. - let loose_bounding_sphere_cube2 = bounding_sphere_cube2.loosened(1.0); - - // Intersection and inclusion tests. - assert!(bounding_sphere_cube1.intersects(&bounding_sphere_cube2)); - assert!(bounding_bounding_sphere.contains(&bounding_sphere_cube1)); - assert!(bounding_bounding_sphere.contains(&bounding_sphere_cube2)); - assert!(!bounding_sphere_cube2.contains(&bounding_bounding_sphere)); - assert!(!bounding_sphere_cube1.contains(&bounding_bounding_sphere)); - assert!(loose_bounding_sphere_cube2.contains(&bounding_sphere_cube2)); +const RENDER_SCALE: f32 = 30.0; + +#[macroquad::main("parry2d::utils::point_in_poly2d")] +async fn main() { + let render_pos = Vec2::new(300.0, 300.0); + + loop { + let elapsed_time = get_time() as f32 * 0.7; + clear_background(BLACK); + + /* + * Initialize the shapes. + */ + let cube1: Cuboid = Cuboid::new(Vector2::repeat(0.5)); + let cube2 = Cuboid::new(Vector2::new(1., 0.5)); + + let cube1_pos = na_from_mquad(lissajous_2d(elapsed_time)) * 5f32; + let cube1_pos = Isometry2::translation(cube1_pos.x, cube1_pos.y); + let cube2_pos = Isometry2::identity(); + + /* + * Compute their bounding spheres. + */ + let bounding_sphere_cube1 = cube1.bounding_sphere(&cube1_pos); + let bounding_sphere_cube2 = cube2.bounding_sphere(&cube2_pos); + + // Merge the two spheres. + let bounding_bounding_sphere = bounding_sphere_cube1.merged(&bounding_sphere_cube2); + + // Enlarge the cube2 bounding sphere. + let loose_bounding_sphere_cube2 = bounding_sphere_cube2.loosened(3.0); + + // Intersection test + let color = if bounding_sphere_cube1.intersects(&bounding_sphere_cube2) { + RED + } else { + GREEN + }; + + //assert!(bounding_bounding_sphere.contains(&bounding_sphere_cube1)); + //assert!(bounding_bounding_sphere.contains(&bounding_sphere_cube2)); + assert!(loose_bounding_sphere_cube2.contains(&bounding_sphere_cube2)); + + let cube1_translation = + mquad_from_na(cube1_pos.translation.vector.into()) * RENDER_SCALE + render_pos; + draw_cuboid(cube1, cube1_translation, color); + + let cube2_translation = + mquad_from_na(cube2_pos.translation.vector.into()) * RENDER_SCALE + render_pos; + draw_cuboid(cube2, cube2_translation, color); + draw_circle_lines( + bounding_sphere_cube1.center.x * RENDER_SCALE + render_pos.x, + bounding_sphere_cube1.center.y * RENDER_SCALE + render_pos.y, + bounding_sphere_cube1.radius * RENDER_SCALE, + 2f32, + color, + ); + draw_circle_lines( + bounding_sphere_cube2.center.x * RENDER_SCALE + render_pos.x, + bounding_sphere_cube2.center.y * RENDER_SCALE + render_pos.y, + bounding_sphere_cube2.radius * RENDER_SCALE, + 2f32, + color, + ); + draw_circle_lines( + bounding_bounding_sphere.center.x * RENDER_SCALE + render_pos.x, + bounding_bounding_sphere.center.y * RENDER_SCALE + render_pos.y, + bounding_bounding_sphere.radius * RENDER_SCALE, + 2f32, + YELLOW, + ); + + // Inclusion test + let color_included: Color = if loose_bounding_sphere_cube2.contains(&bounding_sphere_cube1) + { + BLUE + } else { + MAGENTA + }; + draw_circle_lines( + loose_bounding_sphere_cube2.center.x * RENDER_SCALE + render_pos.x, + loose_bounding_sphere_cube2.center.y * RENDER_SCALE + render_pos.y, + loose_bounding_sphere_cube2.radius * RENDER_SCALE, + 2f32, + color_included, + ); + next_frame().await + } +} + +fn draw_cuboid(cuboid: Cuboid, pos: Vec2, color: Color) { + let aabb = cuboid.local_aabb(); + draw_aabb(aabb, pos, color) +} + +fn draw_aabb(aabb: Aabb, offset: Vec2, color: Color) { + let mins = mquad_from_na(aabb.mins) * RENDER_SCALE + offset; + let maxs = mquad_from_na(aabb.maxs) * RENDER_SCALE + offset; + + let line = vec![ + Vec2::new(mins.x, mins.y), + Vec2::new(mins.x, maxs.y), + Vec2::new(maxs.x, maxs.y), + Vec2::new(maxs.x, mins.y), + Vec2::new(mins.x, mins.y), + ]; + let drawable_line = line + .iter() + .zip(line.iter().cycle().skip(1).take(line.len())) + .map(|item| (item.0.clone(), item.1.clone())) + .collect(); + draw_polyline(drawable_line, color); }