ft: 5,6.1: sphere class + normals
This commit is contained in:
BIN
output.png
BIN
output.png
Binary file not shown.
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 33 KiB |
32
src/main.rs
32
src/main.rs
@@ -1,16 +1,40 @@
|
|||||||
#![feature(core_float_math)]
|
#![feature(core_float_math)]
|
||||||
|
|
||||||
|
mod objects;
|
||||||
mod ray;
|
mod ray;
|
||||||
mod vec3;
|
mod vec3;
|
||||||
|
|
||||||
|
use core::f32;
|
||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
|
|
||||||
|
use crate::objects::hit::Hit;
|
||||||
|
use crate::objects::sphere::Sphere;
|
||||||
|
use crate::objects::traits::{Hittable, Normal};
|
||||||
use crate::ray::Ray;
|
use crate::ray::Ray;
|
||||||
use crate::vec3::{Colour, Vec3};
|
use crate::vec3::{Colour, Vec3};
|
||||||
use log::info;
|
use log::info;
|
||||||
use pretty_env_logger;
|
use pretty_env_logger;
|
||||||
|
|
||||||
fn ray_colour(r: &Ray) -> Colour {
|
fn ray_colour<T>(hittables: &Vec<T>, r: &Ray) -> Colour
|
||||||
|
where
|
||||||
|
T: Hittable + Normal,
|
||||||
|
{
|
||||||
|
let mut closest: Option<Hit> = None;
|
||||||
|
for hittable in hittables {
|
||||||
|
if let Some(hit) = hittable.hit(r) {
|
||||||
|
// hit happens in front of camera and is closer than closest
|
||||||
|
if *hit.t() > 0. && (closest.is_none() || closest.as_ref().unwrap().t() > hit.t()) {
|
||||||
|
closest = Some(hit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(hit) = closest {
|
||||||
|
let n = hit.n();
|
||||||
|
return 0.5 * Colour::new(n.x() + 1., n.y() + 1., n.z() + 1.);
|
||||||
|
}
|
||||||
|
|
||||||
|
// background
|
||||||
let unit_dir = r.dir().get_unit();
|
let unit_dir = r.dir().get_unit();
|
||||||
let a = 0.5 * (unit_dir.y() + 1.);
|
let a = 0.5 * (unit_dir.y() + 1.);
|
||||||
|
|
||||||
@@ -19,8 +43,8 @@ fn ray_colour(r: &Ray) -> Colour {
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// use structs so rust-analyzer can provide lsp
|
// use structs so rust-analyzer can provide lsp
|
||||||
let v = Vec3::new(255., 0., 255.);
|
let s = Sphere::new(Vec3::new(0., 0., -1.), 0.5);
|
||||||
let _ = Ray::new(v.clone(), v.clone());
|
let objects = vec![s];
|
||||||
|
|
||||||
pretty_env_logger::init();
|
pretty_env_logger::init();
|
||||||
|
|
||||||
@@ -56,7 +80,7 @@ fn main() {
|
|||||||
let r = Ray::new(camera_center, ray_dir);
|
let r = Ray::new(camera_center, ray_dir);
|
||||||
|
|
||||||
let pixel = imgbuf.get_pixel_mut(i, j);
|
let pixel = imgbuf.get_pixel_mut(i, j);
|
||||||
*pixel = ray_colour(&r).output();
|
*pixel = ray_colour(&objects, &r).output();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
3
src/objects.rs
Normal file
3
src/objects.rs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
pub mod hit;
|
||||||
|
pub mod sphere;
|
||||||
|
pub mod traits;
|
||||||
25
src/objects/hit.rs
Normal file
25
src/objects/hit.rs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
use crate::vec3::Vec3;
|
||||||
|
|
||||||
|
pub struct Hit {
|
||||||
|
t: f32,
|
||||||
|
p: Vec3,
|
||||||
|
n: Vec3,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hit {
|
||||||
|
pub fn new(t: f32, p: Vec3, n: Vec3) -> Hit {
|
||||||
|
Hit { t: t, p: p, n: n }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn t(&self) -> &f32 {
|
||||||
|
&self.t
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn p(&self) -> &Vec3 {
|
||||||
|
&self.p
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn n(&self) -> &Vec3 {
|
||||||
|
&self.n
|
||||||
|
}
|
||||||
|
}
|
||||||
44
src/objects/sphere.rs
Normal file
44
src/objects/sphere.rs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
use core::f32::math::sqrt;
|
||||||
|
|
||||||
|
use crate::objects::hit::Hit;
|
||||||
|
use crate::objects::traits::{Hittable, Normal};
|
||||||
|
use crate::Vec3;
|
||||||
|
|
||||||
|
pub struct Sphere {
|
||||||
|
center: Vec3,
|
||||||
|
radius: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sphere {
|
||||||
|
pub fn new(center: Vec3, radius: f32) -> Sphere {
|
||||||
|
Sphere {
|
||||||
|
center: center,
|
||||||
|
radius: radius,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hittable for Sphere {
|
||||||
|
fn hit(&self, r: &crate::ray::Ray) -> Option<Hit> {
|
||||||
|
let oc = self.center - r.origin();
|
||||||
|
let a = r.dir().dot(r.dir());
|
||||||
|
let b = -2. * r.dir().dot(&oc);
|
||||||
|
let c = oc.dot(&oc) - self.radius * self.radius;
|
||||||
|
|
||||||
|
let d = b * b - 4. * a * c;
|
||||||
|
|
||||||
|
if d < 0. {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let t = (-b - sqrt(d)) / (2.0 * a);
|
||||||
|
let p = r.at(t);
|
||||||
|
Some(Hit::new(t, p, self.normal_at(&p)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Normal for Sphere {
|
||||||
|
fn normal_at(&self, p: &Vec3) -> Vec3 {
|
||||||
|
(*p - self.center).get_unit()
|
||||||
|
}
|
||||||
|
}
|
||||||
11
src/objects/traits.rs
Normal file
11
src/objects/traits.rs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
use crate::objects::hit::Hit;
|
||||||
|
use crate::Ray;
|
||||||
|
use crate::Vec3;
|
||||||
|
|
||||||
|
pub trait Hittable {
|
||||||
|
fn hit(&self, r: &Ray) -> Option<Hit>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Normal {
|
||||||
|
fn normal_at(&self, p: &Vec3) -> Vec3;
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@ pub struct Ray {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Ray {
|
impl Ray {
|
||||||
pub fn at(self, t: f32) -> Vec3 {
|
pub fn at(&self, t: f32) -> Vec3 {
|
||||||
self.origin + t * self.dir
|
self.origin + t * self.dir
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
21
src/vec3.rs
21
src/vec3.rs
@@ -46,15 +46,11 @@ impl Vec3 {
|
|||||||
(self.r * self.r + self.g * self.g + self.b * self.b) as f32
|
(self.r * self.r + self.g * self.g + self.b * self.b) as f32
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dot(self, other: Vec3) -> Vec3 {
|
pub fn dot(&self, other: &Vec3) -> f32 {
|
||||||
Vec3 {
|
self.r * other.r + self.g * other.g + self.b * other.b
|
||||||
r: self.r * other.r,
|
|
||||||
g: self.g * other.g,
|
|
||||||
b: self.b * other.b,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cross(self, other: Vec3) -> Vec3 {
|
pub fn cross(&self, other: &Vec3) -> Vec3 {
|
||||||
Vec3 {
|
Vec3 {
|
||||||
r: self.g * other.b - self.b * other.g,
|
r: self.g * other.b - self.b * other.g,
|
||||||
g: self.b * other.r - self.r * other.b,
|
g: self.b * other.r - self.r * other.b,
|
||||||
@@ -142,6 +138,17 @@ impl AddAssign<f32> for Vec3 {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl Sub<&Vec3> for Vec3 {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn sub(self, rhs: &Self) -> Self {
|
||||||
|
Self {
|
||||||
|
r: self.r - rhs.r,
|
||||||
|
g: self.g - rhs.g,
|
||||||
|
b: self.b - rhs.b,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Sub<Vec3> for Vec3 {
|
impl Sub<Vec3> for Vec3 {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|||||||
Reference in New Issue
Block a user