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

epa::Face::normal Degenerate variant. #4

Closed
wants to merge 16 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .github/workflows/parry-ci-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
- name: Check serialization
run: cargo check --features bytemuck-serialize,serde-serialize,rkyv-serialize;
- name: Run tests
run: cargo test
run: cargo test --features wavefront
build-wasm:
runs-on: ubuntu-latest
env:
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
- `TriMesh::intersection_with_aabb`
- `SharedShape::trimesh`
- `SharedShape::trimesh_with_flags`
- `point_cloud_bounding_sphere_with_center` now returns a `BoundingSphere`.

## v0.17.1

Expand Down
125 changes: 95 additions & 30 deletions crates/parry2d/examples/aabb2d.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,101 @@
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;
use parry2d::bounding_volume::BoundingVolume;
use parry2d::bounding_volume::{Aabb, BoundingVolume};
use parry2d::shape::Ball;

fn main() {
/*
* Initialize the shapes.
*/
let ball1 = Ball::new(0.5);
let ball2 = Ball::new(1.0);

let ball1_pos = Isometry2::translation(0.0, 1.0);
let ball2_pos = Isometry2::identity();

/*
* Compute their axis-aligned bounding boxes.
*/
let aabb_ball1 = ball1.aabb(&ball1_pos);
let aabb_ball2 = ball2.aabb(&ball2_pos);

// Merge the two boxes.
let bounding_aabb = aabb_ball1.merged(&aabb_ball2);

// Enlarge the ball2 aabb.
let loose_aabb_ball2 = aabb_ball2.loosened(1.0);

// Intersection and inclusion tests.
assert!(aabb_ball1.intersects(&aabb_ball2));
assert!(bounding_aabb.contains(&aabb_ball1));
assert!(bounding_aabb.contains(&aabb_ball2));
assert!(!aabb_ball2.contains(&bounding_aabb));
assert!(!aabb_ball1.contains(&bounding_aabb));
assert!(loose_aabb_ball2.contains(&aabb_ball2));
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 ball1 = Ball::new(0.5);
let ball2 = Ball::new(1.0);

let ball1_pos = na_from_mquad(lissajous_2d(elapsed_time)) * 5f32;
let ball2_pos = Isometry2::identity();

/*
* Compute their axis-aligned bounding boxes.
*/
let aabb_ball1 = ball1.aabb(&ball1_pos.into());
let aabb_ball2 = ball2.aabb(&ball2_pos);

// Merge the two boxes.
let bounding_aabb = aabb_ball1.merged(&aabb_ball2);

// Enlarge the ball2 aabb.
let loose_aabb_ball2 = aabb_ball2.loosened(2f32);

// Intersection test
let color = if aabb_ball1.intersects(&aabb_ball2) {
RED
} else {
GREEN
};

assert!(bounding_aabb.contains(&aabb_ball1));
assert!(bounding_aabb.contains(&aabb_ball2));
assert!(loose_aabb_ball2.contains(&aabb_ball2));

let ball1_translation = mquad_from_na(ball1_pos.coords.into()) * RENDER_SCALE + render_pos;
draw_circle(
ball1_translation.x,
ball1_translation.y,
ball1.radius * RENDER_SCALE,
color,
);
let ball2_translation =
mquad_from_na(ball2_pos.translation.vector.into()) * RENDER_SCALE + render_pos;
draw_circle(
ball2_translation.x,
ball2_translation.y,
ball2.radius * RENDER_SCALE,
color,
);

draw_aabb(aabb_ball1, render_pos, color);
draw_aabb(aabb_ball2, render_pos, color);
draw_aabb(bounding_aabb, render_pos, YELLOW);

// Inclusion test
let color_included: Color = if loose_aabb_ball2.contains(&aabb_ball1) {
BLUE
} else {
MAGENTA
};
draw_aabb(loose_aabb_ball2, render_pos, color_included);
next_frame().await
}
}

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);
}
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);
}
Loading