colon skull
This commit is contained in:
parent
9dafc764c3
commit
70cba6d253
9 changed files with 63 additions and 15 deletions
4
assignment-1c/.gitignore
vendored
4
assignment-1c/.gitignore
vendored
|
@ -1,6 +1,6 @@
|
|||
/target
|
||||
/assignment-1b
|
||||
/raytracer1b
|
||||
/assignment-1c
|
||||
/raytracer1c
|
||||
/examples/*.png
|
||||
*.ppm
|
||||
*.zip
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
eye 0 0 4
|
||||
viewdir 0 0 -1
|
||||
updir 0 1 0
|
||||
updir 1 1 0
|
||||
hfov 60
|
||||
imsize 640 480
|
||||
|
||||
bkgcolor 0.1 0.1 0.1
|
||||
bkgcolor 0.4 0.4 0.4
|
||||
light -2 1 0 1 1 1 1
|
||||
mtlcolor 1 0.6 1 1 1 1 0.1 0.4 0.4 20
|
||||
|
||||
|
|
BIN
assignment-1c/raytracer1b
Executable file
BIN
assignment-1c/raytracer1b
Executable file
Binary file not shown.
|
@ -205,12 +205,13 @@ impl Scene {
|
|||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let average =
|
||||
intersections.iter().cloned().sum::<f64>() / intersections.len() as f64;
|
||||
|
||||
match intersections.is_empty() {
|
||||
true => 1.0,
|
||||
false => average,
|
||||
false => {
|
||||
let average = intersections.iter().cloned().sum::<f64>()
|
||||
/ intersections.len() as f64;
|
||||
average
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ use crate::{
|
|||
data::{Attenuation, Light, LightKind, Material},
|
||||
object::{Object, ObjectKind},
|
||||
sphere::Sphere,
|
||||
texture::Texture,
|
||||
texture::{Texture, NormalMap},
|
||||
triangle::Triangle,
|
||||
Scene,
|
||||
},
|
||||
|
@ -260,6 +260,21 @@ impl Scene {
|
|||
scene.textures.push(texture);
|
||||
}
|
||||
|
||||
"bump" => {
|
||||
let input_parent = path.parent().unwrap().to_path_buf();
|
||||
let path = match parts.next() {
|
||||
Some(s) => input_parent.join(s),
|
||||
None => bail!("Did not provide path."),
|
||||
};
|
||||
|
||||
let idx = scene.textures.len();
|
||||
texture_idx = Some(idx);
|
||||
|
||||
let image = Image::from_file(path)?;
|
||||
let normal_map = NormalMap::new(image);
|
||||
scene.normal_maps.push(normal_map);
|
||||
}
|
||||
|
||||
_ => bail!("Unknown keyword {keyword}"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ use crate::{Point, Point2, Vector};
|
|||
|
||||
use self::data::{Attenuation, DepthCueing, Light, Material};
|
||||
use self::object::Object;
|
||||
use self::texture::Texture;
|
||||
use self::texture::{Texture, NormalMap};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Scene {
|
||||
|
@ -39,6 +39,9 @@ pub struct Scene {
|
|||
/// List of textures
|
||||
pub textures: Vec<Texture>,
|
||||
|
||||
/// List of normal maps (Extra credit)
|
||||
pub normal_maps: Vec<NormalMap>,
|
||||
|
||||
/// Coordinates into a texture image
|
||||
pub texture_vertices: Vec<Point2>,
|
||||
|
||||
|
|
|
@ -45,8 +45,8 @@ impl ObjectKind {
|
|||
}
|
||||
}
|
||||
|
||||
/// Get the coordinates in the texture (between 0 and 1) that corresponds to
|
||||
/// the intersection point
|
||||
/// Get the (u, v) coordinates in the texture (between 0 and 1) that
|
||||
/// corresponds to the intersection point
|
||||
pub fn get_texture_coord(
|
||||
&self,
|
||||
scene: &Scene,
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
use crate::image::{Color, Image};
|
||||
use crate::{
|
||||
image::{Color, Image},
|
||||
Vector,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Texture(Image);
|
||||
|
@ -39,3 +42,23 @@ impl Texture {
|
|||
+ (alpha) * (beta) * self.pixel_at_exact(i + 1, j + 1)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct NormalMap(Image);
|
||||
|
||||
impl NormalMap {
|
||||
pub fn new(image: Image) -> Self {
|
||||
Self(image)
|
||||
}
|
||||
|
||||
pub fn normal_vector_at_exact(&self, x: usize, y: usize) -> Vector {
|
||||
let vec = self.0.data[y * self.0.width + x];
|
||||
|
||||
// So, according to the instructions, this should actually be a value
|
||||
// between -1 and 1. However, we're reading this in through an image.
|
||||
// I'm just going to do the lazy thing here (which theoretically
|
||||
// actually saves cycles) by only doing the transformation when loading
|
||||
// out of the image
|
||||
vec.map(|value| 2.0 * value / 255.0 - 1.0)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use std::f64::EPSILON;
|
||||
|
||||
use anyhow::Result;
|
||||
use nalgebra::{Matrix2, Vector2, Vector3};
|
||||
use ordered_float::NotNan;
|
||||
|
@ -73,7 +75,10 @@ impl Triangle {
|
|||
self.compute_barycentric_coordinates(scene, p)?;
|
||||
|
||||
// Each of alpha, beta, and gamma must be between 0 and 1
|
||||
if ![alpha, beta, gamma].into_iter().all(|v| 0.0 < v && v < 1.0) {
|
||||
if ![alpha, beta, gamma]
|
||||
.into_iter()
|
||||
.all(|v| 0.0 - EPSILON <= v && v <= 1.0 + EPSILON)
|
||||
{
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
|
@ -87,6 +92,7 @@ impl Triangle {
|
|||
|
||||
(alpha * n0 + beta * n1 + gamma * n2).normalize()
|
||||
}
|
||||
|
||||
None => n.normalize(),
|
||||
};
|
||||
|
||||
|
@ -142,7 +148,7 @@ impl Triangle {
|
|||
(p0, p1, p2)
|
||||
}
|
||||
|
||||
/// Get the new basis vectors using p0 as the origin.
|
||||
/// Get the new basis vectors using p0 as the origin. Returns (p0, e1, e2)
|
||||
#[inline]
|
||||
fn basis_vectors(&self, scene: &Scene) -> (Vector, Vector, Vector) {
|
||||
let (p0, p1, p2) = self.corner_coordinates(scene);
|
||||
|
|
Loading…
Reference in a new issue