Working scripting
This commit is contained in:
@@ -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"]}
|
||||||
|
|||||||
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);
|
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);
|
||||||
|
|||||||
@@ -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>) -> Self {
|
pub fn unit(material: Arc<Material>) -> Arc<dyn Primitive> {
|
||||||
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>) -> Self {
|
pub fn unit(material: Arc<Material>) -> Arc<dyn Primitive> {
|
||||||
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>) -> Self {
|
pub fn unit(material: Arc<Material>) -> Arc<dyn Primitive> {
|
||||||
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>) -> Self {
|
pub fn unit(material: Arc<Material>) -> Arc<dyn Primitive> {
|
||||||
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");
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
132
src/scene.rs
132
src/scene.rs
@@ -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(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user