csci5607/assignment-1b/src/scene/data.rs

113 lines
2.9 KiB
Rust
Raw Normal View History

2023-02-06 03:52:42 +00:00
use std::fmt::Debug;
use anyhow::Result;
use nalgebra::Vector3;
use crate::image::Color;
use crate::ray::Ray;
2023-02-15 07:20:03 +00:00
use super::Scene;
2023-02-15 07:22:42 +00:00
use super::illumination::IntersectionContext;
2023-02-15 07:20:03 +00:00
2023-02-06 03:52:42 +00:00
pub trait ObjectKind: Debug + Send + Sync {
/// Determine where the ray intersects this object, returning the earliest
/// time this happens. Returns None if no intersection occurs.
///
/// Also known as Trace_Ray in the slides, except not the part where it calls
/// Shade_Ray.
fn intersects_ray_at(&self, ray: &Ray)
-> Result<Option<IntersectionContext>>;
}
/// An object in the scene
#[derive(Debug)]
pub struct Object {
pub kind: Box<dyn ObjectKind>,
/// Index into the scene's material color list
pub material: usize,
}
#[derive(Debug)]
pub struct Rect {
pub upper_left: Vector3<f64>,
pub upper_right: Vector3<f64>,
pub lower_left: Vector3<f64>,
pub lower_right: Vector3<f64>,
}
#[derive(Debug)]
pub struct Material {
pub diffuse_color: Vector3<f64>,
pub specular_color: Vector3<f64>,
pub k_a: f64,
pub k_d: f64,
pub k_s: f64,
pub exponent: f64,
}
#[derive(Debug)]
pub enum LightKind {
/// A point light source exists at a point and emits light in all directions
Point {
location: Vector3<f64>,
},
Directional {
direction: Vector3<f64>,
},
}
#[derive(Debug)]
pub struct Light {
pub kind: LightKind,
pub color: Vector3<f64>,
}
#[derive(Debug, Default)]
2023-02-15 07:20:03 +00:00
pub struct DepthCueing {
color: Color,
a_max: f64,
a_min: f64,
dist_max: f64,
dist_min: f64,
2023-02-06 03:52:42 +00:00
}
impl Scene {
/// Determine the boundaries of the viewing window in world coordinates
pub fn compute_viewing_window(&self, distance: f64) -> Rect {
// Compute viewing directions
let u = self.view_dir.cross(&self.up_dir).normalize();
let v = u.cross(&self.view_dir).normalize();
// Compute dimensions of viewing window based on field of view
let viewing_width = {
// Divide the angle in 2 since we are trying to use trig rules so we must
// get it from a right triangle
let half_hfov = self.hfov.to_radians() / 2.0;
// tan(hfov / 2) = w / 2d
let w_over_2d = half_hfov.tan();
// To find the viewing width we must multiply by 2d now
w_over_2d * 2.0 * distance
};
let aspect_ratio = self.image_width as f64 / self.image_height as f64;
let viewing_height = viewing_width / aspect_ratio;
// Compute viewing window corners
let n = self.view_dir.normalize();
#[rustfmt::skip] // Otherwise this line wraps over
let view_window = Rect {
upper_left: self.eye_pos + n * distance - u * (viewing_width / 2.0) + v * (viewing_height / 2.0),
upper_right: self.eye_pos + n * distance + u * (viewing_width / 2.0) + v * (viewing_height / 2.0),
lower_left: self.eye_pos + n * distance - u * (viewing_width / 2.0) - v * (viewing_height / 2.0),
lower_right: self.eye_pos + n * distance + u * (viewing_width / 2.0) - v * (viewing_height / 2.0),
};
view_window
}
}