Working scripting
This commit is contained in:
114
src/main.rs
114
src/main.rs
@@ -39,20 +39,19 @@ const EPSILON_VECTOR: Vector3<f32> = Vector3::new(EPSILON, EPSILON, EPSILON);
|
||||
const INFINITY_VECTOR: Vector3<f32> = Vector3::new(INFINITY, INFINITY, INFINITY);
|
||||
|
||||
struct State {
|
||||
scene: Arc<Scene>,
|
||||
scene: Scene,
|
||||
window: Window,
|
||||
pixels: Arc<Mutex<Pixels>>,
|
||||
gui: Gui,
|
||||
|
||||
index: usize,
|
||||
|
||||
camera: Camera,
|
||||
rays: Arc<Vec<Ray>>,
|
||||
}
|
||||
|
||||
impl State {
|
||||
/// 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 pixels = {
|
||||
let surface_texture =
|
||||
@@ -65,14 +64,15 @@ impl State {
|
||||
.unwrap()
|
||||
};
|
||||
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 {
|
||||
scene: Arc::new(scene),
|
||||
scene,
|
||||
window,
|
||||
pixels: Arc::new(Mutex::new(pixels)),
|
||||
gui,
|
||||
|
||||
camera,
|
||||
index: 0,
|
||||
rays: Arc::new(rays),
|
||||
}
|
||||
@@ -92,8 +92,8 @@ impl State {
|
||||
return false;
|
||||
}
|
||||
self.index = 0;
|
||||
self.camera.set_position(self.gui.camera_eye);
|
||||
self.rays = Arc::new(self.camera.cast_rays(width_new, height_new));
|
||||
self.scene.camera.set_position(self.gui.camera_eye);
|
||||
self.rays = Arc::new(self.scene.camera.cast_rays(width_new, height_new));
|
||||
}
|
||||
true
|
||||
}
|
||||
@@ -201,55 +201,57 @@ impl State {
|
||||
fn main() -> Result<(), Error> {
|
||||
env_logger::init();
|
||||
env::set_var("RUST_BACKTRACE", "1");
|
||||
Scene::init("test.rhai").expect("Could not read lua file");
|
||||
|
||||
//Window
|
||||
let event_loop = EventLoop::new();
|
||||
//SCENE
|
||||
//Camera
|
||||
let eye = Point3::new(10.0, 0.0, 10.0);
|
||||
let target = Point3::new(0.0, 0.0, 0.0);
|
||||
let up = Vector3::new(0.0, 1.0, 0.0);
|
||||
let camera = Camera::new(
|
||||
eye,
|
||||
target,
|
||||
up,
|
||||
90.0,
|
||||
(START_WIDTH as f32 / START_HEIGHT as f32) as f32,
|
||||
);
|
||||
// SETUP MATERIALS
|
||||
let magenta = Arc::new(Material::magenta());
|
||||
let blue = Arc::new(Material::blue());
|
||||
let turquoise = Arc::new(Material::turquoise());
|
||||
let red = Arc::new(Material::red());
|
||||
// SETUP PRIMITIVES
|
||||
let mut primitives: Vec<Box<dyn Primitive>> = Vec::new();
|
||||
//let cube = Box::new(Cube::unit(turquoise.clone()));
|
||||
// primitives.push(cube);
|
||||
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 cone = Box::new(Cone::new(1.0, 1.0, -1.0, magenta.clone()));
|
||||
primitives.push(sphere);
|
||||
primitives.push(sphere2);
|
||||
primitives.push(cone);
|
||||
|
||||
// SETUP LIGHTS
|
||||
let light_pos = Point3::new(0.0, 12.0, 4.0);
|
||||
let light_colour = Vector3::new(0.4, 0.4, 0.6);
|
||||
let light_falloff = [1.0, 0.00, 0.00];
|
||||
let light = Light::new(light_colour, light_pos, light_falloff);
|
||||
|
||||
let light_pos2 = Point3::new(10.0, 12.0, -4.0);
|
||||
let light_colour2 = Vector3::new(0.4, 0.0, 0.6);
|
||||
let light_falloff2 = [1.0, 0.00, 0.00];
|
||||
let light2 = Light::new(light_colour2, light_pos2, light_falloff2);
|
||||
|
||||
let ambient_light = Vector3::new(0.0, 0.0, 0.2);
|
||||
|
||||
let scene = Scene::new(
|
||||
primitives,
|
||||
vec![light, light2],
|
||||
vec![camera.clone()],
|
||||
ambient_light,
|
||||
);
|
||||
// //Camera
|
||||
// let eye = Point3::new(10.0, 0.0, 10.0);
|
||||
// let target = Point3::new(0.0, 0.0, 0.0);
|
||||
// let up = Vector3::new(0.0, 1.0, 0.0);
|
||||
// let camera = Camera::new(
|
||||
// eye,
|
||||
// target,
|
||||
// up,
|
||||
// 90.0,
|
||||
// (START_WIDTH as f32 / START_HEIGHT as f32) as f32,
|
||||
// );
|
||||
// // SETUP MATERIALS
|
||||
// let magenta = Arc::new(Material::magenta());
|
||||
// let blue = Arc::new(Material::blue());
|
||||
// let turquoise = Arc::new(Material::turquoise());
|
||||
// let red = Arc::new(Material::red());
|
||||
// // SETUP PRIMITIVES
|
||||
// let mut primitives: Vec<Box<dyn Primitive>> = Vec::new();
|
||||
// //let cube = Box::new(Cube::unit(turquoise.clone()));
|
||||
// // primitives.push(cube);
|
||||
// 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 cone = Box::new(Cone::new(1.0, 1.0, -1.0, magenta.clone()));
|
||||
// primitives.push(sphere);
|
||||
// primitives.push(sphere2);
|
||||
// primitives.push(cone);
|
||||
//
|
||||
// // SETUP LIGHTS
|
||||
// let light_pos = Point3::new(0.0, 12.0, 4.0);
|
||||
// let light_colour = Vector3::new(0.4, 0.4, 0.6);
|
||||
// let light_falloff = [1.0, 0.00, 0.00];
|
||||
// let light = Light::new(light_colour, light_pos, light_falloff);
|
||||
//
|
||||
// let light_pos2 = Point3::new(10.0, 12.0, -4.0);
|
||||
// let light_colour2 = Vector3::new(0.4, 0.0, 0.6);
|
||||
// let light_falloff2 = [1.0, 0.00, 0.00];
|
||||
// let light2 = Light::new(light_colour2, light_pos2, light_falloff2);
|
||||
//
|
||||
// let ambient_light = Vector3::new(0.0, 0.0, 0.2);
|
||||
//
|
||||
// let scene = Scene::new(
|
||||
// primitives,
|
||||
// vec![light, light2],
|
||||
// vec![camera.clone()],
|
||||
// ambient_light,
|
||||
// );
|
||||
//State
|
||||
let window = {
|
||||
let size = LogicalSize::new(START_WIDTH, START_HEIGHT);
|
||||
@@ -260,7 +262,8 @@ fn main() -> Result<(), Error> {
|
||||
.build(&event_loop)
|
||||
.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| {
|
||||
// Draw the current frame
|
||||
@@ -269,6 +272,7 @@ fn main() -> Result<(), Error> {
|
||||
Event::WindowEvent { event, .. } => match event {
|
||||
WindowEvent::CloseRequested => {
|
||||
*control_flow = ControlFlow::Exit;
|
||||
return;
|
||||
}
|
||||
WindowEvent::Resized(size) => {
|
||||
state.resize(&size);
|
||||
|
||||
@@ -15,38 +15,38 @@ pub struct Material {
|
||||
pub shininess: f32,
|
||||
}
|
||||
impl Material {
|
||||
pub fn new(kd: Vector3<f32>, ks: Vector3<f32>, shininess: f32) -> Self {
|
||||
Material { kd, ks, shininess }
|
||||
pub fn new(kd: Vector3<f32>, ks: Vector3<f32>, shininess: f32) -> Arc<Self> {
|
||||
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 ks = Vector3::new(1.0, 0.0, 1.0);
|
||||
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 ks = Vector3::new(0.25, 0.3, 0.7);
|
||||
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 ks = Vector3::new(0.8, 0.3, 0.0);
|
||||
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 ks = Vector3::new(0.3, 0.0, 0.6);
|
||||
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 ks = Vector3::new(0.0, 1.0, 0.0);
|
||||
let shininess = 0.5;
|
||||
Material { kd, ks, shininess }
|
||||
Arc::new(Material { kd, ks, shininess })
|
||||
}
|
||||
}
|
||||
// INTERSECTION -----------------------------------------------------------------
|
||||
@@ -122,20 +122,20 @@ pub struct 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 bln = position - radius_vec;
|
||||
let trf = position + radius_vec;
|
||||
let bounding_box = BoundingBox::new(bln, trf);
|
||||
Sphere {
|
||||
Arc::new(Sphere {
|
||||
position,
|
||||
radius,
|
||||
bounding_box,
|
||||
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)
|
||||
}
|
||||
}
|
||||
@@ -204,21 +204,21 @@ impl Circle {
|
||||
radius: f32,
|
||||
normal: Vector3<f32>,
|
||||
material: Arc<Material>,
|
||||
) -> Self {
|
||||
) -> Arc<dyn Primitive> {
|
||||
let radius_vec = Vector3::new(radius, radius, radius);
|
||||
let bln = position - radius_vec;
|
||||
let trf = position + radius_vec;
|
||||
let bounding_box = BoundingBox::new(bln, trf);
|
||||
Circle {
|
||||
Arc::new(Circle {
|
||||
position,
|
||||
radius,
|
||||
normal: normal.normalize(),
|
||||
material,
|
||||
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 normal = Vector3::new(0.0, 1.0, 0.0);
|
||||
let radius = 1.0;
|
||||
@@ -228,13 +228,13 @@ impl Circle {
|
||||
let trf = Point3::new(radius, 0.0, EPSILON);
|
||||
let bounding_box = BoundingBox { bln, trf };
|
||||
|
||||
Circle {
|
||||
Arc::new(Circle {
|
||||
position,
|
||||
normal,
|
||||
radius,
|
||||
material,
|
||||
bounding_box,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,13 +303,13 @@ pub struct Cone {
|
||||
radius: f32,
|
||||
base: f32,
|
||||
apex: f32,
|
||||
circle: Circle,
|
||||
circle: Arc<dyn Primitive>,
|
||||
material: Arc<Material>,
|
||||
bounding_box: BoundingBox,
|
||||
}
|
||||
|
||||
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(
|
||||
Point3::new(0.0, base, 0.0),
|
||||
radius,
|
||||
@@ -318,16 +318,16 @@ impl Cone {
|
||||
);
|
||||
let bln = Point3::new(-radius, base, -radius);
|
||||
let trf = Point3::new(radius, base + apex, radius);
|
||||
Cone {
|
||||
Arc::new(Cone {
|
||||
radius: radius / 2.0,
|
||||
base,
|
||||
apex,
|
||||
circle,
|
||||
material,
|
||||
bounding_box: BoundingBox { bln, trf },
|
||||
}
|
||||
})
|
||||
}
|
||||
pub fn unit(material: Arc<Material>) -> Self {
|
||||
pub fn unit(material: Arc<Material>) -> Arc<dyn Primitive> {
|
||||
Cone::new(1.0, 2.0, -1.0, material)
|
||||
}
|
||||
|
||||
@@ -431,13 +431,13 @@ impl Rectangle {
|
||||
width: f32,
|
||||
height: f32,
|
||||
material: Arc<Material>,
|
||||
) -> Self {
|
||||
) -> Arc<dyn Primitive> {
|
||||
let normal = normal.normalize();
|
||||
let width_direction = width_direction.normalize();
|
||||
let height_direction = width_direction.cross(&normal);
|
||||
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;
|
||||
Rectangle {
|
||||
Arc::new(Rectangle {
|
||||
position,
|
||||
normal: normal.normalize(),
|
||||
width_direction: width_direction.normalize(),
|
||||
@@ -445,9 +445,9 @@ impl Rectangle {
|
||||
height,
|
||||
material,
|
||||
bounding_box: BoundingBox { bln, trf },
|
||||
}
|
||||
})
|
||||
}
|
||||
pub fn unit(material: Arc<Material>) -> Self {
|
||||
pub fn unit(material: Arc<Material>) -> Arc<dyn Primitive> {
|
||||
Rectangle::new(
|
||||
Point3::new(0.0, 0.0, 0.0),
|
||||
Vector3::new(0.0, 1.0, 0.0),
|
||||
@@ -510,18 +510,18 @@ pub struct 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 bln = Point3::new(-width / 2.0, -height / 2.0, -depth / 2.0);
|
||||
Cube {
|
||||
Arc::new(Cube {
|
||||
width,
|
||||
height,
|
||||
depth,
|
||||
material,
|
||||
bounding_box: BoundingBox { bln, trf },
|
||||
}
|
||||
})
|
||||
}
|
||||
pub fn unit(material: Arc<Material>) -> Self {
|
||||
pub fn unit(material: Arc<Material>) -> Arc<dyn Primitive> {
|
||||
Cube::new(2.0, 2.0, 2.0, material)
|
||||
}
|
||||
}
|
||||
@@ -599,23 +599,28 @@ struct 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 uw = w - u;
|
||||
let normal = uv.cross(&uw).normalize();
|
||||
let bln = u.inf(&v).inf(&w);
|
||||
let trf = u.sup(&v).sup(&w);
|
||||
let bounding_box = BoundingBox { bln, trf };
|
||||
Triangle {
|
||||
Arc::new(Triangle {
|
||||
u,
|
||||
v,
|
||||
w,
|
||||
normal,
|
||||
material,
|
||||
bounding_box,
|
||||
}
|
||||
})
|
||||
}
|
||||
pub fn unit(material: Arc<Material>) -> Self {
|
||||
pub fn unit(material: Arc<Material>) -> Arc<dyn Primitive> {
|
||||
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);
|
||||
@@ -675,24 +680,24 @@ impl Primitive for Triangle {
|
||||
|
||||
// MESH -----------------------------------------------------------------
|
||||
struct Mesh {
|
||||
triangles: Vec<Triangle>,
|
||||
triangles: Vec<Arc<Triangle>>,
|
||||
material: Arc<Material>,
|
||||
bounding_box: BoundingBox,
|
||||
}
|
||||
|
||||
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
|
||||
let bounding_box = Mesh::compute_bounding_box(&triangles);
|
||||
|
||||
Mesh {
|
||||
Arc::new(Mesh {
|
||||
triangles,
|
||||
material,
|
||||
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 trf = -bln;
|
||||
for triangle in triangles {
|
||||
@@ -707,8 +712,8 @@ impl Mesh {
|
||||
BoundingBox { bln, trf }
|
||||
}
|
||||
|
||||
fn from_file(filename: &str, material: Arc<Material>) -> Self {
|
||||
let mut triangles: Vec<Triangle> = Vec::new();
|
||||
fn from_file(filename: &str, material: Arc<Material>) -> Arc<dyn Primitive> {
|
||||
let mut triangles: Vec<Arc<dyn Primitive>> = Vec::new();
|
||||
let mut vertices: Vec<Point3<f32>> = Vec::new();
|
||||
|
||||
let file = File::open(filename).expect("Failed to open file");
|
||||
|
||||
@@ -2,9 +2,10 @@ use crate::{
|
||||
light::Light,
|
||||
primitive::{Intersection, Primitive},
|
||||
ray::Ray,
|
||||
scene::Scene,
|
||||
scene::*,
|
||||
INFINITY,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
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];
|
||||
|
||||
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 {
|
||||
Some(intersect) => phong_shade_point(scene, &intersect),
|
||||
None => {
|
||||
@@ -30,7 +31,7 @@ pub fn shade_rays(scene: &Scene, rays: &Vec<Ray>, width: i32, height: i32) -> Ve
|
||||
}
|
||||
//Shade a single ray
|
||||
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 {
|
||||
Some(intersect) => Some(phong_shade_point(&scene, &intersect)),
|
||||
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
|
||||
pub fn get_closest_intersection(
|
||||
primitives: &Vec<Box<dyn Primitive>>,
|
||||
ray: &Ray,
|
||||
) -> Option<Intersection> {
|
||||
pub fn get_closest_intersection(nodes: &Vec<Node>, ray: &Ray) -> Option<Intersection> {
|
||||
let mut closest_distance = INFINITY;
|
||||
let mut closest_intersect: Option<Intersection> = None;
|
||||
|
||||
for arc_primitive in primitives {
|
||||
let primitive = arc_primitive.clone();
|
||||
for node in nodes {
|
||||
let primitive = node.primitive.clone();
|
||||
|
||||
if let Some(intersect) = primitive.intersect_ray(ray) {
|
||||
if intersect.distance < closest_distance {
|
||||
@@ -70,8 +68,7 @@ pub fn phong_shade_point(scene: &Scene, intersect: &Intersection) -> Vector3<u8>
|
||||
material,
|
||||
..
|
||||
} = intersect;
|
||||
let binding = scene.ambient_light.clone();
|
||||
let ambient_light = binding.as_ref();
|
||||
let ambient_light = &scene.ambient_light;
|
||||
let kd = material.kd;
|
||||
let ks = material.ks;
|
||||
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 mut colour = kd.component_mul(ambient_light);
|
||||
|
||||
for arc_light in scene.lights.as_ref() {
|
||||
let light = arc_light.clone();
|
||||
|
||||
for light in &scene.lights {
|
||||
let Light {
|
||||
position: light_position,
|
||||
colour: light_colour,
|
||||
|
||||
132
src/scene.rs
132
src/scene.rs
@@ -1,29 +1,129 @@
|
||||
use crate::camera::Camera;
|
||||
use crate::light::Light;
|
||||
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;
|
||||
|
||||
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 primitives: Arc<Vec<Box<dyn Primitive>>>,
|
||||
pub lights: Arc<Vec<Light>>,
|
||||
pub cameras: Arc<Vec<Camera>>,
|
||||
pub ambient_light: Arc<Vector3<f32>>,
|
||||
pub nodes: Vec<Node>,
|
||||
pub materials: Vec<Material>,
|
||||
pub lights: Vec<Light>,
|
||||
pub cameras: Vec<Camera>,
|
||||
pub ambient_light: Vector3<f32>,
|
||||
pub camera: Camera,
|
||||
}
|
||||
|
||||
impl Scene {
|
||||
// Creates a scene
|
||||
pub fn new(
|
||||
primitives: Vec<Box<dyn Primitive>>,
|
||||
lights: Vec<Light>,
|
||||
cameras: Vec<Camera>,
|
||||
ambient_light: Vector3<f32>,
|
||||
) -> Self {
|
||||
// Creates an emptry scene
|
||||
pub fn empty() -> Self {
|
||||
Scene {
|
||||
primitives: Arc::new(primitives),
|
||||
lights: Arc::new(lights),
|
||||
cameras: Arc::new(cameras),
|
||||
ambient_light: Arc::new(ambient_light),
|
||||
nodes: Vec::new(),
|
||||
materials: Vec::new(),
|
||||
lights: Vec::new(),
|
||||
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(())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user