use crate::{
bindings::prelude::*,
scalar::{FloatScalar, SignedScalar},
AsRaw, FromRaw, Scalar, ToRaw, Unit, Vector2, Vector3, Vector4,
};
use core::ops::Mul;
#[repr(C)]
#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(bound = ""))]
pub struct Point2<T: Unit = f32> {
pub x: T::Scalar,
pub y: T::Scalar,
}
unsafe impl<T: Unit> bytemuck::Zeroable for Point2<T> {}
unsafe impl<T: Unit> bytemuck::Pod for Point2<T> {}
#[repr(C)]
#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(bound = ""))]
pub struct Point3<T: Unit = f32> {
pub x: T::Scalar,
pub y: T::Scalar,
pub z: T::Scalar,
}
unsafe impl<T: Unit> bytemuck::Zeroable for Point3<T> {}
unsafe impl<T: Unit> bytemuck::Pod for Point3<T> {}
#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(bound = ""))]
#[cfg_attr(
any(
not(any(feature = "scalar-math", target_arch = "spirv")),
feature = "cuda"
),
repr(C, align(16))
)]
pub struct Point4<T: Unit = f32> {
pub x: T::Scalar,
pub y: T::Scalar,
pub z: T::Scalar,
pub w: T::Scalar,
}
unsafe impl<T: Unit> bytemuck::Zeroable for Point4<T> {}
unsafe impl<T: Unit> bytemuck::Pod for Point4<T> {}
macro_rules! point_interface {
($base_type_name:ident, $vector_type:ident) => {
#[inline]
pub fn from_vector(vec: $vector_type<T>) -> Self {
vec.into()
}
#[inline]
pub fn to_vector(self) -> $vector_type<T> {
self.into()
}
#[doc = "Reinterpret as vector."]
#[inline]
pub fn as_vector(&self) -> &$vector_type<T> {
bytemuck::cast_ref(self)
}
#[doc = "Reinterpret as vector."]
#[inline]
pub fn as_vector_mut(&mut self) -> &mut $vector_type<T> {
bytemuck::cast_mut(self)
}
#[inline]
#[must_use]
pub fn translate(self, by: $vector_type<T>) -> Self {
self + by
}
};
}
macro_rules! float_point_interface {
($see_also_doc_ty:ty) => {
crate::forward_to_raw!(
$see_also_doc_ty =>
#[doc = "Distance"]
pub fn distance(self, other: Self) -> T::Scalar;
#[doc = "Distance squared"]
pub fn distance_squared(self, other: Self) -> T::Scalar;
);
};
}
crate::forward_op_to_raw!(Point2, Add<Vector2<T>>::add -> Self);
crate::forward_op_to_raw!(Point3, Add<Vector3<T>>::add -> Self);
crate::forward_op_to_raw!(Point4, Add<Vector4<T>>::add -> Self);
crate::forward_op_to_raw!(Point2, Sub<Vector2<T>>::sub -> Self);
crate::forward_op_to_raw!(Point3, Sub<Vector3<T>>::sub -> Self);
crate::forward_op_to_raw!(Point4, Sub<Vector4<T>>::sub -> Self);
crate::forward_op_to_raw!(Point2, Sub<Self>::sub -> Vector2<T>);
crate::forward_op_to_raw!(Point3, Sub<Self>::sub -> Vector3<T>);
crate::forward_op_to_raw!(Point4, Sub<Self>::sub -> Vector4<T>);
crate::forward_neg_to_raw!(Point2);
crate::forward_neg_to_raw!(Point3);
crate::forward_neg_to_raw!(Point4);
crate::forward_op_assign_to_raw!(Point2, AddAssign<Vector2<T>>::add_assign);
crate::forward_op_assign_to_raw!(Point3, AddAssign<Vector3<T>>::add_assign);
crate::forward_op_assign_to_raw!(Point4, AddAssign<Vector4<T>>::add_assign);
crate::forward_op_assign_to_raw!(Point2, SubAssign<Vector2<T>>::sub_assign);
crate::forward_op_assign_to_raw!(Point3, SubAssign<Vector3<T>>::sub_assign);
crate::forward_op_assign_to_raw!(Point4, SubAssign<Vector4<T>>::sub_assign);
crate::derive_standard_traits!(Point2 {
x: T::Scalar,
y: T::Scalar
});
crate::derive_standard_traits!(Point3 {
x: T::Scalar,
y: T::Scalar,
z: T::Scalar
});
crate::derive_standard_traits!(Point4 {
x: T::Scalar,
y: T::Scalar,
z: T::Scalar,
w: T::Scalar
});
crate::derive_array_conversion_traits!(Point2, 2);
crate::derive_array_conversion_traits!(Point3, 3);
crate::derive_array_conversion_traits!(Point4, 4);
crate::derive_tuple_conversion_traits!(Point2 {
x: T::Scalar,
y: T::Scalar
});
crate::derive_tuple_conversion_traits!(Point3 {
x: T::Scalar,
y: T::Scalar,
z: T::Scalar
});
crate::derive_tuple_conversion_traits!(Point4 {
x: T::Scalar,
y: T::Scalar,
z: T::Scalar,
w: T::Scalar
});
crate::derive_glam_conversion_traits!(Point2 {
x: T::Scalar,
y: T::Scalar
});
crate::derive_glam_conversion_traits!(Point3 {
x: T::Scalar,
y: T::Scalar,
z: T::Scalar
});
crate::derive_glam_conversion_traits!(Point4 {
x: T::Scalar,
y: T::Scalar,
z: T::Scalar,
w: T::Scalar
});
impl<T: Unit> ToRaw for Point2<T> {
type Raw = <T::Scalar as Scalar>::Vec2;
fn to_raw(self) -> Self::Raw {
bytemuck::cast(self)
}
}
impl<T: Unit> FromRaw for Point2<T> {
fn from_raw(raw: Self::Raw) -> Self {
bytemuck::cast(raw)
}
}
impl<T: Unit> AsRaw for Point2<T> {
fn as_raw(&self) -> &Self::Raw {
bytemuck::cast_ref(self)
}
fn as_raw_mut(&mut self) -> &mut Self::Raw {
bytemuck::cast_mut(self)
}
}
impl<T: Unit> ToRaw for Point3<T> {
type Raw = <T::Scalar as Scalar>::Vec3;
fn to_raw(self) -> Self::Raw {
bytemuck::cast(self)
}
}
impl<T: Unit> FromRaw for Point3<T> {
fn from_raw(raw: Self::Raw) -> Self {
bytemuck::cast(raw)
}
}
impl<T: Unit> AsRaw for Point3<T> {
fn as_raw(&self) -> &Self::Raw {
bytemuck::cast_ref(self)
}
fn as_raw_mut(&mut self) -> &mut Self::Raw {
bytemuck::cast_mut(self)
}
}
impl<T: Unit> ToRaw for Point4<T> {
type Raw = <T::Scalar as Scalar>::Vec4;
fn to_raw(self) -> Self::Raw {
bytemuck::cast(self)
}
}
impl<T: Unit> FromRaw for Point4<T> {
fn from_raw(raw: Self::Raw) -> Self {
bytemuck::cast(raw)
}
}
impl<T: Unit> AsRaw for Point4<T> {
fn as_raw(&self) -> &Self::Raw {
bytemuck::cast_ref(self)
}
fn as_raw_mut(&mut self) -> &mut Self::Raw {
bytemuck::cast_mut(self)
}
}
impl<T: Unit> Point2<T> {
pub const ZERO: Self = Self {
x: T::Scalar::ZERO,
y: T::Scalar::ZERO,
};
pub const ONE: Self = Self {
x: T::Scalar::ONE,
y: T::Scalar::ONE,
};
pub const fn new(x: T::Scalar, y: T::Scalar) -> Self {
Point2 { x, y }
}
crate::forward_constructors!(2, glam::Vec2);
crate::forward_comparison!(
<<T::Scalar as Scalar>::Vec2 as crate::bindings::Vector>::Mask,
glam::Vec2
);
crate::casting_interface!(Point2 {
x: T::Scalar,
y: T::Scalar
});
crate::tuple_interface!(Point2 {
x: T::Scalar,
y: T::Scalar
});
crate::array_interface!(2);
crate::forward_to_raw!(
glam::Vec2 =>
#[doc = "Extend with z-component to [`Point3`]."]
pub fn extend(self, z: T::Scalar) -> Point3<T>;
);
point_interface!(Point2, Vector2);
}
impl<T> Point2<T>
where
T: Unit,
T::Scalar: FloatScalar,
{
crate::forward_float_ops!(<T::Scalar as Scalar>::BVec2, glam::Vec2);
float_point_interface!(glam::Vec2);
}
impl<T: Unit> Point3<T> {
pub const ZERO: Self = Self {
x: T::Scalar::ZERO,
y: T::Scalar::ZERO,
z: T::Scalar::ZERO,
};
pub const ONE: Self = Self {
x: T::Scalar::ONE,
y: T::Scalar::ONE,
z: T::Scalar::ONE,
};
pub fn new(x: T::Scalar, y: T::Scalar, z: T::Scalar) -> Self {
Point3 { x, y, z }
}
crate::forward_constructors!(3, glam::Vec3);
crate::forward_comparison!(<T::Scalar as Scalar>::BVec3, glam::Vec3);
crate::casting_interface!(Point3 {
x: T::Scalar,
y: T::Scalar,
z: T::Scalar
});
crate::tuple_interface!(Point3 {
x: T::Scalar,
y: T::Scalar,
z: T::Scalar
});
crate::array_interface!(3);
crate::forward_to_raw!(
glam::Vec3 =>
#[doc = "Extend with w-component to [`Point4`]."]
pub fn extend(self, w: T::Scalar) -> Point4<T>;
#[doc = "Truncate to [`Point2`]."]
pub fn truncate(self) -> Point2<T>;
);
point_interface!(Point3, Vector3);
}
impl<T> Point3<T>
where
T: Unit,
T::Scalar: FloatScalar,
{
crate::forward_float_ops!(<T::Scalar as Scalar>::BVec3, glam::Vec3);
float_point_interface!(glam::Vec3);
}
impl<T: Unit> Point4<T> {
pub const ZERO: Self = Self {
x: T::Scalar::ZERO,
y: T::Scalar::ZERO,
z: T::Scalar::ZERO,
w: T::Scalar::ZERO,
};
pub const ONE: Self = Self {
x: T::Scalar::ONE,
y: T::Scalar::ONE,
z: T::Scalar::ONE,
w: T::Scalar::ONE,
};
pub fn new(x: T::Scalar, y: T::Scalar, z: T::Scalar, w: T::Scalar) -> Self {
Point4 { x, y, z, w }
}
crate::forward_constructors!(4, glam::Vec4);
crate::forward_comparison!(<T::Scalar as Scalar>::BVec4, glam::Vec4);
crate::casting_interface!(Point4 {
x: T::Scalar,
y: T::Scalar,
z: T::Scalar,
w: T::Scalar
});
crate::tuple_interface!(Point4 {
x: T::Scalar,
y: T::Scalar,
z: T::Scalar,
w: T::Scalar
});
crate::array_interface!(4);
crate::forward_to_raw!(
glam::Vec4 =>
#[doc = "Truncate to [`Point3`]."]
pub fn truncate(self) -> Point3<T>;
);
point_interface!(Point4, Vector4);
}
impl<T> Point4<T>
where
T: Unit,
T::Scalar: FloatScalar,
{
crate::forward_float_ops!(<T::Scalar as Scalar>::BVec4, glam::Vec4);
float_point_interface!(glam::Vec4);
}
impl<T> Point3<T>
where
T: Unit<Scalar = f32>,
{
#[inline]
#[must_use]
pub fn from_vec3a(vec: glam::Vec3A) -> Self {
vec.into()
}
#[inline]
#[must_use]
pub fn to_vec3a(self) -> glam::Vec3A {
self.into()
}
}
impl<T> From<glam::Vec3A> for Point3<T>
where
T: Unit<Scalar = f32>,
{
fn from(v: glam::Vec3A) -> Self {
Self::from_raw(v.into())
}
}
impl<T> From<Point3<T>> for glam::Vec3A
where
T: Unit<Scalar = f32>,
{
fn from(v: Point3<T>) -> Self {
v.to_raw().into()
}
}
impl<T> Mul<Point3<T>> for glam::Quat
where
T: Unit<Scalar = f32>,
T::Scalar: FloatScalar<Vec3f = glam::Vec3>,
{
type Output = Point3<T>;
fn mul(self, rhs: Point3<T>) -> Self::Output {
Point3::from_raw(self * rhs.to_raw())
}
}
impl<T> Mul<Point3<T>> for glam::DQuat
where
T: Unit<Scalar = f64>,
T::Scalar: FloatScalar<Vec3f = glam::DVec3>,
{
type Output = Point3<T>;
fn mul(self, rhs: Point3<T>) -> Self::Output {
Point3::from_raw(self * rhs.to_raw())
}
}
impl<T: Unit> From<Vector2<T>> for Point2<T> {
fn from(vec: Vector2<T>) -> Point2<T> {
Self::from_raw(vec.to_raw())
}
}
impl<T: Unit> From<Vector3<T>> for Point3<T> {
#[inline]
fn from(vec: Vector3<T>) -> Point3<T> {
Self::from_raw(vec.to_raw())
}
}
impl<T: Unit> From<Vector4<T>> for Point4<T> {
#[inline]
fn from(vec: Vector4<T>) -> Point4<T> {
Self::from_raw(vec.to_raw())
}
}
impl<T: Unit> From<Point2<T>> for Vector2<T> {
#[inline]
fn from(point: Point2<T>) -> Vector2<T> {
Self::from_raw(point.to_raw())
}
}
impl<T: Unit> From<Point3<T>> for Vector3<T> {
#[inline]
fn from(point: Point3<T>) -> Vector3<T> {
Self::from_raw(point.to_raw())
}
}
impl<T: Unit> From<Point4<T>> for Vector4<T> {
#[inline]
fn from(point: Point4<T>) -> Vector4<T> {
Self::from_raw(point.to_raw())
}
}
#[cfg(test)]
mod tests {
use crate::point;
use super::*;
type Point = super::Point3<f32>;
#[test]
fn subtraction_yields_vector() {
let p = Point::ONE;
let q = Point::ONE;
let v: Vector3<f32> = q - p;
assert_eq!(v, Vector3::ZERO);
}
#[test]
fn not_scalable() {
let p = Point::default();
let _ = p;
}
#[test]
fn vec3a() {
let a: glam::Vec3A = Point::new(0.0, 1.0, 2.0).to_vec3a();
assert_eq!(a, glam::Vec3A::new(0.0, 1.0, 2.0));
let b = Point::from_vec3a(a);
assert_eq!(b, Point::new(0.0, 1.0, 2.0));
}
#[test]
fn rotate() {
use crate::Angle;
use approx::assert_abs_diff_eq;
let v = Point3::<f32>::new(1.0, 0.0, 0.0);
let quat = Angle::from_degrees(180.0f32).to_rotation(Vector3::Z);
assert_abs_diff_eq!(quat * v, -v);
let v = Point3::<f64>::new(1.0, 0.0, 0.0);
let quat = Angle::from_degrees(180.0f64).to_rotation(Vector3::Z);
assert_abs_diff_eq!(quat * v, -v);
}
#[test]
fn from_into_vector() {
let mut p: Point4<f32> = point!(1.0, 2.0, 3.0, 4.0);
let mut v: Vector4<f32> = p.to_vector();
let q: Point4<f32> = Point4::from_vector(v);
assert_eq!(p, q);
assert_eq!(Vector4::from_point(p), v);
let _: &Vector4<_> = p.as_vector();
let _: &mut Vector4<_> = p.as_vector_mut();
let _: &Point4<_> = v.as_point();
let _: &mut Point4<_> = v.as_point_mut();
}
}