From 507038ab4d44887ff6aaae4b662fa802194d271e Mon Sep 17 00:00:00 2001 From: Skye Terran Date: Thu, 28 Jul 2022 00:01:45 -0700 Subject: [PATCH] Refactored, got multiple SDF primitives working --- replicant/src/fields.rs | 78 ++++++++---------------------------- replicant/src/lib.rs | 2 +- replicant/src/main.rs | 89 +++++++++++++++++++++++------------------ 3 files changed, 68 insertions(+), 101 deletions(-) diff --git a/replicant/src/fields.rs b/replicant/src/fields.rs index 6da4882..7f916a5 100644 --- a/replicant/src/fields.rs +++ b/replicant/src/fields.rs @@ -1,29 +1,9 @@ use termtree; -use glam::{Vec3}; +use glam::{Vec3A}; use std::fmt; -/* -Data: [Sphere_0, Sphere_1, Sphere_2] -. -├── Not -├ └── Xor -├ ├── Ref(0) -├ └── Ref(1) -├── Or -├ ├── Ref(2), -├ └── Ref(1) -└── And - ├── Nor - ├ ├── Ref(0), - ├ └── Ref(2) - └── Ref(1) -*/ - -pub trait Field: fmt::Debug + Clone { - fn add(&self, other: Self) -> Self; - fn sub(&self, other: Self) -> Self; - fn mul(&self, other: Self) -> Self; - fn div(&self, other: Self) -> Self; +pub trait Field: fmt::Debug { + fn sample(&self, pos: Vec3A) -> f32; } #[derive(Debug)] @@ -51,24 +31,24 @@ impl fmt::Display for FieldOp { use FieldOp::*; #[derive(Debug)] -pub struct FieldNode { - pub field: T, +pub struct FieldNode { + pub field: Box, pub op: FieldOp, - pub children: Vec>, + pub children: Vec, } -impl FieldNode { - pub fn sample(&self, pos: Vec3) -> T { - let mut result = self.field.clone(); +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.add(child_result) }, - Sub => { result.sub(child_result) }, - Mul => { result.mul(child_result) }, - Div => { result.div(child_result) } + Add => { result + child_result }, + Sub => { result - child_result }, + Mul => { result * child_result }, + Div => { result / child_result } } } @@ -81,7 +61,7 @@ impl FieldNode { if self.children.is_empty() { node_label = format!("{} {:?}", self.op, self.field); } else { - node_label = format!("{} {:?} = {:?}", self.op, self.field, self.sample(Vec3::ZERO)); + node_label = format!("{} {:?} = {:?}", self.op, self.field, self.sample(Vec3A::ZERO)); } let mut tree: termtree::Tree = termtree::Tree::new(node_label); for child in self.children.iter() { @@ -91,34 +71,8 @@ impl FieldNode { } } -impl fmt::Display for FieldNode { +impl fmt::Display for FieldNode { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.to_termtree()) } -} - -/* -#[derive(Debug)] -enum CSGShape { - None, - Sphere, - Rect, - Plane, -} - -impl Field for CSGShape { -} - -impl fmt::Display for CSGShape { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut name = String::new(); - match *self { - None => { name = "".to_string() }, - _ => { name = format!("{:?}", self) } - } - write!(f, "{}", name) - } -} -*/ - -//use CSGShape::*; +} \ No newline at end of file diff --git a/replicant/src/lib.rs b/replicant/src/lib.rs index c283a1d..6158af1 100644 --- a/replicant/src/lib.rs +++ b/replicant/src/lib.rs @@ -1 +1 @@ -pub mod fields; +pub mod fields; \ No newline at end of file diff --git a/replicant/src/main.rs b/replicant/src/main.rs index 1af9ffe..c834001 100644 --- a/replicant/src/main.rs +++ b/replicant/src/main.rs @@ -1,49 +1,62 @@ -use termtree; -use glam::{Vec3}; -use std::fmt; - +use glam::{Vec3A}; use replicant::fields::{Field, FieldOp, FieldNode}; use FieldOp::*; -#[derive(Debug, Clone)] -struct Scalar(f32); +#[derive(Debug)] +struct Sphere { + origin: Vec3A, + radius: f32, +} -impl Field for Scalar { - fn add(&self, other: Self) -> Self { - Scalar(self.0 + other.0) - } - fn sub(&self, other: Self) -> Self { - Scalar(self.0 - other.0) - } - fn mul(&self, other: Self) -> Self { - Scalar(self.0 * other.0) - } - fn div(&self, other: Self) -> Self { - Scalar(self.0 / other.0) +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: Scalar(10.0), op: Add, children: vec![ - FieldNode { field: Scalar(8.0), op: Mul, children: Vec::new() }, - FieldNode { field: Scalar(2.0), op: Sub, children: vec![ - FieldNode { field: Scalar(0.0), op: Add, children: vec![ - FieldNode { field: Scalar(0.7), op: Sub, children: Vec::new() }, - FieldNode { field: Scalar(0.2), op: Add, children: Vec::new() }, - ] }, - FieldNode { field: Scalar(3.0), op: Div, children: Vec::new() }, - ] }, - FieldNode { field: Scalar(7.0), op: Mul, children: vec![ - FieldNode { field: Scalar(0.75), op: Add, children: Vec::new() }, - FieldNode { field: Scalar(1.0), op: Sub, children: vec![ - FieldNode { field: Scalar(0.23), op: Sub, children: Vec::new() }, - ] }, - FieldNode { field: Scalar(2.0), op: Div, children: Vec::new() }, - ] }, - FieldNode { field: Scalar(0.1), op: Mul, children: Vec::new() }, + 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); - println!("{:?}", float_nodes.sample(Vec3::ZERO)); -} - + + 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)); +} \ No newline at end of file