upd
This commit is contained in:
parent
0000053097
commit
00000540b4
11 changed files with 1262 additions and 26 deletions
83
assignment-1c/Cargo.lock
generated
83
assignment-1c/Cargo.lock
generated
|
@ -25,6 +25,8 @@ dependencies = [
|
|||
"base64",
|
||||
"clap",
|
||||
"derivative",
|
||||
"generator",
|
||||
"itertools",
|
||||
"nalgebra",
|
||||
"num",
|
||||
"ordered-float",
|
||||
|
@ -188,6 +190,19 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generator"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d266041a359dfa931b370ef684cceb84b166beb14f7f0421f4a6a3d0c446d12e"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"log",
|
||||
"rustversion",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.8"
|
||||
|
@ -236,6 +251,15 @@ dependencies = [
|
|||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
|
@ -566,6 +590,12 @@ dependencies = [
|
|||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70"
|
||||
|
||||
[[package]]
|
||||
name = "safe_arch"
|
||||
version = "0.6.0"
|
||||
|
@ -780,6 +810,19 @@ version = "0.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.39.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1c4bd0a50ac6020f65184721f758dba47bb9fbc2133df715ec74a237b26794a"
|
||||
dependencies = [
|
||||
"windows_aarch64_msvc 0.39.0",
|
||||
"windows_i686_gnu 0.39.0",
|
||||
"windows_i686_msvc 0.39.0",
|
||||
"windows_x86_64_gnu 0.39.0",
|
||||
"windows_x86_64_msvc 0.39.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.42.0"
|
||||
|
@ -787,12 +830,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_aarch64_msvc 0.42.1",
|
||||
"windows_i686_gnu 0.42.1",
|
||||
"windows_i686_msvc 0.42.1",
|
||||
"windows_x86_64_gnu 0.42.1",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
"windows_x86_64_msvc 0.42.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -801,24 +844,48 @@ version = "0.42.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.39.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec7711666096bd4096ffa835238905bb33fb87267910e154b18b44eaabb340f2"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.39.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "763fc57100a5f7042e3057e7e8d9bdd7860d330070251a73d003563a3bb49e1b"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.39.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7bc7cbfe58828921e10a9f446fcaaf649204dcfe6c1ddd712c5eebae6bda1106"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.39.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6868c165637d653ae1e8dc4d82c25d4f97dd6605eaa8d784b5c6e0ab2a252b65"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.42.1"
|
||||
|
@ -831,6 +898,12 @@ version = "0.42.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.39.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e4d40883ae9cae962787ca76ba76390ffa29214667a111db9e0a1ad8377e809"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.42.1"
|
||||
|
|
|
@ -23,6 +23,8 @@ anyhow = "1.0.68"
|
|||
base64 = "0.21.0"
|
||||
clap = { version = "4.1.4", features = ["cargo", "derive"] }
|
||||
derivative = "2.2.0"
|
||||
generator = "0.7.2"
|
||||
itertools = "0.10.5"
|
||||
nalgebra = "0.32.1"
|
||||
num = { version = "0.4.0", features = ["serde"] }
|
||||
ordered-float = "3.4.0"
|
||||
|
|
2
assignment-1c/examples/.gitignore
vendored
Normal file
2
assignment-1c/examples/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
# Necessary files
|
||||
!/earthtexture.ppm
|
1081
assignment-1c/examples/earthtexture.ppm
Executable file
1081
assignment-1c/examples/earthtexture.ppm
Executable file
File diff suppressed because one or more lines are too long
|
@ -1,11 +1,20 @@
|
|||
use std::io::{Result, Write};
|
||||
use generator::{done, Gn};
|
||||
use itertools::Itertools;
|
||||
use std::{
|
||||
fs::File,
|
||||
io::{BufRead, BufReader, Read, Write},
|
||||
path::Path,
|
||||
};
|
||||
|
||||
use anyhow::Result;
|
||||
use nalgebra::Vector3;
|
||||
|
||||
/// A pixel color represented by a red, green, and blue value in the range 0-1.
|
||||
pub type Color = Vector3<f64>;
|
||||
|
||||
/// A representation of an image
|
||||
#[derive(Derivative)]
|
||||
#[derivative(Debug)]
|
||||
pub struct Image {
|
||||
/// Width in pixels
|
||||
pub width: usize,
|
||||
|
@ -14,10 +23,71 @@ pub struct Image {
|
|||
pub height: usize,
|
||||
|
||||
/// Pixel data in row-major form.
|
||||
#[derivative(Debug = "ignore")]
|
||||
pub data: Vec<Color>,
|
||||
}
|
||||
|
||||
impl Image {
|
||||
pub fn from_file(path: impl AsRef<Path>) -> Result<Self> {
|
||||
let file = File::open(path.as_ref())?;
|
||||
Self::read(file)
|
||||
}
|
||||
|
||||
/// Parse image from a Read
|
||||
pub fn read(r: impl Read + Send) -> Result<Self> {
|
||||
let mut line_reader = BufReader::new(r);
|
||||
|
||||
let mut header = String::new();
|
||||
line_reader.read_line(&mut header)?;
|
||||
let parts = header.split(" ").collect::<Vec<_>>();
|
||||
|
||||
let width = parts[1].parse::<usize>()?;
|
||||
let height = parts[2].parse::<usize>()?;
|
||||
|
||||
let numbers = Gn::<()>::new_scoped(move |mut s| {
|
||||
macro_rules! gen_try {
|
||||
($expr:expr) => {
|
||||
match $expr {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
s.yield_(Err(anyhow::Error::from(e)));
|
||||
done!();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
for line in line_reader.lines() {
|
||||
let line = gen_try!(line);
|
||||
let parts = line.split_whitespace();
|
||||
|
||||
for part in parts {
|
||||
let int = gen_try!(part.parse::<f64>());
|
||||
s.yield_(Ok(int));
|
||||
}
|
||||
}
|
||||
|
||||
done!()
|
||||
});
|
||||
|
||||
let mut data = Vec::with_capacity(width * height);
|
||||
for mut chunk in &(numbers).chunks(3) {
|
||||
let (r, g, b) = match chunk.next_tuple() {
|
||||
Some(v) => v,
|
||||
None => bail!("Not enough elements"),
|
||||
};
|
||||
|
||||
let color = Color::new(r?, g?, b?);
|
||||
data.push(color);
|
||||
}
|
||||
|
||||
Ok(Image {
|
||||
width,
|
||||
height,
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
/// Write the image in PPM format to a file.
|
||||
pub fn write(&self, mut w: impl Write) -> Result<()> {
|
||||
// Header
|
||||
|
|
|
@ -15,3 +15,4 @@ pub mod scene;
|
|||
pub mod utils;
|
||||
|
||||
pub type Point = Vector3<f64>;
|
||||
pub type Vector = Vector3<f64>;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::Point;
|
||||
use crate::{Point, Vector};
|
||||
|
||||
/// A normalized parametric Ray of the form (origin + direction * time)
|
||||
///
|
||||
|
@ -7,7 +7,7 @@ use crate::Point;
|
|||
#[derive(Debug)]
|
||||
pub struct Ray {
|
||||
pub origin: Point,
|
||||
pub direction: Point,
|
||||
pub direction: Vector,
|
||||
}
|
||||
|
||||
impl Ray {
|
||||
|
|
|
@ -3,6 +3,7 @@ use anyhow::Result;
|
|||
use ordered_float::NotNan;
|
||||
|
||||
use crate::utils::compute_rotation_matrix;
|
||||
use crate::Vector;
|
||||
use crate::{ray::Ray, Point};
|
||||
|
||||
use super::illumination::IntersectionContext;
|
||||
|
@ -10,7 +11,7 @@ use super::illumination::IntersectionContext;
|
|||
#[derive(Debug)]
|
||||
pub struct Cylinder {
|
||||
pub center: Point,
|
||||
pub direction: Point,
|
||||
pub direction: Vector,
|
||||
pub radius: f64,
|
||||
pub length: f64,
|
||||
}
|
||||
|
@ -26,7 +27,7 @@ impl Cylinder {
|
|||
) -> Result<Option<IntersectionContext>> {
|
||||
// Determine rotation matrix for turning the cylinder upright along the
|
||||
// Z-axis
|
||||
let target_direction = Point::new(0.0, 0.0, 1.0);
|
||||
let target_direction = Vector::new(0.0, 0.0, 1.0);
|
||||
let rotation_matrix =
|
||||
compute_rotation_matrix(self.direction, target_direction)?;
|
||||
let inverse_rotation_matrix =
|
||||
|
@ -153,7 +154,7 @@ impl Cylinder {
|
|||
}
|
||||
|
||||
let normal_rotated =
|
||||
Point::new(0.0, 0.0, rotated_point.z - rotated_cylinder_center.z)
|
||||
Vector::new(0.0, 0.0, rotated_point.z - rotated_cylinder_center.z)
|
||||
.normalize();
|
||||
let normal = inverse_rotation_matrix * normal_rotated;
|
||||
|
||||
|
@ -179,7 +180,7 @@ impl Cylinder {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{ray::Ray, Point};
|
||||
use crate::{ray::Ray, Point, Vector};
|
||||
|
||||
use super::Cylinder;
|
||||
|
||||
|
@ -187,7 +188,7 @@ mod tests {
|
|||
fn test_cylinder() {
|
||||
let cylinder = Cylinder {
|
||||
center: Point::new(0.0, 0.0, 0.0),
|
||||
direction: Point::new(0.0, 1.0, 0.0),
|
||||
direction: Vector::new(0.0, 1.0, 0.0),
|
||||
radius: 3.0,
|
||||
length: 4.0,
|
||||
};
|
||||
|
|
|
@ -7,7 +7,7 @@ use rayon::prelude::{
|
|||
ParallelIterator,
|
||||
};
|
||||
|
||||
use crate::{image::Color, ray::Ray, utils::dot, Point};
|
||||
use crate::{image::Color, ray::Ray, utils::dot, Point, Vector};
|
||||
|
||||
use super::{
|
||||
data::{DepthCueing, Light, LightKind, Object},
|
||||
|
@ -38,7 +38,7 @@ impl Scene {
|
|||
let ambient_component = material.k_a * material.diffuse_color;
|
||||
|
||||
// Diffuse and specular lighting for each separate light
|
||||
let diffuse_and_specular: Point = self
|
||||
let diffuse_and_specular: Color = self
|
||||
.lights
|
||||
.par_iter()
|
||||
.map(|light| {
|
||||
|
@ -214,7 +214,7 @@ impl Scene {
|
|||
let x = rng.gen_range(0.0..JITTER_RADIUS);
|
||||
let y = rng.gen_range(0.0..JITTER_RADIUS);
|
||||
let z = rng.gen_range(0.0..JITTER_RADIUS);
|
||||
let delta = Point::new(x, y, z);
|
||||
let delta = Vector::new(x, y, z);
|
||||
light_location + delta
|
||||
})
|
||||
.take(JITTER_RAYS)
|
||||
|
@ -267,7 +267,7 @@ pub struct IntersectionContext {
|
|||
/// The normal vector protruding from the surface of the object at the
|
||||
/// intersection point
|
||||
#[derivative(PartialEq = "ignore", Ord = "ignore")]
|
||||
pub normal: Point,
|
||||
pub normal: Vector,
|
||||
}
|
||||
|
||||
impl Eq for IntersectionContext {}
|
||||
|
|
|
@ -4,17 +4,18 @@ pub mod illumination;
|
|||
pub mod input_file;
|
||||
pub mod sphere;
|
||||
|
||||
use nalgebra::Vector3;
|
||||
use nalgebra::{Matrix2x3, Vector3};
|
||||
|
||||
use crate::{image::Color, Point};
|
||||
use crate::image::{Color, Image};
|
||||
use crate::{Point, Vector};
|
||||
|
||||
use self::data::{Attenuation, DepthCueing, Light, Material, Object};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Scene {
|
||||
pub eye_pos: Vector3<f64>,
|
||||
pub view_dir: Vector3<f64>,
|
||||
pub up_dir: Vector3<f64>,
|
||||
pub eye_pos: Point,
|
||||
pub view_dir: Vector,
|
||||
pub up_dir: Vector,
|
||||
|
||||
/// Horizontal field of view (in degrees)
|
||||
pub hfov: f64,
|
||||
|
@ -32,5 +33,10 @@ pub struct Scene {
|
|||
pub lights: Vec<Light>,
|
||||
pub objects: Vec<Object>,
|
||||
|
||||
pub textures: Vec<Image>,
|
||||
pub vertices: Vec<Point>,
|
||||
pub flat_triangles: Vec<Vector3<usize>>,
|
||||
|
||||
pub normals: Vec<Vector>,
|
||||
pub smooth_triangles: Vec<Matrix2x3<usize>>,
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ use anyhow::Result;
|
|||
use nalgebra::{Matrix3, Vector3};
|
||||
use ordered_float::NotNan;
|
||||
|
||||
use crate::Point;
|
||||
use crate::{Vector};
|
||||
|
||||
/// Finds the minimum of an iterator of f64s, ignoring any NaN values
|
||||
#[inline]
|
||||
|
@ -30,17 +30,17 @@ where
|
|||
|
||||
/// Dot-product between two 3D vectors.
|
||||
#[inline]
|
||||
pub fn dot(a: Point, b: Point) -> f64 {
|
||||
pub fn dot(a: Vector, b: Vector) -> f64 {
|
||||
a.x * b.x + a.y * b.y + a.z * b.z
|
||||
}
|
||||
|
||||
/// Cross-product between two 3D vectors.
|
||||
#[inline]
|
||||
pub fn cross(a: Point, b: Point) -> Point {
|
||||
pub fn cross(a: Vector, b: Vector) -> Vector {
|
||||
let x = a.y * b.z - a.z * b.y;
|
||||
let y = a.z * b.x - a.x * b.z;
|
||||
let z = a.x * b.y - a.y * b.x;
|
||||
Point::new(x, y, z)
|
||||
Vector::new(x, y, z)
|
||||
}
|
||||
|
||||
/// Calculate the rotation matrix between the 2 given vectors
|
||||
|
|
Loading…
Reference in a new issue