aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoreug-vs <eugene@eug-vs.xyz>2021-10-28 13:10:28 +0300
committereug-vs <eugene@eug-vs.xyz>2021-10-28 13:25:33 +0300
commitff8e486274d789e9c50b367e5eccf174b85a370d (patch)
treeae94421a567553fe71ac07f3f64c24535980c76e
parentaf515879c9b48a34ca4e953c9eb4bdff9e95fbd2 (diff)
downloadpistol-ff8e486274d789e9c50b367e5eccf174b85a370d.tar.gz
feat: add sdf_gear()
-rw-r--r--src/camera.rs52
-rw-r--r--src/main.rs2
2 files changed, 29 insertions, 25 deletions
diff --git a/src/camera.rs b/src/camera.rs
index 2e11d62..4a985a5 100644
--- a/src/camera.rs
+++ b/src/camera.rs
@@ -1,4 +1,5 @@
use cgmath::Matrix3;
+use cgmath::Rad;
use cgmath::Vector3;
use cgmath::prelude::*;
use std::fmt;
@@ -45,11 +46,11 @@ fn softmin(left: f32, right: f32, k: f32) -> f32 {
return left.min(right) - h*h*k*(1.0/4.0);
}
-fn sphere(point: Vector, center: Vector, radius: f32) -> f32 {
+fn sd_sphere(point: Vector, center: Vector, radius: f32) -> f32 {
(point - center).magnitude() - radius
}
-fn r#box(point: Vector, center: Vector, size: Vector) -> f32 {
+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)
@@ -57,35 +58,38 @@ fn r#box(point: Vector, center: Vector, size: Vector) -> f32 {
impl Camera {
- pub fn sdf(&self, point: Vector) -> f32 {
+ pub fn sd_gear(&self, point: Vector, center: Vector, radius: f32, thickness: f32) -> f32 {
let mut dist: f32;
- // Floor at z = -2
- let floor_dist = point.z + 1.0;
-
- dist = floor_dist;
- // Sphere
+ // Ring
{
- let center = Vector { x: 4.0, y: 0.0, z: 0.0 };
- let radius = 1.5;
- dist = softmin(dist, sphere(point, center, radius), 1.2);
+ let cylinder_dist = (Vector::new(0.0, point.y, point.z) - center).magnitude() - (radius - thickness / 4.0);
+ dist = cylinder_dist.abs() - thickness / 2.0; // Make cylinder hollow
}
- // Hole
+ // Teeth
{
- let center = Vector { x: 4.0, y: 0.0, z: 0.0 };
- let size = Vector::new(5.0, 2.0, 2.0);
- dist = dist.max(-r#box(point, center, size));
- }
+ let center = Vector { x: 0.0, y: radius + thickness / 2.0, z: 0.0 };
+ let size = Vector::new(thickness, thickness * 2.0, thickness);
- // Windows
- {
- let center = Vector { x: 4.0, y: 0.0, z: 0.0 };
- let size = Vector::new(1.0, 5.0, 1.0);
- dist = dist.max(-(r#box(point, center, size)));
+ let sector_angle = Rad::full_turn() / 12.0;
+ let point_angle = (point.z / point.y).atan();
+ let sector = (point_angle / sector_angle.0).round();
+ let mut mapped_point = Matrix3::from_angle_x(-sector_angle * sector) * point;
+ mapped_point.y = mapped_point.y.abs();
+
+
+ // Make teeth smooth by subtracting some amount
+ dist = dist.min(sd_box(mapped_point, center, size) - thickness / 4.0);
}
- return dist
+ // Tak a slice
+ dist = dist.max(point.x.abs() - thickness / 2.0);
+
+ return dist;
+ }
+ pub fn sdf(&self, point: Vector) -> f32 {
+ self.sd_gear(point, Vector::zero(), 3.0, 0.6)
}
pub fn screen(&self) -> (f32, f32) {
@@ -157,7 +161,7 @@ impl Camera {
while dist < 10.0 && count < 30 {
count += 1;
dist = self.sdf(point);
- if dist < threshold {
+ if dist.abs() < threshold {
return Some(point);
}
point += ray * dist;
@@ -174,7 +178,7 @@ impl Camera {
pub fn diffuse_lighting(&self, point: Vector) -> f32 {
let mut res: f32 = 1.0;
let mut ph = 1e20;
- let mut t = 0.1;
+ let mut t = 0.001;
let k = 4.0;
while t < 7.0 {
diff --git a/src/main.rs b/src/main.rs
index b288918..2574746 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -10,7 +10,7 @@ use crate::camera::{Buffer, Camera, WIDTH, HEIGHT};
fn main() {
let mut cam = Camera {
- position: Vector3::zero(),
+ position: Vector3::new(-5.0, 0.0, 2.0),
direction: Vector3::unit_x(),
up: Vector3::unit_z(),
light: Vector3 { x: 1.0, y: 1.0, z: -1.0 }.normalize(),