#[cfg(not(target_arch = "spirv"))]
use core::fmt;
use core::iter::{Product, Sum};
use core::ops::*;
use fidget::context::Tree;
use super::vec2::TreeVec2;
use super::vec4::TreeVec4;
#[inline(always)]
#[must_use]
pub fn treevec3(x: Tree, y: Tree, z: Tree) -> TreeVec3 {
TreeVec3::new(x, y, z)
}
#[derive(Clone, PartialEq)]
pub struct TreeVec3 {
pub x: Tree,
pub y: Tree,
pub z: Tree,
}
impl TreeVec3 {
#[inline(always)]
#[must_use]
pub fn new(x: impl Into<Tree>, y: impl Into<Tree>, z: impl Into<Tree>) -> Self {
Self {
x: x.into(),
y: y.into(),
z: z.into(),
}
}
#[inline]
#[must_use]
pub fn splat(v: impl Into<Tree> + Clone) -> Self {
Self {
x: v.clone().into(),
y: v.clone().into(),
z: v.clone().into(),
}
}
#[inline]
#[must_use]
pub fn from_array(a: [impl Into<Tree> + Clone; 3]) -> Self {
Self::new(
a[0].clone().into(),
a[1].clone().into(),
a[2].clone().into(),
)
}
#[inline]
#[must_use]
pub fn to_array(&self) -> [Tree; 3] {
[self.x.clone(), self.y.clone(), self.z.clone()]
}
#[inline]
#[must_use]
pub fn from_slice(slice: &[impl Into<Tree> + Clone]) -> Self {
Self::new(
slice[0].clone().into(),
slice[1].clone().into(),
slice[2].clone().into(),
)
}
#[inline]
pub fn write_to_slice(&self, slice: &mut [Tree]) {
slice[0] = self.x.clone();
slice[1] = self.y.clone();
slice[2] = self.z.clone();
}
#[allow(dead_code)]
#[inline]
#[must_use]
pub(crate) fn from_vec4(v: &TreeVec4) -> Self {
Self {
x: v.x.clone(),
y: v.y.clone(),
z: v.z.clone(),
}
}
#[inline]
#[must_use]
pub fn extend(&self, w: impl Into<Tree>) -> TreeVec4 {
TreeVec4::new(self.x.clone(), self.y.clone(), self.z.clone(), w.into())
}
#[inline]
#[must_use]
pub fn truncate(&self) -> TreeVec2 {
TreeVec2::new(self.x.clone(), self.y.clone())
}
#[inline]
#[must_use]
pub fn with_x(mut self, x: impl Into<Tree>) -> Self {
self.x = x.into();
self
}
#[inline]
#[must_use]
pub fn with_y(mut self, y: impl Into<Tree>) -> Self {
self.y = y.into();
self
}
#[inline]
#[must_use]
pub fn with_z(mut self, z: impl Into<Tree>) -> Self {
self.z = z.into();
self
}
#[inline]
#[must_use]
pub fn dot(&self, rhs: &Self) -> Tree {
(self.x.clone() * rhs.x.clone())
+ (self.y.clone() * rhs.y.clone())
+ (self.z.clone() * rhs.z.clone())
}
#[inline]
#[must_use]
pub fn dot_into_vec(&self, rhs: &Self) -> Self {
Self::splat(self.dot(rhs))
}
#[inline]
#[must_use]
pub fn cross(&self, rhs: &Self) -> Self {
Self {
x: self.y.clone() * rhs.z.clone() - rhs.y.clone() * self.z.clone(),
y: self.z.clone() * rhs.x.clone() - rhs.z.clone() * self.x.clone(),
z: self.x.clone() * rhs.y.clone() - rhs.x.clone() * self.y.clone(),
}
}
#[inline]
#[must_use]
pub fn min(&self, rhs: &Self) -> Self {
Self {
x: self.x.min(rhs.x.clone()),
y: self.y.min(rhs.y.clone()),
z: self.z.min(rhs.z.clone()),
}
}
#[inline]
#[must_use]
pub fn max(&self, rhs: &Self) -> Self {
Self {
x: self.x.max(rhs.x.clone()),
y: self.y.max(rhs.y.clone()),
z: self.z.max(rhs.z.clone()),
}
}
#[inline]
#[must_use]
pub fn clamp(&self, min: &Self, max: &Self) -> Self {
self.max(min).min(max)
}
#[inline]
#[must_use]
pub fn min_element(&self) -> Tree {
self.x.clone().min(self.y.clone().min(self.z.clone()))
}
#[inline]
#[must_use]
pub fn max_element(&self) -> Tree {
self.x.clone().max(self.y.clone().max(self.z.clone()))
}
#[inline]
#[must_use]
pub fn element_sum(&self) -> Tree {
self.x.clone() + self.y.clone() + self.z.clone()
}
#[inline]
#[must_use]
pub fn element_product(&self) -> Tree {
self.x.clone() * self.y.clone() * self.z.clone()
}
#[inline]
#[must_use]
pub fn abs(&self) -> Self {
Self {
x: self.x.clone().abs(),
y: self.y.clone().abs(),
z: self.z.clone().abs(),
}
}
#[doc(alias = "magnitude")]
#[inline]
#[must_use]
pub fn length(&self) -> Tree {
self.clone().dot(self).sqrt()
}
#[doc(alias = "magnitude2")]
#[inline]
#[must_use]
pub fn length_squared(&self) -> Tree {
self.clone().dot(self)
}
#[inline]
#[must_use]
pub fn length_recip(&self) -> Tree {
Tree::constant(1.0) / self.length()
}
#[inline]
#[must_use]
pub fn distance(&self, rhs: &Self) -> Tree {
(self.clone() - rhs).length()
}
#[inline]
#[must_use]
pub fn distance_squared(&self, rhs: &Self) -> Tree {
(self.clone() - rhs).length_squared()
}
#[inline]
#[must_use]
pub fn normalize(&self) -> Self {
#[allow(clippy::let_and_return)]
let normalized = self.clone().mul(&self.length_recip());
normalized
}
#[inline]
#[must_use]
pub fn project_onto(&self, rhs: &Self) -> Self {
let other_len_sq_rcp = Tree::constant(1.0) / rhs.clone().dot(rhs);
rhs.clone() * &self.dot(rhs) * &other_len_sq_rcp
}
#[inline]
#[must_use]
pub fn reject_from(&self, rhs: &Self) -> Self {
self.clone() - &self.project_onto(rhs)
}
#[inline]
#[must_use]
pub fn project_onto_normalized(&self, rhs: &Self) -> Self {
rhs.clone() * &self.dot(rhs)
}
#[inline]
#[must_use]
pub fn reject_from_normalized(&self, rhs: &Self) -> Self {
self.clone() - &self.project_onto_normalized(rhs)
}
#[inline]
#[must_use]
pub fn round(&self) -> Self {
Self {
x: self.x.clone().round(),
y: self.y.clone().round(),
z: self.z.clone().round(),
}
}
#[inline]
#[must_use]
pub fn floor(&self) -> Self {
Self {
x: self.x.clone().floor(),
y: self.y.clone().floor(),
z: self.z.clone().floor(),
}
}
#[inline]
#[must_use]
pub fn ceil(&self) -> Self {
Self {
x: self.x.clone().ceil(),
y: self.y.clone().ceil(),
z: self.z.clone().ceil(),
}
}
#[inline]
#[must_use]
pub fn fract_gl(&self) -> Self {
self.clone() - &self.floor()
}
#[inline]
#[must_use]
pub fn exp(&self) -> Self {
Self::new(
self.x.clone().exp(),
self.y.clone().exp(),
self.z.clone().exp(),
)
}
#[inline]
#[must_use]
pub fn recip(&self) -> Self {
Self {
x: Tree::constant(1.0) / self.x.clone(),
y: Tree::constant(1.0) / self.y.clone(),
z: Tree::constant(1.0) / self.z.clone(),
}
}
#[doc(alias = "mix")]
#[inline]
#[must_use]
pub fn lerp(&self, rhs: &Self, s: &Tree) -> Self {
self.clone() + &((rhs.clone() - self) * s)
}
#[inline]
pub fn midpoint(&self, rhs: &Self) -> Self {
(self.clone() + rhs) * &Tree::constant(0.5)
}
}
impl Default for TreeVec3 {
#[inline(always)]
fn default() -> Self {
Self::splat(Tree::constant(0.0))
}
}
impl Div<&TreeVec3> for TreeVec3 {
type Output = Self;
#[inline]
fn div(self, rhs: &Self) -> Self {
Self {
x: self.x.div(rhs.x.clone()),
y: self.y.div(rhs.y.clone()),
z: self.z.div(rhs.z.clone()),
}
}
}
impl DivAssign<&TreeVec3> for TreeVec3 {
#[inline]
fn div_assign(&mut self, rhs: &Self) {
self.x.div_assign(rhs.x.clone());
self.y.div_assign(rhs.y.clone());
self.z.div_assign(rhs.z.clone());
}
}
impl Div<&Tree> for TreeVec3 {
type Output = Self;
#[inline]
fn div(self, rhs: &Tree) -> Self {
Self {
x: self.x.div(rhs.clone()),
y: self.y.div(rhs.clone()),
z: self.z.div(rhs.clone()),
}
}
}
impl DivAssign<&Tree> for TreeVec3 {
#[inline]
fn div_assign(&mut self, rhs: &Tree) {
self.x.div_assign(rhs.clone());
self.y.div_assign(rhs.clone());
self.z.div_assign(rhs.clone());
}
}
impl Div<&TreeVec3> for &Tree {
type Output = TreeVec3;
#[inline]
fn div(self, rhs: &TreeVec3) -> TreeVec3 {
TreeVec3 {
x: self.clone().div(rhs.x.clone()),
y: self.clone().div(rhs.y.clone()),
z: self.clone().div(rhs.z.clone()),
}
}
}
impl Mul<&TreeVec3> for TreeVec3 {
type Output = Self;
#[inline]
fn mul(self, rhs: &Self) -> Self {
Self {
x: self.x.mul(rhs.x.clone()),
y: self.y.mul(rhs.y.clone()),
z: self.z.mul(rhs.z.clone()),
}
}
}
impl MulAssign<&TreeVec3> for TreeVec3 {
#[inline]
fn mul_assign(&mut self, rhs: &Self) {
self.x.mul_assign(rhs.x.clone());
self.y.mul_assign(rhs.y.clone());
self.z.mul_assign(rhs.z.clone());
}
}
impl Mul<&Tree> for TreeVec3 {
type Output = Self;
#[inline]
fn mul(self, rhs: &Tree) -> Self {
Self {
x: self.x.mul(rhs.clone()),
y: self.y.mul(rhs.clone()),
z: self.z.mul(rhs.clone()),
}
}
}
impl MulAssign<&Tree> for TreeVec3 {
#[inline]
fn mul_assign(&mut self, rhs: &Tree) {
self.x.mul_assign(rhs.clone());
self.y.mul_assign(rhs.clone());
self.z.mul_assign(rhs.clone());
}
}
impl Mul<&TreeVec3> for &Tree {
type Output = TreeVec3;
#[inline]
fn mul(self, rhs: &TreeVec3) -> TreeVec3 {
TreeVec3 {
x: self.clone().mul(rhs.x.clone()),
y: self.clone().mul(rhs.y.clone()),
z: self.clone().mul(rhs.z.clone()),
}
}
}
impl Add<&TreeVec3> for TreeVec3 {
type Output = Self;
#[inline]
fn add(self, rhs: &Self) -> Self {
Self {
x: self.x.add(rhs.x.clone()),
y: self.y.add(rhs.y.clone()),
z: self.z.add(rhs.z.clone()),
}
}
}
impl AddAssign<&TreeVec3> for TreeVec3 {
#[inline]
fn add_assign(&mut self, rhs: &Self) {
self.x.add_assign(rhs.x.clone());
self.y.add_assign(rhs.y.clone());
self.z.add_assign(rhs.z.clone());
}
}
impl Add<&Tree> for TreeVec3 {
type Output = Self;
#[inline]
fn add(self, rhs: &Tree) -> Self {
Self {
x: self.x.add(rhs.clone()),
y: self.y.add(rhs.clone()),
z: self.z.add(rhs.clone()),
}
}
}
impl AddAssign<&Tree> for TreeVec3 {
#[inline]
fn add_assign(&mut self, rhs: &Tree) {
self.x.add_assign(rhs.clone());
self.y.add_assign(rhs.clone());
self.z.add_assign(rhs.clone());
}
}
impl Add<&TreeVec3> for &Tree {
type Output = TreeVec3;
#[inline]
fn add(self, rhs: &TreeVec3) -> TreeVec3 {
TreeVec3 {
x: self.clone().add(rhs.x.clone()),
y: self.clone().add(rhs.y.clone()),
z: self.clone().add(rhs.z.clone()),
}
}
}
impl Sub<&TreeVec3> for TreeVec3 {
type Output = Self;
#[inline]
fn sub(self, rhs: &Self) -> Self {
Self {
x: self.x.sub(rhs.x.clone()),
y: self.y.sub(rhs.y.clone()),
z: self.z.sub(rhs.z.clone()),
}
}
}
impl SubAssign<&TreeVec3> for TreeVec3 {
#[inline]
fn sub_assign(&mut self, rhs: &TreeVec3) {
self.x.sub_assign(rhs.x.clone());
self.y.sub_assign(rhs.y.clone());
self.z.sub_assign(rhs.z.clone());
}
}
impl Sub<&Tree> for TreeVec3 {
type Output = Self;
#[inline]
fn sub(self, rhs: &Tree) -> Self {
Self {
x: self.x.sub(rhs.clone()),
y: self.y.sub(rhs.clone()),
z: self.z.sub(rhs.clone()),
}
}
}
impl SubAssign<&Tree> for TreeVec3 {
#[inline]
fn sub_assign(&mut self, rhs: &Tree) {
self.x.sub_assign(rhs.clone());
self.y.sub_assign(rhs.clone());
self.z.sub_assign(rhs.clone());
}
}
impl Sub<&TreeVec3> for &Tree {
type Output = TreeVec3;
#[inline]
fn sub(self, rhs: &TreeVec3) -> TreeVec3 {
TreeVec3 {
x: self.clone().sub(rhs.x.clone()),
y: self.clone().sub(rhs.y.clone()),
z: self.clone().sub(rhs.z.clone()),
}
}
}
impl Rem<&TreeVec3> for TreeVec3 {
type Output = Self;
#[inline]
fn rem(self, rhs: &Self) -> Self {
Self {
x: self.x.modulo(rhs.x.clone()),
y: self.y.modulo(rhs.y.clone()),
z: self.z.modulo(rhs.z.clone()),
}
}
}
impl RemAssign<&TreeVec3> for TreeVec3 {
#[inline]
fn rem_assign(&mut self, rhs: &Self) {
self.x = self.x.modulo(rhs.x.clone());
self.y = self.y.modulo(rhs.y.clone());
self.z = self.z.modulo(rhs.z.clone());
}
}
impl Rem<&Tree> for TreeVec3 {
type Output = Self;
#[inline]
fn rem(self, rhs: &Tree) -> Self {
Self {
x: self.x.modulo(rhs.clone()),
y: self.y.modulo(rhs.clone()),
z: self.z.modulo(rhs.clone()),
}
}
}
impl RemAssign<&Tree> for TreeVec3 {
#[inline]
fn rem_assign(&mut self, rhs: &Tree) {
self.x = self.x.modulo(rhs.clone());
self.y = self.y.modulo(rhs.clone());
self.z = self.z.modulo(rhs.clone());
}
}
impl Rem<&TreeVec3> for &Tree {
type Output = TreeVec3;
#[inline]
fn rem(self, rhs: &TreeVec3) -> TreeVec3 {
TreeVec3 {
x: self.clone().modulo(rhs.x.clone()),
y: self.clone().modulo(rhs.y.clone()),
z: self.clone().modulo(rhs.z.clone()),
}
}
}
#[cfg(not(target_arch = "spirv"))]
impl AsRef<[Tree; 3]> for TreeVec3 {
#[inline]
fn as_ref(&self) -> &[Tree; 3] {
unsafe { &*(self as *const TreeVec3 as *const [Tree; 3]) }
}
}
#[cfg(not(target_arch = "spirv"))]
impl AsMut<[Tree; 3]> for TreeVec3 {
#[inline]
fn as_mut(&mut self) -> &mut [Tree; 3] {
unsafe { &mut *(self as *mut TreeVec3 as *mut [Tree; 3]) }
}
}
impl Sum for TreeVec3 {
#[inline]
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::splat(Tree::constant(0.0)), |a, b| Self::add(a, &b))
}
}
impl<'a> Sum<&'a Self> for TreeVec3 {
#[inline]
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::splat(Tree::constant(0.0)), |a, b| Self::add(a, b))
}
}
impl Product for TreeVec3 {
#[inline]
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::splat(Tree::constant(1.0)), |a, b| Self::mul(a, &b))
}
}
impl<'a> Product<&'a Self> for TreeVec3 {
#[inline]
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::splat(Tree::constant(1.0)), |a, b| Self::mul(a, b))
}
}
impl Neg for TreeVec3 {
type Output = Self;
#[inline]
fn neg(self) -> Self {
Self {
x: self.x.neg(),
y: self.y.neg(),
z: self.z.neg(),
}
}
}
impl Index<usize> for TreeVec3 {
type Output = Tree;
#[inline]
fn index(&self, index: usize) -> &Self::Output {
match index {
0 => &self.x,
1 => &self.y,
2 => &self.z,
_ => panic!("index out of bounds"),
}
}
}
impl IndexMut<usize> for TreeVec3 {
#[inline]
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
match index {
0 => &mut self.x,
1 => &mut self.y,
2 => &mut self.z,
_ => panic!("index out of bounds"),
}
}
}
#[cfg(not(target_arch = "spirv"))]
impl fmt::Debug for TreeVec3 {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_tuple(stringify!(TreeVec3))
.field(&self.x)
.field(&self.y)
.field(&self.z)
.finish()
}
}
impl From<[Tree; 3]> for TreeVec3 {
#[inline]
fn from(a: [Tree; 3]) -> Self {
Self::new(a[0].clone(), a[1].clone(), a[2].clone())
}
}
impl From<TreeVec3> for [Tree; 3] {
#[inline]
fn from(v: TreeVec3) -> Self {
[v.x, v.y, v.z]
}
}
impl From<(Tree, Tree, Tree)> for TreeVec3 {
#[inline]
fn from(t: (Tree, Tree, Tree)) -> Self {
Self::new(t.0, t.1, t.2)
}
}
impl From<TreeVec3> for (Tree, Tree, Tree) {
#[inline]
fn from(v: TreeVec3) -> Self {
(v.x, v.y, v.z)
}
}
impl From<(&TreeVec2, Tree)> for TreeVec3 {
#[inline]
fn from((v, z): (&TreeVec2, Tree)) -> Self {
Self::new(v.x.clone(), v.y.clone(), z)
}
}