Clash Detection Point Cloud API#
omni.physx.clashdetection.pointcloud is a lightweight extension that provides
point cloud extraction utilities for the clash detection pipeline.
It depends on the omni.pointcloud.streaming.potree extension to stream point cloud data
from Potree-format sources, then writes the result as UsdGeom.Points prims in the
active stage. The extracted prims are consumed by
ClashDetection when
SETTING_ENABLE_POINT_CLOUDS is enabled.
Note
This extension is included in omni.physx.clashdetection.bundle.
Enable the bundle to make this extension available.
Module#
The public surface of omni.physxclashdetectionpointcloud exports:
from omni.physxclashdetectionpointcloud import extract_point_cloud, ExtensionConfig
Functions#
- async omni.physxclashdetectionpointcloud.extract_point_cloud(
- stage: Usd.Stage,
- point_cloud_prim_path: str,
- destination_path: str,
- aabbs: List[Gf.Range3d],
- max_lod_level: int = 1000000,
- extract_layer_name: str = '',
- extract_to_session_layer: bool = True,
Extracts a point cloud to
UsdGeom.Pointsprims in the given stage.The function streams point cloud geometry from a Potree source prim (referenced by
point_cloud_prim_path), applies an optional axis-aligned bounding box (AABB) filter, and writes the resulting points asUsdGeom.Pointsprims underdestination_path.- Parameters:
stage (Usd.Stage) – The USD stage containing the geometry to process.
point_cloud_prim_path (str) – USD prim path of the point cloud source.
destination_path (str) – Path where extraction results are written as
UsdGeom.Points.aabbs (List[Gf.Range3d]) – AABBs of inclusion regions of interest. Only the first entry is currently used. Pass an empty list (or a list with a single maximum-extent AABB) to include all available points; if the list is empty, a bounding box of
±1e38is used internally.max_lod_level (int) – Maximum level-of-detail level used during extraction. Higher values include finer detail at the cost of more memory and time. Defaults to 1 000 000.
extract_layer_name (str) – Display name of the sublayer to use for writing the extracted prims. When empty the current edit target is used without modification.
extract_to_session_layer (bool) – Relevant only when extract_layer_name is non-empty. If
True, the named sublayer is found or created under the session layer. IfFalse, it is found or created under the root layer.
- Returns:
A
(success, error_message)tuple. error_message is an empty string on success. Returns(True, "")also when the AABB filter matches no points (this is not treated as an error). Returns(False, error_message)on streaming or write failures.- Return type:
Tuple[bool, str]
Note
The coordinate space of the extracted points depends on the position of
destination_pathrelative to the parent xform ofpoint_cloud_prim_path. Whendestination_pathis a child of that xform, points are kept in local space (the xform itself provides the world transform). Otherwise they are transformed to world space automatically.
Example#
Extracting a point cloud and running clash detection against meshes:
import asyncio
from pxr import Usd, UsdUtils, Gf
from omni.physxclashdetectionpointcloud import extract_point_cloud
from omni.physxclashdetectioncore.clash_detect import ClashDetection
from omni.physxclashdetectioncore.clash_detect_settings import SettingId
from omni.physxclashdetectioncore.clash_query import ClashQuery
from omni.physxclashdetectioncore.clash_data import ClashData
from omni.physxclashdetectioncore.clash_data_serializer_sqlite import ClashDataSerializerSqlite
from omni.physxclashdetectioncore.point_cloud_settings import PointCloudSettings
async def run_point_cloud_clash_detection(stage: Usd.Stage):
stage_id = UsdUtils.StageCache.Get().GetId(stage).ToLongInt()
# 1. Configure extraction settings
pc_settings = PointCloudSettings(
point_cloud_prim_path="/World/ScanData",
destination_path="/World/ScanData/Extracted",
save_to_session_layer=True,
skip_rendering=True,
max_lod_level=10,
)
# 2. Extract the point cloud into the stage
roi_aabb = Gf.Range3d(Gf.Vec3d(-100, -100, -100), Gf.Vec3d(100, 100, 100))
success, error = await extract_point_cloud(
stage=stage,
point_cloud_prim_path=pc_settings.point_cloud_prim_path,
destination_path=pc_settings.destination_path,
aabbs=[roi_aabb],
max_lod_level=pc_settings.max_lod_level,
extract_layer_name="ClashPointCloud",
extract_to_session_layer=pc_settings.save_to_session_layer,
)
if not success:
print(f"Extraction failed: {error}")
return
# 3. Set up ClashData and persist the point cloud settings
clash_data = ClashData(ClashDataSerializerSqlite())
clash_data.open(stage_id)
clash_data.insert_point_cloud_settings(pc_settings)
# 4. Create a point cloud clash query
query = ClashQuery(
query_name="Point Cloud vs Building Clash",
object_a_path=pc_settings.point_cloud_prim_path, # point cloud source
object_b_path="/World/Building", # mesh geometry
clash_detect_settings={
SettingId.SETTING_ENABLE_POINT_CLOUDS.name: True,
SettingId.SETTING_POINT_SIZE_OVERRIDE.name: 0.0, # auto-compute size
SettingId.SETTING_LOGGING.name: True,
},
)
clash_data.insert_query(query)
# 5. Run clash detection
clash_detect = ClashDetection()
clash_detect.set_settings(query.clash_detect_settings, stage)
clash_detect.set_scope(stage, query.object_a_path, query.object_b_path)
num_steps = clash_detect.create_pipeline()
for i in range(num_steps):
clash_detect.run_pipeline_step(i)
num_overlaps = clash_detect.get_nb_overlaps()
print(f"Found {num_overlaps} point cloud clashes")
# Fetch and save results
for _ in clash_detect.fetch_and_save_overlaps(stage, clash_data, query):
pass
clash_data.save()
clash_data.close()
clash_data.destroy()
# Run with: asyncio.ensure_future(run_point_cloud_clash_detection(stage))
Classes#
ExtensionConfig#
- class omni.physxclashdetectionpointcloud.ExtensionConfig#
A configuration class that holds extension-wide parameters read from
carb.settingsat startup.All attributes are class-level - do not instantiate this class.
- SETTINGS_DEBUG_LOGGING_ENABLED = "/persistent/clashDetection/pointClouds/debugLogging"
- Type:
str
carb.settingspath for the debug-logging toggle. When the value at this path isTrue, the extractor logs verbose messages (source path, extents, LOD level) viacarb.log_info.
- debug_logging: bool = False
Whether debug logging is currently enabled. Updated at startup and whenever
SETTINGS_DEBUG_LOGGING_ENABLEDchanges (viaSettingChangeSubscription).
- extension_path: Optional[str] = None
Absolute filesystem path to the installed extension directory. Set by
ClashDetectionPointCloudExtension.on_startup;Nonebefore the extension starts.