use super::*;
#[derive(Clone, Copy, Default)]
#[repr(align(16), C)]
pub struct Vec3 {
pub(crate) v4: Vec4,
}
unsafe impl Zeroable for Vec3 {}
unsafe impl Pod for Vec3 {}
impl core::cmp::PartialEq for Vec3 {
#[inline]
fn eq(&self, rhs: &Self) -> bool {
if_sse! {{
let a: m128 = cast(self.v4);
let b: m128 = cast(rhs.v4);
(a.cmp_eq(b).move_mask() & 0b0111) == 0b0111
} else {
let a: [f32;4] = cast(self.v4);
let b: [f32;4] = cast(rhs.v4);
let eq0 = a[0] == b[0];
let eq1 = a[1] == b[1];
let eq2 = a[2] == b[2];
eq0 & eq1 & eq2
}}
}
}
impl core::fmt::Debug for Vec3 {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
let [x, y, z, _]: [f32; 4] = cast(self.v4);
f.write_str("Vec3 { x: ")?;
core::fmt::Debug::fmt(&x, f)?;
f.write_str(", y: ")?;
core::fmt::Debug::fmt(&y, f)?;
f.write_str(", z: ")?;
core::fmt::Debug::fmt(&z, f)?;
f.write_str(" }")
}
}
impl core::fmt::Display for Vec3 {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
let [x, y, z, _]: [f32; 4] = cast(*self);
f.write_str("(")?;
core::fmt::Display::fmt(&x, f)?;
f.write_str(", ")?;
core::fmt::Display::fmt(&y, f)?;
f.write_str(", ")?;
core::fmt::Display::fmt(&z, f)?;
f.write_str(")")
}
}
impl core::fmt::LowerExp for Vec3 {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
let [x, y, z, _]: [f32; 4] = cast(*self);
f.write_str("(")?;
core::fmt::LowerExp::fmt(&x, f)?;
f.write_str(", ")?;
core::fmt::LowerExp::fmt(&y, f)?;
f.write_str(", ")?;
core::fmt::LowerExp::fmt(&z, f)?;
f.write_str(")")
}
}
impl core::fmt::UpperExp for Vec3 {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
let [x, y, z, _]: [f32; 4] = cast(*self);
f.write_str("(")?;
core::fmt::UpperExp::fmt(&x, f)?;
f.write_str(", ")?;
core::fmt::UpperExp::fmt(&y, f)?;
f.write_str(", ")?;
core::fmt::UpperExp::fmt(&z, f)?;
f.write_str(")")
}
}
impl Index<usize> for Vec3 {
type Output = f32;
#[inline(always)]
fn index(&self, index: usize) -> &f32 {
let arr_ref: &[f32; 4] = cast_ref(self);
match index {
0 => &arr_ref[0],
1 => &arr_ref[1],
2 => &arr_ref[2],
otherwise => panic!("Vec3 index out of bounds: {}", otherwise),
}
}
}
impl IndexMut<usize> for Vec3 {
#[inline(always)]
fn index_mut(&mut self, index: usize) -> &mut f32 {
let arr_mut: &mut [f32; 4] = cast_mut(self);
match index {
0 => &mut arr_mut[0],
1 => &mut arr_mut[1],
2 => &mut arr_mut[2],
otherwise => panic!("Vec3 index out of bounds: {}", otherwise),
}
}
}
impl AsRef<[f32; 3]> for Vec3 {
#[inline(always)]
fn as_ref(&self) -> &[f32; 3] {
unsafe { &*(self as *const Vec3 as *const [f32; 3]) }
}
}
impl AsMut<[f32; 3]> for Vec3 {
#[inline(always)]
fn as_mut(&mut self) -> &mut [f32; 3] {
unsafe { &mut *(self as *mut Vec3 as *mut [f32; 3]) }
}
}
impl From<[f32; 3]> for Vec3 {
#[inline]
fn from([x, y, z]: [f32; 3]) -> Self {
Self {
v4: Vec4::from([x, y, z, 0.0]),
}
}
}
impl From<Vec3> for [f32; 3] {
#[inline]
fn from(Vec3 { v4 }: Vec3) -> Self {
let [x, y, z, _]: [f32; 4] = cast(v4);
[x, y, z]
}
}
#[cfg(feature = "mint")]
impl From<mint::Vector3<f32>> for Vec3 {
#[inline]
fn from(mint::Vector3 { x, y, z }: mint::Vector3<f32>) -> Self {
Self::from([x, y, z])
}
}
#[cfg(feature = "mint")]
impl From<Vec3> for mint::Vector3<f32> {
#[inline]
fn from(v: Vec3) -> Self {
let [x, y, z]: [f32; 3] = <[f32; 3]>::from(v);
Self { x, y, z }
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for Vec3 {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
<[f32; 3]>::from(*self).serialize(serializer)
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for Vec3 {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
Ok(Self::from(<[f32; 3]>::deserialize(deserializer)?))
}
}
impl Add for Vec3 {
type Output = Self;
#[inline]
fn add(self, rhs: Self) -> Self {
Self {
v4: self.v4 + rhs.v4,
}
}
}
impl Add<f32> for Vec3 {
type Output = Self;
#[inline]
fn add(self, rhs: f32) -> Self {
Self {
v4: self.v4 + Vec4::splat(rhs),
}
}
}
impl Add<Vec3> for f32 {
type Output = Vec3;
#[inline]
fn add(self, rhs: Vec3) -> Vec3 {
Vec3::splat(self) + rhs
}
}
impl AddAssign for Vec3 {
#[inline]
fn add_assign(&mut self, rhs: Self) {
*self = *self + rhs
}
}
impl AddAssign<f32> for Vec3 {
#[inline]
fn add_assign(&mut self, rhs: f32) {
*self = *self + rhs
}
}
impl Sub for Vec3 {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self {
Self {
v4: self.v4 - rhs.v4,
}
}
}
impl Sub<f32> for Vec3 {
type Output = Self;
#[inline]
fn sub(self, rhs: f32) -> Self {
Self {
v4: self.v4 - Vec4::splat(rhs),
}
}
}
impl Sub<Vec3> for f32 {
type Output = Vec3;
#[inline]
fn sub(self, rhs: Vec3) -> Vec3 {
Vec3::splat(self) - rhs
}
}
impl SubAssign for Vec3 {
#[inline]
fn sub_assign(&mut self, rhs: Self) {
*self = *self - rhs
}
}
impl SubAssign<f32> for Vec3 {
#[inline]
fn sub_assign(&mut self, rhs: f32) {
*self = *self - rhs
}
}
impl Neg for Vec3 {
type Output = Self;
#[inline]
fn neg(self) -> Self {
Self { v4: -self.v4 }
}
}
impl Mul<f32> for Vec3 {
type Output = Self;
#[inline]
fn mul(self, rhs: f32) -> Self {
Self { v4: self.v4 * rhs }
}
}
impl Mul<Vec3> for f32 {
type Output = Vec3;
#[inline]
fn mul(self, rhs: Vec3) -> Vec3 {
rhs * self
}
}
impl MulAssign<f32> for Vec3 {
#[inline]
fn mul_assign(&mut self, rhs: f32) {
*self = *self * rhs;
}
}
impl Mul for Vec3 {
type Output = Self;
#[inline]
fn mul(self, rhs: Self) -> Self {
Self {
v4: self.v4 * rhs.v4,
}
}
}
impl MulAssign for Vec3 {
#[inline]
fn mul_assign(&mut self, rhs: Self) {
*self = *self * rhs;
}
}
impl Vec3 {
#[inline(always)]
pub fn x(self) -> f32 {
let [x, _, _] = <[f32; 3]>::from(self);
x
}
#[inline(always)]
pub fn y(self) -> f32 {
let [_, y, _] = <[f32; 3]>::from(self);
y
}
#[inline(always)]
pub fn z(self) -> f32 {
let [_, _, z] = <[f32; 3]>::from(self);
z
}
#[inline(always)]
pub fn x_mut(&mut self) -> &mut f32 {
let arr_mut: &mut [f32; 4] = cast_mut(self);
&mut arr_mut[0]
}
#[inline(always)]
pub fn y_mut(&mut self) -> &mut f32 {
let arr_mut: &mut [f32; 4] = cast_mut(self);
&mut arr_mut[1]
}
#[inline(always)]
pub fn z_mut(&mut self) -> &mut f32 {
let arr_mut: &mut [f32; 4] = cast_mut(self);
&mut arr_mut[2]
}
}
impl Vec3 {
#[inline(always)]
pub fn new(x: f32, y: f32, z: f32) -> Self {
Self::from([x, y, z])
}
#[inline]
pub fn splat(v: f32) -> Self {
Self { v4: Vec4::splat(v) }
}
#[inline]
pub fn to_vec4(self, w: f32) -> Vec4 {
let [x, y, z]: [f32; 3] = <[f32; 3]>::from(self);
Vec4::from([x, y, z, w])
}
#[inline]
pub fn to_vec2(self) -> Vec2 {
let [x, y, _]: [f32; 3] = <[f32; 3]>::from(self);
Vec2::new(x, y)
}
}
impl Vec3 {
#[inline]
pub fn dot(self, rhs: Self) -> f32 {
if_sse! {{
let square = self * rhs;
let z_ = square.zxx();
let xz_ = square + z_;
let y_ = square.yxx();
let xzy_ = xz_ + y_;
xzy_.v4.sse.extract0_f32()
} else {
let t = self * rhs;
t.x() + t.y() + t.z()
}}
}
#[inline]
pub fn length(self) -> f32 {
lokacore::sqrt_f32(self.length2())
}
#[inline]
pub fn length2(self) -> f32 {
let sq = self * self;
sq.x() + sq.y() + sq.z()
}
#[inline]
pub fn normalize(self) -> Self {
let len = self.length();
Self::new(self.x() / len, self.y() / len, self.z() / len)
}
#[inline]
pub fn cross(self, rhs: Self) -> Self {
(self.yzx() * rhs.zxy()) - (self.zxy() * rhs.yzx())
}
}