PhysX 3.3 基礎(chǔ)

概述

PhysX目前是由 NVIDIA 開(kāi)源的一個(gè)3D物理引擎,由于其功能強(qiáng)大,目前已經(jīng)繼承在了各大商業(yè)游戲引擎中,例如 Unreal, Unity等。

基本概念

PxScene

場(chǎng)景對(duì)象,同一個(gè)場(chǎng)景中的物體才有可能進(jìn)行物理碰撞等,因此場(chǎng)景是一個(gè)場(chǎng)景物體的管理者。

PxRigidActor

剛體對(duì)象(Rigidbody)的封裝

PxShape

幾何體的封裝, 每個(gè) PxRigidActor 可以綁定多個(gè) PxShape 對(duì)象,一般是通過(guò) PxRigidActor 來(lái)創(chuàng)建 PxShape.

PxControllerManager

CharacterControllerManager,用于創(chuàng)建 CharacterController。

CharactorController

上層封裝,其實(shí)就是一個(gè) PxRigidStatic 和 一個(gè) PxShape 的組合體。

碰撞過(guò)濾器 ReportFilterShader

ReportFilterShader用于指定哪些 intersection pairs 需要被處理,因?yàn)檫@個(gè)在物理引擎底層需要被頻繁調(diào)用,因此性能至關(guān)重要,因此提出了 FilterShader 這樣的概念,這 filter 的工作在 GPU 上也能運(yùn)行,即使在 CPU 上運(yùn)行也能并行。例子如下:

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.

簡(jiǎn)單解釋一下:

  • attributes0 和 filterData0 是 intersection pair 中 第一個(gè) PxShape 的數(shù)據(jù),前者表示 PxShape 的 Type(PxFilterObjectType::eRIGID_STATIC, ::eRIGID_DYNAMIC, or ::ePARTICLE_SYSTEM, 是否是 kinematic 或者是一個(gè) trigger),后者是 PxShape 的 UserData,在創(chuàng)建 PxShape 的時(shí)候可以通過(guò) PxShape::setSimulationFilterData 函數(shù)指定;
  • attribute1 和 filterData1 是 intersection pair 中另一個(gè) PxShape 的數(shù)據(jù),含義類(lèi)似;
  • PxFilterFlags 返回值是告訴SDK,如何處理這一對(duì)物體的碰撞,是放棄這一次碰撞的處理(eKILL),還是暫不處理除非這一次碰撞中filterData被改變(eSUPRESS),還是報(bào)告需要回調(diào)函數(shù)(eCALLBACK,eNOTIFY)等。而pairFlags則是定義,如果需要回調(diào)函數(shù)的話(huà),在什么情況下,報(bào)告回調(diào)函數(shù),如碰撞被發(fā)現(xiàn)(eNOTIFY_TOUCH_FOUND), 碰撞結(jié)束兩個(gè)物體已分離(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)建場(chǎng)景的時(shí)候需要指定一個(gè) FilterShader 用于解決后面的碰撞檢測(cè),這是在 PxSceneDesc 中指定的;然后在創(chuàng)建 PxShape 的時(shí)候需要指定 filterData,通過(guò) PxShape::setSimulationFilterData 函數(shù)指定,其中的 word0 字段一般指定 layer,word1 字段指定和哪些 layer 之間會(huì)發(fā)生碰撞。

碰撞回調(diào) PxSimulationEventCallback

場(chǎng)景中所有的碰撞都需要 developer 自己來(lái)進(jìn)行處理,用于實(shí)現(xiàn)一個(gè)類(lèi)繼承 PxSimulationEventCallback,基類(lèi)如下:

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,其中需要實(shí)現(xiàn):

void onShapeHit(const PxControllerShapeHit& hit);
void onControllerHit(const PxControllersHit& hit);

前者表示和其他 PxShape 的碰撞,后者表示和其他 CharacterController 的碰撞。

一般使用流程

  1. PxCreateFoundation 創(chuàng)建 PxFoundaPxPhysicsion 對(duì)象,全局唯一;
  2. PxCreatePhysics 創(chuàng)建 Physics對(duì)象,全局唯一;
  3. PxCreateCooking 創(chuàng)建 PxCooking 對(duì)象,全局唯一;
  4. PxSerialization::createSerializationRegistry 創(chuàng)建 PxSerializationRegistry 對(duì)象,全局唯一;
  5. 需要打開(kāi)一個(gè)場(chǎng)景的時(shí)候,使用 Physics::CreateScene 創(chuàng)建一個(gè)場(chǎng)景,打開(kāi)多個(gè)場(chǎng)景則需要?jiǎng)?chuàng)建多個(gè) Scene 對(duì)象,設(shè)置好 FilterShader 和 SimulationCallback;
  6. 創(chuàng)建 Static 或者 Dynamic Actor 或者 CharacterController;
  7. Tick 中獲取 Dynamin Actor 和 CharacterController的位置同步給邏輯層使用,同時(shí)在 SimulationCallback 中將碰撞信息通知邏輯層。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容