mirror of
https://github.com/bevyengine/bevy
synced 2024-11-24 21:53:07 +00:00
Add Direction3dA
and move direction types out of primitives
(#12018)
# Objective Split up from #12017, add an aligned version of `Direction3d` for SIMD, and move direction types out of `primitives`. ## Solution Add `Direction3dA` and move direction types into a new `direction` module. --- ## Migration Guide The `Direction2d`, `Direction3d`, and `InvalidDirectionError` types have been moved out of `bevy::math::primitives`. Before: ```rust use bevy::math::primitives::Direction3d; ``` After: ```rust use bevy::math::Direction3d; ``` --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
This commit is contained in:
parent
f939c09f2c
commit
9bd6cc0a5e
22 changed files with 598 additions and 371 deletions
|
@ -5,7 +5,7 @@
|
|||
|
||||
use crate::prelude::{GizmoConfigGroup, Gizmos};
|
||||
use bevy_math::Mat2;
|
||||
use bevy_math::{primitives::Direction3d, Quat, Vec2, Vec3};
|
||||
use bevy_math::{Direction3d, Quat, Vec2, Vec3};
|
||||
use bevy_render::color::LegacyColor;
|
||||
use std::f32::consts::TAU;
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ use bevy_ecs::{
|
|||
system::{Deferred, ReadOnlySystemParam, Res, Resource, SystemBuffer, SystemMeta, SystemParam},
|
||||
world::{unsafe_world_cell::UnsafeWorldCell, World},
|
||||
};
|
||||
use bevy_math::{primitives::Direction3d, Mat2, Quat, Vec2, Vec3};
|
||||
use bevy_math::{Direction3d, Mat2, Quat, Vec2, Vec3};
|
||||
use bevy_render::color::LegacyColor;
|
||||
use bevy_transform::TransformPoint;
|
||||
|
||||
|
|
|
@ -5,10 +5,10 @@ use std::f32::consts::PI;
|
|||
use super::helpers::*;
|
||||
|
||||
use bevy_math::primitives::{
|
||||
BoxedPolygon, BoxedPolyline2d, Capsule2d, Circle, Direction2d, Ellipse, Line2d, Plane2d,
|
||||
Polygon, Polyline2d, Primitive2d, Rectangle, RegularPolygon, Segment2d, Triangle2d,
|
||||
BoxedPolygon, BoxedPolyline2d, Capsule2d, Circle, Ellipse, Line2d, Plane2d, Polygon,
|
||||
Polyline2d, Primitive2d, Rectangle, RegularPolygon, Segment2d, Triangle2d,
|
||||
};
|
||||
use bevy_math::{Mat2, Vec2};
|
||||
use bevy_math::{Direction2d, Mat2, Vec2};
|
||||
use bevy_render::color::LegacyColor;
|
||||
|
||||
use crate::prelude::{GizmoConfigGroup, Gizmos};
|
||||
|
|
|
@ -4,10 +4,10 @@ use super::helpers::*;
|
|||
use std::f32::consts::TAU;
|
||||
|
||||
use bevy_math::primitives::{
|
||||
BoxedPolyline3d, Capsule3d, Cone, ConicalFrustum, Cuboid, Cylinder, Direction3d, Line3d,
|
||||
Plane3d, Polyline3d, Primitive3d, Segment3d, Sphere, Torus,
|
||||
BoxedPolyline3d, Capsule3d, Cone, ConicalFrustum, Cuboid, Cylinder, Line3d, Plane3d,
|
||||
Polyline3d, Primitive3d, Segment3d, Sphere, Torus,
|
||||
};
|
||||
use bevy_math::{Quat, Vec3};
|
||||
use bevy_math::{Direction3d, Quat, Vec3};
|
||||
use bevy_render::color::LegacyColor;
|
||||
|
||||
use crate::prelude::{GizmoConfigGroup, Gizmos};
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
//! Contains [`Bounded2d`] implementations for [geometric primitives](crate::primitives).
|
||||
|
||||
use glam::{Mat2, Vec2};
|
||||
|
||||
use crate::primitives::{
|
||||
BoxedPolygon, BoxedPolyline2d, Capsule2d, Circle, Direction2d, Ellipse, Line2d, Plane2d,
|
||||
Polygon, Polyline2d, Rectangle, RegularPolygon, Segment2d, Triangle2d,
|
||||
use crate::{
|
||||
primitives::{
|
||||
BoxedPolygon, BoxedPolyline2d, Capsule2d, Circle, Ellipse, Line2d, Plane2d, Polygon,
|
||||
Polyline2d, Rectangle, RegularPolygon, Segment2d, Triangle2d,
|
||||
},
|
||||
Direction2d, Mat2, Vec2,
|
||||
};
|
||||
|
||||
use super::{Aabb2d, Bounded2d, BoundingCircle};
|
||||
|
@ -262,9 +263,10 @@ mod tests {
|
|||
use crate::{
|
||||
bounding::Bounded2d,
|
||||
primitives::{
|
||||
Capsule2d, Circle, Direction2d, Ellipse, Line2d, Plane2d, Polygon, Polyline2d,
|
||||
Rectangle, RegularPolygon, Segment2d, Triangle2d,
|
||||
Capsule2d, Circle, Ellipse, Line2d, Plane2d, Polygon, Polyline2d, Rectangle,
|
||||
RegularPolygon, Segment2d, Triangle2d,
|
||||
},
|
||||
Direction2d,
|
||||
};
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
//! Contains [`Bounded3d`] implementations for [geometric primitives](crate::primitives).
|
||||
|
||||
use glam::{Mat3, Quat, Vec2, Vec3};
|
||||
|
||||
use crate::{
|
||||
bounding::{Bounded2d, BoundingCircle},
|
||||
primitives::{
|
||||
BoxedPolyline3d, Capsule3d, Cone, ConicalFrustum, Cuboid, Cylinder, Direction3d, Line3d,
|
||||
Plane3d, Polyline3d, Segment3d, Sphere, Torus, Triangle2d,
|
||||
BoxedPolyline3d, Capsule3d, Cone, ConicalFrustum, Cuboid, Cylinder, Line3d, Plane3d,
|
||||
Polyline3d, Segment3d, Sphere, Torus, Triangle2d,
|
||||
},
|
||||
Direction3d, Mat3, Quat, Vec2, Vec3,
|
||||
};
|
||||
|
||||
use super::{Aabb3d, Bounded3d, BoundingSphere};
|
||||
|
@ -311,9 +310,10 @@ mod tests {
|
|||
use crate::{
|
||||
bounding::Bounded3d,
|
||||
primitives::{
|
||||
Capsule3d, Cone, ConicalFrustum, Cuboid, Cylinder, Direction3d, Line3d, Plane3d,
|
||||
Polyline3d, Segment3d, Sphere, Torus,
|
||||
Capsule3d, Cone, ConicalFrustum, Cuboid, Cylinder, Line3d, Plane3d, Polyline3d,
|
||||
Segment3d, Sphere, Torus,
|
||||
},
|
||||
Direction3d,
|
||||
};
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use super::{Aabb2d, BoundingCircle, IntersectsVolume};
|
||||
use crate::{primitives::Direction2d, Ray2d, Vec2};
|
||||
use crate::{Direction2d, Ray2d, Vec2};
|
||||
|
||||
/// A raycast intersection test for 2D bounding volumes
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use super::{Aabb3d, BoundingSphere, IntersectsVolume};
|
||||
use crate::{primitives::Direction3d, Ray3d, Vec3};
|
||||
use crate::{Direction3d, Ray3d, Vec3};
|
||||
|
||||
/// A raycast intersection test for 3D bounding volumes
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
532
crates/bevy_math/src/direction.rs
Normal file
532
crates/bevy_math/src/direction.rs
Normal file
|
@ -0,0 +1,532 @@
|
|||
use crate::{
|
||||
primitives::{Primitive2d, Primitive3d},
|
||||
Quat, Vec2, Vec3, Vec3A,
|
||||
};
|
||||
|
||||
/// An error indicating that a direction is invalid.
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum InvalidDirectionError {
|
||||
/// The length of the direction vector is zero or very close to zero.
|
||||
Zero,
|
||||
/// The length of the direction vector is `std::f32::INFINITY`.
|
||||
Infinite,
|
||||
/// The length of the direction vector is `NaN`.
|
||||
NaN,
|
||||
}
|
||||
|
||||
impl InvalidDirectionError {
|
||||
/// Creates an [`InvalidDirectionError`] from the length of an invalid direction vector.
|
||||
pub fn from_length(length: f32) -> Self {
|
||||
if length.is_nan() {
|
||||
InvalidDirectionError::NaN
|
||||
} else if !length.is_finite() {
|
||||
// If the direction is non-finite but also not NaN, it must be infinite
|
||||
InvalidDirectionError::Infinite
|
||||
} else {
|
||||
// If the direction is invalid but neither NaN nor infinite, it must be zero
|
||||
InvalidDirectionError::Zero
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for InvalidDirectionError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"Direction can not be zero (or very close to zero), or non-finite."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// A normalized vector pointing in a direction in 2D space
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct Direction2d(Vec2);
|
||||
impl Primitive2d for Direction2d {}
|
||||
|
||||
impl Direction2d {
|
||||
/// A unit vector pointing along the positive X axis.
|
||||
pub const X: Self = Self(Vec2::X);
|
||||
/// A unit vector pointing along the positive Y axis.
|
||||
pub const Y: Self = Self(Vec2::Y);
|
||||
/// A unit vector pointing along the negative X axis.
|
||||
pub const NEG_X: Self = Self(Vec2::NEG_X);
|
||||
/// A unit vector pointing along the negative Y axis.
|
||||
pub const NEG_Y: Self = Self(Vec2::NEG_Y);
|
||||
|
||||
/// Create a direction from a finite, nonzero [`Vec2`].
|
||||
///
|
||||
/// Returns [`Err(InvalidDirectionError)`](InvalidDirectionError) if the length
|
||||
/// of the given vector is zero (or very close to zero), infinite, or `NaN`.
|
||||
pub fn new(value: Vec2) -> Result<Self, InvalidDirectionError> {
|
||||
Self::new_and_length(value).map(|(dir, _)| dir)
|
||||
}
|
||||
|
||||
/// Create a [`Direction2d`] from a [`Vec2`] that is already normalized.
|
||||
///
|
||||
/// # Warning
|
||||
///
|
||||
/// `value` must be normalized, i.e it's length must be `1.0`.
|
||||
pub fn new_unchecked(value: Vec2) -> Self {
|
||||
debug_assert!(value.is_normalized());
|
||||
|
||||
Self(value)
|
||||
}
|
||||
|
||||
/// Create a direction from a finite, nonzero [`Vec2`], also returning its original length.
|
||||
///
|
||||
/// Returns [`Err(InvalidDirectionError)`](InvalidDirectionError) if the length
|
||||
/// of the given vector is zero (or very close to zero), infinite, or `NaN`.
|
||||
pub fn new_and_length(value: Vec2) -> Result<(Self, f32), InvalidDirectionError> {
|
||||
let length = value.length();
|
||||
let direction = (length.is_finite() && length > 0.0).then_some(value / length);
|
||||
|
||||
direction
|
||||
.map(|dir| (Self(dir), length))
|
||||
.ok_or(InvalidDirectionError::from_length(length))
|
||||
}
|
||||
|
||||
/// Create a direction from its `x` and `y` components.
|
||||
///
|
||||
/// Returns [`Err(InvalidDirectionError)`](InvalidDirectionError) if the length
|
||||
/// of the vector formed by the components is zero (or very close to zero), infinite, or `NaN`.
|
||||
pub fn from_xy(x: f32, y: f32) -> Result<Self, InvalidDirectionError> {
|
||||
Self::new(Vec2::new(x, y))
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Vec2> for Direction2d {
|
||||
type Error = InvalidDirectionError;
|
||||
|
||||
fn try_from(value: Vec2) -> Result<Self, Self::Error> {
|
||||
Self::new(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Deref for Direction2d {
|
||||
type Target = Vec2;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Neg for Direction2d {
|
||||
type Output = Self;
|
||||
fn neg(self) -> Self::Output {
|
||||
Self(-self.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "approx")]
|
||||
impl approx::AbsDiffEq for Direction2d {
|
||||
type Epsilon = f32;
|
||||
fn default_epsilon() -> f32 {
|
||||
f32::EPSILON
|
||||
}
|
||||
fn abs_diff_eq(&self, other: &Self, epsilon: f32) -> bool {
|
||||
self.as_ref().abs_diff_eq(other.as_ref(), epsilon)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "approx")]
|
||||
impl approx::RelativeEq for Direction2d {
|
||||
fn default_max_relative() -> f32 {
|
||||
f32::EPSILON
|
||||
}
|
||||
fn relative_eq(&self, other: &Self, epsilon: f32, max_relative: f32) -> bool {
|
||||
self.as_ref()
|
||||
.relative_eq(other.as_ref(), epsilon, max_relative)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "approx")]
|
||||
impl approx::UlpsEq for Direction2d {
|
||||
fn default_max_ulps() -> u32 {
|
||||
4
|
||||
}
|
||||
fn ulps_eq(&self, other: &Self, epsilon: f32, max_ulps: u32) -> bool {
|
||||
self.as_ref().ulps_eq(other.as_ref(), epsilon, max_ulps)
|
||||
}
|
||||
}
|
||||
|
||||
/// A normalized vector pointing in a direction in 3D space
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct Direction3d(Vec3);
|
||||
impl Primitive3d for Direction3d {}
|
||||
|
||||
impl Direction3d {
|
||||
/// A unit vector pointing along the positive X axis.
|
||||
pub const X: Self = Self(Vec3::X);
|
||||
/// A unit vector pointing along the positive Y axis.
|
||||
pub const Y: Self = Self(Vec3::Y);
|
||||
/// A unit vector pointing along the positive Z axis.
|
||||
pub const Z: Self = Self(Vec3::Z);
|
||||
/// A unit vector pointing along the negative X axis.
|
||||
pub const NEG_X: Self = Self(Vec3::NEG_X);
|
||||
/// A unit vector pointing along the negative Y axis.
|
||||
pub const NEG_Y: Self = Self(Vec3::NEG_Y);
|
||||
/// A unit vector pointing along the negative Z axis.
|
||||
pub const NEG_Z: Self = Self(Vec3::NEG_Z);
|
||||
|
||||
/// Create a direction from a finite, nonzero [`Vec3`].
|
||||
///
|
||||
/// Returns [`Err(InvalidDirectionError)`](InvalidDirectionError) if the length
|
||||
/// of the given vector is zero (or very close to zero), infinite, or `NaN`.
|
||||
pub fn new(value: Vec3) -> Result<Self, InvalidDirectionError> {
|
||||
Self::new_and_length(value).map(|(dir, _)| dir)
|
||||
}
|
||||
|
||||
/// Create a [`Direction3d`] from a [`Vec3`] that is already normalized.
|
||||
///
|
||||
/// # Warning
|
||||
///
|
||||
/// `value` must be normalized, i.e it's length must be `1.0`.
|
||||
pub fn new_unchecked(value: Vec3) -> Self {
|
||||
debug_assert!(value.is_normalized());
|
||||
|
||||
Self(value)
|
||||
}
|
||||
|
||||
/// Create a direction from a finite, nonzero [`Vec3`], also returning its original length.
|
||||
///
|
||||
/// Returns [`Err(InvalidDirectionError)`](InvalidDirectionError) if the length
|
||||
/// of the given vector is zero (or very close to zero), infinite, or `NaN`.
|
||||
pub fn new_and_length(value: Vec3) -> Result<(Self, f32), InvalidDirectionError> {
|
||||
let length = value.length();
|
||||
let direction = (length.is_finite() && length > 0.0).then_some(value / length);
|
||||
|
||||
direction
|
||||
.map(|dir| (Self(dir), length))
|
||||
.ok_or(InvalidDirectionError::from_length(length))
|
||||
}
|
||||
|
||||
/// Create a direction from its `x`, `y`, and `z` components.
|
||||
///
|
||||
/// Returns [`Err(InvalidDirectionError)`](InvalidDirectionError) if the length
|
||||
/// of the vector formed by the components is zero (or very close to zero), infinite, or `NaN`.
|
||||
pub fn from_xyz(x: f32, y: f32, z: f32) -> Result<Self, InvalidDirectionError> {
|
||||
Self::new(Vec3::new(x, y, z))
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Vec3> for Direction3d {
|
||||
type Error = InvalidDirectionError;
|
||||
|
||||
fn try_from(value: Vec3) -> Result<Self, Self::Error> {
|
||||
Self::new(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Direction3d> for Vec3 {
|
||||
fn from(value: Direction3d) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Deref for Direction3d {
|
||||
type Target = Vec3;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Neg for Direction3d {
|
||||
type Output = Self;
|
||||
fn neg(self) -> Self::Output {
|
||||
Self(-self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul<f32> for Direction3d {
|
||||
type Output = Vec3;
|
||||
fn mul(self, rhs: f32) -> Self::Output {
|
||||
self.0 * rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul<Direction3d> for Quat {
|
||||
type Output = Direction3d;
|
||||
|
||||
/// Rotates the [`Direction3d`] using a [`Quat`].
|
||||
fn mul(self, direction: Direction3d) -> Self::Output {
|
||||
let rotated = self * *direction;
|
||||
|
||||
// Make sure the result is normalized.
|
||||
// This can fail for non-unit quaternions.
|
||||
debug_assert!(rotated.is_normalized());
|
||||
|
||||
Direction3d::new_unchecked(rotated)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "approx")]
|
||||
impl approx::AbsDiffEq for Direction3d {
|
||||
type Epsilon = f32;
|
||||
fn default_epsilon() -> f32 {
|
||||
f32::EPSILON
|
||||
}
|
||||
fn abs_diff_eq(&self, other: &Self, epsilon: f32) -> bool {
|
||||
self.as_ref().abs_diff_eq(other.as_ref(), epsilon)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "approx")]
|
||||
impl approx::RelativeEq for Direction3d {
|
||||
fn default_max_relative() -> f32 {
|
||||
f32::EPSILON
|
||||
}
|
||||
fn relative_eq(&self, other: &Self, epsilon: f32, max_relative: f32) -> bool {
|
||||
self.as_ref()
|
||||
.relative_eq(other.as_ref(), epsilon, max_relative)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "approx")]
|
||||
impl approx::UlpsEq for Direction3d {
|
||||
fn default_max_ulps() -> u32 {
|
||||
4
|
||||
}
|
||||
fn ulps_eq(&self, other: &Self, epsilon: f32, max_ulps: u32) -> bool {
|
||||
self.as_ref().ulps_eq(other.as_ref(), epsilon, max_ulps)
|
||||
}
|
||||
}
|
||||
|
||||
/// A normalized SIMD vector pointing in a direction in 3D space.
|
||||
///
|
||||
/// This type stores a 16 byte aligned [`Vec3A`].
|
||||
/// This may or may not be faster than [`Direction3d`]: make sure to benchmark!
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct Direction3dA(Vec3A);
|
||||
impl Primitive3d for Direction3dA {}
|
||||
|
||||
impl Direction3dA {
|
||||
/// A unit vector pointing along the positive X axis.
|
||||
pub const X: Self = Self(Vec3A::X);
|
||||
/// A unit vector pointing along the positive Y axis.
|
||||
pub const Y: Self = Self(Vec3A::Y);
|
||||
/// A unit vector pointing along the positive Z axis.
|
||||
pub const Z: Self = Self(Vec3A::Z);
|
||||
/// A unit vector pointing along the negative X axis.
|
||||
pub const NEG_X: Self = Self(Vec3A::NEG_X);
|
||||
/// A unit vector pointing along the negative Y axis.
|
||||
pub const NEG_Y: Self = Self(Vec3A::NEG_Y);
|
||||
/// A unit vector pointing along the negative Z axis.
|
||||
pub const NEG_Z: Self = Self(Vec3A::NEG_Z);
|
||||
|
||||
/// Create a direction from a finite, nonzero [`Vec3A`].
|
||||
///
|
||||
/// Returns [`Err(InvalidDirectionError)`](InvalidDirectionError) if the length
|
||||
/// of the given vector is zero (or very close to zero), infinite, or `NaN`.
|
||||
pub fn new(value: Vec3A) -> Result<Self, InvalidDirectionError> {
|
||||
Self::new_and_length(value).map(|(dir, _)| dir)
|
||||
}
|
||||
|
||||
/// Create a [`Direction3dA`] from a [`Vec3A`] that is already normalized.
|
||||
///
|
||||
/// # Warning
|
||||
///
|
||||
/// `value` must be normalized, i.e it's length must be `1.0`.
|
||||
pub fn new_unchecked(value: Vec3A) -> Self {
|
||||
debug_assert!(value.is_normalized());
|
||||
|
||||
Self(value)
|
||||
}
|
||||
|
||||
/// Create a direction from a finite, nonzero [`Vec3A`], also returning its original length.
|
||||
///
|
||||
/// Returns [`Err(InvalidDirectionError)`](InvalidDirectionError) if the length
|
||||
/// of the given vector is zero (or very close to zero), infinite, or `NaN`.
|
||||
pub fn new_and_length(value: Vec3A) -> Result<(Self, f32), InvalidDirectionError> {
|
||||
let length = value.length();
|
||||
let direction = (length.is_finite() && length > 0.0).then_some(value / length);
|
||||
|
||||
direction
|
||||
.map(|dir| (Self(dir), length))
|
||||
.ok_or(InvalidDirectionError::from_length(length))
|
||||
}
|
||||
|
||||
/// Create a direction from its `x`, `y`, and `z` components.
|
||||
///
|
||||
/// Returns [`Err(InvalidDirectionError)`](InvalidDirectionError) if the length
|
||||
/// of the vector formed by the components is zero (or very close to zero), infinite, or `NaN`.
|
||||
pub fn from_xyz(x: f32, y: f32, z: f32) -> Result<Self, InvalidDirectionError> {
|
||||
Self::new(Vec3A::new(x, y, z))
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Vec3A> for Direction3dA {
|
||||
type Error = InvalidDirectionError;
|
||||
|
||||
fn try_from(value: Vec3A) -> Result<Self, Self::Error> {
|
||||
Self::new(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Direction3dA> for Vec3A {
|
||||
fn from(value: Direction3dA) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Deref for Direction3dA {
|
||||
type Target = Vec3A;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Neg for Direction3dA {
|
||||
type Output = Self;
|
||||
fn neg(self) -> Self::Output {
|
||||
Self(-self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul<f32> for Direction3dA {
|
||||
type Output = Vec3A;
|
||||
fn mul(self, rhs: f32) -> Self::Output {
|
||||
self.0 * rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul<Direction3dA> for Quat {
|
||||
type Output = Direction3dA;
|
||||
|
||||
/// Rotates the [`Direction3dA`] using a [`Quat`].
|
||||
fn mul(self, direction: Direction3dA) -> Self::Output {
|
||||
let rotated = self * *direction;
|
||||
|
||||
// Make sure the result is normalized.
|
||||
// This can fail for non-unit quaternions.
|
||||
debug_assert!(rotated.is_normalized());
|
||||
|
||||
Direction3dA::new_unchecked(rotated)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "approx")]
|
||||
impl approx::AbsDiffEq for Direction3dA {
|
||||
type Epsilon = f32;
|
||||
fn default_epsilon() -> f32 {
|
||||
f32::EPSILON
|
||||
}
|
||||
fn abs_diff_eq(&self, other: &Self, epsilon: f32) -> bool {
|
||||
self.as_ref().abs_diff_eq(other.as_ref(), epsilon)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "approx")]
|
||||
impl approx::RelativeEq for Direction3dA {
|
||||
fn default_max_relative() -> f32 {
|
||||
f32::EPSILON
|
||||
}
|
||||
fn relative_eq(&self, other: &Self, epsilon: f32, max_relative: f32) -> bool {
|
||||
self.as_ref()
|
||||
.relative_eq(other.as_ref(), epsilon, max_relative)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "approx")]
|
||||
impl approx::UlpsEq for Direction3dA {
|
||||
fn default_max_ulps() -> u32 {
|
||||
4
|
||||
}
|
||||
fn ulps_eq(&self, other: &Self, epsilon: f32, max_ulps: u32) -> bool {
|
||||
self.as_ref().ulps_eq(other.as_ref(), epsilon, max_ulps)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::InvalidDirectionError;
|
||||
|
||||
#[test]
|
||||
fn dir2_creation() {
|
||||
assert_eq!(Direction2d::new(Vec2::X * 12.5), Ok(Direction2d::X));
|
||||
assert_eq!(
|
||||
Direction2d::new(Vec2::new(0.0, 0.0)),
|
||||
Err(InvalidDirectionError::Zero)
|
||||
);
|
||||
assert_eq!(
|
||||
Direction2d::new(Vec2::new(f32::INFINITY, 0.0)),
|
||||
Err(InvalidDirectionError::Infinite)
|
||||
);
|
||||
assert_eq!(
|
||||
Direction2d::new(Vec2::new(f32::NEG_INFINITY, 0.0)),
|
||||
Err(InvalidDirectionError::Infinite)
|
||||
);
|
||||
assert_eq!(
|
||||
Direction2d::new(Vec2::new(f32::NAN, 0.0)),
|
||||
Err(InvalidDirectionError::NaN)
|
||||
);
|
||||
assert_eq!(
|
||||
Direction2d::new_and_length(Vec2::X * 6.5),
|
||||
Ok((Direction2d::X, 6.5))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dir3_creation() {
|
||||
assert_eq!(Direction3d::new(Vec3::X * 12.5), Ok(Direction3d::X));
|
||||
assert_eq!(
|
||||
Direction3d::new(Vec3::new(0.0, 0.0, 0.0)),
|
||||
Err(InvalidDirectionError::Zero)
|
||||
);
|
||||
assert_eq!(
|
||||
Direction3d::new(Vec3::new(f32::INFINITY, 0.0, 0.0)),
|
||||
Err(InvalidDirectionError::Infinite)
|
||||
);
|
||||
assert_eq!(
|
||||
Direction3d::new(Vec3::new(f32::NEG_INFINITY, 0.0, 0.0)),
|
||||
Err(InvalidDirectionError::Infinite)
|
||||
);
|
||||
assert_eq!(
|
||||
Direction3d::new(Vec3::new(f32::NAN, 0.0, 0.0)),
|
||||
Err(InvalidDirectionError::NaN)
|
||||
);
|
||||
assert_eq!(
|
||||
Direction3d::new_and_length(Vec3::X * 6.5),
|
||||
Ok((Direction3d::X, 6.5))
|
||||
);
|
||||
|
||||
// Test rotation
|
||||
assert!(
|
||||
(Quat::from_rotation_z(std::f32::consts::FRAC_PI_2) * Direction3d::X)
|
||||
.abs_diff_eq(Vec3::Y, 10e-6)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dir3a_creation() {
|
||||
assert_eq!(Direction3dA::new(Vec3A::X * 12.5), Ok(Direction3dA::X));
|
||||
assert_eq!(
|
||||
Direction3dA::new(Vec3A::new(0.0, 0.0, 0.0)),
|
||||
Err(InvalidDirectionError::Zero)
|
||||
);
|
||||
assert_eq!(
|
||||
Direction3dA::new(Vec3A::new(f32::INFINITY, 0.0, 0.0)),
|
||||
Err(InvalidDirectionError::Infinite)
|
||||
);
|
||||
assert_eq!(
|
||||
Direction3dA::new(Vec3A::new(f32::NEG_INFINITY, 0.0, 0.0)),
|
||||
Err(InvalidDirectionError::Infinite)
|
||||
);
|
||||
assert_eq!(
|
||||
Direction3dA::new(Vec3A::new(f32::NAN, 0.0, 0.0)),
|
||||
Err(InvalidDirectionError::NaN)
|
||||
);
|
||||
assert_eq!(
|
||||
Direction3dA::new_and_length(Vec3A::X * 6.5),
|
||||
Ok((Direction3dA::X, 6.5))
|
||||
);
|
||||
|
||||
// Test rotation
|
||||
assert!(
|
||||
(Quat::from_rotation_z(std::f32::consts::FRAC_PI_2) * Direction3dA::X)
|
||||
.abs_diff_eq(Vec3A::Y, 10e-6)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -8,12 +8,14 @@ mod affine3;
|
|||
mod aspect_ratio;
|
||||
pub mod bounding;
|
||||
pub mod cubic_splines;
|
||||
mod direction;
|
||||
pub mod primitives;
|
||||
mod ray;
|
||||
mod rects;
|
||||
|
||||
pub use affine3::*;
|
||||
pub use aspect_ratio::AspectRatio;
|
||||
pub use direction::*;
|
||||
pub use ray::{Ray2d, Ray3d};
|
||||
pub use rects::*;
|
||||
|
||||
|
@ -25,6 +27,7 @@ pub mod prelude {
|
|||
CubicBSpline, CubicBezier, CubicCardinalSpline, CubicGenerator, CubicHermite,
|
||||
CubicSegment,
|
||||
},
|
||||
direction::{Direction2d, Direction3d, Direction3dA},
|
||||
primitives::*,
|
||||
BVec2, BVec3, BVec4, EulerRot, FloatExt, IRect, IVec2, IVec3, IVec4, Mat2, Mat3, Mat4,
|
||||
Quat, Ray2d, Ray3d, Rect, URect, UVec2, UVec3, UVec4, Vec2, Vec2Swizzles, Vec3,
|
||||
|
|
|
@ -1,118 +1,7 @@
|
|||
use std::f32::consts::PI;
|
||||
|
||||
use super::{InvalidDirectionError, Primitive2d, WindingOrder};
|
||||
use crate::Vec2;
|
||||
|
||||
/// A normalized vector pointing in a direction in 2D space
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct Direction2d(Vec2);
|
||||
impl Primitive2d for Direction2d {}
|
||||
|
||||
impl Direction2d {
|
||||
/// A unit vector pointing along the positive X axis.
|
||||
pub const X: Self = Self(Vec2::X);
|
||||
/// A unit vector pointing along the positive Y axis.
|
||||
pub const Y: Self = Self(Vec2::Y);
|
||||
/// A unit vector pointing along the negative X axis.
|
||||
pub const NEG_X: Self = Self(Vec2::NEG_X);
|
||||
/// A unit vector pointing along the negative Y axis.
|
||||
pub const NEG_Y: Self = Self(Vec2::NEG_Y);
|
||||
|
||||
/// Create a direction from a finite, nonzero [`Vec2`].
|
||||
///
|
||||
/// Returns [`Err(InvalidDirectionError)`](InvalidDirectionError) if the length
|
||||
/// of the given vector is zero (or very close to zero), infinite, or `NaN`.
|
||||
pub fn new(value: Vec2) -> Result<Self, InvalidDirectionError> {
|
||||
Self::new_and_length(value).map(|(dir, _)| dir)
|
||||
}
|
||||
|
||||
/// Create a [`Direction2d`] from a [`Vec2`] that is already normalized.
|
||||
///
|
||||
/// # Warning
|
||||
///
|
||||
/// `value` must be normalized, i.e it's length must be `1.0`.
|
||||
pub fn new_unchecked(value: Vec2) -> Self {
|
||||
debug_assert!(value.is_normalized());
|
||||
|
||||
Self(value)
|
||||
}
|
||||
|
||||
/// Create a direction from a finite, nonzero [`Vec2`], also returning its original length.
|
||||
///
|
||||
/// Returns [`Err(InvalidDirectionError)`](InvalidDirectionError) if the length
|
||||
/// of the given vector is zero (or very close to zero), infinite, or `NaN`.
|
||||
pub fn new_and_length(value: Vec2) -> Result<(Self, f32), InvalidDirectionError> {
|
||||
let length = value.length();
|
||||
let direction = (length.is_finite() && length > 0.0).then_some(value / length);
|
||||
|
||||
direction
|
||||
.map(|dir| (Self(dir), length))
|
||||
.ok_or(InvalidDirectionError::from_length(length))
|
||||
}
|
||||
|
||||
/// Create a direction from its `x` and `y` components.
|
||||
///
|
||||
/// Returns [`Err(InvalidDirectionError)`](InvalidDirectionError) if the length
|
||||
/// of the vector formed by the components is zero (or very close to zero), infinite, or `NaN`.
|
||||
pub fn from_xy(x: f32, y: f32) -> Result<Self, InvalidDirectionError> {
|
||||
Self::new(Vec2::new(x, y))
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Vec2> for Direction2d {
|
||||
type Error = InvalidDirectionError;
|
||||
|
||||
fn try_from(value: Vec2) -> Result<Self, Self::Error> {
|
||||
Self::new(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Deref for Direction2d {
|
||||
type Target = Vec2;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Neg for Direction2d {
|
||||
type Output = Self;
|
||||
fn neg(self) -> Self::Output {
|
||||
Self(-self.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "approx")]
|
||||
impl approx::AbsDiffEq for Direction2d {
|
||||
type Epsilon = f32;
|
||||
fn default_epsilon() -> f32 {
|
||||
f32::EPSILON
|
||||
}
|
||||
fn abs_diff_eq(&self, other: &Self, epsilon: f32) -> bool {
|
||||
self.as_ref().abs_diff_eq(other.as_ref(), epsilon)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "approx")]
|
||||
impl approx::RelativeEq for Direction2d {
|
||||
fn default_max_relative() -> f32 {
|
||||
f32::EPSILON
|
||||
}
|
||||
fn relative_eq(&self, other: &Self, epsilon: f32, max_relative: f32) -> bool {
|
||||
self.as_ref()
|
||||
.relative_eq(other.as_ref(), epsilon, max_relative)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "approx")]
|
||||
impl approx::UlpsEq for Direction2d {
|
||||
fn default_max_ulps() -> u32 {
|
||||
4
|
||||
}
|
||||
fn ulps_eq(&self, other: &Self, epsilon: f32, max_ulps: u32) -> bool {
|
||||
self.as_ref().ulps_eq(other.as_ref(), epsilon, max_ulps)
|
||||
}
|
||||
}
|
||||
use super::{Primitive2d, WindingOrder};
|
||||
use crate::{Direction2d, Vec2};
|
||||
|
||||
/// A circle primitive
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
|
@ -806,31 +695,6 @@ mod tests {
|
|||
use super::*;
|
||||
use approx::assert_relative_eq;
|
||||
|
||||
#[test]
|
||||
fn direction_creation() {
|
||||
assert_eq!(Direction2d::new(Vec2::X * 12.5), Ok(Direction2d::X));
|
||||
assert_eq!(
|
||||
Direction2d::new(Vec2::new(0.0, 0.0)),
|
||||
Err(InvalidDirectionError::Zero)
|
||||
);
|
||||
assert_eq!(
|
||||
Direction2d::new(Vec2::new(f32::INFINITY, 0.0)),
|
||||
Err(InvalidDirectionError::Infinite)
|
||||
);
|
||||
assert_eq!(
|
||||
Direction2d::new(Vec2::new(f32::NEG_INFINITY, 0.0)),
|
||||
Err(InvalidDirectionError::Infinite)
|
||||
);
|
||||
assert_eq!(
|
||||
Direction2d::new(Vec2::new(f32::NAN, 0.0)),
|
||||
Err(InvalidDirectionError::NaN)
|
||||
);
|
||||
assert_eq!(
|
||||
Direction2d::new_and_length(Vec2::X * 6.5),
|
||||
Ok((Direction2d::X, 6.5))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rectangle_closest_point() {
|
||||
let rectangle = Rectangle::new(2.0, 2.0);
|
||||
|
|
|
@ -1,150 +1,7 @@
|
|||
use std::f32::consts::{FRAC_PI_3, PI};
|
||||
|
||||
use super::{Circle, InvalidDirectionError, Primitive3d};
|
||||
use crate::{Quat, Vec3};
|
||||
|
||||
/// A normalized vector pointing in a direction in 3D space
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct Direction3d(Vec3);
|
||||
impl Primitive3d for Direction3d {}
|
||||
|
||||
impl Direction3d {
|
||||
/// A unit vector pointing along the positive X axis.
|
||||
pub const X: Self = Self(Vec3::X);
|
||||
/// A unit vector pointing along the positive Y axis.
|
||||
pub const Y: Self = Self(Vec3::Y);
|
||||
/// A unit vector pointing along the positive Z axis.
|
||||
pub const Z: Self = Self(Vec3::Z);
|
||||
/// A unit vector pointing along the negative X axis.
|
||||
pub const NEG_X: Self = Self(Vec3::NEG_X);
|
||||
/// A unit vector pointing along the negative Y axis.
|
||||
pub const NEG_Y: Self = Self(Vec3::NEG_Y);
|
||||
/// A unit vector pointing along the negative Z axis.
|
||||
pub const NEG_Z: Self = Self(Vec3::NEG_Z);
|
||||
|
||||
/// Create a direction from a finite, nonzero [`Vec3`].
|
||||
///
|
||||
/// Returns [`Err(InvalidDirectionError)`](InvalidDirectionError) if the length
|
||||
/// of the given vector is zero (or very close to zero), infinite, or `NaN`.
|
||||
pub fn new(value: Vec3) -> Result<Self, InvalidDirectionError> {
|
||||
Self::new_and_length(value).map(|(dir, _)| dir)
|
||||
}
|
||||
|
||||
/// Create a [`Direction3d`] from a [`Vec3`] that is already normalized.
|
||||
///
|
||||
/// # Warning
|
||||
///
|
||||
/// `value` must be normalized, i.e it's length must be `1.0`.
|
||||
pub fn new_unchecked(value: Vec3) -> Self {
|
||||
debug_assert!(value.is_normalized());
|
||||
|
||||
Self(value)
|
||||
}
|
||||
|
||||
/// Create a direction from a finite, nonzero [`Vec3`], also returning its original length.
|
||||
///
|
||||
/// Returns [`Err(InvalidDirectionError)`](InvalidDirectionError) if the length
|
||||
/// of the given vector is zero (or very close to zero), infinite, or `NaN`.
|
||||
pub fn new_and_length(value: Vec3) -> Result<(Self, f32), InvalidDirectionError> {
|
||||
let length = value.length();
|
||||
let direction = (length.is_finite() && length > 0.0).then_some(value / length);
|
||||
|
||||
direction
|
||||
.map(|dir| (Self(dir), length))
|
||||
.ok_or(InvalidDirectionError::from_length(length))
|
||||
}
|
||||
|
||||
/// Create a direction from its `x`, `y`, and `z` components.
|
||||
///
|
||||
/// Returns [`Err(InvalidDirectionError)`](InvalidDirectionError) if the length
|
||||
/// of the vector formed by the components is zero (or very close to zero), infinite, or `NaN`.
|
||||
pub fn from_xyz(x: f32, y: f32, z: f32) -> Result<Self, InvalidDirectionError> {
|
||||
Self::new(Vec3::new(x, y, z))
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Vec3> for Direction3d {
|
||||
type Error = InvalidDirectionError;
|
||||
|
||||
fn try_from(value: Vec3) -> Result<Self, Self::Error> {
|
||||
Self::new(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Direction3d> for Vec3 {
|
||||
fn from(value: Direction3d) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Deref for Direction3d {
|
||||
type Target = Vec3;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Neg for Direction3d {
|
||||
type Output = Self;
|
||||
fn neg(self) -> Self::Output {
|
||||
Self(-self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul<f32> for Direction3d {
|
||||
type Output = Vec3;
|
||||
fn mul(self, rhs: f32) -> Self::Output {
|
||||
self.0 * rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul<Direction3d> for Quat {
|
||||
type Output = Direction3d;
|
||||
|
||||
/// Rotates the [`Direction3d`] using a [`Quat`].
|
||||
fn mul(self, direction: Direction3d) -> Self::Output {
|
||||
let rotated = self * *direction;
|
||||
|
||||
// Make sure the result is normalized.
|
||||
// This can fail for non-unit quaternions.
|
||||
debug_assert!(rotated.is_normalized());
|
||||
|
||||
Direction3d::new_unchecked(rotated)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "approx")]
|
||||
impl approx::AbsDiffEq for Direction3d {
|
||||
type Epsilon = f32;
|
||||
fn default_epsilon() -> f32 {
|
||||
f32::EPSILON
|
||||
}
|
||||
fn abs_diff_eq(&self, other: &Self, epsilon: f32) -> bool {
|
||||
self.as_ref().abs_diff_eq(other.as_ref(), epsilon)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "approx")]
|
||||
impl approx::RelativeEq for Direction3d {
|
||||
fn default_max_relative() -> f32 {
|
||||
f32::EPSILON
|
||||
}
|
||||
fn relative_eq(&self, other: &Self, epsilon: f32, max_relative: f32) -> bool {
|
||||
self.as_ref()
|
||||
.relative_eq(other.as_ref(), epsilon, max_relative)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "approx")]
|
||||
impl approx::UlpsEq for Direction3d {
|
||||
fn default_max_ulps() -> u32 {
|
||||
4
|
||||
}
|
||||
fn ulps_eq(&self, other: &Self, epsilon: f32, max_ulps: u32) -> bool {
|
||||
self.as_ref().ulps_eq(other.as_ref(), epsilon, max_ulps)
|
||||
}
|
||||
}
|
||||
use super::{Circle, Primitive3d};
|
||||
use crate::{Direction3d, Vec3};
|
||||
|
||||
/// A sphere primitive
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
|
@ -779,6 +636,7 @@ mod tests {
|
|||
// Reference values were computed by hand and/or with external tools
|
||||
|
||||
use super::*;
|
||||
use crate::{InvalidDirectionError, Quat};
|
||||
use approx::assert_relative_eq;
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -15,41 +15,6 @@ pub trait Primitive2d {}
|
|||
/// A marker trait for 3D primitives
|
||||
pub trait Primitive3d {}
|
||||
|
||||
/// An error indicating that a direction is invalid.
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum InvalidDirectionError {
|
||||
/// The length of the direction vector is zero or very close to zero.
|
||||
Zero,
|
||||
/// The length of the direction vector is `std::f32::INFINITY`.
|
||||
Infinite,
|
||||
/// The length of the direction vector is `NaN`.
|
||||
NaN,
|
||||
}
|
||||
|
||||
impl InvalidDirectionError {
|
||||
/// Creates an [`InvalidDirectionError`] from the length of an invalid direction vector.
|
||||
pub fn from_length(length: f32) -> Self {
|
||||
if length.is_nan() {
|
||||
InvalidDirectionError::NaN
|
||||
} else if !length.is_finite() {
|
||||
// If the direction is non-finite but also not NaN, it must be infinite
|
||||
InvalidDirectionError::Infinite
|
||||
} else {
|
||||
// If the direction is invalid but neither NaN nor infinite, it must be zero
|
||||
InvalidDirectionError::Zero
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for InvalidDirectionError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"Direction can not be zero (or very close to zero), or non-finite."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// The winding order for a set of points
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum WindingOrder {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
primitives::{Direction2d, Direction3d, Plane2d, Plane3d},
|
||||
Vec2, Vec3,
|
||||
primitives::{Plane2d, Plane3d},
|
||||
Direction2d, Direction3d, Vec2, Vec3,
|
||||
};
|
||||
|
||||
/// An infinite half-line starting at `origin` and going in `direction` in 2D space.
|
||||
|
|
22
crates/bevy_reflect/src/impls/math/direction.rs
Normal file
22
crates/bevy_reflect/src/impls/math/direction.rs
Normal file
|
@ -0,0 +1,22 @@
|
|||
use crate as bevy_reflect;
|
||||
use crate::{ReflectDeserialize, ReflectSerialize};
|
||||
use bevy_reflect_derive::impl_reflect_value;
|
||||
|
||||
impl_reflect_value!(::bevy_math::Direction2d(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Serialize,
|
||||
Deserialize
|
||||
));
|
||||
impl_reflect_value!(::bevy_math::Direction3d(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Serialize,
|
||||
Deserialize
|
||||
));
|
||||
impl_reflect_value!(::bevy_math::Direction3dA(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Serialize,
|
||||
Deserialize
|
||||
));
|
|
@ -1,14 +1,7 @@
|
|||
use crate as bevy_reflect;
|
||||
use crate::{ReflectDeserialize, ReflectSerialize};
|
||||
use bevy_math::{primitives::*, Vec2};
|
||||
use bevy_reflect_derive::{impl_reflect, impl_reflect_value};
|
||||
|
||||
impl_reflect_value!(::bevy_math::primitives::Direction2d(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Serialize,
|
||||
Deserialize
|
||||
));
|
||||
use bevy_math::{primitives::*, Direction2d, Vec2};
|
||||
use bevy_reflect_derive::impl_reflect;
|
||||
|
||||
impl_reflect!(
|
||||
#[reflect(Debug, PartialEq, Serialize, Deserialize)]
|
||||
|
|
|
@ -1,14 +1,7 @@
|
|||
use crate as bevy_reflect;
|
||||
use crate::{ReflectDeserialize, ReflectSerialize};
|
||||
use bevy_math::{primitives::*, Vec3};
|
||||
use bevy_reflect_derive::{impl_reflect, impl_reflect_value};
|
||||
|
||||
impl_reflect_value!(::bevy_math::primitives::Direction3d(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Serialize,
|
||||
Deserialize
|
||||
));
|
||||
use bevy_math::{primitives::*, Direction3d, Vec3};
|
||||
use bevy_reflect_derive::impl_reflect;
|
||||
|
||||
impl_reflect!(
|
||||
#[reflect(Debug, PartialEq, Serialize, Deserialize)]
|
||||
|
|
|
@ -486,6 +486,7 @@ mod impls {
|
|||
mod glam;
|
||||
#[cfg(feature = "bevy_math")]
|
||||
mod math {
|
||||
mod direction;
|
||||
mod primitives2d;
|
||||
mod primitives3d;
|
||||
mod rect;
|
||||
|
|
|
@ -21,9 +21,7 @@ use bevy_ecs::{
|
|||
system::{Commands, Query, Res, ResMut, Resource},
|
||||
};
|
||||
use bevy_log::warn;
|
||||
use bevy_math::{
|
||||
primitives::Direction3d, vec2, Mat4, Ray3d, Rect, URect, UVec2, UVec4, Vec2, Vec3,
|
||||
};
|
||||
use bevy_math::{vec2, Direction3d, Mat4, Ray3d, Rect, URect, UVec2, UVec4, Vec2, Vec3};
|
||||
use bevy_reflect::prelude::*;
|
||||
use bevy_render_macros::ExtractComponent;
|
||||
use bevy_transform::components::GlobalTransform;
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
use bevy_math::{
|
||||
primitives::{Direction3d, Plane3d},
|
||||
Quat, Vec2, Vec3,
|
||||
};
|
||||
use bevy_math::{primitives::Plane3d, Direction3d, Quat, Vec2, Vec3};
|
||||
use wgpu::PrimitiveTopology;
|
||||
|
||||
use crate::{
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use super::GlobalTransform;
|
||||
use bevy_ecs::{component::Component, reflect::ReflectComponent};
|
||||
use bevy_math::primitives::Direction3d;
|
||||
use bevy_math::{Affine3A, Mat3, Mat4, Quat, Vec3};
|
||||
use bevy_math::{Affine3A, Direction3d, Mat3, Mat4, Quat, Vec3};
|
||||
use bevy_reflect::prelude::*;
|
||||
use bevy_reflect::Reflect;
|
||||
use std::ops::Mul;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! This example demonstrates how to use the `Camera::viewport_to_world` method.
|
||||
|
||||
use bevy::math::primitives::Direction3d;
|
||||
use bevy::math::Direction3d;
|
||||
use bevy::prelude::*;
|
||||
|
||||
fn main() {
|
||||
|
|
Loading…
Reference in a new issue