ovclash Python Package
The ovclash wheel runs clash detection on USD
stages from Python, outside Omniverse Kit. It installs three packages.
All three bind the same native library through ctypes.
| Package | Use it for |
|---|---|
ovclash |
The canonical API. It stays close to the C ABI: one runtime, one stage, one query at a time. |
ovclash_suite |
The Suite API: named queries, stored results, and HTML and JSON export. |
omni.physxclashdetectioncore |
The Suite API under the module names of the Kit extension, for code that you migrate from Kit. |
Pick one package and stay in it. Same-named types in ovclash and ovclash_suite are not
interchangeable; Choosing an API lists the
differences.
This page is the Python guide. It ships as docs/consumer/README.md in the
SDK archive and is the wheel's description on the package index; the wheel
ships no pages. overview.md introduces the whole package and lists every page. The
C/C++ guide is the C quickstart.
Installation
Requirements:
- Python 3.10 or newer.
- Windows x86_64, Linux x86_64 or Linux aarch64.
- On Windows, the Microsoft Visual C++ Redistributable (x64). ovclash does not bundle the MSVC runtime, and its native library does not load without it.
- On Linux, glibc 2.35 or newer and a
libstdc++that providesGLIBCXX_3.4.30; see Linux glibc baseline.
compatibility.md gives the platform tags and the version policy.
Install the wheel with pip:
python -m pip install ovclash
The wheel depends on one exact version of ovstage, the runtime that ovclash reads USD through.
pip installs it together with ovclash. That version is published on public PyPI.
Check the installation:
python -m ovclash --version
The command prints the version of the loaded native library, as ovclash <version>.
Without the pinned ovstage package, import ovclash raises OSError.
Optional extras
The core API needs no extra. Install one with python -m pip install "ovclash[viewer]". When pip
cannot resolve an extra's packages, compare your environment with the version ranges that
Python versions lists.
| Extra | Adds | Use it for |
|---|---|---|
viewer, viewer-ovstage |
NumPy and warp-lang (Warp) |
The zero-copy numpy() and warp() adapters of overlap-report buffers. |
viewer-openusd |
NumPy, warp-lang and usd-core |
Code that imports Python OpenUSD (pxr) itself. usd-core comes from public PyPI. |
Do not install usd-core to fix a failing query. ovstage supplies the USD runtime, and a second
pxr in the process can shadow it. USD coexistence explains how the two can
share a process.
Quick start
The wheel ships a small stage, samples/data/time_sampled.usda, in the installed ovclash
package directory. Its prims /Root/Xform_Primitives/Cube and
/Root/Xform_Primitives/Plane overlap. python -m pip show ovclash prints the parent of that
directory as Location, written <site-packages> on this page.
First query from the command line
python -m ovclash --stage <site-packages>/ovclash/samples/data/time_sampled.usda \
--scope-a /Root/Xform_Primitives/Cube --scope-b /Root/Xform_Primitives/Plane
stdout receives the JSON summary:
{
"duplicate_count": 0,
"duplicates": [],
"overlap_count": 1,
"overlaps": [
{
"name0": "/Root/Xform_Primitives/Cube",
"name1": "/Root/Xform_Primitives/Plane",
"nb_elements": 10,
"time": 0.0,
"type": 0
}
],
"pipeline_steps": [
"Releasing previous data...",
"Finding meshes...",
"Computing initial mesh data...",
"Finding shared meshes...",
"Cooking meshes...",
"Computing global mesh data...",
"Building BVH...",
"Running broad-phase...",
"Purging duplicates...",
"Running narrow-phase...",
"Processing results..."
],
"stage": "<site-packages>/ovclash/samples/data/time_sampled.usda"
}
Command line lists every option.
First query in Python
from pathlib import Path
import ovclash
from ovclash import ClashRuntime, RunSettings
# The wheel ships this stage in samples/data/ of the package directory.
stage = Path(ovclash.__file__).parent / "samples" / "data" / "time_sampled.usda"
runtime = ClashRuntime()
try:
runtime.open_stage(str(stage))
runtime.set_run_settings(RunSettings(tolerance=0.0))
runtime.set_scope(["/Root/Xform_Primitives/Cube"], ["/Root/Xform_Primitives/Plane"])
runtime.run_pipeline()
for index in range(runtime.get_overlap_count()):
details = runtime.get_overlap_details(index)
print(details.name0, details.name1, details.nb_elements)
finally:
runtime.destroy()
Output:
/Root/Xform_Primitives/Cube /Root/Xform_Primitives/Plane 10
The ovclash_suite example runs the same query and saves its results. The
samples/ directory of the package holds complete Python samples;
samples.md describes them and their launchers.
Command line
python -m ovclash opens one stage, runs one query through the canonical ovclash package and
prints a JSON summary. The wheel installs no separate console script.
python -m ovclash [--stage STAGE | STAGE [PATHS ...]] [--scope-a PATHS] [--scope-b PATHS] [options]
| Option | Type | Required | Default | Meaning |
|---|---|---|---|---|
--stage PATH |
String: a file path | One of --stage and STAGE |
None | The USD stage file. |
STAGE [PATHS ...] |
Strings: a file path, then prim paths | One of --stage and STAGE |
None | Positional form: the first argument is the stage, and the rest join search set A. Use this form or --stage, not both: with --stage, the first positional argument is ignored. |
--scope-a PATHS |
String, repeatable | No | The whole stage | Prim paths of search set A. Repeat the option, or separate paths with commas, semicolons or whitespace. |
--scope-b PATHS |
String, repeatable | No | None | Prim paths of search set B, with the same rules. |
--tolerance D |
Float | No | 0.0 |
Clearance distance in stage units. Mesh pairs closer than this clash. 0.0 reports touching or interpenetrating geometry only. |
--dynamic |
Flag | No | Off | Query the time range of --start-time and --end-time. Without it, the query is a static query. |
--start-time S |
Float, in seconds | No | 0.0 |
Start of the time range, in seconds, not USD time codes. |
--end-time S |
Float, in seconds | No | 0.0 |
End of the time range, in seconds. With --dynamic, it must not be below --start-time. An equal value runs a static query at that time. |
--time-codes-per-second N |
Float | No | 24.0 |
Samples per second over the time range. This is not the stage's time-code rate. It must not be negative, and 0 collapses the range to one sample. |
--point-clouds |
Flag | No | Off | Also run point-vs-mesh queries. |
--duplicates |
Flag | No | Off | Find duplicate meshes only, and skip overlap detection. |
--single-threaded |
Flag | No | Off | Run mesh preparation and collision on one thread. Overlap membership does not change. |
--log |
Flag | No | Off | Write the backend's progress and diagnostic lines to stderr. The JSON summary does not change. |
--version |
Flag | No | Off | Print ovclash and the version of the loaded native library to stdout, then exit. |
-h, --help |
Flag | No | Off | Print the usage and the options to stdout, then exit. |
Every other RunSettings field keeps its default. The command also accepts --multi-threaded
from older command lines. It has no effect, and --help does not list it. --help and
--version load the native library, but they do not open a stage.
Scope rules:
- Without scope paths, the command queries the whole stage.
- With set A only, the query tests the meshes of set A against each other.
- With both sets, it tests set A against set B.
- A scope path also covers the prim's descendants.
Query rules:
- A dynamic query (
--dynamicwith--end-timeabove--start-time) drops overlaps between two meshes whose transforms are not animated. Run a static query to find those overlaps. --duplicatesfinds nothing in a dynamic query. Equal start and end times select a static query, which runs the duplicate search. On the bundledtime_sampled.usda,--duplicatesreports one pair,/Root/Xform_Primitives/Cube_Dup1and/Root/Xform_Primitives/Cube_Dup2, with 12 triangles.- To query a range given in USD time codes, divide each time code by the stage's
time-codes-per-second rate.
ClashRuntime.get_stage_timeline_data()reports that rate.
Output rules:
- stdout holds only the JSON summary: one object, indented by two spaces, with sorted keys. You can redirect it to a file or pipe it straight into a JSON parser.
- The version header,
ovclash <version> - Standalone query CLI, and every diagnostic go to stderr. This includes the lines that native plugins write while the stage loads. - An overlap record holds the overlap's first sampled frame only, so a dynamic query reports one frame per overlap.
Every field of the summary is always present:
| Field | Type | Required | Default or values | Description |
|---|---|---|---|---|
stage |
string | Yes | The path as given | The stage path. |
pipeline_steps |
array of strings | Yes | 11 names for a static query | The names of the pipeline steps that ran, in order. |
overlap_count |
integer | Yes | 0 or more | The number of entries in overlaps. |
overlaps |
array of objects | Yes | Can be empty | One object per overlap, with five fields: name0, name1, type, time and nb_elements. |
overlaps[].name0 |
string or null |
Yes | A prim path | The first prim: the point cloud of a point-vs-mesh pair, else a mesh. |
overlaps[].name1 |
string or null |
Yes | A prim path | The second prim, a mesh. |
overlaps[].type |
integer | Yes | 0 mesh-vs-mesh, 1 point-vs-mesh |
The pair type. |
overlaps[].time |
number | Yes | Seconds | The time of the record, in seconds, not USD time codes. |
overlaps[].nb_elements |
integer | Yes | 0 or more | The number of overlapping triangles or points. |
duplicate_count |
integer | Yes | 0 or more | The number of entries in duplicates. |
duplicates |
array of objects | Yes | Can be empty | One object per duplicate mesh pair, with four fields: name0, name1, nb_tris and time. |
duplicates[].name0, duplicates[].name1 |
string or null |
Yes | Prim paths | The two meshes of the pair. |
duplicates[].nb_tris |
integer | Yes | 0 or more | The number of triangles in the duplicated mesh. |
duplicates[].time |
number | Yes | Seconds | The time of the pair. |
Exit status:
| Status | Meaning |
|---|---|
0 |
The summary was printed, or --help or --version ran. |
2 |
A usage error, such as a missing stage path or a non-numeric time. The command prints the usage and the error on stderr. |
1 |
The query raised. ValueError reports a non-finite time, rate or tolerance, a negative --time-codes-per-second or, with --dynamic, an --end-time below --start-time. RuntimeError reports a failed stage open or query. The command prints a traceback on stderr and writes nothing to stdout. |
ovclash
ovclash is a thin binding of the canonical C ABI. One ClashRuntime owns the stage, the
settings, the scope and the results. The first query shows the
lifecycle:
ClashRuntime()creates a native context.open_stage(path)opens a local USD file. Asset URIs are rejected.set_run_settings(RunSettings(...))applies the settings. Unknown field names raiseTypeError, and out-of-range values raiseValueError.set_scope(paths_a, paths_b)records the search sets. Call it afteropen_stage(), because a successful open drops the recorded scope.run_pipeline()runs every pipeline step on the calling thread.- Read the results.
destroy()releases the native context.
A failed native call raises RuntimeError with the context's last error text. Serialize the
calls on one runtime. The docstrings give the full contract of each method:
help(ovclash.ClashRuntime) prints them, and
References in the package lists them with the other
references.
developer_guide.md gives the runtime rules that both languages share, such
as setting a scope.
Run settings
RunSettings holds the settings that standalone queries commonly tune: the tolerance, the time
range (set_times, start_time, end_time, time_codes_per_second), point clouds, duplicate
search, full-scene traversal, invisible prims, the depth mode, threading
(single_threaded, new_task_manager, nb_tasks) and logging. Names in each API
lists its fields, and settings.md gives each field's
default, unit and effect, beside the matching C and Suite settings.
set_run_settings(settings, **changes)appliessettings, orRunSettings()when you omit it, with the keyword changes on top. It does not merge with the settings that the runtime already holds, so every field that you do not pass returns to its default. To change one field and keep the rest, passruntime.get_run_settings()as the base.nb_tasksmust be 1 to 255 whennew_task_managerisFalseandsingle_threadedis not set. Otherwise any unsigned 32-bit value is accepted, and the new task manager ignores it.- A dynamic query (
set_times=Truewithend_timeabovestart_time) drops overlaps between two meshes whose transforms are not animated.RunSettingshas no field for this engine default. Run a static query to find those overlaps. use_usdrthas no effect.
Reading results
| Method | Returns |
|---|---|
get_overlap_count() |
The number of overlapping prim pairs. |
get_overlap_record(index) |
An OverlapRecord: name0, name1, nb_records, nb_elements, type and time. |
get_overlap_details(index) |
An OverlapDetails: the record fields plus clash_hash, mesh_hash0, mesh_hash1, min_distance and max_local_depth. |
get_duplicate_count(), get_duplicate(index) |
Duplicate mesh pairs, as DuplicateMesh values: name0, name1, clash_hash, mesh_hash0, mesh_hash1, nb_tris and time. |
get_query_stats() |
A QueryStats: nb_meshes, nb_shared_meshes, nb_cooked_meshes and nb_point_clouds. |
get_overlap_report(index) |
An OverlapReport with face, outline and point buffers. See Overlap reports. |
- All of these except
get_overlap_report()return copied values. They stay valid after later runs. - The overlap order can differ between runs. Identify an overlap by
name0andname1, or byclash_hash, never by its index; see Overlap index order is not contractual.
OverlapRecord, OverlapDetails and DuplicateMesh are dataclasses with shared field names.
Each field is set on every value of the types that the Description column names:
| Field | Type | Required | Default or values | Description |
|---|---|---|---|---|
name0 |
str or None |
Yes | A prim path; None when empty |
The first prim: the point cloud of a point-vs-mesh pair, else a mesh. All three types. |
name1 |
str or None |
Yes | A prim path; None when empty |
The second prim, a mesh. All three types. |
nb_records |
int |
Yes | Always 1 for a static query | The number of frames in which the pair overlaps. OverlapRecord and OverlapDetails. |
nb_elements |
int |
Yes | 0 or more | The number of overlapping triangles or points in this frame. OverlapRecord and OverlapDetails. |
type |
OverlapType |
Yes | MESH_VS_MESH (0), POINT_VS_MESH (1) or UNDEFINED |
The pair type. Test it as == OverlapType.POINT_VS_MESH, never as != 0, which reads UNDEFINED as a point-cloud pair. OverlapRecord and OverlapDetails. |
time |
float |
Yes | Seconds | The time of the frame, or of the duplicate pair, in seconds, not time codes. All three types. |
clash_hash |
tuple[int, int] |
Yes | The two uint64 words of a 128-bit hash | The clash hash of the two prim paths. OverlapDetails and DuplicateMesh. |
mesh_hash0, mesh_hash1 |
tuple[int, int] |
Yes | The two uint64 words of a 128-bit hash | The mesh hash of the first and of the second prim. OverlapDetails and DuplicateMesh. |
min_distance |
float |
Yes | Stage units; 0.0 when the meshes touch or interpenetrate |
The minimum distance between the triangle pairs. OverlapDetails only. |
max_local_depth |
float |
Yes | Stage units; -1.0 when depth was not computed; always 0.0 for a point-vs-mesh overlap |
The maximum local depth between the triangle pairs. OverlapDetails only. |
nb_tris |
int |
Yes | 0 or more | The number of triangles in the duplicated mesh. DuplicateMesh only. |
QueryStats holds four counters of the last run, all zero before the pipeline has run:
| Field | Type | Required | Default or values | Description |
|---|---|---|---|---|
nb_meshes |
int |
Yes | 0 or more | The number of selected meshes. |
nb_shared_meshes |
int |
Yes | 0 or more | The number of selected meshes that are shared instances. |
nb_cooked_meshes |
int |
Yes | 0 or more | The number of unique meshes cooked. A value below nb_meshes minus nb_shared_meshes means that the run skipped meshes it could not cook. |
nb_point_clouds |
int |
Yes | 0 or more | The number of selected point clouds. |
Overlap reports
An OverlapReport holds the geometry behind one overlap record. get_overlap_report(index) fills
every buffer of the record's first frame. Its keyword arguments narrow it: record_index selects
another frame, and flags, a combination of the OverlapReportFlag members FACES0, FACES1,
OUTLINE and POINTS0, selects the buffers to fill. A report has these attributes:
| Attribute | Type | Required | Default or values | Description |
|---|---|---|---|---|
faces0, faces1 |
BufferView of uint32 |
Yes | Empty unless flags holds FACES0 or FACES1 |
The USD face indices of the colliding faces of the first and of the second mesh. |
outline |
BufferView of float32, shape (segments, 6) |
Yes | Empty unless flags holds OUTLINE |
The intersection outline, one segment per row: x0, y0, z0, x1, y1, z1. |
points0 |
BufferView of uint32 |
Yes | Empty unless flags holds POINTS0 |
The USD point indices of the colliding points of the point cloud. |
point_size0 |
float |
Yes | Stage units; 0.0 when the cloud authors per-point widths that differ |
The point width (diameter), without the prim's transform scaling. A uniform per-point width array reports its single value. |
matrix0, matrix1 |
tuple of 16 float |
Yes | A row-major 4x4 matrix | The world transforms of the first and of the second prim for the record. |
The buffers borrow native memory. Continue the first query, before destroy():
with runtime.get_overlap_report(0) as report:
faces0 = report.faces0.numpy().copy() # uint32 face indices of the first mesh
outline = report.outline.numpy().copy() # float32, shape (segments, 6)
print(len(faces0), outline.shape)
Output:
4 (10, 6)
numpy(),warp()and DLPack (np.from_dlpack(view),torch.from_dlpack(view)) hand the buffer over without copying.numpy()and DLPack need NumPy, andwarp()needswarp-lang; theviewerextra installs both.tolist()copies a buffer without either.- Close a report when you are done, or use it as a context manager.
- The runtime closes open reports itself before it changes its stage, settings, scope or
pipeline, and on
reset()anddestroy(). - Arrays already exported through
numpy(),warp()or DLPack are not tracked. Copy what you keep before those calls.
threading_and_ownership.md gives the lifetime of every borrowed buffer.
Asynchronous runs
run_async() starts the pipeline on a native worker and returns an AsyncPipeline. This code
replaces runtime.run_pipeline() and the result loop of the
first query:
import time
pipeline = runtime.run_async()
running, step = pipeline.poll()
while running: # drive the loop by the running flag, not by step.finished
print(f"{step.progress:.0%} {step.name}")
time.sleep(0.05)
running, step = pipeline.poll()
pipeline.finish() # raises RuntimeError when the run failed or was cancelled
print(runtime.get_overlap_count())
Until you call finish() or cancel(), most runtime methods raise RuntimeError. A cancelled
run can report zero overlaps, so check is_cancelled() before you read zero as clash-free.
async_pipelines.md describes the whole lifecycle.
The ovclash-basics playbook covers the query kinds and common mistakes.
References in the package gives its path in the package
directory and lists every playbook.
ovclash_suite
ovclash_suite is the Suite API. It keeps the legacy clash object model where practical:
ClashDetectiondrives stage loading, settings, scopes, pipeline execution, overlap processing and reports.ClashQuery,ClashInfo,ClashFrameInfoandPointCloudSettingskeep the legacy model names and serialization shape.ClashDatais the facade over a store. By default it creates and owns aClashDataSerializerSqlite. That serializer opens.ovclashdbdatabases and legacy.clashDetectioncontainers by path. No store is loaded from a USD stage.ClashDataSerializerDirectorystores the same records as readable JSON files, one file per record.export_to_html(title, subtitle, column_defs, rows, additional_info=None)andexport_to_json(column_defs, rows, additional_info=None)are module-level functions, not methods. They return the document as UTF-8 bytes. EachExportColumnDefincolumn_defsdescribes one column; Python API lists its fields.
persistence.md helps you choose a store and describes both, sqlite_serializer.md and directory_serializer.md describe each store's format, and export.md describes the reports.
This example runs a query, saves its results, reads them back and exports them as JSON.
The object model lists the fields of ClashQuery and
ClashInfo:
from contextlib import closing
from pathlib import Path
import ovclash
from ovclash_suite import ClashData, ClashDetection, ClashQuery, ExportColumnDef, SettingId, export_to_json
stage = Path(ovclash.__file__).parent / "samples" / "data" / "time_sampled.usda"
query = ClashQuery(
query_name="Cube vs Plane",
object_a_path="/Root/Xform_Primitives/Cube",
object_b_path="/Root/Xform_Primitives/Plane",
clash_detect_settings={SettingId.SETTING_TOLERANCE.name: 0.0},
)
clash = ClashDetection()
data = ClashData() # owns a SQLite serializer
try:
data.open("results.ovclashdb")
data.insert_query(query) # assigns query.identifier
clash.open_stage(str(stage))
clash.set_settings(query.clash_detect_settings)
clash.set_scope_paths([query.object_a_path], [query.object_b_path])
clash.run_pipeline()
with closing(clash.fetch_and_save_overlaps(None, data, query)) as fetch:
for progress in fetch:
pass
clashes = data.find_all_overlaps_by_query_id(query.identifier, False)
rows = [[info.object_a_path, info.object_b_path, info.state.name] for info in clashes.values()]
columns = [ExportColumnDef(0, "Object A"), ExportColumnDef(1, "Object B"), ExportColumnDef(2, "State")]
print(export_to_json(columns, rows).decode("utf-8"))
finally:
data.destroy()
clash.destroy()
Output:
{
"columns": [
"Object A",
"Object B",
"State"
],
"rows": [
[
"/Root/Xform_Primitives/Cube",
"/Root/Xform_Primitives/Plane",
"NEW"
]
]
}
The ovclash-suite-python playbook, which
References in the package lists, covers the settings
model, persistence, export and common mistakes. suite_workflows.md walks
through the five queries of the clash_suite_api sample.
Query settings keys
Key a ClashQuery's settings by the SettingId member name, as in the example. The query
stores its settings as JSON. A SettingId or integer key becomes a decimal string there, and
later lookups ignore it. ClashDetection.set_settings() also accepts SettingId members and
their integer values as keys. It ignores an unknown key without an error.
Names in each API lists every SettingId key, and
settings.md gives its default.
Ownership and errors
- Native failures raise Python exceptions that carry the native last-error text.
AsyncPipelineandAsyncFetchAndSaveare context managers.ClashDetection,ClashDataand the built-in serializers are not context managers. Release each withdestroy().ClashData.destroy()only closes a serializer that you passed in. That serializer stays yours to destroy.
Some legacy ClashData and ClashQuery methods report a failure through their return value
instead of raising. Failures that do not raise lists
them and the failures that do raise.
Fetching Suite runtime results
ClashDetection.fetch_and_save_overlaps(stage, data, query), the
fetch-and-save entry point, saves the results of the completed run for
query into an open store. The store is a ClashData or a serializer. stage is kept
for compatibility and can be None; the results come from the runtime.
The method is a lazy generator that yields progress:
- The argument checks, the native start and the snapshot of the runtime's threading settings happen on the first iteration, not when you call the method.
- Each step handles at most 1,024 frame reports and stops once it reaches about 8 MiB of report payload. One indivisible report can exceed that bound, and a long overlap spans several steps.
- The final
1.0yield follows a successful commit. - An optional
progress_callbackreceives(written, total)counts.writtenequal tototaldoes not mean that the results are committed. - The query's
SETTING_DUP_MESHESdecides whether duplicates are saved. The runtime's duplicate-only detection setting does not.
Iterate to the end, or close the iterator when you stop early, for example with
contextlib.closing. Until then, the iterator reserves the runtime and the built-in store, and
conflicting changes and lifecycle calls fail. Close an abandoned iterator before you close or
destroy either owner. Serialize the calls that share a runtime or a store.
With async_mode=True, initialization, writes and cleanup run on a native worker:
- Custom serializer callbacks run on that worker.
- Progress, modification and timing callbacks stay on the iterating thread.
- While the fetch is live, reads of the runtime and of the built-in store fail too.
- Stopping the iteration without closing leaves the worker running. Closing requests cancellation and waits for the worker.
- Cancellation can race completion. It does not undo a completed commit.
For explicit polling, ClashDetection.run_async_fetch_and_save(stage, data, query) returns an
AsyncFetchAndSave context manager. It has is_running(), get_step_data(), get_counts()
(which returns (written, total, initialized)), get_last_error(), finish(), cancel() and
close().
- Finish asynchronous detection before you start a fetch.
- Close the fetch before you read the store.
- Close it with
close()or awithblock, not through garbage collection, so that cleanup is timely and its errors are visible.
Fetch-and-save is not all-or-nothing for every failure. Saving detection results gives the outcome of each failure, and how to publish results only after complete success.
Clash states
By default, a fetch updates the stored clash states as
Clash states describes: re-detected clashes become ACTIVE, an
unchanged APPROVED clash keeps its approval, and clashes that are no longer detected become
RESOLVED. The same flag controls the ACTIVE update in process_overlap() and
process_duplicate(). To keep the stored states, clear the flag before you start the fetch:
from omni.physxclashdetectioncore.config import ExtensionConfig
ExtensionConfig.update_clash_states_after_detection = False
Custom serializers
A custom serializer derives from AbstractClashDataSerializer and must override
fetch_transaction(operation). That method handles the operations FETCH_BEGIN,
FETCH_COMMIT and FETCH_ROLLBACK, and the savepoints FETCH_BEGIN_OVERLAP,
FETCH_END_OVERLAP and FETCH_ABORT_OVERLAP, with the semantics that
Custom stores gives. Without that override, fetching raises
NotImplementedError before any work starts, because rollback cannot be emulated through the
CRUD methods.
For long APPROVED histories, a SQL-backed store should also override
fetch_iter_saved_frames(identifier, first_frame_offset=0) with a forward cursor:
- The cursor yields owned frames in persisted order and has a
close()method. - The fetch may close the cursor and reopen it at a nonzero offset around writes.
- The default implementation issues one ranged read per frame.
The docstrings of AbstractClashDataSerializer and its fetch_* hooks give the full contract;
References in the package says how to read them.
Numeric fidelity describes which numeric values each store
keeps exactly.
omni.physxclashdetectioncore
omni.physxclashdetectioncore exposes the ovclash_suite API under the Kit extension's module
names, for code that you migrate from Kit. New code imports ovclash_suite.
- A few upstream names are absent.
- The USD-dependent helpers in its
usd_utilsmodule raiseNotImplementedError. help(omni.physxclashdetectioncore)lists every gap, and What does not summarizes them.
kit_compatibility.md describes the porting shim.
Comparing ovstage matrix decompositions
By default, the ovstage backend decomposes mesh matrices with OpenUSD-compatible math. To
compare with the original ovclash math without rebuilding, select it on a ClashRuntime. Here
runtime is the runtime of the first query, and these lines replace its
runtime.run_pipeline() call:
runtime.set_ovstage_matrix_decomposition("ovclash")
runtime.run_pipeline()
runtime.set_ovstage_matrix_decomposition("openusd") # restore the default
runtime.run_pipeline()
runtime.get_ovstage_matrix_decomposition()returns the selection.- The mode belongs to one context. It survives
reset()and stage replacement. - Changing the mode clears existing results, closes open reports and discards the pipeline. The
next
run_pipeline()orrun_async()recreates it. - Selecting the current mode again changes nothing.
- Finish any outstanding async handle first, even when its worker has stopped or the mode is unchanged.
- Any other name raises
ValueError.
The ovclash math can change zero-tolerance clash membership and report payloads. Raw reported world matrices and point-cloud scaling do not change. In both modes, these values fail the affected query instead of being normalized: non-finite or out-of-range matrix values, and invalid resulting poses or scales, including non-unit rotation quaternions.
C callers include <ovclash/ovclash_ovstage.h>, release borrowed reports, and call
ovclash_ovstage_set_matrix_decomposition(context, OVCLASH_OVSTAGE_MATRIX_DECOMPOSITION_OVCLASH).
OVCLASH_OVSTAGE_MATRIX_DECOMPOSITION_OPENUSD restores the default. Create a new pipeline for the
next run. These controls exist only with ovstage, and they do not switch the scene backend. The
Suite API, in Python and in C, has no equivalent control.
ovstage_integration.md covers the other ovstage-only entry points.
Native library lookup
Importing ovclash, ovclash_suite or omni.physxclashdetectioncore loads the native library
once per process. The packages look for it in this order:
OVCLASH_SUITE_LIB, elseOVCLASH_LIB. The value must be the absolute path of the library; a relative path is rejected.- The library bundled in the installed
ovclashpackage. Only the wheel bundles one. The SDK archive's Python packages needOVCLASH_LIB. - The bare library name, through the platform's library search. This step runs only when
OVCLASH_ALLOW_BARE_LIBRARY_LOADis enabled, and it is for development only.
The import raises OSError when it cannot load the library. It raises RuntimeError when the
library's version differs from the version of the Python package.
The ovstage runtime
- The wheel uses the
ovstagepackage that pip installed as its dependency. It ignoresOVCLASH_OVSTAGE_PACKAGE_DIR. - The SDK archive does not bundle ovstage. When
OVCLASH_SUITE_LIBorOVCLASH_LIBnames its library, the packages use theovstagethat the SDK archive'srequirements.txtpins, as installed for the running interpreter. - With the SDK archive,
OVCLASH_OVSTAGE_PACKAGE_DIRselects another installation instead. Set it to the absolute path of that installation'sovstagepackage directory. - With the SDK archive, the selected
ovstagemust be exactly the pinned version, or the import raisesOSError.
Process environment
Loading prepares the process for the runtime:
- It prepends the runtime's OpenUSD plugin directories to
OV_PXR_PLUGINPATH_2511. It also prepends them toPXR_PLUGINPATH_NAMEwhen the runtime's OpenUSD is not namespaced. - On Windows, it adds the runtime's directories to
PATHand to the DLL search path, followed by the directories thatOVCLASH_DLL_DIRSlists, separated by;. - With the wheel, it sets
OVSTAGE_LIBRARY_PATH_HINTwhen the variable is unset. With the SDK archive, it replaces an inherited value with the directory of the selected ovstage. - On Linux, it loads the ovstage libraries into the global symbol namespace.
These changes affect the whole process. Child processes inherit the environment variables.
USD coexistence
ovclash has no OpenUSD linkage of its own: it reads stages through the
ovstage API, and the pinned ovstage runtime carries a namespaced OpenUSD. That OpenUSD reads its
plugin registry from OV_PXR_PLUGINPATH_2511, so the packages publish the registry only there.
An unnamespaced OpenUSD, such as the usd-core wheel, reads PXR_PLUGINPATH_NAME instead and
does not load that registry.
- Keep the ovstage plugin directory out of
PXR_PLUGINPATH_NAMEwhen an unnamespaced OpenUSD shares the process. That OpenUSD would read the variable and then fail to declare its own schema types. - Install
usd-coreonly for code that importspxritself, through theviewer-openusdextra. A query needs no Pythonpxr.
When another component in your process already manages the OpenUSD plugin paths, set
OVCLASH_DISABLE_BUNDLED_PLUGIN_PATHS=1:
- The packages then add nothing to
PXR_PLUGINPATH_NAMEorOV_PXR_PLUGINPATH_2511. - On Windows, they also leave the plugin directories of the ovclash payload out of the DLL search path.
- With the wheel, they still add the
ovstagepackage's runtime and plugin directories to the DLL search path. - The native library does not read this variable.
Environment variables
The Python packages read these variables when they load the native library:
| Variable | Values | Required | Default | Effect |
|---|---|---|---|---|
OVCLASH_SUITE_LIB, OVCLASH_LIB |
The absolute path of the native library | With the SDK archive's Python packages | Unset: the wheel loads the library it bundles | Selects the native library. OVCLASH_SUITE_LIB is checked first, and a relative path raises OSError. See Native library lookup. |
OVCLASH_ALLOW_BARE_LIBRARY_LOAD |
Flag | No | Off | Development only. Allows the bare-name library lookup when neither override is set and no bundled library exists. |
OVCLASH_OVSTAGE_PACKAGE_DIR |
The absolute path of an ovstage package directory |
No | Unset: the ovstage of the running interpreter |
SDK archive only; the wheel ignores it. Selects another installation of the pinned ovstage. See The ovstage runtime. |
OVCLASH_DLL_DIRS |
Directories separated by ; |
No | Unset | Windows only. Adds the directories to PATH and to the DLL search path, after the runtime's directories. |
OVCLASH_DISABLE_BUNDLED_PLUGIN_PATHS |
Flag | No | Off | Leaves the plugin path variables, and on Windows the plugin directories of the ovclash payload, unchanged. See USD coexistence. |
A flag is enabled by any value other than empty, 0, false, off or no, ignoring case.
Environment variables lists every variable that the
Python packages, the native library and the sample launchers read, with its exact rules.
Metadata
Release files for ovclash 0.2.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| ovclash-0.2.2-py3-none-win_amd64.whl | Python 3 | none | Windows x86-64 | Details for ovclash-0.2.2-py3-none-win_amd64.whl |
| ovclash-0.2.2-py3-none-manylinux_2_35_x86_64.whl | Python 3 | none | Linux glibc 2.35+ x86-64 | Details for ovclash-0.2.2-py3-none-manylinux_2_35_x86_64.whl |
| ovclash-0.2.2-py3-none-manylinux_2_35_aarch64.whl | Python 3 | none | Linux glibc 2.35+ ARM64 | Details for ovclash-0.2.2-py3-none-manylinux_2_35_aarch64.whl |
Total release size: 16.4 MB
Release files / ovclash-0.2.2-py3-none-win_amd64.whl
| Download URL | ovclash-0.2.2-py3-none-win_amd64.whl |
|---|---|
| Size | 2.9 MB |
| Tags | Python 3 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
a15071d93d332f3567136e0704e72df27d610020dd3cc536832ff25238e4a469
|
|
BLAKE2b-256 checksum How to use checksums |
3b9c2725e81b80451c4693e4849a9657f22cc44e060df51156dd1049321914ba
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.8
|
Release files / ovclash-0.2.2-py3-none-manylinux_2_35_x86_64.whl
| Download URL | ovclash-0.2.2-py3-none-manylinux_2_35_x86_64.whl |
|---|---|
| Size | 6.6 MB |
| Tags | Linux glibc 2.35+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
7c2cea9bb1b01c1036e8e6a69508bd35389ee485bbeeeee2f55197373378051c
|
|
BLAKE2b-256 checksum How to use checksums |
333b636a962ed11a8ade76337e18a1b74becd71aaedd45874472227bfe738306
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.8
|
Release files / ovclash-0.2.2-py3-none-manylinux_2_35_aarch64.whl
| Download URL | ovclash-0.2.2-py3-none-manylinux_2_35_aarch64.whl |
|---|---|
| Size | 6.9 MB |
| Tags | Linux glibc 2.35+ ARM64 Python 3 |
|
SHA-256 checksum How to use checksums |
fb7125b75905ebfdb947446e058fe55a43d4e060027d9af80f2b1ef7556b4743
|
|
BLAKE2b-256 checksum How to use checksums |
e07c34a4abe86c4c5de3aae12c7a02a7cf7d0e94f5605f4ec7501b7acbd1375a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.8
|
Security for ovclash 0.2.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.