Skip to content

Make math primitives runtime constructable, meshable #20250

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

Merged
merged 24 commits into from
Aug 13, 2025
Merged
Show file tree
Hide file tree
Changes from 16 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
92 changes: 7 additions & 85 deletions crates/bevy_gizmos/src/primitives/dim2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ use super::helpers::*;
use bevy_color::Color;
use bevy_math::{
primitives::{
Annulus, Arc2d, BoxedPolygon, BoxedPolyline2d, Capsule2d, Circle, CircularSector,
CircularSegment, Ellipse, Line2d, Plane2d, Polygon, Polyline2d, Primitive2d, Rectangle,
RegularPolygon, Rhombus, Segment2d, Triangle2d,
Annulus, Arc2d, Capsule2d, Circle, CircularSector, CircularSegment, Ellipse, Line2d,
Plane2d, Polygon, Polyline2d, Primitive2d, Rectangle, RegularPolygon, Rhombus, Segment2d,
Triangle2d,
},
Dir2, Isometry2d, Rot2, Vec2,
};
Expand Down Expand Up @@ -648,7 +648,7 @@ where

// polyline 2d

impl<const N: usize, Config, Clear> GizmoPrimitive2d<Polyline2d<N>> for GizmoBuffer<Config, Clear>
impl<Config, Clear> GizmoPrimitive2d<Polyline2d> for GizmoBuffer<Config, Clear>
where
Config: GizmoConfigGroup,
Clear: 'static + Send + Sync,
Expand All @@ -660,42 +660,7 @@ where

fn primitive_2d(
&mut self,
primitive: &Polyline2d<N>,
isometry: impl Into<Isometry2d>,
color: impl Into<Color>,
) -> Self::Output<'_> {
if !self.enabled {
return;
}

let isometry = isometry.into();

self.linestrip_2d(
primitive
.vertices
.iter()
.copied()
.map(|vec2| isometry * vec2),
color,
);
}
}

// boxed polyline 2d

impl<Config, Clear> GizmoPrimitive2d<BoxedPolyline2d> for GizmoBuffer<Config, Clear>
where
Config: GizmoConfigGroup,
Clear: 'static + Send + Sync,
{
type Output<'a>
= ()
where
Self: 'a;

fn primitive_2d(
&mut self,
primitive: &BoxedPolyline2d,
primitive: &Polyline2d,
isometry: impl Into<Isometry2d>,
color: impl Into<Color>,
) -> Self::Output<'_> {
Expand Down Expand Up @@ -784,7 +749,7 @@ where

// polygon 2d

impl<const N: usize, Config, Clear> GizmoPrimitive2d<Polygon<N>> for GizmoBuffer<Config, Clear>
impl<Config, Clear> GizmoPrimitive2d<Polygon> for GizmoBuffer<Config, Clear>
where
Config: GizmoConfigGroup,
Clear: 'static + Send + Sync,
Expand All @@ -796,7 +761,7 @@ where

fn primitive_2d(
&mut self,
primitive: &Polygon<N>,
primitive: &Polygon,
isometry: impl Into<Isometry2d>,
color: impl Into<Color>,
) -> Self::Output<'_> {
Expand Down Expand Up @@ -827,49 +792,6 @@ where
}
}

// boxed polygon 2d

impl<Config, Clear> GizmoPrimitive2d<BoxedPolygon> for GizmoBuffer<Config, Clear>
where
Config: GizmoConfigGroup,
Clear: 'static + Send + Sync,
{
type Output<'a>
= ()
where
Self: 'a;

fn primitive_2d(
&mut self,
primitive: &BoxedPolygon,
isometry: impl Into<Isometry2d>,
color: impl Into<Color>,
) -> Self::Output<'_> {
if !self.enabled {
return;
}

let isometry = isometry.into();

let closing_point = {
let first = primitive.vertices.first();
(primitive.vertices.last() != first)
.then_some(first)
.flatten()
.cloned()
};
self.linestrip_2d(
primitive
.vertices
.iter()
.copied()
.chain(closing_point)
.map(|vec2| isometry * vec2),
color,
);
}
}

// regular polygon 2d

impl<Config, Clear> GizmoPrimitive2d<RegularPolygon> for GizmoBuffer<Config, Clear>
Expand Down
41 changes: 5 additions & 36 deletions crates/bevy_gizmos/src/primitives/dim3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use super::helpers::*;
use bevy_color::Color;
use bevy_math::{
primitives::{
BoxedPolyline3d, Capsule3d, Cone, ConicalFrustum, Cuboid, Cylinder, Line3d, Plane3d,
Polyline3d, Primitive3d, Segment3d, Sphere, Tetrahedron, Torus, Triangle3d,
Capsule3d, Cone, ConicalFrustum, Cuboid, Cylinder, Line3d, Plane3d, Polyline3d,
Primitive3d, Segment3d, Sphere, Tetrahedron, Torus, Triangle3d,
},
Dir3, Isometry3d, Quat, UVec2, Vec2, Vec3,
};
Expand Down Expand Up @@ -235,7 +235,7 @@ where

// polyline 3d

impl<const N: usize, Config, Clear> GizmoPrimitive3d<Polyline3d<N>> for GizmoBuffer<Config, Clear>
impl<Config, Clear> GizmoPrimitive3d<Polyline3d> for GizmoBuffer<Config, Clear>
where
Config: GizmoConfigGroup,
Clear: 'static + Send + Sync,
Expand All @@ -247,34 +247,7 @@ where

fn primitive_3d(
&mut self,
primitive: &Polyline3d<N>,
isometry: impl Into<Isometry3d>,
color: impl Into<Color>,
) -> Self::Output<'_> {
if !self.enabled {
return;
}

let isometry = isometry.into();
self.linestrip(primitive.vertices.map(|vec3| isometry * vec3), color);
}
}

// boxed polyline 3d

impl<Config, Clear> GizmoPrimitive3d<BoxedPolyline3d> for GizmoBuffer<Config, Clear>
where
Config: GizmoConfigGroup,
Clear: 'static + Send + Sync,
{
type Output<'a>
= ()
where
Self: 'a;

fn primitive_3d(
&mut self,
primitive: &BoxedPolyline3d,
primitive: &Polyline3d,
isometry: impl Into<Isometry3d>,
color: impl Into<Color>,
) -> Self::Output<'_> {
Expand All @@ -284,11 +257,7 @@ where

let isometry = isometry.into();
self.linestrip(
primitive
.vertices
.iter()
.copied()
.map(|vec3| isometry * vec3),
primitive.vertices.iter().map(|vec3| isometry * *vec3),
color,
);
}
Expand Down
40 changes: 10 additions & 30 deletions crates/bevy_math/src/bounding/bounded2d/primitive_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@ use crate::{
ops,
primitives::{
Annulus, Arc2d, Capsule2d, Circle, CircularSector, CircularSegment, ConvexPolygon, Ellipse,
Line2d, Plane2d, Polygon, Polyline2d, Rectangle, RegularPolygon, Rhombus, Segment2d,
Triangle2d,
Line2d, Plane2d, Rectangle, RegularPolygon, Rhombus, Segment2d, Triangle2d,
},
Dir2, Isometry2d, Mat2, Rot2, Vec2,
};
use core::f32::consts::{FRAC_PI_2, PI, TAU};

#[cfg(feature = "alloc")]
use crate::primitives::{BoxedPolygon, BoxedPolyline2d};
use crate::primitives::{Polygon, Polyline2d};

use smallvec::SmallVec;

Expand Down Expand Up @@ -279,18 +278,8 @@ impl Bounded2d for Segment2d {
}
}

impl<const N: usize> Bounded2d for Polyline2d<N> {
fn aabb_2d(&self, isometry: impl Into<Isometry2d>) -> Aabb2d {
Aabb2d::from_point_cloud(isometry, &self.vertices)
}

fn bounding_circle(&self, isometry: impl Into<Isometry2d>) -> BoundingCircle {
BoundingCircle::from_point_cloud(isometry, &self.vertices)
}
}

#[cfg(feature = "alloc")]
impl Bounded2d for BoxedPolyline2d {
impl Bounded2d for Polyline2d {
fn aabb_2d(&self, isometry: impl Into<Isometry2d>) -> Aabb2d {
Aabb2d::from_point_cloud(isometry, &self.vertices)
}
Expand Down Expand Up @@ -366,7 +355,8 @@ impl Bounded2d for Rectangle {
}
}

impl<const N: usize> Bounded2d for Polygon<N> {
#[cfg(feature = "alloc")]
impl Bounded2d for Polygon {
fn aabb_2d(&self, isometry: impl Into<Isometry2d>) -> Aabb2d {
Aabb2d::from_point_cloud(isometry, &self.vertices)
}
Expand All @@ -376,24 +366,14 @@ impl<const N: usize> Bounded2d for Polygon<N> {
}
}

impl<const N: usize> Bounded2d for ConvexPolygon<N> {
fn aabb_2d(&self, isometry: impl Into<Isometry2d>) -> Aabb2d {
Aabb2d::from_point_cloud(isometry, self.vertices().as_slice())
}

fn bounding_circle(&self, isometry: impl Into<Isometry2d>) -> BoundingCircle {
BoundingCircle::from_point_cloud(isometry, self.vertices().as_slice())
}
}

#[cfg(feature = "alloc")]
impl Bounded2d for BoxedPolygon {
impl Bounded2d for ConvexPolygon {
fn aabb_2d(&self, isometry: impl Into<Isometry2d>) -> Aabb2d {
Aabb2d::from_point_cloud(isometry, &self.vertices)
Aabb2d::from_point_cloud(isometry, self.vertices())
}

fn bounding_circle(&self, isometry: impl Into<Isometry2d>) -> BoundingCircle {
BoundingCircle::from_point_cloud(isometry, &self.vertices)
BoundingCircle::from_point_cloud(isometry, self.vertices())
}
}

Expand Down Expand Up @@ -908,7 +888,7 @@ mod tests {

#[test]
fn polyline() {
let polyline = Polyline2d::<4>::new([
let polyline = Polyline2d::new([
Vec2::ONE,
Vec2::new(-1.0, 1.0),
Vec2::NEG_ONE,
Expand Down Expand Up @@ -981,7 +961,7 @@ mod tests {

#[test]
fn polygon() {
let polygon = Polygon::<4>::new([
let polygon = Polygon::new([
Vec2::ONE,
Vec2::new(-1.0, 1.0),
Vec2::NEG_ONE,
Expand Down
37 changes: 7 additions & 30 deletions crates/bevy_math/src/bounding/bounded3d/extrusion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ use crate::{
bounding::{BoundingCircle, BoundingVolume},
ops,
primitives::{
Capsule2d, Cuboid, Cylinder, Ellipse, Extrusion, Line2d, Polygon, Polyline2d, Primitive2d,
Rectangle, RegularPolygon, Segment2d, Triangle2d,
Capsule2d, Cuboid, Cylinder, Ellipse, Extrusion, Line2d, Primitive2d, Rectangle,
RegularPolygon, Segment2d, Triangle2d,
},
Isometry2d, Isometry3d, Quat, Rot2,
};

#[cfg(feature = "alloc")]
use crate::primitives::{BoxedPolygon, BoxedPolyline2d};
use crate::primitives::{Polygon, Polyline2d};

use crate::{bounding::Bounded2d, primitives::Circle};

Expand Down Expand Up @@ -96,19 +96,8 @@ impl BoundedExtrusion for Segment2d {
}
}

impl<const N: usize> BoundedExtrusion for Polyline2d<N> {
fn extrusion_aabb_3d(&self, half_depth: f32, isometry: impl Into<Isometry3d>) -> Aabb3d {
let isometry = isometry.into();
let aabb =
Aabb3d::from_point_cloud(isometry, self.vertices.map(|v| v.extend(0.)).into_iter());
let depth = isometry.rotation * Vec3A::new(0., 0., half_depth);

aabb.grow(depth.abs())
}
}

#[cfg(feature = "alloc")]
impl BoundedExtrusion for BoxedPolyline2d {
impl BoundedExtrusion for Polyline2d {
fn extrusion_aabb_3d(&self, half_depth: f32, isometry: impl Into<Isometry3d>) -> Aabb3d {
let isometry = isometry.into();
let aabb = Aabb3d::from_point_cloud(isometry, self.vertices.iter().map(|v| v.extend(0.)));
Expand Down Expand Up @@ -137,19 +126,7 @@ impl BoundedExtrusion for Rectangle {
}
}

impl<const N: usize> BoundedExtrusion for Polygon<N> {
fn extrusion_aabb_3d(&self, half_depth: f32, isometry: impl Into<Isometry3d>) -> Aabb3d {
let isometry = isometry.into();
let aabb =
Aabb3d::from_point_cloud(isometry, self.vertices.map(|v| v.extend(0.)).into_iter());
let depth = isometry.rotation * Vec3A::new(0., 0., half_depth);

aabb.grow(depth.abs())
}
}

#[cfg(feature = "alloc")]
impl BoundedExtrusion for BoxedPolygon {
impl BoundedExtrusion for Polygon {
fn extrusion_aabb_3d(&self, half_depth: f32, isometry: impl Into<Isometry3d>) -> Aabb3d {
let isometry = isometry.into();
let aabb = Aabb3d::from_point_cloud(isometry, self.vertices.iter().map(|v| v.extend(0.)));
Expand Down Expand Up @@ -367,7 +344,7 @@ mod tests {

#[test]
fn polyline() {
let polyline = Polyline2d::<4>::new([
let polyline = Polyline2d::new([
Vec2::ONE,
Vec2::new(-1.0, 1.0),
Vec2::NEG_ONE,
Expand Down Expand Up @@ -413,7 +390,7 @@ mod tests {

#[test]
fn polygon() {
let polygon = Polygon::<4>::new([
let polygon = Polygon::new([
Vec2::ONE,
Vec2::new(-1.0, 1.0),
Vec2::NEG_ONE,
Expand Down
Loading
Loading