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#
- Nearest edge query — query the edge BVH
- Intersection API — full intersection reference