Fix x and y swapped

This commit is contained in:
Michael Zhang 2023-01-31 15:58:32 -06:00
parent d737124aa1
commit 3b04a7c494
5 changed files with 48 additions and 29 deletions

View file

@ -2,7 +2,25 @@ use std::io::{Result, Write};
/// A 24-bit pixel represented by a red, green, and blue value. /// A 24-bit pixel represented by a red, green, and blue value.
#[derive(Clone, Copy, Default, Debug)] #[derive(Clone, Copy, Default, Debug)]
pub struct Pixel(pub u8, pub u8, pub u8); pub struct Color {
pub red: u8,
pub green: u8,
pub blue: u8,
}
impl Color {
pub fn new(r: u8, g: u8, b: u8) -> Self {
Color {
red: r,
green: g,
blue: b,
}
}
pub fn from_01_float(r: f64, g: f64, b: f64) -> Self {
Color::new((r * 256.0) as u8, (g * 256.0) as u8, (b * 256.0) as u8)
}
}
/// A representation of an image /// A representation of an image
pub struct Image { pub struct Image {
@ -13,7 +31,7 @@ pub struct Image {
pub(crate) height: usize, pub(crate) height: usize,
/// Pixel data in row-major form. /// Pixel data in row-major form.
pub(crate) data: Vec<Pixel>, pub(crate) data: Vec<Color>,
} }
impl Image { impl Image {
@ -24,8 +42,10 @@ impl Image {
w.write_all(header.as_bytes())?; w.write_all(header.as_bytes())?;
// Pixel data // Pixel data
assert_eq!(self.data.len(), self.width * self.height);
for pixel in self.data.iter() { for pixel in self.data.iter() {
let Pixel(red, green, blue) = pixel; let Color { red, green, blue } = pixel;
let pixel = format!("{red} {green} {blue}\n"); let pixel = format!("{red} {green} {blue}\n");
w.write_all(pixel.as_bytes())?; w.write_all(pixel.as_bytes())?;
} }

View file

@ -3,6 +3,7 @@ use std::{fs::File, io::Read, path::Path};
use anyhow::Result; use anyhow::Result;
use crate::{ use crate::{
image::Color,
scene_data::{Object, Scene, Sphere}, scene_data::{Object, Scene, Sphere},
vec3::Vec3, vec3::Vec3,
}; };
@ -48,18 +49,25 @@ pub fn parse_input_file(path: impl AsRef<Path>) -> Result<Scene> {
Ok(Vec3::new(parts[0], parts[1], parts[2])) Ok(Vec3::new(parts[0], parts[1], parts[2]))
}; };
let read_color = || {
if parts.len() < 3 {
bail!("Color requires 3 components.");
}
Ok(Color::from_01_float(parts[0], parts[1], parts[2]))
};
match keyword { match keyword {
"eye" => scene.eye_pos = read_vec3()?, "eye" => scene.eye_pos = read_vec3()?,
"viewdir" => scene.view_dir = read_vec3()?, "viewdir" => scene.view_dir = read_vec3()?,
"updir" => scene.up_dir = read_vec3()?, "updir" => scene.up_dir = read_vec3()?,
"hfov" => scene.hfov = parts[0], "hfov" => scene.hfov = parts[0],
"bkgcolor" => scene.bkg_color = read_vec3()?, "bkgcolor" => scene.bkg_color = read_color()?,
"mtlcolor" => { "mtlcolor" => {
let idx = scene.material_colors.len(); let idx = scene.material_colors.len();
material_color = Some(idx); material_color = Some(idx);
scene.material_colors.push(read_vec3()?); scene.material_colors.push(read_color()?);
} }
"sphere" => scene.objects.push(Object::Sphere(Sphere { "sphere" => scene.objects.push(Object::Sphere(Sphere {

View file

@ -15,7 +15,9 @@ use anyhow::Result;
use clap::Parser; use clap::Parser;
use itertools::Itertools; use itertools::Itertools;
use ordered_float::NotNan; use ordered_float::NotNan;
use rayon::prelude::{IntoParallelIterator, ParallelIterator}; use rayon::prelude::{
IndexedParallelIterator, IntoParallelIterator, ParallelIterator,
};
use crate::image::Image; use crate::image::Image;
use crate::input_file::parse_input_file; use crate::input_file::parse_input_file;
@ -24,7 +26,7 @@ use crate::scene_data::Object;
use crate::vec3::Vec3; use crate::vec3::Vec3;
use crate::view::Rect; use crate::view::Rect;
const ARBITRARY_D: f64 = 1.0; const ARBITRARY_D: f64 = 2.0;
/// Simple raycaster. /// Simple raycaster.
#[derive(Parser)] #[derive(Parser)]
@ -74,7 +76,6 @@ fn main() -> Result<()> {
let viewing_height = viewing_width / aspect_ratio; let viewing_height = viewing_width / aspect_ratio;
// Compute viewing window corners // Compute viewing window corners
// TODO: See slide 101
let n = scene.view_dir.unit(); let n = scene.view_dir.unit();
#[rustfmt::skip] // Otherwise this line wraps over #[rustfmt::skip] // Otherwise this line wraps over
let view_window = Rect { let view_window = Rect {
@ -103,14 +104,14 @@ fn main() -> Result<()> {
}; };
// This is an L because par_bridge is unordered // This is an L because par_bridge is unordered
let pixels = (0..scene.image_width) let pixels = (0..scene.image_height)
.cartesian_product(0..scene.image_height) .cartesian_product(0..scene.image_width)
.collect_vec(); .collect_vec();
// Loop through every single pixel of the output file // Loop through every single pixel of the output file
let pixels = pixels let pixels = pixels
.into_par_iter() .into_par_iter()
.map(|(px, py)| { .map(|(py, px)| {
let pixel_in_space = translate_pixel(px, py); let pixel_in_space = translate_pixel(px, py);
let ray = Ray::from_endpoints(scene.eye_pos, pixel_in_space); let ray = Ray::from_endpoints(scene.eye_pos, pixel_in_space);
@ -130,12 +131,12 @@ fn main() -> Result<()> {
let pixel_color = match earliest_intersection { let pixel_color = match earliest_intersection {
Some((_, sphere)) => scene.material_colors[sphere.material], Some((_, sphere)) => scene.material_colors[sphere.material],
// There was no intersection, so this should default to the background // There was no intersection, so this should default to the scene's
// color // background color
None => scene.bkg_color, None => scene.bkg_color,
}; };
pixel_color.to_pixel() pixel_color
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();

View file

@ -1,4 +1,4 @@
use crate::vec3::Vec3; use crate::{image::Color, vec3::Vec3};
#[derive(Debug)] #[derive(Debug)]
pub struct Sphere { pub struct Sphere {
@ -33,8 +33,8 @@ pub struct Scene {
pub image_height: usize, pub image_height: usize,
/// Background color /// Background color
pub bkg_color: Vec3, pub bkg_color: Color,
pub material_colors: Vec<Vec3>, pub material_colors: Vec<Color>,
pub objects: Vec<Object>, pub objects: Vec<Object>,
} }

View file

@ -1,9 +1,9 @@
use std::ops::{Add, Div, Mul, Sub};
use std::fmt; use std::fmt;
use std::ops::{Add, Div, Mul, Sub};
use num::Float; use num::Float;
use crate::image::Pixel; use crate::image::Color;
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq)] #[derive(Copy, Clone, Default, Debug, PartialEq, Eq)]
pub struct Vec3<T = f64> { pub struct Vec3<T = f64> {
@ -54,16 +54,6 @@ impl<T: Float> Vec3<T> {
} }
} }
impl Vec3<f64> {
/// Convert into an RGB color
pub fn to_pixel(&self) -> Pixel {
let r = (self.x * 256.0) as u8;
let g = (self.y * 256.0) as u8;
let b = (self.z * 256.0) as u8;
Pixel(r, g, b)
}
}
/// Vector addition /// Vector addition
impl<T> Add<Vec3<T>> for Vec3<T> impl<T> Add<Vec3<T>> for Vec3<T>
where where