`
weimou66
  • 浏览: 1251097 次
文章分类
社区版块
存档分类
最新评论

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,应该会有更加好的方法来组织数据。 初次接触,错误难免,望指正。不胜感激!
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics