Files
XCEngine/engine/third_party/physx/source/geomutils/src/gjk/GuVecBox.h

222 lines
7.5 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-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef GU_VEC_BOX_H
#define GU_VEC_BOX_H
#include "foundation/PxTransform.h"
#include "common/PxPhysXCommonConfig.h"
#include "geometry/PxBoxGeometry.h"
#include "foundation/PxVecTransform.h"
#include "GuVecConvex.h"
#include "GuConvexSupportTable.h"
namespace physx
{
PX_PHYSX_COMMON_API extern const aos::BoolV boxVertexTable[8];
namespace Gu
{
#define BOX_MARGIN_RATIO 0.15f
#define BOX_MIN_MARGIN_RATIO 0.05f
#define BOX_SWEEP_MARGIN_RATIO 0.05f
#define BOX_MARGIN_CCD_RATIO 0.01f
#define BOX_MIN_MARGIN_CCD_RATIO 0.005f
class CapsuleV;
PX_FORCE_INLINE void CalculateBoxMargin(const aos::Vec3VArg extent, PxReal& margin, PxReal& minMargin, PxReal& sweepMargin,
const PxReal marginR = BOX_MARGIN_RATIO, const PxReal minMarginR = BOX_MIN_MARGIN_RATIO)
{
using namespace aos;
PxReal minExtent;
const FloatV min = V3ExtractMin(extent);
FStore(min, &minExtent);
margin = minExtent * marginR;
minMargin = minExtent * minMarginR;
sweepMargin = minExtent * BOX_SWEEP_MARGIN_RATIO;
}
PX_FORCE_INLINE aos::FloatV CalculateBoxTolerance(const aos::Vec3VArg extent)
{
using namespace aos;
const FloatV r0 = FLoad(0.01f);
const FloatV min = V3ExtractMin(extent);//FMin(V3GetX(extent), FMin(V3GetY(extent), V3GetZ(extent)));
return FMul(min, r0);
}
//This method is called in the PCM contact gen for the refreshing contacts
PX_FORCE_INLINE aos::FloatV CalculatePCMBoxMargin(const aos::Vec3VArg extent, const PxReal toleranceLength, const PxReal toleranceMarginRatio = BOX_MARGIN_RATIO)
{
using namespace aos;
const FloatV min = V3ExtractMin(extent);//FMin(V3GetX(extent), FMin(V3GetY(extent), V3GetZ(extent)));
const FloatV toleranceMargin = FLoad(toleranceLength * toleranceMarginRatio);
return FMin(FMul(min, FLoad(BOX_MARGIN_RATIO)), toleranceMargin);
}
PX_FORCE_INLINE aos::FloatV CalculateMTDBoxMargin(const aos::Vec3VArg extent)
{
using namespace aos;
const FloatV min = V3ExtractMin(extent);//FMin(V3GetX(extent), FMin(V3GetY(extent), V3GetZ(extent)));
return FMul(min, FLoad(BOX_MARGIN_RATIO));
}
class BoxV : public ConvexV
{
public:
/**
\brief Constructor
*/
PX_INLINE BoxV() : ConvexV(ConvexType::eBOX)
{
}
PX_FORCE_INLINE BoxV(const aos::Vec3VArg origin, const aos::Vec3VArg extent) :
ConvexV(ConvexType::eBOX, origin), extents(extent)
{
CalculateBoxMargin(extent, margin, minMargin, sweepMargin);
}
//this constructor is used by the CCD system
PX_FORCE_INLINE BoxV(const PxGeometry& geom) : ConvexV(ConvexType::eBOX, aos::V3Zero())
{
using namespace aos;
const PxBoxGeometry& boxGeom = static_cast<const PxBoxGeometry&>(geom);
const Vec3V extent = aos::V3LoadU(boxGeom.halfExtents);
extents = extent;
CalculateBoxMargin(extent, margin, minMargin, sweepMargin, BOX_MARGIN_CCD_RATIO, BOX_MIN_MARGIN_CCD_RATIO);
}
/**
\brief Destructor
*/
PX_INLINE ~BoxV()
{
}
PX_FORCE_INLINE void resetMargin(const PxReal toleranceLength)
{
minMargin = PxMin(toleranceLength * BOX_MIN_MARGIN_RATIO, minMargin);
}
//! Assignment operator
PX_FORCE_INLINE const BoxV& operator=(const BoxV& other)
{
center = other.center;
extents = other.extents;
margin = other.margin;
minMargin = other.minMargin;
sweepMargin = other.sweepMargin;
return *this;
}
PX_FORCE_INLINE void populateVerts(const PxU8* inds, PxU32 numInds, const PxVec3* originalVerts, aos::Vec3V* verts)const
{
using namespace aos;
for(PxU32 i=0; i<numInds; ++i)
verts[i] = V3LoadU_SafeReadW(originalVerts[inds[i]]); // PT: safe because of the way vertex memory is allocated in ConvexHullData (and 'populateVerts' is always called with polyData.mVerts)
}
PX_FORCE_INLINE aos::Vec3V supportPoint(const PxI32 index)const
{
using namespace aos;
const BoolV con = boxVertexTable[index];
return V3Sel(con, extents, V3Neg(extents));
}
PX_FORCE_INLINE void getIndex(const aos::BoolV con, PxI32& index)const
{
using namespace aos;
index = PxI32(BGetBitMask(con) & 0x7);
}
PX_FORCE_INLINE aos::Vec3V supportLocal(const aos::Vec3VArg dir)const
{
using namespace aos;
return V3Sel(V3IsGrtr(dir, V3Zero()), extents, V3Neg(extents));
}
//this is used in the sat test for the full contact gen
PX_SUPPORT_INLINE void supportLocal(const aos::Vec3VArg dir, aos::FloatV& min, aos::FloatV& max)const
{
using namespace aos;
const Vec3V point = V3Sel(V3IsGrtr(dir, V3Zero()), extents, V3Neg(extents));
max = V3Dot(dir, point);
min = FNeg(max);
}
PX_SUPPORT_INLINE aos::Vec3V supportRelative(const aos::Vec3VArg dir, const aos::PxMatTransformV& aTob, const aos::PxMatTransformV& aTobT) const
{
//a is the current object, b is the other object, dir is in the local space of b
using namespace aos;
// const Vec3V _dir = aTob.rotateInv(dir);//relTra.rotateInv(dir);//from b to a
const Vec3V _dir = aTobT.rotate(dir);//relTra.rotateInv(dir);//from b to a
const Vec3V p = supportLocal(_dir);
//transfer p into the b space
return aTob.transform(p);//relTra.transform(p);
}
PX_SUPPORT_INLINE aos::Vec3V supportLocal(const aos::Vec3VArg dir, PxI32& index)const
{
using namespace aos;
const BoolV comp = V3IsGrtr(dir, V3Zero());
getIndex(comp, index);
return V3Sel(comp, extents, V3Neg(extents));
}
PX_SUPPORT_INLINE aos::Vec3V supportRelative( const aos::Vec3VArg dir, const aos::PxMatTransformV& aTob,
const aos::PxMatTransformV& aTobT, PxI32& index)const
{
//a is the current object, b is the other object, dir is in the local space of b
using namespace aos;
// const Vec3V _dir = aTob.rotateInv(dir);//relTra.rotateInv(dir);//from b to a
const Vec3V _dir = aTobT.rotate(dir);//relTra.rotateInv(dir);//from b to a
const Vec3V p = supportLocal(_dir, index);
//transfer p into the b space
return aTob.transform(p);//relTra.transform(p);
}
aos::Vec3V extents;
};
} //PX_COMPILE_TIME_ASSERT(sizeof(Gu::BoxV) == 96);
}
#endif