ft: 10: metals
This commit is contained in:
@@ -1,14 +1,26 @@
|
||||
use crate::{objects::traits::Hittable, ray::Ray, vec3::Vec3};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
objects::{materials::traits::Material, traits::Hittable},
|
||||
ray::Ray,
|
||||
vec3::Vec3,
|
||||
};
|
||||
|
||||
pub struct Hit {
|
||||
t: f32,
|
||||
p: Vec3,
|
||||
n: Vec3,
|
||||
mat: Arc<dyn Material>,
|
||||
}
|
||||
|
||||
impl Hit {
|
||||
pub fn new(t: f32, p: Vec3, n: Vec3) -> Hit {
|
||||
Hit { t: t, p: p, n: n }
|
||||
pub fn new(t: f32, p: Vec3, n: Vec3, mat: Arc<dyn Material>) -> Self {
|
||||
Self {
|
||||
t: t,
|
||||
p: p,
|
||||
n: n,
|
||||
mat: mat,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn t(&self) -> &f32 {
|
||||
@@ -23,6 +35,10 @@ impl Hit {
|
||||
&self.n
|
||||
}
|
||||
|
||||
pub fn mat(&self) -> Arc<dyn Material> {
|
||||
self.mat.clone()
|
||||
}
|
||||
|
||||
pub fn hit_list<T: Hittable>(hittables: &Vec<T>, r: &Ray) -> Option<Hit> {
|
||||
let mut closest: Option<Hit> = None;
|
||||
for hittable in hittables {
|
||||
|
||||
2
src/objects/materials.rs
Normal file
2
src/objects/materials.rs
Normal file
@@ -0,0 +1,2 @@
|
||||
pub mod lambertian;
|
||||
pub mod traits;
|
||||
79
src/objects/materials/lambertian.rs
Normal file
79
src/objects/materials/lambertian.rs
Normal file
@@ -0,0 +1,79 @@
|
||||
use rand::RngExt;
|
||||
|
||||
use crate::{
|
||||
objects::{hit::Hit, materials::traits::Material},
|
||||
ray::Ray,
|
||||
vec3::{Colour, Vec3},
|
||||
};
|
||||
|
||||
pub struct Lambertian {
|
||||
albedo: Colour,
|
||||
prob: f32,
|
||||
}
|
||||
|
||||
impl Lambertian {
|
||||
pub fn new(albedo: Colour, prob: f32) -> Self {
|
||||
Self {
|
||||
albedo: albedo,
|
||||
prob: prob,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rgb(r: f32, g: f32, b: f32, prob: f32) -> Self {
|
||||
Self {
|
||||
albedo: Colour::new(r, g, b),
|
||||
prob: prob,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Material for Lambertian {
|
||||
fn scatter(&self, hit: &Hit, ray: &Ray) -> Option<(Ray, Colour)> {
|
||||
let mut rng = rand::rng();
|
||||
if self.prob >= rng.random::<f32>() {
|
||||
let mut dir = *hit.n() + Vec3::random_unit();
|
||||
if dir.near_zero() {
|
||||
dir = *hit.n();
|
||||
}
|
||||
let scattered = Ray::new(*hit.p(), dir);
|
||||
return Some((scattered, self.albedo));
|
||||
}
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Metal {
|
||||
albedo: Colour,
|
||||
prob: f32,
|
||||
fuzz: f32,
|
||||
}
|
||||
|
||||
impl Metal {
|
||||
pub fn new(albedo: Colour, prob: f32, fuzz: f32) -> Self {
|
||||
Self {
|
||||
albedo: albedo,
|
||||
prob: prob,
|
||||
fuzz: fuzz,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rgb(r: f32, g: f32, b: f32, prob: f32, fuzz: f32) -> Self {
|
||||
Self {
|
||||
albedo: Colour::new(r, g, b),
|
||||
prob: prob,
|
||||
fuzz: fuzz,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Material for Metal {
|
||||
fn scatter(&self, hit: &Hit, ray: &Ray) -> Option<(Ray, Colour)> {
|
||||
let mut rng = rand::rng();
|
||||
if self.prob >= rng.random::<f32>() {
|
||||
let mut refl = ray.dir().reflect(hit.n());
|
||||
refl = refl.get_unit() + self.fuzz * Vec3::random_unit();
|
||||
return Some((Ray::new(*hit.p(), refl), self.albedo));
|
||||
}
|
||||
return None;
|
||||
}
|
||||
}
|
||||
5
src/objects/materials/traits.rs
Normal file
5
src/objects/materials/traits.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
use crate::{objects::hit::Hit, ray::Ray, vec3::Colour};
|
||||
|
||||
pub trait Material {
|
||||
fn scatter(&self, hit: &Hit, ray: &Ray) -> Option<(Ray, Colour)>;
|
||||
}
|
||||
@@ -1,19 +1,31 @@
|
||||
use core::f32::math::sqrt;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::objects::hit::Hit;
|
||||
use crate::objects::materials::traits::Material;
|
||||
use crate::objects::traits::Hittable;
|
||||
use crate::Vec3;
|
||||
|
||||
pub struct Sphere {
|
||||
center: Vec3,
|
||||
radius: f32,
|
||||
material: Arc<dyn Material>,
|
||||
}
|
||||
|
||||
impl Sphere {
|
||||
pub fn new(center: Vec3, radius: f32) -> Sphere {
|
||||
Sphere {
|
||||
pub fn new(center: Vec3, r: f32, mat: Arc<dyn Material>) -> Self {
|
||||
Self {
|
||||
center: center,
|
||||
radius: radius,
|
||||
radius: r,
|
||||
material: mat,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn xyz(x: f32, y: f32, z: f32, r: f32, mat: Arc<dyn Material>) -> Self {
|
||||
Self {
|
||||
center: Vec3::new(x, y, z),
|
||||
radius: r,
|
||||
material: mat,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,7 +43,7 @@ impl Hittable for Sphere {
|
||||
} else {
|
||||
let t = (h - sqrt(d)) / a;
|
||||
let p = r.at(t);
|
||||
Some(Hit::new(t, p, self.normal_at(&p)))
|
||||
Some(Hit::new(t, p, self.normal_at(&p), self.material.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user