天天看點

PhysX3 User Guide 01 - 基礎

原文位址:http://www.cnblogs.com/mumuliang/archive/2011/06/02/2068453.html

 1 The SDK Object  

首先用全局函數 PxCreatePhysics建立一個PxPhysics對象。

PhysX3 User Guide 01 - 基礎

#include  " PxPhysicsAPI.h "

bool  recordMemoryAllocations  =   true ;

static  PxDefaultErrorCallback gDefaultErrorCallback;

static  PxDefaultAllocator gDefaultAllocatorCallback;

mSDK  =  PxCreatePhysics(PX_PHYSICS_VERSION, gDefaultAllocatorCallback, gDefaultErrorCallback, PxTolerancesScale(), recordMemoryAllocations );

if ( ! mSDK)

        fatalError( " PxCreatePhysics failed! " );

PhysX3 User Guide 01 - 基礎

這部分和SDK 2.x稍微有些不同,必須設定allocator callback和error callback. physx3的extensions提供了一組預設的 PxDefaultAllocator和 PxDefaultErrorCallback。

倒數第二個參數,PxTolerancesScale, 是建立場景中的物體的預設Tolerances。

最後一個bool,true表示可以 memory usage debugging 。

 2 The Allocator Callback     The allocator callback是需要自己實作的動态記憶體管理的接口類, PxAllocatorCallback。physx實作了一個, PxDefaultAllocator。

PhysX3 User Guide 01 - 基礎

#include  < malloc.h >

class  PxDefaultAllocator :  public  PxAllocatorCallback

{

         void *  allocate(size_t size,  const   char * ,  const   char * ,  int )

        {

                 return  _aligned_malloc(size,  16 );

        }

         void  deallocate( void *  ptr)

        {

                _aligned_free(ptr);

        }

};

PhysX3 User Guide 01 - 基礎

Note 與2.x不同的是,3.要求配置設定的記憶體是16位對齊(We now require that the memory that is returned be 16-byte aligned! )。windows上可以用 _aligned_malloc. 控制台系統(console systems)上的malloc()傳回的已經是16位對其的空間,是以不許特别處理。

If you want to track the SDK’s use of dynamic memory, you can put your own custom instrumentation code into the allocate and deallocate functions.

If you are curious about the three unused parameters of allocate, you can refer to  PxAllocatorCallback::allocate to find out more about them. Basically, we support a system of named allocations which let us identify types of memory allocation so that you can allocate them from special heaps. The last two parameters are the  __FILE__ and  __LINE__inside the SDK code where the allocation was made.

 3 The Error Callback    the error callback也是要自己實作的一個接口 PxErrorCallback。這個接口類隻需要實作一個方法, reportError. physx3也已經實作了一個。

PhysX3 User Guide 01 - 基礎

class  PxDefaultErrorCallback :  public  PxErrorCallback

{

public :

        PxDefaultErrorCallback();

         ~ PxDefaultErrorCallback();

         virtual   void  reportError(PxErrorCode::Enum code,  const   char *  message,  const   char *  file,  int  line);

};

void  PxDefaultErrorCallback::reportError(PxErrorCode::Enum e,  const   char *  message,  const   char *  file,  int  line)

{

         const   char *  errorCode  =  NULL;

         switch  (e)

        {

         case  PxErrorCode::eINVALID_PARAMETER:

                errorCode  =   " invalid parameter " ;

                 break ;

         case  PxErrorCode::eINVALID_OPERATION:

                errorCode  =   " invalid operation " ;

                 break ;

         case  PxErrorCode::eOUT_OF_MEMORY:

                errorCode  =   " out of memory " ;

                 break ;

         case  PxErrorCode::eDEBUG_INFO:

                errorCode  =   " info " ;

                 break ;

         case  PxErrorCode::eDEBUG_WARNING:

                errorCode  =   " warning " ;

                 break ;

         default :

                errorCode  =   " unknown error " ;

                 break ;

        }

        printf( " %s (%d) : " , file, line);

        printf( " %s " , errorCode);

        printf( "  : %s\n " , message);

}

PhysX3 User Guide 01 - 基礎

 4 Cooking and Extensions   PhysX有倆可選庫供使用:extensions 和 cooking. 應該在建立了SDK(也就是PxPhysics)對象後要首先初始化他們。他倆都需要一個東東,SDK的foundation對象。 if  ( ! PxInitExtensions( * mSDK))

        fatalError( " PxInitExtensions failed! " );

mCooking  =  PxCreateCooking(PX_PHYSICS_VERSION,  & mSDK -> getFoundation(), PxCookingParams());

if  ( ! mCooking)

        fatalError( " PxCreateCooking failed! " ); PxCreateCooking的第三個參數是可以設定的, 為了省事兒這兒也有預設值。

 5 The Scene   PxScene是PhysX的展現. 這個必須有。

PhysX3 User Guide 01 - 基礎

static  PxDefaultSimulationFilterShader gDefaultFilterShader;

PxScene *  mScene;

PxSceneDesc sceneDesc(mSDK -> getTolerancesScale());

sceneDesc.gravity  =  PxVec3( 0.0f ,  - 9.81f ,  0.0f );

customizeSceneDesc(sceneDesc);

if ( ! sceneDesc.cpuDispatcher)

{

        mCpuDispatcher  =  PxDefaultCpuDispatcherCreate(mNbThreads);

         if ( ! mCpuDispatcher)

                fatalError( " PxDefaultCpuDispatcherCreate failed! " );

        sceneDesc.cpuDispatcher  =  mCpuDispatcher;

}

if ( ! sceneDesc.filterShader)

        sceneDesc.filterShader   =   & gDefaultFilterShader;

#ifdef PX_WINDOWS

if ( ! sceneDesc.gpuDispatcher  &&  mCudaContextManager)

{

        sceneDesc.gpuDispatcher  =  mCudaContextManager -> getGpuDispatcher();

}

#endif

mScene  =  mSDK -> createScene(sceneDesc);

if  ( ! mScene)

        fatalError( " createScene failed! " );

PhysX3 User Guide 01 - 基礎

PxScene的屬性在建立時設定,建立後不能修改,PxSceneDesc就是描述其屬性的結構體. 

PxDefaultCpuDispatcherCreate 傳回一個預設的 CpuDispatcher對象. 線程數俺們設成1。當然這個 CpuDispatcher也是可以自己去實作的。

PxDefaultSimulationFilterShader ,又一個physx3的預設對象,實作接口 PxSimulationFilterShader.

 6 Basic Actors  

空場景有了,接下來添加物體。所有物體都必須有材質,是以俺們先造個材質 PxMeterial。 PxMaterial *      mMaterial;

mMaterial  =  mSDK -> createMaterial( 0.5f ,  0.5f ,  0.1f );      // static friction, dynamic friction, restitution

if ( ! mMaterial)

        fatalError( " createMaterial failed! " ); 材質定義了物體的摩擦力和慣性系數(friction and restitution coefficients )。  

然後就可以用這個材質建立個最簡單的static geometry,地面。 

PhysX3 User Guide 01 - 基礎

PxReal d  =   0.0f ;

PxU32 axis  =   1 ;

PxTransform pose;

if (axis  ==   0 )

        pose  =  PxTransform(PxVec3(d,  0.0f ,  0.0f ));

else   if (axis  ==   1 )

        pose  =  PxTransform(PxVec3( 0.0f , d,  0.0f ),PxQuat(PxHalfPi, PxVec3( 0.0f ,  0.0f ,  1.0f )));

else   if (axis  ==   2 )

        pose  =  PxTransform(PxVec3( 0.0f ,  0.0f , d), PxQuat( - PxHalfPi, PxVec3( 0.0f ,  1.0f ,  0.0f )));

PxRigidStatic *  plane  =  mSDK -> createRigidStatic(pose);

if  ( ! plane)

        fatalError( " create plane failed! " );

PxShape *  shape  =  plane -> createShape(PxPlaneGeometry(),  * mMaterial);

if  ( ! shape)

        fatalError( " create shape failed! " );

mScene -> addActor( * plane);

PhysX3 User Guide 01 - 基礎

axis的部分給出了分别設定x、y、z方向為豎直方向的做法。(Physx預設姿态?是,X正方向。)

第一個PxRigidStatic actor就醬(sdk調用 createRigidStatic())建立了, 然後往裡扔了一個平面shape, 這個shape使用了前邊兒建立的material。最後,把這個static actor添加到場景中。 

再使用extensions中的全局函數 PxCreateDynamic()建立一個盒子. 這個函數會把shape和actor一并建立,并根據傳入的密度density計算其品質mass和慣性inertia。

PhysX3 User Guide 01 - 基礎

PxReal density  =   1.0f ;

PxTransform(PxVec3( 0.0f ,  5.0f ,  0.0f ), PxQuat::createIdentity());

PxVec3 dimensions( 1.0f ,  1.0f ,  1.0f );

PxBoxGeometry geometry(dimensions);

PxRigidDynamic  * actor  =  PxCreateDynamic( * mSDK, transform, geometry,  * mMaterial, density);

if  ( ! actor)

        fatalError( " create actor failed! " );

mScene -> addActor( * actor);

PhysX3 User Guide 01 - 基礎

這兒還是用的那個材質。最後表忘了mScene->addActor()。

 7 The Simulation Loop   場景和其中的物體都建立好了,要讓他們動起來,需要在仿真循環中往前推進一個時間段。blabla...

一個最簡單的仿真循環:

PhysX3 User Guide 01 - 基礎

mAccumulator  =   0.0f ;

mStepSize  =   1.0f   /   60.0f ;

virtual   bool  advance(PxReal dt)

{

        mAccumulator   +=  dt;

         if (mAccumulator  <  mStepSize)

                 return   false ;

        mAccumulator  -=  mStepSize;

        mScene -> simulate(mStepSize);

         return   true ;

}

PhysX3 User Guide 01 - 基礎

mScene->simulate()的參數是往前推進的時間長度。這個函數極有可能是異步調用的。是以在return的時候可能還沒有算完。

假使這回想在某個圖形引擎中使用PhysX,抓取物體的位置和朝向 (positions and orientations) 以重新整理圖形引擎中對應的資料,可以使用PxShapeExt下的getGlobalPose。 PxTransform newPose  =  PxShapeExt::getGlobalPose( * mPhysicsShape);

圖形引擎run的時候PhysX的也在run,是以應該詢問simulate有否完成。 mScene -> fetchResults( true );

true表示如果還沒完成就block直到完成。在調用fetchResults之前使用getGlobalPose() (或其他擷取狀态的函數) 擷取actor或其他對象的資料,得到的是上一次simulate完成後的資料。

fetchResults, 會調用所有已定義的event callback。參考 ref:callbacks章節。

 8 Shutting Down   PhysX不用了以後,可以手動release。凡是形如 PxCreate... 建立的對象都有release方法,用來銷毀相關的資料。關閉整個場景的話,也同(調用PxPhysicx的release)。 mSDK -> release();

 9 PhysX Visual Debugger Support   PVD (PhysX Visual Debugger) 可直覺的檢視仿真場景中的情形。

PhysX一次隻能連接配接?一個debugger, PvdConnectionFactoryManager管理這些連接配接. 

有幾種方式連接配接debugger. 最簡單的方法是使用a network stream. extensions提供了一個功能函數 PxExtensionVisualDebugger::connect. 調用是要確定debugger已經運作. 

另一種可能更高效的方式把debug資訊寫到一個檔案,然後用debugger打開。 PvdConnectionFactoryManager 類提供了一個完成該功能的函數。

略 

繼續閱讀