From 277c6ef60bfce8d00948ce274b9f3c194d43a3d6 Mon Sep 17 00:00:00 2001 From: Bill Thiede Date: Fri, 3 Aug 2018 21:56:09 -0700 Subject: [PATCH] Implementation of part 1. The green circle. --- bheisler/Cargo.lock | 312 ++++++++++++++++++++++++++++++++++++++ bheisler/Cargo.toml | 7 + bheisler/README.md | 3 + bheisler/src/lib.rs | 60 ++++++++ bheisler/src/main.rs | 3 + bheisler/src/point.rs | 30 ++++ bheisler/src/rendering.rs | 53 +++++++ bheisler/src/scene.rs | 26 ++++ bheisler/src/vector.rs | 48 ++++++ 9 files changed, 542 insertions(+) create mode 100644 bheisler/Cargo.lock create mode 100644 bheisler/Cargo.toml create mode 100644 bheisler/README.md create mode 100644 bheisler/src/lib.rs create mode 100644 bheisler/src/main.rs create mode 100644 bheisler/src/point.rs create mode 100644 bheisler/src/rendering.rs create mode 100644 bheisler/src/scene.rs create mode 100644 bheisler/src/vector.rs diff --git a/bheisler/Cargo.lock b/bheisler/Cargo.lock new file mode 100644 index 0000000..3ab5ad6 --- /dev/null +++ b/bheisler/Cargo.lock @@ -0,0 +1,312 @@ +[[package]] +name = "adler32" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "arrayvec" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bheisler" +version = "0.1.0" +dependencies = [ + "image 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bitflags" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byteorder" +version = "1.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cfg-if" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "color_quant" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "crossbeam-deque" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-utils" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "deflate" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "either" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "gif" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "color_quant 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "image" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "gif 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jpeg-decoder 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-derive 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "num-rational 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "png 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "inflate" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "jpeg-decoder" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lazy_static" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.42" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lzw" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "memoffset" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "nodrop" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "num-derive" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.14.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-integer" +version = "0.1.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-iter" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-rational" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-traits" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "num_cpus" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "png" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "deflate 0.7.18 (registry+https://github.com/rust-lang/crates.io-index)", + "inflate 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro2" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rayon" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rayon-core" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "scoped_threadpool" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "scopeguard" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "syn" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" +"checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" +"checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789" +"checksum byteorder 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8389c509ec62b9fe8eca58c502a0acaf017737355615243496cde4994f8fa4f9" +"checksum cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "efe5c877e17a9c717a0bf3613b2709f723202c4e4675cc8f12926ded29bcb17e" +"checksum color_quant 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0dbbb57365263e881e805dc77d94697c9118fd94d8da011240555aa7b23445bd" +"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" +"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" +"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" +"checksum deflate 0.7.18 (registry+https://github.com/rust-lang/crates.io-index)" = "32c8120d981901a9970a3a1c97cf8b630e0fa8c3ca31e75b6fd6fd5f9f427b31" +"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" +"checksum gif 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff3414b424657317e708489d2857d9575f4403698428b040b609b9d1c1a84a2c" +"checksum image 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ebdff791af04e30089bde8ad2a632b86af433b40c04db8d70ad4b21487db7a6a" +"checksum inflate 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6f53b811ee8e2057ccf9643ca6b4277de90efaf5e61e55fd5254576926bb4245" +"checksum jpeg-decoder 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c8b7d43206b34b3f94ea9445174bda196e772049b9bddbc620c9d29b2d20110d" +"checksum lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fb497c35d362b6a331cfd94956a07fc2c78a4604cdbee844a81170386b996dd3" +"checksum libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)" = "b685088df2b950fccadf07a7187c8ef846a959c142338a48f9dc0b94517eb5f1" +"checksum lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084" +"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" +"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" +"checksum num-derive 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d2c31b75c36a993d30c7a13d70513cb93f02acafdd5b7ba250f9b0e18615de7" +"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" +"checksum num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "af3fdbbc3291a5464dc57b03860ec37ca6bf915ed6ee385e7c6c052c422b2124" +"checksum num-rational 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "ee314c74bd753fc86b4780aa9475da469155f3848473a261d2d18e35245a784e" +"checksum num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "630de1ef5cc79d0cdd78b7e33b81f083cbfe90de0f4b2b2f07f905867c70e9fe" +"checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" +"checksum png 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f54b9600d584d3b8a739e1662a595fab051329eff43f20e7d8cc22872962145b" +"checksum proc-macro2 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "cccdc7557a98fe98453030f077df7f3a042052fae465bb61d2c2c41435cfd9b6" +"checksum quote 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b71f9f575d55555aa9c06188be9d4e2bfc83ed02537948ac0d520c24d0419f1a" +"checksum rayon 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "df7a791f788cb4c516f0e091301a29c2b71ef680db5e644a7d68835c8ae6dbfa" +"checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" +"checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" +"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" +"checksum syn 0.14.7 (registry+https://github.com/rust-lang/crates.io-index)" = "e2e13df71f29f9440b50261a5882c86eac334f1badb3134ec26f0de2f1418e44" +"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" diff --git a/bheisler/Cargo.toml b/bheisler/Cargo.toml new file mode 100644 index 0000000..543ed18 --- /dev/null +++ b/bheisler/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "bheisler" +version = "0.1.0" +authors = ["Bill Thiede "] + +[dependencies] +image = "0.19.0" diff --git a/bheisler/README.md b/bheisler/README.md new file mode 100644 index 0000000..c3907a1 --- /dev/null +++ b/bheisler/README.md @@ -0,0 +1,3 @@ +# What? +Implementation based on +https://bheisler.github.io/post/writing-raytracer-in-rust-part-1/ diff --git a/bheisler/src/lib.rs b/bheisler/src/lib.rs new file mode 100644 index 0000000..09a8722 --- /dev/null +++ b/bheisler/src/lib.rs @@ -0,0 +1,60 @@ +extern crate image; + +pub mod point; +pub mod rendering; +pub mod scene; +pub mod vector; + +use image::GenericImage; +use image::Pixel; +use rendering::Intersectable; +use scene::Scene; + +pub fn render(scene: &Scene) -> image::DynamicImage { + let mut image = image::DynamicImage::new_rgb8(scene.width, scene.height); + let black = image::Rgba::from_channels(0, 0, 0, 0); + for x in 0..scene.width { + for y in 0..scene.height { + let ray = rendering::Ray::create_prime(x, y, scene); + + if scene.sphere.intersect(&ray) { + let c = &scene.sphere.color; + image.put_pixel(x, y, image::Rgba(c.to_rgba())) + } else { + image.put_pixel(x, y, black); + } + } + } + image +} + +#[test] +fn test_can_render_scene() { + use point::Point; + use rendering::Sphere; + use scene::Color; + + let scene = Scene { + width: 800, + height: 600, + fov: 90.0, + sphere: Sphere { + center: Point { + x: 0.0, + y: 0.0, + z: -5.0, + }, + radius: 1.0, + color: Color { + red: 0.4, + green: 1.0, + blue: 0.4, + }, + }, + }; + + let img: image::DynamicImage = render(&scene); + assert_eq!(scene.width, img.width()); + assert_eq!(scene.height, img.height()); + img.save("/tmp/bheisler.png").unwrap(); +} diff --git a/bheisler/src/main.rs b/bheisler/src/main.rs new file mode 100644 index 0000000..e7a11a9 --- /dev/null +++ b/bheisler/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/bheisler/src/point.rs b/bheisler/src/point.rs new file mode 100644 index 0000000..78a04f7 --- /dev/null +++ b/bheisler/src/point.rs @@ -0,0 +1,30 @@ +use std::ops::Sub; + +#[derive(Clone, Copy)] +pub struct Point { + pub x: f32, + pub y: f32, + pub z: f32, +} + +impl Point { + pub fn zero() -> Point { + Point { + x: 0., + y: 0., + z: 0., + } + } +} + +impl Sub for Point { + type Output = Point; + + fn sub(self, other: Point) -> Point { + Point { + x: self.x - other.x, + y: self.y - other.y, + z: self.z - other.z, + } + } +} diff --git a/bheisler/src/rendering.rs b/bheisler/src/rendering.rs new file mode 100644 index 0000000..8c443e6 --- /dev/null +++ b/bheisler/src/rendering.rs @@ -0,0 +1,53 @@ +use point::Point; +use scene::Color; +use scene::Scene; +use vector::Vector3; + +pub trait Intersectable { + fn intersect(&self, ray: &Ray) -> bool; +} + +pub struct Sphere { + pub center: Point, + pub radius: f32, + pub color: Color, +} + +impl Intersectable for Sphere { + fn intersect(&self, ray: &Ray) -> bool { + //Create a line segment between the ray origin and the center of the sphere + let l: Vector3 = (self.center - ray.origin).into(); + //Use l as a hypotenuse and find the length of the adjacent side + let adj2 = l.dot(&ray.direction); + //Find the length-squared of the opposite side + //This is equivalent to (but faster than) (l.length() * l.length()) - (adj2 * adj2) + let d2 = l.dot(&l) - (adj2 * adj2); + //If that length-squared is less than radius squared, the ray intersects the sphere + d2 < (self.radius * self.radius) + } +} + +pub struct Ray { + pub origin: Point, + pub direction: Vector3, +} + +impl Ray { + pub fn create_prime(x: u32, y: u32, scene: &Scene) -> Ray { + assert!(scene.width > scene.height); + let fov_adjustment = (scene.fov.to_radians() / 2.0).tan(); + let aspect_ratio = (scene.width as f32) / (scene.height as f32); + let sensor_x = + ((((x as f32 + 0.5) / scene.width as f32) * 2.0 - 1.0) * aspect_ratio) * fov_adjustment; + let sensor_y = (1.0 - ((y as f32 + 0.5) / scene.height as f32) * 2.0) * fov_adjustment; + + Ray { + origin: Point::zero(), + direction: Vector3 { + x: sensor_x, + y: sensor_y, + z: -1.0, + }.normalize(), + } + } +} diff --git a/bheisler/src/scene.rs b/bheisler/src/scene.rs new file mode 100644 index 0000000..c89562c --- /dev/null +++ b/bheisler/src/scene.rs @@ -0,0 +1,26 @@ +use rendering::Sphere; + +pub struct Color { + pub red: f32, + pub green: f32, + pub blue: f32, +} + +impl Color { + pub fn to_rgba(&self) -> [u8; 4] { + let v: [u8; 4] = [ + (255. * self.red) as u8, + (255. * self.green) as u8, + (255. * self.blue) as u8, + 255u8, + ]; + v + } +} + +pub struct Scene { + pub width: u32, + pub height: u32, + pub fov: f32, + pub sphere: Sphere, +} diff --git a/bheisler/src/vector.rs b/bheisler/src/vector.rs new file mode 100644 index 0000000..b029765 --- /dev/null +++ b/bheisler/src/vector.rs @@ -0,0 +1,48 @@ +use point::Point; +use std::ops::Div; + +pub struct Vector3 { + pub x: f32, + pub y: f32, + pub z: f32, +} + +impl Vector3 { + pub fn normalize(&self) -> Vector3 { + self / self.length() + } + + pub fn length_squared(&self) -> f32 { + self.x * self.x + self.y * self.y + self.z * self.z + } + + pub fn length(&self) -> f32 { + self.length_squared().sqrt() + } + + pub fn dot(&self, rhs: &Vector3) -> f32 { + self.x * rhs.x + self.y * rhs.y + self.z * rhs.z + } +} + +impl<'a> Div for &'a Vector3 { + type Output = Vector3; + + fn div(self, rhs: f32) -> Vector3 { + Vector3 { + x: self.x / rhs, + y: self.y / rhs, + z: self.z / rhs, + } + } +} + +impl From for Vector3 { + fn from(p: Point) -> Self { + Vector3 { + x: p.x, + y: p.y, + z: p.z, + } + } +}