Fix x and y swapped
This commit is contained in:
parent
d737124aa1
commit
3b04a7c494
5 changed files with 48 additions and 29 deletions
|
@ -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())?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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<_>>();
|
||||||
|
|
||||||
|
|
|
@ -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>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue