feat(vec): add more vec3 functions
This commit is contained in:
parent
6f8499acaf
commit
b086a89557
@ -129,6 +129,7 @@ impl TryFrom<Expression> for f64 {
|
|||||||
type Error = EvalError;
|
type Error = EvalError;
|
||||||
fn try_from(value: Expression) -> Result<f64, Self::Error> {
|
fn try_from(value: Expression) -> Result<f64, Self::Error> {
|
||||||
match value {
|
match value {
|
||||||
|
Expression::Integer(i) => Ok(i as f64),
|
||||||
Expression::Float(f) => Ok(f),
|
Expression::Float(f) => Ok(f),
|
||||||
_ => Err(EvalError::TypeError(
|
_ => Err(EvalError::TypeError(
|
||||||
"Expression is not a Float".to_string(),
|
"Expression is not a Float".to_string(),
|
||||||
|
|||||||
@ -64,13 +64,17 @@ impl TryFrom<Expression> for Vec3 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Vec3> for Expression {
|
||||||
|
fn from(value: Vec3) -> Self {
|
||||||
|
Expression::ForeignExpression(ForeignDataWrapper::new(Box::new(value)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Create a vec3 expression from a list of 3 floats
|
/// Create a vec3 expression from a list of 3 floats
|
||||||
pub fn vec_vec(_env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
|
pub fn vec_vec(_env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
|
||||||
let [x, y, z]: [f64; 3] = expr.try_into()?;
|
let [x, y, z]: [f64; 3] = expr.try_into()?;
|
||||||
|
|
||||||
Ok(Expression::ForeignExpression(ForeignDataWrapper::new(
|
Ok(Vec3 { x, y, z }.into())
|
||||||
Box::new(Vec3 { x, y, z }),
|
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add two vec3 expressions
|
/// Add two vec3 expressions
|
||||||
@ -80,17 +84,60 @@ pub fn vec_add(env: &Environment, expr: Expression) -> Result<Expression, EvalEr
|
|||||||
let a = Vec3::try_from(eval(env, a)?)?;
|
let a = Vec3::try_from(eval(env, a)?)?;
|
||||||
let b = Vec3::try_from(eval(env, b)?)?;
|
let b = Vec3::try_from(eval(env, b)?)?;
|
||||||
|
|
||||||
Ok(Expression::ForeignExpression(ForeignDataWrapper::new(
|
Ok(Vec3 {
|
||||||
Box::new(Vec3 {
|
x: a.x + b.x,
|
||||||
x: a.x + b.x,
|
y: a.y + b.y,
|
||||||
y: a.y + b.y,
|
z: a.z + b.z,
|
||||||
z: a.z + b.z,
|
}
|
||||||
}),
|
.into())
|
||||||
)))
|
}
|
||||||
|
|
||||||
|
/// Scale a vector by a factor. First argument is the factor, second the vector
|
||||||
|
pub fn vec_scale(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
|
||||||
|
let [a, b]: [Expression; 2] = expr.try_into()?;
|
||||||
|
|
||||||
|
let a = f64::try_from(eval(env, a)?)?;
|
||||||
|
let b = Vec3::try_from(eval(env, b)?)?;
|
||||||
|
|
||||||
|
Ok(Vec3 {
|
||||||
|
x: a * b.x,
|
||||||
|
y: a * b.y,
|
||||||
|
z: a * b.z,
|
||||||
|
}
|
||||||
|
.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Calculate the dot product of two vec3
|
||||||
|
pub fn vec_dot(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
|
||||||
|
let [a, b]: [Expression; 2] = expr.try_into()?;
|
||||||
|
|
||||||
|
let a = Vec3::try_from(eval(env, a)?)?;
|
||||||
|
let b = Vec3::try_from(eval(env, b)?)?;
|
||||||
|
|
||||||
|
Ok(Expression::Float(a.x * b.x + a.y * b.y + a.z * b.z))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the L2-norm of a vector
|
||||||
|
pub fn vec_norm(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
|
||||||
|
let [arg]: [Expression; 1] = expr.try_into()?;
|
||||||
|
|
||||||
|
let vec = Vec3::try_from(eval(env, arg)?)?;
|
||||||
|
|
||||||
|
let length = (vec.x.powi(2) + vec.y.powi(2) + vec.z.powi(2)).sqrt();
|
||||||
|
|
||||||
|
Ok(Vec3 {
|
||||||
|
x: vec.x / length,
|
||||||
|
y: vec.y / length,
|
||||||
|
z: vec.z / length,
|
||||||
|
}
|
||||||
|
.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add vec3 functions to a layer
|
/// Add vec3 functions to a layer
|
||||||
pub fn mk_vec3(layer: &mut EnvironmentLayer) {
|
pub fn mk_vec3(layer: &mut EnvironmentLayer) {
|
||||||
layer.set("vec3".to_string(), Expression::Function(vec_vec));
|
layer.set("vec3".to_string(), Expression::Function(vec_vec));
|
||||||
layer.set("vec3-add".to_string(), Expression::Function(vec_add));
|
layer.set("vec3-add".to_string(), Expression::Function(vec_add));
|
||||||
|
layer.set("vec3-scale".to_string(), Expression::Function(vec_scale));
|
||||||
|
layer.set("vec3-dot".to_string(), Expression::Function(vec_dot));
|
||||||
|
layer.set("vec3-norm".to_string(), Expression::Function(vec_norm));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ fn main() {
|
|||||||
"pow",
|
"pow",
|
||||||
"(pow 2 10)",
|
"(pow 2 10)",
|
||||||
"(let '((fib . (lambda (n) (if (< n 2) n (+ (fib (- n 1)) (fib (- n 2))))))) (fib 10))",
|
"(let '((fib . (lambda (n) (if (< n 2) n (+ (fib (- n 1)) (fib (- n 2))))))) (fib 10))",
|
||||||
"(vec3-add (vec3 1.0 2.0 3.0) (vec3 4.0 5.0 6.0))",
|
"(let '((a . (vec3 1 2 3)) (b . (vec3 4 5 6))) (vec3-dot (vec3-norm (vec3-add a b)) a))",
|
||||||
];
|
];
|
||||||
|
|
||||||
let environment = Environment::default();
|
let environment = Environment::default();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user