Removed pixels

Finished raytracer
Reimplementing imgui
This commit is contained in:
STP
2023-11-15 16:56:19 -05:00
parent 2e69164dde
commit 80fcc6c8bc
8 changed files with 1159 additions and 658 deletions

View File

@@ -53,8 +53,9 @@ impl Camera {
let view_proj = self.build_view_projection_matrix();
view_proj.try_inverse().expect("Cannot invert!")
}
pub fn cast_rays(&self, width: usize, height: usize) -> Vec<Ray> {
pub fn cast_rays(&self, width: u32, height: u32) -> Vec<Ray> {
let inverse_matrix = self.build_inverse_view_projection_matrix();
let dx = 2.0 / width as f32;
let dy = 2.0 / height as f32;

View File

@@ -1,79 +0,0 @@
use pixels::{Error, Pixels, SurfaceTexture};
use std::time::Instant;
use winit::{
event::{Event, WindowEvent},
event_loop::{ControlFlow, EventLoop},
window::WindowBuilder,
};
pub fn run() -> Result<(), Error> {
// Create an event loop and window using winit
let event_loop = EventLoop::new();
let window = WindowBuilder::new().build(&event_loop).unwrap();
// Create a Pixels instance for drawing
let mut pixels = {
let window_size = window.inner_size();
let surface_texture = SurfaceTexture::new(window_size.width, window_size.height, &window);
Pixels::new(800, 600, surface_texture).unwrap()
};
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Poll;
match event {
Event::WindowEvent {
ref event,
window_id,
} if window_id == window.id() => {
match event {
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
WindowEvent::Resized(physical_size) => {
//We want to change the size of the pixel display
pixels
.resize_surface(physical_size.width, physical_size.height)
.expect("Could not resize");
pixels
.resize_buffer(physical_size.width, physical_size.height)
.expect("Could not resize");
}
WindowEvent::ScaleFactorChanged { new_inner_size, .. } => {
//We want to change the size of the pixel display
// new_inner_size is &mut so w have to dereference it twice
pixels
.resize_surface(new_inner_size.width, new_inner_size.height)
.expect("Could not resize!");
pixels
.resize_buffer(new_inner_size.width, new_inner_size.height)
.expect("Could not resize");
}
WindowEvent::KeyboardInput { input, .. } => {
println!("Key input: {}", input.scancode);
}
_ => {}
}
}
Event::RedrawRequested(_) => {
// Draw a pixel at every coordinate
for (i, pixel) in pixels.frame_mut().chunks_exact_mut(4).enumerate() {
let r = (i as u8).wrapping_mul(50);
let g = 43;
let b = 3;
let a = 255;
pixel.copy_from_slice(&[r, g, b, a]);
}
// Render the frame
if pixels.render().is_err() {
eprintln!("Failed to render frame");
}
}
Event::MainEventsCleared => {
// RedrawRequested will only trigger once, unless we manually
// request it.
window.request_redraw();
}
_ => {}
}
});
}

View File

@@ -2,16 +2,16 @@
#![allow(unused_imports)]
#![allow(unused_variables)]
//Use linear algebra module
use display::run;
use window::run;
//Cameras
mod camera;
mod display;
mod light;
mod primitive;
mod ray;
mod raytracer;
mod scene;
mod window;
// mod state;
// mod texture;
// mod vertex;
@@ -20,5 +20,5 @@ const EPSILON: f32 = 1e-7;
const INFINITY: f32 = 1e7;
fn main() {
run().expect("");
run().expect("YEY");
}

View File

@@ -5,12 +5,7 @@ use roots::{find_roots_quadratic, Roots};
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::Path;
use lazy_static::lazy_static;
lazy_static! {
static ref MAGENTA_MATERIAL: Material = Material::magenta();
}
use std::sync::Arc;
// MATERIAL -----------------------------------------------------------------
pub struct Material {
@@ -30,27 +25,27 @@ impl Material {
}
}
// INTERSECTION -----------------------------------------------------------------
pub struct Intersection<'a> {
pub struct Intersection {
// Information about an intersection
pub primitive: &'a dyn Primitive<'a>,
pub point: Point3<f32>,
pub normal: Vector3<f32>,
pub incidence: Vector3<f32>,
pub material: Arc<Material>,
pub distance: f32,
}
impl<'a> Intersection<'a> {
impl Intersection {
pub fn new(
primitive: &'a dyn Primitive<'a>,
point: Point3<f32>,
normal: Vector3<f32>,
incidence: Vector3<f32>,
material: Arc<Material>,
t: f32,
) -> Self {
Intersection {
primitive,
point,
normal,
incidence,
material,
distance: t,
}
}
@@ -80,22 +75,22 @@ impl BoundingBox {
}
}
// PRIMITIVE TRAIT -----------------------------------------------------------------
pub trait Primitive<'a> {
pub trait Primitive {
fn intersect_ray(&self, ray: &Ray) -> Option<Intersection>;
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>>;
fn get_material(&self) -> &'a Material;
fn get_material(&self) -> Arc<Material>;
}
// SPHERE -----------------------------------------------------------------
struct Sphere<'a> {
struct Sphere {
position: Point3<f32>,
radius: f32,
material: &'a Material,
bounding_box: BoundingBox,
material: Arc<Material>,
}
impl<'a> Sphere<'a> {
fn new(position: Point3<f32>, radius: f32, material: &'a Material) -> Self {
impl Sphere {
fn new(position: Point3<f32>, radius: f32, material: Arc<Material>) -> Self {
let radius_vec = Vector3::new(radius, radius, radius);
let bln = position - radius_vec;
let trf = position + radius_vec;
@@ -103,17 +98,17 @@ impl<'a> Sphere<'a> {
Sphere {
position,
radius,
material,
bounding_box,
material,
}
}
fn unit() -> Self {
Sphere::new(Point3::new(0.0, 0.0, 0.0), 1.0, &MAGENTA_MATERIAL)
fn unit(material: Arc<Material>) -> Self {
Sphere::new(Point3::new(0.0, 0.0, 0.0), 1.0, material)
}
}
impl<'a> Primitive<'a> for Sphere<'a> {
impl Primitive for Sphere {
fn intersect_ray(&self, ray: &Ray) -> Option<Intersection> {
let pos = &ray.a;
let dir = &ray.b;
@@ -144,16 +139,16 @@ impl<'a> Primitive<'a> for Sphere<'a> {
let intersect = ray.at_t(t);
let normal = (intersect - self.position).normalize();
Some(Intersection {
primitive: self,
point: intersect,
normal,
incidence: ray.b,
material: Arc::clone(&self.material),
distance: t,
})
}
fn get_material(&self) -> &'a Material {
self.material
fn get_material(&self) -> Arc<Material> {
Arc::clone(&self.material)
}
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
@@ -162,20 +157,20 @@ impl<'a> Primitive<'a> for Sphere<'a> {
}
// CIRCLE -----------------------------------------------------------------
struct Circle<'a> {
struct Circle {
position: Point3<f32>,
radius: f32,
normal: Vector3<f32>,
material: &'a Material,
material: Arc<Material>,
bounding_box: BoundingBox,
}
impl<'a> Circle<'a> {
impl Circle {
fn new(
position: Point3<f32>,
radius: f32,
normal: Vector3<f32>,
material: &'a Material,
material: Arc<Material>,
) -> Self {
let radius_vec = Vector3::new(radius, radius, radius);
let bln = position - radius_vec;
@@ -190,11 +185,11 @@ impl<'a> Circle<'a> {
}
}
fn unit() -> Self {
fn unit(material: Arc<Material>) -> Self {
let position = Point3::new(0.0, 0.0, 0.0);
let normal = Vector3::new(0.0, 1.0, 0.0);
let radius = 1.0;
let material = &MAGENTA_MATERIAL;
let material = material;
let bln = Point3::new(-radius, 0.0, -EPSILON);
let trf = Point3::new(radius, 0.0, EPSILON);
@@ -210,7 +205,7 @@ impl<'a> Circle<'a> {
}
}
impl<'a> Primitive<'a> for Circle<'a> {
impl Primitive for Circle {
fn intersect_ray(&self, ray: &Ray) -> Option<Intersection> {
let constant = self.position.coords.dot(&self.normal);
let denominator = ray.b.dot(&self.normal);
@@ -224,18 +219,18 @@ impl<'a> Primitive<'a> for Circle<'a> {
true => return None,
false => {
return Some(Intersection {
primitive: self,
point: intersect,
normal: self.normal,
incidence: ray.b,
material: Arc::clone(&self.material),
distance: t,
})
}
}
}
fn get_material(&self) -> &'a Material {
self.material
fn get_material(&self) -> Arc<Material> {
Arc::clone(&self.material)
}
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
@@ -244,23 +239,23 @@ impl<'a> Primitive<'a> for Circle<'a> {
}
// CYLINDER -----------------------------------------------------------------
struct Cylinder<'a> {
struct Cylinder {
radius: f32,
base: f32,
height: f32,
base_circle: &'a Circle<'a>,
height_circle: &'a Circle<'a>,
material: &'a Material,
base_circle: Circle,
height_circle: Circle,
material: Arc<Material>,
}
impl<'a> Cylinder<'a> {}
impl Cylinder {}
impl<'a> Primitive<'a> for Cylinder<'a> {
impl Primitive for Cylinder {
fn intersect_ray(&self, ray: &Ray) -> Option<Intersection> {
todo!()
}
fn get_material(&self) -> &'a Material {
fn get_material(&self) -> Arc<Material> {
todo!()
}
@@ -270,22 +265,22 @@ impl<'a> Primitive<'a> for Cylinder<'a> {
}
// CONE -----------------------------------------------------------------
struct Cone<'a> {
pub struct Cone {
radius: f32,
base: f32,
height: f32,
circle: Circle<'a>,
material: &'a Material,
circle: Circle,
material: Arc<Material>,
bounding_box: BoundingBox,
}
impl<'a> Cone<'a> {
fn new(radius: f32, height: f32, base: f32, material: &'a Material) -> Self {
impl Cone {
pub fn new(radius: f32, height: f32, base: f32, material: Arc<Material>) -> Self {
let circle = Circle::new(
Point3::new(0.0, base, 0.0),
radius,
Vector3::new(0.0, 1.0, 0.0),
&material,
Arc::clone(&material),
);
let bln = Point3::new(-radius, base, -radius);
let trf = Point3::new(radius, base + height, radius);
@@ -298,11 +293,11 @@ impl<'a> Cone<'a> {
bounding_box: BoundingBox { bln, trf },
}
}
fn unit() -> Self {
Cone::new(1.0, 2.0, -1.0, &MAGENTA_MATERIAL)
pub fn unit(material: Arc<Material>) -> Self {
Cone::new(1.0, 2.0, -1.0, material)
}
fn get_normal(&self, intersect: Point3<f32>) -> Vector3<f32> {
pub fn get_normal(&self, intersect: Point3<f32>) -> Vector3<f32> {
let r = self.radius;
let h = self.height;
let (x, y, z) = (intersect.x, intersect.y, intersect.z);
@@ -311,7 +306,7 @@ impl<'a> Cone<'a> {
}
}
impl<'a> Primitive<'a> for Cone<'a> {
impl Primitive for Cone {
fn intersect_ray(&self, ray: &Ray) -> Option<Intersection> {
let point = &ray.a;
let dir = &ray.b;
@@ -346,9 +341,9 @@ impl<'a> Primitive<'a> for Cone<'a> {
let intersect = ray.at_t(t);
match intersect.y >= self.base && intersect.y <= self.height {
true => Some(Intersection {
primitive: self,
point: intersect,
normal: self.get_normal(intersect),
material: Arc::clone(&self.material),
incidence: ray.b,
distance: t,
}),
@@ -374,8 +369,8 @@ impl<'a> Primitive<'a> for Cone<'a> {
}
}
fn get_material(&self) -> &'a Material {
self.material
fn get_material(&self) -> Arc<Material> {
Arc::clone(&self.material)
}
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
@@ -384,24 +379,24 @@ impl<'a> Primitive<'a> for Cone<'a> {
}
// RECTANGLE -----------------------------------------------------------------
struct Rectangle<'a> {
struct Rectangle {
position: Point3<f32>,
normal: Vector3<f32>,
width_direction: Vector3<f32>,
material: &'a Material,
material: Arc<Material>,
width: f32,
height: f32,
bounding_box: BoundingBox,
}
impl<'a> Rectangle<'a> {
impl Rectangle {
fn new(
position: Point3<f32>,
normal: Vector3<f32>,
width_direction: Vector3<f32>,
width: f32,
height: f32,
material: &'a Material,
material: Arc<Material>,
) -> Self {
let normal = normal.normalize();
let width_direction = width_direction.normalize();
@@ -418,19 +413,19 @@ impl<'a> Rectangle<'a> {
bounding_box: BoundingBox { bln, trf },
}
}
fn unit() -> Self {
fn unit(material: Arc<Material>) -> Self {
Rectangle::new(
Point3::new(0.0, 0.0, 0.0),
Vector3::new(0.0, 1.0, 0.0),
Vector3::new(1.0, 0.0, 0.0),
2.0,
2.0,
&MAGENTA_MATERIAL,
material,
)
}
}
impl<'a> Primitive<'a> for Rectangle<'a> {
impl Primitive for Rectangle {
fn intersect_ray(&self, ray: &Ray) -> Option<Intersection> {
let constant = self.position.coords.dot(&self.normal);
let denominator = ray.b.dot(&self.normal);
@@ -451,18 +446,18 @@ impl<'a> Primitive<'a> for Rectangle<'a> {
if pi_dot_r1 >= -w2 && pi_dot_r1 <= w2 && pi_dot_r2 >= -h2 && pi_dot_r2 <= h2 {
return Some(Intersection {
primitive: self,
point: intersect,
normal: self.normal,
incidence: ray.b,
material: Arc::clone(&self.material),
distance: t,
});
}
None
}
fn get_material(&self) -> &'a Material {
self.material
fn get_material(&self) -> Arc<Material> {
Arc::clone(&self.material)
}
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
@@ -471,16 +466,16 @@ impl<'a> Primitive<'a> for Rectangle<'a> {
}
// BOX -----------------------------------------------------------------
struct Box<'a> {
struct Box {
width: f32,
height: f32,
depth: f32,
material: &'a Material,
material: Arc<Material>,
bounding_box: BoundingBox,
}
impl<'a> Box<'a> {
fn new(width: f32, height: f32, depth: f32, material: &'a Material) -> Self {
impl Box {
fn new(width: f32, height: f32, depth: f32, material: Arc<Material>) -> Self {
let trf = Point3::new(width / 2.0, height / 2.0, depth / 2.0);
let bln = Point3::new(-width / 2.0, -height / 2.0, -depth / 2.0);
Box {
@@ -491,12 +486,12 @@ impl<'a> Box<'a> {
bounding_box: BoundingBox { bln, trf },
}
}
fn unit() -> Self {
Box::new(2.0, 2.0, 2.0, &MAGENTA_MATERIAL)
fn unit(material: Arc<Material>) -> Self {
Box::new(2.0, 2.0, 2.0, material)
}
}
impl<'a> Primitive<'a> for Box<'a> {
impl Primitive for Box {
fn intersect_ray(&self, ray: &Ray) -> Option<Intersection> {
// Compute the minimum and maximum t-values for each axis of the bounding box
let t1 = (self.bounding_box.bln - ray.a).component_div(&ray.b);
@@ -538,10 +533,10 @@ impl<'a> Primitive<'a> for Box<'a> {
};
Some(Intersection {
primitive: self,
point: intersect,
normal,
incidence: ray.b,
material: Arc::clone(&self.material),
distance: tmin,
})
} else {
@@ -553,23 +548,23 @@ impl<'a> Primitive<'a> for Box<'a> {
self.bounding_box.intersect_bounding_box(ray)
}
fn get_material(&self) -> &'a Material {
self.material
fn get_material(&self) -> Arc<Material> {
Arc::clone(&self.material)
}
}
// TRIANGLE -----------------------------------------------------------------
struct Triangle<'a> {
struct Triangle {
u: Point3<f32>,
v: Point3<f32>,
w: Point3<f32>,
normal: Vector3<f32>,
material: &'a Material,
material: Arc<Material>,
bounding_box: BoundingBox,
}
impl<'a> Triangle<'a> {
fn new(u: Point3<f32>, v: Point3<f32>, w: Point3<f32>, material: &'a Material) -> Self {
impl Triangle {
fn new(u: Point3<f32>, v: Point3<f32>, w: Point3<f32>, material: Arc<Material>) -> Self {
let uv = v - u;
let uw = w - u;
let normal = uv.cross(&uw).normalize();
@@ -585,16 +580,16 @@ impl<'a> Triangle<'a> {
bounding_box,
}
}
fn unit() -> Self {
fn unit(material: Arc<Material>) -> Self {
let u = Point3::new(-1.0, 0.0, -1.0);
let v = Point3::new(0.0, 0.0, 1.0);
let w = Point3::new(1.0, 0.0, -1.0);
let material = &MAGENTA_MATERIAL;
let material = material;
Triangle::new(u, v, w, material)
}
}
impl<'a> Primitive<'a> for Triangle<'a> {
impl Primitive for Triangle {
fn intersect_ray(&self, ray: &Ray) -> Option<Intersection> {
let constant = self.u.coords.dot(&self.normal);
let denominator = ray.b.dot(&self.normal);
@@ -623,10 +618,10 @@ impl<'a> Primitive<'a> for Triangle<'a> {
if u_cross.dot(&normal) >= 0.0 && v_cross.dot(&normal) >= 0.0 && w_cross.dot(&normal) >= 0.0
{
Some(Intersection {
primitive: self,
point: intersect,
normal,
incidence: ray.b,
material: Arc::clone(&self.material),
distance: t,
})
} else {
@@ -634,8 +629,8 @@ impl<'a> Primitive<'a> for Triangle<'a> {
}
}
fn get_material(&self) -> &'a Material {
self.material
fn get_material(&self) -> Arc<Material> {
Arc::clone(&self.material)
}
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
@@ -644,14 +639,14 @@ impl<'a> Primitive<'a> for Triangle<'a> {
}
// MESH -----------------------------------------------------------------
struct Mesh<'a> {
triangles: Vec<Triangle<'a>>,
material: &'a Material,
struct Mesh {
triangles: Vec<Triangle>,
material: Arc<Material>,
bounding_box: BoundingBox,
}
impl<'a> Mesh<'a> {
fn new(triangles: Vec<Triangle<'a>>, material: &'a Material) -> Self {
impl Mesh {
fn new(triangles: Vec<Triangle>, material: Arc<Material>) -> Self {
// Calculate the bounding box for the entire mesh based on the bounding boxes of individual triangles
let bounding_box = Mesh::compute_bounding_box(&triangles);
@@ -662,7 +657,7 @@ impl<'a> Mesh<'a> {
}
}
fn compute_bounding_box(triangles: &Vec<Triangle<'a>>) -> BoundingBox {
fn compute_bounding_box(triangles: &Vec<Triangle>) -> BoundingBox {
let mut bln = Point3::new(INFINITY, INFINITY, INFINITY);
let mut trf = -bln;
for triangle in triangles {
@@ -677,7 +672,7 @@ impl<'a> Mesh<'a> {
BoundingBox { bln, trf }
}
fn from_file(filename: &str, material: &'a Material) -> Self {
fn from_file(filename: &str, material: Arc<Material>) -> Self {
let mut triangles: Vec<Triangle> = Vec::new();
let mut vertices: Vec<Point3<f32>> = Vec::new();
@@ -715,7 +710,7 @@ impl<'a> Mesh<'a> {
let a = vertices[v1 - 1];
let b = vertices[v2 - 1];
let c = vertices[v3 - 1];
triangles.push(Triangle::new(a, b, c, material));
triangles.push(Triangle::new(a, b, c, Arc::clone(&material)));
}
}
_ => {}
@@ -727,7 +722,7 @@ impl<'a> Mesh<'a> {
}
}
impl<'a> Primitive<'a> for Mesh<'a> {
impl Primitive for Mesh {
fn intersect_ray(&self, ray: &Ray) -> Option<Intersection> {
let mut closest_distance = INFINITY;
let mut closest_intersect: Option<Intersection> = None;
@@ -748,8 +743,8 @@ impl<'a> Primitive<'a> for Mesh<'a> {
closest_intersect
}
fn get_material(&self) -> &'a Material {
self.material
fn get_material(&self) -> Arc<Material> {
Arc::clone(&self.material)
}
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {

View File

@@ -5,20 +5,38 @@ use crate::{
scene::Scene,
INFINITY,
};
use lazy_static::lazy_static;
lazy_static! {
static ref VEC3_ONE: Vector3<f32> = Vector3::new(1.0, 1.0, 1.0);
static ref VEC3_ZERO: Vector3<f32> = Vector3::new(1.0, 1.0, 1.0);
}
use std::sync::Arc;
use nalgebra::{distance, Matrix4, Point3, Vector3, Vector4};
pub fn shade_rays(scene: &Scene, rays: &Vec<Ray>, width: u32, height: u32) -> Vec<Vector3<u8>> {
let mut pixel_data = vec![];
for ray in rays {
let intersect = get_closest_intersection(scene, ray);
match intersect {
Some(interect) => {
let colour = phong_shade_point(scene, &interect);
pixel_data.push(colour);
}
None => {
let colour = Vector3::new(0, 0, 0);
pixel_data.push(colour);
}
}
}
pixel_data
}
// Find the closest intersection, given a ray in world coordinates
fn get_closest_intersection<'a>(scene: &'a Scene, ray: &Ray) -> Option<Intersection<'a>> {
pub fn get_closest_intersection(scene: &Scene, ray: &Ray) -> Option<Intersection> {
let mut closest_distance = INFINITY;
let mut closest_intersect: Option<Intersection> = None;
for primitive in &scene.primitives {
if primitive.intersect_bounding_box(ray) == None {
for arc_primitive in &scene.primitives {
let primitive = arc_primitive.clone();
if primitive.intersect_ray(ray).is_none() {
continue;
};
@@ -37,34 +55,36 @@ fn get_closest_intersection<'a>(scene: &'a Scene, ray: &Ray) -> Option<Intersect
}
// We want to shade a point placed in our scene
fn phong_shade_point(scene: &Scene, intersect: &Intersection) -> Vector3<f32> {
pub fn phong_shade_point(scene: &Scene, intersect: &Intersection) -> Vector3<u8> {
//Useful vectors !!!! CHECK IF WE CAN OPTIMISE
let zero_vector = Vector3::new(0.0, 0.0, 0.0);
let one_vector = Vector3::new(1.0, 1.0, 1.0);
//Unpack the intersection data
let Intersection {
primitive,
point,
normal,
incidence,
material,
..
} = intersect;
let ambient_light = scene.ambient_light;
let material = primitive.get_material();
let binding = scene.ambient_light.clone();
let ambient_light = binding.as_ref();
let kd = material.kd;
let ks = material.ks;
let shininess = material.shininess;
// We should now have all the information for our ray-tracer
// Let us first compute the ambient light component and set it as out base colour
let mut colour = kd.component_mul(&ambient_light);
let mut colour = kd.component_mul(ambient_light);
for arc_light in &scene.lights {
let light = arc_light.clone();
for light in &scene.lights {
let Light {
position: light_position,
colour: light_colour,
falloff: light_falloff,
} = light;
} = light.as_ref();
// Get light incidence vector
let to_light = light_position - point;
@@ -96,5 +116,9 @@ fn phong_shade_point(scene: &Scene, intersect: &Intersection) -> Vector3<f32> {
colour += light_colour.component_mul(&((diffuse + specular) * falloff));
}
nalgebra::clamp(colour, zero_vector, one_vector)
let r = nalgebra::clamp(colour.x * 255.0, 0.0, 255.0) as u8;
let g = nalgebra::clamp(colour.y * 255.0, 0.0, 255.0) as u8;
let b = nalgebra::clamp(colour.z * 255.0, 0.0, 255.0) as u8;
Vector3::new(r, g, b)
}

View File

@@ -2,12 +2,38 @@ use crate::camera::Camera;
use crate::light::Light;
use crate::primitive::Primitive;
use nalgebra::Vector3;
use std::sync::Arc;
pub struct Scene<'a> {
pub primitives: Vec<Box<dyn Primitive<'a>>>,
pub lights: Vec<Light>,
pub cameras: Vec<Camera>,
pub ambient_light: Vector3<f32>,
pub struct Scene {
pub primitives: Vec<Arc<dyn Primitive>>,
pub lights: Vec<Arc<Light>>,
pub cameras: Vec<Arc<Camera>>,
pub ambient_light: Arc<Vector3<f32>>,
}
impl<'a> Scene<'a> {}
impl Scene {
// Creates a new Scene with given parameters
pub fn new(
primitives: Vec<Arc<dyn Primitive>>,
lights: Vec<Arc<Light>>,
cameras: Vec<Arc<Camera>>,
ambient_light: Arc<Vector3<f32>>,
) -> Self {
Scene {
primitives,
lights,
cameras,
ambient_light,
}
}
// Creates an empty Scene with default values
pub fn empty() -> Self {
Scene {
primitives: Vec::new(),
lights: Vec::new(),
cameras: Vec::new(),
ambient_light: Arc::new(Vector3::new(0.0, 0.0, 0.0)),
}
}
}