Implement Rhombus 2D primitive. (#13501)
# Objective - Create a new 2D primitive, Rhombus, also knows as "Diamond Shape" - Simplify the creation and handling of isometric projections - Extend Bevy's arsenal of 2D primitives ## Testing - New unit tests created in bevy_math/ primitives and bev_math/ bounding - Tested translations, rotations, wireframe, bounding sphere, aabb and creation parameters --------- Co-authored-by: Luís Figueiredo <luispcfigueiredo@tecnico.ulisboa.pt>
This commit is contained in:
		
							parent
							
								
									037f37e4d6
								
							
						
					
					
						commit
						7d843e0c08
					
				@ -7,7 +7,7 @@ use super::helpers::*;
 | 
			
		||||
use bevy_color::Color;
 | 
			
		||||
use bevy_math::primitives::{
 | 
			
		||||
    Annulus, BoxedPolygon, BoxedPolyline2d, Capsule2d, Circle, Ellipse, Line2d, Plane2d, Polygon,
 | 
			
		||||
    Polyline2d, Primitive2d, Rectangle, RegularPolygon, Segment2d, Triangle2d,
 | 
			
		||||
    Polyline2d, Primitive2d, Rectangle, RegularPolygon, Rhombus, Segment2d, Triangle2d,
 | 
			
		||||
};
 | 
			
		||||
use bevy_math::{Dir2, Mat2, Vec2};
 | 
			
		||||
 | 
			
		||||
@ -138,6 +138,38 @@ where
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// rhombus 2d
 | 
			
		||||
 | 
			
		||||
impl<'w, 's, Config, Clear> GizmoPrimitive2d<Rhombus> for Gizmos<'w, 's, Config, Clear>
 | 
			
		||||
where
 | 
			
		||||
    Config: GizmoConfigGroup,
 | 
			
		||||
    Clear: 'static + Send + Sync,
 | 
			
		||||
{
 | 
			
		||||
    type Output<'a> = () where Self: 'a;
 | 
			
		||||
 | 
			
		||||
    fn primitive_2d(
 | 
			
		||||
        &mut self,
 | 
			
		||||
        primitive: Rhombus,
 | 
			
		||||
        position: Vec2,
 | 
			
		||||
        angle: f32,
 | 
			
		||||
        color: impl Into<Color>,
 | 
			
		||||
    ) -> Self::Output<'_> {
 | 
			
		||||
        if !self.enabled {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let [a, b, c, d] =
 | 
			
		||||
            [(1.0, 0.0), (0.0, 1.0), (-1.0, 0.0), (0.0, -1.0)].map(|(sign_x, sign_y)| {
 | 
			
		||||
                Vec2::new(
 | 
			
		||||
                    primitive.half_diagonals.x * sign_x,
 | 
			
		||||
                    primitive.half_diagonals.y * sign_y,
 | 
			
		||||
                )
 | 
			
		||||
            });
 | 
			
		||||
        let positions = [a, b, c, d, a].map(rotate_then_translate_2d(angle, position));
 | 
			
		||||
        self.linestrip_2d(positions, color);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// capsule 2d
 | 
			
		||||
 | 
			
		||||
impl<'w, 's, Config, Clear> GizmoPrimitive2d<Capsule2d> for Gizmos<'w, 's, Config, Clear>
 | 
			
		||||
 | 
			
		||||
@ -3,8 +3,8 @@
 | 
			
		||||
use crate::{
 | 
			
		||||
    primitives::{
 | 
			
		||||
        Arc2d, BoxedPolygon, BoxedPolyline2d, Capsule2d, Circle, CircularSector, CircularSegment,
 | 
			
		||||
        Ellipse, Line2d, Plane2d, Polygon, Polyline2d, Rectangle, RegularPolygon, Segment2d,
 | 
			
		||||
        Triangle2d,
 | 
			
		||||
        Ellipse, Line2d, Plane2d, Polygon, Polyline2d, Rectangle, RegularPolygon, Rhombus,
 | 
			
		||||
        Segment2d, Triangle2d,
 | 
			
		||||
    },
 | 
			
		||||
    Dir2, Mat2, Rotation2d, Vec2,
 | 
			
		||||
};
 | 
			
		||||
@ -183,6 +183,33 @@ impl Bounded2d for Ellipse {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Bounded2d for Rhombus {
 | 
			
		||||
    fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rotation2d>) -> Aabb2d {
 | 
			
		||||
        let rotation_mat = rotation.into();
 | 
			
		||||
 | 
			
		||||
        let [rotated_x_half_diagonal, rotated_y_half_diagonal] = [
 | 
			
		||||
            rotation_mat * Vec2::new(self.half_diagonals.x, 0.0),
 | 
			
		||||
            rotation_mat * Vec2::new(0.0, self.half_diagonals.y),
 | 
			
		||||
        ];
 | 
			
		||||
        let aabb_half_extent = rotated_x_half_diagonal
 | 
			
		||||
            .abs()
 | 
			
		||||
            .max(rotated_y_half_diagonal.abs());
 | 
			
		||||
 | 
			
		||||
        Aabb2d {
 | 
			
		||||
            min: -aabb_half_extent + translation,
 | 
			
		||||
            max: aabb_half_extent + translation,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn bounding_circle(
 | 
			
		||||
        &self,
 | 
			
		||||
        translation: Vec2,
 | 
			
		||||
        _rotation: impl Into<Rotation2d>,
 | 
			
		||||
    ) -> BoundingCircle {
 | 
			
		||||
        BoundingCircle::new(translation, self.circumradius())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Bounded2d for Plane2d {
 | 
			
		||||
    fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rotation2d>) -> Aabb2d {
 | 
			
		||||
        let rotation: Rotation2d = rotation.into();
 | 
			
		||||
@ -448,7 +475,7 @@ mod tests {
 | 
			
		||||
        bounding::Bounded2d,
 | 
			
		||||
        primitives::{
 | 
			
		||||
            Arc2d, Capsule2d, Circle, CircularSector, CircularSegment, Ellipse, Line2d, Plane2d,
 | 
			
		||||
            Polygon, Polyline2d, Rectangle, RegularPolygon, Segment2d, Triangle2d,
 | 
			
		||||
            Polygon, Polyline2d, Rectangle, RegularPolygon, Rhombus, Segment2d, Triangle2d,
 | 
			
		||||
        },
 | 
			
		||||
        Dir2,
 | 
			
		||||
    };
 | 
			
		||||
@ -769,6 +796,31 @@ mod tests {
 | 
			
		||||
        assert_eq!(bounding_circle.radius(), 1.0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn rhombus() {
 | 
			
		||||
        let rhombus = Rhombus::new(2.0, 1.0);
 | 
			
		||||
        let translation = Vec2::new(2.0, 1.0);
 | 
			
		||||
 | 
			
		||||
        let aabb = rhombus.aabb_2d(translation, std::f32::consts::FRAC_PI_4);
 | 
			
		||||
        assert_eq!(aabb.min, Vec2::new(1.2928932, 0.29289323));
 | 
			
		||||
        assert_eq!(aabb.max, Vec2::new(2.7071068, 1.7071068));
 | 
			
		||||
 | 
			
		||||
        let bounding_circle = rhombus.bounding_circle(translation, std::f32::consts::FRAC_PI_4);
 | 
			
		||||
        assert_eq!(bounding_circle.center, translation);
 | 
			
		||||
        assert_eq!(bounding_circle.radius(), 1.0);
 | 
			
		||||
 | 
			
		||||
        let rhombus = Rhombus::new(0.0, 0.0);
 | 
			
		||||
        let translation = Vec2::new(0.0, 0.0);
 | 
			
		||||
 | 
			
		||||
        let aabb = rhombus.aabb_2d(translation, std::f32::consts::FRAC_PI_4);
 | 
			
		||||
        assert_eq!(aabb.min, Vec2::new(0.0, 0.0));
 | 
			
		||||
        assert_eq!(aabb.max, Vec2::new(0.0, 0.0));
 | 
			
		||||
 | 
			
		||||
        let bounding_circle = rhombus.bounding_circle(translation, std::f32::consts::FRAC_PI_4);
 | 
			
		||||
        assert_eq!(bounding_circle.center, translation);
 | 
			
		||||
        assert_eq!(bounding_circle.radius(), 0.0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn plane() {
 | 
			
		||||
        let translation = Vec2::new(2.0, 1.0);
 | 
			
		||||
 | 
			
		||||
@ -929,6 +929,132 @@ impl Measured2d for Annulus {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// A rhombus primitive, also known as a diamond shape.
 | 
			
		||||
#[derive(Clone, Copy, Debug, PartialEq)]
 | 
			
		||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
 | 
			
		||||
#[doc(alias = "Diamond")]
 | 
			
		||||
pub struct Rhombus {
 | 
			
		||||
    /// Size of the horizontal and vertical diagonals of the rhombus
 | 
			
		||||
    pub half_diagonals: Vec2,
 | 
			
		||||
}
 | 
			
		||||
impl Primitive2d for Rhombus {}
 | 
			
		||||
 | 
			
		||||
impl Default for Rhombus {
 | 
			
		||||
    /// Returns the default [`Rhombus`] with a half-horizontal and half-vertical diagonal of `0.5`.
 | 
			
		||||
    fn default() -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            half_diagonals: Vec2::splat(0.5),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Rhombus {
 | 
			
		||||
    /// Create a new `Rhombus` from a vertical and horizontal diagonal sizes.
 | 
			
		||||
    #[inline(always)]
 | 
			
		||||
    pub fn new(horizontal_diagonal: f32, vertical_diagonal: f32) -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            half_diagonals: Vec2::new(horizontal_diagonal / 2.0, vertical_diagonal / 2.0),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Create a new `Rhombus` from a side length with all inner angles equal.
 | 
			
		||||
    #[inline(always)]
 | 
			
		||||
    pub fn from_side(side: f32) -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            half_diagonals: Vec2::splat(side.hypot(side) / 2.0),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Create a new `Rhombus` from a given inradius with all inner angles equal.
 | 
			
		||||
    #[inline(always)]
 | 
			
		||||
    pub fn from_inradius(inradius: f32) -> Self {
 | 
			
		||||
        let half_diagonal = inradius * 2.0 / std::f32::consts::SQRT_2;
 | 
			
		||||
        Self {
 | 
			
		||||
            half_diagonals: Vec2::new(half_diagonal, half_diagonal),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Get the length of each side of the rhombus
 | 
			
		||||
    #[inline(always)]
 | 
			
		||||
    pub fn side(&self) -> f32 {
 | 
			
		||||
        self.half_diagonals.length()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Get the radius of the circumcircle on which all vertices
 | 
			
		||||
    /// of the rhombus lie
 | 
			
		||||
    #[inline(always)]
 | 
			
		||||
    pub fn circumradius(&self) -> f32 {
 | 
			
		||||
        self.half_diagonals.x.max(self.half_diagonals.y)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Get the radius of the largest circle that can
 | 
			
		||||
    /// be drawn within the rhombus
 | 
			
		||||
    #[inline(always)]
 | 
			
		||||
    #[doc(alias = "apothem")]
 | 
			
		||||
    pub fn inradius(&self) -> f32 {
 | 
			
		||||
        let side = self.side();
 | 
			
		||||
        if side == 0.0 {
 | 
			
		||||
            0.0
 | 
			
		||||
        } else {
 | 
			
		||||
            (self.half_diagonals.x * self.half_diagonals.y) / side
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Finds the point on the rhombus that is closest to the given `point`.
 | 
			
		||||
    ///
 | 
			
		||||
    /// If the point is outside the rhombus, the returned point will be on the perimeter of the rhombus.
 | 
			
		||||
    /// Otherwise, it will be inside the rhombus and returned as is.
 | 
			
		||||
    #[inline(always)]
 | 
			
		||||
    pub fn closest_point(&self, point: Vec2) -> Vec2 {
 | 
			
		||||
        // Fold the problem into the positive quadrant
 | 
			
		||||
        let point_abs = point.abs();
 | 
			
		||||
        let half_diagonals = self.half_diagonals.abs(); // to ensure correct sign
 | 
			
		||||
 | 
			
		||||
        // The unnormalised normal vector perpendicular to the side of the rhombus
 | 
			
		||||
        let normal = Vec2::new(half_diagonals.y, half_diagonals.x);
 | 
			
		||||
        let normal_magnitude_squared = normal.length_squared();
 | 
			
		||||
        if normal_magnitude_squared == 0.0 {
 | 
			
		||||
            return Vec2::ZERO; // A null Rhombus has only one point anyway.
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // The last term corresponds to normal.dot(rhombus_vertex)
 | 
			
		||||
        let distance_unnormalised = normal.dot(point_abs) - half_diagonals.x * half_diagonals.y;
 | 
			
		||||
 | 
			
		||||
        // The point is already inside so we simply return it.
 | 
			
		||||
        if distance_unnormalised <= 0.0 {
 | 
			
		||||
            return point;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Clamp the point to the edge
 | 
			
		||||
        let mut result = point_abs - normal * distance_unnormalised / normal_magnitude_squared;
 | 
			
		||||
 | 
			
		||||
        // Clamp the point back to the positive quadrant
 | 
			
		||||
        // if it's outside, it needs to be clamped to either vertex
 | 
			
		||||
        if result.x <= 0.0 {
 | 
			
		||||
            result = Vec2::new(0.0, half_diagonals.y);
 | 
			
		||||
        } else if result.y <= 0.0 {
 | 
			
		||||
            result = Vec2::new(half_diagonals.x, 0.0);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Finally, we restore the signs of the original vector
 | 
			
		||||
        result.copysign(point)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Measured2d for Rhombus {
 | 
			
		||||
    /// Get the area of the rhombus
 | 
			
		||||
    #[inline(always)]
 | 
			
		||||
    fn area(&self) -> f32 {
 | 
			
		||||
        2.0 * self.half_diagonals.x * self.half_diagonals.y
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Get the perimeter of the rhombus
 | 
			
		||||
    #[inline(always)]
 | 
			
		||||
    fn perimeter(&self) -> f32 {
 | 
			
		||||
        4.0 * self.side()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// An unbounded plane in 2D space. It forms a separating surface through the origin,
 | 
			
		||||
/// stretching infinitely far
 | 
			
		||||
#[derive(Clone, Copy, Debug, PartialEq)]
 | 
			
		||||
@ -1601,6 +1727,25 @@ mod tests {
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn rhombus_closest_point() {
 | 
			
		||||
        let rhombus = Rhombus::new(2.0, 1.0);
 | 
			
		||||
        assert_eq!(rhombus.closest_point(Vec2::X * 10.0), Vec2::X);
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            rhombus.closest_point(Vec2::NEG_ONE * 0.2),
 | 
			
		||||
            Vec2::NEG_ONE * 0.2
 | 
			
		||||
        );
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            rhombus.closest_point(Vec2::new(-0.55, 0.35)),
 | 
			
		||||
            Vec2::new(-0.5, 0.25)
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        let rhombus = Rhombus::new(0.0, 0.0);
 | 
			
		||||
        assert_eq!(rhombus.closest_point(Vec2::X * 10.0), Vec2::ZERO);
 | 
			
		||||
        assert_eq!(rhombus.closest_point(Vec2::NEG_ONE * 0.2), Vec2::ZERO);
 | 
			
		||||
        assert_eq!(rhombus.closest_point(Vec2::new(-0.55, 0.35)), Vec2::ZERO);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn circle_math() {
 | 
			
		||||
        let circle = Circle { radius: 3.0 };
 | 
			
		||||
@ -1618,6 +1763,28 @@ mod tests {
 | 
			
		||||
        assert_eq!(annulus.perimeter(), 37.699112, "incorrect perimeter");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn rhombus_math() {
 | 
			
		||||
        let rhombus = Rhombus::new(3.0, 4.0);
 | 
			
		||||
        assert_eq!(rhombus.area(), 6.0, "incorrect area");
 | 
			
		||||
        assert_eq!(rhombus.perimeter(), 10.0, "incorrect perimeter");
 | 
			
		||||
        assert_eq!(rhombus.side(), 2.5, "incorrect side");
 | 
			
		||||
        assert_eq!(rhombus.inradius(), 1.2, "incorrect inradius");
 | 
			
		||||
        assert_eq!(rhombus.circumradius(), 2.0, "incorrect circumradius");
 | 
			
		||||
        let rhombus = Rhombus::new(0.0, 0.0);
 | 
			
		||||
        assert_eq!(rhombus.area(), 0.0, "incorrect area");
 | 
			
		||||
        assert_eq!(rhombus.perimeter(), 0.0, "incorrect perimeter");
 | 
			
		||||
        assert_eq!(rhombus.side(), 0.0, "incorrect side");
 | 
			
		||||
        assert_eq!(rhombus.inradius(), 0.0, "incorrect inradius");
 | 
			
		||||
        assert_eq!(rhombus.circumradius(), 0.0, "incorrect circumradius");
 | 
			
		||||
        let rhombus = Rhombus::from_side(std::f32::consts::SQRT_2);
 | 
			
		||||
        assert_eq!(rhombus, Rhombus::new(2.0, 2.0));
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            rhombus,
 | 
			
		||||
            Rhombus::from_inradius(std::f32::consts::FRAC_1_SQRT_2)
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn ellipse_math() {
 | 
			
		||||
        let ellipse = Ellipse::new(3.0, 1.0);
 | 
			
		||||
 | 
			
		||||
@ -28,6 +28,14 @@ impl_reflect!(
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
impl_reflect!(
 | 
			
		||||
    #[reflect(Debug, PartialEq, Serialize, Deserialize)]
 | 
			
		||||
    #[type_path = "bevy_math::primitives"]
 | 
			
		||||
    struct Rhombus {
 | 
			
		||||
        half_diagonals: Vec2,
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
impl_reflect!(
 | 
			
		||||
    #[reflect(Debug, PartialEq, Serialize, Deserialize)]
 | 
			
		||||
    #[type_path = "bevy_math::primitives"]
 | 
			
		||||
 | 
			
		||||
@ -10,7 +10,7 @@ use super::{MeshBuilder, Meshable};
 | 
			
		||||
use bevy_math::{
 | 
			
		||||
    primitives::{
 | 
			
		||||
        Annulus, Capsule2d, Circle, CircularSector, CircularSegment, Ellipse, Rectangle,
 | 
			
		||||
        RegularPolygon, Triangle2d, Triangle3d, WindingOrder,
 | 
			
		||||
        RegularPolygon, Rhombus, Triangle2d, Triangle3d, WindingOrder,
 | 
			
		||||
    },
 | 
			
		||||
    FloatExt, Vec2,
 | 
			
		||||
};
 | 
			
		||||
@ -583,6 +583,38 @@ impl From<Annulus> for Mesh {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Meshable for Rhombus {
 | 
			
		||||
    type Output = Mesh;
 | 
			
		||||
 | 
			
		||||
    fn mesh(&self) -> Self::Output {
 | 
			
		||||
        let [hhd, vhd] = [self.half_diagonals.x, self.half_diagonals.y];
 | 
			
		||||
        let positions = vec![
 | 
			
		||||
            [hhd, 0.0, 0.0],
 | 
			
		||||
            [-hhd, 0.0, 0.0],
 | 
			
		||||
            [0.0, vhd, 0.0],
 | 
			
		||||
            [0.0, -vhd, 0.0],
 | 
			
		||||
        ];
 | 
			
		||||
        let normals = vec![[0.0, 0.0, 1.0]; 4];
 | 
			
		||||
        let uvs = vec![[1.0, 0.5], [0.0, 0.5], [0.5, 0.0], [0.5, 1.0]];
 | 
			
		||||
        let indices = Indices::U32(vec![1, 0, 2, 1, 3, 0]);
 | 
			
		||||
 | 
			
		||||
        Mesh::new(
 | 
			
		||||
            PrimitiveTopology::TriangleList,
 | 
			
		||||
            RenderAssetUsages::default(),
 | 
			
		||||
        )
 | 
			
		||||
        .with_inserted_indices(indices)
 | 
			
		||||
        .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions)
 | 
			
		||||
        .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
 | 
			
		||||
        .with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, uvs)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<Rhombus> for Mesh {
 | 
			
		||||
    fn from(rhombus: Rhombus) -> Self {
 | 
			
		||||
        rhombus.mesh()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Meshable for Triangle2d {
 | 
			
		||||
    type Output = Mesh;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -12,7 +12,7 @@ fn main() {
 | 
			
		||||
        .run();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const X_EXTENT: f32 = 800.;
 | 
			
		||||
const X_EXTENT: f32 = 900.;
 | 
			
		||||
 | 
			
		||||
fn setup(
 | 
			
		||||
    mut commands: Commands,
 | 
			
		||||
@ -28,6 +28,7 @@ fn setup(
 | 
			
		||||
        Mesh2dHandle(meshes.add(Ellipse::new(25.0, 50.0))),
 | 
			
		||||
        Mesh2dHandle(meshes.add(Annulus::new(25.0, 50.0))),
 | 
			
		||||
        Mesh2dHandle(meshes.add(Capsule2d::new(25.0, 50.0))),
 | 
			
		||||
        Mesh2dHandle(meshes.add(Rhombus::new(75.0, 100.0))),
 | 
			
		||||
        Mesh2dHandle(meshes.add(Rectangle::new(50.0, 100.0))),
 | 
			
		||||
        Mesh2dHandle(meshes.add(RegularPolygon::new(50.0, 6))),
 | 
			
		||||
        Mesh2dHandle(meshes.add(Triangle2d::new(
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user