separating finite and infinite 3d planes (#12426)
# Objective Fixes #12388 ## Solution - Removing the plane3d and adding rect3d primitive mesh
This commit is contained in:
parent
158defd67b
commit
2b3e3341d6
@ -134,18 +134,18 @@ impl<T: GizmoConfigGroup> Drop for SphereBuilder<'_, '_, '_, T> {
|
|||||||
|
|
||||||
// plane 3d
|
// plane 3d
|
||||||
|
|
||||||
/// Builder for configuring the drawing options of [`Sphere`].
|
/// Builder for configuring the drawing options of [`Plane3d`].
|
||||||
pub struct Plane3dBuilder<'a, 'w, 's, T: GizmoConfigGroup> {
|
pub struct Plane3dBuilder<'a, 'w, 's, T: GizmoConfigGroup> {
|
||||||
gizmos: &'a mut Gizmos<'w, 's, T>,
|
gizmos: &'a mut Gizmos<'w, 's, T>,
|
||||||
|
|
||||||
// direction of the normal orthogonal to the plane
|
// direction of the normal orthogonal to the plane
|
||||||
normal: Dir3,
|
normal: Dir3,
|
||||||
|
|
||||||
// Rotation of the sphere around the origin in 3D space
|
// Rotation of the plane around the origin in 3D space
|
||||||
rotation: Quat,
|
rotation: Quat,
|
||||||
// Center position of the sphere in 3D space
|
// Center position of the plane in 3D space
|
||||||
position: Vec3,
|
position: Vec3,
|
||||||
// Color of the sphere
|
// Color of the plane
|
||||||
color: Color,
|
color: Color,
|
||||||
|
|
||||||
// Number of axis to hint the plane
|
// Number of axis to hint the plane
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
bounding::{Bounded2d, BoundingCircle},
|
bounding::{Bounded2d, BoundingCircle},
|
||||||
primitives::{
|
primitives::{
|
||||||
BoxedPolyline3d, Capsule3d, Cone, ConicalFrustum, Cuboid, Cylinder, Line3d, Plane3d,
|
BoxedPolyline3d, Capsule3d, Cone, ConicalFrustum, Cuboid, Cylinder, InfinitePlane3d,
|
||||||
Polyline3d, Segment3d, Sphere, Torus, Triangle2d,
|
Line3d, Polyline3d, Segment3d, Sphere, Torus, Triangle2d,
|
||||||
},
|
},
|
||||||
Dir3, Mat3, Quat, Vec2, Vec3,
|
Dir3, Mat3, Quat, Vec2, Vec3,
|
||||||
};
|
};
|
||||||
@ -21,7 +21,7 @@ impl Bounded3d for Sphere {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded3d for Plane3d {
|
impl Bounded3d for InfinitePlane3d {
|
||||||
fn aabb_3d(&self, translation: Vec3, rotation: Quat) -> Aabb3d {
|
fn aabb_3d(&self, translation: Vec3, rotation: Quat) -> Aabb3d {
|
||||||
let normal = rotation * *self.normal;
|
let normal = rotation * *self.normal;
|
||||||
let facing_x = normal == Vec3::X || normal == Vec3::NEG_X;
|
let facing_x = normal == Vec3::X || normal == Vec3::NEG_X;
|
||||||
@ -310,7 +310,7 @@ mod tests {
|
|||||||
use crate::{
|
use crate::{
|
||||||
bounding::Bounded3d,
|
bounding::Bounded3d,
|
||||||
primitives::{
|
primitives::{
|
||||||
Capsule3d, Cone, ConicalFrustum, Cuboid, Cylinder, Line3d, Plane3d, Polyline3d,
|
Capsule3d, Cone, ConicalFrustum, Cuboid, Cylinder, InfinitePlane3d, Line3d, Polyline3d,
|
||||||
Segment3d, Sphere, Torus,
|
Segment3d, Sphere, Torus,
|
||||||
},
|
},
|
||||||
Dir3,
|
Dir3,
|
||||||
@ -334,23 +334,24 @@ mod tests {
|
|||||||
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 aabb1 = Plane3d::new(Vec3::X).aabb_3d(translation, Quat::IDENTITY);
|
let aabb1 = InfinitePlane3d::new(Vec3::X).aabb_3d(translation, Quat::IDENTITY);
|
||||||
assert_eq!(aabb1.min, Vec3::new(2.0, -f32::MAX / 2.0, -f32::MAX / 2.0));
|
assert_eq!(aabb1.min, Vec3::new(2.0, -f32::MAX / 2.0, -f32::MAX / 2.0));
|
||||||
assert_eq!(aabb1.max, Vec3::new(2.0, f32::MAX / 2.0, f32::MAX / 2.0));
|
assert_eq!(aabb1.max, Vec3::new(2.0, f32::MAX / 2.0, f32::MAX / 2.0));
|
||||||
|
|
||||||
let aabb2 = Plane3d::new(Vec3::Y).aabb_3d(translation, Quat::IDENTITY);
|
let aabb2 = InfinitePlane3d::new(Vec3::Y).aabb_3d(translation, Quat::IDENTITY);
|
||||||
assert_eq!(aabb2.min, Vec3::new(-f32::MAX / 2.0, 1.0, -f32::MAX / 2.0));
|
assert_eq!(aabb2.min, Vec3::new(-f32::MAX / 2.0, 1.0, -f32::MAX / 2.0));
|
||||||
assert_eq!(aabb2.max, Vec3::new(f32::MAX / 2.0, 1.0, f32::MAX / 2.0));
|
assert_eq!(aabb2.max, Vec3::new(f32::MAX / 2.0, 1.0, f32::MAX / 2.0));
|
||||||
|
|
||||||
let aabb3 = Plane3d::new(Vec3::Z).aabb_3d(translation, Quat::IDENTITY);
|
let aabb3 = InfinitePlane3d::new(Vec3::Z).aabb_3d(translation, Quat::IDENTITY);
|
||||||
assert_eq!(aabb3.min, Vec3::new(-f32::MAX / 2.0, -f32::MAX / 2.0, 0.0));
|
assert_eq!(aabb3.min, Vec3::new(-f32::MAX / 2.0, -f32::MAX / 2.0, 0.0));
|
||||||
assert_eq!(aabb3.max, Vec3::new(f32::MAX / 2.0, f32::MAX / 2.0, 0.0));
|
assert_eq!(aabb3.max, Vec3::new(f32::MAX / 2.0, f32::MAX / 2.0, 0.0));
|
||||||
|
|
||||||
let aabb4 = Plane3d::new(Vec3::ONE).aabb_3d(translation, Quat::IDENTITY);
|
let aabb4 = InfinitePlane3d::new(Vec3::ONE).aabb_3d(translation, Quat::IDENTITY);
|
||||||
assert_eq!(aabb4.min, Vec3::splat(-f32::MAX / 2.0));
|
assert_eq!(aabb4.min, Vec3::splat(-f32::MAX / 2.0));
|
||||||
assert_eq!(aabb4.max, Vec3::splat(f32::MAX / 2.0));
|
assert_eq!(aabb4.max, Vec3::splat(f32::MAX / 2.0));
|
||||||
|
|
||||||
let bounding_sphere = Plane3d::new(Vec3::Y).bounding_sphere(translation, Quat::IDENTITY);
|
let bounding_sphere =
|
||||||
|
InfinitePlane3d::new(Vec3::Y).bounding_sphere(translation, Quat::IDENTITY);
|
||||||
assert_eq!(bounding_sphere.center, translation);
|
assert_eq!(bounding_sphere.center, translation);
|
||||||
assert_eq!(bounding_sphere.radius(), f32::MAX / 2.0);
|
assert_eq!(bounding_sphere.radius(), f32::MAX / 2.0);
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ use std::f32::consts::{FRAC_PI_3, PI};
|
|||||||
use super::{Circle, Primitive3d};
|
use super::{Circle, Primitive3d};
|
||||||
use crate::{
|
use crate::{
|
||||||
bounding::{Aabb3d, Bounded3d, BoundingSphere},
|
bounding::{Aabb3d, Bounded3d, BoundingSphere},
|
||||||
Dir3, InvalidDirectionError, Mat3, Quat, Vec3,
|
Dir3, InvalidDirectionError, Mat3, Quat, Vec2, Vec3,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A sphere primitive
|
/// A sphere primitive
|
||||||
@ -67,33 +67,38 @@ impl Sphere {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An unbounded plane in 3D space. It forms a separating surface through the origin,
|
/// A bounded plane in 3D space. It forms a surface starting from the origin with a defined height and width.
|
||||||
/// stretching infinitely far
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||||
pub struct Plane3d {
|
pub struct Plane3d {
|
||||||
/// The normal of the plane. The plane will be placed perpendicular to this direction
|
/// The normal of the plane. The plane will be placed perpendicular to this direction
|
||||||
pub normal: Dir3,
|
pub normal: Dir3,
|
||||||
|
/// Half of the width and height of the plane
|
||||||
|
pub half_size: Vec2,
|
||||||
}
|
}
|
||||||
impl Primitive3d for Plane3d {}
|
impl Primitive3d for Plane3d {}
|
||||||
|
|
||||||
impl Default for Plane3d {
|
impl Default for Plane3d {
|
||||||
/// Returns the default [`Plane3d`] with a normal pointing in the `+Y` direction.
|
/// Returns the default [`Plane3d`] with a normal pointing in the `+Y` direction, width and height of `1.0`.
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self { normal: Dir3::Y }
|
Self {
|
||||||
|
normal: Dir3::Y,
|
||||||
|
half_size: Vec2::splat(0.5),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Plane3d {
|
impl Plane3d {
|
||||||
/// Create a new `Plane3d` from a normal
|
/// Create a new `Plane3d` from a normal and a half size
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// Panics if the given `normal` is zero (or very close to zero), or non-finite.
|
/// Panics if the given `normal` is zero (or very close to zero), or non-finite.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn new(normal: Vec3) -> Self {
|
pub fn new(normal: Vec3, half_size: Vec2) -> Self {
|
||||||
Self {
|
Self {
|
||||||
normal: Dir3::new(normal).expect("normal must be nonzero and finite"),
|
normal: Dir3::new(normal).expect("normal must be nonzero and finite"),
|
||||||
|
half_size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,8 +114,71 @@ impl Plane3d {
|
|||||||
/// are *collinear* and lie on the same line.
|
/// are *collinear* and lie on the same line.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn from_points(a: Vec3, b: Vec3, c: Vec3) -> (Self, Vec3) {
|
pub fn from_points(a: Vec3, b: Vec3, c: Vec3) -> (Self, Vec3) {
|
||||||
let normal = Dir3::new((b - a).cross(c - a))
|
let normal = Dir3::new((b - a).cross(c - a)).expect(
|
||||||
.expect("plane must be defined by three finite points that don't lie on the same line");
|
"finite plane must be defined by three finite points that don't lie on the same line",
|
||||||
|
);
|
||||||
|
let translation = (a + b + c) / 3.0;
|
||||||
|
|
||||||
|
(
|
||||||
|
Self {
|
||||||
|
normal,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
translation,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An unbounded plane in 3D space. It forms a separating surface through the origin,
|
||||||
|
/// stretching infinitely far
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||||
|
pub struct InfinitePlane3d {
|
||||||
|
/// The normal of the plane. The plane will be placed perpendicular to this direction
|
||||||
|
pub normal: Dir3,
|
||||||
|
}
|
||||||
|
impl Primitive3d for InfinitePlane3d {}
|
||||||
|
|
||||||
|
impl Default for InfinitePlane3d {
|
||||||
|
/// Returns the default [`InfinitePlane3d`] with a normal pointing in the `+Y` direction.
|
||||||
|
fn default() -> Self {
|
||||||
|
Self { normal: Dir3::Y }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InfinitePlane3d {
|
||||||
|
/// Create a new `InfinitePlane3d` from a normal
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if the given `normal` is zero (or very close to zero), or non-finite.
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn new<T: TryInto<Dir3>>(normal: T) -> Self
|
||||||
|
where
|
||||||
|
<T as TryInto<Dir3>>::Error: std::fmt::Debug,
|
||||||
|
{
|
||||||
|
Self {
|
||||||
|
normal: normal
|
||||||
|
.try_into()
|
||||||
|
.expect("normal must be nonzero and finite"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new `InfinitePlane3d` based on three points and compute the geometric center
|
||||||
|
/// of those points.
|
||||||
|
///
|
||||||
|
/// The direction of the plane normal is determined by the winding order
|
||||||
|
/// of the triangular shape formed by the points.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if a valid normal can not be computed, for example when the points
|
||||||
|
/// are *collinear* and lie on the same line.
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn from_points(a: Vec3, b: Vec3, c: Vec3) -> (Self, Vec3) {
|
||||||
|
let normal = Dir3::new((b - a).cross(c - a)).expect(
|
||||||
|
"infinite plane must be defined by three finite points that don't lie on the same line",
|
||||||
|
);
|
||||||
let translation = (a + b + c) / 3.0;
|
let translation = (a + b + c) / 3.0;
|
||||||
|
|
||||||
(Self { normal }, translation)
|
(Self { normal }, translation)
|
||||||
@ -975,6 +1043,14 @@ mod tests {
|
|||||||
fn plane_from_points() {
|
fn plane_from_points() {
|
||||||
let (plane, translation) = Plane3d::from_points(Vec3::X, Vec3::Z, Vec3::NEG_X);
|
let (plane, translation) = Plane3d::from_points(Vec3::X, Vec3::Z, Vec3::NEG_X);
|
||||||
assert_eq!(*plane.normal, Vec3::NEG_Y, "incorrect normal");
|
assert_eq!(*plane.normal, Vec3::NEG_Y, "incorrect normal");
|
||||||
|
assert_eq!(plane.half_size, Vec2::new(0.5, 0.5), "incorrect half size");
|
||||||
|
assert_eq!(translation, Vec3::Z * 0.33333334, "incorrect translation");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn infinite_plane_from_points() {
|
||||||
|
let (plane, translation) = InfinitePlane3d::from_points(Vec3::X, Vec3::Z, Vec3::NEG_X);
|
||||||
|
assert_eq!(*plane.normal, Vec3::NEG_Y, "incorrect normal");
|
||||||
assert_eq!(translation, Vec3::Z * 0.33333334, "incorrect translation");
|
assert_eq!(translation, Vec3::Z * 0.33333334, "incorrect translation");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
primitives::{Plane2d, Plane3d},
|
primitives::{InfinitePlane3d, Plane2d},
|
||||||
Dir2, Dir3, Vec2, Vec3,
|
Dir2, Dir3, Vec2, Vec3,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ impl Ray3d {
|
|||||||
|
|
||||||
/// Get the distance to a plane if the ray intersects it
|
/// Get the distance to a plane if the ray intersects it
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn intersect_plane(&self, plane_origin: Vec3, plane: Plane3d) -> Option<f32> {
|
pub fn intersect_plane(&self, plane_origin: Vec3, plane: InfinitePlane3d) -> Option<f32> {
|
||||||
let denominator = plane.normal.dot(*self.direction);
|
let denominator = plane.normal.dot(*self.direction);
|
||||||
if denominator.abs() > f32::EPSILON {
|
if denominator.abs() > f32::EPSILON {
|
||||||
let distance = (plane_origin - self.origin).dot(*plane.normal) / denominator;
|
let distance = (plane_origin - self.origin).dot(*plane.normal) / denominator;
|
||||||
@ -141,37 +141,40 @@ mod tests {
|
|||||||
|
|
||||||
// Orthogonal, and test that an inverse plane_normal has the same result
|
// Orthogonal, and test that an inverse plane_normal has the same result
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ray.intersect_plane(Vec3::Z, Plane3d::new(Vec3::Z)),
|
ray.intersect_plane(Vec3::Z, InfinitePlane3d::new(Vec3::Z)),
|
||||||
Some(1.0)
|
Some(1.0)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ray.intersect_plane(Vec3::Z, Plane3d::new(Vec3::NEG_Z)),
|
ray.intersect_plane(Vec3::Z, InfinitePlane3d::new(Vec3::NEG_Z)),
|
||||||
Some(1.0)
|
Some(1.0)
|
||||||
);
|
);
|
||||||
assert!(ray
|
assert!(ray
|
||||||
.intersect_plane(Vec3::NEG_Z, Plane3d::new(Vec3::Z))
|
.intersect_plane(Vec3::NEG_Z, InfinitePlane3d::new(Vec3::Z))
|
||||||
.is_none());
|
.is_none());
|
||||||
assert!(ray
|
assert!(ray
|
||||||
.intersect_plane(Vec3::NEG_Z, Plane3d::new(Vec3::NEG_Z))
|
.intersect_plane(Vec3::NEG_Z, InfinitePlane3d::new(Vec3::NEG_Z))
|
||||||
.is_none());
|
.is_none());
|
||||||
|
|
||||||
// Diagonal
|
// Diagonal
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ray.intersect_plane(Vec3::Z, Plane3d::new(Vec3::ONE)),
|
ray.intersect_plane(Vec3::Z, InfinitePlane3d::new(Vec3::ONE)),
|
||||||
Some(1.0)
|
Some(1.0)
|
||||||
);
|
);
|
||||||
assert!(ray
|
assert!(ray
|
||||||
.intersect_plane(Vec3::NEG_Z, Plane3d::new(Vec3::ONE))
|
.intersect_plane(Vec3::NEG_Z, InfinitePlane3d::new(Vec3::ONE))
|
||||||
.is_none());
|
.is_none());
|
||||||
|
|
||||||
// Parallel
|
// Parallel
|
||||||
assert!(ray
|
assert!(ray
|
||||||
.intersect_plane(Vec3::X, Plane3d::new(Vec3::X))
|
.intersect_plane(Vec3::X, InfinitePlane3d::new(Vec3::X))
|
||||||
.is_none());
|
.is_none());
|
||||||
|
|
||||||
// Parallel with simulated rounding error
|
// Parallel with simulated rounding error
|
||||||
assert!(ray
|
assert!(ray
|
||||||
.intersect_plane(Vec3::X, Plane3d::new(Vec3::X + Vec3::Z * f32::EPSILON))
|
.intersect_plane(
|
||||||
|
Vec3::X,
|
||||||
|
InfinitePlane3d::new(Vec3::X + Vec3::Z * f32::EPSILON)
|
||||||
|
)
|
||||||
.is_none());
|
.is_none());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate as bevy_reflect;
|
use crate as bevy_reflect;
|
||||||
use crate::{ReflectDeserialize, ReflectSerialize};
|
use crate::{ReflectDeserialize, ReflectSerialize};
|
||||||
use bevy_math::{primitives::*, Dir3, Vec3};
|
use bevy_math::{primitives::*, Dir3, Vec2, Vec3};
|
||||||
use bevy_reflect_derive::impl_reflect;
|
use bevy_reflect_derive::impl_reflect;
|
||||||
|
|
||||||
impl_reflect!(
|
impl_reflect!(
|
||||||
@ -16,6 +16,15 @@ impl_reflect!(
|
|||||||
#[type_path = "bevy_math::primitives"]
|
#[type_path = "bevy_math::primitives"]
|
||||||
struct Plane3d {
|
struct Plane3d {
|
||||||
normal: Dir3,
|
normal: Dir3,
|
||||||
|
half_size: Vec2,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
impl_reflect!(
|
||||||
|
#[reflect(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[type_path = "bevy_math::primitives"]
|
||||||
|
struct InfinitePlane3d {
|
||||||
|
normal: Dir3,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -7,21 +7,10 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// A builder used for creating a [`Mesh`] with a [`Plane3d`] shape.
|
/// A builder used for creating a [`Mesh`] with a [`Plane3d`] shape.
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
pub struct PlaneMeshBuilder {
|
pub struct PlaneMeshBuilder {
|
||||||
/// The [`Plane3d`] shape.
|
/// The [`Plane3d`] shape.
|
||||||
pub plane: Plane3d,
|
pub plane: Plane3d,
|
||||||
/// Half the size of the plane mesh.
|
|
||||||
pub half_size: Vec2,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for PlaneMeshBuilder {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
plane: Plane3d::default(),
|
|
||||||
half_size: Vec2::ONE,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PlaneMeshBuilder {
|
impl PlaneMeshBuilder {
|
||||||
@ -29,8 +18,10 @@ impl PlaneMeshBuilder {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(normal: Dir3, size: Vec2) -> Self {
|
pub fn new(normal: Dir3, size: Vec2) -> Self {
|
||||||
Self {
|
Self {
|
||||||
plane: Plane3d { normal },
|
plane: Plane3d {
|
||||||
half_size: size / 2.0,
|
normal,
|
||||||
|
half_size: size / 2.0,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,8 +29,10 @@ impl PlaneMeshBuilder {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_size(size: Vec2) -> Self {
|
pub fn from_size(size: Vec2) -> Self {
|
||||||
Self {
|
Self {
|
||||||
half_size: size / 2.0,
|
plane: Plane3d {
|
||||||
..Default::default()
|
half_size: size / 2.0,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,8 +41,10 @@ impl PlaneMeshBuilder {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_length(length: f32) -> Self {
|
pub fn from_length(length: f32) -> Self {
|
||||||
Self {
|
Self {
|
||||||
half_size: Vec2::splat(length) / 2.0,
|
plane: Plane3d {
|
||||||
..Default::default()
|
half_size: Vec2::splat(length) / 2.0,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,14 +52,17 @@ impl PlaneMeshBuilder {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[doc(alias = "facing")]
|
#[doc(alias = "facing")]
|
||||||
pub fn normal(mut self, normal: Dir3) -> Self {
|
pub fn normal(mut self, normal: Dir3) -> Self {
|
||||||
self.plane = Plane3d { normal };
|
self.plane = Plane3d {
|
||||||
|
normal,
|
||||||
|
..self.plane
|
||||||
|
};
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the size of the plane mesh.
|
/// Sets the size of the plane mesh.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn size(mut self, width: f32, height: f32) -> Self {
|
pub fn size(mut self, width: f32, height: f32) -> Self {
|
||||||
self.half_size = Vec2::new(width, height) / 2.0;
|
self.plane.half_size = Vec2::new(width, height) / 2.0;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,10 +70,10 @@ impl PlaneMeshBuilder {
|
|||||||
pub fn build(&self) -> Mesh {
|
pub fn build(&self) -> Mesh {
|
||||||
let rotation = Quat::from_rotation_arc(Vec3::Y, *self.plane.normal);
|
let rotation = Quat::from_rotation_arc(Vec3::Y, *self.plane.normal);
|
||||||
let positions = vec![
|
let positions = vec![
|
||||||
rotation * Vec3::new(self.half_size.x, 0.0, -self.half_size.y),
|
rotation * Vec3::new(self.plane.half_size.x, 0.0, -self.plane.half_size.y),
|
||||||
rotation * Vec3::new(-self.half_size.x, 0.0, -self.half_size.y),
|
rotation * Vec3::new(-self.plane.half_size.x, 0.0, -self.plane.half_size.y),
|
||||||
rotation * Vec3::new(-self.half_size.x, 0.0, self.half_size.y),
|
rotation * Vec3::new(-self.plane.half_size.x, 0.0, self.plane.half_size.y),
|
||||||
rotation * Vec3::new(self.half_size.x, 0.0, self.half_size.y),
|
rotation * Vec3::new(self.plane.half_size.x, 0.0, self.plane.half_size.y),
|
||||||
];
|
];
|
||||||
|
|
||||||
let normals = vec![self.plane.normal.to_array(); 4];
|
let normals = vec![self.plane.normal.to_array(); 4];
|
||||||
@ -97,10 +95,7 @@ impl Meshable for Plane3d {
|
|||||||
type Output = PlaneMeshBuilder;
|
type Output = PlaneMeshBuilder;
|
||||||
|
|
||||||
fn mesh(&self) -> Self::Output {
|
fn mesh(&self) -> Self::Output {
|
||||||
PlaneMeshBuilder {
|
PlaneMeshBuilder { plane: *self }
|
||||||
plane: *self,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,8 @@ fn draw_cursor(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Calculate if and where the ray is hitting the ground plane.
|
// Calculate if and where the ray is hitting the ground plane.
|
||||||
let Some(distance) = ray.intersect_plane(ground.translation(), Plane3d::new(ground.up()))
|
let Some(distance) =
|
||||||
|
ray.intersect_plane(ground.translation(), InfinitePlane3d::new(ground.up()))
|
||||||
else {
|
else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
@ -499,7 +499,7 @@ fn handle_mouse_clicks(
|
|||||||
let Some(ray) = camera.viewport_to_world(camera_transform, mouse_position) else {
|
let Some(ray) = camera.viewport_to_world(camera_transform, mouse_position) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let Some(ray_distance) = ray.intersect_plane(Vec3::ZERO, Plane3d::new(Vec3::Y)) else {
|
let Some(ray_distance) = ray.intersect_plane(Vec3::ZERO, InfinitePlane3d::new(Vec3::Y)) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let plane_intersection = ray.origin + ray.direction.normalize() * ray_distance;
|
let plane_intersection = ray.origin + ray.direction.normalize() * ray_distance;
|
||||||
|
@ -166,7 +166,10 @@ const TRIANGLE: Triangle2d = Triangle2d {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const PLANE_2D: Plane2d = Plane2d { normal: Dir2::Y };
|
const PLANE_2D: Plane2d = Plane2d { normal: Dir2::Y };
|
||||||
const PLANE_3D: Plane3d = Plane3d { normal: Dir3::Y };
|
const PLANE_3D: Plane3d = Plane3d {
|
||||||
|
normal: Dir3::Y,
|
||||||
|
half_size: Vec2::new(BIG_3D, BIG_3D),
|
||||||
|
};
|
||||||
|
|
||||||
const LINE2D: Line2d = Line2d { direction: Dir2::X };
|
const LINE2D: Line2d = Line2d { direction: Dir2::X };
|
||||||
const LINE3D: Line3d = Line3d { direction: Dir3::X };
|
const LINE3D: Line3d = Line3d { direction: Dir3::X };
|
||||||
|
@ -388,6 +388,7 @@ fn init_meshes(args: &Args, assets: &mut Assets<Mesh>) -> Vec<(Handle<Mesh>, Tra
|
|||||||
assets.add(
|
assets.add(
|
||||||
Plane3d {
|
Plane3d {
|
||||||
normal: Dir3::NEG_Z,
|
normal: Dir3::NEG_Z,
|
||||||
|
half_size: Vec2::splat(0.5),
|
||||||
}
|
}
|
||||||
.mesh()
|
.mesh()
|
||||||
.size(radius, radius),
|
.size(radius, radius),
|
||||||
|
Loading…
Reference in New Issue
Block a user