PhysX3 User Guide 01 - 基础

原文地址: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提供了一组默认的 PxDefaultAllocatorPxDefaultErrorCallback

倒数第二个参数,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 类提供了一个完成该功能的函数。

 

略 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值