Simple Way to check for collision

Hello, I am wondering if there is a simple way to check for collision of two meshes without simulating it? I hope you understand what I mean, so lets say I spawn object A and B and I just want to know if these two meshes collide without any fancy dynamic simulation… Do you have any idea how I could proceed here?

Thanks a lot!


You can refer to the overlap tests at Windows/Physics/Demo Scenes. You can load and open to see the source sample there.

Hey @HaiLocLu , thanks for the reply. Unfortunately I do not have Windows/Physics/Demo Scenes. The only option I got is Physics/PhysX Properties. Is there an extension which I should activate? I am using version 2020.2.2007. Thanks!

Hi,

All Physics Demos I have in version 2020.2.2007 are in Physics/Demos/PhysX. But there is not “Overlap box” sample. Maybe we are seeing some of what is coming in the new version 😲

It’s similar to the ur10_scenarios/bin_stack.py
self._physx_query_interface = omni.physx.get_physx_scene_query_interface()
hit = self._physx_query_interface.raycast_closest(origin, rayDir, 100.0)

but with overlap test numHits = get_physx_scene_query_interface().overlap_box(extent, origin, rot, self.report_hit, False)

We’ll add these tips to the docs.

import carb
from omni.physx.scripts.physicsUtils import *
from pxr import UsdGeom, Gf, Vt
import omni.physxdemos as demo
from omni.physx import get_physx_scene_query_interface
from omni.debugdraw import _debugDraw
from .SceneQueryBaseDemo import *

class OverlapBoxDemo(demo.Base):
title = “Overlap box”
category = demo.Categories.SAMPLES
short_description = “Demo showing overlap box usage”
description = “Demo showing overlap usage. Overlap on a camera position, if it hits a box it turns red. Press play (space) to run the simulation.”

def create(self, stage):
    self._stage = stage
    self.defaultPrimPath = str(stage.GetDefaultPrim().GetPath())
    createSceneQueryBase(stage)
    self._debugDraw = _debugDraw.acquire_debug_draw_interface()

def report_hit(self, hit):
    hitColor = Vt.Vec3fArray([Gf.Vec3f(180.0 / 255.0, 16.0 / 255.0, 0.0)])
    usdGeom = UsdGeom.Mesh.Get(self._stage, hit.rigid_body)
    usdGeom.GetDisplayColorAttr().Set(hitColor)
    return True

def draw_box(self, origin, extent):
    color = 4283782485
    minimum = carb.Float3(origin[0] - extent[0], origin[1] - extent[1], origin[2] - extent[2])
    maximum = carb.Float3(origin[0] + extent[0], origin[1] + extent[1], origin[2] + extent[2])
    self._debugDraw.draw_line(carb.Float3(minimum[0], minimum[1], minimum[2]),color, carb.Float3(maximum[0], minimum[1], minimum[2]), color)
    self._debugDraw.draw_line(carb.Float3(maximum[0], minimum[1], minimum[2]),color, carb.Float3(maximum[0], maximum[1], minimum[2]), color)
    self._debugDraw.draw_line(carb.Float3(maximum[0], maximum[1], minimum[2]),color, carb.Float3(minimum[0], maximum[1], minimum[2]), color)
    self._debugDraw.draw_line(carb.Float3(minimum[0], maximum[1], minimum[2]),color, carb.Float3(minimum[0], minimum[1], minimum[2]), color)
    self._debugDraw.draw_line(carb.Float3(minimum[0], minimum[1], minimum[2]),color, carb.Float3(minimum[0], minimum[1], maximum[2]), color)
    self._debugDraw.draw_line(carb.Float3(minimum[0], minimum[1], maximum[2]),color, carb.Float3(maximum[0], minimum[1], maximum[2]), color)
    self._debugDraw.draw_line(carb.Float3(maximum[0], minimum[1], maximum[2]),color, carb.Float3(maximum[0], maximum[1], maximum[2]), color)
    self._debugDraw.draw_line(carb.Float3(maximum[0], maximum[1], maximum[2]),color, carb.Float3(minimum[0], maximum[1], maximum[2]), color)
    self._debugDraw.draw_line(carb.Float3(minimum[0], maximum[1], maximum[2]),color, carb.Float3(minimum[0], minimum[1], maximum[2]), color)
    self._debugDraw.draw_line(carb.Float3(maximum[0], minimum[1], minimum[2]),color, carb.Float3(maximum[0], minimum[1], maximum[2]), color)
    self._debugDraw.draw_line(carb.Float3(maximum[0], maximum[1], minimum[2]),color, carb.Float3(maximum[0], maximum[1], maximum[2]), color)
    self._debugDraw.draw_line(carb.Float3(minimum[0], maximum[1], minimum[2]),color, carb.Float3(minimum[0], maximum[1], maximum[2]), color)

def update(self, stage, dt, viewport, physxIFace):
    self._stage = stage
    viewport_window = viewport.get_viewport_window()
    activeCamera = viewport_window.get_active_camera()
    cameraPos = viewport_window.get_camera_position(activeCamera)  
    cameraForward = viewport_window.get_camera_forward(activeCamera)      
    if cameraPos[0]:
        origColor = Vt.Vec3fArray([Gf.Vec3f(71.0 / 255.0, 165.0 / 255.0, 1.0)])            
        usdGeom = UsdGeom.Mesh.Get(stage, self.defaultPrimPath + "/boxActor0")
        usdGeom.GetDisplayColorAttr().Set(origColor)
        usdGeom = UsdGeom.Mesh.Get(stage, self.defaultPrimPath + "/boxActor1")
        usdGeom.GetDisplayColorAttr().Set(origColor)
        usdGeom = UsdGeom.Mesh.Get(stage, self.defaultPrimPath + "/boxActor2")
        usdGeom.GetDisplayColorAttr().Set(origColor)

        origin = carb.Float3(cameraPos[1], cameraPos[2], cameraPos[3])
        forwardDir = carb.Float3(cameraForward[1], cameraForward[2], cameraForward[3])       
        origin[0] = origin[0] + forwardDir[0] * 800.0
        origin[1] = origin[1] + forwardDir[1] * 800.0
        origin[2] = origin[2] + forwardDir[2] * 800.0

        rot = carb.Float4(0.0, 0.0, 0.0, 1.0)
        extent = carb.Float3(100.0, 100.0, 100.0)
        self.draw_box(origin, extent)
        numHits = get_physx_scene_query_interface().overlap_box(extent, origin, rot, self.report_hit, False)

Thans for the demo code here, so I am wondering the overlap_box method only checks for collision with a box shaped prim, right? I cannot find any documentation on this method but it seems that the parameters extent, origin, rot describe a box. So my question here is, is there any way to check for collision with an arbitrarely shaped prim I imported myself from a mesh? I guess this must be somehow doable, but I do not find any API to work with…

PhysX has these overlap queries on 2 arbitrary meshes, but they are not currently exposed on the python side.
https://gameworksdocs.nvidia.com/PhysX/4.1/documentation/physxguide/Manual/GeometryQueries.html?highlight=overlap

We currently have simple raycast, overlapbox, sphere, etc exposed on the python side. Something @AlesBorovicka might consider if @fastblizzard could elaborate more on your usage.

Another option is using the contact sensor we’re introducing soon in June but that reports collision contacts instead.

Exposing convexMesh sweeps (we cant sweep non-convex meshes) is something that I was considering to expose, but its really tricky to implement as the convex mesh needs to be cooked first, which is not really obvious. Because the physics representation does not exist it would be very common that the first query would be very expensive as the convex cooking would happen. So I am a bit reluctant to add this so far, if there is a use case, it could be added. But we will need to document well what is going on.
There is already a separate work on quering non convex meshes within the PhysX SDK, but thats not yet ready. As Loc said, what is the exact usage here please?

Hey @HaiLocLu @AlesBorovicka ! thanks for the reply.

→ Yeah, thats what I have found too and this was the reason I thought it might be doable.

So we ware trying to sample grasp poses and therefore we have to check whether a grasp config (pose + grippermesh) is colliding with the scene very fast without actually altering the scene.

Thanks all! Cheers

I see so, in this case if the colliders are already existing in the scene, then the cooking should have happen and the query would be fast. I can expose the convex mesh queries for next release, but without the precooked data there might be hitches.

Hey, this would be very kind of you. I do not actually understand what you mean by cooking. Can you help me out here?

Thanks!

Convex sweep would take as an input a mesh and that mesh is going to be used for the collision detection. But this mesh needs to be cooked, which means the input points needs to be taken a convex approximation needs to be computed. Since we cant do a query with the raw mesh data. So the cooking needs to happen and that would happen the first time the mesh is going to be used (then the cooked data would be stored).