summaryrefslogtreecommitdiff
path: root/tools/editor/sdf.js
blob: c68d79a59004fc139e36af837ebd9608ebf13428 (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
// --- Signed Distance Functions (SDFs) ---
// Generic 2D vector operations
function vec2(x, y) { return { x: x, y: y }; }
function length(v) { return Math.sqrt(v.x * v.x + v.y * v.y); }
function dot(v1, v2) { return v1.x * v2.x + v1.y * v2.y; }
function sub(v1, v2) { return vec2(v1.x - v2.x, v1.y - v2.y); }
function mul(v, s) { return vec2(v.x * s, v.y * s); }
function div(v, s) { return vec2(v.x / s, v.y / s); }
function normalize(v) { return div(v, length(v)); }
function clamp(x, minVal, maxVal) { return Math.max(minVal, Math.min(x, maxVal)); }
function abs(v) { return vec2(Math.abs(v.x), Math.abs(v.y)); }
function max(v1, v2) { return vec2(Math.max(v1.x, v2.x), Math.max(v1.y, v2.y)); }
function sign(x) { return (x > 0) ? 1 : ((x < 0) ? -1 : 0); }

// sdSegment(p, a, b) - signed distance to a line segment
// p: point, a: segment start, b: segment end
function sdSegment(p, a, b) {
    const pa = sub(p, a);
    const ba = sub(b, a);
    const h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);
    return length(sub(pa, mul(ba, h)));
}

// sdEllipse(p, r) - signed distance to an ellipse (p relative to center, r is half-extents)
// p: point relative to ellipse center, r: half-extents (rx, ry)
function sdEllipse(p, r) {
    const k0 = vec2(1, length(div(p, r)));
    const k1 = vec2(length(div(p, r)), 1);
    const f = ((dot(div(mul(p, p), k0), vec2(1, 1)) < dot(div(mul(p, p), k1), vec2(1, 1))) ? k0 : k1);
    return length(sub(p, mul(r, normalize(mul(f, p))))) * sign(length(p) - r.x); // Simplified, original has length(p)-r.x which is only for circular
}

// sdBox(p, r) - signed distance to a rectangle (p relative to center, r is half-extents)
// p: point relative to box center, r: half-extents (hx, hy)
function sdBox(p, r) {
    const q = sub(abs(p), r);
    return length(max(q, vec2(0, 0))) + Math.min(0.0, Math.max(q.x, q.y));
}