AGEIA的PhysX處理器是世界上首款物理模擬處理器 (PPU), 該處理器將解除中央處理器進行物理模擬的負擔。PhysX PPU 的設計構架基于頂點的多線程操作,允許游戲開發人員進行精確、流暢和動畫創作和運動模擬,例如毛發、布料、液體、流體等。目前 AGEIA 的PhysX處理器是世界上第一款也是唯一一款專注于物理算法處理器的產品.
利用PhysX SDK物理引擎開發包來實現我們仿真的效果時,一般需要以下幾個步驟:
(1)??? PrintControls();
(2)??? InitGlut(argc, argv);
(3)??? InitNx();
(4)??? glutMainLoop();
(5)??? ReleaseNx();
其中最為主要的函數是InitNx(),也既是初始化PhysX,創建一個PhysX SDK實例以及建立我們的場景。下面具體分析各個函數的作用。
一.
PrintControls();
顯而易見,利用該函數的目的是在告訴玩家該如何進行操作。操作的按鍵可根據自己的喜好進行設置。
二.
InitGlut(argc, argv);
PhysX是OpenGL上開發的,所以在初始化PhysX實例之前,必須建立一個OpenGL的框架。
①.???
glutInit(&argc, argv) 用來初始化GLUT,并且處理任意的命令行變量
②.???
glutInitWindowSize(int width, int size) 指定了窗口以像素為單位的尺寸
③.???
?glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH) 建立一個帶有雙緩存、RGB顏色模型和很大緩存的窗口
④.???
glutCreateWindow(char* string) 創建一個具有OpenGL創建的窗口,string為該窗口的窗口名
⑤.???
glutSetWindow()
⑥.???
glutDisplayFunc(RenderCallback) 渲染
ProcessCameraKeys();
??? ?SetupCamera();
??? ??? ?if (gScene && !bPause)
??? ?{
??????? GetPhysicsResults();
ProcessInputs();根據選擇的對象,給該對象施加前后、上下、左右不同方向的力,然后調用對象的方法addForce,產生不同的物理效果
??????? StartPhysics();
??? ?}
?? ?// Display scene
??? ?RenderActors(bShadows);
調用函數DrawActor(NxActor* actor)將場景中的物體渲染出來,實在是在DrawActor(NxActor* actor)函數中根據物體形狀調用不同形狀的繪畫函數將物體渲染出來的。在渲染的過程中,利用顯示列表繪制不同形狀的物體。在PhysX中,物體形狀分為以下幾種:NX_SHAPE_PLANE(面板狀), NX_SHAPE_BOX(盒子狀), NX_SHAPE_ SPHERE(球形狀), NX_SHAPE_CAPSULE(膠囊狀), NX_SHAPE_CONVEX(凸多邊形狀), NX_SHAPE_MESH(網狀狀)。
當bShadows為true時,渲染物體的陰影;為false時就不繪制
??? ?DrawForce(box, gForceVec, NxVec3(1,1,0));
??????? 將物體受力的受力方向渲染出來
⑦.???
glutReshapeFunc(ReshapeCallback)
設置窗口
⑧.???
glutIdleFunc(IdleCallback);
??
⑨.???
glutKeyboardFunc(KeyboardCallback);
⑩.???
glutKeyboardUpFunc(KeyboardUpCallback);
?.???
glutSpecialFunc(SpecialCallback);
在此,調用ResetNx(),重新渲染
?.???
glutMouseFunc(MouseCallback);
?.???
glutMotionFunc(MotionCallback);
?.???
MotionCallback(0,0);
三.
InitNx() 因為我們需要初始化PhysX SDK實例,并且建立我們需要的場景;所以我們需要設置以下幾個變量,并且將它們設置為全局變量
??? ???
NxPhysicsSDK*
gPhysicsSDK = NULL;
//PhysX SDK實例對象
NxScene*
gScene = NULL;
//場景對象
NxVec3
?
gDefaultGravity(0,-9.8,0);
***注意:坐標系的方向指向,在PhysX、OpenGL以及3DMax都有一些不一樣,當運行里面的demo的時候就可以體會到。它們的坐標系分別如下:??
??
?
??
下面就在InitNx()中開始初始化實例以及建立場景.
①.???
實例化 physics SDK
gPhysicsSDK = NxCreatePhysicsSDK(NX_PHYSICS_SDK_VERSION);
初始化完Physics SDK后,只是簡單的一個實例。可以通過設置實例的物理參數來充實我們的模擬效果.
gPhysicsSDK->setParameter(NX_SKIN_WIDTH, 0.01);
②.???
創建場景
??? ???????
NxSceneDesc sceneDesc;
//場景表述表對象
???
???????
sceneDesc.gravity?= gDefaultGravity;
??
????
sceneDesc.broadPhase?= NX_BROADPHASE_COHERENT;
??
????
sceneDesc.collisionDetection??? = true;
???
???????
gScene = gPhysicsSDK->createScene(sceneDesc);
在PhysX中,不管是創建場景還是創建各個物體角色時,都是先通過各自對應的描述器(翻譯的不是很準確)設置場景和各個物體的物理參數,用來模擬真實的世界環境和物體。建立好表述器后,通過函數
createSce
ne(
NxSceneDesc
)函數就可以建立需要的場景對象。
一般情況下,場景描述器的參數就是設置重力加速度
sceneDesc.gravity
,是否進行碰撞檢測
collisionDetection
, true為進行,
在PhysX SDK中描述器被廣泛的應用. 描述器包括所有你創建物體的信息
broadphase-coherent
是三種碰撞檢測中的一種。
gPhysicsSDK->setParameter(NX_SKIN_WIDTH, 0.01);
當相互碰撞的物體的材質都很軟的時候,在現實中就會發現當發生碰撞的時候物體之間就會相互嵌入一部分,在這里我們就可以利用物理參數
NX_SKIN_WIDTH
,它的默認值為0.05m,該值越大,嵌入的就越多
?
同時,我們可以對場景中的所有物體創建材質。創建的材質定義了碰撞和物體材料的物理屬性。比如反彈系數、靜摩擦力、滑動摩擦力等。
?
???
??? ????
// Create the default material
通過材質索引創建一個材質的對象
???
??? ????
NxMaterial* defaultMaterial = gScene->getMaterialFromIndex(0);
???
???????
defaultMaterial->setRestitution(0.5);
???
??? ????
defaultMaterial->setStaticFriction(0.5);
???
???????
defaultMaterial->setDynamicFriction(0.5);
?
創建物體,以box為例
NxActor* box = CreateBox(NxVec3(5,1,0));
NxActor* CreateBox(const NxVec3& pos)
{
??? ??? // Add a single-shape actor to the scene
??? ??? NxActorDesc actorDesc;
??? ??? NxBodyDesc bodyDesc;
?
??? ??? // The actor has one shape, a box
??? ??? NxBoxShapeDesc boxDesc;
??? ??? boxDesc.dimensions.set(0.5,1,0.5);
??? ??? actorDesc.shapes.pushBack(&boxDesc);
?
??? ??? actorDesc.body = &bodyDesc;
??? ??? actorDesc.density = 10;
??? ??? actorDesc.globalPose.t = pos;
??? ??? return gScene->createActor(actorDesc);?
}
我們創建一個角色參與者box,它的類型為
NxActor*
。建立該對象的時候需要設置它的描述器,然后利用函數
createActor(NxActorDesc actorDesc)
將該對象加入場景中。每一個對象又有和自己形狀相對應的描述器。利用它設置對象的物理參數。
boxDesc
該描述器描述了該盒子的長、寬、高分別為0.5,初始化的位置以及該盒子的密度。
③.???
創建完所有的物體對象時,調用
UpdateTime()
得到從上一幀渲染到現在經過的時間
④.???
當創建的場景成功,利用函數
StartPhysics()
開始它的第一幀模擬。
??? ???????
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();
}
simulate(deltaTime)
是PhysX 解決物理學的關鍵
?????????????
flushStream()
對時間步進行仿真
四.
glutMainLoop()
程序將一直停留在glutMainLoop()中,直到用戶自己結束。當場景一旦被渲染后,
在
每次
設置下一場景時
,
RenderCallback()
回調函數
將
被調用
五.
ReleaseNx()
??? 刪除場景中所有的物體對象以及場景本身
?