Refactored, got multiple SDF primitives working
This commit is contained in:
parent
01edb49cb8
commit
507038ab4d
|
@ -1,29 +1,9 @@
|
||||||
use termtree;
|
use termtree;
|
||||||
use glam::{Vec3};
|
use glam::{Vec3A};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
/*
|
pub trait Field: fmt::Debug {
|
||||||
Data: [Sphere_0, Sphere_1, Sphere_2]
|
fn sample(&self, pos: Vec3A) -> f32;
|
||||||
.
|
|
||||||
├── 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -51,24 +31,24 @@ impl fmt::Display for FieldOp {
|
||||||
use FieldOp::*;
|
use FieldOp::*;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct FieldNode<T: Field> {
|
pub struct FieldNode {
|
||||||
pub field: T,
|
pub field: Box<dyn Field>,
|
||||||
pub op: FieldOp,
|
pub op: FieldOp,
|
||||||
pub children: Vec<FieldNode<T>>,
|
pub children: Vec<FieldNode>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Field> FieldNode<T> {
|
impl FieldNode {
|
||||||
pub fn sample(&self, pos: Vec3) -> T {
|
pub fn sample(&self, pos: Vec3A) -> f32 {
|
||||||
let mut result = self.field.clone();
|
let mut result = self.field.sample(pos);
|
||||||
|
|
||||||
for child in self.children.iter() {
|
for child in self.children.iter() {
|
||||||
let child_result = child.sample(pos);
|
let child_result = child.sample(pos);
|
||||||
|
|
||||||
result = match child.op {
|
result = match child.op {
|
||||||
Add => { result.add(child_result) },
|
Add => { result + child_result },
|
||||||
Sub => { result.sub(child_result) },
|
Sub => { result - child_result },
|
||||||
Mul => { result.mul(child_result) },
|
Mul => { result * child_result },
|
||||||
Div => { result.div(child_result) }
|
Div => { result / child_result }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +61,7 @@ impl<T: Field> FieldNode<T> {
|
||||||
if self.children.is_empty() {
|
if self.children.is_empty() {
|
||||||
node_label = format!("{} {:?}", self.op, self.field);
|
node_label = format!("{} {:?}", self.op, self.field);
|
||||||
} else {
|
} 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<String> = termtree::Tree::new(node_label);
|
let mut tree: termtree::Tree<String> = termtree::Tree::new(node_label);
|
||||||
for child in self.children.iter() {
|
for child in self.children.iter() {
|
||||||
|
@ -91,34 +71,8 @@ impl<T: Field> FieldNode<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Field> fmt::Display for FieldNode<T> {
|
impl fmt::Display for FieldNode {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "{}", self.to_termtree())
|
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::*;
|
|
|
@ -1 +1 @@
|
||||||
pub mod fields;
|
pub mod fields;
|
|
@ -1,49 +1,62 @@
|
||||||
use termtree;
|
use glam::{Vec3A};
|
||||||
use glam::{Vec3};
|
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
use replicant::fields::{Field, FieldOp, FieldNode};
|
use replicant::fields::{Field, FieldOp, FieldNode};
|
||||||
use FieldOp::*;
|
use FieldOp::*;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug)]
|
||||||
struct Scalar(f32);
|
struct Sphere {
|
||||||
|
origin: Vec3A,
|
||||||
|
radius: f32,
|
||||||
|
}
|
||||||
|
|
||||||
impl Field for Scalar {
|
impl Field for Sphere {
|
||||||
fn add(&self, other: Self) -> Self {
|
fn sample(&self, pos: Vec3A) -> f32 {
|
||||||
Scalar(self.0 + other.0)
|
self.origin.distance(pos) - self.radius
|
||||||
}
|
}
|
||||||
fn sub(&self, other: Self) -> Self {
|
}
|
||||||
Scalar(self.0 - other.0)
|
|
||||||
}
|
#[derive(Debug)]
|
||||||
fn mul(&self, other: Self) -> Self {
|
struct Rect {
|
||||||
Scalar(self.0 * other.0)
|
origin: Vec3A,
|
||||||
}
|
extent: Vec3A,
|
||||||
fn div(&self, other: Self) -> Self {
|
}
|
||||||
Scalar(self.0 / other.0)
|
|
||||||
|
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() {
|
fn main() {
|
||||||
let mut float_nodes: FieldNode<Scalar> = FieldNode { field: Scalar(10.0), op: Add, children: vec![
|
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: Scalar(8.0), op: Mul, children: Vec::new() },
|
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: Scalar(2.0), op: Sub, children: vec![
|
FieldNode { field: Box::new(Plane { height: 0.0, normal: Vec3A::new(0.0, 0.0, 1.0) }), op: Sub, children: Vec::new() },
|
||||||
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() },
|
|
||||||
] };
|
] };
|
||||||
|
|
||||||
println!("Node tree:\n{}", float_nodes);
|
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));
|
||||||
|
}
|
Loading…
Reference in New Issue