Compare commits
4 Commits
Author | SHA1 | Date |
---|---|---|
Skye Terran | 507038ab4d | |
robotcritter | 01edb49cb8 | |
robotcritter | 9c2f58b114 | |
mars | fe5c27e890 |
|
@ -1,6 +1,7 @@
|
|||
[workspace]
|
||||
members = [
|
||||
"editor"
|
||||
"editor",
|
||||
"replicant"
|
||||
]
|
||||
|
||||
[package]
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "replicant"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
glam = "0.21"
|
||||
termtree = "0.4"
|
|
@ -0,0 +1,78 @@
|
|||
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())
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
pub mod fields;
|
|
@ -0,0 +1,62 @@
|
|||
use glam::{Vec3A};
|
||||
use replicant::fields::{Field, FieldOp, FieldNode};
|
||||
use FieldOp::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Sphere {
|
||||
origin: Vec3A,
|
||||
radius: f32,
|
||||
}
|
||||
|
||||
impl Field for Sphere {
|
||||
fn sample(&self, pos: Vec3A) -> f32 {
|
||||
self.origin.distance(pos) - self.radius
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Rect {
|
||||
origin: Vec3A,
|
||||
extent: Vec3A,
|
||||
}
|
||||
|
||||
impl Field for Rect {
|
||||
fn sample(&self, pos: Vec3A) -> f32 {
|
||||
let q: Vec3A = pos.abs() - self.extent;
|
||||
Vec3A::length(Vec3A::max(q, Vec3A::ZERO)) + f32::min(f32::max(q.x, f32::max(q.y, q.z)), 0.0)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
float sdPlane( vec3 p, vec3 n, float h )
|
||||
{
|
||||
// n must be normalized
|
||||
return dot(p,n) + h;
|
||||
}
|
||||
*/
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Plane {
|
||||
height: f32,
|
||||
normal: Vec3A,
|
||||
}
|
||||
|
||||
impl Field for Plane {
|
||||
fn sample(&self, pos: Vec3A) -> f32 {
|
||||
Vec3A::dot(pos, self.normal) + self.height
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut float_nodes: FieldNode = FieldNode { field: Box::new(Sphere { origin: Vec3A::new(0.0, 0.0, 10.0), radius: 10.0 }), op: Add, children: vec![
|
||||
FieldNode { field: Box::new(Rect { origin: Vec3A::new(0.0, 0.0, 0.0), extent: Vec3A::new(5.0, 5.0, 5.0) }), op: Add, children: Vec::new() },
|
||||
FieldNode { field: Box::new(Plane { height: 0.0, normal: Vec3A::new(0.0, 0.0, 1.0) }), op: Sub, children: Vec::new() },
|
||||
] };
|
||||
|
||||
println!("Node tree:\n{}", float_nodes);
|
||||
|
||||
let field = Rect { origin: Vec3A::ZERO, extent: Vec3A::new(10.0, 10.0, 10.0) };
|
||||
let sample_pos = Vec3A::new(11.0, 11.0, 11.0);
|
||||
println!("{:?}", field);
|
||||
println!("Distance at {:?} is {}", sample_pos, field.sample(sample_pos));
|
||||
}
|
Loading…
Reference in New Issue