Implement From translation and rotation for isometries (#15733)
# Objective
Several of our APIs (namely gizmos and bounding) use isometries on
current Bevy main. This is nicer than separate properties in a lot of
cases, but users have still expressed usability concerns.
One problem is that in a lot of cases, you only care about e.g.
translation, so you end up with this:
```rust
gizmos.cross_2d(
Isometry2d::from_translation(Vec2::new(-160.0, 120.0)),
12.0,
FUCHSIA,
);
```
The isometry adds quite a lot of length and verbosity, and isn't really
that relevant since only the translation is important here.
It would be nice if you could use the translation directly, and only
supply an isometry if both translation and rotation are needed. This
would make the following possible:
```rust
gizmos.cross_2d(Vec2::new(-160.0, 120.0), 12.0, FUCHSIA);
```
removing a lot of verbosity.
## Solution
Implement `From<Vec2>` and `From<Rot2>` for `Isometry2d`, and
`From<Vec3>`, `From<Vec3A>`, and `From<Quat>` for `Isometry3d`. These
are lossless conversions that fit the semantics of `From`.
This makes the proposed API possible! The methods must now simply take
an `impl Into<IsometryNd>`, and this works:
```rust
gizmos.cross_2d(Vec2::new(-160.0, 120.0), 12.0, FUCHSIA);
```
This commit is contained in:
parent
8d53c0af91
commit
21b78b5990
@ -50,14 +50,14 @@ where
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn arc_2d(
|
pub fn arc_2d(
|
||||||
&mut self,
|
&mut self,
|
||||||
isometry: Isometry2d,
|
isometry: impl Into<Isometry2d>,
|
||||||
arc_angle: f32,
|
arc_angle: f32,
|
||||||
radius: f32,
|
radius: f32,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Arc2dBuilder<'_, 'w, 's, Config, Clear> {
|
) -> Arc2dBuilder<'_, 'w, 's, Config, Clear> {
|
||||||
Arc2dBuilder {
|
Arc2dBuilder {
|
||||||
gizmos: self,
|
gizmos: self,
|
||||||
isometry,
|
isometry: isometry.into(),
|
||||||
arc_angle,
|
arc_angle,
|
||||||
radius,
|
radius,
|
||||||
color: color.into(),
|
color: color.into(),
|
||||||
@ -176,13 +176,13 @@ where
|
|||||||
&mut self,
|
&mut self,
|
||||||
angle: f32,
|
angle: f32,
|
||||||
radius: f32,
|
radius: f32,
|
||||||
isometry: Isometry3d,
|
isometry: impl Into<Isometry3d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Arc3dBuilder<'_, 'w, 's, Config, Clear> {
|
) -> Arc3dBuilder<'_, 'w, 's, Config, Clear> {
|
||||||
Arc3dBuilder {
|
Arc3dBuilder {
|
||||||
gizmos: self,
|
gizmos: self,
|
||||||
start_vertex: Vec3::X,
|
start_vertex: Vec3::X,
|
||||||
isometry,
|
isometry: isometry.into(),
|
||||||
angle,
|
angle,
|
||||||
radius,
|
radius,
|
||||||
color: color.into(),
|
color: color.into(),
|
||||||
|
|||||||
@ -51,13 +51,13 @@ where
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn ellipse(
|
pub fn ellipse(
|
||||||
&mut self,
|
&mut self,
|
||||||
isometry: Isometry3d,
|
isometry: impl Into<Isometry3d>,
|
||||||
half_size: Vec2,
|
half_size: Vec2,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> EllipseBuilder<'_, 'w, 's, Config, Clear> {
|
) -> EllipseBuilder<'_, 'w, 's, Config, Clear> {
|
||||||
EllipseBuilder {
|
EllipseBuilder {
|
||||||
gizmos: self,
|
gizmos: self,
|
||||||
isometry,
|
isometry: isometry.into(),
|
||||||
half_size,
|
half_size,
|
||||||
color: color.into(),
|
color: color.into(),
|
||||||
resolution: DEFAULT_CIRCLE_RESOLUTION,
|
resolution: DEFAULT_CIRCLE_RESOLUTION,
|
||||||
@ -92,13 +92,13 @@ where
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn ellipse_2d(
|
pub fn ellipse_2d(
|
||||||
&mut self,
|
&mut self,
|
||||||
isometry: Isometry2d,
|
isometry: impl Into<Isometry2d>,
|
||||||
half_size: Vec2,
|
half_size: Vec2,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Ellipse2dBuilder<'_, 'w, 's, Config, Clear> {
|
) -> Ellipse2dBuilder<'_, 'w, 's, Config, Clear> {
|
||||||
Ellipse2dBuilder {
|
Ellipse2dBuilder {
|
||||||
gizmos: self,
|
gizmos: self,
|
||||||
isometry,
|
isometry: isometry.into(),
|
||||||
half_size,
|
half_size,
|
||||||
color: color.into(),
|
color: color.into(),
|
||||||
resolution: DEFAULT_CIRCLE_RESOLUTION,
|
resolution: DEFAULT_CIRCLE_RESOLUTION,
|
||||||
@ -131,13 +131,13 @@ where
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn circle(
|
pub fn circle(
|
||||||
&mut self,
|
&mut self,
|
||||||
isometry: Isometry3d,
|
isometry: impl Into<Isometry3d>,
|
||||||
radius: f32,
|
radius: f32,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> EllipseBuilder<'_, 'w, 's, Config, Clear> {
|
) -> EllipseBuilder<'_, 'w, 's, Config, Clear> {
|
||||||
EllipseBuilder {
|
EllipseBuilder {
|
||||||
gizmos: self,
|
gizmos: self,
|
||||||
isometry,
|
isometry: isometry.into(),
|
||||||
half_size: Vec2::splat(radius),
|
half_size: Vec2::splat(radius),
|
||||||
color: color.into(),
|
color: color.into(),
|
||||||
resolution: DEFAULT_CIRCLE_RESOLUTION,
|
resolution: DEFAULT_CIRCLE_RESOLUTION,
|
||||||
@ -172,13 +172,13 @@ where
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn circle_2d(
|
pub fn circle_2d(
|
||||||
&mut self,
|
&mut self,
|
||||||
isometry: Isometry2d,
|
isometry: impl Into<Isometry2d>,
|
||||||
radius: f32,
|
radius: f32,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Ellipse2dBuilder<'_, 'w, 's, Config, Clear> {
|
) -> Ellipse2dBuilder<'_, 'w, 's, Config, Clear> {
|
||||||
Ellipse2dBuilder {
|
Ellipse2dBuilder {
|
||||||
gizmos: self,
|
gizmos: self,
|
||||||
isometry,
|
isometry: isometry.into(),
|
||||||
half_size: Vec2::splat(radius),
|
half_size: Vec2::splat(radius),
|
||||||
color: color.into(),
|
color: color.into(),
|
||||||
resolution: DEFAULT_CIRCLE_RESOLUTION,
|
resolution: DEFAULT_CIRCLE_RESOLUTION,
|
||||||
@ -214,14 +214,14 @@ where
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn sphere(
|
pub fn sphere(
|
||||||
&mut self,
|
&mut self,
|
||||||
isometry: Isometry3d,
|
isometry: impl Into<Isometry3d>,
|
||||||
radius: f32,
|
radius: f32,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> SphereBuilder<'_, 'w, 's, Config, Clear> {
|
) -> SphereBuilder<'_, 'w, 's, Config, Clear> {
|
||||||
SphereBuilder {
|
SphereBuilder {
|
||||||
gizmos: self,
|
gizmos: self,
|
||||||
radius,
|
radius,
|
||||||
isometry,
|
isometry: isometry.into(),
|
||||||
color: color.into(),
|
color: color.into(),
|
||||||
resolution: DEFAULT_CIRCLE_RESOLUTION,
|
resolution: DEFAULT_CIRCLE_RESOLUTION,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,7 +30,13 @@ where
|
|||||||
/// }
|
/// }
|
||||||
/// # bevy_ecs::system::assert_is_system(system);
|
/// # bevy_ecs::system::assert_is_system(system);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn cross(&mut self, isometry: Isometry3d, half_size: f32, color: impl Into<Color>) {
|
pub fn cross(
|
||||||
|
&mut self,
|
||||||
|
isometry: impl Into<Isometry3d>,
|
||||||
|
half_size: f32,
|
||||||
|
color: impl Into<Color>,
|
||||||
|
) {
|
||||||
|
let isometry = isometry.into();
|
||||||
let color: Color = color.into();
|
let color: Color = color.into();
|
||||||
[Vec3::X, Vec3::Y, Vec3::Z]
|
[Vec3::X, Vec3::Y, Vec3::Z]
|
||||||
.map(|axis| axis * half_size)
|
.map(|axis| axis * half_size)
|
||||||
@ -59,7 +65,13 @@ where
|
|||||||
/// }
|
/// }
|
||||||
/// # bevy_ecs::system::assert_is_system(system);
|
/// # bevy_ecs::system::assert_is_system(system);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn cross_2d(&mut self, isometry: Isometry2d, half_size: f32, color: impl Into<Color>) {
|
pub fn cross_2d(
|
||||||
|
&mut self,
|
||||||
|
isometry: impl Into<Isometry2d>,
|
||||||
|
half_size: f32,
|
||||||
|
color: impl Into<Color>,
|
||||||
|
) {
|
||||||
|
let isometry = isometry.into();
|
||||||
let color: Color = color.into();
|
let color: Color = color.into();
|
||||||
[Vec2::X, Vec2::Y]
|
[Vec2::X, Vec2::Y]
|
||||||
.map(|axis| axis * half_size)
|
.map(|axis| axis * half_size)
|
||||||
|
|||||||
@ -482,10 +482,11 @@ where
|
|||||||
/// # bevy_ecs::system::assert_is_system(system);
|
/// # bevy_ecs::system::assert_is_system(system);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn rect(&mut self, isometry: Isometry3d, size: Vec2, color: impl Into<Color>) {
|
pub fn rect(&mut self, isometry: impl Into<Isometry3d>, size: Vec2, color: impl Into<Color>) {
|
||||||
if !self.enabled {
|
if !self.enabled {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
let isometry = isometry.into();
|
||||||
let [tl, tr, br, bl] = rect_inner(size).map(|vec2| isometry * vec2.extend(0.));
|
let [tl, tr, br, bl] = rect_inner(size).map(|vec2| isometry * vec2.extend(0.));
|
||||||
self.linestrip([tl, tr, br, bl, tl], color);
|
self.linestrip([tl, tr, br, bl, tl], color);
|
||||||
}
|
}
|
||||||
@ -709,10 +710,16 @@ where
|
|||||||
/// # bevy_ecs::system::assert_is_system(system);
|
/// # bevy_ecs::system::assert_is_system(system);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn rect_2d(&mut self, isometry: Isometry2d, size: Vec2, color: impl Into<Color>) {
|
pub fn rect_2d(
|
||||||
|
&mut self,
|
||||||
|
isometry: impl Into<Isometry2d>,
|
||||||
|
size: Vec2,
|
||||||
|
color: impl Into<Color>,
|
||||||
|
) {
|
||||||
if !self.enabled {
|
if !self.enabled {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
let isometry = isometry.into();
|
||||||
let [tl, tr, br, bl] = rect_inner(size).map(|vec2| isometry * vec2);
|
let [tl, tr, br, bl] = rect_inner(size).map(|vec2| isometry * vec2);
|
||||||
self.linestrip_2d([tl, tr, br, bl, tl], color);
|
self.linestrip_2d([tl, tr, br, bl, tl], color);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -218,14 +218,14 @@ where
|
|||||||
/// ```
|
/// ```
|
||||||
pub fn grid(
|
pub fn grid(
|
||||||
&mut self,
|
&mut self,
|
||||||
isometry: Isometry3d,
|
isometry: impl Into<Isometry3d>,
|
||||||
cell_count: UVec2,
|
cell_count: UVec2,
|
||||||
spacing: Vec2,
|
spacing: Vec2,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> GridBuilder2d<'_, 'w, 's, Config, Clear> {
|
) -> GridBuilder2d<'_, 'w, 's, Config, Clear> {
|
||||||
GridBuilder2d {
|
GridBuilder2d {
|
||||||
gizmos: self,
|
gizmos: self,
|
||||||
isometry,
|
isometry: isometry.into(),
|
||||||
spacing,
|
spacing,
|
||||||
cell_count,
|
cell_count,
|
||||||
skew: Vec2::ZERO,
|
skew: Vec2::ZERO,
|
||||||
@ -272,14 +272,14 @@ where
|
|||||||
/// ```
|
/// ```
|
||||||
pub fn grid_3d(
|
pub fn grid_3d(
|
||||||
&mut self,
|
&mut self,
|
||||||
isometry: Isometry3d,
|
isometry: impl Into<Isometry3d>,
|
||||||
cell_count: UVec3,
|
cell_count: UVec3,
|
||||||
spacing: Vec3,
|
spacing: Vec3,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> GridBuilder3d<'_, 'w, 's, Config, Clear> {
|
) -> GridBuilder3d<'_, 'w, 's, Config, Clear> {
|
||||||
GridBuilder3d {
|
GridBuilder3d {
|
||||||
gizmos: self,
|
gizmos: self,
|
||||||
isometry,
|
isometry: isometry.into(),
|
||||||
spacing,
|
spacing,
|
||||||
cell_count,
|
cell_count,
|
||||||
skew: Vec3::ZERO,
|
skew: Vec3::ZERO,
|
||||||
@ -326,11 +326,12 @@ where
|
|||||||
/// ```
|
/// ```
|
||||||
pub fn grid_2d(
|
pub fn grid_2d(
|
||||||
&mut self,
|
&mut self,
|
||||||
isometry: Isometry2d,
|
isometry: impl Into<Isometry2d>,
|
||||||
cell_count: UVec2,
|
cell_count: UVec2,
|
||||||
spacing: Vec2,
|
spacing: Vec2,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> GridBuilder2d<'_, 'w, 's, Config, Clear> {
|
) -> GridBuilder2d<'_, 'w, 's, Config, Clear> {
|
||||||
|
let isometry = isometry.into();
|
||||||
GridBuilder2d {
|
GridBuilder2d {
|
||||||
gizmos: self,
|
gizmos: self,
|
||||||
isometry: Isometry3d::new(
|
isometry: Isometry3d::new(
|
||||||
|
|||||||
@ -41,20 +41,10 @@ fn point_light_gizmo(
|
|||||||
) {
|
) {
|
||||||
let position = transform.translation();
|
let position = transform.translation();
|
||||||
gizmos
|
gizmos
|
||||||
.primitive_3d(
|
.primitive_3d(&Sphere::new(point_light.radius), position, color)
|
||||||
&Sphere {
|
|
||||||
radius: point_light.radius,
|
|
||||||
},
|
|
||||||
Isometry3d::from_translation(position),
|
|
||||||
color,
|
|
||||||
)
|
|
||||||
.resolution(16);
|
.resolution(16);
|
||||||
gizmos
|
gizmos
|
||||||
.sphere(
|
.sphere(position, point_light.range, color)
|
||||||
Isometry3d::from_translation(position),
|
|
||||||
point_light.range,
|
|
||||||
color,
|
|
||||||
)
|
|
||||||
.resolution(32);
|
.resolution(32);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,13 +58,7 @@ fn spot_light_gizmo(
|
|||||||
) {
|
) {
|
||||||
let (_, rotation, translation) = transform.to_scale_rotation_translation();
|
let (_, rotation, translation) = transform.to_scale_rotation_translation();
|
||||||
gizmos
|
gizmos
|
||||||
.primitive_3d(
|
.primitive_3d(&Sphere::new(spot_light.radius), translation, color)
|
||||||
&Sphere {
|
|
||||||
radius: spot_light.radius,
|
|
||||||
},
|
|
||||||
Isometry3d::from_translation(translation),
|
|
||||||
color,
|
|
||||||
)
|
|
||||||
.resolution(16);
|
.resolution(16);
|
||||||
|
|
||||||
// Offset the tip of the cone to the light position.
|
// Offset the tip of the cone to the light position.
|
||||||
|
|||||||
@ -33,7 +33,7 @@ pub trait GizmoPrimitive2d<P: Primitive2d> {
|
|||||||
fn primitive_2d(
|
fn primitive_2d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &P,
|
primitive: &P,
|
||||||
isometry: Isometry2d,
|
isometry: impl Into<Isometry2d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_>;
|
) -> Self::Output<'_>;
|
||||||
}
|
}
|
||||||
@ -53,12 +53,13 @@ where
|
|||||||
fn primitive_2d(
|
fn primitive_2d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &Dir2,
|
primitive: &Dir2,
|
||||||
isometry: Isometry2d,
|
isometry: impl Into<Isometry2d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
if !self.enabled {
|
if !self.enabled {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
let isometry = isometry.into();
|
||||||
let start = Vec2::ZERO;
|
let start = Vec2::ZERO;
|
||||||
let end = *primitive * MIN_LINE_LEN;
|
let end = *primitive * MIN_LINE_LEN;
|
||||||
self.arrow_2d(isometry * start, isometry * end, color);
|
self.arrow_2d(isometry * start, isometry * end, color);
|
||||||
@ -80,13 +81,14 @@ where
|
|||||||
fn primitive_2d(
|
fn primitive_2d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &Arc2d,
|
primitive: &Arc2d,
|
||||||
isometry: Isometry2d,
|
isometry: impl Into<Isometry2d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
if !self.enabled {
|
if !self.enabled {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let isometry = isometry.into();
|
||||||
let start_iso = isometry * Isometry2d::from_rotation(Rot2::radians(-primitive.half_angle));
|
let start_iso = isometry * Isometry2d::from_rotation(Rot2::radians(-primitive.half_angle));
|
||||||
|
|
||||||
self.arc_2d(
|
self.arc_2d(
|
||||||
@ -113,7 +115,7 @@ where
|
|||||||
fn primitive_2d(
|
fn primitive_2d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &Circle,
|
primitive: &Circle,
|
||||||
isometry: Isometry2d,
|
isometry: impl Into<Isometry2d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
self.circle_2d(isometry, primitive.radius, color)
|
self.circle_2d(isometry, primitive.radius, color)
|
||||||
@ -135,13 +137,14 @@ where
|
|||||||
fn primitive_2d(
|
fn primitive_2d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &CircularSector,
|
primitive: &CircularSector,
|
||||||
isometry: Isometry2d,
|
isometry: impl Into<Isometry2d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
if !self.enabled {
|
if !self.enabled {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let isometry = isometry.into();
|
||||||
let color = color.into();
|
let color = color.into();
|
||||||
|
|
||||||
let start_iso =
|
let start_iso =
|
||||||
@ -177,13 +180,14 @@ where
|
|||||||
fn primitive_2d(
|
fn primitive_2d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &CircularSegment,
|
primitive: &CircularSegment,
|
||||||
isometry: Isometry2d,
|
isometry: impl Into<Isometry2d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
if !self.enabled {
|
if !self.enabled {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let isometry = isometry.into();
|
||||||
let color = color.into();
|
let color = color.into();
|
||||||
|
|
||||||
let start_iso =
|
let start_iso =
|
||||||
@ -218,7 +222,7 @@ where
|
|||||||
fn primitive_2d<'a>(
|
fn primitive_2d<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &Ellipse,
|
primitive: &Ellipse,
|
||||||
isometry: Isometry2d,
|
isometry: impl Into<Isometry2d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
self.ellipse_2d(isometry, primitive.half_size, color)
|
self.ellipse_2d(isometry, primitive.half_size, color)
|
||||||
@ -280,12 +284,12 @@ where
|
|||||||
fn primitive_2d(
|
fn primitive_2d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &Annulus,
|
primitive: &Annulus,
|
||||||
isometry: Isometry2d,
|
isometry: impl Into<Isometry2d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
Annulus2dBuilder {
|
Annulus2dBuilder {
|
||||||
gizmos: self,
|
gizmos: self,
|
||||||
isometry,
|
isometry: isometry.into(),
|
||||||
inner_radius: primitive.inner_circle.radius,
|
inner_radius: primitive.inner_circle.radius,
|
||||||
outer_radius: primitive.outer_circle.radius,
|
outer_radius: primitive.outer_circle.radius,
|
||||||
color: color.into(),
|
color: color.into(),
|
||||||
@ -340,12 +344,13 @@ where
|
|||||||
fn primitive_2d(
|
fn primitive_2d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &Rhombus,
|
primitive: &Rhombus,
|
||||||
isometry: Isometry2d,
|
isometry: impl Into<Isometry2d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
if !self.enabled {
|
if !self.enabled {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
let isometry = isometry.into();
|
||||||
let [a, b, c, d] =
|
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)| {
|
[(1.0, 0.0), (0.0, 1.0), (-1.0, 0.0), (0.0, -1.0)].map(|(sign_x, sign_y)| {
|
||||||
Vec2::new(
|
Vec2::new(
|
||||||
@ -373,9 +378,10 @@ where
|
|||||||
fn primitive_2d(
|
fn primitive_2d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &Capsule2d,
|
primitive: &Capsule2d,
|
||||||
isometry: Isometry2d,
|
isometry: impl Into<Isometry2d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
|
let isometry = isometry.into();
|
||||||
let polymorphic_color: Color = color.into();
|
let polymorphic_color: Color = color.into();
|
||||||
|
|
||||||
if !self.enabled {
|
if !self.enabled {
|
||||||
@ -465,13 +471,13 @@ where
|
|||||||
fn primitive_2d(
|
fn primitive_2d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &Line2d,
|
primitive: &Line2d,
|
||||||
isometry: Isometry2d,
|
isometry: impl Into<Isometry2d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
Line2dBuilder {
|
Line2dBuilder {
|
||||||
gizmos: self,
|
gizmos: self,
|
||||||
direction: primitive.direction,
|
direction: primitive.direction,
|
||||||
isometry,
|
isometry: isometry.into(),
|
||||||
color: color.into(),
|
color: color.into(),
|
||||||
draw_arrow: false,
|
draw_arrow: false,
|
||||||
}
|
}
|
||||||
@ -523,9 +529,10 @@ where
|
|||||||
fn primitive_2d(
|
fn primitive_2d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &Plane2d,
|
primitive: &Plane2d,
|
||||||
isometry: Isometry2d,
|
isometry: impl Into<Isometry2d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
|
let isometry = isometry.into();
|
||||||
let polymorphic_color: Color = color.into();
|
let polymorphic_color: Color = color.into();
|
||||||
|
|
||||||
if !self.enabled {
|
if !self.enabled {
|
||||||
@ -604,7 +611,7 @@ where
|
|||||||
fn primitive_2d(
|
fn primitive_2d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &Segment2d,
|
primitive: &Segment2d,
|
||||||
isometry: Isometry2d,
|
isometry: impl Into<Isometry2d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
Segment2dBuilder {
|
Segment2dBuilder {
|
||||||
@ -612,7 +619,7 @@ where
|
|||||||
direction: primitive.direction,
|
direction: primitive.direction,
|
||||||
half_length: primitive.half_length,
|
half_length: primitive.half_length,
|
||||||
|
|
||||||
isometry,
|
isometry: isometry.into(),
|
||||||
color: color.into(),
|
color: color.into(),
|
||||||
|
|
||||||
draw_arrow: Default::default(),
|
draw_arrow: Default::default(),
|
||||||
@ -658,13 +665,15 @@ where
|
|||||||
fn primitive_2d(
|
fn primitive_2d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &Polyline2d<N>,
|
primitive: &Polyline2d<N>,
|
||||||
isometry: Isometry2d,
|
isometry: impl Into<Isometry2d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
if !self.enabled {
|
if !self.enabled {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
self.linestrip_2d(
|
self.linestrip_2d(
|
||||||
primitive
|
primitive
|
||||||
.vertices
|
.vertices
|
||||||
@ -691,13 +700,15 @@ where
|
|||||||
fn primitive_2d(
|
fn primitive_2d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &BoxedPolyline2d,
|
primitive: &BoxedPolyline2d,
|
||||||
isometry: Isometry2d,
|
isometry: impl Into<Isometry2d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
if !self.enabled {
|
if !self.enabled {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
self.linestrip_2d(
|
self.linestrip_2d(
|
||||||
primitive
|
primitive
|
||||||
.vertices
|
.vertices
|
||||||
@ -724,12 +735,15 @@ where
|
|||||||
fn primitive_2d(
|
fn primitive_2d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &Triangle2d,
|
primitive: &Triangle2d,
|
||||||
isometry: Isometry2d,
|
isometry: impl Into<Isometry2d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
if !self.enabled {
|
if !self.enabled {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
let [a, b, c] = primitive.vertices;
|
let [a, b, c] = primitive.vertices;
|
||||||
let positions = [a, b, c, a].map(|vec2| isometry * vec2);
|
let positions = [a, b, c, a].map(|vec2| isometry * vec2);
|
||||||
self.linestrip_2d(positions, color);
|
self.linestrip_2d(positions, color);
|
||||||
@ -751,13 +765,15 @@ where
|
|||||||
fn primitive_2d(
|
fn primitive_2d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &Rectangle,
|
primitive: &Rectangle,
|
||||||
isometry: Isometry2d,
|
isometry: impl Into<Isometry2d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
if !self.enabled {
|
if !self.enabled {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
let [a, b, c, d] =
|
let [a, b, c, d] =
|
||||||
[(1.0, 1.0), (1.0, -1.0), (-1.0, -1.0), (-1.0, 1.0)].map(|(sign_x, sign_y)| {
|
[(1.0, 1.0), (1.0, -1.0), (-1.0, -1.0), (-1.0, 1.0)].map(|(sign_x, sign_y)| {
|
||||||
Vec2::new(
|
Vec2::new(
|
||||||
@ -786,13 +802,15 @@ where
|
|||||||
fn primitive_2d(
|
fn primitive_2d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &Polygon<N>,
|
primitive: &Polygon<N>,
|
||||||
isometry: Isometry2d,
|
isometry: impl Into<Isometry2d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
if !self.enabled {
|
if !self.enabled {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
// Check if the polygon needs a closing point
|
// Check if the polygon needs a closing point
|
||||||
let closing_point = {
|
let closing_point = {
|
||||||
let first = primitive.vertices.first();
|
let first = primitive.vertices.first();
|
||||||
@ -829,13 +847,15 @@ where
|
|||||||
fn primitive_2d(
|
fn primitive_2d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &BoxedPolygon,
|
primitive: &BoxedPolygon,
|
||||||
isometry: Isometry2d,
|
isometry: impl Into<Isometry2d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
if !self.enabled {
|
if !self.enabled {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
let closing_point = {
|
let closing_point = {
|
||||||
let first = primitive.vertices.first();
|
let first = primitive.vertices.first();
|
||||||
(primitive.vertices.last() != first)
|
(primitive.vertices.last() != first)
|
||||||
@ -870,13 +890,15 @@ where
|
|||||||
fn primitive_2d(
|
fn primitive_2d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &RegularPolygon,
|
primitive: &RegularPolygon,
|
||||||
isometry: Isometry2d,
|
isometry: impl Into<Isometry2d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
if !self.enabled {
|
if !self.enabled {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
let points = (0..=primitive.sides)
|
let points = (0..=primitive.sides)
|
||||||
.map(|n| single_circle_coordinate(primitive.circumcircle.radius, primitive.sides, n))
|
.map(|n| single_circle_coordinate(primitive.circumcircle.radius, primitive.sides, n))
|
||||||
.map(|vec2| isometry * vec2);
|
.map(|vec2| isometry * vec2);
|
||||||
|
|||||||
@ -31,7 +31,7 @@ pub trait GizmoPrimitive3d<P: Primitive3d> {
|
|||||||
fn primitive_3d(
|
fn primitive_3d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &P,
|
primitive: &P,
|
||||||
isometry: Isometry3d,
|
isometry: impl Into<Isometry3d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_>;
|
) -> Self::Output<'_>;
|
||||||
}
|
}
|
||||||
@ -51,9 +51,10 @@ where
|
|||||||
fn primitive_3d(
|
fn primitive_3d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &Dir3,
|
primitive: &Dir3,
|
||||||
isometry: Isometry3d,
|
isometry: impl Into<Isometry3d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
|
let isometry = isometry.into();
|
||||||
let start = Vec3::ZERO;
|
let start = Vec3::ZERO;
|
||||||
let end = primitive.as_vec3();
|
let end = primitive.as_vec3();
|
||||||
self.arrow(isometry * start, isometry * end, color);
|
self.arrow(isometry * start, isometry * end, color);
|
||||||
@ -75,7 +76,7 @@ where
|
|||||||
fn primitive_3d(
|
fn primitive_3d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &Sphere,
|
primitive: &Sphere,
|
||||||
isometry: Isometry3d,
|
isometry: impl Into<Isometry3d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
self.sphere(isometry, primitive.radius, color)
|
self.sphere(isometry, primitive.radius, color)
|
||||||
@ -136,13 +137,13 @@ where
|
|||||||
fn primitive_3d(
|
fn primitive_3d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &Plane3d,
|
primitive: &Plane3d,
|
||||||
isometry: Isometry3d,
|
isometry: impl Into<Isometry3d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
Plane3dBuilder {
|
Plane3dBuilder {
|
||||||
gizmos: self,
|
gizmos: self,
|
||||||
normal: primitive.normal,
|
normal: primitive.normal,
|
||||||
isometry,
|
isometry: isometry.into(),
|
||||||
color: color.into(),
|
color: color.into(),
|
||||||
cell_count: UVec2::splat(3),
|
cell_count: UVec2::splat(3),
|
||||||
spacing: Vec2::splat(1.0),
|
spacing: Vec2::splat(1.0),
|
||||||
@ -188,13 +189,14 @@ where
|
|||||||
fn primitive_3d(
|
fn primitive_3d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &Line3d,
|
primitive: &Line3d,
|
||||||
isometry: Isometry3d,
|
isometry: impl Into<Isometry3d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
if !self.enabled {
|
if !self.enabled {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let isometry = isometry.into();
|
||||||
let color = color.into();
|
let color = color.into();
|
||||||
let direction = primitive.direction.as_vec3();
|
let direction = primitive.direction.as_vec3();
|
||||||
self.arrow(isometry * Vec3::ZERO, isometry * direction, color);
|
self.arrow(isometry * Vec3::ZERO, isometry * direction, color);
|
||||||
@ -222,13 +224,14 @@ where
|
|||||||
fn primitive_3d(
|
fn primitive_3d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &Segment3d,
|
primitive: &Segment3d,
|
||||||
isometry: Isometry3d,
|
isometry: impl Into<Isometry3d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
if !self.enabled {
|
if !self.enabled {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let isometry = isometry.into();
|
||||||
let direction = primitive.direction.as_vec3();
|
let direction = primitive.direction.as_vec3();
|
||||||
self.line(isometry * direction, isometry * (-direction), color);
|
self.line(isometry * direction, isometry * (-direction), color);
|
||||||
}
|
}
|
||||||
@ -250,13 +253,14 @@ where
|
|||||||
fn primitive_3d(
|
fn primitive_3d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &Polyline3d<N>,
|
primitive: &Polyline3d<N>,
|
||||||
isometry: Isometry3d,
|
isometry: impl Into<Isometry3d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
if !self.enabled {
|
if !self.enabled {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let isometry = isometry.into();
|
||||||
self.linestrip(primitive.vertices.map(|vec3| isometry * vec3), color);
|
self.linestrip(primitive.vertices.map(|vec3| isometry * vec3), color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -276,13 +280,14 @@ where
|
|||||||
fn primitive_3d(
|
fn primitive_3d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &BoxedPolyline3d,
|
primitive: &BoxedPolyline3d,
|
||||||
isometry: Isometry3d,
|
isometry: impl Into<Isometry3d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
if !self.enabled {
|
if !self.enabled {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let isometry = isometry.into();
|
||||||
self.linestrip(
|
self.linestrip(
|
||||||
primitive
|
primitive
|
||||||
.vertices
|
.vertices
|
||||||
@ -309,13 +314,14 @@ where
|
|||||||
fn primitive_3d(
|
fn primitive_3d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &Triangle3d,
|
primitive: &Triangle3d,
|
||||||
isometry: Isometry3d,
|
isometry: impl Into<Isometry3d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
if !self.enabled {
|
if !self.enabled {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let isometry = isometry.into();
|
||||||
let [a, b, c] = primitive.vertices;
|
let [a, b, c] = primitive.vertices;
|
||||||
self.linestrip([a, b, c, a].map(|vec3| isometry * vec3), color);
|
self.linestrip([a, b, c, a].map(|vec3| isometry * vec3), color);
|
||||||
}
|
}
|
||||||
@ -336,13 +342,15 @@ where
|
|||||||
fn primitive_3d(
|
fn primitive_3d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &Cuboid,
|
primitive: &Cuboid,
|
||||||
isometry: Isometry3d,
|
isometry: impl Into<Isometry3d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
if !self.enabled {
|
if !self.enabled {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
// transform the points from the reference unit cube to the cuboid coords
|
// transform the points from the reference unit cube to the cuboid coords
|
||||||
let vertices @ [a, b, c, d, e, f, g, h] = [
|
let vertices @ [a, b, c, d, e, f, g, h] = [
|
||||||
[1.0, 1.0, 1.0],
|
[1.0, 1.0, 1.0],
|
||||||
@ -429,14 +437,14 @@ where
|
|||||||
fn primitive_3d(
|
fn primitive_3d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &Cylinder,
|
primitive: &Cylinder,
|
||||||
isometry: Isometry3d,
|
isometry: impl Into<Isometry3d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
Cylinder3dBuilder {
|
Cylinder3dBuilder {
|
||||||
gizmos: self,
|
gizmos: self,
|
||||||
radius: primitive.radius,
|
radius: primitive.radius,
|
||||||
half_height: primitive.half_height,
|
half_height: primitive.half_height,
|
||||||
isometry,
|
isometry: isometry.into(),
|
||||||
color: color.into(),
|
color: color.into(),
|
||||||
resolution: DEFAULT_RESOLUTION,
|
resolution: DEFAULT_RESOLUTION,
|
||||||
}
|
}
|
||||||
@ -515,14 +523,14 @@ where
|
|||||||
fn primitive_3d(
|
fn primitive_3d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &Capsule3d,
|
primitive: &Capsule3d,
|
||||||
isometry: Isometry3d,
|
isometry: impl Into<Isometry3d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
Capsule3dBuilder {
|
Capsule3dBuilder {
|
||||||
gizmos: self,
|
gizmos: self,
|
||||||
radius: primitive.radius,
|
radius: primitive.radius,
|
||||||
half_length: primitive.half_length,
|
half_length: primitive.half_length,
|
||||||
isometry,
|
isometry: isometry.into(),
|
||||||
color: color.into(),
|
color: color.into(),
|
||||||
resolution: DEFAULT_RESOLUTION,
|
resolution: DEFAULT_RESOLUTION,
|
||||||
}
|
}
|
||||||
@ -655,14 +663,14 @@ where
|
|||||||
fn primitive_3d(
|
fn primitive_3d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &Cone,
|
primitive: &Cone,
|
||||||
isometry: Isometry3d,
|
isometry: impl Into<Isometry3d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
Cone3dBuilder {
|
Cone3dBuilder {
|
||||||
gizmos: self,
|
gizmos: self,
|
||||||
radius: primitive.radius,
|
radius: primitive.radius,
|
||||||
height: primitive.height,
|
height: primitive.height,
|
||||||
isometry,
|
isometry: isometry.into(),
|
||||||
color: color.into(),
|
color: color.into(),
|
||||||
base_resolution: DEFAULT_RESOLUTION,
|
base_resolution: DEFAULT_RESOLUTION,
|
||||||
height_resolution: DEFAULT_RESOLUTION,
|
height_resolution: DEFAULT_RESOLUTION,
|
||||||
@ -757,7 +765,7 @@ where
|
|||||||
fn primitive_3d(
|
fn primitive_3d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &ConicalFrustum,
|
primitive: &ConicalFrustum,
|
||||||
isometry: Isometry3d,
|
isometry: impl Into<Isometry3d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
ConicalFrustum3dBuilder {
|
ConicalFrustum3dBuilder {
|
||||||
@ -765,7 +773,7 @@ where
|
|||||||
radius_top: primitive.radius_top,
|
radius_top: primitive.radius_top,
|
||||||
radius_bottom: primitive.radius_bottom,
|
radius_bottom: primitive.radius_bottom,
|
||||||
height: primitive.height,
|
height: primitive.height,
|
||||||
isometry,
|
isometry: isometry.into(),
|
||||||
color: color.into(),
|
color: color.into(),
|
||||||
resolution: DEFAULT_RESOLUTION,
|
resolution: DEFAULT_RESOLUTION,
|
||||||
}
|
}
|
||||||
@ -861,14 +869,14 @@ where
|
|||||||
fn primitive_3d(
|
fn primitive_3d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &Torus,
|
primitive: &Torus,
|
||||||
isometry: Isometry3d,
|
isometry: impl Into<Isometry3d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
Torus3dBuilder {
|
Torus3dBuilder {
|
||||||
gizmos: self,
|
gizmos: self,
|
||||||
minor_radius: primitive.minor_radius,
|
minor_radius: primitive.minor_radius,
|
||||||
major_radius: primitive.major_radius,
|
major_radius: primitive.major_radius,
|
||||||
isometry,
|
isometry: isometry.into(),
|
||||||
color: color.into(),
|
color: color.into(),
|
||||||
minor_resolution: DEFAULT_RESOLUTION,
|
minor_resolution: DEFAULT_RESOLUTION,
|
||||||
major_resolution: DEFAULT_RESOLUTION,
|
major_resolution: DEFAULT_RESOLUTION,
|
||||||
@ -937,13 +945,15 @@ impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive3d<Tetrahedron> for Gizmos<'w, '
|
|||||||
fn primitive_3d(
|
fn primitive_3d(
|
||||||
&mut self,
|
&mut self,
|
||||||
primitive: &Tetrahedron,
|
primitive: &Tetrahedron,
|
||||||
isometry: Isometry3d,
|
isometry: impl Into<Isometry3d>,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> Self::Output<'_> {
|
) -> Self::Output<'_> {
|
||||||
if !self.enabled {
|
if !self.enabled {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
let [a, b, c, d] = primitive.vertices.map(|vec3| isometry * vec3);
|
let [a, b, c, d] = primitive.vertices.map(|vec3| isometry * vec3);
|
||||||
|
|
||||||
let lines = [(a, b), (a, c), (a, d), (b, c), (b, d), (c, d)];
|
let lines = [(a, b), (a, c), (a, d), (b, c), (b, d), (c, d)];
|
||||||
|
|||||||
@ -240,7 +240,7 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> {
|
|||||||
/// ```
|
/// ```
|
||||||
pub fn rounded_rect(
|
pub fn rounded_rect(
|
||||||
&mut self,
|
&mut self,
|
||||||
isometry: Isometry3d,
|
isometry: impl Into<Isometry3d>,
|
||||||
size: Vec2,
|
size: Vec2,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> RoundedRectBuilder<'_, 'w, 's, T> {
|
) -> RoundedRectBuilder<'_, 'w, 's, T> {
|
||||||
@ -248,7 +248,7 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> {
|
|||||||
RoundedRectBuilder {
|
RoundedRectBuilder {
|
||||||
gizmos: self,
|
gizmos: self,
|
||||||
config: RoundedBoxConfig {
|
config: RoundedBoxConfig {
|
||||||
isometry,
|
isometry: isometry.into(),
|
||||||
color: color.into(),
|
color: color.into(),
|
||||||
corner_radius,
|
corner_radius,
|
||||||
arc_resolution: DEFAULT_ARC_RESOLUTION,
|
arc_resolution: DEFAULT_ARC_RESOLUTION,
|
||||||
@ -294,10 +294,11 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> {
|
|||||||
/// ```
|
/// ```
|
||||||
pub fn rounded_rect_2d(
|
pub fn rounded_rect_2d(
|
||||||
&mut self,
|
&mut self,
|
||||||
isometry: Isometry2d,
|
isometry: impl Into<Isometry2d>,
|
||||||
size: Vec2,
|
size: Vec2,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> RoundedRectBuilder<'_, 'w, 's, T> {
|
) -> RoundedRectBuilder<'_, 'w, 's, T> {
|
||||||
|
let isometry = isometry.into();
|
||||||
let corner_radius = size.min_element() * DEFAULT_CORNER_RADIUS;
|
let corner_radius = size.min_element() * DEFAULT_CORNER_RADIUS;
|
||||||
RoundedRectBuilder {
|
RoundedRectBuilder {
|
||||||
gizmos: self,
|
gizmos: self,
|
||||||
@ -351,7 +352,7 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> {
|
|||||||
/// ```
|
/// ```
|
||||||
pub fn rounded_cuboid(
|
pub fn rounded_cuboid(
|
||||||
&mut self,
|
&mut self,
|
||||||
isometry: Isometry3d,
|
isometry: impl Into<Isometry3d>,
|
||||||
size: Vec3,
|
size: Vec3,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) -> RoundedCuboidBuilder<'_, 'w, 's, T> {
|
) -> RoundedCuboidBuilder<'_, 'w, 's, T> {
|
||||||
@ -359,7 +360,7 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> {
|
|||||||
RoundedCuboidBuilder {
|
RoundedCuboidBuilder {
|
||||||
gizmos: self,
|
gizmos: self,
|
||||||
config: RoundedBoxConfig {
|
config: RoundedBoxConfig {
|
||||||
isometry,
|
isometry: isometry.into(),
|
||||||
color: color.into(),
|
color: color.into(),
|
||||||
corner_radius,
|
corner_radius,
|
||||||
arc_resolution: DEFAULT_ARC_RESOLUTION,
|
arc_resolution: DEFAULT_ARC_RESOLUTION,
|
||||||
|
|||||||
@ -24,9 +24,9 @@ fn point_cloud_2d_center(points: &[Vec2]) -> Vec2 {
|
|||||||
/// A trait with methods that return 2D bounding volumes for a shape.
|
/// A trait with methods that return 2D bounding volumes for a shape.
|
||||||
pub trait Bounded2d {
|
pub trait Bounded2d {
|
||||||
/// Get an axis-aligned bounding box for the shape translated and rotated by the given isometry.
|
/// Get an axis-aligned bounding box for the shape translated and rotated by the given isometry.
|
||||||
fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d;
|
fn aabb_2d(&self, isometry: impl Into<Isometry2d>) -> Aabb2d;
|
||||||
/// Get a bounding circle for the shape translated and rotated by the given isometry.
|
/// Get a bounding circle for the shape translated and rotated by the given isometry.
|
||||||
fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle;
|
fn bounding_circle(&self, isometry: impl Into<Isometry2d>) -> BoundingCircle;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A 2D axis-aligned bounding box, or bounding rectangle
|
/// A 2D axis-aligned bounding box, or bounding rectangle
|
||||||
@ -58,7 +58,9 @@ impl Aabb2d {
|
|||||||
///
|
///
|
||||||
/// Panics if the given set of points is empty.
|
/// Panics if the given set of points is empty.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn from_point_cloud(isometry: Isometry2d, points: &[Vec2]) -> Aabb2d {
|
pub fn from_point_cloud(isometry: impl Into<Isometry2d>, points: &[Vec2]) -> Aabb2d {
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
// Transform all points by rotation
|
// Transform all points by rotation
|
||||||
let mut iter = points.iter().map(|point| isometry.rotation * *point);
|
let mut iter = points.iter().map(|point| isometry.rotation * *point);
|
||||||
|
|
||||||
@ -472,7 +474,9 @@ impl BoundingCircle {
|
|||||||
///
|
///
|
||||||
/// The bounding circle is not guaranteed to be the smallest possible.
|
/// The bounding circle is not guaranteed to be the smallest possible.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn from_point_cloud(isometry: Isometry2d, points: &[Vec2]) -> BoundingCircle {
|
pub fn from_point_cloud(isometry: impl Into<Isometry2d>, points: &[Vec2]) -> BoundingCircle {
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
let center = point_cloud_2d_center(points);
|
let center = point_cloud_2d_center(points);
|
||||||
let mut radius_squared = 0.0;
|
let mut radius_squared = 0.0;
|
||||||
|
|
||||||
|
|||||||
@ -16,11 +16,13 @@ use smallvec::SmallVec;
|
|||||||
use super::{Aabb2d, Bounded2d, BoundingCircle};
|
use super::{Aabb2d, Bounded2d, BoundingCircle};
|
||||||
|
|
||||||
impl Bounded2d for Circle {
|
impl Bounded2d for Circle {
|
||||||
fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d {
|
fn aabb_2d(&self, isometry: impl Into<Isometry2d>) -> Aabb2d {
|
||||||
|
let isometry = isometry.into();
|
||||||
Aabb2d::new(isometry.translation, Vec2::splat(self.radius))
|
Aabb2d::new(isometry.translation, Vec2::splat(self.radius))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle {
|
fn bounding_circle(&self, isometry: impl Into<Isometry2d>) -> BoundingCircle {
|
||||||
|
let isometry = isometry.into();
|
||||||
BoundingCircle::new(isometry.translation, self.radius)
|
BoundingCircle::new(isometry.translation, self.radius)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -58,19 +60,23 @@ fn arc_bounding_points(arc: Arc2d, rotation: impl Into<Rot2>) -> SmallVec<[Vec2;
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded2d for Arc2d {
|
impl Bounded2d for Arc2d {
|
||||||
fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d {
|
fn aabb_2d(&self, isometry: impl Into<Isometry2d>) -> Aabb2d {
|
||||||
// If our arc covers more than a circle, just return the bounding box of the circle.
|
// If our arc covers more than a circle, just return the bounding box of the circle.
|
||||||
if self.half_angle >= PI {
|
if self.half_angle >= PI {
|
||||||
return Circle::new(self.radius).aabb_2d(isometry);
|
return Circle::new(self.radius).aabb_2d(isometry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
Aabb2d::from_point_cloud(
|
Aabb2d::from_point_cloud(
|
||||||
Isometry2d::from_translation(isometry.translation),
|
Isometry2d::from_translation(isometry.translation),
|
||||||
&arc_bounding_points(*self, isometry.rotation),
|
&arc_bounding_points(*self, isometry.rotation),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle {
|
fn bounding_circle(&self, isometry: impl Into<Isometry2d>) -> BoundingCircle {
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
// There are two possibilities for the bounding circle.
|
// There are two possibilities for the bounding circle.
|
||||||
if self.is_major() {
|
if self.is_major() {
|
||||||
// If the arc is major, then the widest distance between two points is a diameter of the arc's circle;
|
// If the arc is major, then the widest distance between two points is a diameter of the arc's circle;
|
||||||
@ -86,7 +92,9 @@ impl Bounded2d for Arc2d {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded2d for CircularSector {
|
impl Bounded2d for CircularSector {
|
||||||
fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d {
|
fn aabb_2d(&self, isometry: impl Into<Isometry2d>) -> Aabb2d {
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
// If our sector covers more than a circle, just return the bounding box of the circle.
|
// If our sector covers more than a circle, just return the bounding box of the circle.
|
||||||
if self.half_angle() >= PI {
|
if self.half_angle() >= PI {
|
||||||
return Circle::new(self.radius()).aabb_2d(isometry);
|
return Circle::new(self.radius()).aabb_2d(isometry);
|
||||||
@ -99,8 +107,10 @@ impl Bounded2d for CircularSector {
|
|||||||
Aabb2d::from_point_cloud(Isometry2d::from_translation(isometry.translation), &bounds)
|
Aabb2d::from_point_cloud(Isometry2d::from_translation(isometry.translation), &bounds)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle {
|
fn bounding_circle(&self, isometry: impl Into<Isometry2d>) -> BoundingCircle {
|
||||||
if self.arc.is_major() {
|
if self.arc.is_major() {
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
// If the arc is major, that is, greater than a semicircle,
|
// If the arc is major, that is, greater than a semicircle,
|
||||||
// then bounding circle is just the circle defining the sector.
|
// then bounding circle is just the circle defining the sector.
|
||||||
BoundingCircle::new(isometry.translation, self.arc.radius)
|
BoundingCircle::new(isometry.translation, self.arc.radius)
|
||||||
@ -121,17 +131,19 @@ impl Bounded2d for CircularSector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded2d for CircularSegment {
|
impl Bounded2d for CircularSegment {
|
||||||
fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d {
|
fn aabb_2d(&self, isometry: impl Into<Isometry2d>) -> Aabb2d {
|
||||||
self.arc.aabb_2d(isometry)
|
self.arc.aabb_2d(isometry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle {
|
fn bounding_circle(&self, isometry: impl Into<Isometry2d>) -> BoundingCircle {
|
||||||
self.arc.bounding_circle(isometry)
|
self.arc.bounding_circle(isometry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded2d for Ellipse {
|
impl Bounded2d for Ellipse {
|
||||||
fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d {
|
fn aabb_2d(&self, isometry: impl Into<Isometry2d>) -> Aabb2d {
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
// V = (hh * cos(beta), hh * sin(beta))
|
// V = (hh * cos(beta), hh * sin(beta))
|
||||||
// #####*#####
|
// #####*#####
|
||||||
// ### | ###
|
// ### | ###
|
||||||
@ -160,23 +172,28 @@ impl Bounded2d for Ellipse {
|
|||||||
Aabb2d::new(isometry.translation, half_size)
|
Aabb2d::new(isometry.translation, half_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle {
|
fn bounding_circle(&self, isometry: impl Into<Isometry2d>) -> BoundingCircle {
|
||||||
|
let isometry = isometry.into();
|
||||||
BoundingCircle::new(isometry.translation, self.semi_major())
|
BoundingCircle::new(isometry.translation, self.semi_major())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded2d for Annulus {
|
impl Bounded2d for Annulus {
|
||||||
fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d {
|
fn aabb_2d(&self, isometry: impl Into<Isometry2d>) -> Aabb2d {
|
||||||
|
let isometry = isometry.into();
|
||||||
Aabb2d::new(isometry.translation, Vec2::splat(self.outer_circle.radius))
|
Aabb2d::new(isometry.translation, Vec2::splat(self.outer_circle.radius))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle {
|
fn bounding_circle(&self, isometry: impl Into<Isometry2d>) -> BoundingCircle {
|
||||||
|
let isometry = isometry.into();
|
||||||
BoundingCircle::new(isometry.translation, self.outer_circle.radius)
|
BoundingCircle::new(isometry.translation, self.outer_circle.radius)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded2d for Rhombus {
|
impl Bounded2d for Rhombus {
|
||||||
fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d {
|
fn aabb_2d(&self, isometry: impl Into<Isometry2d>) -> Aabb2d {
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
let [rotated_x_half_diagonal, rotated_y_half_diagonal] = [
|
let [rotated_x_half_diagonal, rotated_y_half_diagonal] = [
|
||||||
isometry.rotation * Vec2::new(self.half_diagonals.x, 0.0),
|
isometry.rotation * Vec2::new(self.half_diagonals.x, 0.0),
|
||||||
isometry.rotation * Vec2::new(0.0, self.half_diagonals.y),
|
isometry.rotation * Vec2::new(0.0, self.half_diagonals.y),
|
||||||
@ -191,13 +208,16 @@ impl Bounded2d for Rhombus {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle {
|
fn bounding_circle(&self, isometry: impl Into<Isometry2d>) -> BoundingCircle {
|
||||||
|
let isometry = isometry.into();
|
||||||
BoundingCircle::new(isometry.translation, self.circumradius())
|
BoundingCircle::new(isometry.translation, self.circumradius())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded2d for Plane2d {
|
impl Bounded2d for Plane2d {
|
||||||
fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d {
|
fn aabb_2d(&self, isometry: impl Into<Isometry2d>) -> Aabb2d {
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
let normal = isometry.rotation * *self.normal;
|
let normal = isometry.rotation * *self.normal;
|
||||||
let facing_x = normal == Vec2::X || normal == Vec2::NEG_X;
|
let facing_x = normal == Vec2::X || normal == Vec2::NEG_X;
|
||||||
let facing_y = normal == Vec2::Y || normal == Vec2::NEG_Y;
|
let facing_y = normal == Vec2::Y || normal == Vec2::NEG_Y;
|
||||||
@ -211,13 +231,16 @@ impl Bounded2d for Plane2d {
|
|||||||
Aabb2d::new(isometry.translation, half_size)
|
Aabb2d::new(isometry.translation, half_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle {
|
fn bounding_circle(&self, isometry: impl Into<Isometry2d>) -> BoundingCircle {
|
||||||
|
let isometry = isometry.into();
|
||||||
BoundingCircle::new(isometry.translation, f32::MAX / 2.0)
|
BoundingCircle::new(isometry.translation, f32::MAX / 2.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded2d for Line2d {
|
impl Bounded2d for Line2d {
|
||||||
fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d {
|
fn aabb_2d(&self, isometry: impl Into<Isometry2d>) -> Aabb2d {
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
let direction = isometry.rotation * *self.direction;
|
let direction = isometry.rotation * *self.direction;
|
||||||
|
|
||||||
// Dividing `f32::MAX` by 2.0 is helpful so that we can do operations
|
// Dividing `f32::MAX` by 2.0 is helpful so that we can do operations
|
||||||
@ -230,13 +253,16 @@ impl Bounded2d for Line2d {
|
|||||||
Aabb2d::new(isometry.translation, half_size)
|
Aabb2d::new(isometry.translation, half_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle {
|
fn bounding_circle(&self, isometry: impl Into<Isometry2d>) -> BoundingCircle {
|
||||||
|
let isometry = isometry.into();
|
||||||
BoundingCircle::new(isometry.translation, f32::MAX / 2.0)
|
BoundingCircle::new(isometry.translation, f32::MAX / 2.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded2d for Segment2d {
|
impl Bounded2d for Segment2d {
|
||||||
fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d {
|
fn aabb_2d(&self, isometry: impl Into<Isometry2d>) -> Aabb2d {
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
// Rotate the segment by `rotation`
|
// Rotate the segment by `rotation`
|
||||||
let direction = isometry.rotation * *self.direction;
|
let direction = isometry.rotation * *self.direction;
|
||||||
let half_size = (self.half_length * direction).abs();
|
let half_size = (self.half_length * direction).abs();
|
||||||
@ -244,33 +270,35 @@ impl Bounded2d for Segment2d {
|
|||||||
Aabb2d::new(isometry.translation, half_size)
|
Aabb2d::new(isometry.translation, half_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle {
|
fn bounding_circle(&self, isometry: impl Into<Isometry2d>) -> BoundingCircle {
|
||||||
|
let isometry = isometry.into();
|
||||||
BoundingCircle::new(isometry.translation, self.half_length)
|
BoundingCircle::new(isometry.translation, self.half_length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<const N: usize> Bounded2d for Polyline2d<N> {
|
impl<const N: usize> Bounded2d for Polyline2d<N> {
|
||||||
fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d {
|
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: Isometry2d) -> BoundingCircle {
|
fn bounding_circle(&self, isometry: impl Into<Isometry2d>) -> BoundingCircle {
|
||||||
BoundingCircle::from_point_cloud(isometry, &self.vertices)
|
BoundingCircle::from_point_cloud(isometry, &self.vertices)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded2d for BoxedPolyline2d {
|
impl Bounded2d for BoxedPolyline2d {
|
||||||
fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d {
|
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: Isometry2d) -> BoundingCircle {
|
fn bounding_circle(&self, isometry: impl Into<Isometry2d>) -> BoundingCircle {
|
||||||
BoundingCircle::from_point_cloud(isometry, &self.vertices)
|
BoundingCircle::from_point_cloud(isometry, &self.vertices)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded2d for Triangle2d {
|
impl Bounded2d for Triangle2d {
|
||||||
fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d {
|
fn aabb_2d(&self, isometry: impl Into<Isometry2d>) -> Aabb2d {
|
||||||
|
let isometry = isometry.into();
|
||||||
let [a, b, c] = self.vertices.map(|vtx| isometry.rotation * vtx);
|
let [a, b, c] = self.vertices.map(|vtx| isometry.rotation * vtx);
|
||||||
|
|
||||||
let min = Vec2::new(a.x.min(b.x).min(c.x), a.y.min(b.y).min(c.y));
|
let min = Vec2::new(a.x.min(b.x).min(c.x), a.y.min(b.y).min(c.y));
|
||||||
@ -282,7 +310,8 @@ impl Bounded2d for Triangle2d {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle {
|
fn bounding_circle(&self, isometry: impl Into<Isometry2d>) -> BoundingCircle {
|
||||||
|
let isometry = isometry.into();
|
||||||
let [a, b, c] = self.vertices;
|
let [a, b, c] = self.vertices;
|
||||||
|
|
||||||
// The points of the segment opposite to the obtuse or right angle if one exists
|
// The points of the segment opposite to the obtuse or right angle if one exists
|
||||||
@ -313,7 +342,9 @@ impl Bounded2d for Triangle2d {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded2d for Rectangle {
|
impl Bounded2d for Rectangle {
|
||||||
fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d {
|
fn aabb_2d(&self, isometry: impl Into<Isometry2d>) -> Aabb2d {
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
// Compute the AABB of the rotated rectangle by transforming the half-extents
|
// Compute the AABB of the rotated rectangle by transforming the half-extents
|
||||||
// by an absolute rotation matrix.
|
// by an absolute rotation matrix.
|
||||||
let (sin, cos) = isometry.rotation.sin_cos();
|
let (sin, cos) = isometry.rotation.sin_cos();
|
||||||
@ -323,34 +354,37 @@ impl Bounded2d for Rectangle {
|
|||||||
Aabb2d::new(isometry.translation, half_size)
|
Aabb2d::new(isometry.translation, half_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle {
|
fn bounding_circle(&self, isometry: impl Into<Isometry2d>) -> BoundingCircle {
|
||||||
|
let isometry = isometry.into();
|
||||||
let radius = self.half_size.length();
|
let radius = self.half_size.length();
|
||||||
BoundingCircle::new(isometry.translation, radius)
|
BoundingCircle::new(isometry.translation, radius)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<const N: usize> Bounded2d for Polygon<N> {
|
impl<const N: usize> Bounded2d for Polygon<N> {
|
||||||
fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d {
|
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: Isometry2d) -> BoundingCircle {
|
fn bounding_circle(&self, isometry: impl Into<Isometry2d>) -> BoundingCircle {
|
||||||
BoundingCircle::from_point_cloud(isometry, &self.vertices)
|
BoundingCircle::from_point_cloud(isometry, &self.vertices)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded2d for BoxedPolygon {
|
impl Bounded2d for BoxedPolygon {
|
||||||
fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d {
|
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: Isometry2d) -> BoundingCircle {
|
fn bounding_circle(&self, isometry: impl Into<Isometry2d>) -> BoundingCircle {
|
||||||
BoundingCircle::from_point_cloud(isometry, &self.vertices)
|
BoundingCircle::from_point_cloud(isometry, &self.vertices)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded2d for RegularPolygon {
|
impl Bounded2d for RegularPolygon {
|
||||||
fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d {
|
fn aabb_2d(&self, isometry: impl Into<Isometry2d>) -> Aabb2d {
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
let mut min = Vec2::ZERO;
|
let mut min = Vec2::ZERO;
|
||||||
let mut max = Vec2::ZERO;
|
let mut max = Vec2::ZERO;
|
||||||
|
|
||||||
@ -365,13 +399,16 @@ impl Bounded2d for RegularPolygon {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle {
|
fn bounding_circle(&self, isometry: impl Into<Isometry2d>) -> BoundingCircle {
|
||||||
|
let isometry = isometry.into();
|
||||||
BoundingCircle::new(isometry.translation, self.circumcircle.radius)
|
BoundingCircle::new(isometry.translation, self.circumcircle.radius)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded2d for Capsule2d {
|
impl Bounded2d for Capsule2d {
|
||||||
fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d {
|
fn aabb_2d(&self, isometry: impl Into<Isometry2d>) -> Aabb2d {
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
// Get the line segment between the hemicircles of the rotated capsule
|
// Get the line segment between the hemicircles of the rotated capsule
|
||||||
let segment = Segment2d {
|
let segment = Segment2d {
|
||||||
// Multiplying a normalized vector (Vec2::Y) with a rotation returns a normalized vector.
|
// Multiplying a normalized vector (Vec2::Y) with a rotation returns a normalized vector.
|
||||||
@ -390,7 +427,8 @@ impl Bounded2d for Capsule2d {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle {
|
fn bounding_circle(&self, isometry: impl Into<Isometry2d>) -> BoundingCircle {
|
||||||
|
let isometry = isometry.into();
|
||||||
BoundingCircle::new(isometry.translation, self.radius + self.half_length)
|
BoundingCircle::new(isometry.translation, self.radius + self.half_length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,9 +17,11 @@ use crate::{bounding::Bounded2d, primitives::Circle};
|
|||||||
use super::{Aabb3d, Bounded3d, BoundingSphere};
|
use super::{Aabb3d, Bounded3d, BoundingSphere};
|
||||||
|
|
||||||
impl BoundedExtrusion for Circle {
|
impl BoundedExtrusion for Circle {
|
||||||
fn extrusion_aabb_3d(&self, half_depth: f32, isometry: Isometry3d) -> Aabb3d {
|
fn extrusion_aabb_3d(&self, half_depth: f32, isometry: impl Into<Isometry3d>) -> Aabb3d {
|
||||||
// Reference: http://iquilezles.org/articles/diskbbox/
|
// Reference: http://iquilezles.org/articles/diskbbox/
|
||||||
|
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
let segment_dir = isometry.rotation * Vec3A::Z;
|
let segment_dir = isometry.rotation * Vec3A::Z;
|
||||||
let top = (segment_dir * half_depth).abs();
|
let top = (segment_dir * half_depth).abs();
|
||||||
|
|
||||||
@ -34,7 +36,8 @@ impl BoundedExtrusion for Circle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BoundedExtrusion for Ellipse {
|
impl BoundedExtrusion for Ellipse {
|
||||||
fn extrusion_aabb_3d(&self, half_depth: f32, isometry: Isometry3d) -> Aabb3d {
|
fn extrusion_aabb_3d(&self, half_depth: f32, isometry: impl Into<Isometry3d>) -> Aabb3d {
|
||||||
|
let isometry = isometry.into();
|
||||||
let Vec2 { x: a, y: b } = self.half_size;
|
let Vec2 { x: a, y: b } = self.half_size;
|
||||||
let normal = isometry.rotation * Vec3A::Z;
|
let normal = isometry.rotation * Vec3A::Z;
|
||||||
let conjugate_rot = isometry.rotation.conjugate();
|
let conjugate_rot = isometry.rotation.conjugate();
|
||||||
@ -64,7 +67,8 @@ impl BoundedExtrusion for Ellipse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BoundedExtrusion for Line2d {
|
impl BoundedExtrusion for Line2d {
|
||||||
fn extrusion_aabb_3d(&self, half_depth: f32, isometry: Isometry3d) -> Aabb3d {
|
fn extrusion_aabb_3d(&self, half_depth: f32, isometry: impl Into<Isometry3d>) -> Aabb3d {
|
||||||
|
let isometry = isometry.into();
|
||||||
let dir = isometry.rotation * Vec3A::from(self.direction.extend(0.));
|
let dir = isometry.rotation * Vec3A::from(self.direction.extend(0.));
|
||||||
let half_depth = (isometry.rotation * Vec3A::new(0., 0., half_depth)).abs();
|
let half_depth = (isometry.rotation * Vec3A::new(0., 0., half_depth)).abs();
|
||||||
|
|
||||||
@ -80,7 +84,8 @@ impl BoundedExtrusion for Line2d {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BoundedExtrusion for Segment2d {
|
impl BoundedExtrusion for Segment2d {
|
||||||
fn extrusion_aabb_3d(&self, half_depth: f32, isometry: Isometry3d) -> Aabb3d {
|
fn extrusion_aabb_3d(&self, half_depth: f32, isometry: impl Into<Isometry3d>) -> Aabb3d {
|
||||||
|
let isometry = isometry.into();
|
||||||
let half_size = isometry.rotation * Vec3A::from(self.point1().extend(0.));
|
let half_size = isometry.rotation * Vec3A::from(self.point1().extend(0.));
|
||||||
let depth = isometry.rotation * Vec3A::new(0., 0., half_depth);
|
let depth = isometry.rotation * Vec3A::new(0., 0., half_depth);
|
||||||
|
|
||||||
@ -89,7 +94,8 @@ impl BoundedExtrusion for Segment2d {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<const N: usize> BoundedExtrusion for Polyline2d<N> {
|
impl<const N: usize> BoundedExtrusion for Polyline2d<N> {
|
||||||
fn extrusion_aabb_3d(&self, half_depth: f32, isometry: Isometry3d) -> Aabb3d {
|
fn extrusion_aabb_3d(&self, half_depth: f32, isometry: impl Into<Isometry3d>) -> Aabb3d {
|
||||||
|
let isometry = isometry.into();
|
||||||
let aabb =
|
let aabb =
|
||||||
Aabb3d::from_point_cloud(isometry, self.vertices.map(|v| v.extend(0.)).into_iter());
|
Aabb3d::from_point_cloud(isometry, self.vertices.map(|v| v.extend(0.)).into_iter());
|
||||||
let depth = isometry.rotation * Vec3A::new(0., 0., half_depth);
|
let depth = isometry.rotation * Vec3A::new(0., 0., half_depth);
|
||||||
@ -99,7 +105,8 @@ impl<const N: usize> BoundedExtrusion for Polyline2d<N> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BoundedExtrusion for BoxedPolyline2d {
|
impl BoundedExtrusion for BoxedPolyline2d {
|
||||||
fn extrusion_aabb_3d(&self, half_depth: f32, isometry: Isometry3d) -> Aabb3d {
|
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.)));
|
let aabb = Aabb3d::from_point_cloud(isometry, self.vertices.iter().map(|v| v.extend(0.)));
|
||||||
let depth = isometry.rotation * Vec3A::new(0., 0., half_depth);
|
let depth = isometry.rotation * Vec3A::new(0., 0., half_depth);
|
||||||
|
|
||||||
@ -108,7 +115,8 @@ impl BoundedExtrusion for BoxedPolyline2d {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BoundedExtrusion for Triangle2d {
|
impl BoundedExtrusion for Triangle2d {
|
||||||
fn extrusion_aabb_3d(&self, half_depth: f32, isometry: Isometry3d) -> Aabb3d {
|
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.)));
|
let aabb = Aabb3d::from_point_cloud(isometry, self.vertices.iter().map(|v| v.extend(0.)));
|
||||||
let depth = isometry.rotation * Vec3A::new(0., 0., half_depth);
|
let depth = isometry.rotation * Vec3A::new(0., 0., half_depth);
|
||||||
|
|
||||||
@ -117,7 +125,7 @@ impl BoundedExtrusion for Triangle2d {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BoundedExtrusion for Rectangle {
|
impl BoundedExtrusion for Rectangle {
|
||||||
fn extrusion_aabb_3d(&self, half_depth: f32, isometry: Isometry3d) -> Aabb3d {
|
fn extrusion_aabb_3d(&self, half_depth: f32, isometry: impl Into<Isometry3d>) -> Aabb3d {
|
||||||
Cuboid {
|
Cuboid {
|
||||||
half_size: self.half_size.extend(half_depth),
|
half_size: self.half_size.extend(half_depth),
|
||||||
}
|
}
|
||||||
@ -126,7 +134,8 @@ impl BoundedExtrusion for Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<const N: usize> BoundedExtrusion for Polygon<N> {
|
impl<const N: usize> BoundedExtrusion for Polygon<N> {
|
||||||
fn extrusion_aabb_3d(&self, half_depth: f32, isometry: Isometry3d) -> Aabb3d {
|
fn extrusion_aabb_3d(&self, half_depth: f32, isometry: impl Into<Isometry3d>) -> Aabb3d {
|
||||||
|
let isometry = isometry.into();
|
||||||
let aabb =
|
let aabb =
|
||||||
Aabb3d::from_point_cloud(isometry, self.vertices.map(|v| v.extend(0.)).into_iter());
|
Aabb3d::from_point_cloud(isometry, self.vertices.map(|v| v.extend(0.)).into_iter());
|
||||||
let depth = isometry.rotation * Vec3A::new(0., 0., half_depth);
|
let depth = isometry.rotation * Vec3A::new(0., 0., half_depth);
|
||||||
@ -136,7 +145,8 @@ impl<const N: usize> BoundedExtrusion for Polygon<N> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BoundedExtrusion for BoxedPolygon {
|
impl BoundedExtrusion for BoxedPolygon {
|
||||||
fn extrusion_aabb_3d(&self, half_depth: f32, isometry: Isometry3d) -> Aabb3d {
|
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.)));
|
let aabb = Aabb3d::from_point_cloud(isometry, self.vertices.iter().map(|v| v.extend(0.)));
|
||||||
let depth = isometry.rotation * Vec3A::new(0., 0., half_depth);
|
let depth = isometry.rotation * Vec3A::new(0., 0., half_depth);
|
||||||
|
|
||||||
@ -145,7 +155,8 @@ impl BoundedExtrusion for BoxedPolygon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BoundedExtrusion for RegularPolygon {
|
impl BoundedExtrusion for RegularPolygon {
|
||||||
fn extrusion_aabb_3d(&self, half_depth: f32, isometry: Isometry3d) -> Aabb3d {
|
fn extrusion_aabb_3d(&self, half_depth: f32, isometry: impl Into<Isometry3d>) -> Aabb3d {
|
||||||
|
let isometry = isometry.into();
|
||||||
let aabb = Aabb3d::from_point_cloud(
|
let aabb = Aabb3d::from_point_cloud(
|
||||||
isometry,
|
isometry,
|
||||||
self.vertices(0.).into_iter().map(|v| v.extend(0.)),
|
self.vertices(0.).into_iter().map(|v| v.extend(0.)),
|
||||||
@ -157,14 +168,13 @@ impl BoundedExtrusion for RegularPolygon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BoundedExtrusion for Capsule2d {
|
impl BoundedExtrusion for Capsule2d {
|
||||||
fn extrusion_aabb_3d(&self, half_depth: f32, isometry: Isometry3d) -> Aabb3d {
|
fn extrusion_aabb_3d(&self, half_depth: f32, isometry: impl Into<Isometry3d>) -> Aabb3d {
|
||||||
|
let isometry = isometry.into();
|
||||||
let aabb = Cylinder {
|
let aabb = Cylinder {
|
||||||
half_height: half_depth,
|
half_height: half_depth,
|
||||||
radius: self.radius,
|
radius: self.radius,
|
||||||
}
|
}
|
||||||
.aabb_3d(Isometry3d::from_rotation(
|
.aabb_3d(isometry.rotation * Quat::from_rotation_x(FRAC_PI_2));
|
||||||
isometry.rotation * Quat::from_rotation_x(FRAC_PI_2),
|
|
||||||
));
|
|
||||||
|
|
||||||
let up = isometry.rotation * Vec3A::new(0., self.half_length, 0.);
|
let up = isometry.rotation * Vec3A::new(0., self.half_length, 0.);
|
||||||
let half_size = aabb.max + up.abs();
|
let half_size = aabb.max + up.abs();
|
||||||
@ -173,11 +183,11 @@ impl BoundedExtrusion for Capsule2d {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T: BoundedExtrusion> Bounded3d for Extrusion<T> {
|
impl<T: BoundedExtrusion> Bounded3d for Extrusion<T> {
|
||||||
fn aabb_3d(&self, isometry: Isometry3d) -> Aabb3d {
|
fn aabb_3d(&self, isometry: impl Into<Isometry3d>) -> Aabb3d {
|
||||||
self.base_shape.extrusion_aabb_3d(self.half_depth, isometry)
|
self.base_shape.extrusion_aabb_3d(self.half_depth, isometry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_sphere(&self, isometry: Isometry3d) -> BoundingSphere {
|
fn bounding_sphere(&self, isometry: impl Into<Isometry3d>) -> BoundingSphere {
|
||||||
self.base_shape
|
self.base_shape
|
||||||
.extrusion_bounding_sphere(self.half_depth, isometry)
|
.extrusion_bounding_sphere(self.half_depth, isometry)
|
||||||
}
|
}
|
||||||
@ -191,7 +201,8 @@ impl<T: BoundedExtrusion> Bounded3d for Extrusion<T> {
|
|||||||
/// `impl BoundedExtrusion for MyShape {}`
|
/// `impl BoundedExtrusion for MyShape {}`
|
||||||
pub trait BoundedExtrusion: Primitive2d + Bounded2d {
|
pub trait BoundedExtrusion: Primitive2d + Bounded2d {
|
||||||
/// Get an axis-aligned bounding box for an extrusion with this shape as a base and the given `half_depth`, transformed by the given `translation` and `rotation`.
|
/// Get an axis-aligned bounding box for an extrusion with this shape as a base and the given `half_depth`, transformed by the given `translation` and `rotation`.
|
||||||
fn extrusion_aabb_3d(&self, half_depth: f32, isometry: Isometry3d) -> Aabb3d {
|
fn extrusion_aabb_3d(&self, half_depth: f32, isometry: impl Into<Isometry3d>) -> Aabb3d {
|
||||||
|
let isometry = isometry.into();
|
||||||
let cap_normal = isometry.rotation * Vec3A::Z;
|
let cap_normal = isometry.rotation * Vec3A::Z;
|
||||||
let conjugate_rot = isometry.rotation.conjugate();
|
let conjugate_rot = isometry.rotation.conjugate();
|
||||||
|
|
||||||
@ -213,7 +224,7 @@ pub trait BoundedExtrusion: Primitive2d + Bounded2d {
|
|||||||
|
|
||||||
// Calculate the `Aabb2d` of the base shape. The shape is rotated so that the line of intersection is parallel to the Y axis in the `Aabb2d` calculations.
|
// Calculate the `Aabb2d` of the base shape. The shape is rotated so that the line of intersection is parallel to the Y axis in the `Aabb2d` calculations.
|
||||||
// This guarantees that the X value of the `Aabb2d` is closest to the `ax` plane
|
// This guarantees that the X value of the `Aabb2d` is closest to the `ax` plane
|
||||||
let aabb2d = self.aabb_2d(Isometry2d::from_rotation(Rot2::radians(angle)));
|
let aabb2d = self.aabb_2d(Rot2::radians(angle));
|
||||||
(aabb2d.half_size().x * scale, aabb2d.center().x * scale)
|
(aabb2d.half_size().x * scale, aabb2d.center().x * scale)
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -225,7 +236,13 @@ pub trait BoundedExtrusion: Primitive2d + Bounded2d {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get a bounding sphere for an extrusion of the `base_shape` with the given `half_depth` with the given translation and rotation
|
/// Get a bounding sphere for an extrusion of the `base_shape` with the given `half_depth` with the given translation and rotation
|
||||||
fn extrusion_bounding_sphere(&self, half_depth: f32, isometry: Isometry3d) -> BoundingSphere {
|
fn extrusion_bounding_sphere(
|
||||||
|
&self,
|
||||||
|
half_depth: f32,
|
||||||
|
isometry: impl Into<Isometry3d>,
|
||||||
|
) -> BoundingSphere {
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
// We calculate the bounding circle of the base shape.
|
// We calculate the bounding circle of the base shape.
|
||||||
// Since each of the extrusions bases will have the same distance from its center,
|
// Since each of the extrusions bases will have the same distance from its center,
|
||||||
// and they are just shifted along the Z-axis, the minimum bounding sphere will be the bounding sphere
|
// and they are just shifted along the Z-axis, the minimum bounding sphere will be the bounding sphere
|
||||||
@ -261,13 +278,12 @@ mod tests {
|
|||||||
fn circle() {
|
fn circle() {
|
||||||
let cylinder = Extrusion::new(Circle::new(0.5), 2.0);
|
let cylinder = Extrusion::new(Circle::new(0.5), 2.0);
|
||||||
let translation = Vec3::new(2.0, 1.0, 0.0);
|
let translation = Vec3::new(2.0, 1.0, 0.0);
|
||||||
let isometry = Isometry3d::from_translation(translation);
|
|
||||||
|
|
||||||
let aabb = cylinder.aabb_3d(isometry);
|
let aabb = cylinder.aabb_3d(translation);
|
||||||
assert_eq!(aabb.center(), Vec3A::from(translation));
|
assert_eq!(aabb.center(), Vec3A::from(translation));
|
||||||
assert_eq!(aabb.half_size(), Vec3A::new(0.5, 0.5, 1.0));
|
assert_eq!(aabb.half_size(), Vec3A::new(0.5, 0.5, 1.0));
|
||||||
|
|
||||||
let bounding_sphere = cylinder.bounding_sphere(isometry);
|
let bounding_sphere = cylinder.bounding_sphere(translation);
|
||||||
assert_eq!(bounding_sphere.center, translation.into());
|
assert_eq!(bounding_sphere.center, translation.into());
|
||||||
assert_eq!(bounding_sphere.radius(), ops::hypot(1.0, 0.5));
|
assert_eq!(bounding_sphere.radius(), ops::hypot(1.0, 0.5));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,9 +27,9 @@ fn point_cloud_3d_center(points: impl Iterator<Item = impl Into<Vec3A>>) -> Vec3
|
|||||||
/// A trait with methods that return 3D bounding volumes for a shape.
|
/// A trait with methods that return 3D bounding volumes for a shape.
|
||||||
pub trait Bounded3d {
|
pub trait Bounded3d {
|
||||||
/// Get an axis-aligned bounding box for the shape translated and rotated by the given isometry.
|
/// Get an axis-aligned bounding box for the shape translated and rotated by the given isometry.
|
||||||
fn aabb_3d(&self, isometry: Isometry3d) -> Aabb3d;
|
fn aabb_3d(&self, isometry: impl Into<Isometry3d>) -> Aabb3d;
|
||||||
/// Get a bounding sphere for the shape translated and rotated by the given isometry.
|
/// Get a bounding sphere for the shape translated and rotated by the given isometry.
|
||||||
fn bounding_sphere(&self, isometry: Isometry3d) -> BoundingSphere;
|
fn bounding_sphere(&self, isometry: impl Into<Isometry3d>) -> BoundingSphere;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A 3D axis-aligned bounding box
|
/// A 3D axis-aligned bounding box
|
||||||
@ -62,9 +62,11 @@ impl Aabb3d {
|
|||||||
/// Panics if the given set of points is empty.
|
/// Panics if the given set of points is empty.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn from_point_cloud(
|
pub fn from_point_cloud(
|
||||||
isometry: Isometry3d,
|
isometry: impl Into<Isometry3d>,
|
||||||
points: impl Iterator<Item = impl Into<Vec3A>>,
|
points: impl Iterator<Item = impl Into<Vec3A>>,
|
||||||
) -> Aabb3d {
|
) -> Aabb3d {
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
// Transform all points by rotation
|
// Transform all points by rotation
|
||||||
let mut iter = points.map(|point| isometry.rotation * point.into());
|
let mut iter = points.map(|point| isometry.rotation * point.into());
|
||||||
|
|
||||||
@ -476,9 +478,11 @@ impl BoundingSphere {
|
|||||||
/// The bounding sphere is not guaranteed to be the smallest possible.
|
/// The bounding sphere is not guaranteed to be the smallest possible.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn from_point_cloud(
|
pub fn from_point_cloud(
|
||||||
isometry: Isometry3d,
|
isometry: impl Into<Isometry3d>,
|
||||||
points: &[impl Copy + Into<Vec3A>],
|
points: &[impl Copy + Into<Vec3A>],
|
||||||
) -> BoundingSphere {
|
) -> BoundingSphere {
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
let center = point_cloud_3d_center(points.iter().map(|v| Into::<Vec3A>::into(*v)));
|
let center = point_cloud_3d_center(points.iter().map(|v| Into::<Vec3A>::into(*v)));
|
||||||
let mut radius_squared: f32 = 0.0;
|
let mut radius_squared: f32 = 0.0;
|
||||||
|
|
||||||
|
|||||||
@ -15,17 +15,21 @@ use crate::{
|
|||||||
use super::{Aabb3d, Bounded3d, BoundingSphere};
|
use super::{Aabb3d, Bounded3d, BoundingSphere};
|
||||||
|
|
||||||
impl Bounded3d for Sphere {
|
impl Bounded3d for Sphere {
|
||||||
fn aabb_3d(&self, isometry: Isometry3d) -> Aabb3d {
|
fn aabb_3d(&self, isometry: impl Into<Isometry3d>) -> Aabb3d {
|
||||||
|
let isometry = isometry.into();
|
||||||
Aabb3d::new(isometry.translation, Vec3::splat(self.radius))
|
Aabb3d::new(isometry.translation, Vec3::splat(self.radius))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_sphere(&self, isometry: Isometry3d) -> BoundingSphere {
|
fn bounding_sphere(&self, isometry: impl Into<Isometry3d>) -> BoundingSphere {
|
||||||
|
let isometry = isometry.into();
|
||||||
BoundingSphere::new(isometry.translation, self.radius)
|
BoundingSphere::new(isometry.translation, self.radius)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded3d for InfinitePlane3d {
|
impl Bounded3d for InfinitePlane3d {
|
||||||
fn aabb_3d(&self, isometry: Isometry3d) -> Aabb3d {
|
fn aabb_3d(&self, isometry: impl Into<Isometry3d>) -> Aabb3d {
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
let normal = isometry.rotation * *self.normal;
|
let normal = isometry.rotation * *self.normal;
|
||||||
let facing_x = normal == Vec3::X || normal == Vec3::NEG_X;
|
let facing_x = normal == Vec3::X || normal == Vec3::NEG_X;
|
||||||
let facing_y = normal == Vec3::Y || normal == Vec3::NEG_Y;
|
let facing_y = normal == Vec3::Y || normal == Vec3::NEG_Y;
|
||||||
@ -41,13 +45,15 @@ impl Bounded3d for InfinitePlane3d {
|
|||||||
Aabb3d::new(isometry.translation, half_size)
|
Aabb3d::new(isometry.translation, half_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_sphere(&self, isometry: Isometry3d) -> BoundingSphere {
|
fn bounding_sphere(&self, isometry: impl Into<Isometry3d>) -> BoundingSphere {
|
||||||
|
let isometry = isometry.into();
|
||||||
BoundingSphere::new(isometry.translation, f32::MAX / 2.0)
|
BoundingSphere::new(isometry.translation, f32::MAX / 2.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded3d for Line3d {
|
impl Bounded3d for Line3d {
|
||||||
fn aabb_3d(&self, isometry: Isometry3d) -> Aabb3d {
|
fn aabb_3d(&self, isometry: impl Into<Isometry3d>) -> Aabb3d {
|
||||||
|
let isometry = isometry.into();
|
||||||
let direction = isometry.rotation * *self.direction;
|
let direction = isometry.rotation * *self.direction;
|
||||||
|
|
||||||
// Dividing `f32::MAX` by 2.0 is helpful so that we can do operations
|
// Dividing `f32::MAX` by 2.0 is helpful so that we can do operations
|
||||||
@ -61,13 +67,16 @@ impl Bounded3d for Line3d {
|
|||||||
Aabb3d::new(isometry.translation, half_size)
|
Aabb3d::new(isometry.translation, half_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_sphere(&self, isometry: Isometry3d) -> BoundingSphere {
|
fn bounding_sphere(&self, isometry: impl Into<Isometry3d>) -> BoundingSphere {
|
||||||
|
let isometry = isometry.into();
|
||||||
BoundingSphere::new(isometry.translation, f32::MAX / 2.0)
|
BoundingSphere::new(isometry.translation, f32::MAX / 2.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded3d for Segment3d {
|
impl Bounded3d for Segment3d {
|
||||||
fn aabb_3d(&self, isometry: Isometry3d) -> Aabb3d {
|
fn aabb_3d(&self, isometry: impl Into<Isometry3d>) -> Aabb3d {
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
// Rotate the segment by `rotation`
|
// Rotate the segment by `rotation`
|
||||||
let direction = isometry.rotation * *self.direction;
|
let direction = isometry.rotation * *self.direction;
|
||||||
let half_size = (self.half_length * direction).abs();
|
let half_size = (self.half_length * direction).abs();
|
||||||
@ -75,33 +84,36 @@ impl Bounded3d for Segment3d {
|
|||||||
Aabb3d::new(isometry.translation, half_size)
|
Aabb3d::new(isometry.translation, half_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_sphere(&self, isometry: Isometry3d) -> BoundingSphere {
|
fn bounding_sphere(&self, isometry: impl Into<Isometry3d>) -> BoundingSphere {
|
||||||
|
let isometry = isometry.into();
|
||||||
BoundingSphere::new(isometry.translation, self.half_length)
|
BoundingSphere::new(isometry.translation, self.half_length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<const N: usize> Bounded3d for Polyline3d<N> {
|
impl<const N: usize> Bounded3d for Polyline3d<N> {
|
||||||
fn aabb_3d(&self, isometry: Isometry3d) -> Aabb3d {
|
fn aabb_3d(&self, isometry: impl Into<Isometry3d>) -> Aabb3d {
|
||||||
Aabb3d::from_point_cloud(isometry, self.vertices.iter().copied())
|
Aabb3d::from_point_cloud(isometry, self.vertices.iter().copied())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_sphere(&self, isometry: Isometry3d) -> BoundingSphere {
|
fn bounding_sphere(&self, isometry: impl Into<Isometry3d>) -> BoundingSphere {
|
||||||
BoundingSphere::from_point_cloud(isometry, &self.vertices)
|
BoundingSphere::from_point_cloud(isometry, &self.vertices)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded3d for BoxedPolyline3d {
|
impl Bounded3d for BoxedPolyline3d {
|
||||||
fn aabb_3d(&self, isometry: Isometry3d) -> Aabb3d {
|
fn aabb_3d(&self, isometry: impl Into<Isometry3d>) -> Aabb3d {
|
||||||
Aabb3d::from_point_cloud(isometry, self.vertices.iter().copied())
|
Aabb3d::from_point_cloud(isometry, self.vertices.iter().copied())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_sphere(&self, isometry: Isometry3d) -> BoundingSphere {
|
fn bounding_sphere(&self, isometry: impl Into<Isometry3d>) -> BoundingSphere {
|
||||||
BoundingSphere::from_point_cloud(isometry, &self.vertices)
|
BoundingSphere::from_point_cloud(isometry, &self.vertices)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded3d for Cuboid {
|
impl Bounded3d for Cuboid {
|
||||||
fn aabb_3d(&self, isometry: Isometry3d) -> Aabb3d {
|
fn aabb_3d(&self, isometry: impl Into<Isometry3d>) -> Aabb3d {
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
// Compute the AABB of the rotated cuboid by transforming the half-size
|
// Compute the AABB of the rotated cuboid by transforming the half-size
|
||||||
// by an absolute rotation matrix.
|
// by an absolute rotation matrix.
|
||||||
let rot_mat = Mat3::from_quat(isometry.rotation);
|
let rot_mat = Mat3::from_quat(isometry.rotation);
|
||||||
@ -115,15 +127,18 @@ impl Bounded3d for Cuboid {
|
|||||||
Aabb3d::new(isometry.translation, half_size)
|
Aabb3d::new(isometry.translation, half_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_sphere(&self, isometry: Isometry3d) -> BoundingSphere {
|
fn bounding_sphere(&self, isometry: impl Into<Isometry3d>) -> BoundingSphere {
|
||||||
|
let isometry = isometry.into();
|
||||||
BoundingSphere::new(isometry.translation, self.half_size.length())
|
BoundingSphere::new(isometry.translation, self.half_size.length())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded3d for Cylinder {
|
impl Bounded3d for Cylinder {
|
||||||
fn aabb_3d(&self, isometry: Isometry3d) -> Aabb3d {
|
fn aabb_3d(&self, isometry: impl Into<Isometry3d>) -> Aabb3d {
|
||||||
// Reference: http://iquilezles.org/articles/diskbbox/
|
// Reference: http://iquilezles.org/articles/diskbbox/
|
||||||
|
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
let segment_dir = isometry.rotation * Vec3A::Y;
|
let segment_dir = isometry.rotation * Vec3A::Y;
|
||||||
let top = segment_dir * self.half_height;
|
let top = segment_dir * self.half_height;
|
||||||
let bottom = -top;
|
let bottom = -top;
|
||||||
@ -137,14 +152,17 @@ impl Bounded3d for Cylinder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_sphere(&self, isometry: Isometry3d) -> BoundingSphere {
|
fn bounding_sphere(&self, isometry: impl Into<Isometry3d>) -> BoundingSphere {
|
||||||
|
let isometry = isometry.into();
|
||||||
let radius = ops::hypot(self.radius, self.half_height);
|
let radius = ops::hypot(self.radius, self.half_height);
|
||||||
BoundingSphere::new(isometry.translation, radius)
|
BoundingSphere::new(isometry.translation, radius)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded3d for Capsule3d {
|
impl Bounded3d for Capsule3d {
|
||||||
fn aabb_3d(&self, isometry: Isometry3d) -> Aabb3d {
|
fn aabb_3d(&self, isometry: impl Into<Isometry3d>) -> Aabb3d {
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
// Get the line segment between the hemispheres of the rotated capsule
|
// Get the line segment between the hemispheres of the rotated capsule
|
||||||
let segment_dir = isometry.rotation * Vec3A::Y;
|
let segment_dir = isometry.rotation * Vec3A::Y;
|
||||||
let top = segment_dir * self.half_length;
|
let top = segment_dir * self.half_length;
|
||||||
@ -160,15 +178,18 @@ impl Bounded3d for Capsule3d {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_sphere(&self, isometry: Isometry3d) -> BoundingSphere {
|
fn bounding_sphere(&self, isometry: impl Into<Isometry3d>) -> BoundingSphere {
|
||||||
|
let isometry = isometry.into();
|
||||||
BoundingSphere::new(isometry.translation, self.radius + self.half_length)
|
BoundingSphere::new(isometry.translation, self.radius + self.half_length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded3d for Cone {
|
impl Bounded3d for Cone {
|
||||||
fn aabb_3d(&self, isometry: Isometry3d) -> Aabb3d {
|
fn aabb_3d(&self, isometry: impl Into<Isometry3d>) -> Aabb3d {
|
||||||
// Reference: http://iquilezles.org/articles/diskbbox/
|
// Reference: http://iquilezles.org/articles/diskbbox/
|
||||||
|
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
let segment_dir = isometry.rotation * Vec3A::Y;
|
let segment_dir = isometry.rotation * Vec3A::Y;
|
||||||
let top = segment_dir * 0.5 * self.height;
|
let top = segment_dir * 0.5 * self.height;
|
||||||
let bottom = -top;
|
let bottom = -top;
|
||||||
@ -182,7 +203,9 @@ impl Bounded3d for Cone {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_sphere(&self, isometry: Isometry3d) -> BoundingSphere {
|
fn bounding_sphere(&self, isometry: impl Into<Isometry3d>) -> BoundingSphere {
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
// Get the triangular cross-section of the cone.
|
// Get the triangular cross-section of the cone.
|
||||||
let half_height = 0.5 * self.height;
|
let half_height = 0.5 * self.height;
|
||||||
let triangle = Triangle2d::new(
|
let triangle = Triangle2d::new(
|
||||||
@ -203,9 +226,11 @@ impl Bounded3d for Cone {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded3d for ConicalFrustum {
|
impl Bounded3d for ConicalFrustum {
|
||||||
fn aabb_3d(&self, isometry: Isometry3d) -> Aabb3d {
|
fn aabb_3d(&self, isometry: impl Into<Isometry3d>) -> Aabb3d {
|
||||||
// Reference: http://iquilezles.org/articles/diskbbox/
|
// Reference: http://iquilezles.org/articles/diskbbox/
|
||||||
|
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
let segment_dir = isometry.rotation * Vec3A::Y;
|
let segment_dir = isometry.rotation * Vec3A::Y;
|
||||||
let top = segment_dir * 0.5 * self.height;
|
let top = segment_dir * 0.5 * self.height;
|
||||||
let bottom = -top;
|
let bottom = -top;
|
||||||
@ -223,7 +248,8 @@ impl Bounded3d for ConicalFrustum {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_sphere(&self, isometry: Isometry3d) -> BoundingSphere {
|
fn bounding_sphere(&self, isometry: impl Into<Isometry3d>) -> BoundingSphere {
|
||||||
|
let isometry = isometry.into();
|
||||||
let half_height = 0.5 * self.height;
|
let half_height = 0.5 * self.height;
|
||||||
|
|
||||||
// To compute the bounding sphere, we'll get the center and radius of the circumcircle
|
// To compute the bounding sphere, we'll get the center and radius of the circumcircle
|
||||||
@ -286,7 +312,9 @@ impl Bounded3d for ConicalFrustum {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded3d for Torus {
|
impl Bounded3d for Torus {
|
||||||
fn aabb_3d(&self, isometry: Isometry3d) -> Aabb3d {
|
fn aabb_3d(&self, isometry: impl Into<Isometry3d>) -> Aabb3d {
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
// Compute the AABB of a flat disc with the major radius of the torus.
|
// Compute the AABB of a flat disc with the major radius of the torus.
|
||||||
// Reference: http://iquilezles.org/articles/diskbbox/
|
// Reference: http://iquilezles.org/articles/diskbbox/
|
||||||
let normal = isometry.rotation * Vec3A::Y;
|
let normal = isometry.rotation * Vec3A::Y;
|
||||||
@ -299,14 +327,16 @@ impl Bounded3d for Torus {
|
|||||||
Aabb3d::new(isometry.translation, half_size)
|
Aabb3d::new(isometry.translation, half_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_sphere(&self, isometry: Isometry3d) -> BoundingSphere {
|
fn bounding_sphere(&self, isometry: impl Into<Isometry3d>) -> BoundingSphere {
|
||||||
|
let isometry = isometry.into();
|
||||||
BoundingSphere::new(isometry.translation, self.outer_radius())
|
BoundingSphere::new(isometry.translation, self.outer_radius())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded3d for Triangle3d {
|
impl Bounded3d for Triangle3d {
|
||||||
/// Get the bounding box of the triangle.
|
/// Get the bounding box of the triangle.
|
||||||
fn aabb_3d(&self, isometry: Isometry3d) -> Aabb3d {
|
fn aabb_3d(&self, isometry: impl Into<Isometry3d>) -> Aabb3d {
|
||||||
|
let isometry = isometry.into();
|
||||||
let [a, b, c] = self.vertices;
|
let [a, b, c] = self.vertices;
|
||||||
|
|
||||||
let a = isometry.rotation * a;
|
let a = isometry.rotation * a;
|
||||||
@ -327,7 +357,9 @@ impl Bounded3d for Triangle3d {
|
|||||||
/// The [`Triangle3d`] implements the minimal bounding sphere calculation. For acute triangles, the circumcenter is used as
|
/// The [`Triangle3d`] implements the minimal bounding sphere calculation. For acute triangles, the circumcenter is used as
|
||||||
/// the center of the sphere. For the others, the bounding sphere is the minimal sphere
|
/// the center of the sphere. For the others, the bounding sphere is the minimal sphere
|
||||||
/// that contains the largest side of the triangle.
|
/// that contains the largest side of the triangle.
|
||||||
fn bounding_sphere(&self, isometry: Isometry3d) -> BoundingSphere {
|
fn bounding_sphere(&self, isometry: impl Into<Isometry3d>) -> BoundingSphere {
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
if self.is_degenerate() || self.is_obtuse() {
|
if self.is_degenerate() || self.is_obtuse() {
|
||||||
let (p1, p2) = self.largest_side();
|
let (p1, p2) = self.largest_side();
|
||||||
let (p1, p2) = (Vec3A::from(p1), Vec3A::from(p2));
|
let (p1, p2) = (Vec3A::from(p1), Vec3A::from(p2));
|
||||||
@ -362,13 +394,12 @@ mod tests {
|
|||||||
fn sphere() {
|
fn sphere() {
|
||||||
let sphere = Sphere { radius: 1.0 };
|
let sphere = Sphere { radius: 1.0 };
|
||||||
let translation = Vec3::new(2.0, 1.0, 0.0);
|
let translation = Vec3::new(2.0, 1.0, 0.0);
|
||||||
let isometry = Isometry3d::from_translation(translation);
|
|
||||||
|
|
||||||
let aabb = sphere.aabb_3d(isometry);
|
let aabb = sphere.aabb_3d(translation);
|
||||||
assert_eq!(aabb.min, Vec3A::new(1.0, 0.0, -1.0));
|
assert_eq!(aabb.min, Vec3A::new(1.0, 0.0, -1.0));
|
||||||
assert_eq!(aabb.max, Vec3A::new(3.0, 2.0, 1.0));
|
assert_eq!(aabb.max, Vec3A::new(3.0, 2.0, 1.0));
|
||||||
|
|
||||||
let bounding_sphere = sphere.bounding_sphere(isometry);
|
let bounding_sphere = sphere.bounding_sphere(translation);
|
||||||
assert_eq!(bounding_sphere.center, translation.into());
|
assert_eq!(bounding_sphere.center, translation.into());
|
||||||
assert_eq!(bounding_sphere.radius(), 1.0);
|
assert_eq!(bounding_sphere.radius(), 1.0);
|
||||||
}
|
}
|
||||||
@ -376,25 +407,24 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn plane() {
|
fn plane() {
|
||||||
let translation = Vec3::new(2.0, 1.0, 0.0);
|
let translation = Vec3::new(2.0, 1.0, 0.0);
|
||||||
let isometry = Isometry3d::from_translation(translation);
|
|
||||||
|
|
||||||
let aabb1 = InfinitePlane3d::new(Vec3::X).aabb_3d(isometry);
|
let aabb1 = InfinitePlane3d::new(Vec3::X).aabb_3d(translation);
|
||||||
assert_eq!(aabb1.min, Vec3A::new(2.0, -f32::MAX / 2.0, -f32::MAX / 2.0));
|
assert_eq!(aabb1.min, Vec3A::new(2.0, -f32::MAX / 2.0, -f32::MAX / 2.0));
|
||||||
assert_eq!(aabb1.max, Vec3A::new(2.0, f32::MAX / 2.0, f32::MAX / 2.0));
|
assert_eq!(aabb1.max, Vec3A::new(2.0, f32::MAX / 2.0, f32::MAX / 2.0));
|
||||||
|
|
||||||
let aabb2 = InfinitePlane3d::new(Vec3::Y).aabb_3d(isometry);
|
let aabb2 = InfinitePlane3d::new(Vec3::Y).aabb_3d(translation);
|
||||||
assert_eq!(aabb2.min, Vec3A::new(-f32::MAX / 2.0, 1.0, -f32::MAX / 2.0));
|
assert_eq!(aabb2.min, Vec3A::new(-f32::MAX / 2.0, 1.0, -f32::MAX / 2.0));
|
||||||
assert_eq!(aabb2.max, Vec3A::new(f32::MAX / 2.0, 1.0, f32::MAX / 2.0));
|
assert_eq!(aabb2.max, Vec3A::new(f32::MAX / 2.0, 1.0, f32::MAX / 2.0));
|
||||||
|
|
||||||
let aabb3 = InfinitePlane3d::new(Vec3::Z).aabb_3d(isometry);
|
let aabb3 = InfinitePlane3d::new(Vec3::Z).aabb_3d(translation);
|
||||||
assert_eq!(aabb3.min, Vec3A::new(-f32::MAX / 2.0, -f32::MAX / 2.0, 0.0));
|
assert_eq!(aabb3.min, Vec3A::new(-f32::MAX / 2.0, -f32::MAX / 2.0, 0.0));
|
||||||
assert_eq!(aabb3.max, Vec3A::new(f32::MAX / 2.0, f32::MAX / 2.0, 0.0));
|
assert_eq!(aabb3.max, Vec3A::new(f32::MAX / 2.0, f32::MAX / 2.0, 0.0));
|
||||||
|
|
||||||
let aabb4 = InfinitePlane3d::new(Vec3::ONE).aabb_3d(isometry);
|
let aabb4 = InfinitePlane3d::new(Vec3::ONE).aabb_3d(translation);
|
||||||
assert_eq!(aabb4.min, Vec3A::splat(-f32::MAX / 2.0));
|
assert_eq!(aabb4.min, Vec3A::splat(-f32::MAX / 2.0));
|
||||||
assert_eq!(aabb4.max, Vec3A::splat(f32::MAX / 2.0));
|
assert_eq!(aabb4.max, Vec3A::splat(f32::MAX / 2.0));
|
||||||
|
|
||||||
let bounding_sphere = InfinitePlane3d::new(Vec3::Y).bounding_sphere(isometry);
|
let bounding_sphere = InfinitePlane3d::new(Vec3::Y).bounding_sphere(translation);
|
||||||
assert_eq!(bounding_sphere.center, translation.into());
|
assert_eq!(bounding_sphere.center, translation.into());
|
||||||
assert_eq!(bounding_sphere.radius(), f32::MAX / 2.0);
|
assert_eq!(bounding_sphere.radius(), f32::MAX / 2.0);
|
||||||
}
|
}
|
||||||
@ -402,28 +432,27 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn line() {
|
fn line() {
|
||||||
let translation = Vec3::new(2.0, 1.0, 0.0);
|
let translation = Vec3::new(2.0, 1.0, 0.0);
|
||||||
let isometry = Isometry3d::from_translation(translation);
|
|
||||||
|
|
||||||
let aabb1 = Line3d { direction: Dir3::Y }.aabb_3d(isometry);
|
let aabb1 = Line3d { direction: Dir3::Y }.aabb_3d(translation);
|
||||||
assert_eq!(aabb1.min, Vec3A::new(2.0, -f32::MAX / 2.0, 0.0));
|
assert_eq!(aabb1.min, Vec3A::new(2.0, -f32::MAX / 2.0, 0.0));
|
||||||
assert_eq!(aabb1.max, Vec3A::new(2.0, f32::MAX / 2.0, 0.0));
|
assert_eq!(aabb1.max, Vec3A::new(2.0, f32::MAX / 2.0, 0.0));
|
||||||
|
|
||||||
let aabb2 = Line3d { direction: Dir3::X }.aabb_3d(isometry);
|
let aabb2 = Line3d { direction: Dir3::X }.aabb_3d(translation);
|
||||||
assert_eq!(aabb2.min, Vec3A::new(-f32::MAX / 2.0, 1.0, 0.0));
|
assert_eq!(aabb2.min, Vec3A::new(-f32::MAX / 2.0, 1.0, 0.0));
|
||||||
assert_eq!(aabb2.max, Vec3A::new(f32::MAX / 2.0, 1.0, 0.0));
|
assert_eq!(aabb2.max, Vec3A::new(f32::MAX / 2.0, 1.0, 0.0));
|
||||||
|
|
||||||
let aabb3 = Line3d { direction: Dir3::Z }.aabb_3d(isometry);
|
let aabb3 = Line3d { direction: Dir3::Z }.aabb_3d(translation);
|
||||||
assert_eq!(aabb3.min, Vec3A::new(2.0, 1.0, -f32::MAX / 2.0));
|
assert_eq!(aabb3.min, Vec3A::new(2.0, 1.0, -f32::MAX / 2.0));
|
||||||
assert_eq!(aabb3.max, Vec3A::new(2.0, 1.0, f32::MAX / 2.0));
|
assert_eq!(aabb3.max, Vec3A::new(2.0, 1.0, f32::MAX / 2.0));
|
||||||
|
|
||||||
let aabb4 = Line3d {
|
let aabb4 = Line3d {
|
||||||
direction: Dir3::from_xyz(1.0, 1.0, 1.0).unwrap(),
|
direction: Dir3::from_xyz(1.0, 1.0, 1.0).unwrap(),
|
||||||
}
|
}
|
||||||
.aabb_3d(isometry);
|
.aabb_3d(translation);
|
||||||
assert_eq!(aabb4.min, Vec3A::splat(-f32::MAX / 2.0));
|
assert_eq!(aabb4.min, Vec3A::splat(-f32::MAX / 2.0));
|
||||||
assert_eq!(aabb4.max, Vec3A::splat(f32::MAX / 2.0));
|
assert_eq!(aabb4.max, Vec3A::splat(f32::MAX / 2.0));
|
||||||
|
|
||||||
let bounding_sphere = Line3d { direction: Dir3::Y }.bounding_sphere(isometry);
|
let bounding_sphere = Line3d { direction: Dir3::Y }.bounding_sphere(translation);
|
||||||
assert_eq!(bounding_sphere.center, translation.into());
|
assert_eq!(bounding_sphere.center, translation.into());
|
||||||
assert_eq!(bounding_sphere.radius(), f32::MAX / 2.0);
|
assert_eq!(bounding_sphere.radius(), f32::MAX / 2.0);
|
||||||
}
|
}
|
||||||
@ -431,16 +460,15 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn segment() {
|
fn segment() {
|
||||||
let translation = Vec3::new(2.0, 1.0, 0.0);
|
let translation = Vec3::new(2.0, 1.0, 0.0);
|
||||||
let isometry = Isometry3d::from_translation(translation);
|
|
||||||
|
|
||||||
let segment =
|
let segment =
|
||||||
Segment3d::from_points(Vec3::new(-1.0, -0.5, 0.0), Vec3::new(1.0, 0.5, 0.0)).0;
|
Segment3d::from_points(Vec3::new(-1.0, -0.5, 0.0), Vec3::new(1.0, 0.5, 0.0)).0;
|
||||||
|
|
||||||
let aabb = segment.aabb_3d(isometry);
|
let aabb = segment.aabb_3d(translation);
|
||||||
assert_eq!(aabb.min, Vec3A::new(1.0, 0.5, 0.0));
|
assert_eq!(aabb.min, Vec3A::new(1.0, 0.5, 0.0));
|
||||||
assert_eq!(aabb.max, Vec3A::new(3.0, 1.5, 0.0));
|
assert_eq!(aabb.max, Vec3A::new(3.0, 1.5, 0.0));
|
||||||
|
|
||||||
let bounding_sphere = segment.bounding_sphere(isometry);
|
let bounding_sphere = segment.bounding_sphere(translation);
|
||||||
assert_eq!(bounding_sphere.center, translation.into());
|
assert_eq!(bounding_sphere.center, translation.into());
|
||||||
assert_eq!(bounding_sphere.radius(), ops::hypot(1.0, 0.5));
|
assert_eq!(bounding_sphere.radius(), ops::hypot(1.0, 0.5));
|
||||||
}
|
}
|
||||||
@ -454,13 +482,12 @@ mod tests {
|
|||||||
Vec3::new(1.0, -1.0, -1.0),
|
Vec3::new(1.0, -1.0, -1.0),
|
||||||
]);
|
]);
|
||||||
let translation = Vec3::new(2.0, 1.0, 0.0);
|
let translation = Vec3::new(2.0, 1.0, 0.0);
|
||||||
let isometry = Isometry3d::from_translation(translation);
|
|
||||||
|
|
||||||
let aabb = polyline.aabb_3d(isometry);
|
let aabb = polyline.aabb_3d(translation);
|
||||||
assert_eq!(aabb.min, Vec3A::new(1.0, 0.0, -1.0));
|
assert_eq!(aabb.min, Vec3A::new(1.0, 0.0, -1.0));
|
||||||
assert_eq!(aabb.max, Vec3A::new(3.0, 2.0, 1.0));
|
assert_eq!(aabb.max, Vec3A::new(3.0, 2.0, 1.0));
|
||||||
|
|
||||||
let bounding_sphere = polyline.bounding_sphere(isometry);
|
let bounding_sphere = polyline.bounding_sphere(translation);
|
||||||
assert_eq!(bounding_sphere.center, translation.into());
|
assert_eq!(bounding_sphere.center, translation.into());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
bounding_sphere.radius(),
|
bounding_sphere.radius(),
|
||||||
@ -481,7 +508,7 @@ mod tests {
|
|||||||
assert_eq!(aabb.min, Vec3A::from(translation) - expected_half_size);
|
assert_eq!(aabb.min, Vec3A::from(translation) - expected_half_size);
|
||||||
assert_eq!(aabb.max, Vec3A::from(translation) + expected_half_size);
|
assert_eq!(aabb.max, Vec3A::from(translation) + expected_half_size);
|
||||||
|
|
||||||
let bounding_sphere = cuboid.bounding_sphere(Isometry3d::from_translation(translation));
|
let bounding_sphere = cuboid.bounding_sphere(translation);
|
||||||
assert_eq!(bounding_sphere.center, translation.into());
|
assert_eq!(bounding_sphere.center, translation.into());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
bounding_sphere.radius(),
|
bounding_sphere.radius(),
|
||||||
@ -493,9 +520,8 @@ mod tests {
|
|||||||
fn cylinder() {
|
fn cylinder() {
|
||||||
let cylinder = Cylinder::new(0.5, 2.0);
|
let cylinder = Cylinder::new(0.5, 2.0);
|
||||||
let translation = Vec3::new(2.0, 1.0, 0.0);
|
let translation = Vec3::new(2.0, 1.0, 0.0);
|
||||||
let isometry = Isometry3d::from_translation(translation);
|
|
||||||
|
|
||||||
let aabb = cylinder.aabb_3d(isometry);
|
let aabb = cylinder.aabb_3d(translation);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
aabb.min,
|
aabb.min,
|
||||||
Vec3A::from(translation) - Vec3A::new(0.5, 1.0, 0.5)
|
Vec3A::from(translation) - Vec3A::new(0.5, 1.0, 0.5)
|
||||||
@ -505,7 +531,7 @@ mod tests {
|
|||||||
Vec3A::from(translation) + Vec3A::new(0.5, 1.0, 0.5)
|
Vec3A::from(translation) + Vec3A::new(0.5, 1.0, 0.5)
|
||||||
);
|
);
|
||||||
|
|
||||||
let bounding_sphere = cylinder.bounding_sphere(isometry);
|
let bounding_sphere = cylinder.bounding_sphere(translation);
|
||||||
assert_eq!(bounding_sphere.center, translation.into());
|
assert_eq!(bounding_sphere.center, translation.into());
|
||||||
assert_eq!(bounding_sphere.radius(), ops::hypot(1.0, 0.5));
|
assert_eq!(bounding_sphere.radius(), ops::hypot(1.0, 0.5));
|
||||||
}
|
}
|
||||||
@ -514,9 +540,8 @@ mod tests {
|
|||||||
fn capsule() {
|
fn capsule() {
|
||||||
let capsule = Capsule3d::new(0.5, 2.0);
|
let capsule = Capsule3d::new(0.5, 2.0);
|
||||||
let translation = Vec3::new(2.0, 1.0, 0.0);
|
let translation = Vec3::new(2.0, 1.0, 0.0);
|
||||||
let isometry = Isometry3d::from_translation(translation);
|
|
||||||
|
|
||||||
let aabb = capsule.aabb_3d(isometry);
|
let aabb = capsule.aabb_3d(translation);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
aabb.min,
|
aabb.min,
|
||||||
Vec3A::from(translation) - Vec3A::new(0.5, 1.5, 0.5)
|
Vec3A::from(translation) - Vec3A::new(0.5, 1.5, 0.5)
|
||||||
@ -526,7 +551,7 @@ mod tests {
|
|||||||
Vec3A::from(translation) + Vec3A::new(0.5, 1.5, 0.5)
|
Vec3A::from(translation) + Vec3A::new(0.5, 1.5, 0.5)
|
||||||
);
|
);
|
||||||
|
|
||||||
let bounding_sphere = capsule.bounding_sphere(isometry);
|
let bounding_sphere = capsule.bounding_sphere(translation);
|
||||||
assert_eq!(bounding_sphere.center, translation.into());
|
assert_eq!(bounding_sphere.center, translation.into());
|
||||||
assert_eq!(bounding_sphere.radius(), 1.5);
|
assert_eq!(bounding_sphere.radius(), 1.5);
|
||||||
}
|
}
|
||||||
@ -538,13 +563,12 @@ mod tests {
|
|||||||
height: 2.0,
|
height: 2.0,
|
||||||
};
|
};
|
||||||
let translation = Vec3::new(2.0, 1.0, 0.0);
|
let translation = Vec3::new(2.0, 1.0, 0.0);
|
||||||
let isometry = Isometry3d::from_translation(translation);
|
|
||||||
|
|
||||||
let aabb = cone.aabb_3d(isometry);
|
let aabb = cone.aabb_3d(translation);
|
||||||
assert_eq!(aabb.min, Vec3A::new(1.0, 0.0, -1.0));
|
assert_eq!(aabb.min, Vec3A::new(1.0, 0.0, -1.0));
|
||||||
assert_eq!(aabb.max, Vec3A::new(3.0, 2.0, 1.0));
|
assert_eq!(aabb.max, Vec3A::new(3.0, 2.0, 1.0));
|
||||||
|
|
||||||
let bounding_sphere = cone.bounding_sphere(isometry);
|
let bounding_sphere = cone.bounding_sphere(translation);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
bounding_sphere.center,
|
bounding_sphere.center,
|
||||||
Vec3A::from(translation) + Vec3A::NEG_Y * 0.25
|
Vec3A::from(translation) + Vec3A::NEG_Y * 0.25
|
||||||
@ -560,13 +584,12 @@ mod tests {
|
|||||||
height: 2.0,
|
height: 2.0,
|
||||||
};
|
};
|
||||||
let translation = Vec3::new(2.0, 1.0, 0.0);
|
let translation = Vec3::new(2.0, 1.0, 0.0);
|
||||||
let isometry = Isometry3d::from_translation(translation);
|
|
||||||
|
|
||||||
let aabb = conical_frustum.aabb_3d(isometry);
|
let aabb = conical_frustum.aabb_3d(translation);
|
||||||
assert_eq!(aabb.min, Vec3A::new(1.0, 0.0, -1.0));
|
assert_eq!(aabb.min, Vec3A::new(1.0, 0.0, -1.0));
|
||||||
assert_eq!(aabb.max, Vec3A::new(3.0, 2.0, 1.0));
|
assert_eq!(aabb.max, Vec3A::new(3.0, 2.0, 1.0));
|
||||||
|
|
||||||
let bounding_sphere = conical_frustum.bounding_sphere(isometry);
|
let bounding_sphere = conical_frustum.bounding_sphere(translation);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
bounding_sphere.center,
|
bounding_sphere.center,
|
||||||
Vec3A::from(translation) + Vec3A::NEG_Y * 0.1875
|
Vec3A::from(translation) + Vec3A::NEG_Y * 0.1875
|
||||||
@ -582,15 +605,14 @@ mod tests {
|
|||||||
height: 1.0,
|
height: 1.0,
|
||||||
};
|
};
|
||||||
let translation = Vec3::new(2.0, 1.0, 0.0);
|
let translation = Vec3::new(2.0, 1.0, 0.0);
|
||||||
let isometry = Isometry3d::from_translation(translation);
|
|
||||||
|
|
||||||
let aabb = conical_frustum.aabb_3d(isometry);
|
let aabb = conical_frustum.aabb_3d(translation);
|
||||||
assert_eq!(aabb.min, Vec3A::new(-3.0, 0.5, -5.0));
|
assert_eq!(aabb.min, Vec3A::new(-3.0, 0.5, -5.0));
|
||||||
assert_eq!(aabb.max, Vec3A::new(7.0, 1.5, 5.0));
|
assert_eq!(aabb.max, Vec3A::new(7.0, 1.5, 5.0));
|
||||||
|
|
||||||
// For wide conical frusta like this, the circumcenter can be outside the frustum,
|
// For wide conical frusta like this, the circumcenter can be outside the frustum,
|
||||||
// so the center and radius should be clamped to the longest side.
|
// so the center and radius should be clamped to the longest side.
|
||||||
let bounding_sphere = conical_frustum.bounding_sphere(isometry);
|
let bounding_sphere = conical_frustum.bounding_sphere(translation);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
bounding_sphere.center,
|
bounding_sphere.center,
|
||||||
Vec3A::from(translation) + Vec3A::NEG_Y * 0.5
|
Vec3A::from(translation) + Vec3A::NEG_Y * 0.5
|
||||||
@ -605,13 +627,12 @@ mod tests {
|
|||||||
major_radius: 1.0,
|
major_radius: 1.0,
|
||||||
};
|
};
|
||||||
let translation = Vec3::new(2.0, 1.0, 0.0);
|
let translation = Vec3::new(2.0, 1.0, 0.0);
|
||||||
let isometry = Isometry3d::from_translation(translation);
|
|
||||||
|
|
||||||
let aabb = torus.aabb_3d(isometry);
|
let aabb = torus.aabb_3d(translation);
|
||||||
assert_eq!(aabb.min, Vec3A::new(0.5, 0.5, -1.5));
|
assert_eq!(aabb.min, Vec3A::new(0.5, 0.5, -1.5));
|
||||||
assert_eq!(aabb.max, Vec3A::new(3.5, 1.5, 1.5));
|
assert_eq!(aabb.max, Vec3A::new(3.5, 1.5, 1.5));
|
||||||
|
|
||||||
let bounding_sphere = torus.bounding_sphere(isometry);
|
let bounding_sphere = torus.bounding_sphere(translation);
|
||||||
assert_eq!(bounding_sphere.center, translation.into());
|
assert_eq!(bounding_sphere.center, translation.into());
|
||||||
assert_eq!(bounding_sphere.radius(), 1.5);
|
assert_eq!(bounding_sphere.radius(), 1.5);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -192,6 +192,20 @@ impl From<Isometry2d> for Affine2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Vec2> for Isometry2d {
|
||||||
|
#[inline]
|
||||||
|
fn from(translation: Vec2) -> Self {
|
||||||
|
Isometry2d::from_translation(translation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Rot2> for Isometry2d {
|
||||||
|
#[inline]
|
||||||
|
fn from(rotation: Rot2) -> Self {
|
||||||
|
Isometry2d::from_rotation(rotation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Mul for Isometry2d {
|
impl Mul for Isometry2d {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
@ -466,6 +480,27 @@ impl From<Isometry3d> for Affine3A {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Vec3> for Isometry3d {
|
||||||
|
#[inline]
|
||||||
|
fn from(translation: Vec3) -> Self {
|
||||||
|
Isometry3d::from_translation(translation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Vec3A> for Isometry3d {
|
||||||
|
#[inline]
|
||||||
|
fn from(translation: Vec3A) -> Self {
|
||||||
|
Isometry3d::from_translation(translation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Quat> for Isometry3d {
|
||||||
|
#[inline]
|
||||||
|
fn from(rotation: Quat) -> Self {
|
||||||
|
Isometry3d::from_rotation(rotation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Mul for Isometry3d {
|
impl Mul for Isometry3d {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
|
|||||||
@ -220,7 +220,8 @@ impl InfinitePlane3d {
|
|||||||
/// `point`. The result is a signed value; it's positive if the point lies in the half-space
|
/// `point`. The result is a signed value; it's positive if the point lies in the half-space
|
||||||
/// that the plane's normal vector points towards.
|
/// that the plane's normal vector points towards.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn signed_distance(&self, isometry: Isometry3d, point: Vec3) -> f32 {
|
pub fn signed_distance(&self, isometry: impl Into<Isometry3d>, point: Vec3) -> f32 {
|
||||||
|
let isometry = isometry.into();
|
||||||
self.normal.dot(isometry.inverse() * point)
|
self.normal.dot(isometry.inverse() * point)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,7 +229,7 @@ impl InfinitePlane3d {
|
|||||||
///
|
///
|
||||||
/// This projects the point orthogonally along the shortest path onto the plane.
|
/// This projects the point orthogonally along the shortest path onto the plane.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn project_point(&self, isometry: Isometry3d, point: Vec3) -> Vec3 {
|
pub fn project_point(&self, isometry: impl Into<Isometry3d>, point: Vec3) -> Vec3 {
|
||||||
point - self.normal * self.signed_distance(isometry, point)
|
point - self.normal * self.signed_distance(isometry, point)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1374,36 +1375,36 @@ mod tests {
|
|||||||
|
|
||||||
let point_in_plane = Vec3::X + Vec3::Z;
|
let point_in_plane = Vec3::X + Vec3::Z;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
plane.signed_distance(Isometry3d::from_translation(origin), point_in_plane),
|
plane.signed_distance(origin, point_in_plane),
|
||||||
0.0,
|
0.0,
|
||||||
"incorrect distance"
|
"incorrect distance"
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
plane.project_point(Isometry3d::from_translation(origin), point_in_plane),
|
plane.project_point(origin, point_in_plane),
|
||||||
point_in_plane,
|
point_in_plane,
|
||||||
"incorrect point"
|
"incorrect point"
|
||||||
);
|
);
|
||||||
|
|
||||||
let point_outside = Vec3::Y;
|
let point_outside = Vec3::Y;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
plane.signed_distance(Isometry3d::from_translation(origin), point_outside),
|
plane.signed_distance(origin, point_outside),
|
||||||
-1.0,
|
-1.0,
|
||||||
"incorrect distance"
|
"incorrect distance"
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
plane.project_point(Isometry3d::from_translation(origin), point_outside),
|
plane.project_point(origin, point_outside),
|
||||||
Vec3::ZERO,
|
Vec3::ZERO,
|
||||||
"incorrect point"
|
"incorrect point"
|
||||||
);
|
);
|
||||||
|
|
||||||
let point_outside = Vec3::NEG_Y;
|
let point_outside = Vec3::NEG_Y;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
plane.signed_distance(Isometry3d::from_translation(origin), point_outside),
|
plane.signed_distance(origin, point_outside),
|
||||||
1.0,
|
1.0,
|
||||||
"incorrect distance"
|
"incorrect distance"
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
plane.project_point(Isometry3d::from_translation(origin), point_outside),
|
plane.project_point(origin, point_outside),
|
||||||
Vec3::ZERO,
|
Vec3::ZERO,
|
||||||
"incorrect point"
|
"incorrect point"
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
//! This example demonstrates how to use the `Camera::viewport_to_world_2d` method.
|
//! This example demonstrates how to use the `Camera::viewport_to_world_2d` method.
|
||||||
|
|
||||||
use bevy::{color::palettes::basic::WHITE, math::Isometry2d, prelude::*};
|
use bevy::{color::palettes::basic::WHITE, prelude::*};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
@ -30,7 +30,7 @@ fn draw_cursor(
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
gizmos.circle_2d(Isometry2d::from_translation(point), 10., WHITE);
|
gizmos.circle_2d(point, 10., WHITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup(mut commands: Commands) {
|
fn setup(mut commands: Commands) {
|
||||||
|
|||||||
@ -186,14 +186,10 @@ fn render_volumes(mut gizmos: Gizmos, query: Query<(&CurrentVolume, &Intersects)
|
|||||||
let color = if **intersects { AQUA } else { ORANGE_RED };
|
let color = if **intersects { AQUA } else { ORANGE_RED };
|
||||||
match volume {
|
match volume {
|
||||||
CurrentVolume::Aabb(a) => {
|
CurrentVolume::Aabb(a) => {
|
||||||
gizmos.rect_2d(
|
gizmos.rect_2d(a.center(), a.half_size() * 2., color);
|
||||||
Isometry2d::from_translation(a.center()),
|
|
||||||
a.half_size() * 2.,
|
|
||||||
color,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
CurrentVolume::Circle(c) => {
|
CurrentVolume::Circle(c) => {
|
||||||
gizmos.circle_2d(Isometry2d::from_translation(c.center()), c.radius(), color);
|
gizmos.circle_2d(c.center(), c.radius(), color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -288,7 +284,7 @@ fn setup(mut commands: Commands) {
|
|||||||
|
|
||||||
fn draw_filled_circle(gizmos: &mut Gizmos, position: Vec2, color: Srgba) {
|
fn draw_filled_circle(gizmos: &mut Gizmos, position: Vec2, color: Srgba) {
|
||||||
for r in [1., 2., 3.] {
|
for r in [1., 2., 3.] {
|
||||||
gizmos.circle_2d(Isometry2d::from_translation(position), r, color);
|
gizmos.circle_2d(position, r, color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -361,9 +357,7 @@ fn aabb_cast_system(
|
|||||||
**intersects = toi.is_some();
|
**intersects = toi.is_some();
|
||||||
if let Some(toi) = toi {
|
if let Some(toi) = toi {
|
||||||
gizmos.rect_2d(
|
gizmos.rect_2d(
|
||||||
Isometry2d::from_translation(
|
|
||||||
aabb_cast.ray.ray.origin + *aabb_cast.ray.ray.direction * toi,
|
aabb_cast.ray.ray.origin + *aabb_cast.ray.ray.direction * toi,
|
||||||
),
|
|
||||||
aabb_cast.aabb.half_size() * 2.,
|
aabb_cast.aabb.half_size() * 2.,
|
||||||
LIME,
|
LIME,
|
||||||
);
|
);
|
||||||
@ -391,9 +385,7 @@ fn bounding_circle_cast_system(
|
|||||||
**intersects = toi.is_some();
|
**intersects = toi.is_some();
|
||||||
if let Some(toi) = toi {
|
if let Some(toi) = toi {
|
||||||
gizmos.circle_2d(
|
gizmos.circle_2d(
|
||||||
Isometry2d::from_translation(
|
|
||||||
circle_cast.ray.ray.origin + *circle_cast.ray.ray.direction * toi,
|
circle_cast.ray.ray.origin + *circle_cast.ray.ray.direction * toi,
|
||||||
),
|
|
||||||
circle_cast.circle.radius(),
|
circle_cast.circle.radius(),
|
||||||
LIME,
|
LIME,
|
||||||
);
|
);
|
||||||
@ -414,11 +406,7 @@ fn aabb_intersection_system(
|
|||||||
) {
|
) {
|
||||||
let center = get_intersection_position(&time);
|
let center = get_intersection_position(&time);
|
||||||
let aabb = Aabb2d::new(center, Vec2::splat(50.));
|
let aabb = Aabb2d::new(center, Vec2::splat(50.));
|
||||||
gizmos.rect_2d(
|
gizmos.rect_2d(center, aabb.half_size() * 2., YELLOW);
|
||||||
Isometry2d::from_translation(center),
|
|
||||||
aabb.half_size() * 2.,
|
|
||||||
YELLOW,
|
|
||||||
);
|
|
||||||
|
|
||||||
for (volume, mut intersects) in volumes.iter_mut() {
|
for (volume, mut intersects) in volumes.iter_mut() {
|
||||||
let hit = match volume {
|
let hit = match volume {
|
||||||
@ -437,11 +425,7 @@ fn circle_intersection_system(
|
|||||||
) {
|
) {
|
||||||
let center = get_intersection_position(&time);
|
let center = get_intersection_position(&time);
|
||||||
let circle = BoundingCircle::new(center, 50.);
|
let circle = BoundingCircle::new(center, 50.);
|
||||||
gizmos.circle_2d(
|
gizmos.circle_2d(center, circle.radius(), YELLOW);
|
||||||
Isometry2d::from_translation(center),
|
|
||||||
circle.radius(),
|
|
||||||
YELLOW,
|
|
||||||
);
|
|
||||||
|
|
||||||
for (volume, mut intersects) in volumes.iter_mut() {
|
for (volume, mut intersects) in volumes.iter_mut() {
|
||||||
let hit = match volume {
|
let hit = match volume {
|
||||||
|
|||||||
@ -114,17 +114,9 @@ fn draw_bounds<Shape: Bounded2d + Send + Sync + 'static>(
|
|||||||
let isometry = Isometry2d::new(translation, Rot2::radians(rotation));
|
let isometry = Isometry2d::new(translation, Rot2::radians(rotation));
|
||||||
|
|
||||||
let aabb = shape.0.aabb_2d(isometry);
|
let aabb = shape.0.aabb_2d(isometry);
|
||||||
gizmos.rect_2d(
|
gizmos.rect_2d(aabb.center(), aabb.half_size() * 2.0, RED);
|
||||||
Isometry2d::from_translation(aabb.center()),
|
|
||||||
aabb.half_size() * 2.0,
|
|
||||||
RED,
|
|
||||||
);
|
|
||||||
|
|
||||||
let bounding_circle = shape.0.bounding_circle(isometry);
|
let bounding_circle = shape.0.bounding_circle(isometry);
|
||||||
gizmos.circle_2d(
|
gizmos.circle_2d(bounding_circle.center, bounding_circle.radius(), BLUE);
|
||||||
Isometry2d::from_translation(bounding_circle.center),
|
|
||||||
bounding_circle.radius(),
|
|
||||||
BLUE,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
//! Demonstrates how to observe life-cycle triggers as well as define custom ones.
|
//! Demonstrates how to observe life-cycle triggers as well as define custom ones.
|
||||||
|
|
||||||
use bevy::{
|
use bevy::{
|
||||||
math::Isometry2d,
|
|
||||||
prelude::*,
|
prelude::*,
|
||||||
utils::{HashMap, HashSet},
|
utils::{HashMap, HashSet},
|
||||||
};
|
};
|
||||||
@ -166,7 +165,7 @@ fn explode_mine(trigger: Trigger<Explode>, query: Query<&Mine>, mut commands: Co
|
|||||||
fn draw_shapes(mut gizmos: Gizmos, mines: Query<&Mine>) {
|
fn draw_shapes(mut gizmos: Gizmos, mines: Query<&Mine>) {
|
||||||
for mine in &mines {
|
for mine in &mines {
|
||||||
gizmos.circle_2d(
|
gizmos.circle_2d(
|
||||||
Isometry2d::from_translation(mine.pos),
|
mine.pos,
|
||||||
mine.size,
|
mine.size,
|
||||||
Color::hsl((mine.size - 4.0) / 16.0 * 360.0, 1.0, 0.8),
|
Color::hsl((mine.size - 4.0) / 16.0 * 360.0, 1.0, 0.8),
|
||||||
);
|
);
|
||||||
|
|||||||
@ -67,11 +67,7 @@ fn draw_example_collection(
|
|||||||
|
|
||||||
gizmos.rect_2d(Isometry2d::IDENTITY, Vec2::splat(650.), BLACK);
|
gizmos.rect_2d(Isometry2d::IDENTITY, Vec2::splat(650.), BLACK);
|
||||||
|
|
||||||
gizmos.cross_2d(
|
gizmos.cross_2d(Vec2::new(-160., 120.), 12., FUCHSIA);
|
||||||
Isometry2d::from_translation(Vec2::new(-160., 120.)),
|
|
||||||
12.,
|
|
||||||
FUCHSIA,
|
|
||||||
);
|
|
||||||
|
|
||||||
let domain = Interval::EVERYWHERE;
|
let domain = Interval::EVERYWHERE;
|
||||||
let curve = function_curve(domain, |t| Vec2::new(t, ops::sin(t / 25.0) * 100.0));
|
let curve = function_curve(domain, |t| Vec2::new(t, ops::sin(t / 25.0) * 100.0));
|
||||||
@ -89,11 +85,11 @@ fn draw_example_collection(
|
|||||||
// Circles have 32 line-segments by default.
|
// Circles have 32 line-segments by default.
|
||||||
// You may want to increase this for larger circles.
|
// You may want to increase this for larger circles.
|
||||||
my_gizmos
|
my_gizmos
|
||||||
.circle_2d(Isometry2d::from_translation(Vec2::ZERO), 300., NAVY)
|
.circle_2d(Isometry2d::IDENTITY, 300., NAVY)
|
||||||
.resolution(64);
|
.resolution(64);
|
||||||
|
|
||||||
my_gizmos.ellipse_2d(
|
my_gizmos.ellipse_2d(
|
||||||
Isometry2d::new(Vec2::ZERO, Rot2::radians(time.elapsed_seconds() % TAU)),
|
Rot2::radians(time.elapsed_seconds() % TAU),
|
||||||
Vec2::new(100., 200.),
|
Vec2::new(100., 200.),
|
||||||
YELLOW_GREEN,
|
YELLOW_GREEN,
|
||||||
);
|
);
|
||||||
@ -101,7 +97,7 @@ fn draw_example_collection(
|
|||||||
// Arcs default resolution is linearly interpolated between
|
// Arcs default resolution is linearly interpolated between
|
||||||
// 1 and 32, using the arc length as scalar.
|
// 1 and 32, using the arc length as scalar.
|
||||||
my_gizmos.arc_2d(
|
my_gizmos.arc_2d(
|
||||||
Isometry2d::from_rotation(Rot2::radians(sin_t_scaled / 10.)),
|
Rot2::radians(sin_t_scaled / 10.),
|
||||||
FRAC_PI_2,
|
FRAC_PI_2,
|
||||||
310.,
|
310.,
|
||||||
ORANGE_RED,
|
ORANGE_RED,
|
||||||
|
|||||||
@ -78,19 +78,19 @@ fn draw_example_collection(
|
|||||||
time: Res<Time>,
|
time: Res<Time>,
|
||||||
) {
|
) {
|
||||||
gizmos.grid(
|
gizmos.grid(
|
||||||
Isometry3d::from_rotation(Quat::from_rotation_x(PI / 2.)),
|
Quat::from_rotation_x(PI / 2.),
|
||||||
UVec2::splat(20),
|
UVec2::splat(20),
|
||||||
Vec2::new(2., 2.),
|
Vec2::new(2., 2.),
|
||||||
// Light gray
|
// Light gray
|
||||||
LinearRgba::gray(0.65),
|
LinearRgba::gray(0.65),
|
||||||
);
|
);
|
||||||
gizmos.grid(
|
gizmos.grid(
|
||||||
Isometry3d::new(Vec3::ONE * 10.0, Quat::from_rotation_x(PI / 3. * 2.)),
|
Isometry3d::new(Vec3::splat(10.0), Quat::from_rotation_x(PI / 3. * 2.)),
|
||||||
UVec2::splat(20),
|
UVec2::splat(20),
|
||||||
Vec2::new(2., 2.),
|
Vec2::new(2., 2.),
|
||||||
PURPLE,
|
PURPLE,
|
||||||
);
|
);
|
||||||
gizmos.sphere(Isometry3d::from_translation(Vec3::ONE * 10.0), 1.0, PURPLE);
|
gizmos.sphere(Vec3::splat(10.0), 1.0, PURPLE);
|
||||||
|
|
||||||
gizmos
|
gizmos
|
||||||
.primitive_3d(
|
.primitive_3d(
|
||||||
@ -99,7 +99,7 @@ fn draw_example_collection(
|
|||||||
half_size: Vec2::splat(1.0),
|
half_size: Vec2::splat(1.0),
|
||||||
},
|
},
|
||||||
Isometry3d::new(
|
Isometry3d::new(
|
||||||
Vec3::ONE * 4.0 + Vec2::from(ops::sin_cos(time.elapsed_seconds())).extend(0.0),
|
Vec3::splat(4.0) + Vec2::from(ops::sin_cos(time.elapsed_seconds())).extend(0.0),
|
||||||
Quat::from_rotation_x(PI / 2. + time.elapsed_seconds()),
|
Quat::from_rotation_x(PI / 2. + time.elapsed_seconds()),
|
||||||
),
|
),
|
||||||
GREEN,
|
GREEN,
|
||||||
@ -120,11 +120,7 @@ fn draw_example_collection(
|
|||||||
LIME,
|
LIME,
|
||||||
);
|
);
|
||||||
|
|
||||||
gizmos.cross(
|
gizmos.cross(Vec3::new(-1., 1., 1.), 0.5, FUCHSIA);
|
||||||
Isometry3d::from_translation(Vec3::new(-1., 1., 1.)),
|
|
||||||
0.5,
|
|
||||||
FUCHSIA,
|
|
||||||
);
|
|
||||||
|
|
||||||
let domain = Interval::EVERYWHERE;
|
let domain = Interval::EVERYWHERE;
|
||||||
let curve = function_curve(domain, |t| {
|
let curve = function_curve(domain, |t| {
|
||||||
@ -137,18 +133,10 @@ fn draw_example_collection(
|
|||||||
.map(|t| (t, TEAL.mix(&HOT_PINK, t / 5.0)));
|
.map(|t| (t, TEAL.mix(&HOT_PINK, t / 5.0)));
|
||||||
gizmos.curve_gradient_3d(curve, times_and_colors);
|
gizmos.curve_gradient_3d(curve, times_and_colors);
|
||||||
|
|
||||||
my_gizmos.sphere(
|
my_gizmos.sphere(Vec3::new(1., 0.5, 0.), 0.5, RED);
|
||||||
Isometry3d::from_translation(Vec3::new(1., 0.5, 0.)),
|
|
||||||
0.5,
|
|
||||||
RED,
|
|
||||||
);
|
|
||||||
|
|
||||||
my_gizmos
|
my_gizmos
|
||||||
.rounded_cuboid(
|
.rounded_cuboid(Vec3::new(-2.0, 0.75, -0.75), Vec3::splat(0.9), TURQUOISE)
|
||||||
Isometry3d::from_translation(Vec3::new(-2.0, 0.75, -0.75)),
|
|
||||||
Vec3::splat(0.9),
|
|
||||||
TURQUOISE,
|
|
||||||
)
|
|
||||||
.edge_radius(0.1)
|
.edge_radius(0.1)
|
||||||
.arc_resolution(4);
|
.arc_resolution(4);
|
||||||
|
|
||||||
@ -173,24 +161,17 @@ fn draw_example_collection(
|
|||||||
.resolution(10);
|
.resolution(10);
|
||||||
|
|
||||||
// Circles have 32 line-segments by default.
|
// Circles have 32 line-segments by default.
|
||||||
my_gizmos.circle(
|
my_gizmos.circle(Quat::from_rotation_arc(Vec3::Z, Vec3::Y), 3., BLACK);
|
||||||
Isometry3d::from_rotation(Quat::from_rotation_arc(Vec3::Z, Vec3::Y)),
|
|
||||||
3.,
|
|
||||||
BLACK,
|
|
||||||
);
|
|
||||||
// You may want to increase this for larger circles or spheres.
|
// You may want to increase this for larger circles or spheres.
|
||||||
my_gizmos
|
my_gizmos
|
||||||
.circle(
|
.circle(Quat::from_rotation_arc(Vec3::Z, Vec3::Y), 3.1, NAVY)
|
||||||
Isometry3d::from_rotation(Quat::from_rotation_arc(Vec3::Z, Vec3::Y)),
|
|
||||||
3.1,
|
|
||||||
NAVY,
|
|
||||||
)
|
|
||||||
.resolution(64);
|
.resolution(64);
|
||||||
my_gizmos
|
my_gizmos
|
||||||
.sphere(Isometry3d::IDENTITY, 3.2, BLACK)
|
.sphere(Isometry3d::IDENTITY, 3.2, BLACK)
|
||||||
.resolution(64);
|
.resolution(64);
|
||||||
|
|
||||||
gizmos.arrow(Vec3::ZERO, Vec3::ONE * 1.5, YELLOW);
|
gizmos.arrow(Vec3::ZERO, Vec3::splat(1.5), YELLOW);
|
||||||
|
|
||||||
// You can create more complex arrows using the arrow builder.
|
// You can create more complex arrows using the arrow builder.
|
||||||
gizmos
|
gizmos
|
||||||
|
|||||||
@ -6,7 +6,7 @@ use bevy::{
|
|||||||
ecs::system::Commands,
|
ecs::system::Commands,
|
||||||
gizmos::gizmos::Gizmos,
|
gizmos::gizmos::Gizmos,
|
||||||
input::{mouse::MouseButtonInput, ButtonState},
|
input::{mouse::MouseButtonInput, ButtonState},
|
||||||
math::{cubic_splines::*, vec2, Isometry2d},
|
math::{cubic_splines::*, vec2},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -197,11 +197,7 @@ fn draw_control_points(
|
|||||||
mut gizmos: Gizmos,
|
mut gizmos: Gizmos,
|
||||||
) {
|
) {
|
||||||
for &(point, tangent) in &control_points.points_and_tangents {
|
for &(point, tangent) in &control_points.points_and_tangents {
|
||||||
gizmos.circle_2d(
|
gizmos.circle_2d(point, 10.0, Color::srgb(0.0, 1.0, 0.0));
|
||||||
Isometry2d::from_translation(point),
|
|
||||||
10.0,
|
|
||||||
Color::srgb(0.0, 1.0, 0.0),
|
|
||||||
);
|
|
||||||
|
|
||||||
if matches!(*spline_mode, SplineMode::Hermite) {
|
if matches!(*spline_mode, SplineMode::Hermite) {
|
||||||
gizmos.arrow_2d(point, point + tangent, Color::srgb(1.0, 0.0, 0.0));
|
gizmos.arrow_2d(point, point + tangent, Color::srgb(1.0, 0.0, 0.0));
|
||||||
@ -403,16 +399,8 @@ fn draw_edit_move(
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
gizmos.circle_2d(
|
gizmos.circle_2d(start, 10.0, Color::srgb(0.0, 1.0, 0.7));
|
||||||
Isometry2d::from_translation(start),
|
gizmos.circle_2d(start, 7.0, Color::srgb(0.0, 1.0, 0.7));
|
||||||
10.0,
|
|
||||||
Color::srgb(0.0, 1.0, 0.7),
|
|
||||||
);
|
|
||||||
gizmos.circle_2d(
|
|
||||||
Isometry2d::from_translation(start),
|
|
||||||
7.0,
|
|
||||||
Color::srgb(0.0, 1.0, 0.7),
|
|
||||||
);
|
|
||||||
gizmos.arrow_2d(start, end, Color::srgb(1.0, 0.0, 0.7));
|
gizmos.arrow_2d(start, end, Color::srgb(1.0, 0.0, 0.7));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -197,23 +197,13 @@ fn bounding_shapes_2d(
|
|||||||
BoundingShape::BoundingBox => {
|
BoundingShape::BoundingBox => {
|
||||||
// Get the AABB of the primitive with the rotation and translation of the mesh.
|
// Get the AABB of the primitive with the rotation and translation of the mesh.
|
||||||
let aabb = HEART.aabb_2d(isometry);
|
let aabb = HEART.aabb_2d(isometry);
|
||||||
|
gizmos.rect_2d(aabb.center(), aabb.half_size() * 2., WHITE);
|
||||||
gizmos.rect_2d(
|
|
||||||
Isometry2d::from_translation(aabb.center()),
|
|
||||||
aabb.half_size() * 2.,
|
|
||||||
WHITE,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
BoundingShape::BoundingSphere => {
|
BoundingShape::BoundingSphere => {
|
||||||
// Get the bounding sphere of the primitive with the rotation and translation of the mesh.
|
// Get the bounding sphere of the primitive with the rotation and translation of the mesh.
|
||||||
let bounding_circle = HEART.bounding_circle(isometry);
|
let bounding_circle = HEART.bounding_circle(isometry);
|
||||||
|
|
||||||
gizmos
|
gizmos
|
||||||
.circle_2d(
|
.circle_2d(bounding_circle.center(), bounding_circle.radius(), WHITE)
|
||||||
Isometry2d::from_translation(bounding_circle.center()),
|
|
||||||
bounding_circle.radius(),
|
|
||||||
WHITE,
|
|
||||||
)
|
|
||||||
.resolution(64);
|
.resolution(64);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -244,7 +234,7 @@ fn bounding_shapes_3d(
|
|||||||
|
|
||||||
gizmos.primitive_3d(
|
gizmos.primitive_3d(
|
||||||
&Cuboid::from_size(Vec3::from(aabb.half_size()) * 2.),
|
&Cuboid::from_size(Vec3::from(aabb.half_size()) * 2.),
|
||||||
Isometry3d::from_translation(aabb.center()),
|
aabb.center(),
|
||||||
WHITE,
|
WHITE,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -252,11 +242,7 @@ fn bounding_shapes_3d(
|
|||||||
// Get the bounding sphere of the extrusion with the rotation and translation of the mesh.
|
// Get the bounding sphere of the extrusion with the rotation and translation of the mesh.
|
||||||
let bounding_sphere = EXTRUSION.bounding_sphere(transform.to_isometry());
|
let bounding_sphere = EXTRUSION.bounding_sphere(transform.to_isometry());
|
||||||
|
|
||||||
gizmos.sphere(
|
gizmos.sphere(bounding_sphere.center(), bounding_sphere.radius(), WHITE);
|
||||||
Isometry3d::from_translation(bounding_sphere.center()),
|
|
||||||
bounding_sphere.radius(),
|
|
||||||
WHITE,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -336,7 +322,9 @@ impl Measured2d for Heart {
|
|||||||
|
|
||||||
// The `Bounded2d` or `Bounded3d` traits are used to compute the Axis Aligned Bounding Boxes or bounding circles / spheres for primitives.
|
// The `Bounded2d` or `Bounded3d` traits are used to compute the Axis Aligned Bounding Boxes or bounding circles / spheres for primitives.
|
||||||
impl Bounded2d for Heart {
|
impl Bounded2d for Heart {
|
||||||
fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d {
|
fn aabb_2d(&self, isometry: impl Into<Isometry2d>) -> Aabb2d {
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
// The center of the circle at the center of the right wing of the heart
|
// The center of the circle at the center of the right wing of the heart
|
||||||
let circle_center = isometry.rotation * Vec2::new(self.radius, 0.0);
|
let circle_center = isometry.rotation * Vec2::new(self.radius, 0.0);
|
||||||
// The maximum X and Y positions of the two circles of the wings of the heart.
|
// The maximum X and Y positions of the two circles of the wings of the heart.
|
||||||
@ -353,7 +341,9 @@ impl Bounded2d for Heart {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle {
|
fn bounding_circle(&self, isometry: impl Into<Isometry2d>) -> BoundingCircle {
|
||||||
|
let isometry = isometry.into();
|
||||||
|
|
||||||
// The bounding circle of the heart is not at its origin. This `offset` is the offset between the center of the bounding circle and its translation.
|
// The bounding circle of the heart is not at its origin. This `offset` is the offset between the center of the bounding circle and its translation.
|
||||||
let offset = self.radius / ops::powf(2f32, 1.5);
|
let offset = self.radius / ops::powf(2f32, 1.5);
|
||||||
// The center of the bounding circle
|
// The center of the bounding circle
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user