78 lines
2.0 KiB
Rust
78 lines
2.0 KiB
Rust
use termtree;
|
|
use glam::{Vec3A};
|
|
use std::fmt;
|
|
|
|
pub trait Field: fmt::Debug {
|
|
fn sample(&self, pos: Vec3A) -> f32;
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub enum FieldOp {
|
|
Add,
|
|
Sub,
|
|
Mul,
|
|
Div,
|
|
}
|
|
|
|
impl fmt::Display for FieldOp {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
let mut name = String::new();
|
|
match *self {
|
|
Add => { name = "+".to_string() },
|
|
Sub => { name = "-".to_string() },
|
|
Mul => { name = "*".to_string() },
|
|
Div => { name = "/".to_string() },
|
|
_ => { name = "?".to_string() }
|
|
}
|
|
write!(f, "{}", name)
|
|
}
|
|
}
|
|
|
|
use FieldOp::*;
|
|
|
|
#[derive(Debug)]
|
|
pub struct FieldNode {
|
|
pub field: Box<dyn Field>,
|
|
pub op: FieldOp,
|
|
pub children: Vec<FieldNode>,
|
|
}
|
|
|
|
impl FieldNode {
|
|
pub fn sample(&self, pos: Vec3A) -> f32 {
|
|
let mut result = self.field.sample(pos);
|
|
|
|
for child in self.children.iter() {
|
|
let child_result = child.sample(pos);
|
|
|
|
result = match child.op {
|
|
Add => { result + child_result },
|
|
Sub => { result - child_result },
|
|
Mul => { result * child_result },
|
|
Div => { result / child_result }
|
|
}
|
|
}
|
|
|
|
result
|
|
}
|
|
|
|
pub fn to_termtree(&self) -> termtree::Tree<String> {
|
|
// Turn the node structure into a tree
|
|
let mut node_label = String::new();
|
|
if self.children.is_empty() {
|
|
node_label = format!("{} {:?}", self.op, self.field);
|
|
} else {
|
|
node_label = format!("{} {:?} = {:?}", self.op, self.field, self.sample(Vec3A::ZERO));
|
|
}
|
|
let mut tree: termtree::Tree<String> = termtree::Tree::new(node_label);
|
|
for child in self.children.iter() {
|
|
tree.push(child.to_termtree());
|
|
}
|
|
tree
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for FieldNode {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
write!(f, "{}", self.to_termtree())
|
|
}
|
|
} |