PhysX does not expose an overlap volume API – the PhysXSceneQuery overlap methods (overlap_box, overlap_mesh, etc.) return hit count or boolean, not volume. There is an internal feature request for this, but it is not available yet.
One note on @rasmus.larsson’s suggestion: the mass/density trick gives you the total volume of a single prim – useful on its own, but not the intersection volume of two prims, which is what the original question asks for.
Workaround: trimesh boolean intersection
For the actual overlap volume, the cleanest approach is a mesh boolean intersection using trimesh. trimesh 4.5.2 is bundled with Isaac Sim 6.1.0 (via the IRI pip_prebundle), and you can install the manifold3d backend separately:
pip install manifold3d
Then extract the mesh geometry from your USD prims and compute the intersection:
from pxr import UsdGeom
import trimesh
import trimesh.boolean
import numpy as np
def usd_mesh_to_trimesh(stage, prim_path):
prim = stage.GetPrimAtPath(prim_path)
mesh = UsdGeom.Mesh(prim)
pts = np.array(mesh.GetPointsAttr().Get())
face_counts = np.array(mesh.GetFaceVertexCountsAttr().Get())
face_indices = np.array(mesh.GetFaceVertexIndicesAttr().Get())
# Triangulate: assumes all-triangle mesh; for quads, split each quad into two tris
faces = face_indices.reshape(-1, 3)
return trimesh.Trimesh(vertices=pts, faces=faces)
mesh_robot = usd_mesh_to_trimesh(stage, "/World/Robot")
mesh_zone = usd_mesh_to_trimesh(stage, "/World/Zone")
intersection = trimesh.boolean.intersection([mesh_robot, mesh_zone], engine="manifold")
print("Overlap volume:", intersection.volume)
Requirement: both meshes must be watertight (closed surfaces). If the robot mesh has open
surfaces, trimesh.repair.fill_holes(mesh) can help.
Alternative: voxelization (no extra deps, approximate)
If you cannot install manifold3d, voxelization gives an approximate result with controllable
precision (via the pitch parameter):
pitch = 0.005 # voxel size in stage units; smaller = more accurate, slower
vox_robot = mesh_robot.voxelized(pitch=pitch)
vox_zone = mesh_zone.voxelized(pitch=pitch)
overlap = vox_robot.intersection(vox_zone)
print("Overlap volume (approx):", overlap.volume)
Analytic shortcut (cube zone)
Since your zone is an axis-aligned cube, you can skip the full boolean and instead clip the
robot mesh triangles directly against the cube’s AABB. This avoids the manifold requirement
entirely, but is more code. The trimesh approach above is simpler for most cases.
Closing this topic since the PhysX status has been answered and workarounds are available.
If the native PhysX feature ships in a future release, we will update the docs.