feat(lisp): add overloadable native functions
This commit is contained in:
parent
1856de7685
commit
ad0792dcd3
@ -21,16 +21,16 @@ impl syn::parse::Parse for FlagOrKV {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Attrs {
|
struct NativeLispAttrs {
|
||||||
pub eval: bool,
|
pub eval: bool,
|
||||||
pub fname: Option<Ident>,
|
pub fname: Option<Ident>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl syn::parse::Parse for Attrs {
|
impl syn::parse::Parse for NativeLispAttrs {
|
||||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||||
let exprs = Punctuated::<FlagOrKV, Token![,]>::parse_terminated(input)?;
|
let exprs = Punctuated::<FlagOrKV, Token![,]>::parse_terminated(input)?;
|
||||||
|
|
||||||
let mut ret = Attrs {
|
let mut ret = NativeLispAttrs {
|
||||||
eval: false,
|
eval: false,
|
||||||
fname: None,
|
fname: None,
|
||||||
};
|
};
|
||||||
@ -58,6 +58,47 @@ impl syn::parse::Parse for Attrs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct NativeLispProxyAttrs {
|
||||||
|
pub eval: bool,
|
||||||
|
pub fname: Ident,
|
||||||
|
pub dispatcher: Vec<Ident>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl syn::parse::Parse for NativeLispProxyAttrs {
|
||||||
|
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||||
|
let exprs = Punctuated::<FlagOrKV, Token![,]>::parse_terminated(input)?;
|
||||||
|
|
||||||
|
let mut ret = NativeLispProxyAttrs {
|
||||||
|
eval: false,
|
||||||
|
fname: Ident::new("proxy", proc_macro2::Span::call_site()),
|
||||||
|
dispatcher: Vec::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
for e in exprs {
|
||||||
|
match e {
|
||||||
|
FlagOrKV::Flag(flag) => {
|
||||||
|
if flag.to_string() == "eval" {
|
||||||
|
ret.eval = true;
|
||||||
|
} else {
|
||||||
|
return Err(syn::Error::new_spanned(flag, "Unknown flag"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FlagOrKV::KV(k, v) => {
|
||||||
|
if k.to_string() == "dispatch" {
|
||||||
|
ret.dispatcher.push(v);
|
||||||
|
} else if k.to_string() == "fname" {
|
||||||
|
ret.fname = v;
|
||||||
|
} else {
|
||||||
|
return Err(syn::Error::new_spanned(k, "Unknown key"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(ret)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn native_lisp_function(attr: TokenStream, item: TokenStream) -> TokenStream {
|
pub fn native_lisp_function(attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
// Parse function
|
// Parse function
|
||||||
@ -69,7 +110,7 @@ pub fn native_lisp_function(attr: TokenStream, item: TokenStream) -> TokenStream
|
|||||||
let ret = &sig.output;
|
let ret = &sig.output;
|
||||||
|
|
||||||
// Parse attrs
|
// Parse attrs
|
||||||
let attr = parse_macro_input!(attr as Attrs);
|
let attr = parse_macro_input!(attr as NativeLispAttrs);
|
||||||
|
|
||||||
// Extract argument conversion statements
|
// Extract argument conversion statements
|
||||||
let mut conversion_statements = Vec::new();
|
let mut conversion_statements = Vec::new();
|
||||||
@ -77,15 +118,14 @@ pub fn native_lisp_function(attr: TokenStream, item: TokenStream) -> TokenStream
|
|||||||
for arg in &sig.inputs {
|
for arg in &sig.inputs {
|
||||||
if let FnArg::Typed(PatType { pat, ty, .. }) = arg {
|
if let FnArg::Typed(PatType { pat, ty, .. }) = arg {
|
||||||
if let Pat::Ident(ident) = pat.as_ref() {
|
if let Pat::Ident(ident) = pat.as_ref() {
|
||||||
let arg_name = &ident.ident;
|
let arg_name_str = ident.ident.to_string();
|
||||||
let arg_name_str = arg_name.to_string();
|
|
||||||
if attr.eval {
|
if attr.eval {
|
||||||
conversion_statements.push(quote! {
|
conversion_statements.push(quote! {
|
||||||
let #arg_name: #ty = eval(env, args_iter.next().ok_or(EvalError::ArgumentError(format!("Missing Argument {}", #arg_name_str)))?)?.try_into()?;
|
let #ident: #ty = eval(env, args_iter.next().ok_or(EvalError::ArgumentError(format!("Missing Argument {}", #arg_name_str)))?)?.try_into()?;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
conversion_statements.push(quote! {
|
conversion_statements.push(quote! {
|
||||||
let #arg_name: #ty = args_iter.next().ok_or(EvalError::ArgumentError(format!("Missing Argument {}", #arg_name_str)))?.try_into()?;
|
let #ident: #ty = args_iter.next().ok_or(EvalError::ArgumentError(format!("Missing Argument {}", #arg_name_str)))?.try_into()?;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -97,7 +137,7 @@ pub fn native_lisp_function(attr: TokenStream, item: TokenStream) -> TokenStream
|
|||||||
None => func_name.clone(),
|
None => func_name.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let gen = quote! {
|
quote! {
|
||||||
#vis fn #func_name(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
|
#vis fn #func_name(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
|
||||||
let args: Vec<Expression> = expr.try_into()?;
|
let args: Vec<Expression> = expr.try_into()?;
|
||||||
let mut args_iter = args.into_iter();
|
let mut args_iter = args.into_iter();
|
||||||
@ -106,9 +146,47 @@ pub fn native_lisp_function(attr: TokenStream, item: TokenStream) -> TokenStream
|
|||||||
|
|
||||||
Ok((|| #ret #block)()?.into())
|
Ok((|| #ret #block)()?.into())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[proc_macro]
|
||||||
|
pub fn native_lisp_function_proxy(item: TokenStream) -> TokenStream {
|
||||||
|
let args = parse_macro_input!(item as NativeLispProxyAttrs);
|
||||||
|
let fname = &args.fname;
|
||||||
|
|
||||||
|
let eval_statement = if args.eval {
|
||||||
|
quote! {
|
||||||
|
let exprs: Vec<Expression> = expr.try_into()?;
|
||||||
|
let exprs = exprs.into_iter().map(|expr| eval(env, expr)).collect::<Result<Vec<Expression>, EvalError>>()?;
|
||||||
|
let expr: Expression = exprs.into();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {}
|
||||||
};
|
};
|
||||||
|
|
||||||
let out: TokenStream = gen.into();
|
let try_apply_statements = args
|
||||||
print!("{}", out);
|
.dispatcher
|
||||||
out
|
.iter()
|
||||||
|
.map(|impl_name| {
|
||||||
|
quote! {
|
||||||
|
match #impl_name(env, expr.clone()) {
|
||||||
|
Err(EvalError::ArgumentError(e)) => {/*Pass*/},
|
||||||
|
Err(EvalError::TypeError(e)) => {/*Pass*/},
|
||||||
|
x => return x,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
fn #fname(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
|
||||||
|
#eval_statement
|
||||||
|
|
||||||
|
#(#try_apply_statements)*
|
||||||
|
|
||||||
|
Err(EvalError::TypeError("No applicable method found".to_string()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,6 +7,9 @@ use lispers_core::parser::ExpressionStream;
|
|||||||
fn main() {
|
fn main() {
|
||||||
let programs = [
|
let programs = [
|
||||||
"(vadd (vector 1 2 3) (vector 4 5 6))",
|
"(vadd (vector 1 2 3) (vector 4 5 6))",
|
||||||
|
"(vadd (vector 1 2 3) (point 4 5 6))",
|
||||||
|
"(vadd (point 1 2 3) (vector 4 5 6))",
|
||||||
|
"(vadd (point 1 2 3) (point 4 5 6))",
|
||||||
"(set 'blue (material (color 0 0 1) (color 0 0 1) (color 0 0 0.6) 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 '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 'white (material (color 1 1 1) (color 1 1 1) (color 0.6 0.6 0.6) 100 0.5))",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use crate::raytracer::{scene::Scene, types::Light};
|
use crate::raytracer::{scene::Scene, types::Light};
|
||||||
|
|
||||||
use lispers_macro::native_lisp_function;
|
use lispers_macro::{native_lisp_function, native_lisp_function_proxy};
|
||||||
|
|
||||||
use lispers_core::lisp::{
|
use lispers_core::lisp::{
|
||||||
environment::EnvironmentLayer,
|
environment::EnvironmentLayer,
|
||||||
@ -16,110 +16,72 @@ use super::{
|
|||||||
types::{Color, Material, Point3, RTObjectWrapper, Vector3},
|
types::{Color, Material, Point3, RTObjectWrapper, Vector3},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn point(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
|
#[native_lisp_function(eval)]
|
||||||
let [x, y, z]: [Expression; 3] = expr.try_into()?;
|
pub fn point(x: f64, y: f64, z: f64) -> Result<ForeignDataWrapper<Point3>, EvalError> {
|
||||||
|
Ok(ForeignDataWrapper::new(Point3::new(x, y, z)))
|
||||||
let x: f64 = eval(env, x)?.try_into()?;
|
|
||||||
let y: f64 = eval(env, y)?.try_into()?;
|
|
||||||
let z: f64 = eval(env, z)?.try_into()?;
|
|
||||||
|
|
||||||
Ok(ForeignDataWrapper::new(Point3::new(x, y, z)).into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn vector(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
|
#[native_lisp_function(eval)]
|
||||||
let [x, y, z]: [Expression; 3] = expr.try_into()?;
|
pub fn vector(x: f64, y: f64, z: f64) -> Result<ForeignDataWrapper<Vector3>, EvalError> {
|
||||||
|
Ok(ForeignDataWrapper::new(Vector3::new(x, y, z)))
|
||||||
let x: f64 = eval(env, x)?.try_into()?;
|
|
||||||
let y: f64 = eval(env, y)?.try_into()?;
|
|
||||||
let z: f64 = eval(env, z)?.try_into()?;
|
|
||||||
|
|
||||||
Ok(ForeignDataWrapper::new(Vector3::new(x, y, z)).into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn color(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
|
#[native_lisp_function(eval)]
|
||||||
let [r, g, b]: [Expression; 3] = expr.try_into()?;
|
pub fn color(r: f64, g: f64, b: f64) -> Result<ForeignDataWrapper<Color>, EvalError> {
|
||||||
|
Ok(ForeignDataWrapper::new(Color::new(r, g, b)))
|
||||||
let r: f64 = eval(env, r)?.try_into()?;
|
|
||||||
let g: f64 = eval(env, g)?.try_into()?;
|
|
||||||
let b: f64 = eval(env, b)?.try_into()?;
|
|
||||||
|
|
||||||
Ok(ForeignDataWrapper::new(Color::new(r, g, b)).into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn light(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
|
#[native_lisp_function(eval)]
|
||||||
let [pos, col]: [Expression; 2] = expr.try_into()?;
|
pub fn light(
|
||||||
|
pos: ForeignDataWrapper<Point3>,
|
||||||
let pos: ForeignDataWrapper<Point3> = eval(env, pos)?.try_into()?;
|
col: ForeignDataWrapper<Color>,
|
||||||
let col: ForeignDataWrapper<Color> = eval(env, col)?.try_into()?;
|
) -> Result<ForeignDataWrapper<Light>, EvalError> {
|
||||||
|
Ok(ForeignDataWrapper::new(Light::new(*pos, *col)))
|
||||||
let pos: Point3 = *pos;
|
|
||||||
let col: Color = *col;
|
|
||||||
|
|
||||||
Ok(ForeignDataWrapper::new(Light::new(pos, col)).into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn material(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
|
#[native_lisp_function(eval)]
|
||||||
let [amb, dif, spe, shi, mir]: [Expression; 5] = expr.try_into()?;
|
pub fn material(
|
||||||
|
amb: ForeignDataWrapper<Color>,
|
||||||
let amb: ForeignDataWrapper<Color> = eval(env, amb)?.try_into()?;
|
dif: ForeignDataWrapper<Color>,
|
||||||
let dif: ForeignDataWrapper<Color> = eval(env, dif)?.try_into()?;
|
spe: ForeignDataWrapper<Color>,
|
||||||
let spe: ForeignDataWrapper<Color> = eval(env, spe)?.try_into()?;
|
shi: f64,
|
||||||
let shi: f64 = eval(env, shi)?.try_into()?;
|
mir: f64,
|
||||||
let mir: f64 = eval(env, mir)?.try_into()?;
|
) -> Result<ForeignDataWrapper<Material>, EvalError> {
|
||||||
|
Ok(ForeignDataWrapper::new(Material::new(
|
||||||
let amb: Color = *amb;
|
*amb, *dif, *spe, shi, mir,
|
||||||
let dif: Color = *dif;
|
)))
|
||||||
let spe: Color = *spe;
|
|
||||||
|
|
||||||
Ok(ForeignDataWrapper::new(Material::new(amb, dif, spe, shi, mir)).into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sphere(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
|
#[native_lisp_function(eval)]
|
||||||
let [pos, rad, mat]: [Expression; 3] = expr.try_into()?;
|
pub fn sphere(
|
||||||
|
pos: ForeignDataWrapper<Point3>,
|
||||||
let pos: ForeignDataWrapper<Point3> = eval(env, pos)?.try_into()?;
|
rad: f64,
|
||||||
let rad: f64 = eval(env, rad)?.try_into()?;
|
mat: ForeignDataWrapper<Material>,
|
||||||
let mat: ForeignDataWrapper<Material> = eval(env, mat)?.try_into()?;
|
) -> Result<ForeignDataWrapper<RTObjectWrapper>, EvalError> {
|
||||||
|
Ok(ForeignDataWrapper::new(RTObjectWrapper::from(Sphere::new(*pos, rad, *mat))).into())
|
||||||
let pos: Point3 = *pos;
|
|
||||||
let mat: Material = *mat;
|
|
||||||
|
|
||||||
Ok(ForeignDataWrapper::new(RTObjectWrapper::from(Sphere::new(pos, rad, mat))).into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn plane(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
|
#[native_lisp_function(eval)]
|
||||||
let [pos, dir, mat]: [Expression; 3] = expr.try_into()?;
|
pub fn plane(
|
||||||
|
pos: ForeignDataWrapper<Point3>,
|
||||||
let pos: ForeignDataWrapper<Point3> = eval(env, pos)?.try_into()?;
|
dir: ForeignDataWrapper<Vector3>,
|
||||||
let dir: ForeignDataWrapper<Vector3> = eval(env, dir)?.try_into()?;
|
mat: ForeignDataWrapper<Material>,
|
||||||
let mat: ForeignDataWrapper<Material> = eval(env, mat)?.try_into()?;
|
) -> Result<ForeignDataWrapper<RTObjectWrapper>, EvalError> {
|
||||||
|
Ok(ForeignDataWrapper::new(RTObjectWrapper::from(Plane::new(*pos, *dir, *mat))).into())
|
||||||
let pos: Point3 = *pos;
|
|
||||||
let dir: Vector3 = *dir;
|
|
||||||
let mat: Material = *mat;
|
|
||||||
|
|
||||||
Ok(ForeignDataWrapper::new(RTObjectWrapper::from(Plane::new(pos, dir, mat))).into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn checkerboard(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
|
#[native_lisp_function(eval)]
|
||||||
let [pos, norm, mat1, mat2, sca, up]: [Expression; 6] = expr.try_into()?;
|
pub fn checkerboard(
|
||||||
|
pos: ForeignDataWrapper<Point3>,
|
||||||
let pos: ForeignDataWrapper<Point3> = eval(env, pos)?.try_into()?;
|
norm: ForeignDataWrapper<Vector3>,
|
||||||
let norm: ForeignDataWrapper<Vector3> = eval(env, norm)?.try_into()?;
|
mat1: ForeignDataWrapper<Material>,
|
||||||
let mat1: ForeignDataWrapper<Material> = eval(env, mat1)?.try_into()?;
|
mat2: ForeignDataWrapper<Material>,
|
||||||
let mat2: ForeignDataWrapper<Material> = eval(env, mat2)?.try_into()?;
|
sca: f64,
|
||||||
let sca: f64 = eval(env, sca)?.try_into()?;
|
up: ForeignDataWrapper<Vector3>,
|
||||||
let up: ForeignDataWrapper<Vector3> = eval(env, up)?.try_into()?;
|
) -> Result<ForeignDataWrapper<RTObjectWrapper>, EvalError> {
|
||||||
|
|
||||||
let pos: Point3 = *pos;
|
|
||||||
let norm: Vector3 = *norm;
|
|
||||||
let mat1: Material = *mat1;
|
|
||||||
let mat2: Material = *mat2;
|
|
||||||
let up: Vector3 = *up;
|
|
||||||
|
|
||||||
Ok(
|
Ok(
|
||||||
ForeignDataWrapper::new(RTObjectWrapper::from(Checkerboard::new(
|
ForeignDataWrapper::new(RTObjectWrapper::from(Checkerboard::new(
|
||||||
pos, norm, mat1, mat2, sca, up,
|
*pos, *norm, *mat1, *mat2, sca, *up,
|
||||||
)))
|
)))
|
||||||
.into(),
|
.into(),
|
||||||
)
|
)
|
||||||
@ -147,50 +109,53 @@ pub fn scene(env: &Environment, expr: Expression) -> Result<Expression, EvalErro
|
|||||||
Ok(ForeignDataWrapper::new(scene).into())
|
Ok(ForeignDataWrapper::new(scene).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scene_add_object(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
|
#[native_lisp_function]
|
||||||
let [sce, obj]: [Expression; 2] = expr.try_into()?;
|
pub fn scene_add_object(
|
||||||
|
mut sce: ForeignDataWrapper<Scene>,
|
||||||
let mut sce: ForeignDataWrapper<Scene> = eval(env, sce)?.try_into()?;
|
obj: ForeignDataWrapper<RTObjectWrapper>,
|
||||||
let obj: ForeignDataWrapper<RTObjectWrapper> = eval(env, obj)?.try_into()?;
|
) -> Result<ForeignDataWrapper<Scene>, EvalError> {
|
||||||
|
|
||||||
sce.add_object(obj.clone());
|
sce.add_object(obj.clone());
|
||||||
|
Ok(sce)
|
||||||
Ok(sce.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scene_add_light(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
|
#[native_lisp_function]
|
||||||
let [sce, lgt]: [Expression; 2] = expr.try_into()?;
|
pub fn scene_add_light(
|
||||||
|
mut sce: ForeignDataWrapper<Scene>,
|
||||||
let mut sce: ForeignDataWrapper<Scene> = eval(env, sce)?.try_into()?;
|
lgt: ForeignDataWrapper<Light>,
|
||||||
let lgt: ForeignDataWrapper<Light> = eval(env, lgt)?.try_into()?;
|
) -> Result<ForeignDataWrapper<Scene>, EvalError> {
|
||||||
|
|
||||||
sce.add_light(*lgt);
|
sce.add_light(*lgt);
|
||||||
|
Ok(sce)
|
||||||
Ok(sce.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn camera(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
|
native_lisp_function_proxy!(
|
||||||
let [pos, cnt, up, fovy, w, h]: [Expression; 6] = expr.try_into()?;
|
fname = scene_add,
|
||||||
|
eval,
|
||||||
|
dispatch = scene_add_object,
|
||||||
|
dispatch = scene_add_light
|
||||||
|
);
|
||||||
|
|
||||||
let pos: ForeignDataWrapper<Point3> = eval(env, pos)?.try_into()?;
|
#[native_lisp_function(eval)]
|
||||||
let cnt: ForeignDataWrapper<Point3> = eval(env, cnt)?.try_into()?;
|
pub fn camera(
|
||||||
let up: ForeignDataWrapper<Vector3> = eval(env, up)?.try_into()?;
|
pos: ForeignDataWrapper<Point3>,
|
||||||
let fovy: f64 = eval(env, fovy)?.try_into()?;
|
cnt: ForeignDataWrapper<Point3>,
|
||||||
let w: i64 = eval(env, w)?.try_into()?;
|
up: ForeignDataWrapper<Vector3>,
|
||||||
let h: i64 = eval(env, h)?.try_into()?;
|
fovy: f64,
|
||||||
|
w: i64,
|
||||||
Ok(ForeignDataWrapper::new(Camera::new(*pos, *cnt, *up, fovy, w as usize, h as usize)).into())
|
h: i64,
|
||||||
|
) -> Result<ForeignDataWrapper<Camera>, EvalError> {
|
||||||
|
Ok(ForeignDataWrapper::new(Camera::new(
|
||||||
|
*pos, *cnt, *up, fovy, w as usize, h as usize,
|
||||||
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
|
#[native_lisp_function(eval)]
|
||||||
let [cam, sce, dpt, sbp, out]: [Expression; 5] = expr.try_into()?;
|
pub fn render(
|
||||||
|
cam: ForeignDataWrapper<Camera>,
|
||||||
let cam: ForeignDataWrapper<Camera> = eval(env, cam)?.try_into()?;
|
sce: ForeignDataWrapper<Scene>,
|
||||||
let sce: ForeignDataWrapper<Scene> = eval(env, sce)?.try_into()?;
|
dpt: i64,
|
||||||
let dpt: i64 = eval(env, dpt)?.try_into()?;
|
sbp: i64,
|
||||||
let sbp: i64 = eval(env, sbp)?.try_into()?;
|
out: String,
|
||||||
let out: String = eval(env, out)?.try_into()?;
|
) -> Result<Expression, EvalError> {
|
||||||
|
|
||||||
println!("Rendering to {}...", out);
|
println!("Rendering to {}...", out);
|
||||||
let img = cam.render(&sce, dpt as u32, sbp as u32);
|
let img = cam.render(&sce, dpt as u32, sbp as u32);
|
||||||
|
|
||||||
@ -200,7 +165,7 @@ pub fn render(env: &Environment, expr: Expression) -> Result<Expression, EvalErr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[native_lisp_function(fname = vadd, eval)]
|
#[native_lisp_function]
|
||||||
pub fn vadd_vv(
|
pub fn vadd_vv(
|
||||||
a: ForeignDataWrapper<Vector3>,
|
a: ForeignDataWrapper<Vector3>,
|
||||||
b: ForeignDataWrapper<Vector3>,
|
b: ForeignDataWrapper<Vector3>,
|
||||||
@ -208,6 +173,80 @@ pub fn vadd_vv(
|
|||||||
Ok(ForeignDataWrapper::new(*a + *b))
|
Ok(ForeignDataWrapper::new(*a + *b))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[native_lisp_function]
|
||||||
|
pub fn vadd_vp(
|
||||||
|
a: ForeignDataWrapper<Vector3>,
|
||||||
|
b: ForeignDataWrapper<Point3>,
|
||||||
|
) -> Result<ForeignDataWrapper<Point3>, EvalError> {
|
||||||
|
Ok(ForeignDataWrapper::new(*b + *a))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[native_lisp_function]
|
||||||
|
pub fn vadd_pv(
|
||||||
|
a: ForeignDataWrapper<Point3>,
|
||||||
|
b: ForeignDataWrapper<Vector3>,
|
||||||
|
) -> Result<ForeignDataWrapper<Point3>, EvalError> {
|
||||||
|
Ok(ForeignDataWrapper::new(*a + *b))
|
||||||
|
}
|
||||||
|
|
||||||
|
native_lisp_function_proxy!(
|
||||||
|
fname = vadd,
|
||||||
|
eval,
|
||||||
|
dispatch = vadd_vv,
|
||||||
|
dispatch = vadd_vp,
|
||||||
|
dispatch = vadd_pv
|
||||||
|
);
|
||||||
|
|
||||||
|
#[native_lisp_function]
|
||||||
|
pub fn vsub_vv(
|
||||||
|
a: ForeignDataWrapper<Vector3>,
|
||||||
|
b: ForeignDataWrapper<Vector3>,
|
||||||
|
) -> Result<ForeignDataWrapper<Vector3>, EvalError> {
|
||||||
|
Ok(ForeignDataWrapper::new(*a - *b))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[native_lisp_function]
|
||||||
|
pub fn vsub_vp(
|
||||||
|
a: ForeignDataWrapper<Vector3>,
|
||||||
|
b: ForeignDataWrapper<Point3>,
|
||||||
|
) -> Result<ForeignDataWrapper<Point3>, EvalError> {
|
||||||
|
Ok(ForeignDataWrapper::new(*b - *a))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[native_lisp_function]
|
||||||
|
pub fn vsub_pv(
|
||||||
|
a: ForeignDataWrapper<Point3>,
|
||||||
|
b: ForeignDataWrapper<Vector3>,
|
||||||
|
) -> Result<ForeignDataWrapper<Point3>, EvalError> {
|
||||||
|
Ok(ForeignDataWrapper::new(*a - *b))
|
||||||
|
}
|
||||||
|
|
||||||
|
native_lisp_function_proxy!(
|
||||||
|
fname = vsub,
|
||||||
|
eval,
|
||||||
|
dispatch = vsub_vv,
|
||||||
|
dispatch = vsub_vp,
|
||||||
|
dispatch = vsub_pv
|
||||||
|
);
|
||||||
|
|
||||||
|
#[native_lisp_function]
|
||||||
|
pub fn vmul_vs(
|
||||||
|
a: ForeignDataWrapper<Vector3>,
|
||||||
|
b: f64,
|
||||||
|
) -> Result<ForeignDataWrapper<Vector3>, EvalError> {
|
||||||
|
Ok(ForeignDataWrapper::new(*a * b))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[native_lisp_function]
|
||||||
|
pub fn vmul_sv(
|
||||||
|
a: f64,
|
||||||
|
b: ForeignDataWrapper<Vector3>,
|
||||||
|
) -> Result<ForeignDataWrapper<Vector3>, EvalError> {
|
||||||
|
Ok(ForeignDataWrapper::new(*b * a))
|
||||||
|
}
|
||||||
|
|
||||||
|
native_lisp_function_proxy!(fname = vmul, eval, dispatch = vmul_vs, dispatch = vmul_sv);
|
||||||
|
|
||||||
/// Adds the raytracing functions to the given environment layer.
|
/// Adds the raytracing functions to the given environment layer.
|
||||||
pub fn mk_raytrace(layer: &mut EnvironmentLayer) {
|
pub fn mk_raytrace(layer: &mut EnvironmentLayer) {
|
||||||
layer.set("point".to_string(), Expression::Function(point));
|
layer.set("point".to_string(), Expression::Function(point));
|
||||||
@ -233,4 +272,6 @@ pub fn mk_raytrace(layer: &mut EnvironmentLayer) {
|
|||||||
layer.set("camera".to_string(), Expression::Function(camera));
|
layer.set("camera".to_string(), Expression::Function(camera));
|
||||||
layer.set("render".to_string(), Expression::Function(render));
|
layer.set("render".to_string(), Expression::Function(render));
|
||||||
layer.set("vadd".to_string(), Expression::Function(vadd));
|
layer.set("vadd".to_string(), Expression::Function(vadd));
|
||||||
|
layer.set("vsub".to_string(), Expression::Function(vsub));
|
||||||
|
layer.set("vmul".to_string(), Expression::Function(vmul));
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user