diff options
| author | git perforce import user <a@b> | 2016-10-25 12:29:14 -0600 |
|---|---|---|
| committer | Sheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees> | 2016-10-25 18:56:37 -0500 |
| commit | 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch) | |
| tree | fa6485c169e50d7415a651bf838f5bcd0fd3bfbd /PhysX_3.4/Source/PhysXCharacterKinematic/src/CctObstacleContext.cpp | |
| download | physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip | |
Initial commit:
PhysX 3.4.0 Update @ 21294896
APEX 1.4.0 Update @ 21275617
[CL 21300167]
Diffstat (limited to 'PhysX_3.4/Source/PhysXCharacterKinematic/src/CctObstacleContext.cpp')
| -rw-r--r-- | PhysX_3.4/Source/PhysXCharacterKinematic/src/CctObstacleContext.cpp | 538 |
1 files changed, 538 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/PhysXCharacterKinematic/src/CctObstacleContext.cpp b/PhysX_3.4/Source/PhysXCharacterKinematic/src/CctObstacleContext.cpp new file mode 100644 index 00000000..b6b4b735 --- /dev/null +++ b/PhysX_3.4/Source/PhysXCharacterKinematic/src/CctObstacleContext.cpp @@ -0,0 +1,538 @@ +// 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 "CctObstacleContext.h" +#include "CctCharacterControllerManager.h" +#include "PsUtilities.h" + +using namespace physx; +using namespace Cct; + +//! Initial list size +#define DEFAULT_HANDLEMANAGER_SIZE 2 + +HandleManager::HandleManager() : mCurrentNbObjects(0), mNbFreeIndices(0) +{ + mMaxNbObjects = DEFAULT_HANDLEMANAGER_SIZE; + mObjects = reinterpret_cast<void**>(PX_ALLOC(sizeof(void*)*mMaxNbObjects, "HandleManager")); + mOutToIn = reinterpret_cast<PxU16*>(PX_ALLOC(sizeof(PxU16)*mMaxNbObjects, "HandleManager")); + mInToOut = reinterpret_cast<PxU16*>(PX_ALLOC(sizeof(PxU16)*mMaxNbObjects, "HandleManager")); + mStamps = reinterpret_cast<PxU16*>(PX_ALLOC(sizeof(PxU16)*mMaxNbObjects, "HandleManager")); + PxMemSet(mOutToIn, 0xff, mMaxNbObjects*sizeof(PxU16)); + PxMemSet(mInToOut, 0xff, mMaxNbObjects*sizeof(PxU16)); + PxMemZero(mStamps, mMaxNbObjects*sizeof(PxU16)); +} + +HandleManager::~HandleManager() +{ + SetupLists(); +} + +bool HandleManager::SetupLists(void** objects, PxU16* oti, PxU16* ito, PxU16* stamps) +{ + // Release old data + PX_FREE_AND_RESET(mStamps); + PX_FREE_AND_RESET(mInToOut); + PX_FREE_AND_RESET(mOutToIn); + PX_FREE_AND_RESET(mObjects); + // Assign new data + mObjects = objects; + mOutToIn = oti; + mInToOut = ito; + mStamps = stamps; + return true; +} + +Handle HandleManager::Add(void* object) +{ + // Are there any free indices I should recycle? + if(mNbFreeIndices) + { + const PxU16 FreeIndex = mInToOut[mCurrentNbObjects];// Get the recycled virtual index + mObjects[mCurrentNbObjects] = object; // The physical location is always at the end of the list (it never has holes). + mOutToIn[FreeIndex] = Ps::to16(mCurrentNbObjects++); // Update virtual-to-physical remapping table. + mNbFreeIndices--; + return Handle((mStamps[FreeIndex]<<16)|FreeIndex); // Return virtual index (handle) to the client app + } + else + { + PX_ASSERT_WITH_MESSAGE(mCurrentNbObjects<0xffff ,"Internal error - 64K objects in HandleManager!"); + + // Is the array large enough for another entry? + if(mCurrentNbObjects==mMaxNbObjects) + { + // Nope! Resize all arrays (could be avoided with linked lists... one day) + mMaxNbObjects<<=1; // The more you eat, the more you're given + if(mMaxNbObjects>0xffff) mMaxNbObjects = 0xffff; // Clamp to 64K + void** NewList = reinterpret_cast<void**>(PX_ALLOC(sizeof(void*)*mMaxNbObjects, "HandleManager")); // New physical list + PxU16* NewOTI = reinterpret_cast<PxU16*>(PX_ALLOC(sizeof(PxU16)*mMaxNbObjects, "HandleManager")); // New remapping table + PxU16* NewITO = reinterpret_cast<PxU16*>(PX_ALLOC(sizeof(PxU16)*mMaxNbObjects, "HandleManager")); // New remapping table + PxU16* NewStamps = reinterpret_cast<PxU16*>(PX_ALLOC(sizeof(PxU16)*mMaxNbObjects, "HandleManager")); // New stamps + PxMemCopy(NewList, mObjects, mCurrentNbObjects*sizeof(void*)); // Copy old data + PxMemCopy(NewOTI, mOutToIn, mCurrentNbObjects*sizeof(PxU16)); // Copy old data + PxMemCopy(NewITO, mInToOut, mCurrentNbObjects*sizeof(PxU16)); // Copy old data + PxMemCopy(NewStamps, mStamps, mCurrentNbObjects*sizeof(PxU16)); // Copy old data + PxMemSet(NewOTI+mCurrentNbObjects, 0xff, (mMaxNbObjects-mCurrentNbObjects)*sizeof(PxU16)); + PxMemSet(NewITO+mCurrentNbObjects, 0xff, (mMaxNbObjects-mCurrentNbObjects)*sizeof(PxU16)); + PxMemZero(NewStamps+mCurrentNbObjects, (mMaxNbObjects-mCurrentNbObjects)*sizeof(PxU16)); + SetupLists(NewList, NewOTI, NewITO, NewStamps); + } + + mObjects[mCurrentNbObjects] = object; // Store object at mCurrentNbObjects = physical index = virtual index + mOutToIn[mCurrentNbObjects] = Ps::to16(mCurrentNbObjects); // Update virtual-to-physical remapping table. + mInToOut[mCurrentNbObjects] = Ps::to16(mCurrentNbObjects); // Update physical-to-virtual remapping table. + PxU32 tmp = mCurrentNbObjects++; + return (mStamps[tmp]<<16)|tmp; // Return virtual index (handle) to the client app + } +} + +void HandleManager::Remove(Handle handle) +{ + const PxU16 VirtualIndex = PxU16(handle); + if(VirtualIndex>=mMaxNbObjects) return; // Invalid handle + const PxU16 PhysicalIndex = mOutToIn[VirtualIndex]; // Get the physical index + if(PhysicalIndex==0xffff) return; // Value has already been deleted + if(PhysicalIndex>=mMaxNbObjects) return; // Invalid index + + // There must be at least one valid entry. + if(mCurrentNbObjects) + { + if(mStamps[VirtualIndex]!=handle>>16) return; // Stamp mismatch => index has been recycled + + // Update list so that there's no hole + mObjects[PhysicalIndex] = mObjects[--mCurrentNbObjects];// Move the real object so that the array has no holes. + mOutToIn[mInToOut[mCurrentNbObjects]] = PhysicalIndex; // Update virtual-to-physical remapping table. + mInToOut[PhysicalIndex] = mInToOut[mCurrentNbObjects]; // Update physical-to-virtual remapping table. + // Keep track of the recyclable virtual index + mInToOut[mCurrentNbObjects] = VirtualIndex; // Store the free virtual index/handle at the end of mInToOut + mOutToIn[VirtualIndex] = 0xffff; // Invalidate the entry + mNbFreeIndices++; // One more free index + mStamps[VirtualIndex]++; // Update stamp + } +} + +void* HandleManager::GetObject(Handle handle) const +{ + const PxU16 VirtualIndex = PxU16(handle); + if(VirtualIndex>=mMaxNbObjects) return NULL; // Invalid handle + const PxU16 PhysicalIndex = mOutToIn[VirtualIndex]; // Get physical index + if(PhysicalIndex==0xffff) return NULL; // Object has been deleted + if(PhysicalIndex>=mMaxNbObjects) return NULL; // Index is invalid + if(mStamps[VirtualIndex]!=handle>>16) return NULL; // Index has been recycled + return mObjects[PhysicalIndex]; // Returns stored pointer +} + +bool HandleManager::UpdateObject(Handle handle, void* object) +{ + const PxU16 VirtualIndex = PxU16(handle); + if(VirtualIndex>=mMaxNbObjects) return false; // Invalid handle + const PxU16 PhysicalIndex = mOutToIn[VirtualIndex]; // Get physical index + if(PhysicalIndex==0xffff) return false; // Object has been deleted + if(PhysicalIndex>=mMaxNbObjects) return false; // Index is invalid + if(mStamps[VirtualIndex]!=handle>>16) return false; // Index has been recycled + mObjects[PhysicalIndex] = object; // Updates stored pointer + return true; +} + + +// PT: please do not expose these functions outside of this class, +// as we want to retain the ability to easily modify the handle format if necessary. + +#define NEW_ENCODING +#ifdef NEW_ENCODING +static PX_FORCE_INLINE void* encodeInternalHandle(PxU32 index, PxGeometryType::Enum type) +{ + PX_ASSERT(index<=0xffff); + PX_ASSERT(PxU32(type)<=0xffff); + // PT: we do type+1 to ban internal handles with a 0 value, since it's reserved for NULL pointers + return reinterpret_cast<void*>((size_t(index)<<16)|(size_t(type)+1)); +} + +static PX_FORCE_INLINE PxGeometryType::Enum decodeInternalType(void* handle) +{ + return PxGeometryType::Enum((PxU32(reinterpret_cast<size_t>(handle)) & 0xffff)-1); +} + +static PX_FORCE_INLINE PxU32 decodeInternalIndex(void* handle) +{ + return (PxU32(size_t(handle)))>>16; +} +#else +static PX_FORCE_INLINE ObstacleHandle encodeHandle(PxU32 index, PxGeometryType::Enum type) +{ + PX_ASSERT(index<=0xffff); + PX_ASSERT(type<=0xffff); + return (PxU16(index)<<16)|PxU32(type); +} + +static PX_FORCE_INLINE PxGeometryType::Enum decodeType(ObstacleHandle handle) +{ + return PxGeometryType::Enum(handle & 0xffff); +} + +static PX_FORCE_INLINE PxU32 decodeIndex(ObstacleHandle handle) +{ + return handle>>16; +} +#endif + +ObstacleContext::ObstacleContext(CharacterControllerManager& cctMan) + : mCCTManager(cctMan) +{ +} + +ObstacleContext::~ObstacleContext() +{ +} + +void ObstacleContext::release() +{ + mCCTManager.releaseObstacleContext(*this); +} + +PxControllerManager& ObstacleContext::getControllerManager() const +{ + return mCCTManager; +} + +ObstacleHandle ObstacleContext::addObstacle(const PxObstacle& obstacle) +{ + const PxGeometryType::Enum type = obstacle.getType(); + if(type==PxGeometryType::eBOX) + { + const PxU32 index = mBoxObstacles.size(); +#ifdef NEW_ENCODING + const ObstacleHandle handle = mHandleManager.Add(encodeInternalHandle(index, type)); +#else + const ObstacleHandle handle = encodeHandle(index, type); +#endif + mBoxObstacles.pushBack(InternalBoxObstacle(handle, static_cast<const PxBoxObstacle&>(obstacle))); + mCCTManager.onObstacleAdded(handle, this); + return handle; + } + else if(type==PxGeometryType::eCAPSULE) + { + const PxU32 index = mCapsuleObstacles.size(); +#ifdef NEW_ENCODING + const ObstacleHandle handle = mHandleManager.Add(encodeInternalHandle(index, type)); +#else + const ObstacleHandle handle = encodeHandle(index, type); +#endif + mCapsuleObstacles.pushBack(InternalCapsuleObstacle(handle, static_cast<const PxCapsuleObstacle&>(obstacle))); + mCCTManager.onObstacleAdded(handle, this); + return handle; + } + else return INVALID_OBSTACLE_HANDLE; +} + +#ifdef NEW_ENCODING +template<class T> +static PX_FORCE_INLINE void remove(HandleManager& manager, void* object, ObstacleHandle handle, PxU32 index, PxU32 size, const Ps::Array<T>& obstacles) +{ + manager.Remove(handle); + if(index!=size-1) + { + bool status = manager.UpdateObject(obstacles[size-1].mHandle, object); + PX_ASSERT(status); + PX_UNUSED(status); + } +} +#endif + +bool ObstacleContext::removeObstacle(ObstacleHandle handle) +{ +#ifdef NEW_ENCODING + void* object = mHandleManager.GetObject(handle); + if(!object) + return false; + const PxGeometryType::Enum type = decodeInternalType(object); + const PxU32 index = decodeInternalIndex(object); +#else + const PxGeometryType::Enum type = decodeType(handle); + const PxU32 index = decodeIndex(handle); +#endif + + if(type==PxGeometryType::eBOX) + { + const PxU32 size = mBoxObstacles.size(); + PX_ASSERT(index<size); + if(index>=size) + return false; + +#ifdef NEW_ENCODING + remove<InternalBoxObstacle>(mHandleManager, object, handle, index, size, mBoxObstacles); +#endif + mBoxObstacles.replaceWithLast(index); +#ifdef NEW_ENCODING + mCCTManager.onObstacleRemoved(handle); +#else + mCCTManager.onObstacleRemoved(handle, encodeHandle(size-1, type)); +#endif + return true; + } + else if(type==PxGeometryType::eCAPSULE) + { + const PxU32 size = mCapsuleObstacles.size(); + PX_ASSERT(index<size); + if(index>=size) + return false; + +#ifdef NEW_ENCODING + remove<InternalCapsuleObstacle>(mHandleManager, object, handle, index, size, mCapsuleObstacles); +#endif + + mCapsuleObstacles.replaceWithLast(index); +#ifdef NEW_ENCODING + mCCTManager.onObstacleRemoved(handle); +#else + mCCTManager.onObstacleRemoved(handle, encodeHandle(size-1, type)); +#endif + return true; + } + else return false; +} + +bool ObstacleContext::updateObstacle(ObstacleHandle handle, const PxObstacle& obstacle) +{ +#ifdef NEW_ENCODING + void* object = mHandleManager.GetObject(handle); + if(!object) + return false; + const PxGeometryType::Enum type = decodeInternalType(object); + PX_ASSERT(type==obstacle.getType()); + if(type!=obstacle.getType()) + return false; + const PxU32 index = decodeInternalIndex(object); +#else + const PxGeometryType::Enum type = decodeType(handle); + PX_ASSERT(type==obstacle.getType()); + if(type!=obstacle.getType()) + return false; + const PxU32 index = decodeIndex(handle); +#endif + + if(type==PxGeometryType::eBOX) + { + const PxU32 size = mBoxObstacles.size(); + PX_ASSERT(index<size); + if(index>=size) + return false; + + mBoxObstacles[index].mData = static_cast<const PxBoxObstacle&>(obstacle); + mCCTManager.onObstacleUpdated(handle,this); + return true; + } + else if(type==PxGeometryType::eCAPSULE) + { + const PxU32 size = mCapsuleObstacles.size(); + PX_ASSERT(index<size); + if(index>=size) + return false; + + mCapsuleObstacles[index].mData = static_cast<const PxCapsuleObstacle&>(obstacle); + mCCTManager.onObstacleUpdated(handle,this); + return true; + } + else return false; +} + +PxU32 ObstacleContext::getNbObstacles() const +{ + return mBoxObstacles.size() + mCapsuleObstacles.size(); +} + +const PxObstacle* ObstacleContext::getObstacle(PxU32 i) const +{ + const PxU32 nbBoxes = mBoxObstacles.size(); + if(i<nbBoxes) + return &mBoxObstacles[i].mData; + i -= nbBoxes; + + const PxU32 nbCapsules = mCapsuleObstacles.size(); + if(i<nbCapsules) + return &mCapsuleObstacles[i].mData; + + return NULL; +} + +const PxObstacle* ObstacleContext::getObstacleByHandle(ObstacleHandle handle) const +{ +#ifdef NEW_ENCODING + void* object = mHandleManager.GetObject(handle); + if(!object) + return NULL; + const PxGeometryType::Enum type = decodeInternalType(object); + const PxU32 index = decodeInternalIndex(object); +#else + const PxGeometryType::Enum type = decodeType(handle); + const PxU32 index = decodeIndex(handle); +#endif + + if(type == PxGeometryType::eBOX) + { + const PxU32 size = mBoxObstacles.size(); + if(index>=size) + return NULL; + PX_ASSERT(mBoxObstacles[index].mHandle==handle); + return &mBoxObstacles[index].mData; + } + else if(type==PxGeometryType::eCAPSULE) + { + const PxU32 size = mCapsuleObstacles.size(); + if(index>=size) + return NULL; + PX_ASSERT(mCapsuleObstacles[index].mHandle==handle); + return &mCapsuleObstacles[index].mData; + } + else return NULL; +} + +#include "GuRaycastTests.h" +#include "PxBoxGeometry.h" +#include "PxCapsuleGeometry.h" +#include "PsMathUtils.h" +using namespace Gu; +const PxObstacle* ObstacleContext::raycastSingle(PxRaycastHit& hit, const PxVec3& origin, const PxVec3& unitDir, const PxReal distance, ObstacleHandle& obstacleHandle) const +{ + PxRaycastHit localHit; + PxF32 t = FLT_MAX; + const PxObstacle* touchedObstacle = NULL; + + const PxHitFlags hitFlags = PxHitFlag::eDISTANCE; + + { + const RaycastFunc raycastFunc = Gu::getRaycastFuncTable()[PxGeometryType::eBOX]; + PX_ASSERT(raycastFunc); + + const PxU32 nbExtraBoxes = mBoxObstacles.size(); + for(PxU32 i=0;i<nbExtraBoxes;i++) + { + const PxBoxObstacle& userBoxObstacle = mBoxObstacles[i].mData; + + PxU32 status = raycastFunc( PxBoxGeometry(userBoxObstacle.mHalfExtents), + PxTransform(toVec3(userBoxObstacle.mPos), userBoxObstacle.mRot), + origin, unitDir, distance, + hitFlags, + 1, &localHit); + if(status && localHit.distance<t) + { + t = localHit.distance; + hit = localHit; + obstacleHandle = mBoxObstacles[i].mHandle; + touchedObstacle = &userBoxObstacle; + } + } + } + + { + const RaycastFunc raycastFunc = Gu::getRaycastFuncTable()[PxGeometryType::eCAPSULE]; + PX_ASSERT(raycastFunc); + + const PxU32 nbExtraCapsules = mCapsuleObstacles.size(); + for(PxU32 i=0;i<nbExtraCapsules;i++) + { + const PxCapsuleObstacle& userCapsuleObstacle = mCapsuleObstacles[i].mData; + + PxU32 status = raycastFunc( PxCapsuleGeometry(userCapsuleObstacle.mRadius, userCapsuleObstacle.mHalfHeight), + PxTransform(toVec3(userCapsuleObstacle.mPos), userCapsuleObstacle.mRot), + origin, unitDir, distance, + hitFlags, + 1, &localHit); + if(status && localHit.distance<t) + { + t = localHit.distance; + hit = localHit; + obstacleHandle = mCapsuleObstacles[i].mHandle; + touchedObstacle = &userCapsuleObstacle; + } + } + } + return touchedObstacle; +} + + +const PxObstacle* ObstacleContext::raycastSingle(PxRaycastHit& hit, const ObstacleHandle& obstacleHandle, const PxVec3& origin, const PxVec3& unitDir, const PxReal distance) const +{ + const PxHitFlags hitFlags = PxHitFlag::eDISTANCE; + +#ifdef NEW_ENCODING + void* object = mHandleManager.GetObject(obstacleHandle); + if(!object) + return NULL; + const PxGeometryType::Enum geomType = decodeInternalType(object); + const PxU32 index = decodeInternalIndex(object); +#else + const PxGeometryType::Enum geomType = decodeType(obstacleHandle); + const PxU32 index = decodeIndex(obstacleHandle); +#endif + if(geomType == PxGeometryType::eBOX) + { + const PxBoxObstacle& userBoxObstacle = mBoxObstacles[index].mData; + + PxU32 status = Gu::getRaycastFuncTable()[PxGeometryType::eBOX]( + PxBoxGeometry(userBoxObstacle.mHalfExtents), + PxTransform(toVec3(userBoxObstacle.mPos), userBoxObstacle.mRot), + origin, unitDir, distance, + hitFlags, + 1, &hit); + + if(status) + { + return &userBoxObstacle; + } + } + else + { + PX_ASSERT(geomType == PxGeometryType::eCAPSULE); + const PxCapsuleObstacle& userCapsuleObstacle = mCapsuleObstacles[index].mData; + + PxU32 status = Gu::getRaycastFuncTable()[PxGeometryType::eCAPSULE]( + PxCapsuleGeometry(userCapsuleObstacle.mRadius, userCapsuleObstacle.mHalfHeight), + PxTransform(toVec3(userCapsuleObstacle.mPos), userCapsuleObstacle.mRot), + origin, unitDir, distance, + hitFlags, + 1, &hit); + if(status) + { + return &userCapsuleObstacle; + } + } + + return NULL; +} + +void ObstacleContext::onOriginShift(const PxVec3& shift) +{ + for(PxU32 i=0; i < mBoxObstacles.size(); i++) + mBoxObstacles[i].mData.mPos -= shift; + + for(PxU32 i=0; i < mCapsuleObstacles.size(); i++) + mCapsuleObstacles[i].mData.mPos -= shift; +} |