NVIDIAGameWorks/PhysX

Using scene queries without simulation

nikita-one opened this issue · 6 comments

Hi, I have a question about dynamic actors. The way I (try to) work with PhysX is as follows:

  1. Create a bunch of static actors for static geometry.
  2. Create and place kinematic dynamic actors at specific poses.
  3. Run a bunch of scene queries
  4. Do the previous two steps over and over.

At no point do I call "simulate". Is this a valid way to use the library?
After I move/add/remove kinematic actors to/from the scene, do I have to somehow manually tell PhysX to update its internal structures before calling the queries if I don't plan on calling simulate?

Hi, have you tried? What issues did you run into? I use PxScene::raycast this way, without having to call ::simulate() and it seems fine.

Well, sort of.

I mostly work with static actors at the moment, and those work fine without simulation (as one probably might expect). Although I do call simulate once after I place them on the scene (not sure if it actually does anything).

As for dynamic actors, I am just starting with those. They seem to properly update their positions for scene queries when I move them, but I don't have a test case yet that would be easy to validate, so I thought I might as well ask.

P.S. Today I managed to find the answer in documentation, so I will just quote it below in case anyone stumbles across this issue:

Acceleration structures must be continually modified in accordance with objects being added or removed, or object AABB updates due to changes in position or geometry. To minimize the cost, modifications are deferred for as long as possible. Thus adding or removing objects or updating AABBs occurs in amortized constant time, with the cost of modifications deferred until the changes 'commit'. This happens on the next subsequent query or the next fetchResults() or the next fetchQueries(). To force an immediate commit, call the PxScene::flushQueryUpdates() function.

(from PxPruningStructureType section of the manual)

I'll need to double-check the code but you might run into performance issues eventually if you don't call simulate() / fetchResults(), or if you only call flushQueryUpdates(). You might also have to call sceneQueriesUpdate(), otherwise the current tree will be "refit" and new objects will be added to a secondary pruning structure, but IIRC the new tree's build step will be missing.

I'll need to double-check the code but you might run into performance issues eventually if you don't call simulate() / fetchResults(), or if you only call flushQueryUpdates(). You might also have to call sceneQueriesUpdate(), otherwise the current tree will be "refit" and new objects will be added to a secondary pruning structure, but IIRC the new tree's build step will be missing.

Oh, thanks for the warning. I saw a mention of sceneQueriesUpdate() in documentation but it was not immediately obvious when/if I should call it. I'll try it out.
Another thing that was not quite clear is what forceDynamicTreeRebuild() method does. Is it basically a synchronous equivalent of sceneQueriesUpdate(), or does it have a different purpose entirely?

sceneQueriesUpdate() rebuilds the tree incrementally over N frames. Thus, each call to this function should be relatively cheap.

forceDynamicTreerebuild() rebuilds the tree immediately, and it can be arbitrarily expensive.

Got it, thanks!