@@ 1,27 @@
+mod vec3;
+use vec3::*;
+
+fn main() {
+ let stdout = std::io::stdout();
+ let mut handle = stdout.lock();
+
+ // Image
+ let image_width = 256i32;
+ let image_height = 256i32;
+
+ // Render
+
+ print!("P3\n{} {}\n255\n", image_width, image_height);
+
+ for j in (0..=(image_height-1)).rev() {
+ eprint!("\rScanlines remaining: {} ", j);
+ for i in 0..image_width {
+ let pixel_color = Color::new(
+ i as f64 / (image_width-1) as f64,
+ j as f64 / (image_height-1) as f64,
+ 0.25);
+ write_color(&mut handle, pixel_color);
+ }
+ }
+ eprintln!("\nDone!");
+}
@@ 1,171 @@
+#[derive(Debug, Clone, Copy)]
+pub struct Vec3 {
+ e: [f64; 3],
+}
+
+pub type Point3 = Vec3;
+pub type Color = Vec3;
+
+impl Vec3 {
+ pub fn new(e0: f64, e1: f64, e2: f64) -> Self {
+ Vec3 { e: [e0, e1, e2] }
+ }
+
+ pub fn x(&self) -> f64 {
+ self.e[0]
+ }
+ pub fn y(&self) -> f64 {
+ self.e[1]
+ }
+ pub fn z(&self) -> f64 {
+ self.e[2]
+ }
+
+ pub fn lenght(&self) -> f64 {
+ self.lenght_squared().sqrt()
+ }
+
+ pub fn lenght_squared(&self) -> f64 {
+ self.e[0] * self.e[0] + self.e[1] * self.e[1] + self.e[2] * self.e[2]
+ }
+}
+
+impl std::ops::Neg for &Vec3 {
+ type Output = Vec3;
+
+ fn neg(self) -> Vec3 {
+ Vec3 {
+ e: [-self.e[0], -self.e[1], -self.e[1]],
+ }
+ }
+}
+
+impl std::ops::Index<usize> for Vec3 {
+ type Output = f64;
+
+ fn index(&self, i: usize) -> &f64 {
+ debug_assert!(i < 3);
+ &self.e[i]
+ }
+}
+
+impl std::ops::IndexMut<usize> for Vec3 {
+ fn index_mut(&mut self, i: usize) -> &mut f64 {
+ debug_assert!(i < 3);
+ &mut self.e[i]
+ }
+}
+
+impl std::ops::Add<&Vec3> for &Vec3 {
+ type Output = Vec3;
+ fn add(self, rhs: &Vec3) -> Vec3 {
+ let mut c = self.clone();
+ c += rhs;
+ c
+ }
+}
+
+impl std::ops::AddAssign<&Vec3> for Vec3 {
+ fn add_assign(&mut self, rhs: &Vec3) {
+ self.e[0] += rhs.e[0];
+ self.e[1] += rhs.e[1];
+ self.e[2] += rhs.e[2];
+ }
+}
+
+impl std::ops::Sub<&Vec3> for &Vec3 {
+ type Output = Vec3;
+ fn sub(self, rhs: &Vec3) -> Vec3 {
+ Vec3 {
+ e: [
+ self.e[0] - rhs.e[0],
+ self.e[1] - rhs.e[1],
+ self.e[2] - rhs.e[2],
+ ],
+ }
+ }
+}
+
+impl std::ops::Mul<&Vec3> for &Vec3 {
+ type Output = Vec3;
+ fn mul(self, rhs: &Vec3) -> Vec3 {
+ Vec3 {
+ e: [
+ self.e[0] * rhs.e[0],
+ self.e[1] * rhs.e[1],
+ self.e[2] * rhs.e[2],
+ ],
+ }
+ }
+}
+
+impl std::ops::Mul<f64> for &Vec3 {
+ type Output = Vec3;
+ fn mul(self, rhs: f64) -> Vec3 {
+ Vec3 {
+ e: [self.e[0] * rhs, self.e[1] * rhs, self.e[2] * rhs],
+ }
+ }
+}
+
+impl std::ops::Mul<&Vec3> for f64 {
+ type Output = Vec3;
+ fn mul(self, rhs: &Vec3) -> Vec3 {
+ rhs * self
+ }
+}
+
+impl std::ops::MulAssign<f64> for Vec3 {
+ fn mul_assign(&mut self, rhs: f64) {
+ self.e[0] *= rhs;
+ self.e[1] *= rhs;
+ self.e[2] *= rhs;
+ }
+}
+
+impl std::ops::DivAssign<f64> for Vec3 {
+ fn div_assign(&mut self, rhs: f64) {
+ *self *= 1f64 / rhs;
+ }
+}
+
+impl std::ops::Div<f64> for &Vec3 {
+ type Output = Vec3;
+
+ fn div(self, rhs: f64) -> Vec3 {
+ let mut c = self.clone();
+ c *= 1f64 / rhs;
+ c
+ }
+}
+
+impl Default for Vec3 {
+ fn default() -> Self {
+ Vec3 {
+ e: [0f64, 0f64, 0f64],
+ }
+ }
+}
+
+pub fn dot(u: &Vec3, v: &Vec3) -> f64 {
+ u.e[0] * v.e[0] + u.e[1] * v.e[1] + u.e[2] * v.e[2]
+}
+
+pub fn cross(u: &Vec3, v: &Vec3) -> Vec3 {
+ Vec3::new(
+ u.e[1] * v.e[2] - u.e[2] * v.e[1],
+ u.e[2] * v.e[0] - u.e[0] * v.e[2],
+ u.e[0] * v.e[1] - u.e[1] * v.e[0],
+ )
+}
+
+pub fn unit_vector(v: &Vec3) -> Vec3 {
+ v / v.lenght()
+}
+
+pub fn write_color(out: &mut impl std::io::Write, pixel_color: Color) {
+ write!(out, "{} {} {}\n",
+ (255.999 * pixel_color.x()) as i32,
+ (255.999 * pixel_color.y()) as i32,
+ (255.999 * pixel_color.z()) as i32).unwrap();
+}