Compare commits
3 Commits
fc40e0b798
...
5ffc390d2c
| Author | SHA1 | Date | |
|---|---|---|---|
|
5ffc390d2c
|
|||
|
48d4039c31
|
|||
|
3cb3e4a8fa
|
@@ -1,5 +1,5 @@
|
|||||||
use super::{expression::Expression, prelude::mk_prelude};
|
use super::{expression::Expression, prelude::mk_prelude};
|
||||||
use std::{cell::RefCell, collections::HashMap, rc::Rc};
|
use std::{cell::RefCell, collections::HashMap, env, path::Path, rc::Rc};
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Debug)]
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
/// A Environment is a stack of `EnvironmentLayer`s. Each `EnvironmentLayer` is a mapping from
|
/// A Environment is a stack of `EnvironmentLayer`s. Each `EnvironmentLayer` is a mapping from
|
||||||
|
|||||||
@@ -19,6 +19,12 @@ pub enum EvalError {
|
|||||||
ParserError(ParserError),
|
ParserError(ParserError),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<ParserError> for EvalError {
|
||||||
|
fn from(value: ParserError) -> Self {
|
||||||
|
EvalError::ParserError(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Display for EvalError {
|
impl Display for EvalError {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
|||||||
@@ -361,7 +361,7 @@ impl Display for Expression {
|
|||||||
Expression::Symbol(s) => write!(f, "{}", s),
|
Expression::Symbol(s) => write!(f, "{}", s),
|
||||||
Expression::Integer(i) => write!(f, "{}", i),
|
Expression::Integer(i) => write!(f, "{}", i),
|
||||||
Expression::Float(fl) => write!(f, "{}", fl),
|
Expression::Float(fl) => write!(f, "{}", fl),
|
||||||
Expression::String(s) => write!(f, "{}", s),
|
Expression::String(s) => write!(f, "\"{}\"", s),
|
||||||
Expression::True => write!(f, "true"),
|
Expression::True => write!(f, "true"),
|
||||||
Expression::Nil => write!(f, "nil"),
|
Expression::Nil => write!(f, "nil"),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
use crate::parser::ExpressionStream;
|
||||||
|
use crate::parser::ParserError;
|
||||||
|
|
||||||
use super::environment::Environment;
|
use super::environment::Environment;
|
||||||
use super::environment::EnvironmentLayer;
|
use super::environment::EnvironmentLayer;
|
||||||
use super::eval::eval;
|
use super::eval::eval;
|
||||||
@@ -5,6 +8,7 @@ use super::eval::CellIterator;
|
|||||||
use super::eval::EvalError;
|
use super::eval::EvalError;
|
||||||
use super::expression::Expression;
|
use super::expression::Expression;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
pub fn prelude_add(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
|
pub fn prelude_add(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
|
||||||
let [a, b] = expr.try_into()?;
|
let [a, b] = expr.try_into()?;
|
||||||
@@ -325,6 +329,54 @@ pub fn prelude_to_string(env: &Environment, expr: Expression) -> Result<Expressi
|
|||||||
Ok(Expression::String(format!("{}", eval(env, e)?)))
|
Ok(Expression::String(format!("{}", eval(env, e)?)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn prelude_load(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
|
||||||
|
let [expr] = expr.try_into()?;
|
||||||
|
let lisp_string: String = eval(env, expr)?.try_into()?;
|
||||||
|
|
||||||
|
let mut last_result = Expression::Nil;
|
||||||
|
|
||||||
|
for expr in ExpressionStream::from_char_stream(lisp_string.chars())
|
||||||
|
.collect::<Result<Vec<Expression>, ParserError>>()?
|
||||||
|
{
|
||||||
|
last_result = eval(env, expr)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(last_result)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn prelude_include(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
|
||||||
|
let [expr] = expr.try_into()?;
|
||||||
|
let lisp_file: String = eval(env, expr)?.try_into()?;
|
||||||
|
|
||||||
|
// Try to resolve as relative to FILE
|
||||||
|
let resolved_lisp_file: PathBuf = PathBuf::from(
|
||||||
|
env.get("FILE")
|
||||||
|
.map(|x| x.try_into())
|
||||||
|
.unwrap_or(Ok(String::new()))?,
|
||||||
|
)
|
||||||
|
.parent()
|
||||||
|
.ok_or(EvalError::RuntimeError(
|
||||||
|
"Could not get parent of current file.".to_string(),
|
||||||
|
))?
|
||||||
|
.join(&lisp_file);
|
||||||
|
|
||||||
|
let lisp_string = std::fs::read_to_string(&resolved_lisp_file)
|
||||||
|
.map_err(|e| EvalError::RuntimeError(e.to_string()))?;
|
||||||
|
|
||||||
|
// Use enviroment for resolved file or fallback to the lisp_file argument
|
||||||
|
let mut env = env.mk_inner();
|
||||||
|
env.set(
|
||||||
|
"FILE".to_string(),
|
||||||
|
resolved_lisp_file
|
||||||
|
.to_str()
|
||||||
|
.unwrap_or(&lisp_file)
|
||||||
|
.to_string()
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
|
||||||
|
prelude_load(&env, [lisp_string.into()].into())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn mk_prelude(layer: &mut EnvironmentLayer) {
|
pub fn mk_prelude(layer: &mut EnvironmentLayer) {
|
||||||
layer.set("+".to_string(), Expression::Function(prelude_add));
|
layer.set("+".to_string(), Expression::Function(prelude_add));
|
||||||
layer.set("-".to_string(), Expression::Function(prelude_sub));
|
layer.set("-".to_string(), Expression::Function(prelude_sub));
|
||||||
@@ -355,4 +407,6 @@ pub fn mk_prelude(layer: &mut EnvironmentLayer) {
|
|||||||
"to-string".to_string(),
|
"to-string".to_string(),
|
||||||
Expression::Function(prelude_to_string),
|
Expression::Function(prelude_to_string),
|
||||||
);
|
);
|
||||||
|
layer.set("load".to_string(), Expression::Function(prelude_load));
|
||||||
|
layer.set("include".to_string(), Expression::Function(prelude_include));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,33 +1,4 @@
|
|||||||
(set 'red
|
(include "./materials.lisp")
|
||||||
(material
|
|
||||||
(color 1 0 0)
|
|
||||||
(color 1 0 0)
|
|
||||||
(color 0.5 0 0)
|
|
||||||
50 0.25))
|
|
||||||
(set 'blue
|
|
||||||
(material
|
|
||||||
(color 0 0 1)
|
|
||||||
(color 0 0 1)
|
|
||||||
(color 0 0 0.6)
|
|
||||||
50 0.25))
|
|
||||||
(set 'green
|
|
||||||
(material
|
|
||||||
(color 0 1 0)
|
|
||||||
(color 0 1 0)
|
|
||||||
(color 0 0.6 0)
|
|
||||||
50 0.25))
|
|
||||||
(set 'white
|
|
||||||
(material
|
|
||||||
(color 1 1 1)
|
|
||||||
(color 1 1 1)
|
|
||||||
(color 0.6 0.6 0.6)
|
|
||||||
100 0.5))
|
|
||||||
(set 'black
|
|
||||||
(material
|
|
||||||
(color 0 0 0)
|
|
||||||
(color 0 0 0)
|
|
||||||
(color 0.6 0.6 0.6)
|
|
||||||
100 0.5))
|
|
||||||
|
|
||||||
(set 's1
|
(set 's1
|
||||||
(sphere
|
(sphere
|
||||||
@@ -36,22 +7,26 @@
|
|||||||
(sphere
|
(sphere
|
||||||
(point 2 0.5 2) 0.5 green))
|
(point 2 0.5 2) 0.5 green))
|
||||||
|
|
||||||
(defun spiral-sphere (i n)
|
(set 'mirror-dome
|
||||||
|
(sphere
|
||||||
|
(point 0 -30 0)
|
||||||
|
100 dark-mirror))
|
||||||
|
|
||||||
|
(defun spiral-sphere (i n t)
|
||||||
(sphere
|
(sphere
|
||||||
(progn
|
(progn
|
||||||
(print "Spiral Sphere at: ")
|
(point
|
||||||
(println (point
|
(* 2 (cos (/ (* i 6.2) n)))
|
||||||
(* 2 (cos (/ (* i 6.2) n)))
|
(+ 0.5 (* 0.3 (cos (+ (/ (* i 6.2) n) (/ t 5.0)))))
|
||||||
0.5
|
(* 2 (sin (/ (* i 6.2) n))))
|
||||||
(* 2 (sin (/ (* i 6.2) n)))))
|
|
||||||
)
|
)
|
||||||
0.5 red))
|
0.2 red))
|
||||||
|
|
||||||
(defun spiral (scn i n)
|
(defun spiral (scn i n t)
|
||||||
(if (< i n)
|
(if (< i n)
|
||||||
(scene-add
|
(scene-add
|
||||||
(spiral scn (+ i 1) n)
|
(spiral scn (+ i 1) n t)
|
||||||
(spiral-sphere i n))
|
(spiral-sphere i n t))
|
||||||
scn))
|
scn))
|
||||||
|
|
||||||
(set 'p1
|
(set 'p1
|
||||||
@@ -67,22 +42,20 @@
|
|||||||
|
|
||||||
(set 'scn-base (scene
|
(set 'scn-base (scene
|
||||||
(color 0.1 0.1 0.1)
|
(color 0.1 0.1 0.1)
|
||||||
'(s1 s2 p1)
|
'(s1 s2 p1 mirror-dome)
|
||||||
'(l1 l2)))
|
'(l1 l2)))
|
||||||
|
|
||||||
(set 'scn (spiral scn-base 0 10))
|
|
||||||
|
|
||||||
(set 'cam (camera (point 0 3 6) (point 0 0 0) (vector 0 1 0) 40 1920 1080))
|
(set 'cam (camera (point 0 3 6) (point 0 0 0) (vector 0 1 0) 40 1920 1080))
|
||||||
|
|
||||||
(defun scene-fn (t)
|
(defun scene-fn (t)
|
||||||
scn)
|
(spiral scn-base 0 30 t))
|
||||||
|
|
||||||
(defun cam-fn (t c)
|
(defun cam-fn (t c)
|
||||||
(let '((pos . (point 0 4 8))
|
(let '((pos . (point -3 0.5 8))
|
||||||
(cnt . (point 0 0 0))
|
(cnt . (point 0 0 0))
|
||||||
(to . (point -2 3 -6))
|
(to . (point -3 0.5 -8))
|
||||||
(up . (vector 0 1 0))
|
(up . (vector 0 1 0))
|
||||||
(fovy . 40)
|
(fovy . 80)
|
||||||
(pct . (/ t 300.0)))
|
(pct . (/ t 300.0)))
|
||||||
(let '((tpos . (vadd pos (vmul (vsub to pos) pct)))
|
(let '((tpos . (vadd pos (vmul (vsub to pos) pct)))
|
||||||
(tfovy . (+ fovy (* 40 pct)))
|
(tfovy . (+ fovy (* 40 pct)))
|
||||||
@@ -91,4 +64,4 @@
|
|||||||
)
|
)
|
||||||
))
|
))
|
||||||
|
|
||||||
(render-animation cam "demo-animation-2.mp4" scene-fn cam-fn 300 30 4 2)
|
(render-animation cam "demo-animation.mp4" scene-fn cam-fn 400 30 4 2)
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ fn main() {
|
|||||||
"(defun do-n-times (f n) (if (= n 0) '() (cons (f) (do-n-times f (- n 1)))))",
|
"(defun do-n-times (f n) (if (= n 0) '() (cons (f) (do-n-times f (- n 1)))))",
|
||||||
"(do-n-times (lambda () (print 'hello)) 5)",
|
"(do-n-times (lambda () (print 'hello)) 5)",
|
||||||
"(progn (print 'hello) (print 'world))",
|
"(progn (print 'hello) (print 'world))",
|
||||||
|
"(load \"(defun loaded-foo (x) (+ x 1))\")",
|
||||||
|
"(loaded-foo 1)",
|
||||||
];
|
];
|
||||||
|
|
||||||
let environment = Environment::default();
|
let environment = Environment::default();
|
||||||
|
|||||||
@@ -17,20 +17,27 @@ fn main() {
|
|||||||
mk_prelude(&mut layer);
|
mk_prelude(&mut layer);
|
||||||
mk_raytrace(&mut layer);
|
mk_raytrace(&mut layer);
|
||||||
|
|
||||||
let environment = Environment::from_layer(layer);
|
let mut environment = Environment::from_layer(layer);
|
||||||
|
|
||||||
for (i, r) in
|
for (program, path) in programs.iter().zip(program_paths) {
|
||||||
ExpressionStream::from_char_stream(programs.iter().map(|p| p.chars()).flatten()).enumerate()
|
environment.set("FILE".to_string(), path.clone().into());
|
||||||
{
|
|
||||||
match r {
|
for (i, r) in ExpressionStream::from_char_stream(program.chars()).enumerate() {
|
||||||
Err(err) => {
|
match r {
|
||||||
println!("ParserError in Expression {}: {:?}", i + 1, err);
|
Err(err) => {
|
||||||
break;
|
println!(
|
||||||
|
"ParserError in File {} Expression {}: {:?}",
|
||||||
|
path,
|
||||||
|
i + 1,
|
||||||
|
err
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Ok(expr) => match eval(&environment, expr) {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(e) => println!("Error evaluating Expression {}: {}", i + 1, e),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
Ok(expr) => match eval(&environment, expr) {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(e) => println!("Error evaluating Expression {}: {}", i + 1, e),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use nalgebra::distance;
|
||||||
|
|
||||||
use super::types::{Intersect, Material, Point3, Ray, Scalar, Vector3};
|
use super::types::{Intersect, Material, Point3, Ray, Scalar, Vector3};
|
||||||
|
|
||||||
extern crate nalgebra as na;
|
extern crate nalgebra as na;
|
||||||
@@ -52,12 +54,21 @@ impl Intersect for Sphere {
|
|||||||
if t < Scalar::MAX {
|
if t < Scalar::MAX {
|
||||||
let isect_pt: Point3 = ray.origin + ray.direction * t;
|
let isect_pt: Point3 = ray.origin + ray.direction * t;
|
||||||
|
|
||||||
return Some((
|
if c >= 0.0 {
|
||||||
isect_pt,
|
return Some((
|
||||||
(isect_pt - self.center) / self.radius,
|
isect_pt,
|
||||||
t,
|
(isect_pt - self.center) / self.radius,
|
||||||
self.material.clone(),
|
t,
|
||||||
));
|
self.material.clone(),
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
return Some((
|
||||||
|
isect_pt,
|
||||||
|
-(isect_pt - self.center) / self.radius,
|
||||||
|
t,
|
||||||
|
self.material.clone(),
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user