| 1 | // |
| 2 | // Redistribution and use in source and binary forms, with or without |
| 3 | // modification, are permitted provided that the following conditions |
| 4 | // are met: |
| 5 | // * Redistributions of source code must retain the above copyright |
| 6 | // notice, this list of conditions and the following disclaimer. |
| 7 | // * Redistributions in binary form must reproduce the above copyright |
| 8 | // notice, this list of conditions and the following disclaimer in the |
| 9 | // documentation and/or other materials provided with the distribution. |
| 10 | // * Neither the name of NVIDIA CORPORATION nor the names of its |
| 11 | // contributors may be used to endorse or promote products derived |
| 12 | // from this software without specific prior written permission. |
| 13 | // |
| 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY |
| 15 | // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| 17 | // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
| 18 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| 19 | // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| 20 | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| 21 | // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| 22 | // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 23 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 24 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 25 | // |
| 26 | // Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved. |
| 27 | // Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. |
| 28 | // Copyright (c) 2001-2004 NovodeX AG. All rights reserved. |
| 29 | |
| 30 | |
| 31 | #ifndef PX_PHYSICS_SCENEQUERYMANAGER |
| 32 | #define PX_PHYSICS_SCENEQUERYMANAGER |
| 33 | /** \addtogroup physics |
| 34 | @{ */ |
| 35 | |
| 36 | #include "PxSceneDesc.h" |
| 37 | #include "CmBitMap.h" |
| 38 | #include "PsArray.h" |
| 39 | #include "SqPruner.h" |
| 40 | #include "PsMutex.h" |
| 41 | #include "PxActor.h" // needed for offset table |
| 42 | #include "ScScene.h" |
| 43 | // threading |
| 44 | #include "PsSync.h" |
| 45 | |
| 46 | namespace physx |
| 47 | { |
| 48 | namespace Scb |
| 49 | { |
| 50 | class Scene; |
| 51 | class Shape; |
| 52 | class Actor; |
| 53 | } |
| 54 | |
| 55 | namespace Gu |
| 56 | { |
| 57 | class BVHStructure; |
| 58 | } |
| 59 | |
| 60 | namespace Sq |
| 61 | { |
| 62 | typedef size_t PrunerData; |
| 63 | #define SQ_INVALID_PRUNER_DATA 0xffffffff |
| 64 | |
| 65 | struct PrunerPayload; |
| 66 | class Pruner; |
| 67 | class CompoundPruner; |
| 68 | |
| 69 | // PT: extended pruner structure. We might want to move the additional data to the pruner itself later. |
| 70 | struct PrunerExt |
| 71 | { |
| 72 | PrunerExt(); |
| 73 | ~PrunerExt(); |
| 74 | |
| 75 | void init(PxPruningStructureType::Enum type, PxU64 contextID, PxU32 sceneLimit); |
| 76 | void flushMemory(); |
| 77 | void preallocate(PxU32 nbShapes); |
| 78 | void flushShapes(PxU32 index); |
| 79 | |
| 80 | void addToDirtyList(PrunerHandle handle); |
| 81 | Ps::IntBool isDirty(PrunerHandle handle) const; |
| 82 | void removeFromDirtyList(PrunerHandle handle); |
| 83 | void growDirtyList(PrunerHandle handle); |
| 84 | |
| 85 | PX_FORCE_INLINE PxPruningStructureType::Enum type() const { return mPrunerType; } |
| 86 | PX_FORCE_INLINE const Pruner* pruner() const { return mPruner; } |
| 87 | PX_FORCE_INLINE Pruner* pruner() { return mPruner; } |
| 88 | PX_FORCE_INLINE PxU32 timestamp() const { return mTimestamp; } |
| 89 | PX_FORCE_INLINE void invalidateTimestamp() { mTimestamp++; } |
| 90 | |
| 91 | private: |
| 92 | Pruner* mPruner; |
| 93 | Cm::BitMap mDirtyMap; |
| 94 | Ps::Array<PrunerHandle> mDirtyList; |
| 95 | PxPruningStructureType::Enum mPrunerType; |
| 96 | PxU32 mTimestamp; |
| 97 | |
| 98 | PX_NOCOPY(PrunerExt) |
| 99 | |
| 100 | friend class SceneQueryManager; |
| 101 | }; |
| 102 | |
| 103 | typedef Ps::Pair<PrunerCompoundId, PrunerHandle> CompoundPair; |
| 104 | typedef Ps::CoalescedHashSet<CompoundPair > CompoundPrunerSet; |
| 105 | // AB: extended compoud pruner structure, buffers compound shape changes and flushes them. |
| 106 | struct CompoundPrunerExt |
| 107 | { |
| 108 | CompoundPrunerExt(); |
| 109 | ~CompoundPrunerExt(); |
| 110 | |
| 111 | void flushMemory(); |
| 112 | void preallocate(PxU32 nbShapes); |
| 113 | void flushShapes(); |
| 114 | |
| 115 | void addToDirtyList(PrunerCompoundId compoundId, PrunerHandle handle); |
| 116 | Ps::IntBool isDirty(PrunerCompoundId compoundId, PrunerHandle handle) const; |
| 117 | void removeFromDirtyList(PrunerCompoundId compoundId, PrunerHandle handle); |
| 118 | |
| 119 | PX_FORCE_INLINE const CompoundPruner* pruner() const { return mPruner; } |
| 120 | PX_FORCE_INLINE CompoundPruner* pruner() { return mPruner; } |
| 121 | |
| 122 | private: |
| 123 | CompoundPruner* mPruner; |
| 124 | CompoundPrunerSet mDirtyList; |
| 125 | |
| 126 | PX_NOCOPY(CompoundPrunerExt) |
| 127 | |
| 128 | friend class SceneQueryManager; |
| 129 | }; |
| 130 | |
| 131 | |
| 132 | struct DynamicBoundsSync : public Sc::SqBoundsSync |
| 133 | { |
| 134 | virtual void sync(const PrunerHandle* handles, const PxU32* indices, const PxBounds3* bounds, PxU32 count, const Cm::BitMap& dirtyShapeSimMap); |
| 135 | |
| 136 | Pruner* mPruner; |
| 137 | PxU32* mTimestamp; |
| 138 | }; |
| 139 | |
| 140 | class SceneQueryManager : public Ps::UserAllocated |
| 141 | { |
| 142 | PX_NOCOPY(SceneQueryManager) |
| 143 | public: |
| 144 | SceneQueryManager(Scb::Scene& scene, PxPruningStructureType::Enum staticStructure, |
| 145 | PxPruningStructureType::Enum dynamicStructure, PxU32 dynamicTreeRebuildRateHint, |
| 146 | const PxSceneLimits& limits); |
| 147 | ~SceneQueryManager(); |
| 148 | |
| 149 | PrunerData addPrunerShape(const Scb::Shape& scbShape, const Scb::Actor& scbActor, bool dynamic, PrunerCompoundId compoundId, const PxBounds3* bounds=NULL, bool hasPrunerStructure = false); |
| 150 | void removePrunerShape(PrunerCompoundId compoundId, PrunerData shapeData); |
| 151 | const PrunerPayload& getPayload(PrunerCompoundId compoundId, PrunerData shapeData) const; |
| 152 | |
| 153 | void addPruningStructure(const Sq::PruningStructure& ps); |
| 154 | void addCompoundShape(const Gu::BVHStructure& bvhStructure, PrunerCompoundId compoundId, const PxTransform& compoundTransform, PrunerData* prunerData, const Scb::Shape** scbShapes, const Scb::Actor& scbActor); |
| 155 | |
| 156 | public: |
| 157 | PX_FORCE_INLINE Scb::Scene& getScene() const { return mScene; } |
| 158 | PX_FORCE_INLINE PxU32 getDynamicTreeRebuildRateHint() const { return mRebuildRateHint; } |
| 159 | |
| 160 | PX_FORCE_INLINE const PrunerExt& get(PruningIndex::Enum index) const { return mPrunerExt[index]; } |
| 161 | PX_FORCE_INLINE PrunerExt& get(PruningIndex::Enum index) { return mPrunerExt[index]; } |
| 162 | |
| 163 | PX_FORCE_INLINE const CompoundPrunerExt& getCompoundPruner() const { return mCompoundPrunerExt; } |
| 164 | |
| 165 | void preallocate(PxU32 staticShapes, PxU32 dynamicShapes); |
| 166 | void markForUpdate(PrunerCompoundId compoundId, PrunerData s); |
| 167 | void setDynamicTreeRebuildRateHint(PxU32 dynTreeRebuildRateHint); |
| 168 | |
| 169 | void flushUpdates(); |
| 170 | void forceDynamicTreeRebuild(bool rebuildStaticStructure, bool rebuildDynamicStructure); |
| 171 | void sceneQueryBuildStep(PruningIndex::Enum index); |
| 172 | |
| 173 | void updateCompoundActors(Sc::BodyCore*const* bodies, PxU32 numBodies); |
| 174 | void updateCompoundActor(PrunerCompoundId compoundId, const PxTransform& compoundTransform, bool dynamic); |
| 175 | void removeCompoundActor(PrunerCompoundId compoundId, bool dynamic); |
| 176 | |
| 177 | DynamicBoundsSync& getDynamicBoundsSync() { return mDynamicBoundsSync; } |
| 178 | |
| 179 | bool prepareSceneQueriesUpdate(PruningIndex::Enum index); |
| 180 | |
| 181 | // Force a rebuild of the aabb/loose octree etc to allow raycasting on multiple threads. |
| 182 | void afterSync(PxSceneQueryUpdateMode::Enum updateMode); |
| 183 | void shiftOrigin(const PxVec3& shift); |
| 184 | |
| 185 | void flushMemory(); |
| 186 | private: |
| 187 | PrunerExt mPrunerExt[PruningIndex::eCOUNT]; |
| 188 | CompoundPrunerExt mCompoundPrunerExt; |
| 189 | |
| 190 | PxU32 mRebuildRateHint; |
| 191 | |
| 192 | Scb::Scene& mScene; |
| 193 | |
| 194 | // threading |
| 195 | shdfnd::Mutex mSceneQueryLock; // to make sure only one query updates the dirty pruner structure if multiple queries run in parallel |
| 196 | |
| 197 | DynamicBoundsSync mDynamicBoundsSync; |
| 198 | |
| 199 | volatile bool mPrunerNeedsUpdating; |
| 200 | |
| 201 | void flushShapes(); |
| 202 | }; |
| 203 | |
| 204 | /////////////////////////////////////////////////////////////////////////////// |
| 205 | |
| 206 | // PT: TODO: replace PrunerData with just PxU32 to save memory on Win64. Breaks binary compatibility though. |
| 207 | // PT: was previously called 'ActorShape' but does not contain an actor or shape pointer, contrary to the Np-level struct with the same name. |
| 208 | // PT: it only contains a pruner index (0 or 1) and a pruner handle. Hence the new name. |
| 209 | PX_FORCE_INLINE PrunerData createPrunerData(PxU32 index, PrunerHandle h) { return PrunerData((h << 1) | index); } |
| 210 | PX_FORCE_INLINE PxU32 getPrunerIndex(PrunerData data) { return PxU32(data & 1); } |
| 211 | PX_FORCE_INLINE PrunerHandle getPrunerHandle(PrunerData data) { return PrunerHandle(data >> 1); } |
| 212 | |
| 213 | /////////////////////////////////////////////////////////////////////////////// |
| 214 | |
| 215 | |
| 216 | } // namespace Sq |
| 217 | |
| 218 | } |
| 219 | |
| 220 | /** @} */ |
| 221 | #endif |
| 222 | |