summaryrefslogtreecommitdiff
path: root/src/3d/sdf_cpu.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/3d/sdf_cpu.h')
-rw-r--r--src/3d/sdf_cpu.h55
1 files changed, 55 insertions, 0 deletions
diff --git a/src/3d/sdf_cpu.h b/src/3d/sdf_cpu.h
new file mode 100644
index 0000000..1e461f6
--- /dev/null
+++ b/src/3d/sdf_cpu.h
@@ -0,0 +1,55 @@
+// This file is part of the 64k demo project.
+// It implements CPU-side Signed Distance Field (SDF) primitives
+// and utilities for physics and collision detection.
+
+#pragma once
+
+#include "util/mini_math.h"
+#include <algorithm>
+#include <cmath>
+
+namespace sdf {
+
+inline float sdSphere(vec3 p, float r) {
+ return p.len() - r;
+}
+
+inline float sdBox(vec3 p, vec3 b) {
+ vec3 q;
+ q.x = std::abs(p.x) - b.x;
+ q.y = std::abs(p.y) - b.y;
+ q.z = std::abs(p.z) - b.z;
+
+ vec3 max_q_0;
+ max_q_0.x = std::max(q.x, 0.0f);
+ max_q_0.y = std::max(q.y, 0.0f);
+ max_q_0.z = std::max(q.z, 0.0f);
+
+ return max_q_0.len() + std::min(std::max(q.x, std::max(q.y, q.z)), 0.0f);
+}
+
+inline float sdTorus(vec3 p, vec2 t) {
+ vec2 p_xz(p.x, p.z);
+ vec2 q(p_xz.len() - t.x, p.y);
+ return q.len() - t.y;
+}
+
+inline float sdPlane(vec3 p, vec3 n, float h) {
+ return vec3::dot(p, n) + h;
+}
+
+/**
+ * Calculates the normal of an SDF at point p using numerical differentiation.
+ * sdf_func must be a callable: float sdf_func(vec3 p)
+ */
+template <typename F>
+inline vec3 calc_normal(vec3 p, F sdf_func, float e = 0.001f) {
+ const float d2e = 2.0f * e;
+ return vec3(
+ sdf_func(vec3(p.x + e, p.y, p.z)) - sdf_func(vec3(p.x - e, p.y, p.z)),
+ sdf_func(vec3(p.x, p.y + e, p.z)) - sdf_func(vec3(p.x, p.y - e, p.z)),
+ sdf_func(vec3(p.x, p.y, p.z + e)) - sdf_func(vec3(p.x, p.y, p.z - e)))
+ .normalize();
+}
+
+} // namespace sdf