539 lines
18 KiB
C++
539 lines
18 KiB
C++
//
|
|
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions
|
|
// are met:
|
|
// * Redistributions of source code must retain the above copyright
|
|
// notice, this list of conditions and the following disclaimer.
|
|
// * Redistributions in binary form must reproduce the above copyright
|
|
// notice, this list of conditions and the following disclaimer in the
|
|
// documentation and/or other materials provided with the distribution.
|
|
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
|
// contributors may be used to endorse or promote products derived
|
|
// from this software without specific prior written permission.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
//
|
|
// Copyright (c) 2008-2019 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 "geometry/PxBoxGeometry.h"
|
|
#include "geometry/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 = PxHitFlags(0);
|
|
|
|
{
|
|
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 = PxHitFlags(0);
|
|
|
|
#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;
|
|
}
|