PhysX学习笔记

原文地址:http://blog.csdn.net/xoyojank/article/details/4388900


PhysX学习笔记(1): 基础

简单形状

l  NxBound3: AABB

l  NxBox: OBB

l  NxCapsule: 胶囊(线段+距离)

l  NxPlane

l  NxRay

l  NxSegment: 线段

l  NxSphere

 

SDK 初始化:

跟D3D差不多, 直接NxCreatePhysicsSDK就OK. 释放时不能delete, 因为那是DLL内部的对象, 只能release(). 多次创建返回的都是同一实例, 因为内部为单件实现.

 

对象实例:

一般都通过接口的create*(), 参数都用description类封装成一个. 注意返回值自己验证合法性. 释放时只能是谁创建了它谁释放, 不能自己释放自己. Down casting通过isXXX()这样的函数返回指针, 一个函数两用….

 

用户自定义数据:

物理对象都有一个公有的userData(void*类型)可以用来保存自定义数据. 另外, 每个物理对象都可以设置一个名字(const char*)做为标识. 可惜都是指针…这个地方极有可能变成野指针, 看来需要利用N3的Atom<T>.

 

状态保存:

通过对象的saveToDesc()/loadFromDesc()来保存/还原

 

参量:

l  rigid body transform: 刚体变换

l  position vector: 方位

l  rotation matrix: 旋转矩阵(行列式必须为1)

l  unit quaternion: 单位四元数, 表示旋转量

l  direction/extents vector: 偏移/方向

l  force vector: 力向量

l  torque vector: 力矩

l  velocity vector: 速度

l  angular velocity vector: 角速度

l  momentum vector: 动量

l  angular momentum vector: 角动量

 

工具函数:

见NxUtilLib


PhysX学习笔记(2): 动力学(1)

场景(Scene):

物理模拟发生的场所, 包含了actor, joint, effector. 跟图形引擎里的Scene差不多, 可以有多个实例存在, 互不干涉.

场景没有特别的大小限制. 功能有重力, 射线拣取, 开关硬拼检测等.

 

模拟时序(Timing):

物理模拟导致物体的一些属性随着时间进行变化, 如位置, 速度等.

模拟每经过一次时间步进进行一次, 通常要与渲染帧数进行同步.

前进(也可以说是更新):

void simulate(NxReal elapsedTime);

elapsedTime会被分成多个时间步进来决定物理模拟进行了多少

时序可以用setTiming设置, decriptor也可. 默认值就能够满足大多数程序的要求了.

固定的时间步进可以确保稳定且可以重现的物理模拟, 需指定NX_TIMESTEP_FIXED.

 

异步的步进:

PhysX是多线程的, 物理模拟发生在自己的线程里. 状态变化如下:

1)         开始模拟

2)         确保数据已被发送到模拟线程

3)         检测模拟是否完成, 如果是, 更新状态数据缓冲, 并且->

4)         交换状态数据缓冲, 这样结果可以被程序访问, 后台缓冲可以继续参数模拟(就像D3D的BackBuffer)

 

[cpp]  view plain copy
  1. NxScene* gScene;  
  2. NxReal myTimestep = 1.0f/60.0f;  
  3. ...  
  4.   
  5. void mySimulationStepFunction()  
  6. {  
  7.   
  8.     gScene->simulate(myTimestep);  
  9.     gScene->flushStream();  
  10.   
  11.     //...perform useful work here using previous frame's state data  
  12.   
  13.     gScene-> fetchResults(NX_RIGID_BODY_FINISHED, true);  
  14. }  

注意fetchResults(NX_RIGID_BODY_FINISHED, true)是一个阻塞调用, 可以用这两种方式代替:

[cpp]  view plain copy
  1. while(!gScene->checkResults(NX_RIGID_BODY_FINISHED, false)  
  2. {  
  3.     // do something useful  
  4. }  
  5.   
  6. while(!gScene->fetchResults(NX_RIGID_BODY_FINISHED, false)  
  7. {   
  8.     // do something useful  
  9. }  

注意: 一些函数对于异步的状态改变不可知, 如overlap和raycasting, 直到simulte()/fetchResult()执行后才可.

 

外壳宽度(Skin Width):

通俗点说, 就是能两个物体能相互插入多么深….. 因为模拟是以时间步进为单位的, 所以两次步进之间就会产生一个跳变, 这种互相越界的现象不可避免. 于是乎引入这么一个量, 用于保证稳定性.

PhysX学习笔记_第1张图片


PhysX学习笔记(3): 动力学(2) Actor

Actor

 

Actor扮演两种角色: 静态对象, 动态刚体(也叫body).

Actor包含shape. Shape之间相交会触发很多行为.

Static actor主要作用是碰撞检测, 所以一般都会赋于对应的shape

Dynamic actor可能只表示一个抽象的连接点, 所以不需要对应一个shape

 

创建actor:

[cpp]  view plain copy
  1. NxActorDesc actorDesc;  
  2. actorDesc.globalPose = ...;  
  3. gScene->createActor(actorDesc);  
注意: 一些actor相关的资源在simulate()执行之前不会释放.

 

Actor的Shape:

创建:


  
  
  
  
[cpp] view plain copy
  1. actorDesc.shapes.pushBack(&shapeDesc);// 1st way  
  2. actor->createShape(shapeDesc);// 2nd way  

销毁用actor的releaseShape()
一些限制:
l  Static actor至少需要有一个shape
l  一个actor如果没有solid shape(没有shape或只有trigger shape), 那么它必须有一个body(dynamic的), 包括质量和惯性张量(inertia tensor)
l  包含solid shape的dynamic actor需要满足下列之一:
n  非零质量, 零密度, 没有惯性张量(会根据质量计算)
n  零质量, 非零密度, 没有惯性张量(会根据密度计算)
n  零密度, 但指定质量和惯性惯性张量

复合(compound)shape:

当多个shape指定给actor时就会形成一个复合shape. 它们作为一个整体参与物理模拟, 相互之间没有物理性能消耗.

l  添加一个新的shape到已有shape集合会创建一个新的复合shape再加入, 所以最好一次性创建.

l  尽量避免static actor成为复合的, 因为每个actor的mesh三角形数是有限的, 多掉的会被忽略.

 

参考系(reference frame):

Actor最重要的属性是姿势(pose, 位置和朝向. 好像havok才支持缩放…).

所有actor位于的空间称作世界(world)或全局空间(global space). 一个空间也叫参考系.

Actor的重心是SDK自动计算的(当然也可以手动设置), 作为物体的旋转中心.

通常这样获得渲染所需要的变换矩阵:

[cpp]  view plain copy
  1. float glmat[16];//OpenGL matrix.  
  2. actor->getGlobalPose()->getColumnMajor44(glmat);  
  3. glMultMatrixf(glmat);//Send to OpenGL.  

 

注意: 设置朝向时使用四元数与矩阵没有性能差异.

 

刚体(Rigid Body)属性:

线性分量

角度分量

质量(mass), scalar

惯性(inertia), 质量分布

位置(position), 3-vector

朝向(orientation), quotation/3x3-matrix

速度(velocity), 3-vector

角速度(angular velocity), 3-vector, 方向代表转轴, 长度代表速度大小.

受力(force), 3-vector

力矩(torque), 表示方法同上

 

作用力和力矩

中学学过:   f = m*a (force = mass * acceleration)

NxActor的下列方法:

  
  
  
  
[cpp] view plain copy
  1. void addForceAtPos(const NxVec3 & force, const NxVec3 & pos, NxForceMode);  
  2. void addForceAtLocalPos(const NxVec3 & force, const NxrVec3 & pos, NxForceMode);  
  3. void addLocalForceAtPos(const NxVec3 & force, const NxVec3 & pos, NxForceMode);  
  4. void addLocalForceAtLocalPos(const NxrVec3& force, const NxVec3& pos, NxForceMode);  
  5. void addForce(const NxVec3 &, NxForceMode);  
  6. void addLocalForce(const NxVec3 &, NxForceMode);  
  7. void addTorque(const NxVec3 &, NxForceMode);  
  8. void addLocalTorque(const NxVec3 &, NxForceMode);  
NxForceMode默认是NX_FORCE(简单的受力), 还有NX_IMPULSE(冲力)和NX_VELOCITY_CHANGE(忽略惯性, 直接改变速度).

重力:

对于不需要重力控制的dynamic actor可以设置NxActor::raiseBodyFlag(NX_BF_DISABLE_GRAVITY).

 

设置速度:

不知道质量却需要与之相关的速度可以直接设置动量(momentum).
  
  
  
  
[cpp] view plain copy
  1. void setLinearVelocity(const NxVec3 &);  
  2. void setAngularVelocity(const NxVec3 &);  
  3. void setLinearMomentum(const NxVec3 &);  
  4. void setAngularMomentum(const NxVec3 &);  
注意: 不要让设置的速度超出float的上限, 不然会产生错误!

 

睡眠(Sleep):

睡眠后的物体不参与物理模拟, 直到有一个外部力作用于它.

睡眠判定:

l  简单睡眠: 速度低于NX_SLEEP_INTERVAL

l  平均速度: 比较适合震动体, 设置NX_BF_FILTER_SLEEP_VEL标记开启

l  基于动能: 这是默认的, 设置NX_BF_ENERGY_SLEEP_TEST标记开启

控制睡眠状态:

[cpp]  view plain copy
  1. void NxActor::wakeUp();  
  2. void NxActor::putToSleep();  

更改一些参数也会影响它, 如全局重力.

通过派生NxUserNotify可以实现睡眠状态改变时的事件处理回调. 
 
活跃变换通知:
有大量交互对象时遍历取得变换信息显然不可取. 那么可以只取得活跃的(上一次模拟步进的结果). 
开启:
  
  
  
  
[cpp] view plain copy
  1. sceneDesc.flags |= NX_SF_ENABLE_ACTIVETRANSFORMS;  
获取:
  
  
  
  
[cpp] view plain copy
  1. NxActiveTransform *NxScene::getActiveTransforms(NxU32 &nbActiveTransforms);  
  2. struct NxActiveTransform  
  3. {  
  4.     NxActor* actor;  
  5.     void* userData;  
  6.     NxMat34 actor2World;  
  7. };  
 
Static actor:
没有dynamic actor的任何属性. 创建时把body设置为NULL就好. 
创建好后不建议改变, 因这会打乱SDK为静态物体所做的优化. 
需要运动的static actor, 应使用kinematic actor
 
Kinematic actor:
特殊的dynamic actor, 不受用户控制(力, 碰撞等). 
创建: 先创建一个dynamic actor, 再设置成kinematic: NxActor::raiseBodyFlag(NX_BF_KINEMATIC).
附加说明:
l  Dynamic actor在受到一个kinematic和static(或两个kinematic)actor挤压时会被压进它们之中. 
l  Kinematic actor会与dynamic actor碰撞, 而不会与static actor发生关系. 
l  Kinematic actor每个次simulte移动的距离可能不一样, 因为速度是相对步进恒定的. 

PhysX学习笔记(4): 动力学(3) Joint

(关节)Joint

Joint和contact是约束body运动的两种方式

Joint坐标系:

PhysX学习笔记_第2张图片

 

Joint Limit: 相当于关节的活动范围

Breakable Joint: 可以断开的, 由setBreakable控制. 断开时会响应onJointBreak()

Joint类型:

PhysX学习笔记_第3张图片

球形关节: 肩膀, 绳子

PhysX学习笔记_第4张图片

卷动关节: 门

PhysX学习笔记_第5张图片

棱柱关节: 防震器

圆柱关节: 天线

固定关节: 可打断物体

PhysX学习笔记_第6张图片

距离关节: 钟摆, 弹簧

PhysX学习笔记_第7张图片

点面关节: 磁铁

点线关节: 窗帘挂环

滑轮关节

6DOF(Degree-of-Freedom)关节: 自定义

弹簧: 不建议使用, 应该用distance joint代替


你可能感兴趣的:(PhysX学习笔记)