aboutsummaryrefslogtreecommitdiff
path: root/src/sdf.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/sdf.rs')
-rw-r--r--src/sdf.rs117
1 files changed, 73 insertions, 44 deletions
diff --git a/src/sdf.rs b/src/sdf.rs
index 00a4a11..c46deab 100644
--- a/src/sdf.rs
+++ b/src/sdf.rs
@@ -4,57 +4,86 @@ use cgmath::prelude::*;
type Vector = Vector3<f32>;
-pub fn sd_sphere(point: Vector, center: Vector, radius: f32) -> f32 {
- (point - center).magnitude() - radius
+pub trait Object {
+ fn sdf(&self, point: Vector, time: f32) -> f32;
}
-pub fn sd_box(point: Vector, center: Vector, size: Vector) -> f32 {
- let diff = center - point;
- let q = diff.map(|n| n.abs()) - size / 2.0;
- return q.map(|n| n.max(0.0)).magnitude() + (q.y.max(q.z).max(q.x)).min(0.0)
+pub struct Sphere {
+ pub center: Vector,
+ pub radius: f32,
}
-pub fn sd_gear(point: Vector, time: f32, center: Vector, radius: f32, thickness: f32, turn_rate: f32) -> f32 {
- let mut dist: f32;
+impl Object for Sphere {
+ fn sdf(&self, point: Vector, _time: f32) -> f32 {
+ (point - self.center).magnitude() - self.radius
+ }
+}
- let thickness_over_2 = thickness / 2.0;
- let thickness_over_4 = thickness / 4.0;
+pub struct SDBox {
+ pub center: Vector,
+ pub size: Vector,
+}
- // Ring
- {
- let cylinder_dist = (Vector::new(0.0, point.y, point.z) - center).magnitude() - (radius - thickness_over_4);
- dist = cylinder_dist.abs() - thickness_over_2; // Make cylinder hollow
- }
- // Teeth
- {
- let sector_angle: f32 = 2.0 * PI / 12.0;
-
- // Account for rotation with time
- let angle = sector_angle * time / turn_rate;
- let rotated_point = Vector::new(
- point.x,
- point.y * angle.cos() - point.z * angle.sin(),
- point.y * angle.sin() + point.z * angle.cos()
- );
-
- // Map all space to the first sector
- let point_angle = (rotated_point.z / rotated_point.y).atan();
- let angle2 = -sector_angle * (point_angle / sector_angle).round();
-
- let mapped_point = Vector::new(
- rotated_point.x,
- (rotated_point.y * angle2.cos() - rotated_point.z * angle2.sin()).abs(),
- rotated_point.y * angle2.sin() + rotated_point.z * angle2.cos()
- );
-
- let center = Vector { x: 0.0, y: radius + thickness_over_2, z: 0.0 };
- let size = Vector::new(thickness, thickness * 2.0, thickness);
- // Make teeth smooth by subtracting some amount
- dist = dist.min(sd_box(mapped_point, center, size) - thickness_over_4);
+impl Object for SDBox {
+ fn sdf(&self, point: Vector, _time: f32) -> f32 {
+ let diff = self.center - point;
+ let q = diff.map(|n| n.abs()) - self.size / 2.0;
+ return q.map(|n| n.max(0.0)).magnitude() + (q.y.max(q.z).max(q.x)).min(0.0)
}
+}
+
+pub struct Gear {
+ pub center: Vector,
+ pub radius: f32,
+ pub thickness: f32,
+ pub turn_rate: f32,
+}
+
+impl Object for Gear {
+ fn sdf(&self, point: Vector, time: f32) -> f32 {
+ let mut dist: f32;
- // Take a slice
- dist = dist.max(point.x.abs() - thickness_over_2);
+ let thickness_over_2 = self.thickness / 2.0;
+ let thickness_over_4 = self.thickness / 4.0;
- return dist;
+ // Ring
+ {
+ let cylinder_dist = (Vector::new(0.0, point.y, point.z) - self.center).magnitude() - (self.radius - thickness_over_4);
+ dist = cylinder_dist.abs() - thickness_over_2; // Make cylinder hollow
+ }
+ // Teeth
+ {
+ let sector_angle: f32 = 2.0 * PI / 12.0;
+
+ // Account for rotation with time
+ let angle = sector_angle * time / self.turn_rate;
+ let rotated_point = Vector::new(
+ point.x,
+ point.y * angle.cos() - point.z * angle.sin(),
+ point.y * angle.sin() + point.z * angle.cos()
+ );
+
+ // Map all space to the first sector
+ let point_angle = (rotated_point.z / rotated_point.y).atan();
+ let angle2 = -sector_angle * (point_angle / sector_angle).round();
+
+ let mapped_point = Vector::new(
+ rotated_point.x,
+ (rotated_point.y * angle2.cos() - rotated_point.z * angle2.sin()).abs(),
+ rotated_point.y * angle2.sin() + rotated_point.z * angle2.cos()
+ );
+
+ // Make teeth smooth by subtracting some amount
+ dist = dist.min(SDBox {
+ center: Vector { x: 0.0, y: self.radius + thickness_over_2, z: 0.0 },
+ size: Vector::new(self.thickness, self.thickness * 2.0, self.thickness),
+ }.sdf(mapped_point, time) - thickness_over_4);
+ }
+
+ // Take a slice
+ dist = dist.max(point.x.abs() - thickness_over_2);
+
+ return dist;
+ }
}
+