General functionality implemented.

This commit is contained in:
Madeline Pace
2021-12-19 14:40:26 -05:00
parent 37667fa650
commit 1ad9e037f7
+112 -60
View File
@@ -28,11 +28,6 @@ impl Ray {
} }
} }
struct OrthoCamera {
pos: Vec3<f64>,
plane: bmp::Image
}
struct LightSrc { struct LightSrc {
pos: Vec3<f64>, pos: Vec3<f64>,
intensity: f64 intensity: f64
@@ -47,12 +42,18 @@ impl LightSrc {
} }
} }
struct OrthoCamera {
pos: Vec3<f64>,
plane: bmp::Image,
spheres: Vec<Sphere>,
light: LightSrc
}
impl OrthoCamera { impl OrthoCamera {
fn new(pos: Vec3<f64>) -> OrthoCamera { fn trace(&self, ray: &Ray) -> Option<Intersection> {
OrthoCamera { self.spheres.iter()
pos: pos, .filter_map(|s| s.intersection(ray).map(|d| Intersection::new(d, s) ))
plane: Image::new(256,256) .min_by(|i1, i2| i1.distance.partial_cmp(&i2.distance).unwrap())
}
} }
} }
@@ -94,14 +95,61 @@ impl Sphere {
} }
} }
fn main() { struct Intersection<'a> {
let mut camera = OrthoCamera::new(Vec3::new(0.0, 0.0, 0.0)); distance: f64,
let mut spheres = Vec::new(); object: &'a Sphere
let light = LightSrc::new(Vec3::new(125.0, 0.0, 100.0), 500.0); }
spheres.push(Sphere::new(Vec3::new(125.0, 75.0, 100.0), 20.0)); impl<'a> Intersection<'a> {
spheres.push(Sphere::new(Vec3::new(125.0, 175.0, 100.0), 60.0)); fn new<'b>(distance: f64, object: &'b Sphere) -> Intersection<'b> {
// spheres.push(Sphere::new(Vec3::new(0.0, 0.0, 100.0), 10.0)); Intersection {
distance: distance,
object: & object
}
}
}
fn get_color(camera: &OrthoCamera, ray: &Ray, intersection: &Intersection) -> f64 {
let hit_point = ray.at(intersection.distance);
let normal = intersection.object.pos - hit_point;
let light_vec = hit_point - camera.light.pos;
let light_intensity = camera.light.intensity;
let light_power = (normal.normalize().dot(&light_vec.normalize()) as f64).max(0.0) * light_intensity;
let light_reflected = 2.0 / std::f64::consts::PI;
return light_power * light_reflected;
// let shadow_ray = Ray {
// pos: hit + (normal.normalize() * 1e-03),
// dir: -light_vec.normalize()
// };
//
// let mut in_light = false;
// let mut light_calc = 0.0;
// for shadow_sphere in &spheres {
// if shadow_sphere.intersection(&shadow_ray).is_none() {
// in_light = true;
// }
//
// let light_intensity = if in_light { light.intensity } else { 0.0 };
// let light_power = (normal.normalize().dot(&light_vec.normalize()) as f64).max(0.0) * light_intensity;
// let light_reflected = 2.0 / std::f64::consts::PI;
// light_calc = light_power * light_reflected;
// }
}
fn main() {
let mut camera = OrthoCamera {
pos: Vec3::new(0.0, 0.0, 0.0),
plane: Image::new(256,256),
spheres: Vec::new(),
light: LightSrc::new(Vec3::new(125.0, -100.0, 100.0), 500.0)
};
camera.spheres.push(Sphere::new(Vec3::new(125.0, 75.0, 100.0), 20.0));
camera.spheres.push(Sphere::new(Vec3::new(115.0, 175.0, 100.0), 60.0));
camera.spheres.push(Sphere::new(Vec3::new(0.0, 0.0, 100.0), 10.0));
// for i in 0..15 { // for i in 0..15 {
// let mut rng = rand::thread_rng(); // let mut rng = rand::thread_rng();
// let x: f64 = rng.gen::<f64>() * 250.0; // let x: f64 = rng.gen::<f64>() * 250.0;
@@ -113,51 +161,55 @@ fn main() {
for (x, y) in camera.plane.coordinates() { for (x, y) in camera.plane.coordinates() {
camera.plane.set_pixel(x, y, px!(0, y, 0)); camera.plane.set_pixel(x, y, px!(0, y, 0));
} let ray = Ray::new(Vec3::new(x as f64, y as f64, camera.pos.z as f64), Vec3::new(0.0, 0.0, 1.0));
let result = camera.trace(&ray);
for (x, y) in camera.plane.coordinates() { match result {
for sphere in &spheres { Some(intersection) => {
let ray = Ray::new(Vec3::new(x as f64, y as f64, camera.pos.z as f64), Vec3::new(0.0, 0.0, 1.0)); let light_color = get_color(&camera, &ray, &intersection);
let result = sphere.intersection(&ray); camera.plane.set_pixel(x, y, px!(light_color, 0, 0))
},
None => { }
match result {
Some(distance) => {
let hit = ray.at(distance);
let normal = sphere.pos - hit;
let light_vec = hit - light.pos;
let shadow_ray = Ray {
pos: hit + (normal.normalize() * 1e-03),
dir: -light_vec.normalize()
};
let mut in_light = false;
for shadow_sphere in &spheres {
if shadow_sphere.intersection(&shadow_ray).is_none() {
in_light = true;
}
if in_light {
println!("in light");
}
let light_intensity = if in_light { light.intensity } else { 0.0 };
let light_power = (normal.normalize().dot(&light_vec.normalize()) as f64).max(0.0) * light_intensity;
let light_reflected = 2.0 / std::f64::consts::PI;
let light_calc = light_power * light_reflected;
camera.plane.set_pixel(x, y, px!(light_calc, light_calc, light_calc));
if !in_light {
//camera.plane.set_pixel(x, y, px!(255, 0, 0));
}
}
}
None => { },
}
} }
} }
// for (x, y) in camera.plane.coordinates() {
// for sphere in &spheres {
// let ray = Ray::new(Vec3::new(x as f64, y as f64, camera.pos.z as f64), Vec3::new(0.0, 0.0, 1.0));
// let result = sphere.intersection(&ray);
//
//
// match result {
// Some(distance) => {
// let hit = ray.at(distance);
// let normal = sphere.pos - hit;
// let light_vec = hit - light.pos;
//
// let shadow_ray = Ray {
// pos: hit + (normal.normalize() * 1e-03),
// dir: -light_vec.normalize()
// };
//
// let mut in_light = false;
// let mut light_calc = 0.0;
// for shadow_sphere in &spheres {
// if shadow_sphere.intersection(&shadow_ray).is_none() {
// in_light = true;
// }
//
// let light_intensity = if in_light { light.intensity } else { 0.0 };
// let light_power = (normal.normalize().dot(&light_vec.normalize()) as f64).max(0.0) * light_intensity;
// let light_reflected = 2.0 / std::f64::consts::PI;
// light_calc = light_power * light_reflected;
//
// }
// camera.plane.set_pixel(x, y, px!(light_calc, light_calc, light_calc));
//
// }
// None => { },
// }
// }
// }
let _ = camera.plane.save("img.bmp"); let _ = camera.plane.save("img.bmp");
} }