From 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 Mon Sep 17 00:00:00 2001 From: git perforce import user Date: Tue, 25 Oct 2016 12:29:14 -0600 Subject: Initial commit: PhysX 3.4.0 Update @ 21294896 APEX 1.4.0 Update @ 21275617 [CL 21300167] --- .../Source/LowLevelAABB/src/BpBroadPhaseSapAux.cpp | 876 +++++++++++++++++++++ 1 file changed, 876 insertions(+) create mode 100644 PhysX_3.4/Source/LowLevelAABB/src/BpBroadPhaseSapAux.cpp (limited to 'PhysX_3.4/Source/LowLevelAABB/src/BpBroadPhaseSapAux.cpp') diff --git a/PhysX_3.4/Source/LowLevelAABB/src/BpBroadPhaseSapAux.cpp b/PhysX_3.4/Source/LowLevelAABB/src/BpBroadPhaseSapAux.cpp new file mode 100644 index 00000000..98b8e482 --- /dev/null +++ b/PhysX_3.4/Source/LowLevelAABB/src/BpBroadPhaseSapAux.cpp @@ -0,0 +1,876 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#include "CmPhysXCommon.h" +#include "BpBroadPhaseSapAux.h" +#include "PsFoundation.h" + +namespace physx +{ + +namespace Bp +{ + +PX_FORCE_INLINE void PxBpHandleSwap(BpHandle& a, BpHandle& b) +{ + const BpHandle c = a; a = b; b = c; +} + +PX_FORCE_INLINE void Sort(BpHandle& id0, BpHandle& id1) +{ + if(id0>id1) PxBpHandleSwap(id0, id1); +} + +PX_FORCE_INLINE bool DifferentPair(const BroadPhasePair& p, BpHandle id0, BpHandle id1) +{ + return (id0!=p.mVolA) || (id1!=p.mVolB); +} + +PX_FORCE_INLINE int Hash32Bits_1(int key) +{ + key += ~(key << 15); + key ^= (key >> 10); + key += (key << 3); + key ^= (key >> 6); + key += ~(key << 11); + key ^= (key >> 16); + return key; +} + +PX_FORCE_INLINE PxU32 Hash(BpHandle id0, BpHandle id1) +{ + return PxU32(Hash32Bits_1( int(PxU32(id0)|(PxU32(id1)<<16)) )); +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +SapPairManager::SapPairManager() : + mHashTable (NULL), + mNext (NULL), + mHashSize (0), + mHashCapacity (0), + mMinAllowedHashCapacity (0), + mActivePairs (NULL), + mActivePairStates (NULL), + mNbActivePairs (0), + mActivePairsCapacity (0), + mMask (0) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +SapPairManager::~SapPairManager() +{ + PX_ASSERT(NULL==mHashTable); + PX_ASSERT(NULL==mNext); + PX_ASSERT(NULL==mActivePairs); + PX_ASSERT(NULL==mActivePairStates); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +void SapPairManager::init(const PxU32 size) +{ + mHashTable=reinterpret_cast(PX_ALLOC(ALIGN_SIZE_16(sizeof(BpHandle)*size), "BpHandle")); + mNext=reinterpret_cast(PX_ALLOC(ALIGN_SIZE_16(sizeof(BpHandle)*size), "BpHandle")); + mActivePairs=reinterpret_cast(PX_ALLOC(ALIGN_SIZE_16(sizeof(BroadPhasePair)*size), "BroadPhasePair")); + mActivePairStates=reinterpret_cast(PX_ALLOC(ALIGN_SIZE_16(sizeof(PxU8)*size), "BroadPhaseContextSap ActivePairStates")); + mHashCapacity=size; + mMinAllowedHashCapacity = size; + mActivePairsCapacity=size; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void SapPairManager::release() +{ + PX_FREE(mHashTable); + PX_FREE(mNext); + PX_FREE(mActivePairs); + PX_FREE(mActivePairStates); + mHashTable = NULL; + mNext = NULL; + mActivePairs = NULL; + mActivePairStates = NULL; + mNext = 0; + mHashSize = 0; + mHashCapacity = 0; + mMinAllowedHashCapacity = 0; + mNbActivePairs = 0; + mActivePairsCapacity = 0; + mMask = 0; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +const BroadPhasePair* SapPairManager::FindPair(BpHandle id0, BpHandle id1) const +{ + if(0==mHashSize) return NULL; // Nothing has been allocated yet + + // Order the ids + Sort(id0, id1); + + // Compute hash value for this pair + PxU32 HashValue = Hash(id0, id1) & mMask; + PX_ASSERT(HashValue the pair is persistent + PX_ASSERT(Offset the pair is persistent + PX_ASSERT(Offset= mHashSize) + { + // Get more entries + mHashSize = Ps::nextPowerOfTwo(mNbActivePairs+1); + mMask = mHashSize-1; + + reallocPairs(mHashSize>mHashCapacity); + + // Recompute hash value with new hash size + HashValue = Hash(id0, id1) & mMask; + } + + PX_ASSERT(mNbActivePairsmVolA = id0; // ### CMOVs would be nice here + p->mVolB = id1; + mActivePairStates[mNbActivePairs]=state; + + PX_ASSERT(mNbActivePairsmVolA, Last->mVolB) & mMask; + + // Walk the hash table to fix mNext + PX_ASSERT(LastHashValuemVolA==id0); + PX_ASSERT(P->mVolB==id1); + + RemovePair(id0, id1, HashValue, GetPairIndex(P)); + + shrinkMemory(); + + return true; +} + +bool SapPairManager::RemovePairs(const Cm::BitMap& removedAABBs) +{ + PxU32 i=0; + while(i mMinAllowedHashCapacity) || (mHashSize <= (mHashCapacity >> 2)) || (mHashSize <= (mActivePairsCapacity >> 2))); +} + +void SapPairManager::reallocPairs(const bool allocRequired) +{ + if(allocRequired) + { + PX_FREE(mHashTable); + mHashCapacity=mHashSize; + mActivePairsCapacity=mHashSize; + mHashTable = reinterpret_cast(PX_ALLOC(mHashSize*sizeof(BpHandle), "BpHandle")); + + for(PxU32 i=0;i(PX_ALLOC(mHashSize * sizeof(BroadPhasePair), "BroadPhasePair")); PX_ASSERT(NewPairs); + BpHandle* NewNext = reinterpret_cast(PX_ALLOC(mHashSize * sizeof(BpHandle), "BpHandle")); PX_ASSERT(NewNext); + PxU8* NewPairStates = reinterpret_cast(PX_ALLOC(mHashSize * sizeof(PxU8), "SapPairStates")); PX_ASSERT(NewPairStates); + + // Copy old data if needed + if(mNbActivePairs) + { + PxMemCopy(NewPairs, mActivePairs, mNbActivePairs*sizeof(BroadPhasePair)); + PxMemCopy(NewPairStates, mActivePairStates, mNbActivePairs*sizeof(PxU8)); + } + + // ### check it's actually needed... probably only for pairs whose hash value was cut by the and + // yeah, since Hash(id0, id1) is a constant + // However it might not be needed to recompute them => only less efficient but still ok + for(PxU32 i=0;i only less efficient but still ok + for(PxU32 i=0;i0); + const PxU32 newMaxNumPairs=2*maxNumPairs; + BroadPhasePair* newPairs=reinterpret_cast(PX_ALLOC(sizeof(BroadPhasePair)*newMaxNumPairs, "BroadPhasePair")); + PxMemCopy(newPairs, pairs, sizeof(BroadPhasePair)*maxNumPairs); + PX_FREE(pairs); + pairs=newPairs; + maxNumPairs=newMaxNumPairs; +} + +void ComputeCreatedDeletedPairsLists +(const BpHandle* PX_RESTRICT boxGroups, + const BpHandle* PX_RESTRICT dataArray, const PxU32 dataArraySize, + PxcScratchAllocator* scratchAllocator, + BroadPhasePairReport*& createdPairsList, PxU32& numCreatedPairs, PxU32& maxNumCreatedPairs, + BroadPhasePairReport*& deletedPairsList, PxU32& numDeletedPairs, PxU32& maxNumDeletedPairs, + PxU32& numActualDeletedPairs, + SapPairManager& pairManager) +{ +#if BP_SAP_TEST_GROUP_ID_CREATEUPDATE + PX_UNUSED(boxGroups); +#endif + + for(PxU32 i=0;i(scratchAllocator->alloc(sizeof(BroadPhasePairReport)*2*maxNumDeletedPairs, true)); + PxMemCopy(newDeletedPairsList, deletedPairsList, sizeof(BroadPhasePairReport)*maxNumDeletedPairs); + scratchAllocator->free(deletedPairsList); + deletedPairsList = newDeletedPairsList; + maxNumDeletedPairs = 2*maxNumDeletedPairs; + } + + PX_ASSERT(numDeletedPairsmUserData != 0xcdcdcdcd); + deletedPairsList[numDeletedPairs]=BroadPhasePairReport(UP->mVolA,UP->mVolB, UP->mUserData, ID); + numDeletedPairs++; + } + } + else + { + pairManager.ClearInArray(UP); + // Add => already there... Might want to create user data, though + if(pairManager.IsNew(UP)) + { +#if !BP_SAP_TEST_GROUP_ID_CREATEUPDATE + if(boxGroups[UP->mVolA]!=boxGroups[UP->mVolB]) +#endif + { + if(numCreatedPairs==maxNumCreatedPairs) + { + BroadPhasePairReport* newCreatedPairsList = reinterpret_cast(scratchAllocator->alloc(sizeof(BroadPhasePairReport)*2*maxNumCreatedPairs, true)); + PxMemCopy(newCreatedPairsList, createdPairsList, sizeof(BroadPhasePairReport)*maxNumCreatedPairs); + scratchAllocator->free(createdPairsList); + createdPairsList = newCreatedPairsList; + maxNumCreatedPairs = 2*maxNumCreatedPairs; + } + + PX_ASSERT(numCreatedPairsmVolA,UP->mVolB, UP->mUserData, ID); + numCreatedPairs++; + } + pairManager.ClearNew(UP); + } + } + } + + //Record pairs that are to be deleted because they were simultaneously created and removed + //from different axis sorts. + numActualDeletedPairs=numDeletedPairs; + for(PxU32 i=0;i(scratchAllocator->alloc(sizeof(BroadPhasePairReport)*2*maxNumDeletedPairs, true)); + PxMemCopy(newDeletedPairsList, deletedPairsList, sizeof(BroadPhasePairReport)*maxNumDeletedPairs); + scratchAllocator->free(deletedPairsList); + deletedPairsList = newDeletedPairsList; + maxNumDeletedPairs = 2*maxNumDeletedPairs; + } + + PX_ASSERT(numActualDeletedPairs<=maxNumDeletedPairs); + deletedPairsList[numActualDeletedPairs]=BroadPhasePairReport(UP->mVolA,UP->mVolB, NULL, ID); //KS - should we even get here???? + numActualDeletedPairs++; + } + } + +// // #### try batch removal here +// for(PxU32 i=0;i i && boxGroups[deletedPairsList[numDeletedPairs-1].mVolA] == boxGroups[deletedPairsList[numDeletedPairs-1].mVolB]) + { + numDeletedPairs--; + } + deletedPairsList[i]=deletedPairsList[numDeletedPairs-1]; + numDeletedPairs--; + } + } +#endif +} + +void DeletePairsLists(const PxU32 numActualDeletedPairs, BroadPhasePairReport* deletedPairsList, SapPairManager& pairManager) +{ + // #### try batch removal here + for(PxU32 i=0;iset(boxId); + + globalAABBMinX = PxMin(globalAABBMinX, PxU32(asapBoxes[axis0][boxId].mMinMax[0])); + globalAABBMinY = PxMin(globalAABBMinY, PxU32(asapBoxes[axis1][boxId].mMinMax[0])); + globalAABBMinZ = PxMin(globalAABBMinZ, PxU32(asapBoxes[axis2][boxId].mMinMax[0])); + globalAABBMaxX = PxMax(globalAABBMaxX, PxU32(asapBoxes[axis0][boxId].mMinMax[1])); + globalAABBMaxY = PxMax(globalAABBMaxY, PxU32(asapBoxes[axis1][boxId].mMinMax[1])); + globalAABBMaxZ = PxMax(globalAABBMaxZ, PxU32(asapBoxes[axis2][boxId].mMinMax[1])); + } + + PxU32 oldStaticCount=0; + PxU32 newStaticCount=0; + + //Assign the sorted end pts to the appropriate arrays. + for(PxU32 i=1;itest(boxId)) + { + if(Intersect3D( + globalAABBMinX, globalAABBMaxX, globalAABBMinY, globalAABBMaxY, globalAABBMinZ, globalAABBMaxZ, + asapBoxes[axis0][boxId].mMinMax[0],asapBoxes[axis0][boxId].mMinMax[1],asapBoxes[axis1][boxId].mMinMax[0],asapBoxes[axis1][boxId].mMinMax[1],asapBoxes[axis2][boxId].mMinMax[0],asapBoxes[axis2][boxId].mMinMax[1])) + { + oldBoxIndicesSorted[oldBoxIndicesCount]=boxId; + oldBoxIndicesCount++; + oldStaticCount+=asapBoxGroupIds[boxId]; + } + } + else + { + newBoxIndicesSorted[newBoxIndicesCount]=boxId; + newBoxIndicesCount++; + newStaticCount+=asapBoxGroupIds[boxId]; + } + } + } + + allOldBoxesStatics = oldStaticCount ? false : true; + allNewBoxesStatics = newStaticCount ? false : true; + + //Make sure that we've found the correct number of boxes. + PX_ASSERT(newBoxIndicesCount==(insertAABBEnd-insertAABBStart)); + PX_ASSERT(oldBoxIndicesCount<=((numSortedEndPoints-NUM_SENTINELS)/2)); +} + +void performBoxPruningNewNew +(const Gu::Axes& axes, + const BpHandle* PX_RESTRICT newBoxIndicesSorted, const PxU32 newBoxIndicesCount, const bool allNewBoxesStatics, + BpHandle* PX_RESTRICT minPosList0, + SapBox1D** PX_RESTRICT asapBoxes, const BpHandle* PX_RESTRICT asapBoxGroupIds, + PxcScratchAllocator* scratchAllocator, + SapPairManager& pairManager, BpHandle*& dataArray, PxU32& dataArraySize, PxU32& dataArrayCapacity) +{ + // Checkings + if(!newBoxIndicesCount) return; + + // Catch axes + const PxU32 Axis0 = axes.mAxis0; + const PxU32 Axis1 = axes.mAxis1; + const PxU32 Axis2 = axes.mAxis2; + + // 1) Build main list using the primary axis + for(PxU32 i=0;i