summaryrefslogtreecommitdiff
path: root/src/3d/sdf_cpu.h
blob: 1e461f68dc2965eb24a07bc74706f8791331f65d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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