nVidia的物理系统
PhysX
PhysX(wiki en 中文,physx wiki physx wiki2)是nVidia公司一款跨平台实时物理引擎,可使用硬件(GPU、PPU: Physics Processing Unit, 物理处理器)加速,广泛用于游戏、虚拟现实、工程仿真等领域。
支持刚体(rigid bodies)、软体(soft bodies)、流体(fluids)、面料(cloths)、力场(force fields)等
PhysX 完成基础物理计算:
- 刚体动力学 (Rigid Body)
- 碰撞检测
- 关节和约束
- 软体/布料物理(新版本集成,早期由Apex单独提供)
目前已在github上开源,有3个开源项目:
PhysX3.3(私有库):其中集成了Apex1.3.4
PhysX3.4(公有库):其中集成了Apex1.4,UE4.22-UE4.27集成的是该版本 源代码路径:Engine\Source\ThirdParty\PhysX3 运行时库:Engine\Binaries\ThirdParty\PhysX3
注:UE4集成的PhysX具体版本号在Engine\Source\ThirdParty\PhysX3\PhysX_3.4\release_notes.html
ApexDestruction:Engine\Plugins\Runtime\ApexDestruction
NvCloth:Engine\Source\ThirdParty\PhysX3\NvCloth
Blast:Engine\Plugins\Experimental\BlastPlugin\Source\ThirdParty
PhysX(公有库):最新版本为4.1
UE4可在Build.cs中通过以下设置来控制是否使用PhysX及其相关组件
Target.bCompilePhysX
Target.bCompileAPEX
Target.bCompileNvCloth
== 以PhysX3为例,说明不同版本dll的区别==
PhysX3DEBUG_x64.dll // Debug版本
PhysX3CHECKED_x64.dll // 宏断言版本
PhysX3PROFILE_x64.dll // 带性能数据收集功能版本
PhysX3_x64.dll // Release版本
具体宏详见:
/** PhysX3\PxShared\include\foundation\PxPreprocessor.h */ /* define anything not defined through the command line to 0 */ #ifndef PX_DEBUG #define PX_DEBUG 0 #endif #ifndef PX_CHECKED #define PX_CHECKED 0 #endif #ifndef PX_PROFILE #define PX_PROFILE 0 #endif
UE中WITH_IMMEDIATE_PHYSX宏默认为0,它与 WITH_CHAOS、PHYSICS_INTERFACE_PHYSX 是三选一的物理后端切换宏
在 PhysicsInterfaceDeclaresCore.h 里,开启 Immediate Mode后,所有物理句柄类型全部换成 _ImmediatePhysX 版:
| 类型别名 | WITH_IMMEDIATE_PHYSX=0(默认) | WITH_IMMEDIATE_PHYSX=1 |
|---|---|---|
FPhysScene |
FPhysScene_PhysX |
FPhysScene_ImmediatePhysX |
FPhysicsInterface |
FPhysicsInterface_PhysX |
FPhysicsInterface_ImmediatePhysX |
FPhysicsActorHandle |
FPhysicsActorHandle_PhysX |
FPhysicsActorReference_ImmediatePhysX |
FPhysicsConstraintHandle FPhysicsShapeHandle FPhysicsMaterialHandle FPhysicsAggregateHandle FPhysicsCommand / FPhysicsGeometryCollection |
*_PhysX |
*_ImmediatePhysX |
另外,PhysScene_PhysX.cpp文件被 #if !WITH_CHAOS && !WITH_IMMEDIATE_PHYSX 包起来,开启后整体不编译 注:而这个文件走的是完整的 PxScene::simulate() → fetchResults() 的高层 SDK 流程,包含 broadphase、SAP/MBP、PVD、异步场景、APEX 等一整套。
意味着PhysX 的 Immediate Mode抛弃了 PxScene 高层管线,改用 physx::immediate 低层 API + 自己维护的 SOA(Struct Of Array)数据(PxRigidBodyData、PxSolverBody、Gu::ContactPoint / 自研线性分配器),理论目标是获得零场景开销、可精确控制的 solver。
但当前实现里 StartFrame 的 GenerateContacts / BatchConstraints / PrepareConstraints / SolveAndIntegrate 被 #if 0 屏蔽,且 substep、custom physics、异步场景、APEX、加密、SQ 一大批功能不是空函数就是 check(false)。
所以Immediate Mode在 PhysX 里是一个实验性、未完成的物理后端——启用后能编过、能建 Actor/加力,但真正的模拟推进并没有被实现,属于给自定义或轻量物理(比如物理动画、局部子解算器)预留的骨架。
如果需要在项目中实际使用,必须自己把 #if 0 段落里的 ConstructSolverBodies / GenerateContacts / BatchConstraints / PrepareConstraints / SolveAndIntegrate 的实现补齐
UE4 在 ImmediatePhysics 模块(UnrealEngine\Engine\Source\Runtime\Engine\Public\Physics\ImmediatePhysics)实现了这部分逻辑,可以直接作为 PhysScene_ImmediatePhysX 缺失部分的参考蓝本
在 FPhysScene_ImmediatePhysX::StartFrame() 里:
void FPhysScene_ImmediatePhysX::StartFrame() { #if 0 GenerateContacts(); BatchConstraints(); PrepareConstraints(DeltaSeconds); SolveAndIntegrate(DeltaSeconds); #endif }
同样这五个函数在 ImmediatePhysics_PhysX::FSimulation 里全部有完整实现,且被 Simulate_AssumesLocked 正常串起来
void FSimulation::Simulate_AssumesLocked(float DeltaTime, const FVector& Gravity) { DeltaTime = FMath::Min(DeltaTime, 0.033f); // 强制上限30帧 if (DeltaTime > 0) { ++SimCount; ConstructSolverBodies(DeltaTime, Gravity); // 施加外力 + 计算无约束速度 if (bRecreateIterationCache) PrepareIterationCache(); // 打平 shape SOA + 预计算跳过表 GenerateContacts(); // 近场接触点生成(自建 broadphase),没有broadphase树,就是双重循环 + 半径包围球剔除 BatchConstraints(); // 约束批处理 PrepareConstraints(DeltaTime); // 生成求解描述符 SolveAndIntegrate(DeltaTime); // 迭代求解 + 时间积分 Workspace.Reset(); } }
对比 FPhysScene_ImmediatePhysX(头文件私有字段)与 ImmediatePhysics_PhysX::FSimulation:
TArray<FActorHandle*> ActorHandles; TArray<FJointHandle*> JointHandles; TArray<FActor> Actors; TArray<FJoint> Joints; FLinearBlockAllocator Workspace; // 每帧临时内存 TArray<immediate::PxRigidBodyData> RigidBodiesData; // 位姿、速度、质量、阻尼... TArray<PxSolverBodyData> SolverBodiesData; // 求解器专用 TArray<FImmediateKinematicTarget> KinematicTargets; TArray<PxVec3> PendingAcceleration; TArray<Gu::ContactPoint> ContactPoints; struct FShapeSOA { // 全部 shape 打平存 TArray<PxTransform> LocalTMs; TArray<FMaterial> Materials; TArray<const PxGeometry*> Geometries; TArray<float> Bounds; TArray<PxVec3> BoundsOffsets; TArray<int32> OwningActors; #if PERSISTENT_CONTACT_PAIRS TArray<FPersistentContactPairData> ContactPairData; #endif } ShapeSOA; PxSolverBody* SolverBodies; // 每帧从 Workspace 分配 TArray<PxSolverConstraintDesc> OrderedDescriptors; TArray<PxConstraintBatchHeader> BatchHeaders; TArray<D6JointData> JointData; int32 NumSimulatedBodies; // Dynamic 数量 int32 NumActiveSimulatedBodies; // 其中真正激活的 int32 NumKinematicBodies; int32 NumSimulatedShapesWithCollision; int32 NumPositionIterations; // 默认 8 int32 NumVelocityIterations; // 默认 1 TMap<FActorHandle*, TSet<FActorHandle*>> IgnoreCollisionPairTable; TSet<FActorHandle*> IgnoreCollisionActors; bool bRecreateIterationCache; TArray<int32> SkipCollisionCache; // 记录可以跳过的接触遍历序号
| 字段 | PhysScene_ImmediatePhysX | ImmediatePhysics_PhysX::FSimulation |
|---|---|---|
TArray<FActor> Actors |
✅ | ✅ |
TArray<FJoint> Joints |
✅ | ✅ |
TArray<immediate::PxRigidBodyData> RigidBodiesData |
✅ | ✅ |
TArray<PxSolverBodyData> SolverBodiesData |
✅ | ✅ |
TArray<FKinematicTarget> KinematicTargets |
✅ | ✅ |
TArray<PxVec3> PendingAcceleration |
✅ | ✅ |
TArray<Gu::ContactPoint> ContactPoints |
✅ | ✅ |
FShapeSOA |
✅ | ✅ |
PxSolverBody* SolverBodies |
✅ | ✅ |
TArray<PxSolverConstraintDesc> OrderedDescriptors |
✅ | ✅ |
TArray<PxConstraintBatchHeader> BatchHeaders |
✅ | ✅ |
TArray<D6JointData> JointData |
✅ | ✅ |
FLinearBlockAllocator Workspace |
✅ | ✅ |
FCacheAllocator / FConstraintAllocator |
✅ | ✅ |
NumSimulatedBodies / NumActiveSimulatedBodies / NumKinematicBodies / NumPositionIterations / NumVelocityIterations |
✅ | ✅ |
bRecreateIterationCache / SkipCollisionCache |
✅ | ✅ |
但要让 WITH_IMMEDIATE_PHYSX 真正成为可替换 PxScene 的全局后端,除了搬这五个函数,还得补齐 broadphase、场景查询、事件回调、substep、双场景等这些外围管线
然而,Epic 后来选择的路是"直接押注 Chaos",所以 WITH_IMMEDIATE_PHYSX 就永远停在骨架状态
在UE4中ImmediatePhysics 模块现在作为 AnimNode_RigidBody 的骨骼级物理在引擎中被使用而长期存活了下来
它也给AnimNode_RigidBody("RigidBody" 动画蓝图节点,也叫 PhAT 里的物理动画节点,以及 Physical Animation Component 的部分场景) 提供的一套 自建、独立于主 PxScene 的、每骨骼帧同步驱动的物理求解器
注:PhAT 是 Physics Asset Tool(物理资产工具),是 UE 编辑器里用于编辑 UPhysicsAsset 的模块——你可以给骨骼网格(SkeletalMesh)的每根骨骼添加/调整碰撞体(box/sphere/capsule/convex)、配置物理约束(constraint),并实时 "Simulate" 预览物理表现
获取nVidia Gameworks私有github库方法,大致步骤如下:
1. 注册NVIDIA Developer开发者账号(不是有NVIDIA账号就能直接登录的,必须是开发者账号)
2.同意最终用户许可协议(EULA),并在最后把自己的GitHub用户名输入。
3. 在一段时间后,会收到github上NvidiaGameWorksAdmin拉你入NVIDIAGameWorks组的邮件。
4. 加入NVIDIAGameWorks后,会收到NVIDIA GameWorks用github邮箱发的邮件,告诉你已经把你拉入GameWorks_EULA_Access Team,并被赋予“Pull”权限。
5. 访问https://github.com/NVIDIAGameWorks,这个时候就能看见NvCloth、Blast、Flex、Flow等私有库。
① UE3中Pawn行走时的碰撞检测、重力、武器射击、流体(FluidSurfaceActor)的模拟是自己实现的
② 人物死亡,调用SetPawnRBChannels(TRUE)开启布娃娃系统(ragdoll),并且将SetPhysics(PHYS_RigidBody),则会使用Pawn的PhysicsAsset数据进行PhysX物理模拟
③ 载具使用是PhysX物理模拟 (udn 设置载具 载具系统技术指南)
④ 从RigidBodyBase派生的Actor(如:RB_ConstraintActor、RB_PrismaticActor)开启模拟后,会进行PhysX物理模拟
⑤ 破坏(FracturedStaticMesh)、软体会使用PhysX进行物理模拟

Apex
Apex(physx wiki)在PhysX之上开发一套跨平台SDK,用于制作和运行复杂的物理数据(如带破坏模型、面料等)
Apex 不是独立的物理引擎,而是 PhysX 之上的 “物理内容中间层库”
Apex 重点在于做动画和特效解决方案,比如:
- 布料模拟(Apex Clothing)
- 破碎/瓦砾/毁坏模拟(Apex Destruction)
- 粒子/流体效应(Apex Particles)
- 毛发效果(Apex Turbulence)
这些模块利用 PhysX 提供的底层动力学和碰撞,但封装成易用的特效 API。
Apex 里所有物理相关的计算、碰撞、刚体约束最终都“委托”给 PhysX 完成。比如 Apex Clothing(布料)用的是 PhysX Cloth 底层算法;Apex Destruction 用的是 PhysX 的物体拆分、碰撞响应。
结构图示例:
应用/Game引擎 ↓ Apex (Clothing、Destruction...) ↓ PhysX (Rigid/Soft/Cloth collision, Dynamics, etc.) ↓ CPU/GPU(硬件加速,不同端实现)
Apex1.3.4(随PhysX3.3)和Apex1.4(随PhysX3.4)已开源,具体文档详见:NVIDIA(R) APEX(TM) SDK Documentation
1.4版本之后(PhysX 4.x 后),nVidia放弃了Apex,并发布了一些新开源项目NvCloth、Blast、Flow(私有库)来替换Apex中各个组件
Apex的发布记录:NVIDIA(R) APEX(TM) SDK Release Notes
Apex的架构如下:

注1:Authoring为制作物理资源的组件集合,Run-time为运行物理资源的组件集合
注2:绿色部分为nVidia提供的物理组件工具集
Apex包括如下组件模块:
APEX Clothing(面料) --> NvCloth(docs 私有库 github)
APEX Destruction(破碎与破坏,Fracture and Destruction) --> Blast(api docs authoring docs 私有库 github) ue的Blast插件代码(私有库):https://github.com/NvPhysX/UnrealEngine/tree/4.20.3-Blast_1.1.4
APEX Particles(粒子) --> Flow(docs 私有库 github) ue的Flow插件代码(私有库):https://github.com/NvPhysX/UnrealEngine/tree/NvFlow-4.19
APEX Turbulence(湍流)
APEX ForceField(力场)
APEX Vegetation (植被 开发已暂停)
在UE3中使用Apex
布料:APEX Clothing in UE3(udn en 中文)
破坏:APEX Destruction in UE3(udn en 中文)
从UE4.16起,APEX Cloth 已被 NVIDIA的NvCloth解算器取代,求解基于 Position Based Dynamics,逐粒子而非刚体。这是一个轻巧的服装布料解算器,负责运行布料服装的模拟
NvCloth使用碰撞球 / 胶囊 / 凸平面做碰撞体,不与场景刚体自动碰撞。这也意味着布料不参与刚体的 broad phase,开发者必须把角色的骨骼胶囊、场景碰撞体手动喂给 cloth 的 collision 数据。这是布料"穿模"最常见的原因。
该服装布料模拟器集成轻巧且非常可扩展,因为我们现在可以直接访问此数据。而APEX Clothing是一个复杂的SDK,可以一站式地进行服装模拟,同时处理模拟和渲染
Android、iOS等移动平台默认就不编译Apex
在PC windows平台,如果不需要Apex中的功能(如破坏、粒子、毛发等),可以将Apex不进行编译
; BaseEngine.ini [/Script/BuildSettings.BuildSettings] bCompileAPEX = false;
FleX
FleX(physx wiki)是GPU加速基于粒子模型(paticle)的物理模拟库,其源码也在Github上开源(私有库)
支持刚体(rigid bodies)、变形体(deformable bodies)、软体(soft bodies)、流体(fluids)、面料(cloths)、气体(gases)等
FleX Documentation
FleX UE4 Plugin Documentation ue4的FleX插件代码(私有库):https://github.com/NvPhysX/UnrealEngine/tree/FleX-4.19.2
相关youtube视频:
Introduction on how to use Nvidia Flex in UE 4
Flex tutorial 1 Rigids, cloth and softbodies
Flex tutorial 4 - How to change container values ingame
Flex tutorial 5 - Overlap events with Flex
PhysX资料和相关软件
nVidia Gameworks documentation simulation中列出了所有物理相关的SDK组件
GameWorks PhysX Overview中介绍了最新的PhysX及基于PhysX的组件
nVidia Gameworks Download Center中提供了PhysX相关的软件下载(需要登录nVidia开发者账号),如下为PhysX SDK3.4.0的下载内容:


3D Studio Max DCC plug-in for PhysX:PhysX的3Ds Max插件
Maya DCC plug-in for PhysX :PhysX的Maya插件
注:① DCC为Digital Content Creation简称 ② DCC plug-in for PhysX
PhysX Visual Debugger(PVD):PhysX的可视化调试软件。通过与被调试的PhysX程序建立连接,实时地将其物理元素可视化到PVD中
PhysX Lab:为APEX Destruction(破坏)和APEX Particles(粒子)制作数据的工具

参考
浙公网安备 33010602011771号