概述
PhysX目前是由 NVIDIA 開源的一個3D物理引擎瘟忱,由于其功能強大,目前已經(jīng)繼承在了各大商業(yè)游戲引擎中苫幢,例如 Unreal, Unity等访诱。
基本概念
PxScene
場景對象,同一個場景中的物體才有可能進行物理碰撞等韩肝,因此場景是一個場景物體的管理者触菜。
PxRigidActor
剛體對象(Rigidbody)的封裝
PxShape
幾何體的封裝, 每個 PxRigidActor 可以綁定多個 PxShape 對象哀峻,一般是通過 PxRigidActor 來創(chuàng)建 PxShape.
PxControllerManager
CharacterControllerManager涡相,用于創(chuàng)建 CharacterController。
CharactorController
上層封裝剩蟀,其實就是一個 PxRigidStatic 和 一個 PxShape 的組合體催蝗。
碰撞過濾器 ReportFilterShader
ReportFilterShader用于指定哪些 intersection pairs 需要被處理,因為這個在物理引擎底層需要被頻繁調(diào)用育特,因此性能至關(guān)重要丙号,因此提出了 FilterShader 這樣的概念,這 filter 的工作在 GPU 上也能運行缰冤,即使在 CPU 上運行也能并行犬缨。例子如下:
PxFilterFlags contactReportFilterShader(PxFilterObjectAttributes attributes0,
PxFilterData filterData0,
PxFilterObjectAttributes attributes1,
PxFilterData filterData1,
PxPairFlags& pairFlags,
const void* constantBlock,
PxU32 constantBlockSize)
{
if(PxFilterObjectIsTrigger(attributes0) || PxFilterObjectIsTrigger(attributes1))
{
pairFlags = PxPairFlag::eTRIGGER_DEFAULT;
return PxFilterFlag::eDEFAULT;
}
pairFlags = PxPairFlag::eCONTACT_DEFAULT;
// trigger the contact callback for pairs (A,B) where
// the filtermask of A contains the ID of B and vice versa.
// PX_INFO("contactReportFilterShader|%x|%x|%x|%x", filterData0.word0, filterData1.word1, filterData1.word0, filterData0.word1);
if((filterData0.word0 & filterData1.word1) && (filterData1.word0 & filterData0.word1))
{
pairFlags |= PxPairFlag::eNOTIFY_TOUCH_FOUND;
return PxFilterFlag::eDEFAULT;
}
return PxFilterFlag::eDEFAULT;
}
我們需要了解 ReportFilterShader 函數(shù)的參數(shù)含義以及返回值的含義:
先看看文檔是怎么描述的:
The arguments of SampleSubmarineFilterShader() include PxFilterObjectAttributes and PxFilterData for the two objects, and a constant block of memory. Note that the pointers to the two objects are NOT passed, because those pointers refer to the computer's main memory, and that may, as we said, not be available to the shader, so the pointers would not be very useful, as dereferencing them would likely cause a crash. PxFilterObjectAttributes and PxFilterData are intended to contain all the useful information that one could quickly glean from the pointers. PxFilterObjectAttributes are 32 bits of data, that encode the type of object: For examplePxFilterObjectType::eRIGID_STATIC, ::eRIGID_DYNAMIC, or even ::ePARTICLE_SYSTEM. Additionally, it lets you find out if the object is kinematic, or a trigger.
Each PxShape and PxParticleBase object in PhysX has a member variable of type PxFilterData. This is 128 bits of user defined data that can be used to store application specific information related to collision filtering. This is the other variable that is passed to SampleSubmarineFilterShader() for each object.
There is also the constant block. This is a chunk of per-scene global information that the application can give to the shader to operate on. You will want to use this to encode rules about what to filter and what not.
Finally, SampleSubmarineFilterShader() also has a PxPairFlags parameter. This is an output, like the return value PxFilterFlags, though used slightly differently. PxFilterFlags tells the SDK if it should ignore the pair for good (eKILL), ignore the pair while it is overlapping, but ask again, when filtering related data changes for one of the objects (eSUPPRESS), or call the low performance but more flexible CPU callback if the shader cannot decide (eCALLBACK).
PxPairFlags specifies additional flags that stand for actions that the simulation should take in the future for this pair. For example,eNOTIFY_TOUCH_FOUND means notify the user when the pair really starts to touch, not just potentially.
簡單解釋一下:
- attributes0 和 filterData0 是 intersection pair 中 第一個 PxShape 的數(shù)據(jù),前者表示 PxShape 的 Type(PxFilterObjectType::eRIGID_STATIC, ::eRIGID_DYNAMIC, or ::ePARTICLE_SYSTEM棉浸, 是否是 kinematic 或者是一個 trigger)怀薛,后者是 PxShape 的 UserData,在創(chuàng)建 PxShape 的時候可以通過 PxShape::setSimulationFilterData 函數(shù)指定迷郑;
- attribute1 和 filterData1 是 intersection pair 中另一個 PxShape 的數(shù)據(jù)乾戏,含義類似迂苛;
- PxFilterFlags 返回值是告訴SDK三热,如何處理這一對物體的碰撞鼓择,是放棄這一次碰撞的處理(eKILL),還是暫不處理除非這一次碰撞中filterData被改變(eSUPRESS)就漾,還是報告需要回調(diào)函數(shù)(eCALLBACK,eNOTIFY)等呐能。而pairFlags則是定義,如果需要回調(diào)函數(shù)的話抑堡,在什么情況下摆出,報告回調(diào)函數(shù),如碰撞被發(fā)現(xiàn)(eNOTIFY_TOUCH_FOUND), 碰撞結(jié)束兩個物體已分離(eNOTIFY_TOUCH_LOST)等首妖。
- constantBlock 和 constantBlockSize (This is a chunk of per-scene global information that the application can give to the shader to operate on. You will want to use this to encode rules about what to filter and what not.)
在創(chuàng)建場景的時候需要指定一個 FilterShader 用于解決后面的碰撞檢測偎漫,這是在 PxSceneDesc 中指定的;然后在創(chuàng)建 PxShape 的時候需要指定 filterData有缆,通過 PxShape::setSimulationFilterData 函數(shù)指定象踊,其中的 word0 字段一般指定 layer,word1 字段指定和哪些 layer 之間會發(fā)生碰撞棚壁。
碰撞回調(diào) PxSimulationEventCallback
場景中所有的碰撞都需要 developer 自己來進行處理杯矩,用于實現(xiàn)一個類繼承 PxSimulationEventCallback,基類如下:
class PxSimulationEventCallback {
public:
void onConstraintBreak(PxConstraintInfo* constraints, PxU32 count) ;
void onWake(PxActor** actors, PxU32 count);
void onSleep(PxActor** actors, PxU32 count) ;
virtual void onTrigger(PxTriggerPair* pairs, PxU32 count);
void onContact(const PxContactPairHeader& pairHeader, const PxContactPair* pairs, PxU32 nbPairs) ;
};
一般而言只需要處理 OnTrigger 和 OnContact 方法袖外。
CharacterController 碰撞回調(diào)
需要設(shè)置 PxCapsuleControllerDesc.reportCallback史隆,其中需要實現(xiàn):
void onShapeHit(const PxControllerShapeHit& hit);
void onControllerHit(const PxControllersHit& hit);
前者表示和其他 PxShape 的碰撞,后者表示和其他 CharacterController 的碰撞曼验。
一般使用流程
- PxCreateFoundation 創(chuàng)建 PxFoundaPxPhysicsion 對象泌射,全局唯一;
- PxCreatePhysics 創(chuàng)建 Physics對象鬓照,全局唯一熔酷;
- PxCreateCooking 創(chuàng)建 PxCooking 對象,全局唯一颖杏;
- PxSerialization::createSerializationRegistry 創(chuàng)建 PxSerializationRegistry 對象纯陨,全局唯一;
- 需要打開一個場景的時候留储,使用 Physics::CreateScene 創(chuàng)建一個場景翼抠,打開多個場景則需要創(chuàng)建多個 Scene 對象,設(shè)置好 FilterShader 和 SimulationCallback获讳;
- 創(chuàng)建 Static 或者 Dynamic Actor 或者 CharacterController;
- Tick 中獲取 Dynamin Actor 和 CharacterController的位置同步給邏輯層使用阴颖,同時在 SimulationCallback 中將碰撞信息通知邏輯層。