Skip to content

Raycasting

Raycasting casts a ray into the scene and reports what it meets — the shape, the exact point, the face, its normal and its texture coordinate. Pointer events raycast too, but only ever answer which shape; this is how you get the rest.

NOTE

For the full API, see the 3D API Reference.

Demo

Casting a ray

context.raycast(x, y) builds the world-space ray through a point on the surface, in the same logical CSS pixels the pointer reports. It is correct under both perspective and orthographic projection — an orthographic ray is parallel to the view direction rather than fanning from an eye point.

ts
const ray = context.raycast(pointerX, pointerY);

context.raycastAll(scene, x, y) casts that ray and returns every shape it meets, nearest first, reaching through nested groups.

ts
const hits = context.raycastAll(scene, pointerX, pointerY);

A single shape can be tested directly:

ts
const hit = torus.raycast(ray, { backFaces: false });

What a hit reports

  • element: the shape that was hit
  • distance: distance along the ray, in world units
  • point: the world-space point of the hit
  • face: the face that was hit
  • faceIndex: its index within the shape's face list
  • normal: the world-space surface normal, interpolated when the face carries vertex normals
  • uv: the texture coordinate at the hit, when the face carries UVs
  • backFacing: whether the triangle was met from behind

Why not just use pointer events

3D shapes support the ordinary pointer events, and for most interactions those are the right tool — they need no wiring, and they raycast too: a pointer over the hole of a torus passes through it, and where two parts overlap the nearer one wins.

What they cannot give you is the hit itself. mouseenter says that a shape was hit, not where, on which face, at what texture coordinate, or how far along the ray. Reach for raycast when you need any of that — placing a marker on a surface, reading a value off a plot, aligning something to the normal at the hit — or when you want to query the scene without a pointer at all.

Two things pointer events do not honour, because they have no meaning for a solid: pointerEvents: 'fill' and 'stroke' are both treated as 'all'. 'none' still opts a shape out entirely.