diff options
Diffstat (limited to 'PhysX_3.4/Source/SceneQuery/src/SqPruningPool.cpp')
| -rw-r--r-- | PhysX_3.4/Source/SceneQuery/src/SqPruningPool.cpp | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/SceneQuery/src/SqPruningPool.cpp b/PhysX_3.4/Source/SceneQuery/src/SqPruningPool.cpp new file mode 100644 index 00000000..8a90a1d3 --- /dev/null +++ b/PhysX_3.4/Source/SceneQuery/src/SqPruningPool.cpp @@ -0,0 +1,182 @@ +// 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 "foundation/PxMemory.h" +#include "SqPruningPool.h" + +using namespace physx; +using namespace Sq; +using namespace Cm; + +PruningPool::PruningPool() : + mNbObjects (0), + mMaxNbObjects (0), + mWorldBoxes (NULL), + mObjects (NULL), + mHandleToIndex (NULL), + mIndexToHandle (NULL), + mFirstRecycledHandle(INVALID_PRUNERHANDLE) +{ +} + +PruningPool::~PruningPool() +{ + PX_FREE_AND_RESET(mWorldBoxes); + PX_FREE_AND_RESET(mObjects); + PX_FREE_AND_RESET(mHandleToIndex); + PX_FREE_AND_RESET(mIndexToHandle); +} + +bool PruningPool::resize(PxU32 newCapacity) +{ + // PT: we always allocate one extra box, to make sure we can safely use V4 loads on the array + PxBounds3* newBoxes = reinterpret_cast<PxBounds3*>(PX_ALLOC(sizeof(PxBounds3)*(newCapacity+1), "PxBounds3")); + PrunerPayload* newData = reinterpret_cast<PrunerPayload*>(PX_ALLOC(sizeof(PrunerPayload)*newCapacity, "PrunerPayload*")); + PrunerHandle* newIndexToHandle = reinterpret_cast<PrunerHandle*>(PX_ALLOC(sizeof(PrunerHandle)*newCapacity, "Pruner Index Mapping")); + PoolIndex* newHandleToIndex = reinterpret_cast<PoolIndex*>(PX_ALLOC(sizeof(PoolIndex)*newCapacity, "Pruner Index Mapping")); + if( (NULL==newBoxes) || (NULL==newData) || (NULL==newIndexToHandle) || (NULL==newHandleToIndex) + ) + { + PX_FREE_AND_RESET(newBoxes); + PX_FREE_AND_RESET(newData); + PX_FREE_AND_RESET(newIndexToHandle); + PX_FREE_AND_RESET(newHandleToIndex); + return false; + } + + if(mWorldBoxes) PxMemCopy(newBoxes, mWorldBoxes, mNbObjects*sizeof(PxBounds3)); + if(mObjects) PxMemCopy(newData, mObjects, mNbObjects*sizeof(PrunerPayload)); + if(mIndexToHandle) PxMemCopy(newIndexToHandle, mIndexToHandle, mNbObjects*sizeof(PrunerHandle)); + if(mHandleToIndex) PxMemCopy(newHandleToIndex, mHandleToIndex, mMaxNbObjects*sizeof(PoolIndex)); + mMaxNbObjects = newCapacity; + + PX_FREE_AND_RESET(mWorldBoxes); + PX_FREE_AND_RESET(mObjects); + PX_FREE_AND_RESET(mHandleToIndex); + PX_FREE_AND_RESET(mIndexToHandle); + mWorldBoxes = newBoxes; + mObjects = newData; + mHandleToIndex = newHandleToIndex; + mIndexToHandle = newIndexToHandle; + + return true; +} + +void PruningPool::preallocate(PxU32 newCapacity) +{ + if(newCapacity>mMaxNbObjects) + resize(newCapacity); +} + +PxU32 PruningPool::addObjects(PrunerHandle* results, const PxBounds3* bounds, const PrunerPayload* payload, PxU32 count) +{ + for(PxU32 i=0;i<count;i++) + { + if(mNbObjects==mMaxNbObjects) // increase the capacity on overflow + { + if(!resize(PxMax<PxU32>(mMaxNbObjects*2, 64))) + { + // pool can return an invalid handle if memory alloc fails + // should probably have an error here or not handle this + results[i] = INVALID_PRUNERHANDLE; // PT: we need to write the potentially invalid handle to let users know which object failed first + return i; + } + } + PX_ASSERT(mNbObjects!=mMaxNbObjects); + + const PoolIndex index = mNbObjects++; + + // update mHandleToIndex and mIndexToHandle mappings + PrunerHandle handle; + if(mFirstRecycledHandle != INVALID_PRUNERHANDLE) + { + // mFirstRecycledHandle is an entry into a freelist for removed slots + // this path is only taken if we have any removed slots + handle = mFirstRecycledHandle; + mFirstRecycledHandle = mHandleToIndex[handle]; + } + else + { + handle = index; + } + + // PT: TODO: investigate why we added mIndexToHandle/mHandleToIndex. The initial design with 'Prunable' objects didn't need these arrays. + + // PT: these 3 arrays are "parallel" + mWorldBoxes [index] = bounds[i]; // store the payload and AABB in parallel arrays + mObjects [index] = payload[i]; + mIndexToHandle [index] = handle; + + mHandleToIndex[handle] = index; + results[i] = handle; + } + return count; +} + +PoolIndex PruningPool::removeObject(PrunerHandle h) +{ + PX_ASSERT(mNbObjects); + + // remove the object and its AABB by provided PrunerHandle and update mHandleToIndex and mIndexToHandle mappings + const PoolIndex indexOfRemovedObject = mHandleToIndex[h]; // retrieve object's index from handle + + const PoolIndex indexOfLastObject = --mNbObjects; // swap the object at last index with index + if(indexOfLastObject!=indexOfRemovedObject) + { + // PT: move last object's data to recycled spot (from removed object) + + // PT: the last object has moved so we need to handle the mappings for this object + // PT: TODO: investigate where this double-mapping comes from. Should not be needed... + + // PT: these 3 arrays are "parallel" + const PrunerHandle handleOfLastObject = mIndexToHandle[indexOfLastObject]; + mWorldBoxes [indexOfRemovedObject] = mWorldBoxes [indexOfLastObject]; + mObjects [indexOfRemovedObject] = mObjects [indexOfLastObject]; + mIndexToHandle [indexOfRemovedObject] = handleOfLastObject; + + mHandleToIndex[handleOfLastObject] = indexOfRemovedObject; + } + + // mHandleToIndex also stores the freelist for removed handles (in place of holes formed by removed handles) + mHandleToIndex[h] = mFirstRecycledHandle; // update linked list of available recycled handles + mFirstRecycledHandle = h; // update the list head + + return indexOfLastObject; +} + +void PruningPool::shiftOrigin(const PxVec3& shift) +{ + for(PxU32 i=0; i < mNbObjects; i++) + { + mWorldBoxes[i].minimum -= shift; + mWorldBoxes[i].maximum -= shift; + } +} |