原文位址:http://www.cnblogs.com/mumuliang/archive/2011/06/02/2068453.html
1 The SDK Object
首先用全局函數 PxCreatePhysics建立一個PxPhysics對象。

#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! " );

這部分和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。

#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);
}
};

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也已經實作了一個。

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);
}

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的展現. 這個必須有。

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! " );

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,地面。

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);

axis的部分給出了分别設定x、y、z方向為豎直方向的做法。(Physx預設姿态?是,X正方向。)
第一個PxRigidStatic actor就醬(sdk調用 createRigidStatic())建立了, 然後往裡扔了一個平面shape, 這個shape使用了前邊兒建立的material。最後,把這個static actor添加到場景中。
再使用extensions中的全局函數 PxCreateDynamic()建立一個盒子. 這個函數會把shape和actor一并建立,并根據傳入的密度density計算其品質mass和慣性inertia。

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);

這兒還是用的那個材質。最後表忘了mScene->addActor()。
7 The Simulation Loop 場景和其中的物體都建立好了,要讓他們動起來,需要在仿真循環中往前推進一個時間段。blabla...
一個最簡單的仿真循環:

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 ;
}

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 類提供了一個完成該功能的函數。
略