feat(vec): add more vec3 functions

This commit is contained in:
Jonas Röger 2024-11-10 02:36:00 +01:00
parent 6f8499acaf
commit b086a89557
Signed by: jonas
GPG Key ID: 4000EB35E1AE0F07
3 changed files with 59 additions and 11 deletions

View File

@ -129,6 +129,7 @@ impl TryFrom<Expression> for f64 {
type Error = EvalError;
fn try_from(value: Expression) -> Result<f64, Self::Error> {
match value {
Expression::Integer(i) => Ok(i as f64),
Expression::Float(f) => Ok(f),
_ => Err(EvalError::TypeError(
"Expression is not a Float".to_string(),

View File

@ -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
pub fn vec_vec(_env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
let [x, y, z]: [f64; 3] = expr.try_into()?;
Ok(Expression::ForeignExpression(ForeignDataWrapper::new(
Box::new(Vec3 { x, y, z }),
)))
Ok(Vec3 { x, y, z }.into())
}
/// 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 b = Vec3::try_from(eval(env, b)?)?;
Ok(Expression::ForeignExpression(ForeignDataWrapper::new(
Box::new(Vec3 {
x: a.x + b.x,
y: a.y + b.y,
z: a.z + b.z,
}),
)))
Ok(Vec3 {
x: a.x + b.x,
y: a.y + b.y,
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
pub fn mk_vec3(layer: &mut EnvironmentLayer) {
layer.set("vec3".to_string(), Expression::Function(vec_vec));
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));
}

View File

@ -15,7 +15,7 @@ fn main() {
"pow",
"(pow 2 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();