RAGBAZRAGBAZ
sections
home pricing
learn
school face lesson game search docs
demos
face demo glither wasm
governance
buyer page formal spec
schoolcomputer vision

Face Mesh Morphing Techniques

Face morphing looks like image blending, but the convincing version is geometry first: stable face points, a shared triangle topology, and texture coordinates that move with the expression.

landmarks Delaunay mesh interpolation dual UVs debugging

Face Points

A face mesh begins as landmark points. Each point marks a stable semantic place on the face: a mouth corner, eyelid edge, brow ridge, nose bridge, cheek contour, or jaw point.

Most browser pipelines store those points in normalized image space so the same data works for any render size.

x: 0.0 left  -> 1.0 right
y: 0.0 top   -> 1.0 bottom
z: relative depth

The critical rule is point-index identity. Point 61 in expression A and point 61 in expression B must mean the same anatomical point, or the morph will twist.

Interactive Mesh Lab

Scrub between two real expression tiles. The compact teaching mesh uses only 19 landmarks, but it preserves the same three invariants as the full 478-point model: landmark identity, shared triangle indices, and source-specific texture coordinates.

Interactive face landmark morph Two expression images blend while a shared landmark mesh interpolates between their facial features.
t = 0.00

Every triangle keeps the same three landmark indices while its corners move. This is shared topology.

source A100%
source B0%
teaching mesh19 points / 24 faces

From Points To Triangles

A renderer cannot draw a cloud of points as a face surface. It needs triangles, and the same triangle list should be reused for every expression.

Stable topologyTriangle indices stay constant between expressions, keeping eyebrows, lips, and jawlines from reconnecting during animation.
Local motionEach triangle carries nearby texture detail, so a smile can move the mouth without dragging the whole image sheet.

Voronoi And Delaunay Intuition

A Voronoi diagram answers: which landmark owns each patch of nearby image space? Its dual, the Delaunay triangulation, connects landmarks so triangle edges tend to avoid long skinny slivers.

That matters for faces because skinny triangles stretch texture aggressively. Delaunay-style connectivity gives better local neighborhoods for cheeks, lips, and eyes.

Morphing Positions

The simplest morph is linear interpolation. At time t, each vertex is somewhere between expression A and expression B.

P(t) = A + (B - A) * t

When every landmark index is consistent, the whole face appears to change expression. When an index is wrong, a lip vertex may jump into an eyelid or a cheek can fold through the mouth.

Worked vertex

Suppose one mouth corner moves from A = (0.37, 0.61) to B = (0.42, 0.56). At t = 0.25, it has completed one quarter of that motion.

x coordinate0.37 + 0.25(0.05) = 0.3825
y coordinate0.61 + 0.25(-0.05) = 0.5975
resultP(0.25) = (0.3825, 0.5975)

Texture Coordinates And Dual UVs

Geometry motion is only half the trick. The shader also needs to sample each source texture at the correct landmark coordinates. The face viewer keeps two UV attributes: one for expression A and one for expression B.

color = mix(textureA(uvA), textureB(uvB), t)

This is why the texture follows the face points instead of sliding over a static rectangle. The destination mouth texture is sampled from the destination mouth coordinates, even while the geometry is halfway through the morph.

Transforms

Normalized image points must be transformed into the coordinate system used by the canvas or Three.js scene. A common mapping centers the face and flips the Y axis so screen coordinates become world coordinates.

world_x = (x - 0.5) * 2
world_y = -(y - 0.5) * 2
world_z = z * depth_scale

Scale, rotation, and translation are then safe to expose as controls because they operate on the mesh after the landmark topology has been built.

Checkpoint

Try to answer each question before opening the explanation.

Why not triangulate every expression independently?

Independent triangulations can connect different landmark indices. Interpolation then changes both vertex positions and surface connectivity, producing folds and texture jumps. One shared triangle list keeps connectivity invariant.

Why are two UV sets needed if there is only one moving mesh?

The same vertex refers to different pixel locations in the two source images. uvA samples the feature in expression A and uvB samples its matching feature in expression B; the shader blends those two samples.

A mouth shape moves correctly, but its color slides across the cheek. Which data should you inspect?

Inspect the UV attributes and source image dimensions. Correct geometry with sliding texture usually means the vertex positions are right but one texture is sampled with the wrong coordinates or scale.

Debugging Checklist

  • Draw the points before drawing triangles.
  • Toggle wireframe to inspect topology during the blend.
  • Check the same landmark index on both expressions.
  • Verify UVs against both source images, not just the current geometry.
  • Keep privacy boundaries explicit: this is a morphing demo, not identity verification.

Transfer exercise

  1. Open face.ragbaz.cc and choose two expressions with a large mouth or brow difference.
  2. Scrub slowly, then enable wireframe. Identify one region whose triangles move locally and one region that barely moves.
  3. Swap A and B. The same triangle indices should now travel in reverse without reconnecting.

For the production data flow and shader contract, continue to the Atlas experiment notes.