rtiow: move vec3 to separate crate so it can be used elsewhere.

This commit is contained in:
Bill Thiede 2023-01-15 11:35:55 -08:00
parent a12938db95
commit 24e8b4f9cf
7 changed files with 323 additions and 296 deletions

56
rtiow/Cargo.lock generated
View File

@ -940,9 +940,9 @@ version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
dependencies = [
"proc-macro2 1.0.43",
"proc-macro2 1.0.49",
"quote 1.0.21",
"syn 1.0.99",
"syn 1.0.107",
"synstructure",
]
@ -1943,9 +1943,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.43"
version = "1.0.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
dependencies = [
"unicode-ident",
]
@ -1971,7 +1971,7 @@ version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
dependencies = [
"proc-macro2 1.0.43",
"proc-macro2 1.0.49",
]
[[package]]
@ -2289,6 +2289,7 @@ dependencies = [
"serde_derive",
"serde_json",
"structopt",
"vec3",
]
[[package]]
@ -2393,19 +2394,22 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "serde"
version = "1.0.144"
version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860"
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.144"
version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00"
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
dependencies = [
"proc-macro2 1.0.43",
"proc-macro2 1.0.49",
"quote 1.0.21",
"syn 1.0.99",
"syn 1.0.107",
]
[[package]]
@ -2602,11 +2606,11 @@ dependencies = [
[[package]]
name = "syn"
version = "1.0.99"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13"
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
dependencies = [
"proc-macro2 1.0.43",
"proc-macro2 1.0.49",
"quote 1.0.21",
"unicode-ident",
]
@ -2617,9 +2621,9 @@ version = "0.12.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
dependencies = [
"proc-macro2 1.0.43",
"proc-macro2 1.0.49",
"quote 1.0.21",
"syn 1.0.99",
"syn 1.0.107",
"unicode-xid 0.2.4",
]
@ -3212,9 +3216,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2ca2a14bc3fc5b64d188b087a7d3a927df87b152e941ccfbc66672e20c467ae"
dependencies = [
"nom",
"proc-macro2 1.0.43",
"proc-macro2 1.0.49",
"quote 1.0.21",
"syn 1.0.99",
"syn 1.0.107",
]
[[package]]
@ -3227,6 +3231,14 @@ dependencies = [
"v_escape",
]
[[package]]
name = "vec3"
version = "0.1.0"
dependencies = [
"serde",
"serde_derive",
]
[[package]]
name = "vec_map"
version = "0.8.2"
@ -3336,9 +3348,9 @@ dependencies = [
"bumpalo",
"log 0.4.17",
"once_cell",
"proc-macro2 1.0.43",
"proc-macro2 1.0.49",
"quote 1.0.21",
"syn 1.0.99",
"syn 1.0.107",
"wasm-bindgen-shared",
]
@ -3358,9 +3370,9 @@ version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
dependencies = [
"proc-macro2 1.0.43",
"proc-macro2 1.0.49",
"quote 1.0.21",
"syn 1.0.99",
"syn 1.0.107",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]

View File

@ -5,6 +5,7 @@ members = [
"noise_explorer_warp",
"renderer",
"tracer",
"vec3",
]
[profile]

View File

@ -22,6 +22,7 @@ serde = "1.0.79"
serde_derive = "1.0.79"
serde_json = "1.0.41"
structopt = "0.2.10"
vec3 = {path = "../vec3"}
[dev-dependencies]
criterion = "0.2"

View File

@ -1,274 +1 @@
use std::{
convert::From,
fmt,
num::ParseFloatError,
ops::{Add, Div, Index, Mul, Neg, Sub},
str,
};
use serde_derive::{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.));
}
}
pub use vec3::*;

10
rtiow/vec3/Cargo.toml Normal file
View 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
View File

@ -0,0 +1,2 @@
mod vec3;
pub use vec3::*;

274
rtiow/vec3/src/vec3.rs Normal file
View 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.));
}
}