

天正式开始接触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; } 
         }