Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example bounding sphere using macroquad #259

Merged
merged 29 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
44c81cc
example for projection (+ bug detected)
Vrixyz Jul 31, 2024
9526e75
simpler project example
Vrixyz Jul 31, 2024
113046d
use lissajous trajectory + small polish pass
Vrixyz Jul 31, 2024
ed6a112
zoom in
Vrixyz Aug 14, 2024
8c09f1a
Merge branch 'master' into projection_example
Vrixyz Aug 14, 2024
b181c65
scrape plane intersection
Vrixyz Aug 14, 2024
2a68514
expose cuboid::to_trimesh for parry2d + add 2d example for projectpoint
Vrixyz Aug 14, 2024
065f6b6
fix local point inside the shape
Vrixyz Aug 14, 2024
174f012
common macroquad code in their example
Vrixyz Aug 14, 2024
3955d44
use a shaded cube for project_point2d too.
Vrixyz Aug 14, 2024
4bbe298
lighter cube
Vrixyz Sep 3, 2024
2dcadc9
fix plane intersection code with common code
Vrixyz Sep 3, 2024
d61b05b
removed a few unused variables
Vrixyz Sep 3, 2024
8ab7b5c
2d examples use common macroquad code
Vrixyz Sep 3, 2024
8057422
add example for convex hull
Vrixyz Sep 3, 2024
feda1a6
3d example for convex hull
Vrixyz Sep 3, 2024
39d7f8e
3d example for convex hull
Vrixyz Sep 3, 2024
aa711e6
add example for aabb2d
Vrixyz Sep 3, 2024
335639f
example for aabb in 3d
Vrixyz Sep 3, 2024
35c557f
remove a few unused code
Vrixyz Sep 3, 2024
1bf510f
bounding sphere example using macroquad
Vrixyz Sep 4, 2024
359b76b
add a note about float imprecisions
Vrixyz Sep 4, 2024
607ac1f
simpler aabb 3d function
Vrixyz Sep 4, 2024
cafcad4
Merge branch 'example_aabb' into example_bounding_sphere
Vrixyz Sep 4, 2024
cfd62f4
3d example for bounding spheres
Vrixyz Sep 4, 2024
abf04f3
Merge branch 'master' into example_bounding_sphere
Vrixyz Sep 20, 2024
4c8e1ae
Merge branch 'master' into example_bounding_sphere
Vrixyz Sep 20, 2024
b68ed9d
revert a few unneeded changes
Vrixyz Sep 20, 2024
098ddf3
pr feedback
Vrixyz Sep 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 124 additions & 30 deletions crates/parry2d/examples/bounding_sphere2d.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,130 @@
mod common_macroquad2d;

extern crate nalgebra as na;

use common_macroquad2d::{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::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::from(cube1_pos);
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
};

// Due to float imprecisions, it's dangerous to assume that both shapes will be
// contained in the merged.
// You can leverage `BoundingVolume::loosened` with an epsilon for expected results.
//
// These might fail:
// assert!(bounding_bounding_sphere.contains(&bounding_sphere_cube1));
// assert!(bounding_bounding_sphere.contains(&bounding_sphere_cube2));

assert!(loose_bounding_sphere_cube2.contains(&bounding_sphere_cube1));
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);
}
135 changes: 106 additions & 29 deletions crates/parry3d/examples/bounding_sphere3d.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,113 @@
mod common_macroquad3d;

extern crate nalgebra as na;

use std::ops::Rem;

use common_macroquad3d::{lissajous_3d, mquad_from_na, na_from_mquad};
use macroquad::prelude::*;
use na::{Isometry3, Vector3};
use parry3d::bounding_volume::BoundingVolume;
use parry3d::shape::Cuboid;

fn main() {
/*
* Initialize the shapes.
*/
let cube1 = Cuboid::new(Vector3::repeat(0.5));
let cube2 = Cuboid::new(Vector3::new(0.5, 1.0, 0.5));

let cube1_pos = Isometry3::translation(0.0, 0.0, 1.0); // 1.0 along the `z` axis.
let cube2_pos = Isometry3::identity(); // Identity matrix.

/*
* 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));
#[macroquad::main("parry2d::utils::point_in_poly2d")]
async fn main() {
let camera_pos = Vec3::new(8f32, 8f32, 12f32);

loop {
let elapsed_time = get_time() as f32 * 0.7;
clear_background(BLACK);
// Initialize 3D camera.
set_camera(&Camera3D {
position: camera_pos,
up: Vec3::new(0f32, 1f32, 0f32),
target: Vec3::new(0.5f32, 0f32, 0.5f32),
..Default::default()
});

/*
* Initialize the shapes.
*/
let cube1 = Cuboid::new(Vector3::repeat(0.5));
let cube2 = Cuboid::new(Vector3::new(0.5, 1.0, 0.5));

let cube1_pos = na_from_mquad(lissajous_3d(elapsed_time)) * 4f32;
let cube1_pos = Isometry3::from(cube1_pos);
let cube2_pos = Isometry3::identity(); // Identity matrix.

/*
* 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 and inclusion tests.
let mut color = if bounding_sphere_cube1.intersects(&bounding_sphere_cube2) {
RED
} else {
GREEN
};
color.a = 1f32 * (elapsed_time.rem(1f32) - 0.5).abs() * 2f32;

// Due to float imprecisions, it's dangerous to assume that both shapes will be
// contained in the merged.
// You can leverage `BoundingVolume::loosened` with an epsilon for expected results.
//
// These might fail:
//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());
draw_cube_wires(
cube1_translation,
mquad_from_na(cube1.half_extents.into()) * 2f32,
WHITE,
);
let cube2_translation = mquad_from_na(cube2_pos.translation.vector.into());
draw_cube_wires(
cube2_translation,
mquad_from_na(cube2.half_extents.into()) * 2f32,
WHITE,
);

draw_sphere_wires(
mquad_from_na(bounding_sphere_cube1.center),
bounding_sphere_cube1.radius,
None,
color,
);
draw_sphere_wires(
mquad_from_na(bounding_sphere_cube2.center),
bounding_sphere_cube2.radius,
None,
color,
);
draw_sphere_wires(
mquad_from_na(bounding_bounding_sphere.center),
bounding_bounding_sphere.radius,
None,
YELLOW,
);

let color_included: Color = if loose_bounding_sphere_cube2.contains(&bounding_sphere_cube1)
{
BLUE
} else {
MAGENTA
};
draw_sphere_wires(
mquad_from_na(loose_bounding_sphere_cube2.center),
loose_bounding_sphere_cube2.radius,
None,
color_included,
);
next_frame().await
}
}