diff --git a/ria-weekend/examples/ppm.rs b/ria-weekend/examples/ppm.rs index 8422cd0..d0d6bf5 100644 --- a/ria-weekend/examples/ppm.rs +++ b/ria-weekend/examples/ppm.rs @@ -27,14 +27,16 @@ fn main() { width = input[0]; } let file_name = format!("ppm_sample{}x{}.ppm", width, height); - let ppm_sample = ppm::create_sample(height, width); + let mut buf = format!("P3\n{} {}\n255\n", width, height); + + ppm::create_sample(&mut buf, height, width); let mut file = match File::create(&file_name) { Ok(file) => file, Err(e) => panic!("couldn't create {}: {}", file_name, e.description()), }; - match file.write_all(ppm_sample.as_bytes()) { + match file.write_all(buf.as_bytes()) { Ok(_) => println!("Succesfully wrote to {}", file_name), Err(e) => panic!("couldn't write to {}: {}", file_name, e.description()), } diff --git a/ria-weekend/examples/ray_demo.rs b/ria-weekend/examples/ray_demo.rs new file mode 100644 index 0000000..2d4f2d2 --- /dev/null +++ b/ria-weekend/examples/ray_demo.rs @@ -0,0 +1,41 @@ +extern crate ria_weekend; + +use ria_weekend::ray; +use std::error::Error; +use std::fs::File; +use std::{io, io::Write}; + +fn main() { + let mut height = 100; + let mut width = 200; + + println!("Enter width and height seperated by space"); + + let mut input = String::new(); + io::stdin() + .read_line(&mut input) + .expect("error in reading input"); + + let input = input + .trim() + .split(" ") + .map(|v| v.parse::().expect("error in parsing input")) + .collect::>(); + + if input.len() >= 2 { + height = input[1]; + width = input[0]; + } + let file_name = format!("ray_demo{}x{}.ppm", width, height); + let mut buf = format!("P3\n{} {}\n255\n", width, height); + let mut file = match File::create(&file_name) { + Ok(file) => file, + Err(e) => panic!("couldn't create {}: {}", file_name, e.description()), + }; + ray::create_ray_demo(&mut buf, width, height); + + match file.write_all(buf.as_bytes()) { + Ok(_) => println!("Succesfully wrote to {}", file_name), + Err(e) => panic!("couldn't write to {}: {}", file_name, e.description()), + } +} diff --git a/ria-weekend/src/ppm.rs b/ria-weekend/src/ppm.rs index 39b7133..66025f1 100644 --- a/ria-weekend/src/ppm.rs +++ b/ria-weekend/src/ppm.rs @@ -1,7 +1,6 @@ use crate::vec3::Vec3; -pub fn create_sample(h: u32, w: u32) -> String { - let mut buf = format!("P3\n{} {}\n255\n", w, h); +pub fn create_sample(buf: &mut String, h: u32, w: u32) { for j in (0..h).rev() { for i in 0..w { let color = Vec3::new((i as f32) / (w as f32), (j as f32) / (h as f32), 0.5_f32); @@ -12,5 +11,4 @@ pub fn create_sample(h: u32, w: u32) -> String { buf.push_str(&format!("{} {} {}\n", ir, ig, ib)); } } - buf } diff --git a/ria-weekend/src/ray.rs b/ria-weekend/src/ray.rs index 39b763f..6a285ba 100644 --- a/ria-weekend/src/ray.rs +++ b/ria-weekend/src/ray.rs @@ -6,19 +6,45 @@ pub struct Ray { } impl Ray { - pub const fn new(a: Vec3, b: Vec3) -> Ray { + pub fn new(a: Vec3, b: Vec3) -> Ray { Ray { a, b } } - - pub const fn origin(&self) -> &Vec3 { - return &self.a; + pub fn origin(&self) -> Vec3 { + return self.a; } - - pub const fn direction(&self) -> &Vec3 { - return &self.b; + pub fn direction(&self) -> Vec3 { + return self.b; } - - pub const fn point_at_diameter(&self, t: f32) -> Vec3 { - return self.a + t * self.b; + pub fn point_at_parameter(&self, t: f32) -> Vec3 { + return self.a + self.b * t; + } +} + +fn color(ray: Ray) -> Vec3 { + let unit_direction = ray.direction().unit_vector(); + let t = 0.5 * (unit_direction.y() + 1.0); + return Vec3::new(1.0, 1.0, 1.0) * (1.0 - t) + Vec3::new(0.5, 0.7, 1.0) * t; +} + +pub fn create_ray_demo(buf: &mut String, w: u32, h: u32) { + let lower_left_corner = Vec3::new(-2.0, -1.0, -1.0); + let horizontal = Vec3::new(4.0, 0.0, 0.0); + let vertical = Vec3::new(0.0, 2.0, 0.0); + let origin = Vec3::new(0.0, 0.0, 0.0); + + for j in (0..h).rev() { + for i in 0..w { + let u = i as f32 / w as f32; + let v = j as f32 / h as f32; + + let ray = Ray::new(origin, lower_left_corner + horizontal * u + vertical * v); + + let color = color(ray); + let ir = (255.99 * color[0]) as u32; + let ig = (255.99 * color[1]) as u32; + let ib = (255.99 * color[2]) as u32; + let output = format!("{} {} {}\n", ir, ig, ib); + buf.push_str(&output); + } } } diff --git a/ria-weekend/src/vec3.rs b/ria-weekend/src/vec3.rs index 99e4581..99fcffc 100644 --- a/ria-weekend/src/vec3.rs +++ b/ria-weekend/src/vec3.rs @@ -1,5 +1,6 @@ -use std::ops::{Add, Div, Index, Mul, Sub}; +use std::ops::{Add, Div, Index, IndexMut, Mul, MulAssign, Sub}; +#[derive(Debug, Copy, Clone)] pub struct Vec3 { inner: [f32; 3], } @@ -10,50 +11,54 @@ impl Vec3 { } pub fn x(&self) -> f32 { - self.inner[0] + self[0] } pub fn y(&self) -> f32 { - self.inner[1] + self[1] } pub fn z(&self) -> f32 { - self.inner[2] + self[2] } pub fn r(&self) -> f32 { - self.inner[0] + self[0] } pub fn g(&self) -> f32 { - self.inner[1] + self[1] } pub fn b(&self) -> f32 { - self.inner[2] + self[2] } pub fn length(&self) -> f32 { - (self.inner[0] * self.inner[0] - + self.inner[1] * self.inner[1] - + self.inner[2] * self.inner[2]) - .sqrt() + self.sq_len().sqrt() } pub fn sq_len(&self) -> f32 { - self.inner[0] * self.inner[0] - + self.inner[1] * self.inner[1] - + self.inner[2] * self.inner[2] + self[0] * self[0] + + self[1] * self[1] + + self[2] * self[2] } pub fn dot(&self, v: &Vec3) -> f32 { - self.inner[0] * v.inner[0] + self.inner[1] * v.inner[1] + self.inner[2] * v.inner[2] + self[0] * v[0] + self[1] * v[1] + self[2] * v[2] } pub fn cross(&self, v: &Vec3) -> Vec3 { Vec3 { inner: [ - self.inner[1] * v.inner[2] - self.inner[2] * v.inner[1], - self.inner[2] * v.inner[0] - self.inner[0] * v.inner[2], - self.inner[0] * v.inner[1] - self.inner[1] * v.inner[0], + self[1] * v[2] - self[2] * v[1], + self[2] * v[0] - self[0] * v[2], + self[0] * v[1] - self[1] * v[0], ], } } + + pub fn unit_vector(&self) -> Vec3 { + let length = self.length(); + Vec3 { + inner: [self[0] / length, self[1] / length, self[2] / length], + } + } } impl Add for Vec3 { @@ -62,9 +67,9 @@ impl Add for Vec3 { fn add(self, o: Vec3) -> Vec3 { Vec3 { inner: [ - self.inner[0] + o.inner[0], - self.inner[1] + o.inner[1], - self.inner[2] + o.inner[2], + self[0] + o[0], + self[1] + o[1], + self[2] + o[2], ], } } @@ -76,34 +81,35 @@ impl Sub for Vec3 { fn sub(self, o: Vec3) -> Vec3 { Vec3 { inner: [ - self.inner[0] - o.inner[0], - self.inner[1] - o.inner[1], - self.inner[2] - o.inner[2], + self[0] - o[0], + self[1] - o[1], + self[2] - o[2], ], } } } -impl Mul for Vec3 { - type Output = Vec3; +impl MulAssign for Vec3 { + fn mul_assign(&mut self, o: Vec3) { + self[0] *= o[0]; + self[1] *= o[1]; + self[2] *= o[2]; + } +} - fn mul(self, o: Vec3) -> Vec3 { - Vec3 { - inner: [ - self.inner[0] * o.inner[0], - self.inner[1] * o.inner[1], - self.inner[2] * o.inner[2], - ], - } +impl MulAssign for Vec3 { + fn mul_assign(&mut self, o: f32) { + self[0] *= o; + self[1] *= o; + self[2] *= o; } } impl Mul for Vec3 { type Output = Vec3; - fn mul(self, o: f32) -> Vec3 { Vec3 { - inner: [self.inner[0] * o, self.inner[1] * o, self.inner[2] * o], + inner: [self[0] * o, self[1] * o, self[2] * o], } } } @@ -114,9 +120,9 @@ impl Div for Vec3 { fn div(self, o: Vec3) -> Vec3 { Vec3 { inner: [ - self.inner[0] / o.inner[0], - self.inner[1] / o.inner[1], - self.inner[2] / o.inner[2], + self[0] / o[0], + self[1] / o[1], + self[2] / o[2], ], } } @@ -128,7 +134,7 @@ impl Div for Vec3 { fn div(self, o: f32) -> Vec3 { let o = 1.0 / o; Vec3 { - inner: [self.inner[0] * o, self.inner[1] * o, self.inner[2] * o], + inner: [self[0] * o, self[1] * o, self[2] * o], } } } @@ -140,3 +146,9 @@ impl Index for Vec3 { &self.inner[q] } } + +impl IndexMut for Vec3 { + fn index_mut(&mut self, q: usize) -> &mut f32 { + &mut self.inner[q] + } +}