原文地址: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
场景(Scene):
物理模拟发生的场所, 包含了actor, joint, effector. 跟图形引擎里的Scene差不多, 可以有多个实例存在, 互不干涉.
场景没有特别的大小限制. 功能有重力, 射线拣取, 开关硬拼检测等.
模拟时序(Timing):
物理模拟导致物体的一些属性随着时间进行变化, 如位置, 速度等.
模拟每经过一次时间步进进行一次, 通常要与渲染帧数进行同步.
前进(也可以说是更新):
void simulate(NxReal elapsedTime);
elapsedTime会被分成多个时间步进来决定物理模拟进行了多少
时序可以用setTiming设置, decriptor也可. 默认值就能够满足大多数程序的要求了.
固定的时间步进可以确保稳定且可以重现的物理模拟, 需指定NX_TIMESTEP_FIXED.
异步的步进:
PhysX是多线程的, 物理模拟发生在自己的线程里. 状态变化如下:
1) 开始模拟
2) 确保数据已被发送到模拟线程
3) 检测模拟是否完成, 如果是, 更新状态数据缓冲, 并且->
4) 交换状态数据缓冲, 这样结果可以被程序访问, 后台缓冲可以继续参数模拟(就像D3D的BackBuffer)
注意: 一些函数对于异步的状态改变不可知, 如overlap和raycasting, 直到simulte()/fetchResult()执行后才可.
外壳宽度(Skin Width):
通俗点说, 就是能两个物体能相互插入多么深….. 因为模拟是以时间步进为单位的, 所以两次步进之间就会产生一个跳变, 这种互相越界的现象不可避免. 于是乎引入这么一个量, 用于保证稳定性.
PhysX学习笔记(3): 动力学(2) Actor
Actor
Actor扮演两种角色: 静态对象, 动态刚体(也叫body).
Actor包含shape. Shape之间相交会触发很多行为.
Static actor主要作用是碰撞检测, 所以一般都会赋于对应的shape
Dynamic actor可能只表示一个抽象的连接点, 所以不需要对应一个shape
创建actor:
注意: 一些actor相关的资源在simulate()执行之前不会释放.
Actor的Shape:
创建:
[cpp] view plain copy
- actorDesc.shapes.pushBack(&shapeDesc);// 1st way
- 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自动计算的(当然也可以手动设置), 作为物体的旋转中心.
通常这样获得渲染所需要的变换矩阵:
注意: 设置朝向时使用四元数与矩阵没有性能差异.
刚体(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的下列方法:
NxForceMode默认是NX_FORCE(简单的受力), 还有NX_IMPULSE(冲力)和NX_VELOCITY_CHANGE(忽略惯性, 直接改变速度).[cpp] view plain copy
- void addForceAtPos(const NxVec3 & force, const NxVec3 & pos, NxForceMode);
- void addForceAtLocalPos(const NxVec3 & force, const NxrVec3 & pos, NxForceMode);
- void addLocalForceAtPos(const NxVec3 & force, const NxVec3 & pos, NxForceMode);
- void addLocalForceAtLocalPos(const NxrVec3& force, const NxVec3& pos, NxForceMode);
- void addForce(const NxVec3 &, NxForceMode);
- void addLocalForce(const NxVec3 &, NxForceMode);
- void addTorque(const NxVec3 &, NxForceMode);
- void addLocalTorque(const NxVec3 &, NxForceMode);
重力:
对于不需要重力控制的dynamic actor可以设置NxActor::raiseBodyFlag(NX_BF_DISABLE_GRAVITY).
设置速度:
不知道质量却需要与之相关的速度可以直接设置动量(momentum).
注意: 不要让设置的速度超出float的上限, 不然会产生错误![cpp] view plain copy
- void setLinearVelocity(const NxVec3 &);
- void setAngularVelocity(const NxVec3 &);
- void setLinearMomentum(const NxVec3 &);
- void setAngularMomentum(const NxVec3 &);
睡眠(Sleep):
睡眠后的物体不参与物理模拟, 直到有一个外部力作用于它.
睡眠判定:
l 简单睡眠: 速度低于NX_SLEEP_INTERVAL
l 平均速度: 比较适合震动体, 设置NX_BF_FILTER_SLEEP_VEL标记开启
l 基于动能: 这是默认的, 设置NX_BF_ENERGY_SLEEP_TEST标记开启
控制睡眠状态:
更改一些参数也会影响它, 如全局重力.
通过派生NxUserNotify可以实现睡眠状态改变时的事件处理回调.
活跃变换通知:
有大量交互对象时遍历取得变换信息显然不可取. 那么可以只取得活跃的(上一次模拟步进的结果).
开启:
[cpp] view plain copy
- sceneDesc.flags |= NX_SF_ENABLE_ACTIVETRANSFORMS;
获取:
[cpp] view plain copy
- NxActiveTransform *NxScene::getActiveTransforms(NxU32 &nbActiveTransforms);
- struct NxActiveTransform
- {
- NxActor* actor;
- void* userData;
- NxMat34 actor2World;
- };
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坐标系:
Joint Limit: 相当于关节的活动范围
Breakable Joint: 可以断开的, 由setBreakable控制. 断开时会响应onJointBreak()
Joint类型:
球形关节: 肩膀, 绳子
卷动关节: 门
棱柱关节: 防震器
圆柱关节: 天线
固定关节: 可打断物体
距离关节: 钟摆, 弹簧
点面关节: 磁铁
点线关节: 窗帘挂环
滑轮关节
6DOF(Degree-of-Freedom)关节: 自定义
弹簧: 不建议使用, 应该用distance joint代替