Skip to main content

closestPoint: Triangle Surface Projection

Point-to-Triangle Distance Minimization

The closestPoint function finds the point on a triangle surface that minimizes distance to any given position in 3D space. This operation involves projecting the query point onto the triangle plane and testing barycentric coordinates to determine the final position.

The algorithm follows a systematic approach:

  1. Plane Projection: Projects the input point onto the triangle plane using the surface normal
  2. Barycentric Testing: Computes barycentric coordinates to determine if the projection lies within triangle bounds
  3. Edge Clamping: When projection falls outside triangle boundaries, clamps to the nearest edge segment

For triangle vertices AA, BB, CC and query point PP, the projected point PP' is computed as:

P=Pn,PAnP' = P - \langle \mathbf{n}, P - A \rangle \mathbf{n}

where n=(CA)×(BA)(CA)×(BA)\mathbf{n} = \frac{(C-A) \times (B-A)}{||(C-A) \times (B-A)||} is the unit normal vector.

The barycentric coordinates (α,β,γ)(\alpha, \beta, \gamma) determine the final result:

  • If all coordinates are non-negative: P=αA+βB+γCP' = \alpha A + \beta B + \gamma C
  • If any coordinate is negative: clamp to the nearest edge using parametric line projection
Live Editor
const fragment = () => Scope(() => {
      const tri = Triangle({
              a: vec3(-0.4, -0.3, 0),
              b: vec3(0.4, -0.3, 0),
              c: vec3(0, 0.5, 0)
      })
      const testPos = vec3(uv.mul(2).sub(1), 0)
      const nearest = closestPoint(tri, testPos)
      const distField = testPos.sub(nearest).length().mul(4)
      const red = distField.saturate()
      const green = nearest.x.add(0.5).saturate()
      const blue = nearest.y.add(0.5).saturate()
      return vec4(red, green, blue, 1)
})