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
56
57
|
// 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
|