rtiow: move vec3 to separate crate so it can be used elsewhere.
This commit is contained in:
10
rtiow/vec3/Cargo.toml
Normal file
10
rtiow/vec3/Cargo.toml
Normal file
@@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "vec3"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "1.0.152", features = ["serde_derive"] }
|
||||
serde_derive = "1.0.152"
|
||||
2
rtiow/vec3/src/lib.rs
Normal file
2
rtiow/vec3/src/lib.rs
Normal file
@@ -0,0 +1,2 @@
|
||||
mod vec3;
|
||||
pub use vec3::*;
|
||||
274
rtiow/vec3/src/vec3.rs
Normal file
274
rtiow/vec3/src/vec3.rs
Normal file
@@ -0,0 +1,274 @@
|
||||
use std::{
|
||||
convert::From,
|
||||
fmt,
|
||||
num::ParseFloatError,
|
||||
ops::{Add, Div, Index, Mul, Neg, Sub},
|
||||
str,
|
||||
};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Default, Debug, Deserialize, Serialize, PartialEq, Copy, Clone)]
|
||||
pub struct Vec3 {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
pub z: f32,
|
||||
}
|
||||
|
||||
pub fn cross(v1: Vec3, v2: Vec3) -> Vec3 {
|
||||
Vec3 {
|
||||
x: v1.y * v2.z - v1.z * v2.y,
|
||||
y: v1.z * v2.x - v1.x * v2.z,
|
||||
z: v1.x * v2.y - v1.y * v2.x,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dot(v1: Vec3, v2: Vec3) -> f32 {
|
||||
v1.x * v2.x + v1.y * v2.y + v1.z * v2.z
|
||||
}
|
||||
|
||||
impl Vec3 {
|
||||
pub fn new(x: f32, y: f32, z: f32) -> Vec3 {
|
||||
Vec3 { x, y, z }
|
||||
}
|
||||
|
||||
pub fn min(self) -> f32 {
|
||||
self.x.min(self.y).min(self.z)
|
||||
}
|
||||
|
||||
pub fn max(self) -> f32 {
|
||||
self.x.max(self.y).max(self.z)
|
||||
}
|
||||
|
||||
pub fn length(self) -> f32 {
|
||||
self.squared_length().sqrt()
|
||||
}
|
||||
|
||||
pub fn squared_length(self) -> f32 {
|
||||
self.x * self.x + self.y * self.y + self.z * self.z
|
||||
}
|
||||
|
||||
pub fn unit_vector(self) -> Vec3 {
|
||||
self / self.length()
|
||||
}
|
||||
|
||||
pub fn make_unit_vector(&mut self) {
|
||||
*self = self.unit_vector();
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[f32; 3]> for Vec3 {
|
||||
fn from(v: [f32; 3]) -> Self {
|
||||
Vec3 {
|
||||
x: v[0],
|
||||
y: v[1],
|
||||
z: v[2],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Vec3 {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{} {} {}", self.x, self.y, self.z)
|
||||
}
|
||||
}
|
||||
|
||||
impl str::FromStr for Vec3 {
|
||||
type Err = ParseFloatError;
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let coords: Vec<&str> = s.split(' ').collect();
|
||||
Ok(Vec3 {
|
||||
x: coords[0].parse::<f32>()?,
|
||||
y: coords[1].parse::<f32>()?,
|
||||
z: coords[2].parse::<f32>()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<f32> for Vec3 {
|
||||
type Output = Vec3;
|
||||
|
||||
fn add(self, r: f32) -> Vec3 {
|
||||
Vec3 {
|
||||
x: self.x + r,
|
||||
y: self.y + r,
|
||||
z: self.z + r,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for Vec3 {
|
||||
type Output = Vec3;
|
||||
|
||||
fn add(self, r: Vec3) -> Vec3 {
|
||||
Vec3 {
|
||||
x: self.x + r.x,
|
||||
y: self.y + r.y,
|
||||
z: self.z + r.z,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<Vec3> for f32 {
|
||||
type Output = Vec3;
|
||||
|
||||
fn div(self, r: Vec3) -> Vec3 {
|
||||
Vec3 {
|
||||
x: self / r.x,
|
||||
y: self / r.y,
|
||||
z: self / r.z,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<f32> for Vec3 {
|
||||
type Output = Vec3;
|
||||
|
||||
fn div(self, r: f32) -> Vec3 {
|
||||
Vec3 {
|
||||
x: self.x / r,
|
||||
y: self.y / r,
|
||||
z: self.z / r,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<usize> for Vec3 {
|
||||
type Output = f32;
|
||||
fn index(&self, idx: usize) -> &f32 {
|
||||
match idx {
|
||||
0 => &self.x,
|
||||
1 => &self.y,
|
||||
2 => &self.z,
|
||||
_ => panic!("idx {} out of range for vec3", idx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul for Vec3 {
|
||||
type Output = Vec3;
|
||||
|
||||
fn mul(self, r: Vec3) -> Vec3 {
|
||||
Vec3 {
|
||||
x: self.x * r.x,
|
||||
y: self.y * r.y,
|
||||
z: self.z * r.z,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Vec3> for f32 {
|
||||
type Output = Vec3;
|
||||
|
||||
fn mul(self, v: Vec3) -> Vec3 {
|
||||
Vec3 {
|
||||
x: v.x * self,
|
||||
y: v.y * self,
|
||||
z: v.z * self,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<f32> for Vec3 {
|
||||
type Output = Vec3;
|
||||
|
||||
fn mul(self, r: f32) -> Vec3 {
|
||||
Vec3 {
|
||||
x: self.x * r,
|
||||
y: self.y * r,
|
||||
z: self.z * r,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Neg for Vec3 {
|
||||
type Output = Vec3;
|
||||
|
||||
fn neg(self) -> Vec3 {
|
||||
-1. * self
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub for Vec3 {
|
||||
type Output = Vec3;
|
||||
|
||||
fn sub(self, r: Vec3) -> Vec3 {
|
||||
Vec3 {
|
||||
x: self.x - r.x,
|
||||
y: self.y - r.y,
|
||||
z: self.z - r.z,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::{f32::consts::PI, str::FromStr};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn vec_add() {
|
||||
let v0 = Vec3::new(1., 2., 3.);
|
||||
let v1 = Vec3::new(1., 1., 1.);
|
||||
assert_eq!(v0 + v1, Vec3::new(2., 3., 4.));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vec_div() {
|
||||
let v0 = Vec3::new(1., 2., 4.);
|
||||
assert_eq!(v0 / 2., Vec3::new(0.5, 1., 2.));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vec_mul() {
|
||||
let v0 = Vec3::new(1., 2., 4.);
|
||||
assert_eq!(v0 * 0.5, Vec3::new(0.5, 1., 2.));
|
||||
assert_eq!(v0 * v0, Vec3::new(1., 4., 16.));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vec_sub() {
|
||||
let v0 = Vec3::new(1., 2., 3.);
|
||||
let v1 = Vec3::new(1., 1., 1.);
|
||||
assert_eq!(v0 - v1, Vec3::new(0., 1., 2.));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vec_idx() {
|
||||
let v0 = Vec3::new(1., 2., 3.);
|
||||
assert_eq!(v0[2], 3.);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vec_display() {
|
||||
let v0 = Vec3::new(1., 2., 3.);
|
||||
assert_eq!(format!("{}", v0), "1 2 3".to_owned());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vec_from_str() {
|
||||
assert_eq!(Vec3::from_str("1. 2. 3.").unwrap(), Vec3::new(1., 2., 3.));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vec_str_roundtrip() {
|
||||
let v = Vec3::from_str("1 2 3").unwrap();
|
||||
let s = format!("{}", v);
|
||||
assert_eq!(v, Vec3::from_str(&s).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vec_dot() {
|
||||
let v0 = Vec3::new(1., 0., 0.);
|
||||
let v1 = Vec3::new(-1., 0., 0.);
|
||||
assert_eq!(dot(v0, v1), v0.length() * v1.length() * PI.cos());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vec_cross() {
|
||||
let v0 = Vec3::new(1., 0., 0.);
|
||||
let v1 = Vec3::new(0., 1., 0.);
|
||||
assert_eq!(cross(v0, v1), Vec3::new(0., 0., 1.));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user