use crate::{
material::Cull,
mesh::{Mesh, VindT, mesh_ray_intersect},
model::{Model, model_ray_intersect},
};
use std::{
fmt::Display,
ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
};
pub type Bool32T = i32;
pub fn lerp(a: f32, b: f32, t: f32) -> f32 {
a + (b - a) * t
}
pub fn angle_dist(a: f32, b: f32) -> f32 {
let delta = (b - a + 180.0) % 360.0 - 180.0;
(if delta < -180.0 { delta + 360.0 } else { delta }).abs()
}
pub mod units {
pub const CM2M: f32 = 0.01;
pub const MM2M: f32 = 0.001;
pub const M2CM: f32 = 100.0;
pub const M2MM: f32 = 1000.0;
pub const CM: f32 = 0.01;
pub const MM: f32 = 0.001;
pub const M: f32 = 1.0;
pub const KM: f32 = 1000.0;
}
#[derive(Debug, Default, Copy, Clone)]
#[repr(C)]
pub struct Vec2 {
pub x: f32,
pub y: f32,
}
impl From<glam::Vec2> for Vec2 {
fn from(val: glam::Vec2) -> Self {
Vec2 { x: val.x, y: val.y }
}
}
impl From<Vec2> for glam::Vec2 {
fn from(val: Vec2) -> Self {
Self::new(val.x, val.y)
}
}
impl From<[f32; 2]> for Vec2 {
fn from(val: [f32; 2]) -> Self {
Vec2 { x: val[0], y: val[1] }
}
}
impl PartialEq for Vec2 {
fn eq(&self, other: &Self) -> bool {
((self.x - other.x).abs() < 0.0001) && ((self.y - other.y).abs() < 0.0001)
}
}
impl Vec2 {
pub const ZERO: Self = Self::new(0.0, 0.0);
pub const ONE: Self = Self::new(1.0, 1.0);
pub const X: Self = Self::new(1.0, 0.0);
pub const Y: Self = Self::new(0.0, 1.0);
pub const NEG_X: Self = Self::new(-1.0, 0.0);
pub const NEG_Y: Self = Self::new(0.0, -1.0);
#[inline]
pub const fn new(x: f32, y: f32) -> Self {
Self { x, y }
}
#[inline]
pub fn angle(&self) -> f32 {
let mut result = self.y.atan2(self.x).to_degrees();
if result < 0.0 {
result += 360.0
};
result
}
#[inline]
pub fn in_radius(&self, point: Self, radius: f32) -> bool {
Self::distance(*self, point) <= radius
}
#[inline]
pub fn normalize(&mut self) {
let n = *self * (self.length().recip());
self.x = n.x;
self.y = n.y;
}
#[inline]
pub fn length(&self) -> f32 {
Self::dot(*self, *self).sqrt()
}
#[inline]
pub fn length_sq(&self) -> f32 {
Self::dot(*self, *self)
}
#[inline]
pub fn magnitude(&self) -> f32 {
self.length()
}
#[inline]
pub fn magnitude_sq(&self) -> f32 {
self.length_sq()
}
#[inline]
pub fn get_normalized(&self) -> Self {
*self * (self.length().recip())
}
#[inline]
pub fn x0y(&self) -> Vec3 {
Vec3 { x: self.x, y: 0.0, z: self.y }
}
#[inline]
pub fn xy0(&self) -> Vec3 {
Vec3 { x: self.x, y: self.y, z: 0.0 }
}
#[inline]
pub fn yx(&self) -> Self {
Self { x: self.y, y: self.x }
}
#[inline]
pub fn angle_between(a: Self, b: Self) -> f32 {
(Self::dot(a, b) / (a.length_sq() * b.length_sq()).sqrt()).acos().to_degrees()
}
#[inline]
pub fn direction(to: Self, from: Self) -> Self {
(to - from).get_normalized()
}
#[inline]
pub fn distance(a: Self, b: Self) -> f32 {
(a - b).length()
}
#[inline]
pub fn distance_sq(a: Self, b: Self) -> f32 {
(a - b).length_sq()
}
#[inline]
pub fn dot(a: Self, b: Self) -> f32 {
(a.x * b.x) + (a.y * b.y)
}
#[inline]
pub fn from_angles(degree: f32) -> Self {
Self { x: degree.to_radians().cos(), y: degree.to_radians().sin() }
}
#[inline]
pub fn lerp(a: Self, b: Self, blend: f32) -> Self {
a + ((b - a) * blend)
}
#[inline]
pub fn max(a: Self, b: Self) -> Self {
Self { x: f32::max(a.x, b.x), y: f32::max(a.y, b.y) }
}
#[inline]
pub fn min(a: Self, b: Self) -> Self {
Self { x: f32::min(a.x, b.x), y: f32::min(a.y, b.y) }
}
#[inline]
pub fn abs(&self) -> Self {
Self { x: self.x.abs(), y: self.y.abs() }
}
}
impl Display for Vec2 {
#[inline]
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "[x:{}, y:{}]", self.x, self.y)
}
}
impl Div<Vec2> for Vec2 {
type Output = Self;
#[inline]
fn div(self, rhs: Self) -> Self::Output {
Self { x: self.x.div(rhs.x), y: self.y.div(rhs.y) }
}
}
impl DivAssign<Vec2> for Vec2 {
#[inline]
fn div_assign(&mut self, rhs: Self) {
self.x.div_assign(rhs.x);
self.y.div_assign(rhs.y);
}
}
impl Div<f32> for Vec2 {
type Output = Self;
#[inline]
fn div(self, rhs: f32) -> Self::Output {
Self { x: self.x.div(rhs), y: self.y.div(rhs) }
}
}
impl DivAssign<f32> for Vec2 {
#[inline]
fn div_assign(&mut self, rhs: f32) {
self.x.div_assign(rhs);
self.y.div_assign(rhs);
}
}
impl Div<Vec2> for f32 {
type Output = Vec2;
#[inline]
fn div(self, rhs: Vec2) -> Self::Output {
Vec2 { x: self.div(rhs.x), y: self.div(rhs.y) }
}
}
impl Mul<Vec2> for Vec2 {
type Output = Self;
#[inline]
fn mul(self, rhs: Self) -> Self::Output {
Self { x: self.x.mul(rhs.x), y: self.y.mul(rhs.y) }
}
}
impl MulAssign<Vec2> for Vec2 {
#[inline]
fn mul_assign(&mut self, rhs: Self) {
self.x.mul_assign(rhs.x);
self.y.mul_assign(rhs.y);
}
}
impl Mul<f32> for Vec2 {
type Output = Self;
#[inline]
fn mul(self, rhs: f32) -> Self::Output {
Self { x: self.x.mul(rhs), y: self.y.mul(rhs) }
}
}
impl MulAssign<f32> for Vec2 {
#[inline]
fn mul_assign(&mut self, rhs: f32) {
self.x.mul_assign(rhs);
self.y.mul_assign(rhs);
}
}
impl Mul<Vec2> for f32 {
type Output = Vec2;
#[inline]
fn mul(self, rhs: Vec2) -> Self::Output {
Vec2 { x: self.mul(rhs.x), y: self.mul(rhs.y) }
}
}
impl Add<Vec2> for Vec2 {
type Output = Self;
#[inline]
fn add(self, rhs: Self) -> Self::Output {
Self { x: self.x.add(rhs.x), y: self.y.add(rhs.y) }
}
}
impl AddAssign<Vec2> for Vec2 {
#[inline]
fn add_assign(&mut self, rhs: Self) {
self.x.add_assign(rhs.x);
self.y.add_assign(rhs.y);
}
}
impl Sub<Vec2> for Vec2 {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self::Output {
Self { x: self.x.sub(rhs.x), y: self.y.sub(rhs.y) }
}
}
impl SubAssign<Vec2> for Vec2 {
#[inline]
fn sub_assign(&mut self, rhs: Vec2) {
self.x.sub_assign(rhs.x);
self.y.sub_assign(rhs.y);
}
}
impl Neg for Vec2 {
type Output = Self;
#[inline]
fn neg(self) -> Self::Output {
self * -1.0
}
}
#[derive(Debug, Default, Copy, Clone)]
#[repr(C)]
pub struct Vec3 {
pub x: f32,
pub y: f32,
pub z: f32,
}
impl From<glam::Vec3> for Vec3 {
fn from(val: glam::Vec3) -> Self {
Vec3 { x: val.x, y: val.y, z: val.z }
}
}
impl From<Vec3> for glam::Vec3 {
fn from(val: Vec3) -> Self {
Self::new(val.x, val.y, val.z)
}
}
impl From<[f32; 3]> for Vec3 {
fn from(val: [f32; 3]) -> Self {
Vec3 { x: val[0], y: val[1], z: val[2] }
}
}
impl From<Vec3> for [f32; 3] {
fn from(val: Vec3) -> Self {
[val.x, val.y, val.z]
}
}
impl PartialEq for Vec3 {
fn eq(&self, other: &Self) -> bool {
((self.x - other.x).abs() < 0.0001)
&& ((self.y - other.y).abs() < 0.0001)
&& ((self.z - other.z).abs() < 0.0001)
}
}
unsafe extern "C" {
pub fn vec3_cross(a: *const Vec3, b: *const Vec3) -> Vec3;
}
impl Vec3 {
pub const FORWARD: Self = Self::NEG_Z;
pub const ONE: Self = Self::new(1.0, 1.0, 1.0);
pub const NEG_ONE: Self = Self::new(-1.0, -1.0, -1.0);
pub const RIGHT: Self = Self::X;
pub const X: Self = Self::new(1.0, 0.0, 0.0);
pub const Y: Self = Self::new(0.0, 1.0, 0.0);
pub const Z: Self = Self::new(0.0, 0.0, 1.0);
pub const NEG_X: Self = Self::new(-1.0, 0.0, 0.0);
pub const NEG_Y: Self = Self::new(0.0, -1.0, 0.0);
pub const NEG_Z: Self = Self::new(0.0, 0.0, -1.0);
pub const UP: Self = Self::Y;
pub const ZERO: Vec3 = Self::new(0.0, 0.0, 0.0);
#[inline]
pub const fn new(x: f32, y: f32, z: f32) -> Self {
Self { x, y, z }
}
#[inline]
pub fn in_radius(&self, point: Self, radius: f32) -> bool {
Self::distance(*self, point) <= radius
}
#[inline]
pub fn normalize(&mut self) {
let n = *self * (self.length().recip());
self.x = n.x;
self.y = n.y;
self.z = n.z;
}
#[inline]
pub fn length(&self) -> f32 {
Self::dot(*self, *self).sqrt()
}
#[inline]
pub fn length_sq(&self) -> f32 {
Self::dot(*self, *self)
}
#[inline]
pub fn magnitude(&self) -> f32 {
self.length()
}
#[inline]
pub fn magnitude_squared(&self) -> f32 {
self.length_sq()
}
#[inline]
pub fn get_normalized(&self) -> Self {
*self * (self.length().recip())
}
#[inline]
pub fn x0z(&self) -> Self {
Self { x: self.x, y: 0.0, z: self.z }
}
#[inline]
pub fn xy0(&self) -> Self {
Self { x: self.x, y: self.y, z: 0.0 }
}
#[inline]
pub fn xy1(&self) -> Self {
Self { x: self.x, y: self.y, z: 1.0 }
}
#[inline]
pub fn xy(&self) -> Vec2 {
Vec2::new(self.x, self.y)
}
#[inline]
pub fn yz(&self) -> Vec2 {
Vec2::new(self.y, self.z)
}
#[inline]
pub fn xz(&self) -> Vec2 {
Vec2::new(self.x, self.z)
}
#[inline]
pub fn angle_between(a: Self, b: Self) -> f32 {
(Self::dot(a, b) / (a.length_sq() * b.length_sq()).sqrt()).acos().to_degrees()
}
#[inline]
pub fn angle_xy(angle_deg: f32, z: f32) -> Vec3 {
Self { x: angle_deg.to_radians().cos(), y: angle_deg.to_radians().sin(), z }
}
#[inline]
pub fn angle_xz(angle_deg: f32, y: f32) -> Self {
Self { x: angle_deg.to_radians().cos(), y, z: angle_deg.to_radians().sin() }
}
#[inline]
pub fn cross(a: Self, b: Self) -> Self {
unsafe { vec3_cross(&a, &b) }
}
#[inline]
pub fn direction(to: Self, from: Self) -> Self {
(to - from).get_normalized()
}
#[inline]
pub fn distance(a: Self, b: Self) -> f32 {
(a - b).length()
}
#[inline]
pub fn distance_sq(a: Self, b: Self) -> f32 {
(a - b).length_sq()
}
#[inline]
pub fn dot(a: Self, b: Self) -> f32 {
(a.x * b.x) + (a.y * b.y) + (a.z * b.z)
}
#[inline]
pub fn lerp(a: Self, b: Self, blend: f32) -> Self {
a + ((b - a) * blend)
}
#[inline]
pub fn max(a: Self, b: Self) -> Self {
Self { x: f32::max(a.x, b.x), y: f32::max(a.y, b.y), z: f32::max(a.z, b.z) }
}
#[inline]
pub fn min(a: Self, b: Self) -> Self {
Self { x: f32::min(a.x, b.x), y: f32::min(a.y, b.y), z: f32::min(a.z, b.z) }
}
#[inline]
pub fn perpendicular_right(forward: Self, up: Self) -> Self {
Self::cross(forward, up)
}
#[inline]
pub fn abs(&self) -> Self {
Self { x: self.x.abs(), y: self.y.abs(), z: self.z.abs() }
}
#[inline]
pub const fn to_array(&self) -> [f32; 3] {
[self.x, self.y, self.z]
}
}
impl Display for Vec3 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "[x:{}, y:{}, z:{}]", self.x, self.y, self.z)
}
}
impl Div<Vec3> for Vec3 {
type Output = Self;
#[inline]
fn div(self, rhs: Self) -> Self::Output {
Self { x: self.x.div(rhs.x), y: self.y.div(rhs.y), z: self.z.div(rhs.z) }
}
}
impl DivAssign<Vec3> for Vec3 {
#[inline]
fn div_assign(&mut self, rhs: Self) {
self.x.div_assign(rhs.x);
self.y.div_assign(rhs.y);
self.z.div_assign(rhs.z);
}
}
impl Div<f32> for Vec3 {
type Output = Self;
#[inline]
fn div(self, rhs: f32) -> Self::Output {
Self { x: self.x.div(rhs), y: self.y.div(rhs), z: self.z.div(rhs) }
}
}
impl DivAssign<f32> for Vec3 {
#[inline]
fn div_assign(&mut self, rhs: f32) {
self.x.div_assign(rhs);
self.y.div_assign(rhs);
self.z.div_assign(rhs);
}
}
impl Div<Vec3> for f32 {
type Output = Vec3;
#[inline]
fn div(self, rhs: Vec3) -> Self::Output {
Vec3 { x: self.div(rhs.x), y: self.div(rhs.y), z: self.div(rhs.z) }
}
}
impl Mul<Vec3> for Vec3 {
type Output = Self;
#[inline]
fn mul(self, rhs: Self) -> Self::Output {
Self { x: self.x.mul(rhs.x), y: self.y.mul(rhs.y), z: self.z.mul(rhs.z) }
}
}
impl MulAssign<Vec3> for Vec3 {
#[inline]
fn mul_assign(&mut self, rhs: Self) {
self.x.mul_assign(rhs.x);
self.y.mul_assign(rhs.y);
self.z.mul_assign(rhs.z);
}
}
impl Mul<f32> for Vec3 {
type Output = Self;
#[inline]
fn mul(self, rhs: f32) -> Self::Output {
Self { x: self.x.mul(rhs), y: self.y.mul(rhs), z: self.z.mul(rhs) }
}
}
impl MulAssign<f32> for Vec3 {
#[inline]
fn mul_assign(&mut self, rhs: f32) {
self.x.mul_assign(rhs);
self.y.mul_assign(rhs);
self.z.mul_assign(rhs);
}
}
impl Mul<Vec3> for f32 {
type Output = Vec3;
#[inline]
fn mul(self, rhs: Vec3) -> Self::Output {
Vec3 { x: self.mul(rhs.x), y: self.mul(rhs.y), z: self.mul(rhs.z) }
}
}
impl Add<Vec3> for Vec3 {
type Output = Self;
#[inline]
fn add(self, rhs: Self) -> Self::Output {
Self { x: self.x.add(rhs.x), y: self.y.add(rhs.y), z: self.z.add(rhs.z) }
}
}
impl AddAssign<Vec3> for Vec3 {
#[inline]
fn add_assign(&mut self, rhs: Self) {
self.x.add_assign(rhs.x);
self.y.add_assign(rhs.y);
self.z.add_assign(rhs.z);
}
}
impl Sub<Vec3> for Vec3 {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self::Output {
Self { x: self.x.sub(rhs.x), y: self.y.sub(rhs.y), z: self.z.sub(rhs.z) }
}
}
impl SubAssign<Vec3> for Vec3 {
#[inline]
fn sub_assign(&mut self, rhs: Vec3) {
self.x.sub_assign(rhs.x);
self.y.sub_assign(rhs.y);
self.z.sub_assign(rhs.z);
}
}
impl Neg for Vec3 {
type Output = Self;
#[inline]
fn neg(self) -> Self::Output {
self * -1.0
}
}
#[derive(Debug, Default, Copy, Clone)]
#[repr(C)]
pub struct Vec4 {
pub x: f32,
pub y: f32,
pub z: f32,
pub w: f32,
}
impl From<glam::Vec4> for Vec4 {
fn from(value: glam::Vec4) -> Self {
Self { x: value.x, y: value.y, z: value.z, w: value.w }
}
}
impl From<[f32; 4]> for Vec4 {
fn from(val: [f32; 4]) -> Self {
Vec4 { x: val[0], y: val[1], z: val[2], w: val[3] }
}
}
impl From<Vec4> for glam::Vec4 {
fn from(value: Vec4) -> Self {
Self::new(value.x, value.y, value.z, value.w)
}
}
impl PartialEq for Vec4 {
fn eq(&self, other: &Self) -> bool {
((self.x - other.x).abs() < 0.0001)
&& ((self.y - other.y).abs() < 0.0001)
&& ((self.z - other.z).abs() < 0.0001)
&& ((self.w - other.w).abs() < 0.0001)
}
}
impl Vec4 {
pub const ZERO: Vec4 = Vec4 { x: 0.0, y: 0.0, z: 0.0, w: 0.0 };
pub const ONE: Vec4 = Vec4 { x: 1.0, y: 1.0, z: 1.0, w: 1.0 };
pub const X: Vec4 = Vec4 { x: 1.0, y: 0.0, z: 0.0, w: 0.0 };
pub const Y: Vec4 = Vec4 { x: 0.0, y: 1.0, z: 0.0, w: 0.0 };
pub const Z: Vec4 = Vec4 { x: 0.0, y: 0.0, z: 1.0, w: 0.0 };
pub const W: Vec4 = Vec4 { x: 0.0, y: 0.0, z: 0.0, w: 1.0 };
pub const NEG_X: Vec4 = Vec4 { x: -1.0, y: 0.0, z: 0.0, w: 0.0 };
pub const NEG_Y: Vec4 = Vec4 { x: 0.0, y: -1.0, z: 0.0, w: 0.0 };
pub const NEG_Z: Vec4 = Vec4 { x: 0.0, y: 0.0, z: -1.0, w: 0.0 };
pub const NEG_W: Vec4 = Vec4 { x: 0.0, y: 0.0, z: 0.0, w: -1.0 };
#[inline]
pub const fn new(x: f32, y: f32, z: f32, w: f32) -> Self {
Self { x, y, z, w }
}
#[inline]
pub fn xy(&self) -> Vec2 {
Vec2::new(self.x, self.y)
}
#[inline]
pub fn yz(&self) -> Vec2 {
Vec2::new(self.y, self.z)
}
#[inline]
pub fn xz(&self) -> Vec2 {
Vec2::new(self.x, self.z)
}
#[inline]
pub fn zw(&self) -> Vec2 {
Vec2::new(self.z, self.w)
}
#[inline]
pub fn xyz(&self) -> Vec3 {
Vec3::new(self.x, self.y, self.z)
}
#[inline]
pub fn get_as_quat(&self) -> Quat {
Quat { x: self.x, y: self.y, z: self.z, w: self.w }
}
#[inline]
pub fn length_sq(&self) -> f32 {
Self::dot(*self, *self)
}
#[inline]
pub fn dot(a: Self, b: Self) -> f32 {
(a.x * b.x) + (a.y * b.y) + (a.z * b.z) + (a.w * b.w)
}
#[inline]
pub fn lerp(a: Self, b: Self, blend: f32) -> Self {
a + ((b - a) * blend)
}
#[inline]
pub fn max(a: Self, b: Self) -> Self {
Self { x: f32::max(a.x, b.x), y: f32::max(a.y, b.y), z: f32::max(a.z, b.z), w: f32::max(a.w, b.w) }
}
#[inline]
pub fn min(a: Self, b: Self) -> Self {
Self { x: f32::min(a.x, b.x), y: f32::min(a.y, b.y), z: f32::min(a.z, b.z), w: f32::min(a.w, b.w) }
}
}
impl Display for Vec4 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "[x:{}, y:{}, z:{}, w:{}]", self.x, self.y, self.z, self.w)
}
}
impl Div<Vec4> for Vec4 {
type Output = Self;
#[inline]
fn div(self, rhs: Self) -> Self::Output {
Self { x: self.x.div(rhs.x), y: self.y.div(rhs.y), z: self.z.div(rhs.z), w: self.w.div(rhs.w) }
}
}
impl DivAssign<Vec4> for Vec4 {
#[inline]
fn div_assign(&mut self, rhs: Self) {
self.x.div_assign(rhs.x);
self.y.div_assign(rhs.y);
self.z.div_assign(rhs.z);
self.w.div_assign(rhs.w);
}
}
impl Div<f32> for Vec4 {
type Output = Self;
#[inline]
fn div(self, rhs: f32) -> Self::Output {
Self { x: self.x.div(rhs), y: self.y.div(rhs), z: self.z.div(rhs), w: self.w.div(rhs) }
}
}
impl DivAssign<f32> for Vec4 {
#[inline]
fn div_assign(&mut self, rhs: f32) {
self.x.div_assign(rhs);
self.y.div_assign(rhs);
self.z.div_assign(rhs);
self.w.div_assign(rhs);
}
}
impl Div<Vec4> for f32 {
type Output = Vec4;
#[inline]
fn div(self, rhs: Vec4) -> Self::Output {
Vec4 { x: self.div(rhs.x), y: self.div(rhs.y), z: self.div(rhs.z), w: self.div(rhs.w) }
}
}
impl Mul<Vec4> for Vec4 {
type Output = Self;
#[inline]
fn mul(self, rhs: Self) -> Self::Output {
Self { x: self.x.mul(rhs.x), y: self.y.mul(rhs.y), z: self.z.mul(rhs.z), w: self.w.mul(rhs.w) }
}
}
impl MulAssign<Vec4> for Vec4 {
#[inline]
fn mul_assign(&mut self, rhs: Self) {
self.x.mul_assign(rhs.x);
self.y.mul_assign(rhs.y);
self.z.mul_assign(rhs.z);
self.w.mul_assign(rhs.w)
}
}
impl Mul<f32> for Vec4 {
type Output = Self;
#[inline]
fn mul(self, rhs: f32) -> Self::Output {
Self { x: self.x.mul(rhs), y: self.y.mul(rhs), z: self.z.mul(rhs), w: self.w.mul(rhs) }
}
}
impl MulAssign<f32> for Vec4 {
#[inline]
fn mul_assign(&mut self, rhs: f32) {
self.x.mul_assign(rhs);
self.y.mul_assign(rhs);
self.z.mul_assign(rhs);
self.w.mul_assign(rhs);
}
}
impl Mul<Vec4> for f32 {
type Output = Vec4;
#[inline]
fn mul(self, rhs: Vec4) -> Self::Output {
Vec4 { x: self.mul(rhs.x), y: self.mul(rhs.y), z: self.mul(rhs.z), w: self.mul(rhs.w) }
}
}
impl Add<Vec4> for Vec4 {
type Output = Self;
#[inline]
fn add(self, rhs: Self) -> Self::Output {
Self { x: self.x.add(rhs.x), y: self.y.add(rhs.y), z: self.z.add(rhs.z), w: self.w.add(rhs.w) }
}
}
impl AddAssign<Vec4> for Vec4 {
#[inline]
fn add_assign(&mut self, rhs: Self) {
self.x.add_assign(rhs.x);
self.y.add_assign(rhs.y);
self.z.add_assign(rhs.z);
self.w.add_assign(rhs.w);
}
}
impl Sub<Vec4> for Vec4 {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self::Output {
Self { x: self.x.sub(rhs.x), y: self.y.sub(rhs.y), z: self.z.sub(rhs.z), w: self.w.sub(rhs.w) }
}
}
impl SubAssign<Vec4> for Vec4 {
#[inline]
fn sub_assign(&mut self, rhs: Vec4) {
self.x.sub_assign(rhs.x);
self.y.sub_assign(rhs.y);
self.z.sub_assign(rhs.z);
self.w.sub_assign(rhs.w);
}
}
impl Neg for Vec4 {
type Output = Self;
#[inline]
fn neg(self) -> Self::Output {
self * -1.0
}
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct Quat {
pub x: f32,
pub y: f32,
pub z: f32,
pub w: f32,
}
impl From<glam::Quat> for Quat {
fn from(val: glam::Quat) -> Self {
Quat { x: val.x, y: val.y, z: val.z, w: val.w }
}
}
impl From<Quat> for glam::Quat {
fn from(val: Quat) -> Self {
Self::from_xyzw(val.x, val.y, val.z, val.w)
}
}
impl From<glam::Vec4> for Quat {
fn from(val: glam::Vec4) -> Self {
Quat { x: val.x, y: val.y, z: val.z, w: val.w }
}
}
impl From<Quat> for glam::Vec4 {
fn from(val: Quat) -> Self {
Self::new(val.x, val.y, val.z, val.w)
}
}
impl From<[f32; 3]> for Quat {
fn from(val: [f32; 3]) -> Self {
Quat::from_angles(val[0], val[1], val[2])
}
}
impl From<Vec4> for Quat {
fn from(val: Vec4) -> Self {
Quat { x: val.x, y: val.y, z: val.z, w: val.w }
}
}
impl From<Quat> for Vec4 {
fn from(val: Quat) -> Self {
Self { x: val.x, y: val.y, z: val.z, w: val.w }
}
}
impl Default for Quat {
fn default() -> Self {
Quat::IDENTITY
}
}
impl PartialEq for Quat {
fn eq(&self, other: &Self) -> bool {
((self.x - other.x).abs() < 0.00001)
&& ((self.y - other.y).abs() < 0.00001)
&& ((self.z - other.z).abs() < 0.00001)
&& ((self.w - other.w).abs() < 0.00001)
}
}
unsafe extern "C" {
pub fn quat_difference(a: *const Quat, b: *const Quat) -> Quat;
pub fn quat_lookat(from: *const Vec3, at: *const Vec3) -> Quat;
pub fn quat_lookat_up(from: *const Vec3, at: *const Vec3, up: *const Vec3) -> Quat;
pub fn quat_from_angles(pitch_x_deg: f32, yaw_y_deg: f32, roll_z_deg: f32) -> Quat;
pub fn quat_slerp(a: *const Quat, b: *const Quat, t: f32) -> Quat;
pub fn quat_normalize(a: *const Quat) -> Quat;
pub fn quat_inverse(a: *const Quat) -> Quat;
pub fn quat_mul(a: *const Quat, b: *const Quat) -> Quat;
pub fn quat_mul_vec(a: *const Quat, b: *const Vec3) -> Vec3;
pub fn quat_to_axis_angle(a: Quat, out_axis: *mut Vec3, out_rotation_deg: *mut f32);
}
impl Quat {
pub const IDENTITY: Self = Self { x: 0.0, y: 0.0, z: 0.0, w: 1.0 };
pub const Y_180: Self = Self { x: 0.0, y: 1.0, z: 0.0, w: 0.0 };
pub const ZERO: Self = Self { x: 0.0, y: 0.0, z: 0.0, w: 0.0 };
#[inline]
pub const fn new(x: f32, y: f32, z: f32, w: f32) -> Self {
Self { x, y, z, w }
}
#[inline]
pub fn invert(&mut self) -> &mut Self {
let m = unsafe { quat_inverse(self) };
self.x = m.x;
self.y = m.y;
self.z = m.z;
self.w = m.w;
self
}
#[inline]
pub fn conjugate(&self) -> Self {
Self { x: -self.x, y: -self.y, z: -self.z, w: self.w }
}
#[inline]
pub fn normalize(&mut self) -> &mut Self {
let m = unsafe { quat_normalize(self) };
self.x = m.x;
self.y = m.y;
self.z = m.z;
self.w = m.w;
self
}
#[inline]
pub fn relative(&mut self, to: Self) -> &mut Self {
let m = to.mul(*self).mul(to.get_inverse());
self.x = m.x;
self.y = m.y;
self.z = m.z;
self.w = m.w;
self
}
#[inline]
pub fn rotate_point(&self, point: Vec3) -> Vec3 {
unsafe { quat_mul_vec(self, &point) }
}
#[inline]
pub fn to_angles_degrees(&self) -> [f32; 3] {
let mut axis = Vec3::ZERO;
let mut rotation: f32 = 0.0;
unsafe { quat_to_axis_angle(*self, &mut axis, &mut rotation) };
axis.normalize();
[rotation * axis.x, rotation * axis.y, rotation * axis.z]
}
#[inline]
pub fn to_angles(&self) -> [f32; 3] {
self.to_angles_degrees().map(|x| x.to_radians())
}
#[inline]
pub fn rotate(a: Quat, point: Vec3) -> Vec3 {
unsafe { quat_mul_vec(&a, &point) }
}
#[inline]
pub fn delta(from: Self, to: Self) -> Self {
unsafe { quat_difference(&from, &to) }
}
#[inline]
pub fn delta_dir(from: Vec3, to: Vec3) -> Self {
let c = Vec3::cross(from, to);
let mut out = Quat { x: c.x, y: c.y, z: c.z, w: 1.0 + Vec3::dot(from, to) };
*(out.normalize())
}
#[inline]
pub fn from_angles(pitch_x_deg: f32, yaw_y_deg: f32, roll_z_deg: f32) -> Self {
unsafe { quat_from_angles(pitch_x_deg, yaw_y_deg, roll_z_deg) }
}
#[inline]
pub fn look_at<V: Into<Vec3>>(from: V, at: V, up: Option<Vec3>) -> Self {
let from = from.into();
let at = at.into();
match up {
Some(up) => unsafe { quat_lookat_up(&from, &at, &up) },
None => unsafe { quat_lookat(&from, &at) },
}
}
#[inline]
pub fn look_dir<V: Into<Vec3>>(direction: V) -> Self {
let direction = direction.into();
unsafe { quat_lookat(&Vec3::ZERO, &direction) }
}
#[inline]
pub fn slerp(a: Self, b: Self, slerp: f32) -> Self {
unsafe { quat_slerp(&a, &b, slerp) }
}
#[inline]
pub fn get_inverse(&self) -> Self {
unsafe { quat_inverse(self) }
}
#[inline]
pub fn get_normalized(&self) -> Self {
unsafe { quat_normalize(self) }
}
#[inline]
pub fn get_as_vec4(&self) -> Vec4 {
Vec4 { x: self.x, y: self.y, z: self.z, w: self.w }
}
#[inline]
pub fn mul(&self, rhs: Self) -> Self {
unsafe { quat_mul(self, &rhs) }
}
#[inline]
pub fn mul_vec3<V: Into<Vec3>>(&self, rhs: V) -> Vec3 {
let rhs = rhs.into();
unsafe { quat_mul_vec(self, &rhs) }
}
#[inline]
pub const fn to_array(&self) -> [f32; 4] {
[self.x, self.y, self.z, self.w]
}
}
impl Display for Quat {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "[x:{}, y:{}, z:{}, w:{}]", self.x, self.y, self.z, self.w)
}
}
impl Mul<Quat> for Quat {
type Output = Self;
#[inline]
fn mul(self, rhs: Self) -> Self::Output {
unsafe { quat_mul(&self, &rhs) }
}
}
impl MulAssign<Quat> for Quat {
#[inline]
fn mul_assign(&mut self, rhs: Quat) {
*self = unsafe { quat_mul(self, &rhs) }
}
}
impl Mul<Vec3> for Quat {
type Output = Vec3;
fn mul(self, rhs: Vec3) -> Self::Output {
unsafe { quat_mul_vec(&self, &rhs) }
}
}
impl Sub<Quat> for Quat {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
unsafe { quat_difference(&self, &rhs) }
}
}
#[repr(C)]
#[derive(Copy, Clone)]
pub union Matrix {
pub row: [Vec4; 4usize],
pub m: [f32; 16usize],
}
impl From<glam::Mat4> for Matrix {
fn from(m: glam::Mat4) -> Self {
Matrix { row: [m.x_axis.into(), m.y_axis.into(), m.z_axis.into(), m.w_axis.into()] }
}
}
impl From<[f32; 16]> for Matrix {
fn from(s: [f32; 16]) -> Self {
Self { m: s }
}
}
impl From<Pose> for Matrix {
fn from(pose: Pose) -> Self {
Self::t_r(pose.position, pose.orientation)
}
}
impl std::fmt::Debug for Matrix {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{self}")
}
}
impl PartialEq for Matrix {
fn eq(&self, other: &Self) -> bool {
unsafe {
self.row[0] == other.row[0]
&& self.row[1] == other.row[1]
&& self.row[2] == other.row[2]
&& self.row[3] == other.row[3]
}
}
}
unsafe extern "C" {
pub fn pose_matrix_out(pose: *const Pose, out_result: *mut Matrix, scale: Vec3);
pub fn matrix_inverse(a: *const Matrix, out_Matrix: *mut Matrix);
pub fn matrix_invert(a: *const Matrix) -> Matrix;
pub fn matrix_mul(a: *const Matrix, b: *const Matrix, out_Matrix: *mut Matrix);
pub fn matrix_mul_direction(transform: *const Matrix, direction: *const Vec3) -> Vec3;
pub fn matrix_transform_pt(transform: Matrix, point: Vec3) -> Vec3;
pub fn matrix_transform_pt4(transform: Matrix, point: Vec4) -> Vec4;
pub fn matrix_transform_dir(transform: Matrix, direction: Vec3) -> Vec3;
pub fn matrix_transform_ray(transform: Matrix, ray: Ray) -> Ray;
pub fn matrix_transform_quat(transform: Matrix, rotation: Quat) -> Quat;
pub fn matrix_transform_pose(transform: Matrix, pose: Pose) -> Pose;
pub fn matrix_transpose(transform: Matrix) -> Matrix;
pub fn matrix_to_angles(transform: *const Matrix) -> Vec3;
pub fn matrix_trs(position: *const Vec3, orientation: *const Quat, scale: *const Vec3) -> Matrix;
pub fn matrix_t(position: Vec3) -> Matrix;
pub fn matrix_r(orientation: Quat) -> Matrix;
pub fn matrix_s(scale: Vec3) -> Matrix;
pub fn matrix_ts(position: Vec3, scale: Vec3) -> Matrix;
pub fn matrix_trs_out(out_result: *mut Matrix, position: *const Vec3, orientation: *const Quat, scale: *const Vec3);
pub fn matrix_perspective(fov_degrees: f32, aspect_ratio: f32, near_clip: f32, far_clip: f32) -> Matrix;
pub fn matrix_orthographic(width: f32, height: f32, near_clip: f32, far_clip: f32) -> Matrix;
pub fn matrix_decompose(
transform: *const Matrix,
out_position: *mut Vec3,
out_scale: *mut Vec3,
out_orientation: *mut Quat,
) -> Bool32T;
pub fn matrix_extract_translation(transform: *const Matrix) -> Vec3;
pub fn matrix_extract_scale(transform: *const Matrix) -> Vec3;
pub fn matrix_extract_rotation(transform: *const Matrix) -> Quat;
pub fn matrix_extract_pose(transform: *const Matrix) -> Pose;
}
impl Matrix {
pub const IDENTITY: Matrix = Matrix { row: [Vec4::X, Vec4::Y, Vec4::Z, Vec4::W] };
pub const Y_180: Matrix = Matrix { row: [Vec4::NEG_X, Vec4::Y, Vec4::NEG_Z, Vec4::W] };
pub const NULL: Matrix = Matrix { row: [Vec4::ZERO, Vec4::ZERO, Vec4::ZERO, Vec4::ZERO] };
#[inline]
pub fn orthographic(width: f32, height: f32, near_clip: f32, far_clip: f32) -> Self {
unsafe { matrix_orthographic(width, height, near_clip, far_clip) }
}
#[inline]
pub fn perspective(fov_degrees: f32, aspect_ratio: f32, near_clip: f32, far_clip: f32) -> Self {
unsafe { matrix_perspective(fov_degrees.to_radians(), aspect_ratio, near_clip, far_clip) }
}
#[inline]
pub fn perspective_focal(image_resolution: Vec2, focal_length_px: f32, near_clip: f32, far_clip: f32) -> Self {
let near_plane_dimensions = image_resolution / focal_length_px * near_clip;
let two_near = near_clip + near_clip;
let f_range = far_clip / (near_clip - far_clip);
Self {
m: [
two_near / near_plane_dimensions.x,
0.0,
0.0,
0.0,
0.0,
two_near / near_plane_dimensions.y,
0.0,
0.0,
0.0,
0.0,
f_range,
-1.0,
0.0,
0.0,
f_range * near_clip,
0.0,
],
}
}
#[inline]
pub fn look_at(from: Vec3, at: Vec3, up: Option<Vec3>) -> Self {
let up = up.unwrap_or(Vec3::UP);
let forward = (from - at).get_normalized();
let right_v = Vec3::perpendicular_right(forward, up).get_normalized();
let up_v = Vec3::perpendicular_right(right_v, forward).get_normalized();
Self {
m: [
right_v.x,
up_v.x,
forward.x,
0.0,
right_v.y,
up_v.y,
forward.y,
0.0,
right_v.z,
up_v.z,
forward.z,
0.0,
-Vec3::dot(from, right_v),
-Vec3::dot(from, up_v),
-Vec3::dot(from, forward),
1.0,
],
}
}
#[inline]
pub fn r<Q: Into<Quat>>(rotation: Q) -> Self {
unsafe { matrix_r(rotation.into()) }
}
#[inline]
pub fn update_r(&mut self, rotation: &Quat) {
unsafe { matrix_trs_out(self, &Vec3::ZERO, rotation, &Vec3::ONE) }
}
#[inline]
pub fn s<V: Into<Vec3>>(scale: V) -> Self {
unsafe { matrix_s(scale.into()) }
}
#[inline]
pub fn update_s(&mut self, scale: &Vec3) {
unsafe { matrix_trs_out(self, &Vec3::ZERO, &Quat::IDENTITY, scale) }
}
#[inline]
pub fn t<V: Into<Vec3>>(translation: V) -> Self {
unsafe { matrix_t(translation.into()) }
}
#[inline]
pub fn update_t(&mut self, translation: &Vec3) {
unsafe { matrix_trs_out(self, translation, &Quat::IDENTITY, &Vec3::ONE) }
}
#[deprecated(since = "0.40.0", note = "please use Matrix::t_r or Matrix::update_t_r")]
#[inline]
pub fn tr(translation: &Vec3, rotation: &Quat) -> Self {
unsafe { matrix_trs(translation, rotation, &Vec3::ONE) }
}
#[inline]
pub fn t_r<V: Into<Vec3>, Q: Into<Quat>>(translation: V, rotation: Q) -> Self {
unsafe { matrix_trs(&translation.into(), &rotation.into(), &Vec3::ONE) }
}
#[inline]
pub fn update_t_r(&mut self, translation: &Vec3, rotation: &Quat) {
unsafe { matrix_trs_out(self, translation, rotation, &Vec3::ONE) }
}
#[deprecated(since = "0.40.0", note = "please use Matrix::t_s or Matrix::update_t_s")]
#[inline]
pub fn ts<V: Into<Vec3>>(translation: V, scale: V) -> Self {
unsafe { matrix_ts(translation.into(), scale.into()) }
}
#[inline]
pub fn t_s<V: Into<Vec3>>(translation: V, scale: V) -> Self {
unsafe { matrix_ts(translation.into(), scale.into()) }
}
#[inline]
pub fn update_t_s(&mut self, translation: &Vec3, scale: &Vec3) {
unsafe { matrix_trs_out(self, translation, &Quat::IDENTITY, scale) }
}
#[deprecated(since = "0.40.0", note = "please use Matrix::t_r_s or Matrix::update_t_r_s")]
#[inline]
pub fn trs(translation: &Vec3, rotation: &Quat, scale: &Vec3) -> Self {
unsafe { matrix_trs(translation, rotation, scale) }
}
#[inline]
pub fn t_r_s<V: Into<Vec3>, Q: Into<Quat>>(translation: V, rotation: Q, scale: V) -> Self {
unsafe { matrix_trs(&translation.into(), &rotation.into(), &scale.into()) }
}
#[inline]
pub fn update_t_r_s(&mut self, translation: &Vec3, rotation: &Quat, scale: &Vec3) {
unsafe { matrix_trs_out(self, translation, rotation, scale) }
}
#[deprecated(since = "0.40.0", note = "please use Matrix::update_t_r, Matrix::update_t_s or Matrix::update_t_r_s")]
#[inline]
#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub fn trs_to_pointer(translation: &Vec3, rotation: &Quat, scale: &Vec3, out_result: *mut Matrix) {
unsafe { matrix_trs_out(out_result, translation, rotation, scale) }
}
#[inline]
pub fn invert(&mut self) -> &mut Self {
let m = unsafe { matrix_invert(self) };
unsafe {
self.row[0] = m.row[0];
self.row[1] = m.row[1];
self.row[2] = m.row[2];
self.row[3] = m.row[3];
}
self
}
#[inline]
pub fn transpose(&mut self) -> &mut Self {
let m = unsafe { matrix_transpose(*self) };
unsafe {
self.row[0] = m.row[0];
self.row[1] = m.row[1];
self.row[2] = m.row[2];
self.row[3] = m.row[3];
}
self
}
#[inline]
pub fn decompose(&self) -> Option<(Vec3, Vec3, Quat)> {
let position: *mut Vec3 = &mut Vec3 { x: 0.0, y: 0.0, z: 0.0 };
let scale: *mut Vec3 = &mut Vec3 { x: 0.0, y: 0.0, z: 0.0 };
let orientation: *mut Quat = &mut Quat { x: 0.0, y: 0.0, z: 0.0, w: 0.0 };
match unsafe { matrix_decompose(self, position, scale, orientation) } {
0 => None,
_ => unsafe { Some((*position, *scale, *orientation)) },
}
}
#[inline]
pub fn decompose_to_ptr(&self, out_position: &mut Vec3, out_orientation: &mut Quat, out_scale: &mut Vec3) -> bool {
unsafe { matrix_decompose(self, out_position, out_scale, out_orientation) != 0 }
}
#[inline]
pub fn transform_point<V: Into<Vec3>>(&self, point: V) -> Vec3 {
unsafe { matrix_transform_pt(*self, point.into()) }
}
#[inline]
pub fn transform_ray<R: Into<Ray>>(&self, ray: R) -> Ray {
unsafe { matrix_transform_ray(*self, ray.into()) }
}
#[inline]
pub fn transform_pose<P: Into<Pose>>(&self, pose: P) -> Pose {
unsafe { matrix_transform_pose(*self, pose.into()) }
}
#[inline]
pub fn transform_quat<Q: Into<Quat>>(&self, rotation: Q) -> Quat {
unsafe { matrix_transform_quat(*self, rotation.into()) }
}
#[inline]
pub fn transform_normal<V: Into<Vec3>>(&self, normal: V) -> Vec3 {
unsafe { matrix_transform_dir(*self, normal.into()) }
}
#[inline]
pub fn get_inverse(&self) -> Self {
let out: *mut Matrix = &mut Matrix { row: [Vec4::ZERO, Vec4::ZERO, Vec4::ZERO, Vec4::ZERO] };
unsafe {
matrix_inverse(self, out);
*out
}
}
#[inline]
pub fn get_inverse_to_ptr(&self, out: &mut Matrix) {
unsafe {
matrix_inverse(self, out);
}
}
#[inline]
pub fn get_pose(&self) -> Pose {
unsafe { matrix_extract_pose(self) }
}
#[inline]
pub fn get_rotation(&self) -> Quat {
unsafe { matrix_extract_rotation(self) }
}
#[inline]
pub fn get_scale(&self) -> Vec3 {
unsafe { matrix_extract_scale(self) }
}
#[inline]
pub fn get_translation(&self) -> Vec3 {
unsafe { matrix_extract_translation(self) }
}
#[inline]
pub fn get_transposed(&self) -> Self {
unsafe { matrix_transpose(*self) }
}
}
impl Display for Matrix {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
unsafe { write!(f, "[\r\n {},\r\n {},\r\n {},\r\n {}]", self.row[0], self.row[1], self.row[2], self.row[3]) }
}
}
impl Mul<Vec3> for Matrix {
type Output = Vec3;
fn mul(self, rhs: Vec3) -> Self::Output {
unsafe { matrix_transform_pt(self, rhs) }
}
}
impl MulAssign<Matrix> for Vec3 {
fn mul_assign(&mut self, rhs: Matrix) {
let res = unsafe { matrix_transform_pt(rhs, *self) };
self.x = res.x;
self.y = res.y;
self.z = res.z;
}
}
impl Mul<Matrix> for Vec3 {
type Output = Vec3;
fn mul(self, rhs: Matrix) -> Self::Output {
unsafe { matrix_transform_pt(rhs, self) }
}
}
impl Mul<Vec4> for Matrix {
type Output = Vec4;
fn mul(self, rhs: Vec4) -> Self::Output {
unsafe { matrix_transform_pt4(self, rhs) }
}
}
impl MulAssign<Matrix> for Vec4 {
fn mul_assign(&mut self, rhs: Matrix) {
let res = unsafe { matrix_transform_pt4(rhs, *self) };
self.x = res.x;
self.y = res.y;
self.z = res.z;
self.w = res.w
}
}
impl Mul<Matrix> for Vec4 {
type Output = Vec4;
fn mul(self, rhs: Matrix) -> Self::Output {
unsafe { matrix_transform_pt4(rhs, self) }
}
}
impl Mul<Ray> for Matrix {
type Output = Ray;
fn mul(self, rhs: Ray) -> Self::Output {
unsafe { matrix_transform_ray(self, rhs) }
}
}
impl MulAssign<Matrix> for Ray {
fn mul_assign(&mut self, rhs: Matrix) {
let res = unsafe { matrix_transform_ray(rhs, *self) };
self.position = res.position;
self.direction = res.direction;
}
}
impl Mul<Matrix> for Ray {
type Output = Ray;
fn mul(self, rhs: Matrix) -> Self::Output {
unsafe { matrix_transform_ray(rhs, self) }
}
}
impl Mul<Quat> for Matrix {
type Output = Quat;
fn mul(self, rhs: Quat) -> Self::Output {
unsafe { matrix_transform_quat(self, rhs) }
}
}
impl MulAssign<Matrix> for Quat {
fn mul_assign(&mut self, rhs: Matrix) {
let res = unsafe { matrix_transform_quat(rhs, *self) };
self.x = res.x;
self.y = res.y;
self.z = res.z;
self.w = res.w
}
}
impl Mul<Matrix> for Quat {
type Output = Quat;
fn mul(self, rhs: Matrix) -> Self::Output {
unsafe { matrix_transform_quat(rhs, self) }
}
}
impl Mul<Pose> for Matrix {
type Output = Pose;
fn mul(self, rhs: Pose) -> Self::Output {
unsafe { matrix_transform_pose(self, rhs) }
}
}
impl MulAssign<Matrix> for Pose {
fn mul_assign(&mut self, rhs: Matrix) {
let res = unsafe { matrix_transform_pose(rhs, *self) };
self.position = res.position;
self.orientation = res.orientation;
}
}
impl Mul<Matrix> for Pose {
type Output = Pose;
fn mul(self, rhs: Matrix) -> Self::Output {
unsafe { matrix_transform_pose(rhs, self) }
}
}
impl Mul<Matrix> for Matrix {
type Output = Self;
fn mul(self, rhs: Matrix) -> Self::Output {
let out: *mut Matrix = &mut Matrix { row: [Vec4::ZERO, Vec4::ZERO, Vec4::ZERO, Vec4::ZERO] };
unsafe {
matrix_mul(&self, &rhs, out);
*out
}
}
}
impl MulAssign<Matrix> for Matrix {
fn mul_assign(&mut self, rhs: Matrix) {
unsafe { matrix_mul(self, &rhs, self) };
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq)]
#[repr(C)]
pub struct Bounds {
pub center: Vec3,
pub dimensions: Vec3,
}
impl AsRef<Bounds> for Bounds {
fn as_ref(&self) -> &Bounds {
self
}
}
unsafe extern "C" {
pub fn bounds_ray_intersect(bounds: Bounds, ray: Ray, out_pt: *mut Vec3) -> Bool32T;
pub fn bounds_point_contains(bounds: Bounds, pt: Vec3) -> Bool32T;
pub fn bounds_line_contains(bounds: Bounds, pt1: Vec3, pt2: Vec3) -> Bool32T;
pub fn bounds_capsule_contains(bounds: Bounds, pt1: Vec3, pt2: Vec3, radius: f32) -> Bool32T;
pub fn bounds_grow_to_fit_pt(bounds: Bounds, pt: Vec3) -> Bounds;
pub fn bounds_grow_to_fit_box(bounds: Bounds, box_: Bounds, opt_box_transform: *const Matrix) -> Bounds;
pub fn bounds_transform(bounds: Bounds, transform: Matrix) -> Bounds;
}
impl Bounds {
#[inline]
pub fn new<V: Into<Vec3>>(center: V, dimensions: V) -> Bounds {
Bounds { center: center.into(), dimensions: dimensions.into() }
}
#[inline]
pub fn bounds_centered(dimensions: impl Into<Vec3>) -> Bounds {
Bounds { center: Vec3::ZERO, dimensions: dimensions.into() }
}
#[inline]
pub fn from_corner<V: Into<Vec3>>(bottom_left_back: V, dimensions: V) -> Bounds {
let dim = dimensions.into();
Bounds { center: bottom_left_back.into() + dim / 2.0, dimensions: dim }
}
#[inline]
pub fn from_corners<V: Into<Vec3>>(bottom_left_back: V, top_right_front: V) -> Bounds {
let blb = bottom_left_back.into();
let trf = top_right_front.into();
Bounds { center: blb / 2.0 + trf / 2.0, dimensions: (trf - blb).abs() }
}
#[inline]
pub fn grown_point(&mut self, pt: impl Into<Vec3>) -> &mut Self {
let b = unsafe { bounds_grow_to_fit_pt(*self, pt.into()) };
self.center = b.center;
self.dimensions = b.dimensions;
self
}
#[inline]
pub fn grown_box<M: Into<Matrix>>(&mut self, box_: impl AsRef<Bounds>, opt_box_transform: M) -> &mut Self {
let b = unsafe { bounds_grow_to_fit_box(*self, *(box_.as_ref()), &opt_box_transform.into()) };
self.center = b.center;
self.dimensions = b.dimensions;
self
}
#[inline]
pub fn scale(&mut self, scale: f32) -> &mut Self {
self.dimensions *= scale;
self.center *= scale;
self
}
#[inline]
pub fn scale_vec(&mut self, scale: impl Into<Vec3>) -> &mut Self {
let scale = scale.into();
self.dimensions *= scale;
self.center *= scale;
self
}
#[inline]
pub fn contains_point(&self, pt: impl Into<Vec3>) -> bool {
unsafe { bounds_point_contains(*self, pt.into()) != 0 }
}
#[inline]
pub fn contains_line<V3: Into<Vec3>>(&self, line_pt1: V3, line_pt2: V3) -> bool {
unsafe { bounds_line_contains(*self, line_pt1.into(), line_pt2.into()) != 0 }
}
#[inline]
pub fn contains_capsule<V3: Into<Vec3>>(&self, line_pt1: V3, line_pt2: V3, radius: f32) -> bool {
unsafe { bounds_capsule_contains(*self, line_pt1.into(), line_pt2.into(), radius) != 0 }
}
#[inline]
pub fn intersect<R: Into<Ray>>(&self, ray: R) -> Option<Vec3> {
let mut pt = Vec3::default();
let ray = ray.into();
match unsafe { bounds_ray_intersect(*self, ray, &mut pt) != 0 } {
true => Some(pt),
false => None,
}
}
#[inline]
pub fn scaled(&self, scale: f32) -> Self {
*self * scale
}
#[inline]
pub fn scaled_vec(&self, scale: impl Into<Vec3>) -> Self {
*self * scale.into()
}
#[inline]
pub fn transformed(&self, transform: impl Into<Matrix>) -> Self {
unsafe { bounds_transform(*self, transform.into()) }
}
#[inline]
pub fn tlc(&self) -> Vec3 {
self.center + self.dimensions.xy0() / 2.0
}
#[inline]
pub fn tlb(&self) -> Vec3 {
self.center + self.dimensions / 2.0
}
}
impl Display for Bounds {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "[center:{} dimensions:{}]", self.center, self.dimensions)
}
}
impl Mul<f32> for Bounds {
type Output = Bounds;
fn mul(self, rhs: f32) -> Self::Output {
Bounds { center: self.center * rhs, dimensions: self.dimensions * rhs }
}
}
impl MulAssign<f32> for Bounds {
fn mul_assign(&mut self, rhs: f32) {
self.center.mul_assign(rhs);
self.dimensions.mul_assign(rhs);
}
}
impl Mul<Bounds> for f32 {
type Output = Bounds;
fn mul(self, rhs: Bounds) -> Self::Output {
Bounds { center: rhs.center * self, dimensions: rhs.dimensions * self }
}
}
impl Mul<Vec3> for Bounds {
type Output = Bounds;
fn mul(self, rhs: Vec3) -> Self::Output {
Bounds { center: self.center * rhs, dimensions: self.dimensions * rhs }
}
}
impl MulAssign<Vec3> for Bounds {
fn mul_assign(&mut self, rhs: Vec3) {
self.center.mul_assign(rhs);
self.dimensions.mul_assign(rhs);
}
}
#[derive(Copy, Clone, Debug, Default)]
#[repr(C)]
pub struct Plane {
pub normal: Vec3,
pub d: f32,
}
impl AsRef<Plane> for Plane {
fn as_ref(&self) -> &Plane {
self
}
}
impl PartialEq for Plane {
fn eq(&self, other: &Self) -> bool {
self.normal == other.normal && self.d - other.d < 0.0001
}
}
unsafe extern "C" {
pub fn plane_from_points(p1: Vec3, p2: Vec3, p3: Vec3) -> Plane;
pub fn plane_from_ray(ray: Ray) -> Plane;
pub fn plane_ray_intersect(plane: Plane, ray: Ray, out_pt: *mut Vec3) -> Bool32T;
pub fn plane_line_intersect(plane: Plane, p1: Vec3, p2: Vec3, out_pt: *mut Vec3) -> Bool32T;
pub fn plane_point_closest(plane: Plane, pt: Vec3) -> Vec3;
}
impl Plane {
pub fn new<V: Into<Vec3>>(normal: V, d: f32) -> Plane {
Plane { normal: normal.into(), d }
}
#[inline]
pub fn from_point<V: Into<Vec3>>(point_on_plane: V, plane_normal: V) -> Plane {
let p_o_p = point_on_plane.into();
let normal = plane_normal.into();
Plane { normal, d: -Vec3::dot(p_o_p, normal) }
}
#[deprecated(since = "0.4.0", note = "Unstable! use `Plane::from_point` or `Plane::new` instead")]
#[inline]
pub fn from_points<V: Into<Vec3>>(point_on_plane1: V, point_on_plane2: V, point_on_plane3: V) -> Plane {
let p1 = point_on_plane1.into();
let p2 = point_on_plane2.into();
let p3 = point_on_plane3.into();
let dir1 = p2 - p1;
let dir2 = p2 - p3;
let mut normal = Vec3::cross(dir1, dir2).get_normalized();
if normal.z.is_nan() {
let dir1 = p1 - p3;
let dir2 = p1 - p2;
normal = Vec3::cross(dir1, dir2).get_normalized();
if normal.z.is_nan() {
let dir1 = p3 - p1;
let dir2 = p3 - p2;
normal = Vec3::cross(dir1, dir2).get_normalized();
}
}
Plane { normal, d: -Vec3::dot(p2, normal) }
}
#[inline]
pub fn closest<V: Into<Vec3>>(&self, to: V) -> Vec3 {
unsafe { plane_point_closest(*self, to.into()) }
}
#[inline]
pub fn intersect(&self, ray: Ray) -> Option<Vec3> {
let mut pt = Vec3::default();
match unsafe { plane_ray_intersect(*self, ray, &mut pt) != 0 } {
true => Some(pt),
false => None,
}
}
#[inline]
pub fn intersect_line<V: Into<Vec3>>(&self, line_start: V, line_end: V) -> Option<Vec3> {
let mut pt = Vec3::default();
match unsafe { plane_line_intersect(*self, line_start.into(), line_end.into(), &mut pt) != 0 } {
true => Some(pt),
false => None,
}
}
}
impl Display for Plane {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "[normal:{} distance:{}]", self.normal, self.d)
}
}
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Pose {
pub position: Vec3,
pub orientation: Quat,
}
impl From<Matrix> for Pose {
fn from(matrix: Matrix) -> Self {
matrix.get_pose()
}
}
impl Default for Pose {
fn default() -> Self {
Pose::IDENTITY
}
}
impl Pose {
pub const IDENTITY: Pose = Pose { position: Vec3::new(0.0, 0.0, 0.0), orientation: Quat::IDENTITY };
pub const ZERO: Pose = Pose { position: Vec3::new(0.0, 0.0, 0.0), orientation: Quat::ZERO };
#[inline]
pub fn new(position: impl Into<Vec3>, orientation: Option<Quat>) -> Self {
let orientation = orientation.unwrap_or(Quat::IDENTITY);
Self { position: position.into(), orientation }
}
#[inline]
pub fn lerp(a: impl Into<Pose>, b: impl Into<Pose>, percent: f32) -> Self {
let a = a.into();
let b = b.into();
Self {
position: Vec3::lerp(a.position, b.position, percent),
orientation: Quat::slerp(a.orientation, b.orientation, percent),
}
}
#[inline]
pub fn look_at(from: impl Into<Vec3>, at: impl Into<Vec3>) -> Self {
let from = from.into();
let at = at.into();
Self { position: from, orientation: Quat::look_at(from, at, None) }
}
#[inline]
pub fn to_matrix(&self, scale: Option<Vec3>) -> Matrix {
match scale {
Some(scale) => Matrix::t_r_s(self.position, self.orientation, scale),
None => Matrix::t_r(self.position, self.orientation),
}
}
#[inline]
pub fn to_matrix_inv(&self, scale: Option<Vec3>) -> Matrix {
let inv_orientation = self.orientation.conjugate();
match scale {
Some(scale) => {
let inv_scale = 1.0 / scale;
let inv_transform = inv_orientation.rotate_point(-self.position * inv_scale);
Matrix::t_r_s(inv_transform, inv_orientation, inv_scale)
}
None => {
let inv_transform = inv_orientation.rotate_point(-self.position);
Matrix::t_r(inv_transform, inv_orientation)
}
}
}
#[inline]
pub fn get_forward(&self) -> Vec3 {
self.orientation.mul_vec3(Vec3::FORWARD)
}
#[inline]
pub fn get_ray(&self) -> Ray {
Ray { position: self.position, direction: self.orientation.mul_vec3(Vec3::FORWARD) }
}
#[inline]
pub fn get_right(&self) -> Vec3 {
self.orientation.mul_vec3(Vec3::RIGHT)
}
#[inline]
pub fn get_up(&self) -> Vec3 {
self.orientation.mul_vec3(Vec3::UP)
}
#[inline]
pub fn is_zero(&self) -> bool {
self.orientation.x == 0.0 && self.orientation.y == 0.0 && self.orientation.z == 0.0 && self.orientation.w == 0.0
}
}
impl Display for Pose {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "[position:{} forward:{}]", self.position, self.orientation)
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq)]
#[repr(C)]
pub struct Sphere {
pub center: Vec3,
pub radius: f32,
}
impl AsRef<Sphere> for Sphere {
fn as_ref(&self) -> &Sphere {
self
}
}
unsafe extern "C" {
pub fn sphere_ray_intersect(sphere: Sphere, ray: Ray, out_pt: *mut Vec3) -> Bool32T;
pub fn sphere_point_contains(sphere: Sphere, pt: Vec3) -> Bool32T;
}
impl Sphere {
#[inline]
pub fn new<V: Into<Vec3>>(center: V, radius: f32) -> Sphere {
Sphere { center: center.into(), radius }
}
#[inline]
pub fn contains<V: Into<Vec3>>(&self, point: V) -> bool {
unsafe { sphere_point_contains(*self, point.into()) != 0 }
}
#[inline]
pub fn intersect(&self, ray: Ray) -> Option<Vec3> {
let mut pt = Vec3::default();
match unsafe { sphere_ray_intersect(*self, ray, &mut pt) != 0 } {
true => Some(pt),
false => None,
}
}
}
impl Display for Sphere {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "[center:{} radius:{}]", self.center, self.radius)
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
#[repr(C)]
pub struct Rect {
pub x: f32,
pub y: f32,
pub width: f32,
pub height: f32,
}
impl Default for Rect {
fn default() -> Self {
Self { x: 0.0, y: 0.0, width: 1.0, height: 1.0 }
}
}
impl Rect {
pub const fn new(x: f32, y: f32, width: f32, height: f32) -> Self {
Self { x, y, width, height }
}
}
#[derive(Default, Debug, Copy, Clone, PartialEq)]
#[repr(C)]
pub struct Ray {
pub position: Vec3,
pub direction: Vec3,
}
unsafe extern "C" {
pub fn ray_intersect_plane(ray: Ray, plane_pt: Vec3, plane_normal: Vec3, out_t: *mut f32) -> Bool32T;
pub fn ray_from_mouse(screen_pixel_pos: Vec2, out_ray: *mut Ray) -> Bool32T;
pub fn ray_point_closest(ray: Ray, pt: Vec3) -> Vec3;
}
impl Ray {
pub const ZERO: Self = Ray { position: Vec3::ZERO, direction: Vec3::ZERO };
#[inline]
pub fn new<V: Into<Vec3>>(pos: V, dir: V) -> Self {
Self { position: pos.into(), direction: dir.into() }
}
#[inline]
pub fn from_to<V: Into<Vec3>>(a: V, b: V) -> Ray {
let position = a.into();
let direction = b.into() - position;
Ray { position, direction }
}
#[inline]
pub fn get_at(&self, percent: f32) -> Vec3 {
self.position + self.direction * percent
}
#[inline]
pub fn closest<V: Into<Vec3>>(&self, to: V) -> Vec3 {
unsafe { ray_point_closest(*self, to.into()) }
}
#[inline]
pub fn intersect_plane(&self, plane: Plane) -> Option<Vec3> {
let mut pt = Vec3::default();
match unsafe { plane_ray_intersect(plane, *self, &mut pt) != 0 } {
true => Some(pt),
false => None,
}
}
#[inline]
pub fn intersect_sphere(&self, sphere: Sphere) -> Option<Vec3> {
let mut pt = Vec3::default();
match unsafe { sphere_ray_intersect(sphere, *self, &mut pt) != 0 } {
true => Some(pt),
false => None,
}
}
#[inline]
pub fn intersect_bounds(&self, bounds: Bounds) -> Option<Vec3> {
let mut pt = Vec3::default();
match unsafe { bounds_ray_intersect(bounds, *self, &mut pt) != 0 } {
true => Some(pt),
false => None,
}
}
#[inline]
pub fn intersect_mesh(&self, mesh: &Mesh, cull: Option<Cull>) -> Option<(Vec3, VindT)> {
let mut out_ray = Ray::default();
let mut out_inds = 0;
let cull = cull.unwrap_or(Cull::Back);
match unsafe { mesh_ray_intersect(mesh.0.as_ptr(), *self, cull, &mut out_ray, &mut out_inds) != 0 } {
true => Some((out_ray.position, out_inds)),
false => None,
}
}
#[inline]
#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub fn intersect_mesh_to_ptr(
&self,
mesh: &Mesh,
cull: Option<Cull>,
out_model_space_at: *mut Ray,
out_start_inds: *mut u32,
) -> bool {
let cull = cull.unwrap_or(Cull::Back);
unsafe { mesh_ray_intersect(mesh.0.as_ptr(), *self, cull, out_model_space_at, out_start_inds) != 0 }
}
#[inline]
pub fn intersect_model(&self, model: &Model, cull: Option<Cull>) -> Option<Vec3> {
let mut out_ray = Ray::default();
let cull = cull.unwrap_or(Cull::Back);
match unsafe { model_ray_intersect(model.0.as_ptr(), *self, cull, &mut out_ray) != 0 } {
true => Some(out_ray.position),
false => None,
}
}
#[inline]
#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub fn intersect_model_to_ptr(&self, model: &Model, cull: Option<Cull>, out_model_space_at: *mut Ray) -> bool {
let cull = cull.unwrap_or(Cull::Back);
unsafe { model_ray_intersect(model.0.as_ptr(), *self, cull, out_model_space_at) != 0 }
}
}
impl Display for Ray {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "[position:{} direction:{}]", self.position, self.direction)
}
}