E6:原生扩展、GPU 与能力边界#
Sim Atlas 学习首页 · 完整路线 · 源码地图 · 本章验收
先修:E1 对象/COM/时间、E2 驱动、E3 接触与求解;GPU 所有权和同步可先看 E5。本章完成 B6 的原生扩展/后端边界与 B7 综合追踪,也补充 B0/B4 的非刚体状态和数值语义。
固定基线仍是 ovphysx-0.6.3、提交 da950a3537927784951853c66618036f332ca0ce、SDK 头文件 5.11.0。以下结论来自公开源码和契约,不是运行验收。没有构建、链接或执行 SDK,没有 CUDA 编译/JIT、仿真、渲染、训练或基准。历史 Isaac Sim 5.1 / UniSim 1.7.10 所用核心 binary/config 仍须由 DexLab #126 的原批次证据确定,不能用本章默认值补齐。
1. “扩展 PhysX”具体扩展哪一层#
需求 |
原生入口/实现位置 |
扩展者承担的责任 |
|---|---|---|
增加关节或自定义运动关系 |
|
用原生一维行描述几何误差和速度关系;管理数据块、COM/origin 变化和 release |
增加碰撞几何 |
|
bounds、接触、query、质量属性和缓存一致;不能只返回一个视觉 mesh |
修改已有接触 |
|
在允许的线程/阶段改 contact set;不能添加任意数量的接触,也不是替换整个求解器 |
GPU 数据/额外计算 |
|
设备指针、容量、事件和阶段;回调中的自定义 CUDA 工作属于应用 |
使用已提供的扩展 |
Character Controller、Vehicle components、Immediate Mode |
按该扩展的状态/更新契约组织程序,不把它们混成一个通用机器人 API |
改算法本身 |
修改公开 C++/CUDA 实现并维护自己的 build |
接口/数值/版本责任转移到该派生实现;公开源码不等于运行时可注册任意 GPU solver 插件 |
createConstraint 接收两 actor、connector、shader table 和数据块大小;这里的 shader 是约束行准备函数,不是图像 shader。Character Controller 的 move 是 collide-and-slide 位移接口,底层使用 kinematic actor,不能据此声称它是有执行器动力学的人形机器人。Vehicle 的 PxVehicleComponentSequence 支持组件与 substep group;该局部更新次数不自动等于 Scene 的物理步数。
Immediate Mode 公开构造 solver bodies、生成 contacts、batch/求解约束及积分函数。这让调用者显式组织数据与阶段,同时也把 contact cache/allocator 生命周期、对象索引及一致步长的责任交给调用者;不是一行替换 simulate 就能得到完整 Scene 服务。本章读这些原生接缝,不另建统一 wrapper。
2. 自定义几何:碰撞、查询、质量必须一致#
2.1 回调是共享对象引用,不是拥有数据的网格#
PxCustomGeometry 仅保存 Callbacks*;复制 geometry 也只是复制该指针,isValid() 只检查类型和非空指针。它既不证明几何算法正确,也不延长回调对象生命周期。应用应保证回调及其依赖数据晚于所有使用它的 shapes/queries 释放;不要把栈上 callback 的地址留在长期 shape 内。
回调 |
输入/输出契约 |
常见误用 |
|---|---|---|
|
用官方宏产生应用侧 type ID;SDK 不用它替换 dispatch 类型 |
把运行时 ID 当跨进程资产 ID |
|
geometry 局部坐标 AABB |
返回 world AABB;或小于实际碰撞支持集,造成 broad phase 漏检 |
|
两 geometry/world poses、contactDistance、margin、toleranceLength → |
只实现相交测试,没有一致的法向/分离量/接触点 |
|
单位方向、最大距离、hit flags、maxHits、stride |
连续紧密写 |
|
本几何与另一几何;sweep 中移动的是 |
几何对和运动方向写反 |
|
动态使用时提供局部质量、COM、惯量 |
可碰撞即假定质量正确;忽略密度或几何 margin |
|
调试图元;PCM 是否可复用及失效阈值 |
把 debug 画面当 renderer;几何变了却继续复用旧接触 |
逐字段见 Callbacks 声明。即使 visualize 注释写 optional,它在基类仍是纯虚函数,可提供空实现,而不是省掉所有 override。查询与碰撞可能由不同调用线程使用同一 callback;本章建议数据在一个模拟/查询阶段内保持只读、临时量放栈上,应用自行同步形状修改。其依据是指针共享以及 E4/E5 的并发调用边界,而非声称 SDK 会替应用加锁。
2.2 用 cylinder 读懂 support、margin 与惯量#
官方 PxCustomGeometryExt::CylinderCallbacks 给出现成实现,axis 的 0/1/2 分别为局部 X/Y/Z,height 是全高。对局部 X 轴、无 margin 的圆柱,支持点可写为:
假设方向非零;纯轴向需要单独处理,不能除以零。源码 supportLocal 包含这个分支,并将 bounds 按 margin 扩张。对密度为 \(\rho\) 的实心圆柱:
长度量纲为 \(L\)、密度 \(ML^{-3}\)、惯量 \(ML^2\)。原生质量构造约定是密度 1,质量/惯量随密度线性缩放。computeMassProperties 的 margin=0 分支正是上述圆柱式;margin 非零转入分片计算,不能继续套裸圆柱惯量后称为同一几何。
这个例子展示扩展协议,不表示新版只有 custom geometry 才能表达圆柱:PxConvexCore 已定义 point/segment/box/ellipsoid/cylinder/cone。原生 convex core 和虚函数 custom geometry 是不同 dispatch 身份,需分别核对支持矩阵。
2.3 PCM 与 GPU 回退#
GuPCMContactCustomGeometry 先判断 PCM 缓存是否失效;有效时可复用 manifold,不保证每步调用 generateContacts。交换 geometry 顺序后还会翻转输出法向。修改 callback 内部参数时,不能假定 SDK 自动知道所有 shape/query/contact cache 已过期;在安全阶段更新原生 shape 几何并处理质量/查询更新,具体变化需按使用路径验证。
GPU Scene 也不会把 C++ 虚函数自动编译成 CUDA。固定源码的 sphere/custom 等 pair 被送往 eFallback,GPU dispatcher 将其交给 CPU fallback context。cloth/custom 的分支还明确写有过滤限制;因此刚体 pair 能回退不等于 deformable/particle 与任意 custom geometry 都支持碰撞。
3. 自定义约束:把关系写成一维行#
3.1 行的物理含义与单位#
原生 Px1DConstraint 把两个刚体的世界坐标速度组合为:
注意后两个分量的负号由 SDK 定义;不能在 linear1/angular1 再额外取负,除非你的几何约束本身如此。对一个 world 单位轴 \(\mathbf n\) 上的点间关系,\(\mathbf l_i=\mathbf n\)、\(\mathbf a_i=\mathbf r_i\times\mathbf n\),\(\mathbf r_i\) 从该 body COM 指向 attachment。这样 \(v_c\) 是 \(L/T\),角 Jacobian 分量有长度量纲,不能把“angular 字段”一律理解为无量纲旋转轴。
硬约束的位置阶段以几何误差 \(g\)、target \(v_t\) 表达 \(J\mathbf u+\beta g/h-v_t=0\);\(\beta\) 是内部稳定化系数。velocity 阶段通常移除 bias,eKEEPBIAS 有例外。spring 则定义隐式力或加速度:
线性 force spring 中 \(f\) 为力,\(k\) 是 \(M/T^2\)(SI: N/m),\(c\) 是 \(M/T\)(N·s/m);acceleration spring 的 \(k,c\) 分别为 \(T^{-2},T^{-1}\)。纯旋转 force row 的输出改为力矩,刚度相应为 N·m/rad。公式以一致的单位制、固定行方向和本步线性化为前提,不能据“隐式”二字保证任意刚度、步长和接触切换稳定。
字段/标志 |
作用 |
必须留意 |
|---|---|---|
|
本行位置误差/速度目标 |
线性和角向行的量纲不同;target 不是求解后的速度 |
|
允许的累计行冲量区间 |
默认按冲量;force-limit 转换有两重条件 |
|
spring 模型/质量归一化加速度模型 |
acceleration 位仅对 spring 有效;与 restitution 模型区分 |
|
此行参与 constraint 总输出和断裂判断 |
未设时仍可参与求解,但不进入该报告 |
|
类型与预处理提示 |
不保证行一定保留;退化响应和预处理仍影响结果 |
|
此 constraint 的逆质量/逆惯量缩放 |
不是修改 body 实际质量;会影响观测的物理解释 |
原生标志见 row flags。一个值得实际追源码的冲突:该文件 eHAS_DRIVE_LIMIT 短注释写的 unless 与执行条件相反;共享 CPU/GPU helper 实际是 hasDriveLimit 和 driveLimitsAreForces 都为真时乘 simDt,否则原值当 impulse。eDRIVE_LIMITS_ARE_FORCES 在当前公开 flags 已标 deprecated,本文按固定实现讲解,既不删掉历史分支,也不把未来行为当现在行为。
3.2 从接口实现到生命周期#
应用定义可按字节复制的 constant block,保存参数和 body-local attachment frames;不要在 shader 中追踪随时可变的外部状态。
实现
PxConstraintConnector,向 SDK 返回prepareData()和 shader/constant 指针;修改数据后markDirty()。SDK 会在步开始复制数据块,不是每行执行时重新调用应用的 setter。实现
PxConstraintSolverPrep:只访问传入参数,返回不超过maxConstraints的行数,并完整填写所用行、inverse-mass scales、anchor 输出和bodyAWorldOffset。该函数必须可重入。输入 transform 是 COM frame;static/null actor 对应 identity,应用的数据需正确承担 world anchoring。用
PxConstraintShaderTable和createConstraint接入。actor-local frames 与 COM-local frames 是不同层;COM 变化需要onComShift,world origin shift 可能也需改数据并重新标 dirty。释放应从
PxConstraint::release()进入,等onConstraintRelease回调再释放 connector 资源。serialization、debug/PVD 和 owner ID 各有自己的 hook,并非创建成功就自动完成应用资产序列化。
本章原创 C++ row-prep 片段 描述一个固定 world 轴、双 attachment、对称冲量限幅的双向弹簧。它完整实现一个原生 solver-prep 签名,且把 force spring 和 raw impulse cap 分开。没有 main、connector 或资源创建;它是行构造阅读片段,不是可加载的完整插件。语法/类型检查见验收记录,还没有验证约束实际收敛、受力或 GPU 行为。
3.3 CPU / GPU / Direct GPU 不是同一扩展契约#
一般 Scene 的公开 custom constraint 路径允许 CPU row preparation;GPU dynamics 还有自己的数据准备和受支持关节路径。不能凭 shader table 含一个函数指针,就推断 CPU callback 可在 GPU 执行。
eGPU_COMPATIBLE 是内部位,公开 setter 明确拒绝;Direct GPU Scene 的 constraint 加入逻辑 拒绝非兼容项并建议 D6。固定源码 D6 的官方 shader table 有该位,而 DistanceJoint 没有。学习下一节 CPU DistanceJoint 路径不等于它可直接迁移到 Direct GPU;更不能伪设内部位绕过真实数据布局要求。
4. B7 综合追踪:一个距离弹簧怎样产生报告力#
选择原生 DistanceJoint、两个普通刚体、CPU PGS、非退化 attachment 距离,不包含 articulation 的 extended response、不含 inverse-mass scaling、不把接触混入关节报告。TGS 和 GPU 分支另列,避免拼成一条不存在的执行链。
4.1 配置与数据块#
PxDistanceJointCreate 检查 frames 和 actors,经 createJointT 创建 extension 对象,再调用 physics.createConstraint(..., sizeof(DataType))。setMinDistance/setMaxDistance/setStiffness/setDamping/setDistanceJointFlags 写入数据并 markDirty。ExtJoint::prepareData() 返回 mData,随后进入上一节的 SDK 复制路径。
设置相等 min/max 且同时启用两限位才能表达定距目标;只开 max 是单边“绳长上限”。默认只开 max、tolerance 为 0.025 * scale.length,stiffness/damping 为 0;不能以默认 joint 宣称已启用弹簧。默认初始化
4.2 几何到行#
DistanceJointSolverPrep 从两个 world joint frame 得到 \(d=\|\mathbf p_A-\mathbf p_B\|\)、\(\mathbf n=(\mathbf p_A-\mathbf p_B)/d\)。当 d 很小时采用固定 X 轴,这只是确定一个数值方向,不是证明重合 attachment 的距离梯度唯一。相等上下限的几何误差为:
\(\epsilon\) 是 joint tolerance,量纲 \(L\),它是几何死区,不是“求解残差小于 epsilon 就停止”。只开 min 时 minImpulse=0;只开 max 时 maxImpulse=0,符号与 \(\mathbf n\) 一起决定拉/推;两限位不相等时 shader 生成两行,因为此时没有速度用于预先判断哪边即将激活。行填充及单边区间
ConstraintHelper 当前以 joint B 点作为两侧力臂的共同参考点;对距离行,因为 \(\mathbf p_A-\mathbf p_B\) 平行 \(\mathbf n\),用 A/B 点算 body A 的 \(\mathbf r\times\mathbf n\) 等价。具体 frame/offset 实现 解释了为什么不能只看变量名推测 torque 的参考点。
4.3 行准备、隐式系数与迭代#
CPU PGS 的 DyDynamics 取 constant block、COM poses、writeback pool,并尝试四约束批处理;失败/不适用时逐项调用 SetupSolverConstraint。因此下面的标量链是该 fallback 准备/求解路径的解释,不声称所有 joint 每次都绕过 SIMD。
row prep → 预处理/惯性转换 → unit response \(w=JM^{-1}J^T\) → solver constants。对本节的线性 force spring,令 \(h\) 是 Scene step,\(v_t\) 为 target、\(g\) 为行误差:
对应 PGS compute1dConstraintSolverConstantsPGS 先产生 constant=xb、velMultiplier=-xa、impulseMultiplier=1-x,随后加上初始速度 bias,使最终 constant=xb-xa*v_pre。\(w\) 对该线性行是 \(M^{-1}\),\(a\) 是 \(M\)、\(b\) 是冲量 \(ML/T\),所以 \(aw\) 无量纲;若切到 acceleration spring,源码会引入 recipUnitResponse,不能沿用上述刚度单位。
solve1D 计算累计候选冲量并投影到上下限:
这里将 \(v_c=v_{pre}+\Delta v_c\) 写成当前总行速度:原生 normalVel 是 solver 累计的速度增量,初始项已进入 constant,不能重复加减。该式限定为前述普通刚体 force-spring 行;不能当任意离线 state 的通用一步公式。solver 内部 angular state 采用惯性平方根变换,源码注释称 momocity。内部变量 appliedForce 实际累积的是冲量。位置/速度迭代上限和积分顺序接 E3,不是在这里额外添加一个 epsilon 收敛检测。
4.4 writeback 到原生 getter#
writeBack1D 只求和带 eOUTPUT_FORCE 的行,先得 body 0 的线/角冲量,再把角冲量从 COM 平移至 body0WorldOffset 对应点:
世界坐标分量分别为 \(ML/T\)、\(ML^2/T\),除以 step 后是 N 和 N·m(SI)。Sc::ConstraintSim::getForce 用 Scene 的 oneOverDt 转换;NpConstraint::getForce 检查读取阶段再进入 core。推荐在成功 fetchResults 后采样,不把 getter 调用时间误写成新的物理时刻。
断裂阈值也先乘 simDt 成冲量,再比较线/角冲量范数。报告只覆盖被标记的 constraint 行;未启用输出、休眠/未激活、退化行、断裂或未在 Scene 等状态必须另外解释。它不是 actor 所有接触/重力/驱动总 wrench,也不是 E4 的 articulation incoming joint force。
TGS 使用 DyTGSDynamics 和 TGS 行系数,含 stepDt、位置增量及不同 bias 更新;不能把 PGS 的 h 原样套到所有 TGS 内部变量。GPU 是下一节的独立调度/布局,CPU trace 不构成 GPU 数值等价或性能结论。
5. GPU 后端:公开了什么,仍需什么#
固定树公开 GPU 代码。说“PhysX GPU 后端一概闭源”不符合本章版本;反过来,文件存在也不代表本机已安装匹配 GPU library、driver 或测试过全部 pair。
层次 |
固定源码证据 |
不能推出的结论 |
|---|---|---|
Scene/backend 选择 |
|
GPU broad phase = GPU dynamics = Direct GPU 三者等价 |
GPU solver 选择 |
|
所有宿主固定使用 TGS;当前设置能填历史批次 |
刚体/约束内核 |
|
与 CPU bitwise 相等或任意 custom shader 支持 Direct GPU |
articulation |
所有 CPU cache/getter 在 Direct GPU 下仍有效,详见 E5 |
|
FEM 与粒子 |
本章第 6–7 节的公开 CUDA 实现 |
图像、RL、autograd、任意多物理模型自动具备 |
构建/装载 |
|
仅有 C++ 头文件即已构建或运行 GPU;驱动实现属于本仓源码 |
“GPU scene”仍可能包含 CPU 工作。registerContactManager 要求 PCM、无 contact modification、离散检测等条件才查 GPU pair table;其余走 fallback。故 contact modification 开关、cooking 是否生成相应数据、mesh/geometry 类型与 pair 支持都会改变执行路径。同步、GPU index、首步初始化、device events、scene-wide padded stride 的细节仍按 E5 执行,不能只记录一个 device=cuda 字符串。
**公开范围与外部范围分开记:**上表的 SDK CPU/CUDA 与扩展实现在固定官方树内可读;CUDA driver/toolchain、目标机器实际加载的 binary、宿主 importer/renderer/RL 版本和用户自定义插件不由这些文件证明。本章没有为整个仓库全部 GPU 内核作形式正确性审计,没有下载或执行任何 GPU 二进制。
6. Deformable volume / surface:不是换一个刚体 shape#
6.1 对象、拓扑和状态#
PxDeformableVolume 与 PxDeformableSurface 明确仅支持 GPU,要求 GPU dynamics 和 GPU broad phase。它们继承 PxDeformableBody,不使用 rigid body 的单一 pose、COM 和 6D 速度来完整表示形变。
对象/数据 |
原生意义 |
容量、所有权和更新时间 |
|---|---|---|
volume collision mesh |
接触几何的四面体网格; |
collision vertex count;attachShape 分配、detachShape 释放 |
volume simulation mesh |
形变求解自由度; |
simulation vertex count;与 collision count 可不同,不能混索引 |
surface mesh |
三角形顶点的位置/速度/rest 数据 |
三角 mesh vertex count;由 shape 生命周期约束 |
per-vertex |
xyz 位置/速度,位置 w 为 inverse mass,速度 w 未使用 |
device 地址;每顶点 16B 对齐,不是 CPU 可直接解引用数组 |
应用修改 |
volume |
dirty 只通知引擎,不替应用拷贝数据、等待 CUDA 或构造有效初态 |
Volume 完整 buffer 契约 和 surface 契约 明确:从 simulate 开始到 fetchResults 返回不得写;读取必须等 PhysX tasks 完成,文档特别允许 completion task 读。需要在 GPU 合法时间读取并完成 D→H 拷贝,CPU 才有自己的快照。markDirty 不能消除这些同步条件。固定 NpScene 还检查 shape/simulation mesh 前置条件,不能把空 actor 成功分配当“软体创建完成”。
6.2 材料、FEM 与数值分支#
PxDeformableMaterial 提供 Young's modulus \(E\)、Poisson ratio \(\nu\)、dynamic friction、elasticity damping;volume 另有 eCO_ROTATIONAL / eNEO_HOOKEAN。这里 E 量纲为压力 \(ML^{-1}T^{-2}\)(Pa),不是刚体 contact stiffness 的 N/m;\(\nu\) 无量纲。质量通过网格顶点 inverse mass 参与求解,不能用一个外观材质替代力学参数。
对各向同性材料、\(E>0\) 且 \(0\le\nu<0.5\),源码 Lamé 参数 为:
不要把 \(\lambda_L\) 和约束乘子同名混用。公开 API 允许 \(\nu=0.5\),但上式在端点奇异;实际 kernel 的体积项有单独分支,不能由连续公式替实现做除零。
以 softBodyGM.cu 的 co-rotational 分支 为例,rest 边矩阵 \(D_m\) 和变形后边矩阵 \(D_s\) 给出无量纲 \(F=D_sD_m^{-1}\),tet rest volume \(V\),rotation R。该路径先处理 ARAP 形变项,再处理 \(\det(F)-1\) 体积项;ARAP 代码 在范数中还加了数值 epsilon。不能将它描述为“每步一次精确解线性 FEM”,也不能把 neo-Hookean 路径的含义直接替成此分支。
在无阻尼、单个无量纲约束 C、未触发 abs(denom) < 1e-15 保护的分母条件下,对应更新 是:
\(w_i=1/m_i\);ARAP 分支 \(\tilde\alpha=1/(2\mu Vh^2)\)。因此 \(\tilde\alpha\) 和分母量纲均为 \(M^{-1}L^{-2}\),\(\ell\) 为 \(ML^2\),\(\Delta x\) 为长度。这里的乘子不是刚体行冲量,不可直接除以 h 叫作 Newton。带阻尼分支会改变分母和分子;TGS/non-TGS 对 multiplier 初始化/复用也不同,见上述具体行。表面上都出现“迭代”,不意味着其迭代和 E3 刚体行求解可等量比较。
surface 有厚度、弯曲刚度/阻尼的材料接口。FEMClothUtil 使用 area * thickness 构造体积尺度并解膜/面积项;FEMCloth.cu 将位置修正按 delta / dt 写入速度,另有 triangle-pair bending 路径。厚度是 \(L\),不能把它当接触 offset;弯曲/阻尼数值也不能未经该模型的实现/单位转换就照抄材料手册或其他引擎。本章不为这些值提供未验证的实物标定配方。
6.3 耦合、attachment 与 callback#
PxDeformableAttachmentData 要求至少一方是 deformable:surface 使用 vertex/triangle,volume 使用 simulation mesh vertex/tetrahedron,rigid 使用局部笛卡尔点,world 使用世界点;元素内位置由重心坐标表示。对 tetrahedron 内点 \(\mathbf p=\sum_{i=0}^3b_i\mathbf x_i\),\(\sum b_i=1\),位于元素内部时 \(b_i\ge0\),b 无量纲。拓扑创建后固定,变更 attachment 点需重建;rigid/world pose 可更新。这与“每步把所有顶点强行写到目标”是不同约束。
公开 cloth-rigid contact prep 使用接触位置、重心信息、刚体/顶点响应准备耦合约束。原生存在这些特定耦合,不等于支持任意几何 pair、断裂、热传导、电磁、流固材料模型或工程认证精度;每一种额外物理都要明确方程、耦合接口、实现者和验证范围。
Scene 的 PxPostSolveCallback::onPostSolve(CUevent) 只给出 solver 完成事件;用户 stream 应等待它后才读结果。它不意味着 CPU 已同步,也不承诺引擎自动等待你另一个 stream 后续任意写入;应用需在下一次引擎访问前建立正确依赖。注册入口见deformable callbacks。
7. PBD 粒子:phase、邻域和数据协议#
PxPBDParticleSystem 提供位置迭代和速度迭代;源码 NpScene::addParticleSystem 限制 GPU scene。接口概述列举多种粒子用途,但本章只把读到的 granular/fluid buffer、phase 和密度/接触路径作为具体证据,不从概述词汇推断所有布料/充气体对象或功能都已实现、验收。PxPBDMaterial 的 lift/drag 注释 还明确将 particle-cloth、particle-rigids、attachments、volumes 标为 deprecated;这不能混同本章独立的 FEM surface/volume,也不等于禁用流体粒子与普通刚体的接触。
PxParticleBuffer 与 Scene/particle system 分离,在步间可添加/移除/转移;位置和 inverse mass 是 PxVec4(x,y,z,1/m),速度是 PxVec4(vx,vy,vz,0),phase 为每粒子 PxU32。active count 不超过创建时 capacity;getFlatListStartIndex() 只有加入 system 且至少 simulate 一次后才有效。buffer 内部设备地址不能直接当 NumPy/CPU 指针,释放会回收其内存。
createPhase(material, flags) 将材料与 group/behavior 编码结合;PxParticlePhaseFlag 区分同组自碰撞、基于 rest pose 的邻近过滤、fluid 密度约束。它不是刚体 PxFilterData.word0 的 env_id;同 scene 的多环境粒子隔离不能机械照搬 E5 rigid shape shader。修改位置/速度/phase 后按 PxParticleBufferFlag raise dirty flags,并履行复制和同步协议。
五个长度参数要拆开:rigid/deformable restOffset、contactOffset、particleContactOffset、solidRestOffset,以及 fluidRestOffset。粒子–刚体的静止距离涉及两边 restOffset 之和;两 solid 或 solid/fluid 静止间距是 2 * solidRestOffset;两 fluid 是 2 * fluidRestOffset。particleContactOffset 决定邻域接触尺度,必须大于后两者,不能把它叫作唯一的“粒径”。
密度求解也不是名字相同就等于通用 SPH Navier–Stokes 离散。固定 particlesystem.cu 在邻域里以内部 kernel/尺度累积 rho,片段里的 mass 明确设为 1,再将:
存入名为 mDensity 的工作数组。此式描述内部归一化/缩放后的约束值;该数组不是无需转换即可导出的 kg/m³ 测量。后续 ps_solveDensityLaunch 消费这些工作量,另有 contact、viscosity、surface tension、velocity 路径。PBD 材料接口的cohesion/viscosity/surface tension 等参数 必须按实现尺度解释,不能把它们一律当 SI 连续介质系数。
PxParticleSystemCallback 的 onBegin/onAdvance/onPostSolve 接收 mirrored pointers 与 CUstream;“host/device mirror”只是调用者应该满足的关系,类型本身不保证同步。按所给 stream 排序工作;fetchResultsParticleSystem 才是相关 particle data copies 的同步入口,callback 文档也将其作为完成保证。自建其他 stream 的依赖仍由应用承担。callback 不应在 simulation 正在执行时更换,setter 注释 明确这些调用会被忽略。
8. 回调、可微与宿主:能力归属的最后一层#
8.1 回调阶段不能互换#
接缝 |
能做什么 |
不应该由它承担什么 |
|---|---|---|
simulation filter shader / callback |
按 pair/属性筛选及请求 flags,见 E3/E5 |
任意读写正在推进的 scene;假定 query filter 一并生效 |
custom geometry callbacks |
在 narrow phase/query 定义几何答案 |
修改 Scene 或依赖一份无锁可变全局临时缓存 |
constraint solver-prep |
由传入数据生成约束行,需可重入 |
直接积分 body、调用控制器副作用或替换后续所有 solver 阶段 |
contact modify |
改现有接触点属性或 ignore |
添加新 contact 数量、当最终力报告或常规 update loop |
simulation event / contact report |
取回事件与报告,见 E3/E4 |
把某次 callback 当独立物理步或完整传感器 |
particle / deformable GPU callback |
在提供的 stream/event 契约上排自定义 GPU 工作 |
宣称 CPU 可直接读 D 指针;把排队完成当执行完成 |
Contact modify 契约 要求线程安全/必要时可重入、pair 开 eMODIFY_CONTACTS、actor 保持 awake;仅移除 callback 并不能清除 pair flag 对性能路径的影响。普通 modification 与 CCD 的 独立接口 也不可混为一谈。PxContactSet 暴露 point/normal/target velocity/impulse cap 等修改入口,这些是模型干预,不是测得同名物理量。
8.2 Jacobian、GPU array 和 autograd 是三个概念#
E2/E5 的 articulation Jacobian 解决速度映射、惯性矩阵和逆动力学等具体问题;本章的 \(\nabla C\) 是内部约束空间导数。二者都不自动构成可训练 rollout 的反向接口。端到端可微仿真需定义:
以及接触拓扑变化、clamp/限幅、休眠、迭代截断、缓存历史和非光滑点的导数约定。公开 PxArticulationReducedCoordinate、PxDirectGPUAPI 与本章 constraint/deformable/particle contracts 没有为上述完整 Scene step 提供通用 tape/backward 契约。本章结论限定为这些已核对的原生接口不能据此宣称端到端 autograd 支持;不把负面结论扩大成“外部研究或派生实现永远不能求梯度”。
CUDA 内核源码可读、zero-copy/interoperability 或把数组交给 PyTorch/Warp,都不会自动为 PhysX step 注册梯度。若另写有限差分、可微代理或 custom backward,应记录它自己的方程、实现、版本及与原仿真是否等价;当前没有实现或验证这类系统。RL 本身也不要求 simulator 可微,学习任务/奖励/优化器仍是 E5 的宿主层 职责。
8.3 多物理“有耦合”不等于“所有物理”#
本章有源码证据的 native 能力是刚体/约束、reduced-coordinate articulation、特定 FEM 体/面、PBD 粒子,以及受支持对象间的接触/attachment。它们有不同状态维度、材料 law、buffer 和同步边界,不能把所有物体装进一套 pose, velocity 就认为完整。
相机 RGB/depth/segmentation、材质光照、任务 reward、数据集 schema 和 sim-to-real 标定仍需宿主/应用实现;见 E4 与 E5。光学 mesh 变形可消费物理顶点结果,但不是 FEM kernel 自己产生图像。热/电磁/化学或未核实的专用流体模型,应明确标“本课程未找到所需原生接口/未覆盖”,不能用“multiphysics”宣传语补成已验收功能。
9. 易错点#
同一名称对应不同层:
shader、density、appliedForce、lambda、substep都须沿类型/量纲/调用者解释。复制
PxCustomGeometry不复制 callback 对象;返回有效 geometry 不保证 bounds/contact/query/mass 一致。未计 geometry margin 的 inertia、混用 actor/COM frame、把 body1 Jacobian 重复取负,都会改变约束模型。
改数据块不 markDirty,或 callback 内违反阶段改 scene,不能靠提高 solver iterations 修复。
force limit 与 impulse cap、几何 tolerance 与求解残差、constraint getForce 与 total wrench 不能互换。
GPU Scene 有 CPU fallback;GPU library 有源码也仍需要外部 CUDA 运行环境。不得手动伪设内部兼容标志。
deformable collision/simulation vertex 索引可能不同;particle phase 也不是 rigid env_id。
device pointer/dirty flag/mirrored pointer 都不是已同步 CPU 快照;post-solve event 不自动回收应用异步任务。
FEM E、关节 k、粒子材料参数和渲染材质不具有统一数值含义;先核量纲、状态和 law。
Jacobian、梯度形函数和训练可微 rollout 是不同证据;当前源码身份也不能替代历史宿主 binary 身份。
10. 阅读练习与参考答案#
把临时 CylinderCallbacks 传给 PxCustomGeometry,再复制 geometry 给长期 shape,是否安全?
不安全。geometry 复制保留同一个裸 callback 指针;临时对象释放后悬空。需由应用保持回调及依赖数据活着,直到所有使用者结束;之后还要核对并发和缓存更新。
cylinder 高度从 H 变为 2H,只更新碰撞支持点够不够?
不够。bounds、query、接触 cache 和质量/COM/惯量需要一致更新;固定密度下质量翻倍,横向惯量含 H² 项,不是简单所有分量乘 2。margin 非零还有另一质量计算路径。
linear1=-n再交给 Px1DConstraint,是否描述两个 attachment 的相对速度?通常不是。原生 J 已含负的 linear1/angular1;本章相对点速需两个 linear 字段都填 n,再各填 r×n。重复取负会变成速度相加。
row 的 maxImpulse=10,hasDriveLimit=true,driveLimitsAreForces=true,simDt=0.002,最终上限是多少?
按实际 helper 是 0.02(线性行为 N·s);缺任一 flag 时为 10 N·s。不能照
eHAS_DRIVE_LIMIT短注释的反向 unless 理解,也不能把 TGS 内部 h 随意替换 simDt。distance joint 的 tolerance=0.01 意味着残差小于 0.01 就退出 solver 吗?
不是。它用于构造几何死区和单边误差;迭代预算另设。还需检查 min/max flags、spring flag 和刚度,默认 joint 不能称为已配置弹簧。
一行没开 eOUTPUT_FORCE,但仍修正了速度。getForce 为零是否说明无约束作用?
不能。writeback 只累计带输出标志的行,断裂判断也使用这部分;还需辨清 scene/激活/断裂状态和采样阶段。报告不含所有外力。
custom geometry 在普通 GPU scene 可用,因此也能和 cloth 碰撞、并完全在 GPU 跑?
不成立。rigid custom pair 有 CPU fallback,cloth/custom 分支有过滤限制;具体 pair、PCM、contact modification 都影响路径。CPU 虚函数不会自动成为 GPU kernel。
为了 Direct GPU,把 custom constraint 的 eGPU_COMPATIBLE 打开是否够了?
不够且公开 setter 禁止。官方 D6 的内建路径和数据格式才有相应支持;DistanceJoint/custom solver-prep 的 CPU 链不能据此迁移。
FEM volume 有 400 个 collision 顶点、120 个 simulation 顶点,复制哪个长度作为完整求解状态?
两者分别有自己的缓冲/语义;simulation position/velocity 用 120,collision position/rest 用 400,不能互换。完整恢复还要初态/拓扑/参数/同步,单一位置数组不是完整 checkpoint。
把无量纲 FEM C 的乘子 ell 除以 dt 能直接得力吗?
按本章无阻尼 co-rotational 更新,ell 量纲是 ML²,除以 T 不是力。它还需通过梯度/具体离散方程解释,不能仿照刚体冲量读回。
粒子数组叫 mDensity,是否可直接当 kg/m³ 传感器输出?
不能。所引 kernel 写入的是截断密度误差乘预计算 scale;局部 mass=1。必须追溯内部归一化、用途和对外 API,名称不足以证明物理单位。
接到 post-solve event,能立即在 CPU 读取 GPU buffer,或让下个 step 自动等自己的 kernel 吗?
都不能这样推断。先让用户 stream 等事件,再安排读/拷贝,CPU 等拷贝完成;应用额外写入还须在下次引擎访问前建立依赖。particle callbacks 另有提供 stream 与 fetchResultsParticleSystem 的契约。
Direct GPU Jacobian 可读,是否完成可微仿真?
没有。它不提供整步状态/动作/参数的反向传播及非光滑点约定。外部代理/有限差分/custom backward 是另一个实现和验证对象;当前只完成源码课程。
11. 本章完成范围与后续入口#
B6/B7 已建立扩展协议、CPU DistanceJoint 从配置到输出的完整追踪、公开 GPU 调度/内核地图、FEM/particle 状态与代表性数值路径,以及宿主/可微/多物理边界。此处“源码课完成”不表示逐行证明所有后端或已运行任何示例。新的原生片段只有 syntax/type 检查;公开源码与实际硬件/运行能力分开记录。
E7 仍待完成 A0 安装专题与双路线整体审校,包括统一先修、术语、未决项和 DexLab 原批次复用入口;当前不自动开展安装/原生构建。本仓先解释引擎,实验最终复用 DexLab,保留原版本、配置与工况,不新增评分器或比较排名。