Skip to content

Commit

Permalink
Make sure Collider::triangle is oriented CCW (#579)
Browse files Browse the repository at this point in the history
# Objective

Fixes #368.

Many users create 2D triangle colliders with clockwise orientation. However, this produces a collider that doesn't work, as Parry seems to require conterclockwise orientation.

## Solution

Check the orientation in `Collider::triangle`, and reverse it if necessary. If the orientation is known to be counterclockwise, `Collider::triangle_unchecked` can be used instead.
  • Loading branch information
Jondolf authored Dec 6, 2024
1 parent 628215a commit d179fc8
Showing 1 changed file with 32 additions and 1 deletion.
33 changes: 32 additions & 1 deletion src/collision/collider/parry/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -732,7 +732,38 @@ impl Collider {
SharedShape::segment(a.into(), b.into()).into()
}

/// Creates a collider with a triangle shape defined by its points `a`, `b` and `c`.
/// Creates a collider with a triangle shape defined by its points `a`, `b`, and `c`.
///
/// If the triangle is oriented clockwise, it will be reversed to be counterclockwise
/// by swapping `b` and `c`. This is needed for collision detection.
///
/// If you know that the given points produce a counterclockwise triangle,
/// consider using [`Collider::triangle_unchecked`] instead.
#[cfg(feature = "2d")]
pub fn triangle(a: Vector, b: Vector, c: Vector) -> Self {
let mut triangle = parry::shape::Triangle::new(a.into(), b.into(), c.into());

// Make sure the triangle is counterclockwise. This is needed for collision detection.
if triangle.orientation(1e-8) == parry::shape::TriangleOrientation::Clockwise {
triangle.reverse();
}

SharedShape::new(triangle).into()
}

/// Creates a collider with a triangle shape defined by its points `a`, `b`, and `c`.
///
/// The orientation of the triangle is assumed to be counterclockwise.
/// This is needed for collision detection.
///
/// If you are unsure about the orientation of the triangle, consider using [`Collider::triangle`] instead.
#[cfg(feature = "2d")]
pub fn triangle_unchecked(a: Vector, b: Vector, c: Vector) -> Self {
SharedShape::triangle(a.into(), b.into(), c.into()).into()
}

/// Creates a collider with a triangle shape defined by its points `a`, `b`, and `c`.
#[cfg(feature = "3d")]
pub fn triangle(a: Vector, b: Vector, c: Vector) -> Self {
SharedShape::triangle(a.into(), b.into(), c.into()).into()
}
Expand Down

0 comments on commit d179fc8

Please sign in to comment.