今日由于选修了雷哥的物理学,所以不得不学有余力。好在现在为网路时代,共享心得的热心者有许多,所以学习起来总有参照
虽然资料并非全新,但是依旧免去了后辈的许多烦恼。
英文原文请戳我
本文参照 Tasos Papazoglou Chalikias于2013,2,24发表的Getting started on PhysX3.2.1&OpenGL一文。
PhysX,nVidia的一款物理引擎,被应用在多款游戏中,UDK(虚幻引擎)便采用了其解决方案。鉴于之后从事游戏制作会与
UnReal打交道,那么部署服务器的时候势必会使用到PhysX。在这里选用physx物理引擎+openGL可视化渲染的方案。
注:下文将创建一个空的PhysX sample。
1.下载PhysX SDK(截止目前官方最新为3.3.2)
2.新建一个Visual C++的新工程,按下Alt+F7,呼出属性界面
3.配置SDK与工程的路径连接
修改可执行目录(binary),包含目录(Include),库目录(Lib),源目录(Src)
$(SDK_Path)Bin\win32;$(ExecutablePath)
$(SDK_Path)Include;$(IncludePath)
$(SDK_Path)Lib\win32;$(LibraryPath)
$(SDK_Path)Source;$(SourcePath)
4.由于需要使用到OpenGL,所以要下载glut等常用工具。
glut等配置在隔壁放映室
5.俗话说的好,磨刀不误砍柴工,在正式敲击代码之前,我们尚需申明一下我们的类库。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#pragma comment(lib, "PhysX3_x86.lib")
#pragma comment(lib, "PhysX3Common_x86.lib")
#pragma comment(lib, "PhysX3Extensions.lib")
#pragma comment(lib, "PxTask.lib")
using namespace physx;
using namespace std;
如果遇到一些不明白的函数和类库可以参照下面的链接
NVIDIA PhysX API QAO
7.接下来就是正式的coding阶段
int start_time = 0,total_frames = 0;
float fps =0;
const int WINDOW_WIDTH = 800,WINDOW_HEIGHT =600;
PxScene *gloable_scene = NULL;
PxReal myTimestep = 1.0/60.0f;
窗口宽高
timestep设置了迭代时间
void InitPx()
{
PxFoundation *foundation = PxCreateFoundation(PX_PHYSICS_VERSION,gAllocator,gErrorcallback);
PxDirector = PxCreatePhysics(PX_PHYSICS_VERSION,*foudation,PxTolerancesScale() );
PxInitExtensions(*PxDirector);
//创建场景
PxSceneDesc sceneDesc(PxDirector->getToleranceScale());
sceneDesc.gravity = PxVec(0.0f,-9.8f,0.0f);
if(!sceneDesc.cpuDispatcher)
{
PxDefaultCpuDispatcher *mCpuDispatcher = PxDefaultCpuDispatcherCreate(1);
sceneDesc.cpuDispatcher = mCpuDispatcher;
}
if(sceneDesc.filterShader)
{
sceneDesc.filterShader = gFilterShader;
}
gScene = PxDirector->createScene(sceneDesc);
}
每一个Px模块都需要一个可用的基础(PxFoundation实例)。
需要的参数是 版本ID (PX_PHYSICS_VERSION),一个分配回调(gAllocator),一个错误回调(gErrorcallback),这两个参数需要你自己预先创建。
然后我们创建一个顶级的PxPhysic对象(PxDirector),需要版本ID,基础对象,以及一个PxToleranceScale()函数。
PxTolerance参数使得在不同尺寸创作内容的时候更加便捷,并且PhysX依旧像预期的效果一样。
但是为了快速开始我们传入了这个类型的默认对象。你也可以设置一个参数 recordMemoryAllocations 来开启内存性能分析。
同样的,设置mProfileZoneManager 参数可以开启PhysX可视化调试器性能分析。PhysX Visual Debugger下载
接下来,我们初始化扩展库。它包含了许多对使用者有用的函数,但是一些使用者可能更乐意在他们的应用中
忽略掉代码大小的原因或者避免使用某些子系统,例如和网络相关的。初始化扩展库需要有PxPhysics对象。
现在创建这个场景。PxScene对象是物理世界中具现化对象。创建场景需要在PxSceneDesc中指定一系列的不变 的参数。
我们先获取toleranceScale并且可以设定场景的性质。在示例代码中,我们设定了scene的重力场,一个Vec3。
之后我们创建了一个cpuDispatcher。Cpu调度员是SDK用来连接程序线程池的抽象类。一般般来说,一整个应用会有一个CpuDispatcher,除非这儿的确需要更多的线程池。在括号里的数值设定了使用CPU线程的数量(代码中为1)。如果你想包括CUDA的话,你也可以建立一个GPU调度员。
CUDA(compute unified devicearchitecture)是NVIDIA推出的通用运行计算架构。传送门
同样我们需要创建滤波着色器。
准备齐全所有的东西之后就可以根据场景描述来建立场景了(当然你得用顶级对象PxDirector去调用)
Ps:
不知道怎么写代码的看这里,是需要你自己预先创建的几个值。
static PxPhysics* PxDirector = NULL;
static PxDefaultErrorCallback gErrorcallback;
static PxDefaultAllocator gAllocator;
static PxSimulationFilterShader gFilterShader = PxDefaultSimulationFilterShader;
我们需要一些函数来管理时间迭代和PhysX的注销。
void StepPx()
{
gScene->simulate(myTimeStep);
while(!gScene->fetchResults())
{
//做一些你想做的事情嘿嘿
}
}
void onRender()
{
total_frames++;
int current = glutGet(GLUT_ELAPSED_TIME);
if((current-start_time)>1000)
{
float elapsedTime =current-start_time;
fps = ((tot *1000.0f)/elapsedTime);
start_time =current;
total_frames =0;
}
if(gScene)
{
StepPx();
}
glClearColor(0.1,0.1,0.1);
glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glSwapBuffers();
}
void Idle()
{
glutPostRedisplay();
}
void onShutdown()
{
gScene->release();
PxDirector->relea();
}
stepPx用simulate()设置了场景时间,simulate通过预定义的时间间隔(也就是我们的myTimeStep)来移动场景中的所有物体。
onRender函数计算了帧率,并且调用了stepPx,当然调用了glut清除buffers。
onShutDown 中我们调用了每一个Px物体的release函数,这会销毁这些对象,以及他们的子对象。
为了完全地注销physics,我们还调用了顶级PxPhysics对象的release函数,这将把所有的物理对象清除。最后我们也消除了foundation对象,当然这得在其他所有PhysX模组释放之后。
ps:这里需要注意,销毁函数要严格按照顺序,可以尝试一下,如果在场景之前预先调用了PxPhysics对象PxDirector的销毁函数,
在其他模组销毁之前将foundation销毁,会导致访问出错,不信你试一下不咯?
void main(int argc,char **argv)
{
atexit(onShutdown);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(WINDOW_WIDTH,WINDOW_HEIGHT);
glutCreateWindow("PxTest");
glutDisplayFunc(onRender);
glutIdleFunc(Idle);
InitPx();
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glutMainLoop();
}
喜闻乐见的计算机图形学必备技巧,openGL基础代码。
最后不要忘记把PhysX3_x86.dll和P3Common_x86.dll复制到你的 PxTest.vcxproj路径下,不然你会打不开的。虽然你可以丢在System32里面=-=但是我还是建议扔到解决方案路径下........
好了,以上就是一个PhysX的空框架。打开之后就能看见夜空(一片黑= =)
不要泄气添加几何体的教程陆续会来的
我是妖哲,希望教程对你有所帮助。
源代码移步github