use crate::scalar::*;
use crate::vector::*;
use crate::matrix::*;
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct Dimension<T : Scalar> {
pub width: T,
pub height: T
}
impl<T: Scalar> Dimension<T> {
pub fn new(width: T, height: T) -> Self { Self { width, height} }
}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct Rect<T : Scalar> {
pub x: T,
pub y: T,
pub width: T,
pub height: T
}
impl<T: Scalar> Rect<T> {
pub fn new(x: T, y: T, width: T, height: T) -> Self { Self { x, y, width, height} }
pub fn from(minVec: &Vector2<T>, maxVec: &Vector2<T>) -> Self {
let minX = T::min(minVec.x, maxVec.x);
let minY = T::min(minVec.y, maxVec.y);
let maxX = T::max(minVec.x, maxVec.x);
let maxY = T::max(minVec.y, maxVec.y);
Self {
x: minX,
y: minY,
width: maxX - minX,
height: maxY - minY
}
}
pub fn min(&self) -> Vector2<T> { Vector2::new(self.x, self.y) }
pub fn max(&self) -> Vector2<T> { Vector2::new(self.x + self.width, self.y + self.height) }
pub fn intersect(&self, other: &Self) -> Option<Self> {
let smx = self.max();
let smn = self.min();
let omx = other.max();
let omn = other.min();
if smx.x < omn.x || smx.y < omn.y || smn.x > omx.x || smn.y > omx.y {
return None
}
let minVec = Vector2::max(&self.min(), &other.min());
let maxVec = Vector2::min(&self.max(), &other.max());
Some(Self::from(&minVec, &maxVec))
}
pub fn contains(&self, p: &Vector2<T>) -> bool {
p.x >= self.x && p.y >= self.y && p.x <= self.x + self.width && p.y <= self.y + self.height
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct Box3<T : Scalar> {
pub min: Vector3<T>,
pub max: Vector3<T>,
}
impl<T: Scalar> Box3<T> {
pub fn new(v0: &Vector3<T>, v1: &Vector3<T>) -> Self { Self { min: Vector3::min(v0, v1), max: Vector3::max(v0, v1) } }
pub fn center(&self) -> Vector3<T> { (self.max + self.min) * T::half() }
pub fn extent(&self) -> Vector3<T> { self.max - self.center() }
pub fn overlap(&self, other: &Self) -> bool {
if self.max.x < other.min.x { return false }
if self.max.y < other.min.y { return false }
if self.max.z < other.min.z { return false }
if self.min.x > other.max.x { return false }
if self.min.x > other.max.x { return false }
if self.min.x > other.max.x { return false }
return true
}
pub fn add(&self, p: &Vector3<T>) -> Self {
Self {
min: Vector3::min(&p, &self.min),
max: Vector3::max(&p, &self.max),
}
}
pub fn subdivide(&self) -> [Self; 8] {
let cubeTable : [Vector3<i32>; 8] = [
Vector3::new(0, 1, 0),
Vector3::new(1, 1, 0),
Vector3::new(1, 1, 1),
Vector3::new(0, 1, 1),
Vector3::new(0, 0, 0),
Vector3::new(1, 0, 0),
Vector3::new(1, 0, 1),
Vector3::new(0, 0, 1)
];
let ps: [Vector3<T>; 2] = [ self.min, self.max ];
let mut vs = [Vector3::zero(); 8];
for i in 0..8 {
vs[i] = Vector3::new(ps[cubeTable[i].x as usize].x, ps[cubeTable[i].y as usize].y, ps[cubeTable[i].z as usize].z);
}
let c = self.center();
let mut out = [Box3 { min: Vector3::zero(), max:Vector3::zero() }; 8];
for i in 0..8 {
out[i] = Self::new(&Vector3::min(&c, &vs[i]), &Vector3::max(&c, &vs[i]));
}
out
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct Line2<T : Scalar> {
pub p: Vector2<T>,
pub d: Vector2<T>,
}
impl<T: Scalar> Line2<T> {
pub fn new(p: &Vector2<T>, d: &Vector2<T>) -> Self { Self { p: *p, d: *d } }
pub fn fromStartEnd(s: &Vector2<T>, e: &Vector2<T>) -> Self { Self { p: *s, d: (*e - *s) } }
pub fn normalize(&self) -> Self { Self { p: self.p, d: Vector2::normalize(&self.d) }}
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct Line3<T : Scalar> {
pub p: Vector3<T>,
pub d: Vector3<T>,
}
impl<T: Scalar> Line3<T> {
pub fn new(p: &Vector3<T>, d: &Vector3<T>) -> Self { Self { p: *p, d: *d } }
pub fn fromStartEnd(s: &Vector3<T>, e: &Vector3<T>) -> Self { Self { p: *s, d: (*e - *s) } }
pub fn normalize(&self) -> Self { Self { p: self.p, d: Vector3::normalize(&self.d) }}
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct Segment3<T : Scalar> {
pub s: Vector3<T>,
pub e: Vector3<T>,
}
impl<T: Scalar> Segment3<T> {
pub fn new(s: &Vector3<T>, e: &Vector3<T>) -> Self { Self { s: *s, e: *e } }
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct Ray3<T : Scalar> {
pub start: Vector3<T>,
pub direction: Vector3<T>,
}
impl<T: Scalar> Ray3<T> {
pub fn new(start: &Vector3<T>, direction: &Vector3<T>) -> Self {
Self { start: *start, direction: Vector3::normalize(direction) }
}
pub fn intersect(&self, p: &Plane<T>) -> Option<Vector3<T>> {
let n = p.normal();
let t : T = -(p.d + Vector3::dot(&n, &self.start)) / Vector3::dot(&n, &self.direction);
if t < T::zero() {
None
} else {
Some(self.direction * t + self.start)
}
}
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct Sphere3<T: FloatNum> {
pub center : Vector3<T>,
pub radius : T,
}
impl<T: FloatNum> Sphere3<T> {
pub fn new(center: Vector3<T>, radius: T) -> Self {
Self {
center : center,
radius : radius
}
}
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct Tri3<T: FloatNum> {
vertices: [Vector3<T>; 3],
}
impl<T: FloatNum> Tri3<T> {
pub fn new(vertices: [Vector3<T>; 3]) -> Self { Self { vertices: vertices } }
pub fn vertices(&self) -> &[Vector3<T>; 3] { &self.vertices }
pub fn barycentricCoordinates(&self, pt: &Vector3<T>) -> Vector3<T> {
let v0 = self.vertices[0];
let v1 = self.vertices[1];
let v2 = self.vertices[2];
let m = Matrix3::new(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, v2.x, v2.y, v2.z);
m.inverse() * *pt
}
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct Plane<T : Scalar> {
a: T,
b: T,
c: T,
d: T
}
impl<T: Scalar> Plane<T> {
pub fn new(n: &Vector3<T>, p: &Vector3<T>) -> Self { let norm = Vector3::normalize(n); let d = Vector3::dot(&norm, p); Self { a: norm.x, b: norm.y, c: norm.z, d: -d } }
pub fn normal(&self) -> Vector3<T> { Vector3::new(self.a, self.b, self.c) }
pub fn constant(&self) -> T { self.d }
pub fn fromTri(v0: &Vector3<T>, v1: &Vector3<T>, v2: &Vector3<T>) -> Self { let n = triNormal(v0, v1, v2); Self::new(&n, v0) }
pub fn fromQuad(v0: &Vector3<T>, v1: &Vector3<T>, v2: &Vector3<T>, v3: &Vector3<T>) -> Self {
let n = quadNormal(v0, v1, v2, v3);
let c = (*v0 + *v1 + *v2 + *v3) * T::quarter();
Self::new(&n, &c)
}
pub fn intersect(&self, r: &Ray3<T>) -> Option<Vector3<T>> {
r.intersect(self)
}
}
pub fn triNormal<T: Scalar>(v0: &Vector3<T>, v1: &Vector3<T>, v2: &Vector3<T>) -> Vector3<T> {
let v10 = *v1 - *v0;
let v20 = *v2 - *v0;
Vector3::normalize(&Vector3::cross(&v10, &v20))
}
pub fn quadNormal<T: Scalar>(v0: &Vector3<T>, v1: &Vector3<T>, v2: &Vector3<T>, v3: &Vector3<T>) -> Vector3<T> {
let v20 = *v2 - *v0;
let v31 = *v3 - *v1;
Vector3::normalize(&Vector3::cross(&v20, &v31))
}