Skip to content

Commit

Permalink
Add and impl Primitives (#10580)
Browse files Browse the repository at this point in the history
# Add and implement constructors for Primitives

- Adds more Primitive types and adds a constructor for almost all of
them
- Works towards finishing #10572 

## Solution

- Created new primitives
    - Torus
    - Conical Frustum
    - Cone
    - Ellipse
- Implemented constructors (`Primitive::new`) for almost every single
other primitive.

---------

Co-authored-by: Joona Aalto <[email protected]>
Co-authored-by: Alice Cecile <[email protected]>
  • Loading branch information
3 people authored Nov 17, 2023
1 parent 0c9f265 commit 33cd59f
Show file tree
Hide file tree
Showing 2 changed files with 195 additions and 2 deletions.
119 changes: 117 additions & 2 deletions crates/bevy_math/src/primitives/dim2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,26 @@ pub struct Circle {
}
impl Primitive2d for Circle {}

/// An ellipse primitive
#[derive(Clone, Copy, Debug)]
pub struct Ellipse {
/// The half "width" of the ellipse
pub half_width: f32,
/// The half "height" of the ellipse
pub half_height: f32,
}
impl Primitive2d for Ellipse {}

impl Ellipse {
/// Create a new `Ellipse` from a "width" and a "height"
pub fn new(width: f32, height: f32) -> Self {
Self {
half_width: width / 2.0,
half_height: height / 2.0,
}
}
}

/// An unbounded plane in 2D space. It forms a separating surface through the origin,
/// stretching infinitely far
#[derive(Clone, Copy, Debug)]
Expand Down Expand Up @@ -108,6 +128,24 @@ pub struct Polyline2d<const N: usize> {
}
impl<const N: usize> Primitive2d for Polyline2d<N> {}

impl<const N: usize> FromIterator<Vec2> for Polyline2d<N> {
fn from_iter<I: IntoIterator<Item = Vec2>>(iter: I) -> Self {
let mut vertices: [Vec2; N] = [Vec2::ZERO; N];

for (index, i) in iter.into_iter().take(N).enumerate() {
vertices[index] = i;
}
Self { vertices }
}
}

impl<const N: usize> Polyline2d<N> {
/// Create a new `Polyline2d` from its vertices
pub fn new(vertices: impl IntoIterator<Item = Vec2>) -> Self {
Self::from_iter(vertices)
}
}

/// A series of connected line segments in 2D space, allocated on the heap
/// in a `Box<[Vec2]>`.
///
Expand All @@ -119,6 +157,22 @@ pub struct BoxedPolyline2d {
}
impl Primitive2d for BoxedPolyline2d {}

impl FromIterator<Vec2> for BoxedPolyline2d {
fn from_iter<I: IntoIterator<Item = Vec2>>(iter: I) -> Self {
let vertices: Vec<Vec2> = iter.into_iter().collect();
Self {
vertices: vertices.into_boxed_slice(),
}
}
}

impl BoxedPolyline2d {
/// Create a new `BoxedPolyline2d` from its vertices
pub fn new(vertices: impl IntoIterator<Item = Vec2>) -> Self {
Self::from_iter(vertices)
}
}

/// A triangle in 2D space
#[derive(Clone, Debug)]
pub struct Triangle2d {
Expand All @@ -127,6 +181,15 @@ pub struct Triangle2d {
}
impl Primitive2d for Triangle2d {}

impl Triangle2d {
/// Create a new `Triangle2d` from `a`, `b`, and `c`,
pub fn new(a: Vec2, b: Vec2, c: Vec2) -> Self {
Self {
vertices: [a, b, c],
}
}
}

/// A rectangle primitive
#[doc(alias = "Quad")]
#[derive(Clone, Copy, Debug)]
Expand Down Expand Up @@ -158,22 +221,56 @@ impl Rectangle {
/// For a version without generics: [`BoxedPolygon`]
#[derive(Clone, Debug)]
pub struct Polygon<const N: usize> {
/// The vertices of the polygon
/// The vertices of the `Polygon`
pub vertices: [Vec2; N],
}
impl<const N: usize> Primitive2d for Polygon<N> {}

impl<const N: usize> FromIterator<Vec2> for Polygon<N> {
fn from_iter<I: IntoIterator<Item = Vec2>>(iter: I) -> Self {
let mut vertices: [Vec2; N] = [Vec2::ZERO; N];

for (index, i) in iter.into_iter().take(N).enumerate() {
vertices[index] = i;
}
Self { vertices }
}
}

impl<const N: usize> Polygon<N> {
/// Create a new `Polygon` from its vertices
pub fn new(vertices: impl IntoIterator<Item = Vec2>) -> Self {
Self::from_iter(vertices)
}
}

/// A polygon with a variable number of vertices, allocated on the heap
/// in a `Box<[Vec2]>`.
///
/// For a version without alloc: [`Polygon`]
#[derive(Clone, Debug)]
pub struct BoxedPolygon {
/// The vertices of the polygon
/// The vertices of the `BoxedPolygon`
pub vertices: Box<[Vec2]>,
}
impl Primitive2d for BoxedPolygon {}

impl FromIterator<Vec2> for BoxedPolygon {
fn from_iter<I: IntoIterator<Item = Vec2>>(iter: I) -> Self {
let vertices: Vec<Vec2> = iter.into_iter().collect();
Self {
vertices: vertices.into_boxed_slice(),
}
}
}

impl BoxedPolygon {
/// Create a new `BoxedPolygon` from its vertices
pub fn new(vertices: impl IntoIterator<Item = Vec2>) -> Self {
Self::from_iter(vertices)
}
}

/// A polygon where all vertices lie on a circle, equally far apart
#[derive(Clone, Copy, Debug)]
pub struct RegularPolygon {
Expand All @@ -183,3 +280,21 @@ pub struct RegularPolygon {
pub sides: usize,
}
impl Primitive2d for RegularPolygon {}

impl RegularPolygon {
/// Create a new `RegularPolygon`
/// from the radius of the circumcircle and number of sides
///
/// # Panics
///
/// Panics if `circumcircle_radius` is non-positive
pub fn new(circumcircle_radius: f32, sides: usize) -> Self {
assert!(circumcircle_radius > 0.0);
Self {
circumcircle: Circle {
radius: circumcircle_radius,
},
sides,
}
}
}
78 changes: 78 additions & 0 deletions crates/bevy_math/src/primitives/dim3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,24 @@ pub struct Polyline3d<const N: usize> {
}
impl<const N: usize> Primitive3d for Polyline3d<N> {}

impl<const N: usize> FromIterator<Vec3> for Polyline3d<N> {
fn from_iter<I: IntoIterator<Item = Vec3>>(iter: I) -> Self {
let mut vertices: [Vec3; N] = [Vec3::ZERO; N];

for (index, i) in iter.into_iter().take(N).enumerate() {
vertices[index] = i;
}
Self { vertices }
}
}

impl<const N: usize> Polyline3d<N> {
/// Create a new `Polyline3d` from its vertices
pub fn new(vertices: impl IntoIterator<Item = Vec3>) -> Self {
Self::from_iter(vertices)
}
}

/// A series of connected line segments in 3D space, allocated on the heap
/// in a `Box<[Vec3]>`.
///
Expand All @@ -118,6 +136,22 @@ pub struct BoxedPolyline3d {
}
impl Primitive3d for BoxedPolyline3d {}

impl FromIterator<Vec3> for BoxedPolyline3d {
fn from_iter<I: IntoIterator<Item = Vec3>>(iter: I) -> Self {
let vertices: Vec<Vec3> = iter.into_iter().collect();
Self {
vertices: vertices.into_boxed_slice(),
}
}
}

impl BoxedPolyline3d {
/// Create a new `BoxedPolyline3d` from its vertices
pub fn new(vertices: impl IntoIterator<Item = Vec3>) -> Self {
Self::from_iter(vertices)
}
}

/// A cuboid primitive, more commonly known as a box.
#[derive(Clone, Copy, Debug)]
pub struct Cuboid {
Expand Down Expand Up @@ -171,3 +205,47 @@ pub struct Capsule {
}
impl super::Primitive2d for Capsule {}
impl Primitive3d for Capsule {}

impl Capsule {
/// Create a new `Capsule` from a radius and length
pub fn new(radius: f32, length: f32) -> Self {
Self {
radius,
half_length: length / 2.0,
}
}
}

/// A cone primitive.
#[derive(Clone, Copy, Debug)]
pub struct Cone {
/// The radius of the base
pub radius: f32,
/// The height of the cone
pub height: f32,
}
impl Primitive3d for Cone {}

/// A conical frustum primitive.
/// A conical frustum can be created
/// by slicing off a section of a cone.
#[derive(Clone, Copy, Debug)]
pub struct ConicalFrustum {
/// The radius of the top of the frustum
pub radius_top: f32,
/// The radius of the base of the frustum
pub radius_bottom: f32,
/// The height of the frustum
pub height: f32,
}
impl Primitive3d for ConicalFrustum {}

/// A torus (AKA donut) primitive.
#[derive(Clone, Copy, Debug)]
pub struct Torus {
/// The radius of the overall shape
pub radius: f32,
/// The radius of the internal ring
pub ring_radius: f32,
}
impl Primitive3d for Torus {}

0 comments on commit 33cd59f

Please sign in to comment.