use std::{mem::size_of, convert::TryInto, ops};
use field_offset::FieldOffset;
use crate::db_internal::{mat4_loadSIMD, mat4_storeSIMD, mat4_mulSIMD, mat4_transformSIMD};
#[repr(C)]
#[derive(Clone, Copy)]
pub struct Vector2 {
pub x: f32,
pub y: f32,
}
impl Vector2 {
pub const fn new(x: f32, y: f32) -> Vector2 {
return Vector2 { x: x, y: y };
}
pub const fn zero() -> Vector2 {
return Vector2 { x: 0.0, y: 0.0 };
}
pub const fn unit_x() -> Vector2 {
return Vector2 { x: 1.0, y: 0.0 };
}
pub const fn unit_y() -> Vector2 {
return Vector2 { x: 0.0, y: 1.0 };
}
pub fn distance_sq(lhs: &Vector2, rhs: &Vector2) -> f32 {
let dx = lhs.x - rhs.x;
let dy = lhs.y - rhs.y;
return (dx * dx) + (dy * dy);
}
pub fn distance(lhs: &Vector2, rhs: &Vector2) -> f32 {
let dx = lhs.x - rhs.x;
let dy = lhs.y - rhs.y;
return ((dx * dx) + (dy * dy)).sqrt();
}
pub fn length_sq(self) -> f32 {
return (self.x * self.x) + (self.y * self.y);
}
pub fn length(self) -> f32 {
return ((self.x * self.x) + (self.y * self.y)).sqrt();
}
pub fn normalize(&mut self) {
let mag = 1.0 / (self.x * self.x + self.y * self.y).sqrt();
self.x *= mag;
self.y *= mag;
}
pub fn normalized(&self) -> Vector2 {
let mag = 1.0 / (self.x * self.x + self.y * self.y).sqrt();
return Vector2 { x: self.x * mag, y: self.y * mag };
}
pub fn dot(lhs: &Vector2, rhs: &Vector2) -> f32 {
return (lhs.x * rhs.x) + (lhs.y * rhs.y);
}
}
impl ops::Add<Vector2> for Vector2 {
type Output = Vector2;
fn add(self, rhs: Vector2) -> Vector2 {
return Vector2 { x: self.x + rhs.x, y: self.y + rhs.y };
}
}
impl ops::Sub<Vector2> for Vector2 {
type Output = Vector2;
fn sub(self, rhs: Vector2) -> Vector2 {
return Vector2 { x: self.x - rhs.x, y: self.y - rhs.y };
}
}
impl ops::Mul<Vector2> for Vector2 {
type Output = Vector2;
fn mul(self, rhs: Vector2) -> Vector2 {
return Vector2 { x: self.x * rhs.x, y: self.y * rhs.y };
}
}
impl ops::Mul<f32> for Vector2 {
type Output = Vector2;
fn mul(self, rhs: f32) -> Vector2 {
return Vector2 { x: self.x * rhs, y: self.y * rhs };
}
}
impl ops::Mul<Vector2> for f32 {
type Output = Vector2;
fn mul(self, rhs: Vector2) -> Vector2 {
return Vector2 { x: self * rhs.x, y: self * rhs.y };
}
}
impl ops::Div<Vector2> for Vector2 {
type Output = Vector2;
fn div(self, rhs: Vector2) -> Vector2 {
return Vector2 { x: self.x / rhs.x, y: self.y / rhs.y };
}
}
impl ops::Div<f32> for Vector2 {
type Output = Vector2;
fn div(self, rhs: f32) -> Vector2 {
return Vector2 { x: self.x / rhs, y: self.y / rhs };
}
}
impl ops::Div<Vector2> for f32 {
type Output = Vector2;
fn div(self, rhs: Vector2) -> Vector2 {
return Vector2 { x: self / rhs.x, y: self / rhs.y };
}
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct Vector3 {
pub x: f32,
pub y: f32,
pub z: f32,
}
impl Vector3 {
pub const fn new(x: f32, y: f32, z: f32) -> Vector3 {
return Vector3 { x: x, y: y, z: z };
}
pub const fn zero() -> Vector3 {
return Vector3 { x: 0.0, y: 0.0, z: 0.0 };
}
pub const fn unit_x() -> Vector3 {
return Vector3 { x: 1.0, y: 0.0, z: 0.0 };
}
pub const fn unit_y() -> Vector3 {
return Vector3 { x: 0.0, y: 1.0, z: 0.0 };
}
pub const fn unit_z() -> Vector3 {
return Vector3 { x: 0.0, y: 0.0, z: 1.0 };
}
pub fn distance_sq(lhs: &Vector3, rhs: &Vector3) -> f32 {
let dx = lhs.x - rhs.x;
let dy = lhs.y - rhs.y;
let dz = lhs.z - rhs.z;
return (dx * dx) + (dy * dy) + (dz * dz);
}
pub fn distance(lhs: &Vector3, rhs: &Vector3) -> f32 {
let dx = lhs.x - rhs.x;
let dy = lhs.y - rhs.y;
let dz = lhs.z - rhs.z;
return ((dx * dx) + (dy * dy) + (dz * dz)).sqrt();
}
pub fn length_sq(self) -> f32 {
return (self.x * self.x) + (self.y * self.y) + (self.z * self.z);
}
pub fn length(self) -> f32 {
return ((self.x * self.x) + (self.y * self.y) + (self.z * self.z)).sqrt();
}
pub fn normalize(&mut self) {
let mag = 1.0 / (self.x * self.x + self.y * self.y + self.z * self.z).sqrt();
self.x *= mag;
self.y *= mag;
self.z *= mag;
}
pub fn normalized(&self) -> Vector3 {
let mag = 1.0 / (self.x * self.x + self.y * self.y + self.z * self.z).sqrt();
return Vector3 { x: self.x * mag, y: self.y * mag, z: self.z * mag };
}
pub fn dot(lhs: &Vector3, rhs: &Vector3) -> f32 {
return (lhs.x * rhs.x) + (lhs.y * rhs.y) + (lhs.z * rhs.z);
}
pub fn cross(lhs: &Vector3, rhs: &Vector3) -> Vector3 {
return Vector3 {
x: lhs.y * rhs.z - lhs.z * rhs.y,
y: -(lhs.x * rhs.z - lhs.z * rhs.x),
z: lhs.x * rhs.y - lhs.y * rhs.x
};
}
}
impl ops::Add<Vector3> for Vector3 {
type Output = Vector3;
fn add(self, rhs: Vector3) -> Vector3 {
return Vector3 { x: self.x + rhs.x, y: self.y + rhs.y, z: self.z + rhs.z };
}
}
impl ops::Sub<Vector3> for Vector3 {
type Output = Vector3;
fn sub(self, rhs: Vector3) -> Vector3 {
return Vector3 { x: self.x - rhs.x, y: self.y - rhs.y, z: self.z - rhs.z };
}
}
impl ops::Mul<Vector3> for Vector3 {
type Output = Vector3;
fn mul(self, rhs: Vector3) -> Vector3 {
return Vector3 { x: self.x * rhs.x, y: self.y * rhs.y, z: self.z * rhs.z };
}
}
impl ops::Mul<f32> for Vector3 {
type Output = Vector3;
fn mul(self, rhs: f32) -> Vector3 {
return Vector3 { x: self.x * rhs, y: self.y * rhs, z: self.z * rhs };
}
}
impl ops::Mul<Vector3> for f32 {
type Output = Vector3;
fn mul(self, rhs: Vector3) -> Vector3 {
return Vector3 { x: self * rhs.x, y: self * rhs.y, z: self * rhs.z };
}
}
impl ops::Div<Vector3> for Vector3 {
type Output = Vector3;
fn div(self, rhs: Vector3) -> Vector3 {
return Vector3 { x: self.x / rhs.x, y: self.y / rhs.y, z: self.z / rhs.z };
}
}
impl ops::Div<f32> for Vector3 {
type Output = Vector3;
fn div(self, rhs: f32) -> Vector3 {
return Vector3 { x: self.x / rhs, y: self.y / rhs, z: self.z / rhs };
}
}
impl ops::Div<Vector3> for f32 {
type Output = Vector3;
fn div(self, rhs: Vector3) -> Vector3 {
return Vector3 { x: self / rhs.x, y: self / rhs.y, z: self / rhs.z };
}
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct Vector4 {
pub x: f32,
pub y: f32,
pub z: f32,
pub w: f32,
}
impl Vector4 {
pub const fn new(x: f32, y: f32, z: f32, w: f32) -> Vector4 {
return Vector4 { x: x, y: y, z: z, w: w };
}
pub const fn zero() -> Vector4 {
return Vector4 { x: 0.0, y: 0.0, z: 0.0, w: 0.0 };
}
pub const fn unit_x() -> Vector4 {
return Vector4 { x: 1.0, y: 0.0, z: 0.0, w: 0.0 };
}
pub const fn unit_y() -> Vector4 {
return Vector4 { x: 0.0, y: 1.0, z: 0.0, w: 0.0 };
}
pub const fn unit_z() -> Vector4 {
return Vector4 { x: 0.0, y: 0.0, z: 1.0, w: 0.0 };
}
pub const fn unit_w() -> Vector4 {
return Vector4 { x: 0.0, y: 0.0, z: 0.0, w: 1.0 };
}
pub fn distance_sq(lhs: &Vector4, rhs: &Vector4) -> f32 {
let dx = lhs.x - rhs.x;
let dy = lhs.y - rhs.y;
let dz = lhs.z - rhs.z;
let dw = lhs.w - rhs.w;
return (dx * dx) + (dy * dy) + (dz * dz) + (dw * dw);
}
pub fn distance(lhs: &Vector4, rhs: &Vector4) -> f32 {
let dx = lhs.x - rhs.x;
let dy = lhs.y - rhs.y;
let dz = lhs.z - rhs.z;
let dw = lhs.w - rhs.w;
return ((dx * dx) + (dy * dy) + (dz * dz) + (dw * dw)).sqrt();
}
pub fn length_sq(self) -> f32 {
return (self.x * self.x) + (self.y * self.y) + (self.z * self.z) + (self.w * self.w);
}
pub fn length(self) -> f32 {
return ((self.x * self.x) + (self.y * self.y) + (self.z * self.z) + (self.w * self.w)).sqrt();
}
pub fn normalize(&mut self) {
let mag = 1.0 / (self.x * self.x + self.y * self.y + self.z * self.z + self.w * self.w).sqrt();
self.x *= mag;
self.y *= mag;
self.z *= mag;
self.w *= mag;
}
pub fn normalized(&self) -> Vector4 {
let mag = 1.0 / (self.x * self.x + self.y * self.y + self.z * self.z + self.w * self.w).sqrt();
return Vector4 { x: self.x * mag, y: self.y * mag, z: self.z * mag, w: self.w * mag };
}
pub fn dot(lhs: &Vector4, rhs: &Vector4) -> f32 {
return (lhs.x * rhs.x) + (lhs.y * rhs.y) + (lhs.z * rhs.z) + (lhs.w * rhs.w);
}
}
impl ops::Add<Vector4> for Vector4 {
type Output = Vector4;
fn add(self, rhs: Vector4) -> Vector4 {
return Vector4 { x: self.x + rhs.x, y: self.y + rhs.y, z: self.z + rhs.z, w: self.w + rhs.w };
}
}
impl ops::Sub<Vector4> for Vector4 {
type Output = Vector4;
fn sub(self, rhs: Vector4) -> Vector4 {
return Vector4 { x: self.x - rhs.x, y: self.y - rhs.y, z: self.z - rhs.z, w: self.w - rhs.w };
}
}
impl ops::Mul<Vector4> for Vector4 {
type Output = Vector4;
fn mul(self, rhs: Vector4) -> Vector4 {
return Vector4 { x: self.x * rhs.x, y: self.y * rhs.y, z: self.z * rhs.z, w: self.w * rhs.w };
}
}
impl ops::Mul<f32> for Vector4 {
type Output = Vector4;
fn mul(self, rhs: f32) -> Vector4 {
return Vector4 { x: self.x * rhs, y: self.y * rhs, z: self.z * rhs, w: self.w * rhs };
}
}
impl ops::Mul<Vector4> for f32 {
type Output = Vector4;
fn mul(self, rhs: Vector4) -> Vector4 {
return Vector4 { x: self * rhs.x, y: self * rhs.y, z: self * rhs.z, w: self * rhs.w };
}
}
impl ops::Div<Vector4> for Vector4 {
type Output = Vector4;
fn div(self, rhs: Vector4) -> Vector4 {
return Vector4 { x: self.x / rhs.x, y: self.y / rhs.y, z: self.z / rhs.z, w: self.w / rhs.w };
}
}
impl ops::Div<f32> for Vector4 {
type Output = Vector4;
fn div(self, rhs: f32) -> Vector4 {
return Vector4 { x: self.x / rhs, y: self.y / rhs, z: self.z / rhs, w: self.w / rhs };
}
}
impl ops::Div<Vector4> for f32 {
type Output = Vector4;
fn div(self, rhs: Vector4) -> Vector4 {
return Vector4 { x: self / rhs.x, y: self / rhs.y, z: self / rhs.z, w: self / rhs.w };
}
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct Quaternion {
pub x: f32,
pub y: f32,
pub z: f32,
pub w: f32,
}
impl Quaternion {
pub const fn new(x: f32, y: f32, z: f32, w: f32) -> Quaternion {
return Quaternion { x: x, y: y, z: z, w: w };
}
pub const fn identity() -> Quaternion {
return Quaternion { x: 0.0, y: 0.0, z: 0.0, w: 1.0 };
}
pub fn from_euler(euler_angles: Vector3) -> Quaternion {
let cx = (euler_angles.x * 0.5).cos();
let sx = (euler_angles.x * 0.5).sin();
let cy = (euler_angles.y * 0.5).cos();
let sy = (euler_angles.y * 0.5).sin();
let cz = (euler_angles.z * 0.5).cos();
let sz = (euler_angles.z * 0.5).sin();
return Quaternion {
x: sx * cy * cz - cx * sy * sz,
y: cx * sy * cz + sx * cy * sz,
z: cx * cy * sz - sx * sy * cz,
w: cx * cy * cz + sx * sy * sz,
};
}
pub fn normalize(&mut self) {
let mag = 1.0 / (self.x * self.x + self.y * self.y + self.z * self.z + self.w * self.w).sqrt();
self.x *= mag;
self.y *= mag;
self.z *= mag;
self.w *= mag;
}
pub fn normalized(&self) -> Quaternion {
let mag = 1.0 / (self.x * self.x + self.y * self.y + self.z * self.z + self.w * self.w).sqrt();
return Quaternion { x: self.x * mag, y: self.y * mag, z: self.z * mag, w: self.w * mag };
}
pub fn invert(&mut self) {
let n = 1.0 / (self.x * self.x + self.y * self.y + self.z * self.z + self.w * self.w);
self.x *= -n;
self.y *= -n;
self.z *= -n;
self.w *= n;
}
}
impl ops::Mul<Quaternion> for Quaternion {
type Output = Quaternion;
fn mul(self, rhs: Quaternion) -> Quaternion {
let x = self.x * rhs.w + self.y * rhs.z - self.z * rhs.y + self.w * rhs.x;
let y = -self.x * rhs.z + self.y * rhs.w + self.z * rhs.x + self.w * rhs.y;
let z = self.x * rhs.y - self.y * rhs.x + self.z * rhs.w + self.w * rhs.z;
let w = -self.x * rhs.x - self.y * rhs.y - self.z * rhs.z + self.w * rhs.w;
return Quaternion { x: x, y: y, z: z, w: w };
}
}
impl ops::Mul<Vector3> for Quaternion {
type Output = Vector3;
fn mul(self, rhs: Vector3) -> Vector3 {
let x = 2.0 * (self.y * rhs.z - self.z * rhs.y);
let y = 2.0 * (self.z * rhs.x - self.x * rhs.z);
let z = 2.0 * (self.x * rhs.y - self.y * rhs.x);
let rx = rhs.x + x * self.w + (self.y * z - self.z * y);
let ry = rhs.y + y * self.w + (self.z * x - self.x * z);
let rz = rhs.z + z * self.w + (self.x * y - self.y * x);
return Vector3 { x: rx, y: ry, z: rz };
}
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct Matrix4x4 {
pub m: [[f32;4];4],
}
impl Matrix4x4 {
pub const fn identity() -> Matrix4x4 {
return Matrix4x4 { m: [
[1.0, 0.0, 0.0, 0.0],
[0.0, 1.0, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
[0.0, 0.0, 0.0, 1.0],
] };
}
pub fn translation(translation: Vector3) -> Matrix4x4 {
return Matrix4x4 { m: [
[1.0, 0.0, 0.0, 0.0],
[0.0, 1.0, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
[translation.x, translation.y, translation.z, 1.0],
] };
}
pub fn scale(scale: Vector3) -> Matrix4x4 {
return Matrix4x4 { m: [
[scale.x, 0.0, 0.0, 0.0],
[0.0, scale.y, 0.0, 0.0],
[0.0, 0.0, scale.z, 0.0],
[0.0, 0.0, 0.0, 1.0],
] };
}
pub fn rotation(rotation: Quaternion) -> Matrix4x4 {
let num9 = rotation.x * rotation.x;
let num8 = rotation.y * rotation.y;
let num7 = rotation.z * rotation.z;
let num6 = rotation.x * rotation.y;
let num5 = rotation.z * rotation.w;
let num4 = rotation.z * rotation.x;
let num3 = rotation.y * rotation.w;
let num2 = rotation.y * rotation.z;
let num = rotation.x * rotation.w;
let mut result = Matrix4x4::identity();
result.m[0][0] = 1.0 - (2.0 * (num8 + num7));
result.m[0][1] = 2.0 * (num6 + num5);
result.m[0][2] = 2.0 * (num4 - num3);
result.m[0][3] = 0.0;
result.m[1][0] = 2.0 * (num6 - num5);
result.m[1][1] = 1.0 - (2.0 * (num7 + num9));
result.m[1][2] = 2.0 * (num2 + num);
result.m[1][3] = 0.0;
result.m[2][0] = 2.0 * (num4 + num3);
result.m[2][1] = 2.0 * (num2 - num);
result.m[2][2] = 1.0 - (2.0 * (num8 + num9));
result.m[2][3] = 0.0;
result.m[3][0] = 0.0;
result.m[3][1] = 0.0;
result.m[3][2] = 0.0;
result.m[3][3] = 1.0;
return result;
}
pub fn projection_ortho(left: f32, right: f32, top: f32, bottom: f32, near: f32, far: f32) -> Matrix4x4 {
let scale_x = 2.0 / (right - left);
let scale_y = 2.0 / (top - bottom);
let scale_z = 1.0 / (near - far);
let mut mat = Matrix4x4::identity();
mat.m[0][0] = scale_x;
mat.m[1][1] = scale_y;
mat.m[2][2] = scale_z;
mat.m[3][0] = (left + right) / (left - right);
mat.m[3][1] = (top + bottom) / (bottom - top);
mat.m[3][2] = near / (near - far);
return mat;
}
pub fn projection_ortho_aspect(aspect_ratio: f32, scale: f32, near: f32, far: f32) -> Matrix4x4 {
let extent_x = scale * aspect_ratio * 0.5;
let extent_y = scale * 0.5;
return Matrix4x4::projection_ortho(-extent_x, extent_x, extent_y, -extent_y, near, far);
}
pub fn projection_perspective(aspect_ratio: f32, field_of_view: f32, near: f32, far: f32) -> Matrix4x4 {
let top = (field_of_view * 0.5).tan() * near;
let bottom = -top;
let right = top * aspect_ratio;
let left = -right;
let height = top - bottom;
let width = right - left;
let two_n = 2.0 * near;
let mut mat = Matrix4x4 {m: [
[ 0.0, 0.0, 0.0, 0.0 ],
[ 0.0, 0.0, 0.0, 0.0 ],
[ 0.0, 0.0, 0.0, 0.0 ],
[ 0.0, 0.0, 0.0, 0.0 ],
]};
mat.m[0][0] = two_n / width;
mat.m[1][1] = two_n / height;
mat.m[2][2] = far / (near - far);
mat.m[2][3] = -1.0;
mat.m[3][2] = (near * far) /
(near - far);
return mat;
}
pub fn load_identity_simd() {
let m = Matrix4x4::identity();
Matrix4x4::load_simd(&m);
}
pub fn load_simd(matrix: &Matrix4x4) {
unsafe { mat4_loadSIMD(matrix) };
}
pub fn store_simd(matrix: &mut Matrix4x4) {
unsafe { mat4_storeSIMD(matrix) };
}
pub fn mul_simd(matrix: &Matrix4x4) {
unsafe { mat4_mulSIMD(matrix) };
}
pub fn transform_vector_simd(data: &mut [Vector4]) {
unsafe {
let ptr = data.as_mut_ptr();
let stride = size_of::<Vector4>();
mat4_transformSIMD(ptr, ptr, data.len().try_into().unwrap(), stride.try_into().unwrap());
}
}
pub fn transform_vertex_simd<T>(data: &mut [T], field: FieldOffset<T,Vector4>) {
unsafe {
let fieldref = field.apply_ptr_mut(data.as_mut_ptr());
let stride = size_of::<T>();
mat4_transformSIMD(fieldref, fieldref, data.len().try_into().unwrap(), stride.try_into().unwrap());
}
}
}
impl ops::Mul<Vector4> for Matrix4x4 {
type Output = Vector4;
fn mul(self, rhs: Vector4) -> Vector4 {
let x = (rhs.x * self.m[0][0]) + (rhs.y * self.m[1][0]) + (rhs.z * self.m[2][0]) + (rhs.w * self.m[3][0]);
let y = (rhs.x * self.m[0][1]) + (rhs.y * self.m[1][1]) + (rhs.z * self.m[2][1]) + (rhs.w * self.m[3][1]);
let z = (rhs.x * self.m[0][2]) + (rhs.y * self.m[1][2]) + (rhs.z * self.m[2][2]) + (rhs.w * self.m[3][2]);
let w = (rhs.x * self.m[0][3]) + (rhs.y * self.m[1][3]) + (rhs.z * self.m[2][3]) + (rhs.w * self.m[3][3]);
return Vector4 { x: x, y: y, z: z, w: w };
}
}