Ray-mesh intersection

Trace custom rays against a triangle mesh and read hit geometry

Overview#

This tutorial walks through building a scene, constructing a batch of rays, and reading intersection results including hit point, distance, and primitive IDs.

Build the Scene#

import rayd as rd
import drjit as dr
 
rd.set_device(0)
 
mesh = rd.Mesh(
    dr.cuda.Array3f(
        [-1.0, 1.0, 1.0, -1.0],
        [-1.0, -1.0, 1.0, 1.0],
        [3.0, 3.0, 3.0, 3.0],
    ),
    dr.cuda.Array3i([0, 0], [1, 2], [2, 3]),
)
 
scene = rd.Scene()
scene.add_mesh(mesh)
scene.build()

The mesh has four vertices forming a quad at z=3. The two triangles share the diagonal from vertex 0 to vertex 2.

Trace Rays#

rays = rd.Ray(
    dr.cuda.Array3f(
        [0.0, 0.75, 1.5, -0.5],
        [0.0, 0.75, 0.0, -0.5],
        [-1.0, -1.0, -1.0, -1.0],
    ),
    dr.cuda.Array3f(
        [0.0, 0.0, 0.0, 0.0],
        [0.0, 0.0, 0.0, 0.0],
        [1.0, 1.0, 1.0, 1.0],
    ),
)
 
its = scene.intersect(rays)

All four rays point in the +z direction. Rays 0 and 1 hit the quad, ray 2 misses (x=1.5 is outside the quad), and ray 3 hits.

Read Results#

for i, valid in enumerate(list(its.is_valid())):
    if valid:
        point = [float(its.p[axis][i]) for axis in range(3)]
        print(
            f"ray[{i}] hit: t={float(its.t[i]):.4f}, "
            f"shape_id={int(its.shape_id[i])}, "
            f"prim_id={int(its.prim_id[i])}, "
            f"p={point}"
        )
    else:
        print(f"ray[{i}] miss")

Backpropagate Through Intersection#

To differentiate the hit distance with respect to vertex positions:

verts = dr.cuda.ad.Array3f(
    [0.0, 1.0, 0.0],
    [0.0, 0.0, 1.0],
    [0.0, 0.0, 0.0],
)
dr.enable_grad(verts)
 
mesh = rd.Mesh(
    dr.cuda.Array3f([0.0, 1.0, 0.0], [0.0, 0.0, 1.0], [0.0, 0.0, 0.0]),
    dr.cuda.Array3i([0], [1], [2]),
)
mesh.vertex_positions = verts
 
scene = rd.Scene()
scene.add_mesh(mesh)
scene.build()
 
ray = rd.Ray(
    dr.cuda.ad.Array3f([0.25], [0.25], [-1.0]),
    dr.cuda.ad.Array3f([0.0], [0.0], [1.0]),
)
 
its = scene.intersect(ray)
loss = dr.sum(its.t)
dr.backward(loss)
 
print("grad z =", dr.grad(verts)[2])

Next Steps#