PhysX之旅(一)
-- NxBoxes的逐行分析
学习新东西免不了走弯路,这个时候能得到指引的话,实在是很幸运的事情。所以我想说:能有SDK真是太好了!
NxBoxes是PhysX的第1个例子,对它进行逐行分析是很有必要的。当我们完完全全了解每一行代码有什么用的时候,我们也就入门了。
#include <stdio.h>
#include <GL/glut.h>
#include "NxPhysics.h"
#pragma comment(lib, "C:/Program Files/NVIDIA Corporation/NVIDIA PhysX SDK/v2.8.1/SDKs/lib/Win32/PhysXLoader.lib")
#pragma comment(lib, "E:/work/test_bin/extern_library/lib/debug/freeglut.lib")
#define NOMINMAX
#include <windows.h>
//#include "ErrorStream.h"
#include <windows.h>
//#include "PerfRenderer.h"
//#include "Utilities.h"
//#include "SamplesVRDSettings.h"
// Physics
static NxPhysicsSDK*gPhysicsSDK = NULL;// PhysX接口指针
static NxScene*gScene = NULL;// 场景指针
//static PerfRenderer gPerfRenderer;
/*
渲染前统计用的类
该类只有2个对外方法:
bool toggleEnable(); // 显示/隐藏切换
void render(const NxProfileData* prof, int width, int height);
关于NxProfileData:
\brief Array of profiling data.
性能数据数组。
profileZones points to an array of numZones profile zones. Zones are sorted such that the parent zones always come before their children.
Some zones have multiple parents (code called from multiple places) in which case only the relationship to the first parent is displayed.
returned by NxScene::readProfileData().
关于ProfileZones
\brief Names for a number of profile zones that should always be available. Can be used with NxProfileData::getNamedZone()
<b>Platform:</b>
\li PC SW: Yes
\li PPU : Yes
\li PS3 : No
\li XB360: No
enum NxProfileZoneName
{
NX_PZ_CLIENT_FRAME,//!< Clock start is in client thread, just before scene thread was kicked off; clock end is when client calls fetchResults().
NX_PZ_CPU_SIMULATE,//!< Maximum time of simulation thread ((Nf)Scene::simulate(NxU32)), over all CPU scenes inside the NxScene.
NX_PZ_PPU0_SIMULATE,//!< Maximum time of simulation thread over all PPU# scenes inside the NxScene.
NX_PZ_PPU1_SIMULATE,
NX_PZ_PPU2_SIMULATE,
NX_PZ_PPU3_SIMULATE,
NX_PZ_TOTAL_SIMULATION = 0x10,//!< Clock start is in client thread, just before scene thread was kicked off; clock end is in simulation thread when it finishes.
};
*/
// Rendering
static NxVec3gEye(50.0f, 50.0f, 50.0f);// 摄象机位置
static NxVec3gDir(-0.6f,-0.2f,-0.7f);// 摄象机方向
static NxVec3gViewY;// 摄象机“左平移”的方向
static intgMouseX = 0;// 鼠标当前X坐标(abs)
static intgMouseY = 0;// 鼠标当前Y坐标(abs)
static bool InitNx() // 该函数负责初始化PhysX
{
// Initialize PhysicsSDK
NxPhysicsSDKDesc desc; // 设备描述符,主要用来指定硬件和场景之间“对数据的共享程度”?
NxSDKCreateError errorCode = NXCE_NO_ERROR; // 调用NxCreatePhysicsSDK()返回的错误信息
/*
enum NxSDKCreateError
{
NXCE_NO_ERROR= 0,// 没错误
NXCE_PHYSX_NOT_FOUND= 1,// 找不到PhysX库,未安装PhysX驱动
NXCE_WRONG_VERSION= 2,// SDK版本和Driver版本不匹配
NXCE_DESCRIPTOR_INVALID= 3,// 无效的描述符
NXCE_CONNECTION_ERROR= 4,// 与设备通信出现故障。
NXCE_RESET_ERROR= 5,// 未重置(初始化)的设备
NXCE_IN_USE_ERROR= 6,// 设备正在被其他程序使用
NXCE_BUNDLE_ERROR= 7// 恭喜,你的物理加速卡坏了
};
*/
gPhysicsSDK = NxCreatePhysicsSDK(NX_PHYSICS_SDK_VERSION, NULL, /*new ErrorStream()*/NULL, desc, &errorCode); // 创建接口指针。
if(gPhysicsSDK == NULL) // 如果出错了,打印出错误信息
{
//printf("\nSDK create error (%d - %s).\nUnable to initialize the PhysX SDK, exiting the sample.\n\n", errorCode, getNxSDKCreateError(errorCode));
return false;
}
// 可视化远程调试器的设置...从来没玩过...
//#if SAMPLES_USE_VRD
//// 设置Visual Remote Debugger的IP和port。(在SampleCommonCode/SamplesVRDSettings.h文件中定义)
//if (gPhysicsSDK->getFoundationSDK().getRemoteDebugger())
//gPhysicsSDK->getFoundationSDK().getRemoteDebugger()->connect(SAMPLES_VRD_HOST, SAMPLES_VRD_PORT, SAMPLES_VRD_EVENTMASK);
//#endif
// 设置变量,皮肤厚度为0.05,实际结果就是角色的碰撞几何体被缩小了0.05。
gPhysicsSDK->setParameter(NX_SKIN_WIDTH, 0.05f);
// Create a scene
NxSceneDesc sceneDesc; // 声明一个场景描述符
sceneDesc.gravity= NxVec3(0.0f, -9.81f, 0.0f); // 设置重力加速度
gScene = gPhysicsSDK->createScene(sceneDesc);// 使用刚才的场景描述符来创建场景
if(gScene == NULL)// 错误处理
{
printf("\nError: Unable to create a PhysX scene, exiting the sample.\n\n");
return false;
}
// Set default material // 设置材质
// 总是存在一个默认材质(index = 0),该材质也不能被释放,调用releaseMaterial(defaultMaterial)将没有任何效果
NxMaterial* defaultMaterial = gScene->getMaterialFromIndex(0);
defaultMaterial->setRestitution(0.0f);// 设置还原系数
defaultMaterial->setStaticFriction(0.5f);// 设置静摩擦系数
defaultMaterial->setDynamicFriction(0.5f);// 设置动摩擦系数
// Create ground plane // 创建一个片,作为地板
NxPlaneShapeDesc planeDesc;// 很明显,片描述符
NxActorDesc actorDesc;// 角色描述符
actorDesc.shapes.pushBack(&planeDesc);// 将片描述符添加到角色描述符中
gScene->createActor(actorDesc);// 创建角色
return true;
}
// 该函数做清理工作
static void ExitNx()
{
if(gPhysicsSDK != NULL)
{
if(gScene != NULL) gPhysicsSDK->releaseScene(*gScene);// 释放场景
gScene = NULL;
NxReleasePhysicsSDK(gPhysicsSDK);// 释放PhysX
gPhysicsSDK = NULL;
}
}
// 创建一个cube
static void CreateCube(const NxVec3& pos, int size=2, const NxVec3* initialVelocity=NULL)
{
if(gScene == NULL) return;
// Create body // 创建刚体
NxBodyDesc bodyDesc;// 刚体描述符
bodyDesc.angularDamping= 0.5f;// 旋转衰减
if(initialVelocity) bodyDesc.linearVelocity = *initialVelocity;// (沿着某个方向的)速度
NxBoxShapeDesc boxDesc;// 盒子描述符
boxDesc.dimensions = NxVec3((float)size, (float)size, (float)size);// 设置盒子的体积
NxActorDesc actorDesc;// 角色描述符
actorDesc.shapes.pushBack(&boxDesc);// 将盒子描述符添加到角色描述符中
actorDesc.body= &bodyDesc;// 设置刚体描述符
actorDesc.density= 10.0f;// 设置密度
actorDesc.globalPose.t = pos;// 设置物体当前坐标(世界坐标系)
gScene->createActor(actorDesc)->userData = (void*)size_t(size); // 创建角色
//printf("Total: %d actors\n", gScene->getNbActors());
}
// 创建大方块
static void CreateCubeFromEye(int size)
{
NxVec3 t = gEye;// 点
NxVec3 vel = gDir;// 方向
vel.normalize();// 归一化
vel*=200.0f;// 该方向上的速度(200个单位向量)
CreateCube(t, size, &vel); // 创建方块
}
// 创建金字塔
static void CreateStack(int size)
{
const float cubeSize = 2.0f;
const float spacing = -2.0f*gPhysicsSDK->getParameter(NX_SKIN_WIDTH); // 缩放产生的尺寸减少的值。
// 只要知道“皮肤厚度”代表的意义之后,以下的代码不过是为了让这些方块紧密排列的算法而已。
NxVec3 pos(0.0f, cubeSize, 0.0f);
float offset = -size * (cubeSize * 2.0f + spacing) * 0.5f;
while(size)
{
for(int i=0;i<size;i++)
{
pos.x = offset + (float)i * (cubeSize * 2.0f + spacing);
CreateCube(pos, (int)cubeSize);
}
offset += cubeSize;
pos.y += (cubeSize * 2.0f + spacing);
size--;
}
}
// 创建棍子
static void CreateTower(int size)
{
const float cubeSize = 2.0f;
const float spacing = 0.01f;
NxVec3 pos(0.0f, cubeSize, 0.0f);
while(size)
{
CreateCube(pos, (int)cubeSize);
pos.y += (cubeSize * 2.0f + spacing);
size--;
}
}
// 键盘回调函数
static void KeyboardCallback(unsigned char key, int x, int y)
{
switch(key)
{
case 27:// ESC的ASCII码为27
exit(0);
break;
case '0':
//gPerfRenderer.toggleEnable();
break;
case ' ':
CreateCube(NxVec3(0.0f, 20.0f, 0.0f),1); // 在 (0,20,0)的位置创建 大小为1,速度为0的方块
break;
case 's':
case 'S':
CreateStack(10);
break;
case 'b':
case 'B':
CreateStack(30);
break;
case 't':
case 'T':
CreateTower(30);
break;
case 'w':
case 'W':
CreateCubeFromEye(8);
break;
case 'q':
case 'Q':
{
NxActor** actors = gScene->getActors();
if(gScene->getNbActors() > 1){
gScene->releaseActor(*actors[gScene->getNbActors()-1]);
}
}
break;
case GLUT_KEY_UP:case '8':gEye += gDir*2.0f; break;
case GLUT_KEY_DOWN: case '2':gEye -= gDir*2.0f; break;
case GLUT_KEY_LEFT:case '4':gEye -= gViewY*2.0f; break;
case GLUT_KEY_RIGHT: case '6':gEye += gViewY*2.0f; break;
}
}
// 键盘回调函数
static void ArrowKeyCallback(int key, int x, int y)
{
KeyboardCallback(key,x,y);
}
// 鼠标回调函数
static void MouseCallback(int button, int state, int x, int y)
{
gMouseX = x;
gMouseY = y;
}
// 运动回调函数?
static void MotionCallback(int x, int y)
{
int dx = gMouseX - x;
int dy = gMouseY - y;
gDir.normalize();
gViewY.cross(gDir, NxVec3(0,1,0));
NxQuat qx(NxPiF32 * dx * 20/ 180.0f, NxVec3(0,1,0));
qx.rotate(gDir);
NxQuat qy(NxPiF32 * dy * 20/ 180.0f, gViewY);
qy.rotate(gDir);
gMouseX = x;
gMouseY = y;
}
// 渲染回调函数
// 当把上一贞的结果提交到渲染队列进行渲染的时候,CPU就空闲了,这个时候再
static void RenderCallback()
{
static DWORD elapsedTime = 0;
if(gScene == NULL) return;
// Start simulation (non blocking)
if( elapsedTime!= 0 )
{
elapsedTime = ::GetTickCount() - elapsedTime;
}
gScene->simulate( elapsedTime *0.001f ); // 进行模拟,所有的物理相关的计算都由该函数处理了。
#pragma region OpenGL相关
// Clear buffers
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
// Setup projection matrix
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0f, (float)glutGet(GLUT_WINDOW_WIDTH)/(float)glutGet(GLUT_WINDOW_HEIGHT), 1.0f, 10000.0f);
gluLookAt(gEye.x, gEye.y, gEye.z, gEye.x + gDir.x, gEye.y + gDir.y, gEye.z + gDir.z, 0.0f, 1.0f, 0.0f);
// Setup modelview matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Render all actors
int nbActors = gScene->getNbActors();// 获得角色总数
NxActor** actors = gScene->getActors();// 获得角色队列指针
while(nbActors--)// 不渲染地板,因为可以从代码的编写上来保证第1个一定是地板,所以这里不做检测
{
NxActor* actor = *actors++;// 做迭代
if(!actor->userData) continue;// 如果角色的“用户自定义数据”指针非空,也不渲染它
// 渲染角色
// Render actor
glPushMatrix();
float glMat[16];
actor->getGlobalPose().getColumnMajor44(glMat);
glMultMatrixf(glMat);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);// 设置颜色
glutSolidCube(float(size_t(actor->userData))*2.0f); // 进行渲染
glPopMatrix();
// Render shadow
glPushMatrix();
const static float shadowMat[]={ 1,0,0,0, 0,0,0,0, 0,0,1,0, 0,0,0,1 };
glMultMatrixf(shadowMat);
glMultMatrixf(glMat);
glDisable(GL_LIGHTING);
glColor4f(0.1f, 0.2f, 0.3f, 1.0f);
glutSolidCube(float(size_t(actor->userData))*2.0f);
glEnable(GL_LIGHTING);
glPopMatrix();
}
#pragma endregion OpenGL相关
// Fetch simulation results
gScene->flushStream();
gScene->fetchResults(NX_RIGID_BODY_FINISHED, true);
elapsedTime = ::GetTickCount();
// Print profile results (if enabled)
//gPerfRenderer.render(gScene->readProfileData(true), glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));
glutSwapBuffers();
}
static void ReshapeCallback(int width, int height)
{
glViewport(0, 0, width, height);
}
static void IdleCallback()
{
glutPostRedisplay();
}
int main(int argc, char** argv)
{
// Initialize glut
printf("Use the arrow keys or 2, 4, 6 and 8 to move the camera.\n");
printf("Use the mouse to rotate the camera.\n");
printf("Press the keys w, t, s, b and space to create various things.\n");
printf("Press q to destroy the last thing created.\n");
printf("Press 0 to toggle the frame rate display.\n");
glutInit(&argc, argv);
glutInitWindowSize(512, 512);
glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH);
int mainHandle = glutCreateWindow("SampleBoxes");
glutSetWindow(mainHandle);
glutDisplayFunc(RenderCallback);
glutReshapeFunc(ReshapeCallback);
glutIdleFunc(IdleCallback);
glutKeyboardFunc(KeyboardCallback);
glutSpecialFunc(ArrowKeyCallback);
glutMouseFunc(MouseCallback);
glutMotionFunc(MotionCallback);
MotionCallback(0,0);
atexit(ExitNx);
// Setup default render states
glClearColor(0.3f, 0.4f, 0.5f, 1.0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
// Setup lighting
glEnable(GL_LIGHTING);
float ambientColor[]= { 0.0f, 0.1f, 0.2f, 0.0f };
float diffuseColor[]= { 1.0f, 1.0f, 1.0f, 0.0f };
float specularColor[]= { 0.0f, 0.0f, 0.0f, 0.0f };
float position[]= { 100.0f, 100.0f, 400.0f, 1.0f };
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientColor);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseColor);
glLightfv(GL_LIGHT0, GL_SPECULAR, specularColor);
glLightfv(GL_LIGHT0, GL_POSITION, position);
glEnable(GL_LIGHT0);
// Initialize physics scene and start the application main loop if scene was created
if (InitNx())
glutMainLoop();
return 0;
}
分享到:
相关推荐
Physx 系统配置,最新版. 安装Physx,先下载安装SystemSoftware,后下载安装physx sdk
enable AMD + Nvidia Display Card use PhysX
PhysX-3.4-master\PhysX_3.4\Source\compiler,然后根据操作系统版本选文件夹,选中PhysX.sln 生成解决方案后,SnippetHelloWorld设启动项可展开demo
COMPATIBLE),DirectX 9(使用SlimDX)3D引擎/ HELPER / WRAPPER该项目将这些技术合并到一个简单的开源引擎中,从而允许使用DirectX轻松访问Nvidia PhysX库。 9(VIA-SLIMDX)在VB.NET中使用C#和其他.NET语言兼容...
煤渣物理 适用于Cinder的Nvidia Physx SDK实现。 在此处了解有关Physx的更多信息: : ... 打开“ Cinder-Physx / PhysX-3.3 / PhysXSDK / Source / compiler / vc12win64 / PhysX.sln” 转到“构建”>“批量构建
PhysX-4.1 source code 源码 带工程 用VS2017编译打开physx\compiler\vc15win64\PhysXSDK.sln
PhysX.Net 使用C ++ / CLI编写的NVIDIA PhysX 4.1.0的.NET包装。努吉特PM>安装包PhysX.Net-预发行版建造所有东西! 所有相关DLL和示例的压缩文件-https: 发展历程适用于NVIDIA PhysX 4.1.0.25992954的PhysX.Net ...
破解N卡PhysX物理加速实现N卡同A卡混合使用教程借鉴.pdf
As a game developer, you'll know the power of PhysX to add simulation-level realism to games, and this book shows you exactly how best to achieve it with a hands-on, examples-led approach. ...
为免于多次评分之烦恼,在最后一个包加积分需求。 若需要官方其它资源,可以联系我,我帮忙下载。xy.kong@gmail.com APEXSDK-1.0.39 beta-PhysX_2.8.4.5-WIN-VC9.msi Subcategories in 'APEX' Contains APEX ...
ALI213-PhysX
PhysX JS PhysX for JavaScript。 该回购补充了在工作正在做超过为创建emscripten绑定。... 该示例也可以在,它托管通过npm使用npm install physx-jsphysx.release.js文件可以通过Webpack导入,也可以作为脚本包含在
刚刚下下来的最新版的physx3.2sdk,是学习物理引擎的好资料,由于文件较大不能一次上传,只好分开压缩上传了,共有三个压缩文件
掌握PhysX 3物理引擎开发技术 教你如何进行物理仿真编程
[PhysX] PhysX 物理建模 学习教程 (英文版)Learning Physics Modeling with PhysX.pdf 能找到的资料不多关于Physx的内容。
版本3.4
physx 入门的简单文档,供刚接触physx参考,辅以一个hello world例子
OpenSceneGraph结合PhysX物理引擎,示例代码,很棒。
physX的.net wrapper,有例程适用于xna4.0,对开发很有帮助
PhysX 2.8.1 SDK physX 物理引擎第二部分