Changelog#
All notable changes to ovphysx are documented in this file.
[0.7.0] - Date 2026-10-14#
API, ABI and package migration required. Rebuild native consumers against the 0.7.0 headers. Lifecycle and session calls return task receipts whose outcomes must be collected; Python’s synchronous read/write conveniences now use
*_syncnames. Replacereset_stage()with detach followed by a successful wait, and move raw contact-report consumers to contact sessions. Install and registerphysx-usd-schemasseparately. See the 0.6 to 0.7 migration guide and the breaking changes below for configuration, schema and removed-API replacements.
Added#
Contact sensing is available through query/read sessions.
ovphysx_query_contacts()and PythonContactSelectionpair sensor and filter selections. Read net normal and friction forces, force matrices, filtered contact detail, raw contacts andcontactEvent*payloads throughCONTACT_SENSORqueries. Arrays fit the current step’s contacts without a caller-supplied capacity; detailed events remain unavailable on DirectGPU. A reporting collider can have its own row on host scenes, overlapping its body’s aggregate row: do not sum both. ApplyPhysxContactReportAPIto a selected child collider and enable reporting on its owning body, link or articulation root. On DirectGPU, separate child rows are omitted and standalone static sensors read zero force. See Contact sensors.Read and write queries can select a subset of prims. Use
ovphysx_query_selection()or theprim_paths/patternarguments ofPhysX.query(),read_sync(),read_tokens_sync()andwrite_sync().prim_pathscontains interned path handles and takes precedence over a pattern. Selections include sleeping objects, cannot be combined with Pythonscope=ObjectScope.ACTIVE, and may validly match no objects.Vehicle controls and telemetry use the session API. Query whole vehicles for managed controls and transmission state, chassis rigid bodies for pose and velocity, and wheel attachments for telemetry or raw-wheel controls.
resetToRestStateis a one-time command; requested controls are distinct from actual state. Vehicle columns are host-resident and unavailable on DirectGPU.Capsule character controllers accept session movement commands. Write a world-space displacement to
moveonCHARACTER_CONTROLLER; each commit applies it once. A zero displacement still follows a moving platform, and rigid-body pose reads reflect the movement after the next simulation step. DirectGPU movement is unsupported.Articulation reads expose topology and DOF identity. Read
dofCount,linkCount,jointCount,fixedTendonCount,spatialTendonCountandisFixedBase, including mixed articulation topologies.dofJointPathanddofAxisIndexmap each DOF to its joint and axis; floating-base inverse-dynamics matrices place these DOFs after six root columns. DOF rows are padded to the widest articulation in the group.Rigid-body and volume-deformable kinematic targets are accessible through sessions.
kinematicTargetPositionandkinematicTargetOrientationdrive rigid bodies on CPU and GPU scenes with readback; updating one preserves the other, and reads without a pending target return the current pose. DirectGPU rigid-body writes are rejected, and articulation-link targets are read-only. Volume-deformablekinematicTargetprovides simulation-mesh-local positions and an active flag per node, including on DirectGPU; freeing every node removes the drive. Reads include only driven bodies, and surface deformables do not support the attribute.Sessions expose sleep state and wake/sleep commands. Read
isSleepingfor rigid bodies or articulation links; links report their articulation’s state, and scenes with sleeping disabled, including DirectGPU, report zero. Writewakeon rigid bodies with nonzero to wake or zero to sleep. These writes reject DirectGPU and articulation links and skip kinematic or simulation-disabled bodies. Use all-object scope or an explicit selection to include sleeping bodies.SDF shapes can be evaluated through a query.
ovphysx_evaluate_sdf_shapes()andPhysX.evaluate_sdf_shapes()write gradients and signed distances for caller-supplied points into a GPU buffer. Points and gradients use each shape’s mesh space. This DirectGPU-only path replaces deprecated SDF views; a query must stay within one scene and each evaluation supports at most 65,535 shapes. Native callers includeovphysx_geometry_query.hexplicitly.Profiling supports Chrome trace output and covers every public C call. Select
OVPHYSX_PROFILER=traceornvtxbefore creating the first instance, or setGlobalConfigKey.PROFILER_BACKEND. SetOVPHYSX_PROFILER_OUTPUTfor the trace destination. Traces are written when the last instance shuts down and include API, runtime and SDK zones; SDK phases spanning threads are omitted under both backends.Optional companion services support legacy physics extension workflows. Services cover inspection, queries, events, interaction, copied-data cooking, mass and attachment authoring, and preview. Optional Python utilities use application-provided USD. Event polling reports lost history explicitly; custom joint and geometry access requires separate, build-matched SDK headers.
Changed#
The bundled simulation engine advances to PhysX 5.12. Deformable collision filtering, attachments and material reuse have corrected behavior, alongside joint force/torque reporting and material-limit and scene-query fixes. Existing scenes can produce different collision and material responses.
TGS applies external forces every position iteration by default.
physxScene:enableExternalForcesEveryIterationnow defaults totrueand is deprecated. Scenes that did not author it can produce different trajectories, including more accurate free-fall displacement. Authorfalseto retain once-per-step application while the attribute remains supported; PGS behavior is unchanged.Several instances can keep independent stages attached. Each instance holds at most one live stage, and the same stage cannot be attached twice. Reads and writes on one instance can complete while another instance steps. Detach and destruction preserve other instances. Queries, subscriptions and retained errors belong to their owner; subscriptions and debug-render settings survive its stage replacement, except stage-specific debug scope tokens. CPU-only policy, tolerance scale and recording transport remain process-wide.
Successful object-change unsubscription waits for callbacks to finish. After
ovphysx_unsubscribe_object_changes()succeeds, the subscription will no longer accessuser_data. Unsubscribing from that same callback returnsINVALID_STATEand leaves it active. Drop cached native pointers before the matching destroy callback returns; refresh caches after cloning, which does not emit object-change notifications.OVStage advances to the 0.3 line. Python and native applications must use the matching wheel and SDK dependencies. Native SDK applications can use the supplied fetcher and shared download cache; Python installs the separately pinned wheel. Population shared with rendering retains the authored physics types and point-instancer prototype targets.
Additional legacy families emit deprecation warnings. Scene queries, SDF views and
ovphysx_get_object_type()join tensor and contact bindings in the legacy headers.ovphysx.hstill includes those declarations, and Python methods remain available. Prefer session APIs where a replacement exists; see Migrating off Tensor Bindings.Recording exports use consistent OVD names. Use
ovphysx_ovd_start_recording(),ovphysx_ovd_stop_recording()andovphysx_ovd_is_recording(). The old exports andovphysx_handle_tremain deprecated aliases; new native code usesovphysx_instance_handle_t. Python recording method names are unchanged.
Fixed#
Linux shutdown preserves host exit callbacks and buffered output. A balanced
ovphysx_initialize()/ovphysx_shutdown()lifecycle no longer skips earlier host exit callbacks or leaves buffered files empty. Destroy all instances before shutdown. Windows hosts, and Linux hosts that load independent libraries with terminating exit handlers, must still flush output explicitly.Repeated SDK lifecycles preserve logging and clean up caches safely. Log callbacks and source filtering continue to work after shutdown and reinitialization. Private cooking caches remain available until their background writers stop: Linux removes them at SDK shutdown, while Windows attempts removal at normal process exit. Windows cache cleanup remains best-effort and may require normal temporary-directory cleanup.
CPU-only stage population works without an available CUDA device. Populating a CPU-only stage no longer enters a CUDA-dependent update path. GPU-backed stages continue to require CUDA.
Attach again rejects stages when ovstage reports missing PhysX schemas. Register both resource directories from the external
physx-usd-schemaspackage before the first USD schema read (population or export) in each process, including workers. A refusal requires a process restart with correct registration; the legacy/ovphysx/schemas/requireRegistration = falsesetting permits attach with a warning but does not restore dropped settings.GPU contact generation avoids invalid memory access. Sphere contacts at heightfield boundary edges no longer trigger CUDA errors. Exhausted contact or force buffers discard contacts that do not fit instead of publishing invalid data; overflow diagnostics remain.
CPU continuous collision detection preserves valid later impacts. A fast-moving body no longer passes through a triangle mesh when an earlier grazing hit is rejected.
Live stage edits preserve unrelated simulated motion. Moving a kinematic body no longer freezes falling bodies during GPU hierarchy updates. Adding visual children or refreshing unchanged prim types also preserves existing body poses and velocities.
Moving a body between physics scenes no longer duplicates read rows. Whole-body position and velocity reads return each body once, including transfers into an initially empty scene.
Re-enabling gravity wakes sleeping articulations. Applying
physxRigidBody:disableGravity = falsethrough a live stage update now starts the articulation moving; disabling gravity preserves sleep.Live GPU particle position updates reach the simulation. Vector arrays are no longer silently ignored when read from OVStage.
Instanced colliders use their prototype’s authored density. Mass and inertia calculations now honor collider density at attachment and after later mass-property edits. Explicit instance values retain precedence.
Deformables retain authored rest offsets with automatic contact offsets. Volume and surface deformables no longer replace
physxCollision:restOffsetwith its default in this case. Equal explicit contact and rest offsets preserve the rest offset and raise the contact offset with a diagnostic.Local-space velocities on point-instanced bodies are mapped consistently. With
physics:localSpaceVelocitieson a prototype, linear and angular instance velocities use the instance’s current world frame at load and after edits. Linear velocity is scaled then rotated; angular velocity is rotated only. Writing velocity back to the instancer arrays uses the inverse mapping. Read-session velocities remain world-space. See Local-space instance velocities.Fixed-tendon gearing beyond ±π is converted instead of discarded. A revolute fixed-tendon axis whose
gearingexceeded ±π could make the articulation non-finite on its first step. Gearings now convert across the documented range; values too large to represent after degrees-to-radians conversion saturate with a warning identifying the axis and joint.Selected material writes preserve other shapes and untouched properties. Session friction or restitution writes no longer change unselected shapes sharing the material. Tensor-binding writes preserve damping, combine modes and material flags. At the material limit or without an active scene, writes report failure instead of crashing; affected shapes retain their materials, although earlier rows may already have changed.
Articulation link forces reach the intended links. Indexed tensor writes handle mixed articulation sizes and reordered GPU indices correctly. Separate DirectGPU session writes to different articulations before a step no longer clear the forces or torques written by earlier sessions.
GPU tendon updates affect the next simulation step. Fixed and spatial tendon stiffness, damping, limit stiffness and offset, along with attachment coefficients and rest lengths, no longer read back successfully while leaving the GPU solver unchanged. The earlier wake-up workaround is no longer needed.
Retained accelerations no longer corrupt subsequent TGS steps. On GPU rigid bodies, one-time impulses and velocity changes are no longer replayed as persistent forces. CPU articulation links also retain the intended accelerations, correcting motion under gravity when acceleration retention and per-iteration external forces are enabled.
GPU articulation contacts and spherical-joint drives are corrected. Scenes with more than 32 articulations and an articulation exceeding 64 links no longer suffer incorrect or nondeterministic contact responses from this case. Spherical-joint drives with performance envelopes use the correct joint effort, avoiding missed targets and incorrectly applied effort limits.
Failed SDK initialization leaves other live instances usable. Invalid stage units and initialization failures produce errors instead of crashes or partially initialized state. Correct the stage and retry attachment after collecting the failed task’s outcome.
Disabled deformables no longer crash filtered-pair creation. Collision filtering skips disabled deformables that have no simulation object.
Raycasts and sphere sweeps tolerate invalid mesh material indices. A hit whose triangle refers outside the shape’s material table still returns the hit with an empty material identity and an error, instead of crashing.
Local linear velocity respects non-uniform scale before rotation. Loading and live velocity edits now scale in local axes before converting to world space. Rotated, non-uniformly scaled bodies therefore move in the intended direction and at the intended speed.
Live Newton joint edits reach the simulation. Changes to
newton:armature,newton:frictionandnewton:dampingwere applied at load but ignored on a live stage. Per-axisPhysxJointAxisAPIvalues retain precedence, and removing that API at runtime restores the Newton values.Cloned contact sensors follow the originals’ eligibility rules. The exact selected object must carry
PhysxContactReportAPI; a tagged parent no longer qualifies an untagged cloned child or adds unintended wildcard sensors.Contact-binding force reads stay correct after zero-duration steps. Both
step()andstep_sync()retain the last simulated step’s impulse-to-force conversion whendtis zero.Invalidated tensor views fail cleanly. Destroying an articulation invalidates rigid-body views of its links, and resets before simulation starts invalidate existing views. Incoming joint-force and tendon-damping reads through stale views report failure instead of crashing.
Articulation and tendon sessions handle initialization correctly. Queries no longer index incomplete link metadata out of bounds or publish partial results when a later articulation is invalid. Articulation root, link and joint writes work before the first step on CPU and GPU scenes with readback. Reads refresh articulation and tendon membership after insertion, avoiding empty results left over from initialization. DirectGPU articulation and tendon commits still require a simulation step and now report that requirement explicitly.
Rejected kinematic targets report their cause and body path. Disabled bodies, non-finite positions and invalid quaternions produce task errors even with logging disabled. Rejected batches leave their valid peers untouched.
Linux wildcard selections handle very long prim names without crashing. Tensor bindings and session queries retain the existing pattern grammar and pattern-length limit without imposing a new prim-name limit.
Python destruction protects borrowed read arrays.
PhysX.destroy()refuses to release storage while a read array or a view of it remains alive. Release those borrows before retrying destruction.Python debug-render sessions work with an attached stage. Settings writes and geometry reads no longer fail because the query loses its attachment. Attribute tokens use the attached stage’s dictionary; detaching still invalidates existing queries and sessions.
Python tensor transfers wait for CUDA producers before accessing buffers. Full, indexed, masked and cached transfers honor pending Warp work and the CUDA DLPack stream handoff, preventing stale writes and read results being overwritten by unfinished buffer initialization. Callers must still synchronize raw
DLTensorand pinned host buffers themselves. Empty GPU contact reads also clear caller buffers correctly when they belong to another CUDA context.Writing CPU poses to GPU-backed OVStage matrices preserves the caller’s CUDA context.
writeWorldTransformsToOvstage()restores the previous context, including when none was current, for both cached and uncached writes.Asynchronous stepping accepts the same timestep range as synchronous stepping.
step()now accepts finite, nonnegative values above one second, asstep_sync()already did. Neither path clamps nor subdivides the timestep; callers choose a value suitable for collision accuracy.USD authoring utilities handle inactive transforms and invalid inputs. Existing translate, orient and scale operations excluded from the effective transform stack are reactivated while preserving precision and reset state. Unit-conversion helpers warn and use a scale of one for invalid
metersPerUnit; they do not repair stage metadata.create_mesh_cone()rejects invalid dimensions or tessellation before editing the stage, while zero radius remains supported.Startup worker-pool overrides take effect before workers start. Carbonite tasking and TBB settings now control their pools; invalid counts and late changes are rejected. Configure them through the first instance’s legacy Carbonite overrides. The PhysX dispatcher count is a separate setting.
Copied examples find their installed dependencies and scene data. Python examples import schema helpers and locate bundled scenes through the installed package. The guides distinguish source-checkout paths from installed wheel and SDK sample locations, and identify
scene.usdaas a caller-supplied file rather than a bundled scene. Shipped workflows register PhysX and Newton schemas before population and add USD references without replacing the scene. Bundled CPU and GPU variants now declare their intended units and up axis, correcting default-density masses and scene orientation.Windows C sample launchers preserve the caller’s environment and exit code. Generated launchers restore the caller’s
PATHand return the application’s exit status. The shipped instructions include schema setup and launcher use.Simulation guides clarify scene defaults and state interpretation. GPU dynamics and GPU broadphase are defaults; per-scene CPU setup must disable GPU dynamics and select a CPU broadphase. DirectGPU live velocity edits through OVStage require world-space bodies and values after the first step; use session writes for bodies authored with local-space velocities. Rendering guidance explains signed scale and why debug wireframes can trail post-step poses.
Breaking Changes#
Lifecycle and session operations return task receipts. Check admission, then collect execution with
ovphysx_wait_task()orovphysx_wait_all(); acceptance alone does not establish success. This includes attach, update, detach, query/read/write creation, fetching, committing and releasing sessions. Replacewait_op()withwait_task()on the returned receipt. Each outcome is collected once; an earlier failure does not make a later successful task’s wait fail.wait_all()collects outstanding outcomes in submission order. Timed-out waits remain retryable, and a repeated collected wait returnsNOT_FOUND.C wait results carry complete task receipts. Replace
ovphysx_op_wait_result_twithovphysx_wait_task_result_t,error_op_indiceswitherror_tasks, andlowest_pending_op_indexwithpending_task. The new fields hold full receipts instead of integer indices. Zero-initialize results and inspect completed failures even when a wait returnsTIMEOUT. Read error messages before callingovphysx_destroy_wait_task_result(); do not shallow-copy the result or freeerror_tasksseparately.Python read/write calls distinguish asynchronous and synchronous use.
PhysX.read(query, attributes)andwrite(query, attributes)return typedOperationobjects on a completed query. Useread_sync(),read_tokens_sync()andwrite_sync()for the former convenience call shapes. Writes may request multiple attributes; fetched groups identify their original request. Collect commits withcommit_sync()orcommit(group).wait(); leaving awrite_sync()context does not collect a commit’s outcome.Stage teardown uses detach and a successful wait.
reset_stage()andovphysx_reset_stage()are removed. Keep the stage alive through successful detach or instance destruction, and sealed attach/update data through task completion. Pythonattach_ovstage()requires the owningovstage.Stage; raw handles andNoneraiseTypeError. Raw-handle integrations use the C API. Useis_stage_attached()for the immediate ownership check; public attachment identities are removed. Replacestep_n_sync()with a loop ofstep_sync()calls, and removed user-task callbacks with application code run after the relevant wait.Configuration separates process and instance settings.
ovphysx_create_instance()now takes only the output handle; unrelated legacy creation arguments useovphysx_create_instance_with_args(). Set process keys throughset_global_config()and instance keys throughPhysX.set_config()or their C equivalents. SetACTIVE_CUDA_GPUSafter creation and before attach; matching environment variables override global setters. Carbonite-only settings still usePhysXConfig.carbonite_overrides, despite the legacy configuration warning. Replace removed OmniPVD startup settings with globalOVD_RECORDING_CAPABLEbefore creation, followed by FILE or TCP recording after attach; see the OVD migration guide. ReplaceOVPHYSX_NVTX/nvtx_enabledwith the profiler backend setting.Schemas are installed separately from the wheel and SDK. Install
physx-usd-schemasand register both PhysX and deformable resource directories before population. Bundled schema resources,ovphysx_get_codeless_schema_root()and Pythoncodeless_schema_root()/codeless_schema_paths()are removed. Native applications extract the provider wheel as data; Python applications locate it through distribution metadata. Native samples fetch the provider from public PyPI. Source builds using--devschemaproduce a separate local provider, including from the public source export. See Physics Schemas.PhysxJointAPIis removed and its authored values are ignored silently. ReplacephysxJoint:maxJointVelocityandphysxJoint:armaturewithNewtonJointAPIvalues for all DOFs, orPhysxJointAxisAPIvalues per axis; per-axis values take precedence. The old joint-friction coefficient has no numeric replacement: retune withnewton:friction/newton:damping, or per-axisstaticFrictionEffort,dynamicFrictionEffortandviscousFrictionCoefficient. The population helpersPrimBatch::applyPhysxJointAPI()andapply_physx_joint_api()are also removed.Dedicated contact-report, pointer and debug-render calls move to sessions. Replace
ovphysx_get_contact_report()and Pythonget_contact_report()withcontactEvent*reads, adapting to per-sensor grouping and session-owned arrays. Removed-shape events cannot appear without a selected sensor that can claim them; net-force reads do not replace event payloads. Replaceovphysx_get_physx_ptr()with aphysxPointerread and theovphysx_debug_render_*family withDEBUG_RENDERqueries. Debug settings and geometry are session attributes, and debug queries require no attached stage.Native query and articulation-update signatures change.
ovphysx_query_target_tandOVPHYSX_QUERY_TARGET_*replace the old object enum and constants. Includeovphysx_attributes.hexplicitly forOVPHYSX_ATTR_*names. Query summaries replaceovphysx_fetch_query_result(); use the attached stage’s dictionary instead ofovphysx_query_shared_dictionary().ovphysx_update_articulations_kinematic()takes a query and position/velocity flags, replacing the binding-based update. Wait before reading updated state; DirectGPU may refresh both components for either nonzero mask. Object-change subscribe/unsubscribe andovphysx_get_last_task_error()take the owner first.Native CUDA readiness waits use CUDA directly.
ovphysx_cuda_stream_wait_event()is removed. UsecuStreamWaitEvent()orcudaStreamWaitEvent()on a read group’s nonzero borrowed event and check the result; never destroy that event. Finish consumers before releasing the session. Python orders readiness onto the current Warp stream and raises before exposing arrays if the wait fails, without a new Python CUDA dependency.Status codes and fetch exhaustion change.
END_OF_ITERATIONis removed, andINVALID_STATEchanges from 10 to 9; use named constants. A successful fetch ends with a null group, or PythonNone. Check task completion first, because a failed fetch can also leave a null group.
Performance#
Repeated DirectGPU active-body reads cost less. Reads with
ObjectScope.ACTIVEreuse the eligible body selection until membership or kinematic state changes. CPU active reads are unchanged. Change kinematic and simulation-disable flags through supported stage or session APIs; mutation through a raw PhysX pointer does not maintain these selections.CPU reads of multiple inverse-dynamics columns share their work. Reading
jacobian,massMatrix,coriolisForce,gravityForceandcentroidalMomentumtogether avoids repeated calculations while preserving the values returned by separate reads.Whole-scene GPU articulation refreshes have less overhead. Queries covering every articulation use the scene-wide refresh, while partial queries retain their selection. Refresh failures are reported instead of allowing stale link state to appear successfully updated.