PhysX

今天正式開始接觸PhysX,關於這個東西還是簡單說幾句。這是個很NB的物理引擎,Xbox360和PS3都使用了這個東東。 PhysX這個引擎很好用,上手十分簡單。簡單說句,現在在他的官方主頁上已經無法獲得SDK了 ,必須要先註冊提交申請,通過後才能下載。目前官方的最新版本似乎是2.5版本。我使用了以前下載的2.4.4版。 值得一提的是PhysX的文檔相當的詳細,從路徑設置到Tutorials的代碼解釋都有,大家有空還是看看吧。我這也是照抄文檔而已。 1、 安裝和設置 首先安裝好後,要設置編譯器路徑:
代碼:
Include文件: SDKs/Foundation/include", "SDKs/Physics/include" "SDKs/PhysXLoader/include "SDKs/NxCharacter/include" "SDKs/Cooking/include"
Lib文件: "SDKs/lib/win32/" Ok,現在就可以正式的使用這個引擎的SDK來開發了。 2、概念首先解釋幾個關於PhysX的概念: 要使用這個物理引擎模擬真實的物理現象,需要以下幾個東西: NxPhysicsSDK:Physics SDK對象,這個是進行物理模擬的最基礎的東西。它提供了創建物理系統的接口,是個純虛類。 NxScene: 場景。可以把它看成是物理概念上的世界,負責管理所有的物體以及世界的重力等等。一個程序可以維護多個場景。 Descriptor:一個專門負責初始化的類。你可以用這個類初始化任何該物理引擎要用到的東西,當然Descriptor也有很多種,有專門負責Scene的Descriptor,有專門負責初始化各個物體的Descriptor等等 。 NxMaterial:材質,描述物體的表面特徵。 Actors: 就是場景中的物體。也就是模擬的對象。 Joints: 用於連接的物體的物體。 當然還有很多概念,例如液體,等等。但是對於剛開始的來說已經足夠了。 另外,值得一提的是時間概念:和所有實時渲染的圖形庫一樣,時間在這個實時的物理引擎中的作用也是不可缺少的。物理引擎將在指定的時間片內對需要的物理計算進行運算然後傳遞給圖形接口繪製計算結果。 3、構建物理世界
代碼:
NxPhysicsSDK*     gPhysicsSDK = NULL; NxScene*          gScene = NULL; NxActor* groundPlane = NULL; NxActor* box = NULL;
首先建立SDK對象並初始化,然後分別是場景,物體。 void InitNx() { 1、 使用NxCreatePhysicsSDK()建立SDK對象,並初始化全局變量。 2、 建立NxSceneDesc,也就是描述Scene的描述對象,將初始化的值賦給它,例如重力,風。 3、 使用NxSceneDesc建立Scene:gPhysicsSDK->createScene(sceneDesc); 4、 建立並初始化NxMaterial 5、 建立2個NxActorDesc,並使用它們建立2個NxActor。 6、 獲取當前時間 7、 開始物理計算 } 羅列代碼我就不做了,如果需要SDK的可以聯繫我,或者誰能提供一個空間放上去更加好。 值得注意的是建立2個NxActor的過程,因爲NxActor有衆多的參數需要設置。] 4、進行物理模擬我們需要在每次渲染之前進行物理運算然後將結果取出交給圖形部分渲染。 使用引擎進行物理模擬很簡單,我們初始化完世界以及設置好物體之後,我們只需要2句話就能讓物理引擎自動進行相應的物理運算:
代碼:
void StartPhysics() {      // Update the time step      NxReal deltaTime = UpdateTime();        // Start collision and dynamics for delta time since the last frame     gScene->simulate(deltaTime);      gScene->flushStream(); } //============================================================= void GetPhysicsResults() {      // Get results from gScene->simulate(deltaTime)      while (!gScene->fetchResults(NX_RIGID_BODY_FINISHED, false)); }
注意使用fetchResults函數的時候最後傳遞的參數是false,這表明程序將以非阻塞的方式調用。如果使用阻塞方式調用的話,就一定會等到simulate有結果才返回。 所以每次渲染前先調用這2個函數然後再進行繪圖:
代碼:
void RenderCallback() { ...     if (gScene && !bPause) //是否暫停 或者是否需要繪製場景     {         GetPhysicsResults(); //獲取上次模擬結果         ProcessInputs();    //處理輸入         StartPhysics();     //根據輸入進行新的運算     } … }  
5、動態的施加力目前爲止,程序已經能模擬在重力環境下的物理運動,以及和地面的碰撞監測。我們同樣可以動態的施加任意方向的力給物體,只需要一句話即可:
代碼:
NxVec3 gForceVec(0,0,0); //全局變量,用於描述力的方向和大小 NxReal gForceStrength = 150; gForceVec = ApplyForceToActor(box,NxVec3(0,0,1),gForceStrength);//Z方向施力
這樣處理按鍵的代碼就顯而易見了:
代碼:
         switch (i)          {               // Force controls               case 'i': { gForceVec = ApplyForceToActor(box,NxVec3(0,0,1),gForceStrength); break; }               case 'k': { gForceVec = ApplyForceToActor(box,NxVec3(0,0,-1),gForceStrength); break; }               case 'j': { gForceVec = ApplyForceToActor(box,NxVec3(1,0,0),gForceStrength); break; }               case 'l': { gForceVec = ApplyForceToActor(box,NxVec3(-1,0,0),gForceStrength); break; }               case 'u': { gForceVec = ApplyForceToActor(box,NxVec3(0,1,0),gForceStrength); break; }               case 'm': { gForceVec = ApplyForceToActor(box,NxVec3(0,-1,0),gForceStrength); break; }                // Return box to (0,5,0)              case 't': { box->setGlobalPosition(NxVec3(0,5,0)); break; }          }    
6、畫出物體目前所有的物體的信息都位於Actor中。所以我們需要獲取所有的Actor。用循環分別畫出。
代碼:
void RenderActors(bool shadows) {     NxU32 nbActors = gScene->getNbActors(); //number     NxActor** actors = gScene->getActors(); //Actor的數組     while (nbActors--)     {         NxActor* actor = *actors++;         DrawActor(actor);         if (shadows)        // 處理陰影         {               DrawActorShadow(actor);         }     } }  
7、清理工作
代碼:
void ReleaseNx() {     if (gScene)     {         GetPhysicsResults(); // 確保沒有fetchResults在等待運行結果         gPhysicsSDK->releaseScene(*gScene);     }     if (gPhysicsSDK) gPhysicsSDK->release(); }   void ResetNx()       //重置 {     ReleaseNx();     InitNx(); }  
End 我覺得其實搞清楚物理引擎的工作流程比理解其中細節更加重要,其實PhysX事例中附帶的圖形部分的代碼也很有意思,不過重點不在那罷了。 有一點我覺得還是不太理解,整個程序的物體的信息都是保存在Sence中的Actor裏面的,包括最後的渲染都需要從Actor裏面取得,如果遊戲中的幾何物體很複雜而且很多的話我覺得還是不太妥當,當然這僅僅是第一次接觸PhysX,應該會有更加好的方法來組織數據。 初次接觸,錯誤難免,望指正。不勝感激!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章