Projekt_Grafika/dependencies/physx-4.1/source/physxextensions/src/ExtDefaultSimulationFilterS...

338 lines
9.9 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 "extensions/PxDefaultSimulationFilterShader.h"
#include "PxRigidActor.h"
#include "PxShape.h"
#include "PsIntrinsics.h"
#include "PsAllocator.h"
#include "PsInlineArray.h"
#include "PsFoundation.h"
#include "CmPhysXCommon.h"
using namespace physx;
namespace
{
#define GROUP_SIZE 32
struct PxCollisionBitMap
{
PX_INLINE PxCollisionBitMap() : enable(true) {}
bool operator()() const { return enable; }
bool& operator= (const bool &v) { enable = v; return enable; }
private:
bool enable;
};
PxCollisionBitMap gCollisionTable[GROUP_SIZE][GROUP_SIZE];
PxFilterOp::Enum gFilterOps[3] = { PxFilterOp::PX_FILTEROP_AND, PxFilterOp::PX_FILTEROP_AND, PxFilterOp::PX_FILTEROP_AND };
PxGroupsMask gFilterConstants[2];
bool gFilterBool = false;
static void gAND(PxGroupsMask& results, const PxGroupsMask& mask0, const PxGroupsMask& mask1)
{
results.bits0 = PxU16(mask0.bits0 & mask1.bits0);
results.bits1 = PxU16(mask0.bits1 & mask1.bits1);
results.bits2 = PxU16(mask0.bits2 & mask1.bits2);
results.bits3 = PxU16(mask0.bits3 & mask1.bits3);
}
static void gOR(PxGroupsMask& results, const PxGroupsMask& mask0, const PxGroupsMask& mask1)
{
results.bits0 = PxU16(mask0.bits0 | mask1.bits0);
results.bits1 = PxU16(mask0.bits1 | mask1.bits1);
results.bits2 = PxU16(mask0.bits2 | mask1.bits2);
results.bits3 = PxU16(mask0.bits3 | mask1.bits3);
}
static void gXOR(PxGroupsMask& results, const PxGroupsMask& mask0, const PxGroupsMask& mask1)
{
results.bits0 = PxU16(mask0.bits0 ^ mask1.bits0);
results.bits1 = PxU16(mask0.bits1 ^ mask1.bits1);
results.bits2 = PxU16(mask0.bits2 ^ mask1.bits2);
results.bits3 = PxU16(mask0.bits3 ^ mask1.bits3);
}
static void gNAND(PxGroupsMask& results, const PxGroupsMask& mask0, const PxGroupsMask& mask1)
{
results.bits0 = PxU16(~(mask0.bits0 & mask1.bits0));
results.bits1 = PxU16(~(mask0.bits1 & mask1.bits1));
results.bits2 = PxU16(~(mask0.bits2 & mask1.bits2));
results.bits3 = PxU16(~(mask0.bits3 & mask1.bits3));
}
static void gNOR(PxGroupsMask& results, const PxGroupsMask& mask0, const PxGroupsMask& mask1)
{
results.bits0 = PxU16(~(mask0.bits0 | mask1.bits0));
results.bits1 = PxU16(~(mask0.bits1 | mask1.bits1));
results.bits2 = PxU16(~(mask0.bits2 | mask1.bits2));
results.bits3 = PxU16(~(mask0.bits3 | mask1.bits3));
}
static void gNXOR(PxGroupsMask& results, const PxGroupsMask& mask0, const PxGroupsMask& mask1)
{
results.bits0 = PxU16(~(mask0.bits0 ^ mask1.bits0));
results.bits1 = PxU16(~(mask0.bits1 ^ mask1.bits1));
results.bits2 = PxU16(~(mask0.bits2 ^ mask1.bits2));
results.bits3 = PxU16(~(mask0.bits3 ^ mask1.bits3));
}
static void gSWAP_AND(PxGroupsMask& results, const PxGroupsMask& mask0, const PxGroupsMask& mask1)
{
results.bits0 = PxU16(mask0.bits0 & mask1.bits2);
results.bits1 = PxU16(mask0.bits1 & mask1.bits3);
results.bits2 = PxU16(mask0.bits2 & mask1.bits0);
results.bits3 = PxU16(mask0.bits3 & mask1.bits1);
}
typedef void (*FilterFunction) (PxGroupsMask& results, const PxGroupsMask& mask0, const PxGroupsMask& mask1);
FilterFunction const gTable[] = { gAND, gOR, gXOR, gNAND, gNOR, gNXOR, gSWAP_AND };
static PxFilterData convert(const PxGroupsMask& mask)
{
PxFilterData fd;
fd.word2 = PxU32(mask.bits0 | (mask.bits1 << 16));
fd.word3 = PxU32(mask.bits2 | (mask.bits3 << 16));
return fd;
}
static PxGroupsMask convert(const PxFilterData& fd)
{
PxGroupsMask mask;
mask.bits0 = PxU16((fd.word2 & 0xffff));
mask.bits1 = PxU16((fd.word2 >> 16));
mask.bits2 = PxU16((fd.word3 & 0xffff));
mask.bits3 = PxU16((fd.word3 >> 16));
return mask;
}
static bool getFilterData(const PxActor& actor, PxFilterData& fd)
{
PxActorType::Enum aType = actor.getType();
switch (aType)
{
case PxActorType::eRIGID_DYNAMIC:
case PxActorType::eRIGID_STATIC:
case PxActorType::eARTICULATION_LINK:
{
const PxRigidActor& rActor = static_cast<const PxRigidActor&>(actor);
PX_CHECK_AND_RETURN_VAL(rActor.getNbShapes() >= 1,"There must be a shape in actor", false);
PxShape* shape = NULL;
rActor.getShapes(&shape, 1);
fd = shape->getSimulationFilterData();
}
break;
case PxActorType::eACTOR_COUNT:
case PxActorType::eACTOR_FORCE_DWORD:
break;
}
return true;
}
PX_FORCE_INLINE static void adjustFilterData(bool groupsMask, const PxFilterData& src, PxFilterData& dst)
{
if (groupsMask)
{
dst.word2 = src.word2;
dst.word3 = src.word3;
}
else
dst.word0 = src.word0;
}
template<bool TGroupsMask>
static void setFilterData(PxActor& actor, const PxFilterData& fd)
{
PxActorType::Enum aType = actor.getType();
switch (aType)
{
case PxActorType::eRIGID_DYNAMIC:
case PxActorType::eRIGID_STATIC:
case PxActorType::eARTICULATION_LINK:
{
const PxRigidActor& rActor = static_cast<const PxRigidActor&>(actor);
PxShape* shape;
for(PxU32 i=0; i < rActor.getNbShapes(); i++)
{
rActor.getShapes(&shape, 1, i);
// retrieve current group mask
PxFilterData resultFd = shape->getSimulationFilterData();
adjustFilterData(TGroupsMask, fd, resultFd);
// set new filter data
shape->setSimulationFilterData(resultFd);
}
}
break;
case PxActorType::eACTOR_COUNT:
case PxActorType::eACTOR_FORCE_DWORD:
break;
}
}
}
PxFilterFlags physx::PxDefaultSimulationFilterShader(
PxFilterObjectAttributes attributes0,
PxFilterData filterData0,
PxFilterObjectAttributes attributes1,
PxFilterData filterData1,
PxPairFlags& pairFlags,
const void* constantBlock,
PxU32 constantBlockSize)
{
PX_UNUSED(constantBlock);
PX_UNUSED(constantBlockSize);
// let triggers through
if(PxFilterObjectIsTrigger(attributes0) || PxFilterObjectIsTrigger(attributes1))
{
pairFlags = PxPairFlag::eTRIGGER_DEFAULT;
return PxFilterFlags();
}
// Collision Group
if (!gCollisionTable[filterData0.word0][filterData1.word0]())
{
return PxFilterFlag::eSUPPRESS;
}
// Filter function
PxGroupsMask g0 = convert(filterData0);
PxGroupsMask g1 = convert(filterData1);
PxGroupsMask g0k0; gTable[gFilterOps[0]](g0k0, g0, gFilterConstants[0]);
PxGroupsMask g1k1; gTable[gFilterOps[1]](g1k1, g1, gFilterConstants[1]);
PxGroupsMask final; gTable[gFilterOps[2]](final, g0k0, g1k1);
bool r = final.bits0 || final.bits1 || final.bits2 || final.bits3;
if (r != gFilterBool)
{
return PxFilterFlag::eSUPPRESS;
}
pairFlags = PxPairFlag::eCONTACT_DEFAULT;
return PxFilterFlags();
}
bool physx::PxGetGroupCollisionFlag(const PxU16 group1, const PxU16 group2)
{
PX_CHECK_AND_RETURN_NULL(group1 < 32 && group2 < 32, "Group must be less than 32");
return gCollisionTable[group1][group2]();
}
void physx::PxSetGroupCollisionFlag(const PxU16 group1, const PxU16 group2, const bool enable)
{
PX_CHECK_AND_RETURN(group1 < 32 && group2 < 32, "Group must be less than 32");
gCollisionTable[group1][group2] = enable;
gCollisionTable[group2][group1] = enable;
}
PxU16 physx::PxGetGroup(const PxActor& actor)
{
PxFilterData fd;
getFilterData(actor, fd);
return PxU16(fd.word0);
}
void physx::PxSetGroup(PxActor& actor, const PxU16 collisionGroup)
{
PX_CHECK_AND_RETURN(collisionGroup < 32,"Collision group must be less than 32");
PxFilterData fd(collisionGroup, 0, 0, 0);
setFilterData<false>(actor, fd);
}
void physx::PxGetFilterOps(PxFilterOp::Enum& op0, PxFilterOp::Enum& op1, PxFilterOp::Enum& op2)
{
op0 = gFilterOps[0];
op1 = gFilterOps[1];
op2 = gFilterOps[2];
}
void physx::PxSetFilterOps(const PxFilterOp::Enum& op0, const PxFilterOp::Enum& op1, const PxFilterOp::Enum& op2)
{
gFilterOps[0] = op0;
gFilterOps[1] = op1;
gFilterOps[2] = op2;
}
bool physx::PxGetFilterBool()
{
return gFilterBool;
}
void physx::PxSetFilterBool(const bool enable)
{
gFilterBool = enable;
}
void physx::PxGetFilterConstants(PxGroupsMask& c0, PxGroupsMask& c1)
{
c0 = gFilterConstants[0];
c1 = gFilterConstants[1];
}
void physx::PxSetFilterConstants(const PxGroupsMask& c0, const PxGroupsMask& c1)
{
gFilterConstants[0] = c0;
gFilterConstants[1] = c1;
}
PxGroupsMask physx::PxGetGroupsMask(const PxActor& actor)
{
PxFilterData fd;
if (getFilterData(actor, fd))
return convert(fd);
else
return PxGroupsMask();
}
void physx::PxSetGroupsMask(PxActor& actor, const PxGroupsMask& mask)
{
PxFilterData fd = convert(mask);
setFilterData<true>(actor, fd);
}