use std::fmt;
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
use super::single::{self, InvariantF32};
use super::{Matrix3x2, Matrix4x4, Quaternion};
use crate::Vector;
#[derive(Clone, Copy, Debug, PartialEq, Default)]
pub struct Vector2 {
pub x: f32,
pub y: f32,
}
impl Vector2 {
pub const ZERO: Vector2 = Vector2::new(0.0, 0.0);
pub const ONE: Vector2 = Vector2::new(1.0, 1.0);
pub const UNIT_X: Vector2 = Vector2::new(1.0, 0.0);
pub const UNIT_Y: Vector2 = Vector2::new(0.0, 1.0);
#[inline]
pub const fn new(x: f32, y: f32) -> Self {
Self { x, y }
}
#[inline]
pub const fn from_value(value: f32) -> Self {
Self::new(value, value)
}
#[inline]
pub fn abs(value: Vector2) -> Vector2 {
Vector2::new(value.x.abs(), value.y.abs())
}
#[inline]
pub fn clamp(value1: Vector2, min: Vector2, max: Vector2) -> Vector2 {
Vector2::min(Vector2::max(value1, min), max)
}
#[inline]
pub fn distance(value1: Vector2, value2: Vector2) -> f32 {
Vector2::distance_squared(value1, value2).sqrt()
}
#[inline]
pub fn distance_squared(value1: Vector2, value2: Vector2) -> f32 {
(value1 - value2).length_squared()
}
#[inline]
pub fn dot(value1: Vector2, value2: Vector2) -> f32 {
(value1.x * value2.x) + (value1.y * value2.y)
}
#[inline]
pub fn length(&self) -> f32 {
self.length_squared().sqrt()
}
#[inline]
pub fn length_squared(&self) -> f32 {
Vector2::dot(*self, *self)
}
#[inline]
pub fn lerp(value1: Vector2, value2: Vector2, amount: f32) -> Vector2 {
(value1 * (1.0 - amount)) + (value2 * amount)
}
#[inline]
pub fn max(value1: Vector2, value2: Vector2) -> Vector2 {
Vector2::new(single::max(value1.x, value2.x), single::max(value1.y, value2.y))
}
#[inline]
pub fn min(value1: Vector2, value2: Vector2) -> Vector2 {
Vector2::new(single::min(value1.x, value2.x), single::min(value1.y, value2.y))
}
#[inline]
pub fn normalize(value: Vector2) -> Vector2 {
value / value.length()
}
#[inline]
pub fn square_root(value: Vector2) -> Vector2 {
Vector2::new(value.x.sqrt(), value.y.sqrt())
}
#[inline]
pub fn transform(position: Vector2, matrix: Matrix3x2) -> Vector2 {
Vector2::new(
(position.x * matrix.m11) + (position.y * matrix.m21) + matrix.m31,
(position.x * matrix.m12) + (position.y * matrix.m22) + matrix.m32,
)
}
#[inline]
pub fn transform_matrix4x4(position: Vector2, matrix: Matrix4x4) -> Vector2 {
Vector2::new(
(position.x * matrix.m11) + (position.y * matrix.m21) + matrix.m41,
(position.x * matrix.m12) + (position.y * matrix.m22) + matrix.m42,
)
}
pub fn transform_quaternion(value: Vector2, rotation: Quaternion) -> Vector2 {
let x2 = rotation.x + rotation.x;
let y2 = rotation.y + rotation.y;
let z2 = rotation.z + rotation.z;
let wz2 = rotation.w * z2;
let xx2 = rotation.x * x2;
let xy2 = rotation.x * y2;
let yy2 = rotation.y * y2;
let zz2 = rotation.z * z2;
Vector2::new(
value.x * (1.0 - yy2 - zz2) + value.y * (xy2 - wz2),
value.x * (xy2 + wz2) + value.y * (1.0 - xx2 - zz2),
)
}
#[inline]
pub fn transform_normal(normal: Vector2, matrix: Matrix3x2) -> Vector2 {
Vector2::new(
(normal.x * matrix.m11) + (normal.y * matrix.m21),
(normal.x * matrix.m12) + (normal.y * matrix.m22),
)
}
}
impl From<Vector> for Vector2 {
#[inline]
fn from(value: Vector) -> Vector2 {
Vector2::new(value.x as f32, value.y as f32)
}
}
impl From<Vector2> for Vector {
#[inline]
fn from(value: Vector2) -> Vector {
Vector::new(value.x as f64, value.y as f64)
}
}
impl Add for Vector2 {
type Output = Vector2;
#[inline]
fn add(self, right: Vector2) -> Vector2 {
Vector2::new(self.x + right.x, self.y + right.y)
}
}
impl Sub for Vector2 {
type Output = Vector2;
#[inline]
fn sub(self, right: Vector2) -> Vector2 {
Vector2::new(self.x - right.x, self.y - right.y)
}
}
impl Mul for Vector2 {
type Output = Vector2;
#[inline]
fn mul(self, right: Vector2) -> Vector2 {
Vector2::new(self.x * right.x, self.y * right.y)
}
}
impl Mul<f32> for Vector2 {
type Output = Vector2;
#[inline]
fn mul(self, right: f32) -> Vector2 {
Vector2::new(self.x * right, self.y * right)
}
}
impl Mul<Vector2> for f32 {
type Output = Vector2;
#[inline]
fn mul(self, right: Vector2) -> Vector2 {
right * self
}
}
impl Div for Vector2 {
type Output = Vector2;
#[inline]
fn div(self, right: Vector2) -> Vector2 {
Vector2::new(self.x / right.x, self.y / right.y)
}
}
impl Div<f32> for Vector2 {
type Output = Vector2;
#[inline]
fn div(self, right: f32) -> Vector2 {
Vector2::new(self.x / right, self.y / right)
}
}
impl Neg for Vector2 {
type Output = Vector2;
#[inline]
fn neg(self) -> Vector2 {
Vector2::new(-self.x, -self.y)
}
}
impl AddAssign for Vector2 {
#[inline]
fn add_assign(&mut self, right: Vector2) {
*self = *self + right;
}
}
impl SubAssign for Vector2 {
#[inline]
fn sub_assign(&mut self, right: Vector2) {
*self = *self - right;
}
}
impl MulAssign for Vector2 {
#[inline]
fn mul_assign(&mut self, right: Vector2) {
*self = *self * right;
}
}
impl MulAssign<f32> for Vector2 {
#[inline]
fn mul_assign(&mut self, right: f32) {
*self = *self * right;
}
}
impl DivAssign for Vector2 {
#[inline]
fn div_assign(&mut self, right: Vector2) {
*self = *self / right;
}
}
impl DivAssign<f32> for Vector2 {
#[inline]
fn div_assign(&mut self, right: f32) {
*self = *self / right;
}
}
impl fmt::Display for Vector2 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<{}, {}>", InvariantF32(self.x), InvariantF32(self.y))
}
}