Colliders#
A collider lets geometry participate in collision. It is the base that rigid
bodies and articulation links build on. Apply PhysicsCollisionAPI to a
geometry prim and the collision representation is created implicitly from the USD
geometry. If the collider prim (or an ancestor) has PhysicsRigidBodyAPI, the
collider moves with that dynamic body; otherwise it is static.
This page covers authoring colliders for scenes that ovphysx loads. For the base
authoring pattern (core UsdPhysics typed APIs plus codeless PhysX schemas), see
Physics Schemas; for the physics scene and ground, see
Physics Scene.
Static Colliders#
A collider with no rigid body on it or above it is static: it does not move, but dynamic bodies rest on and bounce off it (this is how a ground is authored).
def Cube "ground" (
prepend apiSchemas = ["PhysicsCollisionAPI"]
)
{
double size = 100
}
from pxr import UsdGeom, UsdPhysics
cube = UsdGeom.Cube.Define(stage, "/World/ground")
cube.CreateSizeAttr(100.0)
UsdPhysics.CollisionAPI.Apply(cube.GetPrim())
Primitive Colliders#
The following UsdGeom primitives are supported with PhysicsCollisionAPI, and
the resulting collision shape maps to the geometry exactly: Sphere, Cube,
Capsule, Cylinder, Cone. Primitives are the cheapest and most stable
choice — prefer them whenever they approximate the object well.

from pxr import UsdGeom, UsdPhysics
sphere = UsdGeom.Sphere.Define(stage, "/World/sphere")
sphere.CreateRadiusAttr(2.0)
UsdPhysics.CollisionAPI.Apply(sphere.GetPrim())
Boxes are authored as a Cube with non-uniform scale; capsules, cylinders, and
cones take radius, height, and axis attributes.
Rounded Cones and Cylinders#
A cone or cylinder can be given a rounded edge with a positive convex margin (a PhysX-specific, codeless attribute):
from pxr import Sdf
cylinder_prim.CreateAttribute("physxConvexGeometry:margin", Sdf.ValueTypeNames.Float).Set(0.1)
Cones and cylinders can also be approximated with convex meshes, which ignores
the margin but is often faster (prefer it unless you need smooth rolling
behavior). In ovphysx this is controlled per instance through PhysXConfig:
from ovphysx import PhysX, PhysXConfig
# Approximate cylinders/cones with convex meshes instead of exact custom geometry.
physx = PhysX(config=PhysXConfig(
collision_cylinder_custom_geometry=False,
collision_cone_custom_geometry=False,
))
Mesh Colliders#
Mesh colliders (UsdGeom.Mesh with PhysicsCollisionAPI) require an
approximation, chosen with PhysicsMeshCollisionAPI’s
physics:approximation attribute:
none,meshSimplification— full / simplified triangle mesh. Valid only for static or kinematic bodies, not dynamic ones.convexHull— a single convex hull. For dynamic bodies with a roughly convex shape.convexDecomposition— several convex hulls. For dynamic bodies with a non-convex shape.boundingSphere,boundingCube— a coarse, cheap primitive bound.sdf— a signed distance field, for dynamic bodies needing high-detail non-convex contact (refer to SDF Colliders).

A dynamic rigid body cannot use a plain triangle mesh (
none/meshSimplification). Use a convex approximation, convex decomposition, or SDF. Triangle meshes are for static or kinematic geometry.
from pxr import UsdGeom, UsdPhysics
mesh = UsdGeom.Mesh.Define(stage, "/World/mesh")
mesh.CreateFaceVertexCountsAttr(vertex_counts)
mesh.CreateFaceVertexIndicesAttr(indices)
mesh.CreatePointsAttr(points)
UsdPhysics.CollisionAPI.Apply(mesh.GetPrim())
mesh_collision = UsdPhysics.MeshCollisionAPI.Apply(mesh.GetPrim())
mesh_collision.CreateApproximationAttr(UsdPhysics.Tokens.convexHull)
Merging Multiple Meshes#
PhysxMeshMergeCollisionAPI (codeless) applied to an Xformable prim defines a
collection of meshes that are merged into a single collider before the
approximation is computed. The source meshes can be sourced from anywhere in the
stage. If some of the collection’s meshes are descendants of a rigid body, only
those descendants move with the body — a natural consequence of the UsdPhysics
rule that only rigid-body transforms are updated.
SDF Colliders#
Signed-Distance-Field (SDF) collision enables dynamic and kinematic rigid bodies
with high-detail mesh colliders — the standard choice for contact-rich
interaction between highly non-convex shapes (for example robotic assembly).
Enable it by setting the mesh approximation to sdf and applying the codeless
PhysxSDFMeshCollisionAPI:
from pxr import Sdf, UsdPhysics
UsdPhysics.CollisionAPI.Apply(sdf_mesh_prim)
mesh_collision = UsdPhysics.MeshCollisionAPI.Apply(sdf_mesh_prim)
mesh_collision.CreateApproximationAttr("sdf")
sdf_mesh_prim.ApplyAPI("PhysxSDFMeshCollisionAPI")
sdf_mesh_prim.CreateAttribute("physxSDFMeshCollision:sdfResolution", Sdf.ValueTypeNames.Int).Set(300)
Notes:
Multi-material triangle-mesh colliders are not supported with SDF.
Sparse SDFs add a hierarchical structure with fewer samples far from the surface, saving memory at similar fidelity. Enable them with a nonzero
physxSDFMeshCollision:sdfSubgridResolution.

For high-throughput, on-GPU access to SDF samples and gradients at runtime, use
ovphysx’s SDF view: PhysX.create_sdf_view() in Python or
ovphysx_create_sdf_view() in C (GPU instances only). SDF views are tied to the
attached USD stage; after reset_stage() or detach_ovstage(), destroy existing
views and create replacements after re-attaching a stage.
Cooking Mesh Colliders#
Generating a collision approximation from mesh data is called cooking, and
its output is cooking data. ovphysx cooks colliders that need it when a stage
is attached, blocking until the required data is available (from cache or freshly
computed). To persist cooked results across runs, configure a cooked-collider
cache directory through PhysXConfig(cooked_collider_cache_dir=...) — refer to the
cooked-collider cache (UJITSO) section of the
Developer Guide for details.
Rest and Contact Offsets#
The contact offset and rest offset tune when and where contacts are
generated and resolved. Both are attributes of the codeless PhysxCollisionAPI
applied to a collider prim.
Contact offset — the distance from the surface at which contacts start being generated. The default auto-computes a value from gravity, timestep, and geometry extent. Increase it for fast-moving or thin objects that tunnel through each other in one step (an alternative is CCD, see Rigid Bodies). Larger offsets can cost performance because more contacts are generated.
Rest offset — a small distance from the surface at which the effective contact takes place. It may be positive, zero, or negative. A negative rest offset is useful when the collision geometry is slightly larger than the render mesh, so contact occurs at the visually correct distance.

from pxr import Sdf
prim.ApplyAPI("PhysxCollisionAPI")
prim.CreateAttribute("physxCollision:contactOffset", Sdf.ValueTypeNames.Float).Set(0.02)
prim.CreateAttribute("physxCollision:restOffset", Sdf.ValueTypeNames.Float).Set(0.0)
Contact and rest offsets can also be read/written at runtime in bulk through the
RIGID_BODY_CONTACT_OFFSET / RIGID_BODY_REST_OFFSET tensor types — refer to the
Tensor Bindings reference.
Collision Filtering#
Two mechanisms disable collision between specific colliders.
Collision Group Filtering#
Collision groups (UsdPhysicsCollisionGroup) enable or disable collision between
sets of colliders. Every collider in a group collides with every other collider,
and each group carries a list of other groups it should (or should not) collide
with. By default the lists are opt-out: every group collides with every other,
and the lists name pairs that do not collide. Setting
physxScene:invertCollisionGroupFilter on the scene inverts this to opt-in: no
pairs collide except those named.
Assign colliders to a group with a Usd.CollectionAPI (colliders collection)
on the group prim, and relate groups to filter with the group’s
filteredGroups relationship.
Pairwise Collision Filtering#
When groups are too coarse, UsdPhysicsFilteredPairsAPI disables collision
between specific stage hierarchies. Pairwise filtering takes precedence over
group filtering. The filteredPairs relationship names the hierarchies to
filter; all child objects (colliders, rigid bodies, articulations) are filtered
with the pair.
from pxr import UsdPhysics
filtered = UsdPhysics.FilteredPairsAPI.Apply(box_a_prim)
filtered.CreateFilteredPairsRel().AddTarget("/World/boxC")
Performance and Stability Tips#
Keep sizes and dimension ratios within roughly 1/100. Both the sizes of interacting colliders and the ratio of a collider’s own dimensions should stay within about two orders of magnitude to avoid floating-point instability.
Prefer primitives (sphere, capsule, box, plane) — cheapest and most stable.
Convex meshes (convex hull / decomposition) are next. For GPU compatibility, a convex mesh’s largest dimension should not exceed ~100x its insphere radius; otherwise cooking may produce a CPU-only convex that will not interact with GPU-only features (deformables, particles) and may be slower.
Cylinders and cones model wheels and similar shapes with smooth surfaces; approximate them with convex meshes if precise rolling is not required.
Triangle meshes suit large static or kinematic geometry; keep triangles evenly sized and apply the 1/100 ratio to individual triangles.
SDF meshes are best for dynamic bodies needing high-detail non-convex collision.
For deeper contact-quality tuning (GPU contact limits, mass ratios, depenetration, friction, timestep), refer to the Collision Tuning guide.
CPU / GPU Collider Compatibility#
Not every collider pair is supported in both CPU and GPU simulation. In general, CPU collision geometry generates contacts on the CPU and GPU geometry on the GPU; most geometry supports both and picks the device automatically. GPU-only features (deformables, particles) require GPU simulation. Some CPU-only geometry (for example an oblong convex hull, or a multi-material triangle mesh) still works with GPU simulation by generating contacts on the CPU, which can carry a performance penalty in large GPU scenes such as RL environments.
