Working scripting

This commit is contained in:
STP
2023-11-19 15:33:04 -05:00
parent 7d04822b1f
commit f31ebb06bd
5 changed files with 236 additions and 132 deletions

View File

@@ -20,4 +20,4 @@ winit = "0.27"
winit_input_helper = "0.13" winit_input_helper = "0.13"
pixels = "0.13" pixels = "0.13"
error-iter = "0.4.1" error-iter = "0.4.1"
rhai = "1.16.3" rhai = {version = "1.16.3", features=["f32_float"]}

View File

@@ -39,20 +39,19 @@ const EPSILON_VECTOR: Vector3<f32> = Vector3::new(EPSILON, EPSILON, EPSILON);
const INFINITY_VECTOR: Vector3<f32> = Vector3::new(INFINITY, INFINITY, INFINITY); const INFINITY_VECTOR: Vector3<f32> = Vector3::new(INFINITY, INFINITY, INFINITY);
struct State { struct State {
scene: Arc<Scene>, scene: Scene,
window: Window, window: Window,
pixels: Arc<Mutex<Pixels>>, pixels: Arc<Mutex<Pixels>>,
gui: Gui, gui: Gui,
index: usize, index: usize,
camera: Camera,
rays: Arc<Vec<Ray>>, rays: Arc<Vec<Ray>>,
} }
impl State { impl State {
/// Create a new `World` instance that can draw a moving box. /// Create a new `World` instance that can draw a moving box.
fn new(window: Window, scene: Scene, camera: Camera) -> Self { fn new(window: Window, scene: Scene) -> Self {
let window_size = window.inner_size(); let window_size = window.inner_size();
let pixels = { let pixels = {
let surface_texture = let surface_texture =
@@ -65,14 +64,15 @@ impl State {
.unwrap() .unwrap()
}; };
let gui = Gui::new(&window, &pixels); let gui = Gui::new(&window, &pixels);
let rays = camera.cast_rays(window_size.width, window_size.height); let rays = scene
.camera
.cast_rays(window_size.width, window_size.height);
Self { Self {
scene: Arc::new(scene), scene,
window, window,
pixels: Arc::new(Mutex::new(pixels)), pixels: Arc::new(Mutex::new(pixels)),
gui, gui,
camera,
index: 0, index: 0,
rays: Arc::new(rays), rays: Arc::new(rays),
} }
@@ -92,8 +92,8 @@ impl State {
return false; return false;
} }
self.index = 0; self.index = 0;
self.camera.set_position(self.gui.camera_eye); self.scene.camera.set_position(self.gui.camera_eye);
self.rays = Arc::new(self.camera.cast_rays(width_new, height_new)); self.rays = Arc::new(self.scene.camera.cast_rays(width_new, height_new));
} }
true true
} }
@@ -201,55 +201,57 @@ impl State {
fn main() -> Result<(), Error> { fn main() -> Result<(), Error> {
env_logger::init(); env_logger::init();
env::set_var("RUST_BACKTRACE", "1"); env::set_var("RUST_BACKTRACE", "1");
Scene::init("test.rhai").expect("Could not read lua file");
//Window //Window
let event_loop = EventLoop::new(); let event_loop = EventLoop::new();
//SCENE //SCENE
//Camera // //Camera
let eye = Point3::new(10.0, 0.0, 10.0); // let eye = Point3::new(10.0, 0.0, 10.0);
let target = Point3::new(0.0, 0.0, 0.0); // let target = Point3::new(0.0, 0.0, 0.0);
let up = Vector3::new(0.0, 1.0, 0.0); // let up = Vector3::new(0.0, 1.0, 0.0);
let camera = Camera::new( // let camera = Camera::new(
eye, // eye,
target, // target,
up, // up,
90.0, // 90.0,
(START_WIDTH as f32 / START_HEIGHT as f32) as f32, // (START_WIDTH as f32 / START_HEIGHT as f32) as f32,
); // );
// SETUP MATERIALS // // SETUP MATERIALS
let magenta = Arc::new(Material::magenta()); // let magenta = Arc::new(Material::magenta());
let blue = Arc::new(Material::blue()); // let blue = Arc::new(Material::blue());
let turquoise = Arc::new(Material::turquoise()); // let turquoise = Arc::new(Material::turquoise());
let red = Arc::new(Material::red()); // let red = Arc::new(Material::red());
// SETUP PRIMITIVES // // SETUP PRIMITIVES
let mut primitives: Vec<Box<dyn Primitive>> = Vec::new(); // let mut primitives: Vec<Box<dyn Primitive>> = Vec::new();
//let cube = Box::new(Cube::unit(turquoise.clone())); // //let cube = Box::new(Cube::unit(turquoise.clone()));
// primitives.push(cube); // // primitives.push(cube);
let sphere = Box::new(Sphere::new(Point3::new(0.0, -2.0, 0.0), 1.0, red.clone())); // let sphere = Box::new(Sphere::new(Point3::new(0.0, -2.0, 0.0), 1.0, red.clone()));
let sphere2 = Box::new(Sphere::new(Point3::new(0.0, 2.0, 0.0), 1.0, red.clone())); // let sphere2 = Box::new(Sphere::new(Point3::new(0.0, 2.0, 0.0), 1.0, red.clone()));
let cone = Box::new(Cone::new(1.0, 1.0, -1.0, magenta.clone())); // let cone = Box::new(Cone::new(1.0, 1.0, -1.0, magenta.clone()));
primitives.push(sphere); // primitives.push(sphere);
primitives.push(sphere2); // primitives.push(sphere2);
primitives.push(cone); // primitives.push(cone);
//
// SETUP LIGHTS // // SETUP LIGHTS
let light_pos = Point3::new(0.0, 12.0, 4.0); // let light_pos = Point3::new(0.0, 12.0, 4.0);
let light_colour = Vector3::new(0.4, 0.4, 0.6); // let light_colour = Vector3::new(0.4, 0.4, 0.6);
let light_falloff = [1.0, 0.00, 0.00]; // let light_falloff = [1.0, 0.00, 0.00];
let light = Light::new(light_colour, light_pos, light_falloff); // let light = Light::new(light_colour, light_pos, light_falloff);
//
let light_pos2 = Point3::new(10.0, 12.0, -4.0); // let light_pos2 = Point3::new(10.0, 12.0, -4.0);
let light_colour2 = Vector3::new(0.4, 0.0, 0.6); // let light_colour2 = Vector3::new(0.4, 0.0, 0.6);
let light_falloff2 = [1.0, 0.00, 0.00]; // let light_falloff2 = [1.0, 0.00, 0.00];
let light2 = Light::new(light_colour2, light_pos2, light_falloff2); // let light2 = Light::new(light_colour2, light_pos2, light_falloff2);
//
let ambient_light = Vector3::new(0.0, 0.0, 0.2); // let ambient_light = Vector3::new(0.0, 0.0, 0.2);
//
let scene = Scene::new( // let scene = Scene::new(
primitives, // primitives,
vec![light, light2], // vec![light, light2],
vec![camera.clone()], // vec![camera.clone()],
ambient_light, // ambient_light,
); // );
//State //State
let window = { let window = {
let size = LogicalSize::new(START_WIDTH, START_HEIGHT); let size = LogicalSize::new(START_WIDTH, START_HEIGHT);
@@ -260,7 +262,8 @@ fn main() -> Result<(), Error> {
.build(&event_loop) .build(&event_loop)
.unwrap() .unwrap()
}; };
let mut state = State::new(window, scene, camera); let scene = Scene::empty();
let mut state = State::new(window, scene);
event_loop.run(move |event, _, control_flow| { event_loop.run(move |event, _, control_flow| {
// Draw the current frame // Draw the current frame
@@ -269,6 +272,7 @@ fn main() -> Result<(), Error> {
Event::WindowEvent { event, .. } => match event { Event::WindowEvent { event, .. } => match event {
WindowEvent::CloseRequested => { WindowEvent::CloseRequested => {
*control_flow = ControlFlow::Exit; *control_flow = ControlFlow::Exit;
return;
} }
WindowEvent::Resized(size) => { WindowEvent::Resized(size) => {
state.resize(&size); state.resize(&size);

View File

@@ -15,38 +15,38 @@ pub struct Material {
pub shininess: f32, pub shininess: f32,
} }
impl Material { impl Material {
pub fn new(kd: Vector3<f32>, ks: Vector3<f32>, shininess: f32) -> Self { pub fn new(kd: Vector3<f32>, ks: Vector3<f32>, shininess: f32) -> Arc<Self> {
Material { kd, ks, shininess } Arc::new(Material { kd, ks, shininess })
} }
pub fn magenta() -> Self { pub fn magenta() -> Arc<Self> {
let kd = Vector3::new(1.0, 0.0, 1.0); let kd = Vector3::new(1.0, 0.0, 1.0);
let ks = Vector3::new(1.0, 0.0, 1.0); let ks = Vector3::new(1.0, 0.0, 1.0);
let shininess = 0.5; let shininess = 0.5;
Material { kd, ks, shininess } Arc::new(Material { kd, ks, shininess })
} }
pub fn turquoise() -> Self { pub fn turquoise() -> Arc<Self> {
let kd = Vector3::new(0.25, 0.3, 0.7); let kd = Vector3::new(0.25, 0.3, 0.7);
let ks = Vector3::new(0.25, 0.3, 0.7); let ks = Vector3::new(0.25, 0.3, 0.7);
let shininess = 0.5; let shininess = 0.5;
Material { kd, ks, shininess } Arc::new(Material { kd, ks, shininess })
} }
pub fn red() -> Self { pub fn red() -> Arc<Self> {
let kd = Vector3::new(0.8, 0.0, 0.3); let kd = Vector3::new(0.8, 0.0, 0.3);
let ks = Vector3::new(0.8, 0.3, 0.0); let ks = Vector3::new(0.8, 0.3, 0.0);
let shininess = 0.5; let shininess = 0.5;
Material { kd, ks, shininess } Arc::new(Material { kd, ks, shininess })
} }
pub fn blue() -> Self { pub fn blue() -> Arc<Self> {
let kd = Vector3::new(0.0, 0.3, 0.6); let kd = Vector3::new(0.0, 0.3, 0.6);
let ks = Vector3::new(0.3, 0.0, 0.6); let ks = Vector3::new(0.3, 0.0, 0.6);
let shininess = 0.5; let shininess = 0.5;
Material { kd, ks, shininess } Arc::new(Material { kd, ks, shininess })
} }
pub fn green() -> Self { pub fn green() -> Arc<Self> {
let kd = Vector3::new(0.0, 1.0, 0.0); let kd = Vector3::new(0.0, 1.0, 0.0);
let ks = Vector3::new(0.0, 1.0, 0.0); let ks = Vector3::new(0.0, 1.0, 0.0);
let shininess = 0.5; let shininess = 0.5;
Material { kd, ks, shininess } Arc::new(Material { kd, ks, shininess })
} }
} }
// INTERSECTION ----------------------------------------------------------------- // INTERSECTION -----------------------------------------------------------------
@@ -122,20 +122,20 @@ pub struct Sphere {
} }
impl Sphere { impl Sphere {
pub fn new(position: Point3<f32>, radius: f32, material: Arc<Material>) -> Self { pub fn new(position: Point3<f32>, radius: f32, material: Arc<Material>) -> Arc<dyn Primitive> {
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;
let bounding_box = BoundingBox::new(bln, trf); let bounding_box = BoundingBox::new(bln, trf);
Sphere { Arc::new(Sphere {
position, position,
radius, radius,
bounding_box, bounding_box,
material, material,
} })
} }
pub fn unit(material: Arc<Material>) -> Self { pub fn unit(material: Arc<Material>) -> Arc<dyn Primitive> {
Sphere::new(Point3::new(0.0, 0.0, 0.0), 1.0, material) Sphere::new(Point3::new(0.0, 0.0, 0.0), 1.0, material)
} }
} }
@@ -204,21 +204,21 @@ impl Circle {
radius: f32, radius: f32,
normal: Vector3<f32>, normal: Vector3<f32>,
material: Arc<Material>, material: Arc<Material>,
) -> Self { ) -> Arc<dyn Primitive> {
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;
let bounding_box = BoundingBox::new(bln, trf); let bounding_box = BoundingBox::new(bln, trf);
Circle { Arc::new(Circle {
position, position,
radius, radius,
normal: normal.normalize(), normal: normal.normalize(),
material, material,
bounding_box, bounding_box,
} })
} }
pub fn unit(material: Arc<Material>) -> Self { pub fn unit(material: Arc<Material>) -> Arc<dyn Primitive> {
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;
@@ -228,13 +228,13 @@ impl Circle {
let trf = Point3::new(radius, 0.0, EPSILON); let trf = Point3::new(radius, 0.0, EPSILON);
let bounding_box = BoundingBox { bln, trf }; let bounding_box = BoundingBox { bln, trf };
Circle { Arc::new(Circle {
position, position,
normal, normal,
radius, radius,
material, material,
bounding_box, bounding_box,
} })
} }
} }
@@ -303,13 +303,13 @@ pub struct Cone {
radius: f32, radius: f32,
base: f32, base: f32,
apex: f32, apex: f32,
circle: Circle, circle: Arc<dyn Primitive>,
material: Arc<Material>, material: Arc<Material>,
bounding_box: BoundingBox, bounding_box: BoundingBox,
} }
impl Cone { impl Cone {
pub fn new(radius: f32, apex: f32, base: f32, material: Arc<Material>) -> Self { pub fn new(radius: f32, apex: f32, base: f32, material: Arc<Material>) -> Arc<dyn Primitive> {
let circle = Circle::new( let circle = Circle::new(
Point3::new(0.0, base, 0.0), Point3::new(0.0, base, 0.0),
radius, radius,
@@ -318,16 +318,16 @@ impl Cone {
); );
let bln = Point3::new(-radius, base, -radius); let bln = Point3::new(-radius, base, -radius);
let trf = Point3::new(radius, base + apex, radius); let trf = Point3::new(radius, base + apex, radius);
Cone { Arc::new(Cone {
radius: radius / 2.0, radius: radius / 2.0,
base, base,
apex, apex,
circle, circle,
material, material,
bounding_box: BoundingBox { bln, trf }, bounding_box: BoundingBox { bln, trf },
})
} }
} pub fn unit(material: Arc<Material>) -> Arc<dyn Primitive> {
pub fn unit(material: Arc<Material>) -> Self {
Cone::new(1.0, 2.0, -1.0, material) Cone::new(1.0, 2.0, -1.0, material)
} }
@@ -431,13 +431,13 @@ impl Rectangle {
width: f32, width: f32,
height: f32, height: f32,
material: Arc<Material>, material: Arc<Material>,
) -> Self { ) -> Arc<dyn Primitive> {
let normal = normal.normalize(); let normal = normal.normalize();
let width_direction = width_direction.normalize(); let width_direction = width_direction.normalize();
let height_direction = width_direction.cross(&normal); let height_direction = width_direction.cross(&normal);
let bln = position - width / 2.0 * width_direction - height / 2.0 * height_direction; let bln = position - width / 2.0 * width_direction - height / 2.0 * height_direction;
let trf = position + width / 2.0 * width_direction + height / 2.0 * height_direction; let trf = position + width / 2.0 * width_direction + height / 2.0 * height_direction;
Rectangle { Arc::new(Rectangle {
position, position,
normal: normal.normalize(), normal: normal.normalize(),
width_direction: width_direction.normalize(), width_direction: width_direction.normalize(),
@@ -445,9 +445,9 @@ impl Rectangle {
height, height,
material, material,
bounding_box: BoundingBox { bln, trf }, bounding_box: BoundingBox { bln, trf },
})
} }
} pub fn unit(material: Arc<Material>) -> Arc<dyn Primitive> {
pub 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),
@@ -510,18 +510,18 @@ pub struct Cube {
} }
impl Cube { impl Cube {
fn new(width: f32, height: f32, depth: f32, material: Arc<Material>) -> Self { fn new(width: f32, height: f32, depth: f32, material: Arc<Material>) -> Arc<dyn Primitive> {
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);
Cube { Arc::new(Cube {
width, width,
height, height,
depth, depth,
material, material,
bounding_box: BoundingBox { bln, trf }, bounding_box: BoundingBox { bln, trf },
})
} }
} pub fn unit(material: Arc<Material>) -> Arc<dyn Primitive> {
pub fn unit(material: Arc<Material>) -> Self {
Cube::new(2.0, 2.0, 2.0, material) Cube::new(2.0, 2.0, 2.0, material)
} }
} }
@@ -599,23 +599,28 @@ struct Triangle {
} }
impl Triangle { impl Triangle {
fn new(u: Point3<f32>, v: Point3<f32>, w: Point3<f32>, material: Arc<Material>) -> Self { fn new(
u: Point3<f32>,
v: Point3<f32>,
w: Point3<f32>,
material: Arc<Material>,
) -> Arc<dyn Primitive> {
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();
let bln = u.inf(&v).inf(&w); let bln = u.inf(&v).inf(&w);
let trf = u.sup(&v).sup(&w); let trf = u.sup(&v).sup(&w);
let bounding_box = BoundingBox { bln, trf }; let bounding_box = BoundingBox { bln, trf };
Triangle { Arc::new(Triangle {
u, u,
v, v,
w, w,
normal, normal,
material, material,
bounding_box, bounding_box,
})
} }
} pub fn unit(material: Arc<Material>) -> Arc<dyn Primitive> {
pub 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);
@@ -675,24 +680,24 @@ impl Primitive for Triangle {
// MESH ----------------------------------------------------------------- // MESH -----------------------------------------------------------------
struct Mesh { struct Mesh {
triangles: Vec<Triangle>, triangles: Vec<Arc<Triangle>>,
material: Arc<Material>, material: Arc<Material>,
bounding_box: BoundingBox, bounding_box: BoundingBox,
} }
impl Mesh { impl Mesh {
fn new(triangles: Vec<Triangle>, material: Arc<Material>) -> Self { fn new(triangles: Vec<Arc<Triangle>>, material: Arc<Material>) -> Arc<dyn Primitive> {
// 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);
Mesh { Arc::new(Mesh {
triangles, triangles,
material, material,
bounding_box, bounding_box,
} })
} }
fn compute_bounding_box(triangles: &Vec<Triangle>) -> BoundingBox { fn compute_bounding_box(triangles: &Vec<Arc<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 {
@@ -707,8 +712,8 @@ impl Mesh {
BoundingBox { bln, trf } BoundingBox { bln, trf }
} }
fn from_file(filename: &str, material: Arc<Material>) -> Self { fn from_file(filename: &str, material: Arc<Material>) -> Arc<dyn Primitive> {
let mut triangles: Vec<Triangle> = Vec::new(); let mut triangles: Vec<Arc<dyn Primitive>> = Vec::new();
let mut vertices: Vec<Point3<f32>> = Vec::new(); let mut vertices: Vec<Point3<f32>> = Vec::new();
let file = File::open(filename).expect("Failed to open file"); let file = File::open(filename).expect("Failed to open file");

View File

@@ -2,9 +2,10 @@ use crate::{
light::Light, light::Light,
primitive::{Intersection, Primitive}, primitive::{Intersection, Primitive},
ray::Ray, ray::Ray,
scene::Scene, scene::*,
INFINITY, INFINITY,
}; };
use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
use nalgebra::{distance, Matrix4, Point3, Unit, Vector3, Vector4}; use nalgebra::{distance, Matrix4, Point3, Unit, Vector3, Vector4};
@@ -16,7 +17,7 @@ pub fn shade_rays(scene: &Scene, rays: &Vec<Ray>, width: i32, height: i32) -> Ve
let mut pixel_data = vec![Vector3::new(0, 0, 0); (width * height) as usize]; let mut pixel_data = vec![Vector3::new(0, 0, 0); (width * height) as usize];
for (pixel_index, ray) in rays.iter().enumerate() { for (pixel_index, ray) in rays.iter().enumerate() {
let intersect = get_closest_intersection(&scene.primitives, ray); let intersect = get_closest_intersection(&scene.nodes, ray);
let colour = match intersect { let colour = match intersect {
Some(intersect) => phong_shade_point(scene, &intersect), Some(intersect) => phong_shade_point(scene, &intersect),
None => { None => {
@@ -30,7 +31,7 @@ pub fn shade_rays(scene: &Scene, rays: &Vec<Ray>, width: i32, height: i32) -> Ve
} }
//Shade a single ray //Shade a single ray
pub fn shade_ray(scene: &Scene, ray: &Ray) -> Option<Vector3<u8>> { pub fn shade_ray(scene: &Scene, ray: &Ray) -> Option<Vector3<u8>> {
let intersect = get_closest_intersection(&scene.primitives, ray); let intersect = get_closest_intersection(&scene.nodes, ray);
match intersect { match intersect {
Some(intersect) => Some(phong_shade_point(&scene, &intersect)), Some(intersect) => Some(phong_shade_point(&scene, &intersect)),
None => None, None => None,
@@ -38,15 +39,12 @@ pub fn shade_ray(scene: &Scene, ray: &Ray) -> Option<Vector3<u8>> {
} }
// Find the closest intersection, given a ray in world coordinates // Find the closest intersection, given a ray in world coordinates
pub fn get_closest_intersection( pub fn get_closest_intersection(nodes: &Vec<Node>, ray: &Ray) -> Option<Intersection> {
primitives: &Vec<Box<dyn Primitive>>,
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 arc_primitive in primitives { for node in nodes {
let primitive = arc_primitive.clone(); let primitive = node.primitive.clone();
if let Some(intersect) = primitive.intersect_ray(ray) { if let Some(intersect) = primitive.intersect_ray(ray) {
if intersect.distance < closest_distance { if intersect.distance < closest_distance {
@@ -70,8 +68,7 @@ pub fn phong_shade_point(scene: &Scene, intersect: &Intersection) -> Vector3<u8>
material, material,
.. ..
} = intersect; } = intersect;
let binding = scene.ambient_light.clone(); let ambient_light = &scene.ambient_light;
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;
@@ -80,9 +77,7 @@ pub fn phong_shade_point(scene: &Scene, intersect: &Intersection) -> Vector3<u8>
// 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.as_ref() { for light in &scene.lights {
let light = arc_light.clone();
let Light { let Light {
position: light_position, position: light_position,
colour: light_colour, colour: light_colour,

View File

@@ -1,29 +1,129 @@
use crate::camera::Camera; use crate::camera::Camera;
use crate::light::Light; use crate::light::Light;
use crate::primitive::Primitive; use crate::primitive::Primitive;
use nalgebra::Vector3; use crate::primitive::*;
use nalgebra::{Matrix4, Point3, Vector3};
use rhai::{Engine, EvalAltResult};
use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
const LIGHT_AMBIENT: f32 = 0.2;
#[derive(Clone)]
pub struct Node {
pub primitive: Arc<dyn Primitive>,
pub model_transform: Matrix4<f32>,
}
impl Node {
pub fn new(primitive: Arc<dyn Primitive>) -> Self {
Node {
primitive,
model_transform: Matrix4::identity(),
}
}
pub fn rotate(&mut self, roll: f32, pitch: f32, yaw: f32) {
let roll = (roll as f64).to_radians() as f32;
let pitch = (pitch as f64).to_radians() as f32;
let yaw = (yaw as f64).to_radians() as f32;
let rotation_matrix = Matrix4::from_euler_angles(roll, pitch, yaw);
self.model_transform = rotation_matrix * self.model_transform;
}
pub fn translate(&mut self, translation: &Vector3<f32>) {
let translation_matrix = Matrix4::new_translation(translation);
self.model_transform = translation_matrix * self.model_transform;
}
pub fn scale(&mut self, scale: &Vector3<f32>) {
let scale_matrix = Matrix4::new_nonuniform_scaling(scale);
self.model_transform = scale_matrix * self.model_transform;
}
}
#[derive(Clone)]
pub struct Scene { pub struct Scene {
pub primitives: Arc<Vec<Box<dyn Primitive>>>, pub nodes: Vec<Node>,
pub lights: Arc<Vec<Light>>, pub materials: Vec<Material>,
pub cameras: Arc<Vec<Camera>>, pub lights: Vec<Light>,
pub ambient_light: Arc<Vector3<f32>>, pub cameras: Vec<Camera>,
pub ambient_light: Vector3<f32>,
pub camera: Camera,
} }
impl Scene { impl Scene {
// Creates a scene // Creates an emptry scene
pub fn new( pub fn empty() -> Self {
primitives: Vec<Box<dyn Primitive>>,
lights: Vec<Light>,
cameras: Vec<Camera>,
ambient_light: Vector3<f32>,
) -> Self {
Scene { Scene {
primitives: Arc::new(primitives), nodes: Vec::new(),
lights: Arc::new(lights), materials: Vec::new(),
cameras: Arc::new(cameras), lights: Vec::new(),
ambient_light: Arc::new(ambient_light), cameras: Vec::new(),
camera: Camera::new(
Point3::new(0.0, 0.0, -10.0),
Point3::new(0.0, 0.0, 0.0),
Vector3::new(0.0, 0.0, -1.0),
120.0,
1.0,
),
ambient_light: Vector3::new(LIGHT_AMBIENT, LIGHT_AMBIENT, LIGHT_AMBIENT),
} }
} }
fn add_node(&mut self, node: Node) {
self.nodes.push(node);
}
fn add_material(&mut self, material: Material) {
self.materials.push(material);
}
fn add_light(&mut self, light: Light) {
self.lights.push(light);
}
fn add_camera(&mut self, camera: Camera) {
self.cameras.push(camera);
}
fn set_ambient(&mut self, intensity: Vector3<f32>) {
self.ambient_light = intensity;
}
fn set_camera(&mut self, camera: Camera) {
self.camera = camera;
}
fn get_camera(&self) -> &Camera {
&self.camera
}
fn get_ambient(&self) -> Arc<Vector3<f32>> {
Arc::new(self.ambient_light)
}
pub fn init(filename: &str) -> Result<(), Box<EvalAltResult>> {
let mut engine = Engine::new();
engine
.register_type::<Vector3<f32>>()
.register_fn("V", Vector3::<f32>::new);
engine
.register_type::<Point3<f32>>()
.register_fn("P", Point3::<f32>::new);
engine
.register_type::<Scene>()
.register_fn("Scene", Scene::empty)
.register_fn("addNode", Scene::add_node);
engine
.register_type::<Node>()
.register_fn("Node", Node::new)
.register_fn("translate", Node::translate)
.register_fn("rotate", Node::rotate)
.register_fn("scale", Node::scale);
engine
.register_type::<Camera>()
.register_fn("Camera", Camera::new);
engine
.register_type::<Light>()
.register_fn("Light", Light::new);
engine
.register_type::<Material>()
.register_fn("Material", Material::new);
engine
.register_type::<Sphere>()
.register_fn("Sphere", Sphere::new);
engine.run_file(filename.into())?;
Ok(())
}
} }