ft (wip): random scene generation
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
use std::f32::consts::PI;
|
use std::f32::consts::PI;
|
||||||
|
|
||||||
use log::{info, warn};
|
use log::info;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
objects::{hit::Hit, traits::Hittable},
|
objects::{hit::Hit, traits::Hittable},
|
||||||
@@ -129,7 +129,6 @@ impl Camera {
|
|||||||
if self.dirty {
|
if self.dirty {
|
||||||
self.init()
|
self.init()
|
||||||
}
|
}
|
||||||
warn!("{}", format!("{self:#?}"));
|
|
||||||
|
|
||||||
let mut imgbuf = image::ImageBuffer::new(self.image_width, self.image_height);
|
let mut imgbuf = image::ImageBuffer::new(self.image_width, self.image_height);
|
||||||
|
|
||||||
|
|||||||
112
src/main.rs
112
src/main.rs
@@ -10,39 +10,109 @@ use std::sync::Arc;
|
|||||||
use crate::camera::Camera;
|
use crate::camera::Camera;
|
||||||
use crate::objects::materials::dielectric::Dielectric;
|
use crate::objects::materials::dielectric::Dielectric;
|
||||||
use crate::objects::materials::lambertian::{Lambertian, Metal};
|
use crate::objects::materials::lambertian::{Lambertian, Metal};
|
||||||
|
use crate::objects::materials::traits::Material;
|
||||||
use crate::objects::sphere::Sphere;
|
use crate::objects::sphere::Sphere;
|
||||||
|
use crate::objects::traits::Hittable;
|
||||||
use crate::ray::Ray;
|
use crate::ray::Ray;
|
||||||
use crate::vec3::Vec3;
|
use crate::vec3::Vec3;
|
||||||
use dotenv::dotenv;
|
use dotenv::dotenv;
|
||||||
|
use log::info;
|
||||||
use pretty_env_logger;
|
use pretty_env_logger;
|
||||||
|
use rand::seq::IndexedRandom;
|
||||||
|
use rand::RngExt;
|
||||||
|
|
||||||
|
fn random_material() -> Arc<dyn Material> {
|
||||||
|
let mut rng = rand::rng();
|
||||||
|
let col = Vec3::new(rng.random(), rng.random(), rng.random());
|
||||||
|
match rng.random_range(0..3) {
|
||||||
|
0 => Arc::new(Lambertian::new(col, 1.)),
|
||||||
|
1 => Arc::new(Metal::new(col, 1., rng.random())),
|
||||||
|
2 => Arc::new(Dielectric::new(rng.random_range(0.3..1.9))),
|
||||||
|
_ => Arc::new(Metal::new(col, 0., rng.random())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn random_sphere_on_floor<T: Hittable>(
|
||||||
|
materials: &Vec<Arc<dyn Material>>,
|
||||||
|
existing: &Vec<T>,
|
||||||
|
max_size: f32,
|
||||||
|
) -> Sphere {
|
||||||
|
let mut rng = rand::rng();
|
||||||
|
let r = rng.random_range(0.1..max_size);
|
||||||
|
let mut sphere = Sphere::xyz(
|
||||||
|
rng.random_range((-50.)..50.),
|
||||||
|
r,
|
||||||
|
rng.random_range((-50.)..50.),
|
||||||
|
r,
|
||||||
|
materials.choose(&mut rng).unwrap().clone(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut isct = true;
|
||||||
|
let mut attempts_left = 49;
|
||||||
|
while isct && attempts_left > 0 {
|
||||||
|
isct = false;
|
||||||
|
for h in existing {
|
||||||
|
if h.inside(&h.closest_on_surface(sphere.center())) {
|
||||||
|
info!("Generating sphere failed, {} attempts left", attempts_left);
|
||||||
|
isct = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if isct {
|
||||||
|
sphere.set_center(Vec3::new(
|
||||||
|
rng.random_range(0.5..100.),
|
||||||
|
r,
|
||||||
|
rng.random_range(0.5..100.),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
attempts_left -= 1;
|
||||||
|
}
|
||||||
|
sphere
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dotenv().ok();
|
dotenv().ok();
|
||||||
pretty_env_logger::init();
|
pretty_env_logger::init();
|
||||||
|
|
||||||
// setup objects
|
// setup objects
|
||||||
let blue = Arc::new(Metal::rgb(0.2, 0.4, 0.8, 1., 0.1));
|
// let blue = Arc::new(Metal::rgb(0.2, 0.4, 0.8, 1., 0.1));
|
||||||
let metal = Arc::new(Metal::rgb(0.7, 0.4, 0.2, 1., 0.1));
|
// let metal = Arc::new(Metal::rgb(0.7, 0.4, 0.2, 1., 0.1));
|
||||||
let ground = Arc::new(Lambertian::rgb(0.8, 0.8, 0., 1.0));
|
// let ground = Arc::new(Lambertian::rgb(0.8, 0.8, 0., 1.0));
|
||||||
let center = Arc::new(Lambertian::rgb(0.1, 0.2, 0.5, 1.));
|
// let center = Arc::new(Lambertian::rgb(0.1, 0.2, 0.5, 1.));
|
||||||
let left = Arc::new(Dielectric::new(1.5));
|
// let left = Arc::new(Dielectric::new(1.5));
|
||||||
let bubble = Arc::new(Dielectric::new(1. / 1.5));
|
// let bubble = Arc::new(Dielectric::new(1. / 1.5));
|
||||||
let right = Arc::new(Metal::rgb(0.8, 0.6, 0.2, 1., 1.0));
|
// let right = Arc::new(Metal::rgb(0.8, 0.6, 0.2, 1., 1.0));
|
||||||
|
//
|
||||||
|
// let mut world = vec![Sphere::xyz(0., 0.5, -0.8, 0.1, metal.clone())];
|
||||||
|
// world.push(Sphere::xyz(0., -100.5, -1., 100., ground.clone()));
|
||||||
|
// world.push(Sphere::xyz(0., 0., -1.2, 0.5, center.clone()));
|
||||||
|
// world.push(Sphere::xyz(-1., 0., -1.0, 0.5, left.clone()));
|
||||||
|
// world.push(Sphere::xyz(-1., 0., -1.0, 0.4, bubble.clone()));
|
||||||
|
// world.push(Sphere::xyz(1., 0., -1.0, 0.5, right.clone()));
|
||||||
|
// world.push(Sphere::xyz(0., 0.7, -0.4, 0.2, blue.clone()));
|
||||||
|
|
||||||
let mut world = vec![Sphere::xyz(0., 0.5, -0.8, 0.1, metal.clone())];
|
let mut materials: Vec<Arc<dyn Material>> = vec![Arc::new(Lambertian::rgb(0.1, 0.2, 0.6, 1.))];
|
||||||
world.push(Sphere::xyz(0., -100.5, -1., 100., ground.clone()));
|
for i in 0..15 {
|
||||||
world.push(Sphere::xyz(0., 0., -1.2, 0.5, center.clone()));
|
info!("Generating {}th material.", i + 1);
|
||||||
world.push(Sphere::xyz(-1., 0., -1.0, 0.5, left.clone()));
|
materials.push(random_material());
|
||||||
world.push(Sphere::xyz(-1., 0., -1.0, 0.4, bubble.clone()));
|
}
|
||||||
world.push(Sphere::xyz(1., 0., -1.0, 0.5, right.clone()));
|
|
||||||
world.push(Sphere::xyz(0., 0.7, -0.4, 0.2, blue.clone()));
|
|
||||||
|
|
||||||
let mut c = Camera::new(400, 300);
|
let mut world = vec![Sphere::xyz(0., -1000.5, -1., 1000., materials[0].clone())];
|
||||||
// let mut c = Camera::new(1920, 1080);
|
for i in 0..40 {
|
||||||
c.set_fov(20.);
|
info!("Generating {}th sphere.", i + 1);
|
||||||
c.set_anti_alias_rate(2);
|
world.push(random_sphere_on_floor(
|
||||||
c.set_max_depth(90);
|
&materials,
|
||||||
c.set_look_from(Vec3::new(-2., 2., 1.));
|
&world,
|
||||||
c.set_look_at(Vec3::new(0., 0., -1.));
|
(i + 1) as f32 / 3.,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// let mut c = Camera::new(400, 300);
|
||||||
|
let mut c = Camera::new(1920, 1080);
|
||||||
|
c.set_fov(90.);
|
||||||
|
c.set_anti_alias_rate(6);
|
||||||
|
c.set_max_depth(100);
|
||||||
|
c.set_look_from(Vec3::new(-60., 10., 1.));
|
||||||
|
c.set_look_at(Vec3::new(0., 0., 0.));
|
||||||
c.render(&world);
|
c.render(&world);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,16 @@ impl Sphere {
|
|||||||
material: mat,
|
material: mat,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn center(&self) -> &Vec3 {
|
||||||
|
&self.center
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_center(&mut self, center: Vec3) {
|
||||||
|
if self.center != center {
|
||||||
|
self.center = center;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Hittable for Sphere {
|
impl Hittable for Sphere {
|
||||||
@@ -60,4 +70,12 @@ impl Hittable for Sphere {
|
|||||||
fn normal_at(&self, p: &Vec3) -> Vec3 {
|
fn normal_at(&self, p: &Vec3) -> Vec3 {
|
||||||
(*p - self.center).get_unit()
|
(*p - self.center).get_unit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn inside(&self, p: &Vec3) -> bool {
|
||||||
|
(*p - self.center).length() < self.radius
|
||||||
|
}
|
||||||
|
|
||||||
|
fn closest_on_surface(&self, p: &Vec3) -> Vec3 {
|
||||||
|
self.normal_at(p) * self.radius
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,4 +5,7 @@ use crate::Vec3;
|
|||||||
pub trait Hittable {
|
pub trait Hittable {
|
||||||
fn hit(&self, r: &Ray) -> Option<Hit>;
|
fn hit(&self, r: &Ray) -> Option<Hit>;
|
||||||
fn normal_at(&self, p: &Vec3) -> Vec3;
|
fn normal_at(&self, p: &Vec3) -> Vec3;
|
||||||
|
// fn intersect<H: Hittable>(&self, o: &H) -> bool;
|
||||||
|
fn inside(&self, p: &Vec3) -> bool;
|
||||||
|
fn closest_on_surface(&self, p: &Vec3) -> Vec3;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user