Removed pixels
Finished raytracer Reimplementing imgui
This commit is contained in:
1429
Cargo.lock
generated
1429
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
21
Cargo.toml
21
Cargo.toml
@@ -4,25 +4,18 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies.image]
|
|
||||||
version = "0.24"
|
|
||||||
default-features = false
|
|
||||||
features = ["png", "jpeg"]
|
|
||||||
|
|
||||||
[dependencies.winit]
|
|
||||||
version = "0.27"
|
|
||||||
features = ["x11"]
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
cfg-if = "1"
|
cfg-if = "1"
|
||||||
env_logger = "0.10"
|
env_logger = "0.10"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
wgpu = "0.18"
|
|
||||||
pollster = "0.3"
|
pollster = "0.3"
|
||||||
bytemuck = { version = "1.12", features = [ "derive" ] }
|
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
nalgebra = "0.32.3"
|
nalgebra = "0.32.3"
|
||||||
roots = "0.0.8"
|
roots = "0.0.8"
|
||||||
lazy_static = "1.4.0"
|
pyo3 = "0.20.0"
|
||||||
arc = "0.0.1"
|
imgui = "0.11"
|
||||||
pixels = "0.13.0"
|
imgui-wgpu = "0.24"
|
||||||
|
imgui-winit-support = "0.11"
|
||||||
|
winit_input_helper = "0.13"
|
||||||
|
winit = "0.29.3"
|
||||||
|
wgpu = "0.18.0"
|
||||||
|
|||||||
@@ -53,8 +53,9 @@ impl Camera {
|
|||||||
let view_proj = self.build_view_projection_matrix();
|
let view_proj = self.build_view_projection_matrix();
|
||||||
view_proj.try_inverse().expect("Cannot invert!")
|
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 inverse_matrix = self.build_inverse_view_projection_matrix();
|
||||||
|
|
||||||
let dx = 2.0 / width as f32;
|
let dx = 2.0 / width as f32;
|
||||||
let dy = 2.0 / height as f32;
|
let dy = 2.0 / height as f32;
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -2,16 +2,16 @@
|
|||||||
#![allow(unused_imports)]
|
#![allow(unused_imports)]
|
||||||
#![allow(unused_variables)]
|
#![allow(unused_variables)]
|
||||||
//Use linear algebra module
|
//Use linear algebra module
|
||||||
use display::run;
|
use window::run;
|
||||||
|
|
||||||
//Cameras
|
//Cameras
|
||||||
mod camera;
|
mod camera;
|
||||||
mod display;
|
|
||||||
mod light;
|
mod light;
|
||||||
mod primitive;
|
mod primitive;
|
||||||
mod ray;
|
mod ray;
|
||||||
mod raytracer;
|
mod raytracer;
|
||||||
mod scene;
|
mod scene;
|
||||||
|
mod window;
|
||||||
// mod state;
|
// mod state;
|
||||||
// mod texture;
|
// mod texture;
|
||||||
// mod vertex;
|
// mod vertex;
|
||||||
@@ -20,5 +20,5 @@ const EPSILON: f32 = 1e-7;
|
|||||||
const INFINITY: f32 = 1e7;
|
const INFINITY: f32 = 1e7;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
run().expect("");
|
run().expect("YEY");
|
||||||
}
|
}
|
||||||
|
|||||||
185
src/primitive.rs
185
src/primitive.rs
@@ -5,12 +5,7 @@ use roots::{find_roots_quadratic, Roots};
|
|||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{BufRead, BufReader};
|
use std::io::{BufRead, BufReader};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::sync::Arc;
|
||||||
use lazy_static::lazy_static;
|
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
static ref MAGENTA_MATERIAL: Material = Material::magenta();
|
|
||||||
}
|
|
||||||
|
|
||||||
// MATERIAL -----------------------------------------------------------------
|
// MATERIAL -----------------------------------------------------------------
|
||||||
pub struct Material {
|
pub struct Material {
|
||||||
@@ -30,27 +25,27 @@ impl Material {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// INTERSECTION -----------------------------------------------------------------
|
// INTERSECTION -----------------------------------------------------------------
|
||||||
pub struct Intersection<'a> {
|
pub struct Intersection {
|
||||||
// Information about an intersection
|
// Information about an intersection
|
||||||
pub primitive: &'a dyn Primitive<'a>,
|
|
||||||
pub point: Point3<f32>,
|
pub point: Point3<f32>,
|
||||||
pub normal: Vector3<f32>,
|
pub normal: Vector3<f32>,
|
||||||
pub incidence: Vector3<f32>,
|
pub incidence: Vector3<f32>,
|
||||||
|
pub material: Arc<Material>,
|
||||||
pub distance: f32,
|
pub distance: f32,
|
||||||
}
|
}
|
||||||
impl<'a> Intersection<'a> {
|
impl Intersection {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
primitive: &'a dyn Primitive<'a>,
|
|
||||||
point: Point3<f32>,
|
point: Point3<f32>,
|
||||||
normal: Vector3<f32>,
|
normal: Vector3<f32>,
|
||||||
incidence: Vector3<f32>,
|
incidence: Vector3<f32>,
|
||||||
|
material: Arc<Material>,
|
||||||
t: f32,
|
t: f32,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Intersection {
|
Intersection {
|
||||||
primitive,
|
|
||||||
point,
|
point,
|
||||||
normal,
|
normal,
|
||||||
incidence,
|
incidence,
|
||||||
|
material,
|
||||||
distance: t,
|
distance: t,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -80,22 +75,22 @@ impl BoundingBox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// PRIMITIVE TRAIT -----------------------------------------------------------------
|
// PRIMITIVE TRAIT -----------------------------------------------------------------
|
||||||
pub trait Primitive<'a> {
|
pub trait Primitive {
|
||||||
fn intersect_ray(&self, ray: &Ray) -> Option<Intersection>;
|
fn intersect_ray(&self, ray: &Ray) -> Option<Intersection>;
|
||||||
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>>;
|
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>>;
|
||||||
fn get_material(&self) -> &'a Material;
|
fn get_material(&self) -> Arc<Material>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SPHERE -----------------------------------------------------------------
|
// SPHERE -----------------------------------------------------------------
|
||||||
struct Sphere<'a> {
|
struct Sphere {
|
||||||
position: Point3<f32>,
|
position: Point3<f32>,
|
||||||
radius: f32,
|
radius: f32,
|
||||||
material: &'a Material,
|
|
||||||
bounding_box: BoundingBox,
|
bounding_box: BoundingBox,
|
||||||
|
material: Arc<Material>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Sphere<'a> {
|
impl Sphere {
|
||||||
fn new(position: Point3<f32>, radius: f32, material: &'a Material) -> Self {
|
fn new(position: Point3<f32>, radius: f32, material: Arc<Material>) -> Self {
|
||||||
let radius_vec = Vector3::new(radius, radius, radius);
|
let radius_vec = Vector3::new(radius, radius, radius);
|
||||||
let bln = position - radius_vec;
|
let bln = position - radius_vec;
|
||||||
let trf = position + radius_vec;
|
let trf = position + radius_vec;
|
||||||
@@ -103,17 +98,17 @@ impl<'a> Sphere<'a> {
|
|||||||
Sphere {
|
Sphere {
|
||||||
position,
|
position,
|
||||||
radius,
|
radius,
|
||||||
material,
|
|
||||||
bounding_box,
|
bounding_box,
|
||||||
|
material,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unit() -> Self {
|
fn unit(material: Arc<Material>) -> Self {
|
||||||
Sphere::new(Point3::new(0.0, 0.0, 0.0), 1.0, &MAGENTA_MATERIAL)
|
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> {
|
fn intersect_ray(&self, ray: &Ray) -> Option<Intersection> {
|
||||||
let pos = &ray.a;
|
let pos = &ray.a;
|
||||||
let dir = &ray.b;
|
let dir = &ray.b;
|
||||||
@@ -144,16 +139,16 @@ impl<'a> Primitive<'a> for Sphere<'a> {
|
|||||||
let intersect = ray.at_t(t);
|
let intersect = ray.at_t(t);
|
||||||
let normal = (intersect - self.position).normalize();
|
let normal = (intersect - self.position).normalize();
|
||||||
Some(Intersection {
|
Some(Intersection {
|
||||||
primitive: self,
|
|
||||||
point: intersect,
|
point: intersect,
|
||||||
normal,
|
normal,
|
||||||
incidence: ray.b,
|
incidence: ray.b,
|
||||||
|
material: Arc::clone(&self.material),
|
||||||
distance: t,
|
distance: t,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_material(&self) -> &'a Material {
|
fn get_material(&self) -> Arc<Material> {
|
||||||
self.material
|
Arc::clone(&self.material)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
|
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
|
||||||
@@ -162,20 +157,20 @@ impl<'a> Primitive<'a> for Sphere<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CIRCLE -----------------------------------------------------------------
|
// CIRCLE -----------------------------------------------------------------
|
||||||
struct Circle<'a> {
|
struct Circle {
|
||||||
position: Point3<f32>,
|
position: Point3<f32>,
|
||||||
radius: f32,
|
radius: f32,
|
||||||
normal: Vector3<f32>,
|
normal: Vector3<f32>,
|
||||||
material: &'a Material,
|
material: Arc<Material>,
|
||||||
bounding_box: BoundingBox,
|
bounding_box: BoundingBox,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Circle<'a> {
|
impl Circle {
|
||||||
fn new(
|
fn new(
|
||||||
position: Point3<f32>,
|
position: Point3<f32>,
|
||||||
radius: f32,
|
radius: f32,
|
||||||
normal: Vector3<f32>,
|
normal: Vector3<f32>,
|
||||||
material: &'a Material,
|
material: Arc<Material>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let radius_vec = Vector3::new(radius, radius, radius);
|
let radius_vec = Vector3::new(radius, radius, radius);
|
||||||
let bln = position - radius_vec;
|
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 position = Point3::new(0.0, 0.0, 0.0);
|
||||||
let normal = Vector3::new(0.0, 1.0, 0.0);
|
let normal = Vector3::new(0.0, 1.0, 0.0);
|
||||||
let radius = 1.0;
|
let radius = 1.0;
|
||||||
let material = &MAGENTA_MATERIAL;
|
let material = material;
|
||||||
|
|
||||||
let bln = Point3::new(-radius, 0.0, -EPSILON);
|
let bln = Point3::new(-radius, 0.0, -EPSILON);
|
||||||
let trf = 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> {
|
fn intersect_ray(&self, ray: &Ray) -> Option<Intersection> {
|
||||||
let constant = self.position.coords.dot(&self.normal);
|
let constant = self.position.coords.dot(&self.normal);
|
||||||
let denominator = ray.b.dot(&self.normal);
|
let denominator = ray.b.dot(&self.normal);
|
||||||
@@ -224,18 +219,18 @@ impl<'a> Primitive<'a> for Circle<'a> {
|
|||||||
true => return None,
|
true => return None,
|
||||||
false => {
|
false => {
|
||||||
return Some(Intersection {
|
return Some(Intersection {
|
||||||
primitive: self,
|
|
||||||
point: intersect,
|
point: intersect,
|
||||||
normal: self.normal,
|
normal: self.normal,
|
||||||
incidence: ray.b,
|
incidence: ray.b,
|
||||||
|
material: Arc::clone(&self.material),
|
||||||
distance: t,
|
distance: t,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_material(&self) -> &'a Material {
|
fn get_material(&self) -> Arc<Material> {
|
||||||
self.material
|
Arc::clone(&self.material)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
|
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
|
||||||
@@ -244,23 +239,23 @@ impl<'a> Primitive<'a> for Circle<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CYLINDER -----------------------------------------------------------------
|
// CYLINDER -----------------------------------------------------------------
|
||||||
struct Cylinder<'a> {
|
struct Cylinder {
|
||||||
radius: f32,
|
radius: f32,
|
||||||
base: f32,
|
base: f32,
|
||||||
height: f32,
|
height: f32,
|
||||||
base_circle: &'a Circle<'a>,
|
base_circle: Circle,
|
||||||
height_circle: &'a Circle<'a>,
|
height_circle: Circle,
|
||||||
material: &'a Material,
|
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> {
|
fn intersect_ray(&self, ray: &Ray) -> Option<Intersection> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_material(&self) -> &'a Material {
|
fn get_material(&self) -> Arc<Material> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,22 +265,22 @@ impl<'a> Primitive<'a> for Cylinder<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CONE -----------------------------------------------------------------
|
// CONE -----------------------------------------------------------------
|
||||||
struct Cone<'a> {
|
pub struct Cone {
|
||||||
radius: f32,
|
radius: f32,
|
||||||
base: f32,
|
base: f32,
|
||||||
height: f32,
|
height: f32,
|
||||||
circle: Circle<'a>,
|
circle: Circle,
|
||||||
material: &'a Material,
|
material: Arc<Material>,
|
||||||
bounding_box: BoundingBox,
|
bounding_box: BoundingBox,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Cone<'a> {
|
impl Cone {
|
||||||
fn new(radius: f32, height: f32, base: f32, material: &'a Material) -> Self {
|
pub fn new(radius: f32, height: f32, base: f32, material: Arc<Material>) -> Self {
|
||||||
let circle = Circle::new(
|
let circle = Circle::new(
|
||||||
Point3::new(0.0, base, 0.0),
|
Point3::new(0.0, base, 0.0),
|
||||||
radius,
|
radius,
|
||||||
Vector3::new(0.0, 1.0, 0.0),
|
Vector3::new(0.0, 1.0, 0.0),
|
||||||
&material,
|
Arc::clone(&material),
|
||||||
);
|
);
|
||||||
let bln = Point3::new(-radius, base, -radius);
|
let bln = Point3::new(-radius, base, -radius);
|
||||||
let trf = Point3::new(radius, base + height, radius);
|
let trf = Point3::new(radius, base + height, radius);
|
||||||
@@ -298,11 +293,11 @@ impl<'a> Cone<'a> {
|
|||||||
bounding_box: BoundingBox { bln, trf },
|
bounding_box: BoundingBox { bln, trf },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn unit() -> Self {
|
pub fn unit(material: Arc<Material>) -> Self {
|
||||||
Cone::new(1.0, 2.0, -1.0, &MAGENTA_MATERIAL)
|
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 r = self.radius;
|
||||||
let h = self.height;
|
let h = self.height;
|
||||||
let (x, y, z) = (intersect.x, intersect.y, intersect.z);
|
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> {
|
fn intersect_ray(&self, ray: &Ray) -> Option<Intersection> {
|
||||||
let point = &ray.a;
|
let point = &ray.a;
|
||||||
let dir = &ray.b;
|
let dir = &ray.b;
|
||||||
@@ -346,9 +341,9 @@ impl<'a> Primitive<'a> for Cone<'a> {
|
|||||||
let intersect = ray.at_t(t);
|
let intersect = ray.at_t(t);
|
||||||
match intersect.y >= self.base && intersect.y <= self.height {
|
match intersect.y >= self.base && intersect.y <= self.height {
|
||||||
true => Some(Intersection {
|
true => Some(Intersection {
|
||||||
primitive: self,
|
|
||||||
point: intersect,
|
point: intersect,
|
||||||
normal: self.get_normal(intersect),
|
normal: self.get_normal(intersect),
|
||||||
|
material: Arc::clone(&self.material),
|
||||||
incidence: ray.b,
|
incidence: ray.b,
|
||||||
distance: t,
|
distance: t,
|
||||||
}),
|
}),
|
||||||
@@ -374,8 +369,8 @@ impl<'a> Primitive<'a> for Cone<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_material(&self) -> &'a Material {
|
fn get_material(&self) -> Arc<Material> {
|
||||||
self.material
|
Arc::clone(&self.material)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
|
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
|
||||||
@@ -384,24 +379,24 @@ impl<'a> Primitive<'a> for Cone<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RECTANGLE -----------------------------------------------------------------
|
// RECTANGLE -----------------------------------------------------------------
|
||||||
struct Rectangle<'a> {
|
struct Rectangle {
|
||||||
position: Point3<f32>,
|
position: Point3<f32>,
|
||||||
normal: Vector3<f32>,
|
normal: Vector3<f32>,
|
||||||
width_direction: Vector3<f32>,
|
width_direction: Vector3<f32>,
|
||||||
material: &'a Material,
|
material: Arc<Material>,
|
||||||
width: f32,
|
width: f32,
|
||||||
height: f32,
|
height: f32,
|
||||||
bounding_box: BoundingBox,
|
bounding_box: BoundingBox,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Rectangle<'a> {
|
impl Rectangle {
|
||||||
fn new(
|
fn new(
|
||||||
position: Point3<f32>,
|
position: Point3<f32>,
|
||||||
normal: Vector3<f32>,
|
normal: Vector3<f32>,
|
||||||
width_direction: Vector3<f32>,
|
width_direction: Vector3<f32>,
|
||||||
width: f32,
|
width: f32,
|
||||||
height: f32,
|
height: f32,
|
||||||
material: &'a Material,
|
material: Arc<Material>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let normal = normal.normalize();
|
let normal = normal.normalize();
|
||||||
let width_direction = width_direction.normalize();
|
let width_direction = width_direction.normalize();
|
||||||
@@ -418,19 +413,19 @@ impl<'a> Rectangle<'a> {
|
|||||||
bounding_box: BoundingBox { bln, trf },
|
bounding_box: BoundingBox { bln, trf },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn unit() -> Self {
|
fn unit(material: Arc<Material>) -> Self {
|
||||||
Rectangle::new(
|
Rectangle::new(
|
||||||
Point3::new(0.0, 0.0, 0.0),
|
Point3::new(0.0, 0.0, 0.0),
|
||||||
Vector3::new(0.0, 1.0, 0.0),
|
Vector3::new(0.0, 1.0, 0.0),
|
||||||
Vector3::new(1.0, 0.0, 0.0),
|
Vector3::new(1.0, 0.0, 0.0),
|
||||||
2.0,
|
2.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> {
|
fn intersect_ray(&self, ray: &Ray) -> Option<Intersection> {
|
||||||
let constant = self.position.coords.dot(&self.normal);
|
let constant = self.position.coords.dot(&self.normal);
|
||||||
let denominator = ray.b.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 {
|
if pi_dot_r1 >= -w2 && pi_dot_r1 <= w2 && pi_dot_r2 >= -h2 && pi_dot_r2 <= h2 {
|
||||||
return Some(Intersection {
|
return Some(Intersection {
|
||||||
primitive: self,
|
|
||||||
point: intersect,
|
point: intersect,
|
||||||
normal: self.normal,
|
normal: self.normal,
|
||||||
incidence: ray.b,
|
incidence: ray.b,
|
||||||
|
material: Arc::clone(&self.material),
|
||||||
distance: t,
|
distance: t,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_material(&self) -> &'a Material {
|
fn get_material(&self) -> Arc<Material> {
|
||||||
self.material
|
Arc::clone(&self.material)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
|
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
|
||||||
@@ -471,16 +466,16 @@ impl<'a> Primitive<'a> for Rectangle<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// BOX -----------------------------------------------------------------
|
// BOX -----------------------------------------------------------------
|
||||||
struct Box<'a> {
|
struct Box {
|
||||||
width: f32,
|
width: f32,
|
||||||
height: f32,
|
height: f32,
|
||||||
depth: f32,
|
depth: f32,
|
||||||
material: &'a Material,
|
material: Arc<Material>,
|
||||||
bounding_box: BoundingBox,
|
bounding_box: BoundingBox,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Box<'a> {
|
impl Box {
|
||||||
fn new(width: f32, height: f32, depth: f32, material: &'a Material) -> Self {
|
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 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);
|
let bln = Point3::new(-width / 2.0, -height / 2.0, -depth / 2.0);
|
||||||
Box {
|
Box {
|
||||||
@@ -491,12 +486,12 @@ impl<'a> Box<'a> {
|
|||||||
bounding_box: BoundingBox { bln, trf },
|
bounding_box: BoundingBox { bln, trf },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn unit() -> Self {
|
fn unit(material: Arc<Material>) -> Self {
|
||||||
Box::new(2.0, 2.0, 2.0, &MAGENTA_MATERIAL)
|
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> {
|
fn intersect_ray(&self, ray: &Ray) -> Option<Intersection> {
|
||||||
// Compute the minimum and maximum t-values for each axis of the bounding box
|
// 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);
|
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 {
|
Some(Intersection {
|
||||||
primitive: self,
|
|
||||||
point: intersect,
|
point: intersect,
|
||||||
normal,
|
normal,
|
||||||
incidence: ray.b,
|
incidence: ray.b,
|
||||||
|
material: Arc::clone(&self.material),
|
||||||
distance: tmin,
|
distance: tmin,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@@ -553,23 +548,23 @@ impl<'a> Primitive<'a> for Box<'a> {
|
|||||||
self.bounding_box.intersect_bounding_box(ray)
|
self.bounding_box.intersect_bounding_box(ray)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_material(&self) -> &'a Material {
|
fn get_material(&self) -> Arc<Material> {
|
||||||
self.material
|
Arc::clone(&self.material)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TRIANGLE -----------------------------------------------------------------
|
// TRIANGLE -----------------------------------------------------------------
|
||||||
struct Triangle<'a> {
|
struct Triangle {
|
||||||
u: Point3<f32>,
|
u: Point3<f32>,
|
||||||
v: Point3<f32>,
|
v: Point3<f32>,
|
||||||
w: Point3<f32>,
|
w: Point3<f32>,
|
||||||
normal: Vector3<f32>,
|
normal: Vector3<f32>,
|
||||||
material: &'a Material,
|
material: Arc<Material>,
|
||||||
bounding_box: BoundingBox,
|
bounding_box: BoundingBox,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Triangle<'a> {
|
impl Triangle {
|
||||||
fn new(u: Point3<f32>, v: Point3<f32>, w: Point3<f32>, material: &'a Material) -> Self {
|
fn new(u: Point3<f32>, v: Point3<f32>, w: Point3<f32>, material: Arc<Material>) -> Self {
|
||||||
let uv = v - u;
|
let uv = v - u;
|
||||||
let uw = w - u;
|
let uw = w - u;
|
||||||
let normal = uv.cross(&uw).normalize();
|
let normal = uv.cross(&uw).normalize();
|
||||||
@@ -585,16 +580,16 @@ impl<'a> Triangle<'a> {
|
|||||||
bounding_box,
|
bounding_box,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn unit() -> Self {
|
fn unit(material: Arc<Material>) -> Self {
|
||||||
let u = Point3::new(-1.0, 0.0, -1.0);
|
let u = Point3::new(-1.0, 0.0, -1.0);
|
||||||
let v = Point3::new(0.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 w = Point3::new(1.0, 0.0, -1.0);
|
||||||
let material = &MAGENTA_MATERIAL;
|
let material = material;
|
||||||
Triangle::new(u, v, w, 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> {
|
fn intersect_ray(&self, ray: &Ray) -> Option<Intersection> {
|
||||||
let constant = self.u.coords.dot(&self.normal);
|
let constant = self.u.coords.dot(&self.normal);
|
||||||
let denominator = ray.b.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
|
if u_cross.dot(&normal) >= 0.0 && v_cross.dot(&normal) >= 0.0 && w_cross.dot(&normal) >= 0.0
|
||||||
{
|
{
|
||||||
Some(Intersection {
|
Some(Intersection {
|
||||||
primitive: self,
|
|
||||||
point: intersect,
|
point: intersect,
|
||||||
normal,
|
normal,
|
||||||
incidence: ray.b,
|
incidence: ray.b,
|
||||||
|
material: Arc::clone(&self.material),
|
||||||
distance: t,
|
distance: t,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@@ -634,8 +629,8 @@ impl<'a> Primitive<'a> for Triangle<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_material(&self) -> &'a Material {
|
fn get_material(&self) -> Arc<Material> {
|
||||||
self.material
|
Arc::clone(&self.material)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
|
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
|
||||||
@@ -644,14 +639,14 @@ impl<'a> Primitive<'a> for Triangle<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MESH -----------------------------------------------------------------
|
// MESH -----------------------------------------------------------------
|
||||||
struct Mesh<'a> {
|
struct Mesh {
|
||||||
triangles: Vec<Triangle<'a>>,
|
triangles: Vec<Triangle>,
|
||||||
material: &'a Material,
|
material: Arc<Material>,
|
||||||
bounding_box: BoundingBox,
|
bounding_box: BoundingBox,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Mesh<'a> {
|
impl Mesh {
|
||||||
fn new(triangles: Vec<Triangle<'a>>, material: &'a Material) -> Self {
|
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
|
// Calculate the bounding box for the entire mesh based on the bounding boxes of individual triangles
|
||||||
let bounding_box = Mesh::compute_bounding_box(&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 bln = Point3::new(INFINITY, INFINITY, INFINITY);
|
||||||
let mut trf = -bln;
|
let mut trf = -bln;
|
||||||
for triangle in triangles {
|
for triangle in triangles {
|
||||||
@@ -677,7 +672,7 @@ impl<'a> Mesh<'a> {
|
|||||||
BoundingBox { bln, trf }
|
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 triangles: Vec<Triangle> = Vec::new();
|
||||||
let mut vertices: Vec<Point3<f32>> = Vec::new();
|
let mut vertices: Vec<Point3<f32>> = Vec::new();
|
||||||
|
|
||||||
@@ -715,7 +710,7 @@ impl<'a> Mesh<'a> {
|
|||||||
let a = vertices[v1 - 1];
|
let a = vertices[v1 - 1];
|
||||||
let b = vertices[v2 - 1];
|
let b = vertices[v2 - 1];
|
||||||
let c = vertices[v3 - 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> {
|
fn intersect_ray(&self, ray: &Ray) -> Option<Intersection> {
|
||||||
let mut closest_distance = INFINITY;
|
let mut closest_distance = INFINITY;
|
||||||
let mut closest_intersect: Option<Intersection> = None;
|
let mut closest_intersect: Option<Intersection> = None;
|
||||||
@@ -748,8 +743,8 @@ impl<'a> Primitive<'a> for Mesh<'a> {
|
|||||||
closest_intersect
|
closest_intersect
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_material(&self) -> &'a Material {
|
fn get_material(&self) -> Arc<Material> {
|
||||||
self.material
|
Arc::clone(&self.material)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
|
fn intersect_bounding_box(&self, ray: &Ray) -> Option<Point3<f32>> {
|
||||||
|
|||||||
@@ -5,20 +5,38 @@ use crate::{
|
|||||||
scene::Scene,
|
scene::Scene,
|
||||||
INFINITY,
|
INFINITY,
|
||||||
};
|
};
|
||||||
use lazy_static::lazy_static;
|
use std::sync::Arc;
|
||||||
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 nalgebra::{distance, Matrix4, Point3, Vector3, Vector4};
|
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
|
// 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_distance = INFINITY;
|
||||||
let mut closest_intersect: Option<Intersection> = None;
|
let mut closest_intersect: Option<Intersection> = None;
|
||||||
for primitive in &scene.primitives {
|
for arc_primitive in &scene.primitives {
|
||||||
if primitive.intersect_bounding_box(ray) == None {
|
let primitive = arc_primitive.clone();
|
||||||
|
|
||||||
|
if primitive.intersect_ray(ray).is_none() {
|
||||||
continue;
|
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
|
// 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
|
//Useful vectors !!!! CHECK IF WE CAN OPTIMISE
|
||||||
let zero_vector = Vector3::new(0.0, 0.0, 0.0);
|
let zero_vector = Vector3::new(0.0, 0.0, 0.0);
|
||||||
let one_vector = Vector3::new(1.0, 1.0, 1.0);
|
let one_vector = Vector3::new(1.0, 1.0, 1.0);
|
||||||
//Unpack the intersection data
|
//Unpack the intersection data
|
||||||
let Intersection {
|
let Intersection {
|
||||||
primitive,
|
|
||||||
point,
|
point,
|
||||||
normal,
|
normal,
|
||||||
incidence,
|
incidence,
|
||||||
|
material,
|
||||||
..
|
..
|
||||||
} = intersect;
|
} = intersect;
|
||||||
let ambient_light = scene.ambient_light;
|
let binding = scene.ambient_light.clone();
|
||||||
let material = primitive.get_material();
|
let ambient_light = binding.as_ref();
|
||||||
let kd = material.kd;
|
let kd = material.kd;
|
||||||
let ks = material.ks;
|
let ks = material.ks;
|
||||||
let shininess = material.shininess;
|
let shininess = material.shininess;
|
||||||
// We should now have all the information for our ray-tracer
|
// 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 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 {
|
let Light {
|
||||||
position: light_position,
|
position: light_position,
|
||||||
colour: light_colour,
|
colour: light_colour,
|
||||||
falloff: light_falloff,
|
falloff: light_falloff,
|
||||||
} = light;
|
} = light.as_ref();
|
||||||
|
|
||||||
// Get light incidence vector
|
// Get light incidence vector
|
||||||
let to_light = light_position - point;
|
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));
|
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)
|
||||||
}
|
}
|
||||||
|
|||||||
38
src/scene.rs
38
src/scene.rs
@@ -2,12 +2,38 @@ use crate::camera::Camera;
|
|||||||
use crate::light::Light;
|
use crate::light::Light;
|
||||||
use crate::primitive::Primitive;
|
use crate::primitive::Primitive;
|
||||||
use nalgebra::Vector3;
|
use nalgebra::Vector3;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub struct Scene<'a> {
|
pub struct Scene {
|
||||||
pub primitives: Vec<Box<dyn Primitive<'a>>>,
|
pub primitives: Vec<Arc<dyn Primitive>>,
|
||||||
pub lights: Vec<Light>,
|
pub lights: Vec<Arc<Light>>,
|
||||||
pub cameras: Vec<Camera>,
|
pub cameras: Vec<Arc<Camera>>,
|
||||||
pub ambient_light: Vector3<f32>,
|
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)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user