Skip to content

Commit

Permalink
feat: add scripting subsystem
Browse files Browse the repository at this point in the history
  • Loading branch information
alanjian85 committed Jul 19, 2024
1 parent 2fcc80f commit bcf5b19
Show file tree
Hide file tree
Showing 9 changed files with 149 additions and 55 deletions.
41 changes: 41 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ edition = "2021"
clap = { version = "4.5.8", features = ["derive"] }
image = "0.25.1"
indicatif = "0.17.8"
mlua = { version = "0.9.9", features = ["lua54"] }
nalgebra = "0.33.0"
palette = "0.7.6"
rand = "0.8.5"
6 changes: 6 additions & 0 deletions scripts/scene.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
camera.pos = {-2.0, 2.0, 1.0}
camera.center = {0.0, 0.0, -1.0}
camera.up = {0.0, 1.0, 0.0}
camera.fov = math.rad(20.0)
camera.focus_dist = 3.4
camera.lens_angle = math.rad(10.0)
2 changes: 1 addition & 1 deletion src/core.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
mod camera;
mod material;
pub mod primitive;
mod primitive;
mod ray;
mod scene;

Expand Down
12 changes: 7 additions & 5 deletions src/core/primitive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ pub struct RayIntersection {
pub material: Rc<dyn Material>,
}

pub fn flip_normal(dir: Vector3<f64>, normal: Vector3<f64>) -> (bool, Vector3<f64>) {
if dir.dot(&normal) < 0.0 {
(true, normal)
} else {
(false, -normal)
impl RayIntersection {
pub fn flip_normal(dir: Vector3<f64>, normal: Vector3<f64>) -> (bool, Vector3<f64>) {
if dir.dot(&normal) < 0.0 {
(true, normal)
} else {
(false, -normal)
}
}
}

Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ pub mod core;
pub mod materials;
pub mod math;
pub mod primitives;
pub mod scripting;
pub mod utils;
56 changes: 9 additions & 47 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
use clap::Parser;
use image::{Rgb, RgbImage};
use indicatif::ProgressBar;
use nalgebra::{Point2, Point3, Vector3};
use nalgebra::Point2;
use palette::{LinSrgb, Srgb};
use prisma::config::{Config, Size};
use prisma::core::{CameraBuilder, Ray, Scene};
use prisma::materials::{Dielectric, Lambertian, Metal};
use prisma::primitives::Sphere;
use prisma::core::{Ray, Scene};
use prisma::scripting::Scripting;
use rand::rngs::ThreadRng;
use std::rc::Rc;
use std::fs;

fn compute_ray_color(
config: &Config,
Expand Down Expand Up @@ -37,52 +36,15 @@ fn main() {
let config = Config::parse();
let Size { width, height } = config.size;

let script = fs::read_to_string("scripts/scene.lua").unwrap();

let scripting = Scripting::new().unwrap();
let (camera, scene) = scripting.load(&config, &script).unwrap();

let mut image = RgbImage::new(width, height);
let progress_bar = ProgressBar::new(height as u64);
let mut rng = rand::thread_rng();

let camera = CameraBuilder::new(width, height)
.pos(Point3::new(-2.0, 2.0, 1.0))
.center(Point3::new(0.0, 0.0, -1.0))
.up(Vector3::new(0.0, 1.0, 0.0))
.fov(20.0_f64.to_radians())
.focus_dist(3.4)
.lens_angle(10.0_f64.to_radians())
.build();
let mut scene = Scene::new();

let material_ground = Lambertian::new(LinSrgb::new(0.8, 0.8, 0.0));
let material_center = Lambertian::new(LinSrgb::new(0.1, 0.2, 0.5));
let material_left = Dielectric::new(1.5);
let material_bubble = Dielectric::new(1.0 / 1.5);
let material_right = Metal::new(LinSrgb::new(0.8, 0.6, 0.2), 1.0);

scene.add(Box::new(Sphere::new(
Point3::new(0.0, -100.5, -1.0),
100.0,
Rc::new(material_ground),
)));
scene.add(Box::new(Sphere::new(
Point3::new(0.0, 0.0, -1.2),
0.5,
Rc::new(material_center),
)));
scene.add(Box::new(Sphere::new(
Point3::new(-1.0, 0.0, -1.0),
0.5,
Rc::new(material_left),
)));
scene.add(Box::new(Sphere::new(
Point3::new(-1.0, 0.0, -1.0),
0.4,
Rc::new(material_bubble),
)));
scene.add(Box::new(Sphere::new(
Point3::new(1.0, 0.0, -1.0),
0.5,
Rc::new(material_right),
)));

for y in 0..height {
for x in 0..width {
let mut color = LinSrgb::new(0.0, 0.0, 0.0);
Expand Down
4 changes: 2 additions & 2 deletions src/primitives/sphere.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::core::{primitive, Material, Primitive, Ray, RayIntersection};
use crate::core::{Material, Primitive, Ray, RayIntersection};
use nalgebra::Point3;
use std::ops::Range;
use std::rc::Rc;
Expand Down Expand Up @@ -40,7 +40,7 @@ impl Primitive for Sphere {

let pos = ray.at(t);
let normal = (pos - self.center) / self.radius;
let (front, normal) = primitive::flip_normal(ray.dir, normal);
let (front, normal) = RayIntersection::flip_normal(ray.dir, normal);
Some((
t,
RayIntersection {
Expand Down
81 changes: 81 additions & 0 deletions src/scripting.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
use crate::config::Config;
use crate::core::{Camera, CameraBuilder, Scene};
use crate::materials::{Dielectric, Lambertian, Metal};
use crate::primitives::Sphere;
use mlua::{prelude::*, Table};
use nalgebra::{Point3, Vector3};
use palette::LinSrgb;
use std::rc::Rc;

pub struct Scripting {
lua: Lua,
}

impl Scripting {
pub fn new() -> LuaResult<Self> {
let lua = Lua::new();

let camera = lua.create_table()?;
lua.globals().set("camera", camera)?;

Ok(Self { lua })
}

pub fn load(&self, config: &Config, script: &String) -> LuaResult<(Camera, Scene)> {
self.lua.load(script).exec()?;

let camera: Table = self.lua.globals().get("camera")?;
let camera = CameraBuilder::new(config.size.width, config.size.height)
.pos(table_to_point3(&camera.get("pos")?)?)
.center(table_to_point3(&camera.get("center")?)?)
.up(table_to_vector3(&camera.get("up")?)?)
.fov(camera.get("fov")?)
.focus_dist(camera.get("focus_dist")?)
.lens_angle(camera.get("lens_angle")?)
.build();

let mut scene = Scene::new();

let material_ground = Lambertian::new(LinSrgb::new(0.8, 0.8, 0.0));
let material_center = Lambertian::new(LinSrgb::new(0.1, 0.2, 0.5));
let material_left = Dielectric::new(1.5);
let material_bubble = Dielectric::new(1.0 / 1.5);
let material_right = Metal::new(LinSrgb::new(0.8, 0.6, 0.2), 1.0);

scene.add(Box::new(Sphere::new(
Point3::new(0.0, -100.5, -1.0),
100.0,
Rc::new(material_ground),
)));
scene.add(Box::new(Sphere::new(
Point3::new(0.0, 0.0, -1.2),
0.5,
Rc::new(material_center),
)));
scene.add(Box::new(Sphere::new(
Point3::new(-1.0, 0.0, -1.0),
0.5,
Rc::new(material_left),
)));
scene.add(Box::new(Sphere::new(
Point3::new(-1.0, 0.0, -1.0),
0.4,
Rc::new(material_bubble),
)));
scene.add(Box::new(Sphere::new(
Point3::new(1.0, 0.0, -1.0),
0.5,
Rc::new(material_right),
)));

Ok((camera, scene))
}
}

fn table_to_point3(table: &Table) -> LuaResult<Point3<f64>> {
Ok(Point3::new(table.get(1)?, table.get(2)?, table.get(3)?))
}

fn table_to_vector3(table: &Table) -> LuaResult<Vector3<f64>> {
Ok(Vector3::new(table.get(1)?, table.get(2)?, table.get(3)?))
}

0 comments on commit bcf5b19

Please sign in to comment.