Scene Queries
Introduction
PhysX provides some methods in PxScene to perform collision queries on actors and additional shapes in the scene. There are three types of queries: ray casting, scanning, and overlapping. Each query can return a single result or multiple results. In a broad sense, each query traverses the culling structure containing scene objects, performs precision testing using the GeometryQuery function (see geometric queries), and accumulates the results. Filtering may occur before or after precision testing.
This scenario uses two different query structures, one for pxrigidstaticator and the other for pxrigidbody actor (PxRigidDynamic and pxarticlelink). These two structures can be configured to use different culling implementations, depending on the required speed / spatial characteristics (see PxPruningStructureType).
Basic queries
Raycasts
PxScene:: raycast() query intersects the user-defined light with the whole scene. The simplest use case of raycast() query is to find the closest hit along a given light, as shown below:
PxScene* scene; PxVec3 origin = ...; // [in] Ray origin PxVec3 unitDir = ...; // [in] Normalized ray direction PxReal maxDistance = ...; // [in] Raycast max distance PxRaycastBuffer hit; // [out] Raycast results // Raycast against all static & dynamic objects (no filtering) // The main result from this call is the closest hit, stored in the 'hit.block' structure bool status = scene->raycast(origin, unitDir, maxDistance, hit); if (status) applyDamage(hit.block.position, hit.block.normal);
In this code snippet, the PxRaycastBuffer object is used to receive the results from the raycasting query. If raycast() is hit, the call to raycast() returns true. hit.hadBlock is also set to true if there is a hit. The distance of the ray casting must be within [0, inf).
Ray casting results include position, normal, hit distance, shape and actor, as well as the face index with UV coordinates of triangular mesh and height field. Before using the query results, please check the PxHitFlag:: position, normal, eDISTANCE and eUV flags, because they are not set in some cases.
Sweeps
PxScene:: sweep() query is geometrically similar to raycast(): the PxGeometry shape scans from the specified initial pose with the specified maximum length direction unit Dir to find the influence points between the geometry and the scene object. The maximum distance of the scan must be within [0, inf) and will be clamped to PX_MAX_SWEEP_DISTANCE defined in the file PxScene.h.
The allowed shapes are box, ball, capsule and convex.
The PxSweepBuffer object is used to receive the results from the sweep() query:
PxSweepBuffer hit; // [out] Sweep results PxGeometry sweepShape = ...; // [in] swept shape PxTransform initialPose = ...; // [in] initial shape pose (at distance=0) PxVec3 sweepDirection = ...; // [in] normalized sweep direction bool status = scene->sweep(sweepShape, initialPose, sweepDirection, sweepDistance, hit);
The scan results include position, normal, hit distance, shape and actor, as well as face index of triangular mesh and height field.
Overlaps
PxScene:: overlap() query searches for any overlapping objects in the scene in the area surrounded by the specified shape. The area is specified as transformed box, sphere, capsule or convex geometry.
The PxOverlapBuffer object is used to receive the results from the overlap() query:
PxOverlapBuffer hit; // [out] Overlap results PxGeometry overlapShape = ...; // [in] shape to test for overlaps PxTransform shapePose = ...; // [in] initial shape pose (at distance=0) PxOverlapBuffer hit; bool status = scene->overlap(overlapShape, shapePose, hit);
Overlapping results include only actor / shape and face indexes because there is no single intersection.
Touching and blocking hits
For queries with multiple results, we distinguish between touch and block hits. Whether a hit touches or blocks the filtering logic implemented by the user. Intuitively, blocking hits prevents further progress of ray casting or sweeping along its path, and records touch hits, but allows rays or scans to continue. Therefore, the multiple hit query will return the closest blocked hit, if any, and any closer touch hits. If there are no blocked hits, all touch hits will be returned.
For more information, see the filtering section.
Query modes
Closest hit
The default operation mode for all three query types is closest hit. The query finds all blocking hits, selects the hit with the smallest distance, and reports it in the PxHitBuffer:: block member.
- For the overlap() query, select any blocked hit as the reported blocked hit (for all overlap() hits, the distance is treated as zero).
Any hit
All three query types can be run in any hit mode. This is a performance prompt for the query system, indicating that there is no need to find the closest hit - any hit encountered can be found. This pattern is most commonly used for Boolean blocking / non blocking queries. The performance improvement may be 3x or more, depending on the solution. To activate this mode, use PxQueryFlag:: eANY_HIT filter data flag and set it as PxQueryFilterData object, for example:
PxQueryFilterData fd; fd.flags |= PxQueryFlag::eANY_HIT; // note the OR with the default value bool status = scene->raycast(origin, unitDir, maxDistance, hit, PxHitFlags(PxHitFlag::eDEFAULT), fdAny);
Multiple hits
All three query types (ray casting, overlap, scan) can also report multiple hits of objects in the scene.
- To activate this mode for raycasting, use the PxRaycastBuffer constructor, which contains the user supplied buffer for touch hits.
- In this mode, all hits default to the "touch" type and are recorded in the PxRaycastBuffer:: touches array.
For example:
PxScene* scene; PxVec3 origin = ...; // [in] Ray origin PxVec3 unitDir = ...; // [in] Normalized ray direction PxReal maxDistance = ...; // [in] Raycast max distance const PxU32 bufferSize = 256; // [in] size of 'hitBuffer' PxRaycastHit hitBuffer[bufferSize]; // [out] User provided buffer for results PxRaycastBuffer buf(hitBuffer, bufferSize); // [out] Blocking and touching hits stored here // Raycast against all static & dynamic objects (no filtering) // The main result from this call are all hits along the ray, stored in 'hitBuffer' scene->raycast(origin, unitDir, maxDistance, buf); for (PxU32 i = 0; i < buf.nbTouches; i++) animateLeaves(buf.touches[i]);
The same mechanism is used for overlap (using PxOverlapBuffer and PxOverlapHit []) and scanning (PxSweepBuffer and PxSweepHit []).
Multiple hits with blocking hit
In the above multi click clip, we only expect to touch the click. If blocking hits and touch hits are encountered, they are reported in the PxHitBuffer:: block member, and the touch buffer will contain only closer touch hits. This combination is useful in situations such as bullets passing through windows (breaking them on the way) or leaves (making them rustle) until they hit blocking objects (concrete walls):
// same initialization code as in the snippet for multiple hits bool hadBlockingHit = scene->raycast(origin, unitDir, maxDistance, buf); if (hadBlockingHit) drawWallDecal(buf.block); for (PxU32 i = 0; i < buf.nbTouches; i++) { assert(buf.touches[i].distance <= buf.block.distance); animateLeaves(buf.touches[i]); }
-
By default, when a touch buffer is provided, it is assumed that the hit is a touch, and the filter callback should return PxQueryHitType:: eBLOCK to indicate that the hit is blocking. For more information, see filtering.
-
For the overlap() query, all touch hits will be recorded even if a block hit is encountered and the PxQueryFlag:: eNO_BLOCK flag is set.
Filtering
Filtering controls how shapes are excluded from scene query results and how results are reported. All three query types support the following filter parameters:
- PxQueryFilterData structure, including PxQueryFlags and PxFilterData
- An optional PxQueryFilterCallback
PxQueryFlag::eSTATIC, PxQueryFlag::eDYNAMIC
The PxQueryFlag:: static and PxQueryFlag:: eDYNAMIC flags control whether queries should contain shapes from static and / or dynamic query structures. This is the most effective way to filter out all static / dynamic shapes. For example, the explosion effect of applying forces to all dynamics in a region can use a spherical overlap query, and only the PxQueryFlag:: eDYNAMIC flag can exclude all static objects because forces cannot be applied to static objects. By default, statistics and dynamics are included in query results.
For example:
PxScene* scene; PxVec3 origin = ...; // [in] Ray origin PxVec3 unitDir = ...; // [in] Normalized ray direction PxReal maxDistance = ...; // [in] Raycast max distance PxRaycastBuffer hit; // [out] Raycast results // [in] Define filter for static objects only PxQueryFilterData filterData(PxQueryFlag::eSTATIC); // Raycast against static objects only // The main result from this call is the boolean 'status' bool status = scene->raycast(origin, unitDir, maxDistance, hit, PxHitFlag::eDEFAULT, filterData);
PxQueryFlag::ePREFILTER, PxQueryFlag::ePOSTFILTER
The scene query is executed in three stages: wide phase, medium phase and narrow phase.
- The wide phase traverses the global scene space partition structure to find the candidates of medium and narrow phase.
- The middle phase traverses the triangular mesh and the internal elimination structure of the height field to find the smaller subset of triangles in the mesh reported by the wide phase.
- The narrow phase performs a precise intersection test (ray test for ray casting () queries and a precise scan shape test or overlap test for scan () and overlap () queries).
To implement custom filtering in a query, set the PxQueryFlag:: prefix and / or PxQueryFlag:: eopostfilter flag and subclass PxQueryFilterCallback with the required filtering logic.
- Pre filtering occurs before the middle and narrow phases and allows the shape to be effectively discarded before a potentially expensive accurate collision test. For triangular meshes, height fields, convex surfaces, and most scans, these tests are more expensive than ray casting and overlap tests involving only simple shapes such as spheres, capsules, and boxes.
- Post filtration occurs after the narrow phase test, Therefore, you can use test results (such as PxRaycastHit.position) to determine whether hits should be discarded. These results can be accessed through the hit input parameter to filter the callback (PxQueryFilterCallback:: p ostFilter). For example, use static_cast < pxraycasthit & > (HIT) to access data specific to raycasting queries, and similar overlaps (PxOverlapHit) and scanning (PxSweepHit).
The implementation of the filter callback returns PxQueryHitType results.
- eNONE indicates that the hit should be discarded.
- eBLOCK indicates that the hit is blocking.
- eTOUCH indicates that the hit is touching.
Whenever a raycast(), sweep(), or overlap() query is called with the non-zero PxHitCallback:: nbTouches and PxHitCallback:: touches parameters, it is reported that eTOUCH type hits (touch distance < = block distance) are not further from the nearest eBLOCK type hits. For example, to record all hits in a raycasting query, always return eTOUCH.
Returning eTOUCH from the filter callback requires that the hit buffer query parameter has a non-zero:: touches array, otherwise PhysX will generate an error in the checked build and discard any touch hits.
eBLOCK should not be returned from user filters that overlap (). Doing so will result in undefined behavior and will issue a warning. If the PxQueryFlag:: eNO_BLOCK flag is set, eBLOCK will automatically convert to electronic touch and suppress the display of warnings.
PxQueryFlag::eANY_HIT
Use this flag to force a query to report the first hit encountered (which may not be the closest) as a blocked hit. Performance may be more than three times faster, depending on the scenario. The best gain can be expected for long ray casting / scanning with nearby intersecting objects, or overlapping with multiple intersecting objects.
Also see PxHitFlag::eMESH_ANY
PxQueryFlag::eNO_BLOCK
If you want to override the eBLOCK value returned from the filter to eTOUCH, Or if a hit is not expected to be blocked (in this case, this flag is used as a performance hint), use this flag. Then, all hits will be reported as touches regardless of the return value of the filter callback. When using this flag, the hit callback / buffer object provided to the query needs to have a non-zero PxHitBuffer:: touches buffer. Significant hits should be expected only in the case of contact hit buffer overflow Improved performance.
This flag will override the return values of the pre filter function and the post filter function, so hits previously returned as blocking will be returned as touch.
PxFilterData fixed function filtering
PxFilterData provides a fast fixed function filter. PxFilterData is a 4 * 32-bit mask used by the built-in filtering equation. Each shape has a bitmask (set by PxShape:: setQueryFilterData()), and the query also has a bitmask.
Batch queries and non batch queries use query data in different ways (see below for batch queries). For queries that are not entered, the following rules apply:
- If the bitmasks of the query are all zero, the custom filtering and intersection test will proceed as usual.
- Otherwise, if the bitwise AND value of the bitmask of the query AND the bitmask of the shape is zero, the shape is skipped
Or in other words:
PxU32 keep = (query.word0 & object.word0) | (query.word1 & object.word1) | (query.word2 & object.word2) | (query.word3 & object.word3);
This hard coded formula can provide simple filtering while avoiding the function call overhead of filtering callbacks. For example, to simulate the behavior of a PhysX 2 active group, define the group as follows:
enum ActiveGroup { GROUP1 = (1<<0), GROUP2 = (1<<1), GROUP3 = (1<<2), GROUP4 = (1<<3), ... };
When you create shapes, you can assign them to groups, such as GROUP1:
PxShape* shape; // Previously created shape PxFilterData filterData; filterData.word0 = GROUP1; shape->setQueryFilterData(filterData);
Or more groups, such as GROUP1 and GROUP3:
PxShape* shape; // Previously created shape PxFilterData filterData; filterData.word0 = GROUP1|GROUP3; shape->setQueryFilterData(filterData);
When executing a scenario query, select the group in which the query is active (for example, GROUP2 and GROUP3), as shown below:
PxScene* scene; PxVec3 origin = ...; // [in] Ray origin PxVec3 unitDir = ...; // [in] Normalized ray direction PxReal maxDistance = ...; // [in] Raycast max distance PxRaycastBuffer hit; // [out] Raycast results // [in] Define what parts of PxRaycastHit we're interested in const PxHitFlags outputFlags = PxHitFlag::eDISTANCE | PxHitFlag::ePOSITION | PxHitFlag::eNORMAL; // [in] Raycast against GROUP2 and GROUP3 PxQueryFilterData filterData = PxQueryFilterData(); filterData.data.word0 = GROUP2|GROUP3; bool status = scene->raycast(origin, unitDir, maxDistance, hit, outputFlags, filterData);
User defined hit callbacks for unbounded results
Queries can sometimes return very many results (for example, queries in areas with very large objects or high object density) and the cost of retaining memory buffers large enough may be too high. Classes PxRaycastCallback, PxSweepCallback, and PxOverlapCallback provide efficient callback based solutions for such schemes. For example, raycast queries with PxRaycastCallback will pass through multiple virtual pxhit Callback:: P processtouches() callback returns all touch hits:
struct UserCallback : PxRaycastCallback { UserData data; virtual PxAgain processTouches(const PxRaycastHit* buffer, PxU32 nbHits) // This callback can be issued multiple times and can be used // to process an unbounded number of touching hits. // Each reported touching hit in buffer is guaranteed to be closer than // the final block hit after the query has fully executed. { for (PxU32 i = 0; i < nbHits; i++) animateLeaves(buffer[i], data); } virtual void finalizeQuery() { drawWallDecal(this->block, data); } }; PxScene* scene; PxVec3 origin = ...; // [in] Ray origin PxVec3 unitDir = ...; // [in] Normalized ray direction PxReal maxDistance = ...; // [in] Raycast max distance UserCallback cb; cb.data = ...; scene->raycast(origin, unitDir, maxDistance, cb); // see UserCallback::processTouches
In this code fragment, the raycast () query may call processTouches multiple times, and all touch hits have been clipped to the global closest blocking hit.
- Note that if all eTOUCH results are not suitable for the provided touch buffer, and blocking hits are also found, the overhead of the query may be up to twice.
- See also PxQueryFlag:: eNO_BLOCK
Batched queries
PhysX supports batch processing of scene queries through the PxBatchQuery interface. Using this API can simplify multithreading implementation.
Batch query is deprecated in PhysX version 3.4.
- The PxBatchQuery interface facilitates batch processing and execution of multiple queries at the same time. PxBatchQuery buffers raycasting, overlapping, and scanning queries until PxBatchQuery:: execute() is called.
- Use PxScene:: createBatchQuery (const pxbatchquerydesc & DESC) to create a PxBatchQuery object.
- Hard coded filter formulas are not used for batch queries. Instead, there are two filter shaders that run accurate collision tests for each shape after (PxBatchQueryPreFilterShader) and (PxBatchQueryPostFilterShader). See PxBatchQueryDesc:: p reFilterShader and PxBatchQueryDesc:: p ostFilterShader.
- BatchQueryFilterData:: filterShaderData will be copied through the constantBlock parameter and passed to the filter shader.
- The results are written to the user-defined buffer PxBatchQueryMemory in PxBatchQueryDesc in the same order as the queries are queued in the PxBatchQuery object.
- The results and hit buffers for each query type used (raycasting, overlap, scan) are specified separately.
- These buffers can be changed before each batch query execution call. The SDK will generate warnings for batch queries with NULL results or hit buffers for the corresponding query type (raycasting, overlap, or scan).
Volume Caching
PxVolumeCache provides a mechanism to speed up scene query. This class implements caching for objects in the specified volume and provides an API similar to PxScene for raycasting, overlapping, and scanning. PxVolumeCache can provide performance improvement when querying objects in the same local space area multiple times in the same simulation framework or in subsequent frames.
Volume caching is deprecated in PhysX version 3.4.
Some expected use cases for PxVolumeCache are:
- A particle system with many ray irradiations performed on each particle from a spatially positioned cloud.
- Multiple short-range character controllers cast rays in the same area around the character.
- Caching query results across multiple frames, you can fill the cache with a larger volume on the previous frame (possibly stretching in the expected direction of movement), and then query with a smaller volume.
The cache has the maximum capacity, which is specified for dynamic and static objects in PxScene:: createVolumeCache().
For multi-threaded access purposes, any operation on the cache counts as a read call to the scene.
Filling the Cache
To populate the cache, Please call PxVolumeCache:: fill (). This will query the scene for objects that overlap the volume defined by the geometry, and convert and store the results in the internal buffer until the maximum size of static and dynamic objects is reached. cacheVolume only supports PxBoxGeometry, pxsphereometry, and PxCapsuleGeometry. The call will always refill the static and dynamic internal cache, even if the new volume is completely located before The same is true for cache volumes. It returns results of type PxVolumeCache:: FillStatus.
If the scene query subsystem has been updated since the last filling, Subsequent queries against the cache (ray casting, overlap, scan, forEach) will automatically repopulate the cache with the same volume. For static and dynamic, the update status is tracked independently, so the query may repopulate only the dynamic cache and reuse the static valid cache results. If any attempt to populate or repopulate fails, the cache is invalid and any subsequent query will attempt to populate Cache.
Querying the Cache
PxVolumeCache provides an API for ray casting, scanning and overlapping, similar to the scene query API. The main difference between signatures is that PxVolumeCache queries do not support single object caching. The query results are reported through the PxVolumeCache:: Iterator:: shapes() callback. The query may call the callback multiple times to provide multiple batches of results.
- Raycasts, overlaps, and scans for valid caches will only return results that overlap cache volumes, but all such volumes are guaranteed to be returned.
- Raycasting, overlapping, and scanning against invalid caches will fall back to the scene query. In this case, a result that does not overlap the cache volume may be returned.
Since the cache will automatically repopulate on any query whose scene has changed, these two conditions ensure that queries for caches that are completely within the cache volume will always return exactly the same shape as the query scene. If the query is not entirely within the cache volume (and the cache is valid), only those shapes that overlap the cache volume are returned. If you issue a query on a cache that has never called fill(), an error is reported.
The cache also provides a low-level forEach() mechanism for looping through cached objects. If forEach() is executed on a cache that has never called fill(), it will return without reporting an error. If the cache is invalid, forEach () will retrieve shapes that overlap the cache volume directly from the scene. This process involves the allocation of temporary buffers. If the allocation fails, forEach () will issue an error message and return.
This code snippet shows how to use PxVolumeCache:
PxScene* scene; PxVec3 poi = ...; // point of interest PxVec3 origin = ...; // [in] Ray origin PxVec3 unitDir = ...; // [in] Normalized ray direction PxReal maxDistance = ...; // [in] Raycast max distance PxRaycastBuffer hit; // [out] Raycast results const PxU32 maxStatics = 32, maxDynamics = 8; // persistent cache, valid until invalidated by object movement, // insertion or deletion PxVolumeCache* cache = scene->createVolumeCache(maxStatics, maxDynamics); cache->setMaxNbStaticShapes(64); cache->setMaxNbDynamicShapes(16); // fill the cache using a box geometry centered around the point of interest cache->fill(PxBoxGeometry(PxVec3(1.0f)), PxTransform(position)); ... // Perform multiple raycast queries using the cache PxRaycastBuffer hit; const bool status = cache->raycast(origin, unitDir, maxDistance, hit); // low level iterator for stored actor/shape pairs struct UserIterator : PxVolumeCache::Iterator { UserData userData; virtual void shapes(PxU32 count, const PxActorShape* actorShapePairs) { for (PxU32 i = 0; i < count; i++) doSomething(actorShapePairs[i].actor, actorShapePairs[i].shape, userData); } } iter; // invoke UserIterator::shapes() callback for all actor/shape pairs in the cache cache->forEach(iter);
Single Object Caching
Another special case mechanism for accelerating scene queries is the single object cache using PxQueryCache.
- This cache can provide additional acceleration and memory savings for ray casting and scanning queries in any operation mode.
- The cache object defines which shape should be tested first. For queries with high temporal consistency, this can significantly improve performance. A good strategy to capture this consistency is to simply fill the cache object of a given query with the eBLOCK result of the previous frame (the last blocking shape).
- Note that caching with past touch hits (recorded with the eTOUCH flag) may be incorrect because it will be interpreted as blocking and overwriting any filtering.
For example, AI visibility queries are likely to return the same line of sight blocking shape for multiple frames. Combining a raycasting query with a properly populated PxQueryCache object will allow PhysX to test a single shape before traversing the internal space partition structure, and can completely bypass the traversal in the case of "cache hit". For example:
PxScene* scene; PxVec3 origin = ...; // [in] Ray origin PxVec3 unitDir = ...; // [in] Normalized ray direction PxReal maxDistance = ...; // [in] Raycast max distance PxRaycastBuffer hit; // [out] Raycast results // Per-raycast persistent cache, valid from one frame to the next static PxQueryCache persistentCache; // Define cache for current frame: // - if there was a hit in the previous frame, use the cache. // - otherwise do not (PhysX requires given cache has a valid shape pointer) const PxQueryCache* cache = persistentCache.shape ? &persistentCache : NULL; // Perform a raycast query using the cache const bool status = scene->raycast(origin, unitDir, maxDistance, hit, PxHitFlags(PxHitFlag::eDEFAULT), PxQueryFilterData(), NULL, cache); if(status) { // We hit a shape. Cache it for next frame. persistentCache.shape = hit.block.shape; persistentCache.faceIndex = hit.block.faceIndex; } else { // We did not hit anything. Reset the cache for next frame. persistentCache = PxQueryCache(); }
Cache is looking for the closest block hit or using eany_ The hit flag is also useful in queries. In this case, testing the previous nearest object first can make PhysX shorten the query distance as soon as possible, so as to reduce the total narrow phase collision test and exit the traversal in advance.
PhysX does not detect stale pointers, so the application is responsible for caching the validity of objects when deleting shapes.
Overlap does not support single hit blocking cache.
PxPruningStructureType
The PhysX SDK provides different pruning structures to speed up scene query. This paragraph describes the differences between them.
Generalities
The scene query system uses two different acceleration structures, namely hierarchical grid and AABB tree.
The grid is constructed quickly in O (n) time, and the query is executed between O (1) and O (n) time, depending on the uniform distribution of objects in space. When all objects are clustered in the same grid cell, the worst-case performance is O (n).
Trees are built in O (n log (n)) time, but queries with a single result usually run in O (log (n)) time. Queries that return multiple results will traverse more trees, at worst in o (n) Returns the query of all objects in the scene in time. When the object location changes, if the maintenance time of the same topology is too long, and in pathological cases, the query performance may be reduced to o (n) time, the tree is vulnerable to degradation.
The acceleration structure must be constantly modified according to the objects to be added or deleted or the object AABB update due to changes in position or geometry. In order to minimize costs, modifications will be postponed for as long as possible. Therefore, adding or deleting objects or updating AABB occurs within a constant time of amortization, and the modification cost is deferred to the change "submission". This occurs when the next subsequent query or the next fetchResults() or the next fetchQueries(). To force an immediate commit, call the PxScene:: flushQueryUpdates() function.
The exact details of the submission process depend on the values of staticStructure and dynamicStructure specified in PxSceneDesc.
To avoid triggering automatic resizing due to inserting into the internal scene query data structure, please reserve space in advance. See PxSceneDesc:: maxNbStaticShapes and PxSceneDesc:: maxNbDynamicShapes.
PxPruningStructureType::eNONE
The acceleration structure is similar to a layered grid. Submitting changes requires a complete rebuild. This is a good choice if you want to update objects in this structure little or never.
PxPruningStructureType::eSTATIC_AABB_TREE
The acceleration structure is a tree. Submitting changes requires a complete rebuild. This is generally not recommended, but if the static Actor in the scene is created at initialization and is not modified later, it may be a good choice for staticStructure. If you often add or delete static geometry, the default is edynamic_ AABB_ The tree setting is usually a better choice, although it uses more memory than static_ AABB_ TREE.
PxPruningStructureType::eDYNAMIC_AABB_TREE
In this case, both the tree and the grid are used, and each query searches for both.
The tree was originally built by the first commit. After the tree is built, commit the changes as follows:: * re fit the tree according to the updates and deletions of the objects it contains* Add objects to the mesh. Such adding or removing the current object in the mesh, or changing the AABB of an object in the mesh, will cause the object to be regenerated.
In addition, In fetchResults During (), a new tree is built incrementally over multiple frames controlled by the dynamicTreeRebuildRateHint property of PxScene. At the beginning of the build, it will include all objects in the current tree and grid. When it is completed, after some frames, the new tree will be re fitted according to any AABB changes or deletions since the start of the build, and then replace the current tree Any objects added since the start of the build will remain in the mesh.
To force an immediate full rebuild, call PxScene:: forceDynamicTreeRebuild(). This can be useful in the following situations:
- A slow reconstruction rate is usually desirable, but occasionally a large number of added objects will produce high occupancy in the mesh, especially if the addition is local, so as to exert pressure on only a few mesh cells.
- You are moving many objects over a long distance because refitting may significantly reduce the quality of the current tree
PxSceneQueryUpdateMode
You can define what work related to scene query is done in PxScene:: fetchResults.
By default, fetchResults will synchronize the changed boundaries during simulation and update the scene query boundaries in the trimmer, which is mandatory. Other work can be optional, based on PxSceneQueryUpdateMode:
- eCOMMIT_ENABLED_BUILD_ENABLED allows new AABB tree building steps to be performed during fetchResults, and also calls pruner commit where any changes are applied. During submission, PhysX will readjust the dynamic scene query tree. If a new tree is built and the construction is completed, the tree will be exchanged with the current AABB tree.
- eCOMMIT_DISABLED_BUILD_ENABLED allows new AABB tree building steps to be performed during fetchResults. The Pruner commit is not called, which means that the refit will be performed during the first scene query after fetchResults, or it may be enforced by the PxScene:: flushSceneQueryUpdates() method.
- eCOMMIT_DISABLED_BUILD_DISABLED does not perform further scene queries. Scene query update needs to be called manually. Please refer to PxScene:: scene queriesupdate. It is recommended to call PxScene:: sceneQueriesUpdateResults immediately after fetch because the pruning structure is not updated.
PxPruningStructure
Provides access to the precomputed pruning structure used to speed up scene queries for newly added actors.
You can provide a trim structure for PxScene:: addActors. Then, the Actor scene query shape will be directly merged into the scene AABB tree without recalculation of the AABB tree:
// Create pruning structure from given actors. PxPruningStructure* ps = PxPhysics::createPruningStructure(&actors[0], (PxU32)actors.size()); // Add actors into a scene together with the precomputed pruning structure. PxScene::addActors(*ps); ps->release();
PxPruningStructure objects can be serialized into collections with their execution components.
For the use of PxPruningStructure, see snippet prunerserialization.
A typical use case of pxpruning structure is a large-scale world scenario in which tightly positioned actor blocks are streamed.
Merge process
The merging process of scenario query acceleration structure varies with PxPruningStructureType: * static_ AABB_ Tree - the trim structure is merged directly into the AABtree of the scene. This may make the tree unbalanced. It is recommended to recalculate the static tree at some time* eDYNAMIC_ AABB_ The tree - pruning structure is merged into the temporary pruning structure until the newly optimized AABB tree of the scene is calculated.