Initializing 3D Canvas...

SDF Transformations & Curves

2 min read•1 page

Deformation Operators:

1. Translation / Rotation: f(T^-1(p)). Query point is shifted/rotated opposite to the desired movement. 2. Infinite Repetition: Spatial domain folding using a modulo operator mod(p, s) - 0.5s. 3. Twist / Bend: Varying the rotation angle dynamically as a function of the query point's coordinate (e.g. height y).
python
1# Modifiers work by transforming the query point 'p' in reverse
2def op_translate(p, offset):
3 return p - offset
4
5def op_repeat(p, size):
6 # Map p to local repeated cell
7 return Vector3(
8 (p.x % size) - 0.5 * size,
9 p.y,
10 (p.z % size) - 0.5 * size
11 )
12
13def op_twist(p, k):
14 # Twist angle proportional to height (y)
15 angle = p.y * k
16 c, s = cos(angle), sin(angle)
17 rx = p.x * c - p.z * s
18 rz = p.x * s + p.z * c
19 return Vector3(rx, p.y, rz)

Unlike boundary meshes, SDFs are transformed by applying the inverse transform to the query point p before evaluating the distance function. This lets us bend, twist, or duplicate geometry infinitely with zero memory overhead.

Modifier (0=Translate/Rotate, 1=Repeat, 2=Twist)
0.00
5 min read•2 pages

Projection Mathematics:

1. Segment Projection: Project query point p onto the infinite line of the segment, then clamp to the boundaries [0, 1]. 2. Bezier Closest Point: The vector from the closest point on the Bezier curve B(t) to p must be orthogonal to the tangent vector B'(t), yielding dot(B(t) - p, B'(t)) = 0.
python
1def sd_segment(p, a, b):
2 pa = p - a
3 ba = b - a
4 # Clamped projection factor
5 t = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0)
6 return length(pa - ba * t)
7
8def sd_quadratic_bezier(p, a, b, c, steps=16):
9 # Find parameter t in [0, 1] minimizing dist(p, B(t))
10 # where B(t) = (1-t)^2*a + 2(1-t)*t*b + t^2*c
11 best_t = 0.0
12 min_dist = float('inf')
13 for i in range(steps + 1):
14 t = i / steps
15 bt = (1.0 - t)**2 * a + 2.0 * (1.0 - t) * t * b + t**2 * c
16 d = length(p - bt)
17 if d < min_dist:
18 min_dist, best_t = d, t
19
20 # Refine root of dot(B(t) - p, B'(t)) = 0 via Newton-Raphson
21 t = best_t
22 for _ in range(4):
23 bt = (1.0 - t)**2 * a + 2.0 * (1.0 - t) * t * b + t**2 * c
24 d1 = 2.0 * (1.0 - t) * (b - a) + 2.0 * t * (c - b)
25 d2 = 2.0 * (c - 2.0 * b + a)
26 denom = dot(d1, d1) + dot(bt - p, d2)
27 if abs(denom) > 1e-8:
28 t = clamp(t - dot(bt - p, d1) / denom, 0.0, 1.0)
29
30 closest_pt = (1.0 - t)**2 * a + 2.0 * (1.0 - t) * t * b + t**2 * c
31 return length(p - closest_pt)

Calculating distances to curves is essential for outline rendering and wireframe effects. A line segment has a straightforward projection calculation. A quadratic Bezier curve is more complex, requiring us to solve a cubic equation to find the closest point.

Curve Type (0=Line Segment, 1=Bezier Curve)
0.00
Query Point X
0.50

Related Concepts