
最近项目里接到一个蛮有意思的需求角色身上那块做旧的大装甲需要表现出“正在被外力弯折”的金属形变而且弯折的力度、位置要在动画里随时调整最好还能带一点弹塑性回弹。我第一反应是用传统方式手K关节权重或者做个简单旋转点但美术那边给出的反馈很快需求太动态了一个角色好几块板甲要分别弯曲手K等于要把整个绑定流程再走一遍时间完全不够。后来我转向Houdini做金属弯曲模拟折腾了几轮之后发现这事其实非常适合用解算器来处理。Houdini的优势在于它可以基于约束和物理参数把“金属被弯过去的动态过程”模拟出来同时还能控制弹性和塑性变形比例弯曲哪里、弯多少度都能用属性或驱动物体去控制。这篇笔记把这次的完整方案和踩过的坑都记录下来给同样在游戏或影视TA方向上需要做类似效果的朋友一个参考。1. 方案选择为什么用Houdini而不是直接手K或Maya柔体1.1 传统手K的问题在哪如果你有几分钟时间让我先说一下为什么一开始用“手K关节旋转”的方案被否掉了。手K本身并不是不能用它的问题在于金属弯折的过程通常伴随局部的挤压和拉伸单靠旋转角度很难模拟出材料厚度变化带来的褶皱感。角色动画过程中弯折的起始点和终止点会变手K版本需要重新调整权重、修改旋转数值工作量成倍增加。金属有一个很关键的特征当弯折超过一定角度后它不会弹回来这个塑性变形程度用骨骼旋转去“假装”是很别扭的。也就是说手K适合做简单的门轴、机械杆这类单纯旋转不适合做柔性的、带局部形变的金属片弯折。1.2 Houdini Vellum的匹配度Houdini里做金属弯曲模拟我最终采用的是基于Vellum Solver的方案。Vellum本身是PBDPosition Based Dynamics风格的解算器实时性、可调性和可控性都很好。金属弯折放进Vellum里本质上可以抽象为“弯曲约束 碰撞约束 塑性属性变换”。和Maya的nCloth或者C4D柔体相比Houdini Vellum的替换感更强约束类型丰富可以单独给弯曲约束设置刚度、摩擦和塑性范围可以用属性贴图、距离衰减、组范围来控制约束的影响区域解算结束后的几何仍然保留精细的点线面结构方便后续直接渲染或导出。站在技术美术的角度选择Vellum还有一个理由数据流透明。每一个点的rest position、弯曲角度、塑性状态都可以通过point wrangle查看和修改。对于需要团队协作的项目这意味着可以从流程层面进行调试而不只是扔个黑盒缓存给下游。1.3 替代方案显式SOP Solver做程序化弯折可能会有人问那直接用SOP Solver加point wrangle手写弯曲变形行不行这个方案我也试过。在可控性上SOP Solver写一个简单的弯曲算法其实不难取轴向根据角度和位置旋转点然后叠加噪音模拟不规则形变。但是这里有几个绕不开的坎真实的金属弯折弯曲内侧会被压缩外侧会被拉伸这种体积保持效果需要在弯曲变形里额外加体积约束或mesh优化很折腾。回弹和塑性需要跟踪每个点的应力/应变历史相当于自己实现材料模型的记忆功能。当弯折过程中发生自我碰撞例如金属片弯到对折没有解算器的碰撞处理穿模会非常严重。所以如果你只是想弯曲一个圆柱体SOP Solver方案就够了但要弯曲一块不规则的板甲、还要求表现真实质感的弯曲反馈建议直接用Vellum。2. 金属弯曲的物理特征与参数映射2.1 金属弯折过程分几个阶段在做金属弯曲模拟之前强烈建议先理解一下真实金属弯折的几个阶段。这个理解直接决定了你在Houdini里的参数怎么调。真实金属受弯时大致经历这样的过程弹性阶段力不大时金属发生微小形变撤销力后完全恢复原状。屈服阶段当应力超过材料的屈服强度金属开始发生无法自行恢复的变形此时形变随应力增大而明显增加。塑性强化阶段超过屈服点后材料出现硬化需要继续增加应力才能持续变形。断裂阶段如果继续弯形变超过延展极限材料出现裂纹或断开。我们在做角色金属甲片弯曲时一般需要模拟的是从弹性到塑性前期的过程让它“弯过去后不回弹”。如果要模拟断裂后掉落碎片的镜头还得再叠加切分和刚体解算。2.2 Vellum约束怎么对应金属特性Vellum里直接和金属弯曲相关的主要是Bend Constraint弯曲约束和它背后的材质参数。要让弯曲模拟看起来像金属我的经验是重点关注这几个量Bend Weight / Bend Stiffness控制抗弯曲能力刚度越大越难弯。金属通常需要一个偏高的基础刚度来体现实质感。Bend Radius影响弯曲约束的有效范围。这个参数对形变的细节影响很大 radius太小可能出现锯齿状褶皱radius太大则弯曲效果会显得“糊”。Plasticity塑性度决定变形超过多少之后转为永久形变。如果将Plasticity设为0.8意味着 80% 的弯曲会被“记住”只有剩下20%回弹。Plastic Threshold触发塑性变形的弯曲角度阈值小于这个角度的弯折完全回弹大于这个角度的弯折开始保留剩下的大部分变形。具体到Vellum材质模型里Houdini从19版本开始提供了较为直观的塑性参数面板。如果你使用的还是老版本也可以通过自定义VEX在Point Wrangle里维护一个塑性状态属性实现类似效果。2.3 把真实金属概念“翻译”为Houdini能用的参数下面这份映射表是我个人比较常用的初始对照可以作为预调参数参考真实金属特性Vellum/Houdini参数参考范围按单位相对尺寸效果说明弹性模量Bend Stiffness0.5 - 1.0数值越大越难被弯曲屈服点Plastic Threshold0.1 - 0.5 rad超过该角度开始产生塑性记忆塑性保留比例Plasticity0.7 - 0.95决定回弹程度越大越“软塌”材料内阻Damping0.01 - 0.1数值过大弯曲会发“肉”厚度感Bend Radius几何厚度数值的3-8倍决定褶皱、皱纹的尺度我把金属甲片的几何厚度做成厚度属性后直接在Bend Radius里连上这个属性比手动填一个统一数值更贴合实际造型表现。3. 实操流程从几何准备到缓存输出3.1 初始几何准备Houdini金属弯曲模拟虽然用的是解算器但真正决定成败的往往在解算之前的几何准备。我推荐板状金属在进入Vellum之前做以下几个处理足够的细分如果没有足够多的面数弯曲约束没有足够的采样点去形成均匀的圆弧过渡很容易出现棱角感。一般按金属片面积估算至少保证弯曲方向上有20段以上的网格划分。厚度和双层结构真实的金属片哪怕很薄也有厚度但Vellum默认是单面约束不感知厚度。你可以用PolyExtrude给一个微小厚度或者在碰撞阶段特意加一个Collision Width来模拟厚度。这个细节能显著减少弯曲时的“纸片感”。清理穿模初始状态如果初始状态下金属片和驱动工具已经处于相交状态解算起步就会产生巨大碰撞弹出最好是先把驱动工具放在恰好接触的位置。另外如果这块金属片来自角色的模型需要注意模型上往往带有多余的点组比如命名空间、材质id点组建议提前用Group Promote清理无用点组避免后续属性传输时出现命名冲突。3.2 Vellum Configure设置Houdini的Vellum配置入口主要有两个一个是从菜单直接选“Vellum Cloth”或“Vellum Soft Body”预设另一个是用Vellum Configure节点自选约束类型。金属弯曲模拟更适合用Vellum Configure手动配置把Constraints设为Bend Only加上Kill固定或Collision。个人习惯的组合是Bend Constraint金属核心的弯曲行为Collision Constraint和碰撞体或自碰撞的接触Pin Constraint按需把金属片某一边钉到角色骨骼或盔甲底座上如果你需要做“金属被一个机械爪抓住并折弯”的效果机械爪和金属片之间的接触可以给金属片加一个Soft Pin Constraint指向抓取工具上的点这样金属片会跟着机械手运动同时产生弯曲形变。3.3 关键参数调优假设你有一个简单的矩形金属条一端固定另一端用一个平面向下压。此时Vellum Solver的主要参数可以这样设置Solve StepsSubSteps建议至少4到8。金属约束刚度高时约束反馈会很“硬”如果解算迭代不足会出现明显的抖动。Constraint Iterations默认一般2-3次做金属时我一般开到8-15尤其是要保留褶皱细节的时候。迭代次数并非越高越好太高会让几何整体变“僵硬”反而损失自然运动细节。Collision Tolerance碰撞容差默认值在单位尺度正常时够用。如果你的场景单位是米而金属片厚度是几毫米需要手动给碰撞容差一个合适大小否则会穿透。这里有一个容易踩坑的地方Vellum的Collision Width其实是每个点属性collision_width决定的。如果你希望金属片在弯曲时保持厚度感不要只调Solver面板上的全局Collision Width还要注意把金属片点上的collision_width设置成适当数值比如厚度的一半。如果不设置点的Collision Width可能默认是0.01这种小数值碰撞效果约等于没有。3.4 用驱动物体控制弯曲位置和角度大多数时候我们不会只想要一个柔性金属片在那自由摆动而是希望某个位置、以某个节奏弯折并且还能随时调整。我的做法是使用一个中间的“驱动骨架线”在金属片上按轴向放置一根曲线用PolyFrame沿片的方向生成中线。这根曲线用Transform或Animation节点去K帧旋转模拟弯折的方向和角度。Vellum里用Attach Constraint把金属片点约束到这根曲线附近且约束强度控制在0.5左右。这样金属片会跟随驱动曲线运动但又不至于完全变成刚性保留了弯曲模拟的细节。这个方案的调参自由度很大驱动曲线可以不断调整弯曲角度Vellum负责在中间填充形变细节。先前在最终渲染图里装甲在弯曲过程中的那个自然形成的厚度挤压褶皱几乎都是这个方案做出来的。3.5 输出阶段烘焙缓存与属性导出Vellum解算完成后一般需要将模拟结果缓存通常用Cache Sequence或者Active Rig Body 的模拟缓存输出为bgeo cache。但如果这个金属片还要回到Maya或引擎里编辑最终动画我建议这样处理提取最终静止形状用Time Shift取到最后一帧或者用Visibility控制解算片段然后Adaptive Level of Detail减少面数如果前面为了褶皱细分比较高。输出位置和旋转属性到骨骼层级如果是给引擎用可以把这个模拟得到的形变逐帧烘焙到贴图或者顶点动画Texture。Houdini里有Vertex Animation Texture的专门节点VAT可以直接把点位置变化输出为纹理贴图性能消耗相对可控。属性传递如果需要把弯曲量映射到材质比如弯曲区域响应金属表面拉伤、划痕可以在模拟完成后用Point Wrangle计算每个点相对rest shape的角度变化方法是用Rest Node存初始位置再用dot(当前normal, rest normal)得到变化余弦值存成bend_angle属性后续导入到材质里去混合贴图。4. 常见问题与排查技巧实录4.1 金属片弯曲时疯狂抖动这是最经典的问题尤其是把Bend Stiffness调高以后Vellum求解器很容易出现高频抖动。典型表现就是弯折位置出现“果冻感”解算结果像布条而不像金属。排查顺序先检查SubSteps金属单元通常需要更高的子步数我建议从8起步。然后看Constraint Iterations如果迭代太少约束力传递不到位会产生能量积聚表现为抖振。最后确认Damping不要为了稳定把Damping直接调高那样弯曲就变“软”了。可以尝试先把Damping控制在0.02-0.05之间再回头解决子步和迭代。我遇到过的最隐蔽原因是碰撞交互过大导致局部点被弹飞之后整片震荡。解决方法是给碰撞体合适的Collision Tolerance不要用默认值直接用需要和金属片的尺寸量级匹配。4.2 弯折后完全回弹塑性没生效如果发现金属弯曲模拟时弯过去又弹回来几乎可以断定是Plasticity参数没有正确作用于该组约束。这里要留意Vellum里的约束类型。Bend Constraint默认情况下不一定启用塑性你需要在Vellum Configure里勾选Plasticity选项并给上Threshold和Plasticity数值。如果你是用自定义VEX维护了一个塑性属性还需要检查解算器是否在每帧正确读取该属性。另外组的选择也很关键。我调试时曾经把弯曲约束添加到了“固定组”上结果固定部分完全不动、自然没有塑性形变。这种情况只需要检查约束是施加在需要弯折的组上而不是被固定约束覆盖掉。4.3 穿模尤其是金属片对折时自碰撞金属片弯到比较大角度时经常出现两片面互相穿插。此时自碰撞设置要重点看两个地方Self Collision选项是否开启Vellum Solver默认可能不开自碰撞。Self Collision的碰撞阈值Self Collision Tolerance是不是太小。对于薄板来说建议做成金属厚度的30%到50%太大容易造成表面互相推开时的“气垫感”太小又会透明对穿。如果还是穿透可以在Vellum Configure里给金属片额外生成一组“加厚碰撞代理”的碰撞点组。做法是复制原几何略微偏移半个厚度作为碰撞体专门用来参与自碰撞解算渲染时仍然用原始面。这是我在做很薄的甲片时常用的一招。4.4 弯曲褶皱的位置不自然金属片弯曲时褶皱的分布主要受弯曲约束的选择和Bend Radius影响。如果褶皱集中在某几列网格上而不是均匀分布通常是约束点设置得不均匀。解决思路用Attribute Paint把Bend Stiffness做一个渐变分布例如中间部分更柔软、边缘更硬这样弯曲过渡更平滑褶皱自然分散。适当提高Bend Radius褶皱会变得更宽更自然反之则会出现脆裂感的细密褶。在需要的地方还可以用Noise (VEX) 给Bend Stiffness叠加一点随机扰动会模拟出真实金属材料不均匀导致的局部回弹差异视觉表现上更有说服力。4.5 解算速度太慢金属弯曲模拟如果细分较高、迭代数开得很大解算速度可能让人崩溃。经验做法是这样前期开发调参用低面数版本一个简单box分成几十个点就行调好视觉节奏后再替换高清晰度版本进行最终模拟。如果高清晰度版本运行太慢可以考虑按需局部细分比如只在你预期要弯折的区域做密集细分其余保持低细节。碰撞体也可以用简化代理比如机械爪用不做详细雕刻的简单几何体只保留接触面外形。另外金属弯曲模拟过程中如果必要可以使用Solver节点里的“Re-solve from Scratch”方式把非解算部分缓存下来这样每轮调参不用重复计算之前的过程。5. 进阶扩展把模拟结果用于角色绑定和实时渲染从项目落地的角度看Houdini模拟出来的金属弯曲结果最好能无缝接入下游的绑定系统或引擎渲染管线。这里分享两条我实际验证过的路线。5.1 绑定接入方案如果金属片是角色身体的一部分希望能跟着骨骼变形又保留解算出来的弯曲细节可以这样做将Houdini模拟出的形变值烘焙为骨骼或曲线旋转。用Houdini的Bake Animation节点可以提取模拟网格上某一点/某条曲线的运动轨迹并转成transform通道。随后把烘焙出的动画导入到Maya的骨骼层级让骨骼去驱动装好的权重叠加在原有动画上面。这个方法适合实时计算场景因为它不需要在引擎里跑布料/软体解算性能消耗很低。5.2 引擎顶点动画贴图方案对于弯曲形变较为独立、且希望尽可能保留Houdini精细模拟结果的场景可以用Vertex Animation Texture。具体操作步骤用Rest节点存初始位置和法线。在解算结束后利用Time Shift提取需要的时间范围。用Point Wrangle计算从rest到当前帧的位移输出到pos和normal属性。用Vertex Animation节点导出贴图设置合适的尺寸和帧数。引擎里用Shader采样贴图并应用到对应网格上。这个方法在UE和Unity都通用关键是纹理采样的边界设置要处理好防止顶点插值产生偏移。我这里一般设置纹理Wrap Mode为Clamp具体项目里可能还需要在Shader中增加一定的偏移校正。6. 我在实际项目中总结的几条经验第一金属弯曲模拟不是越精细越好看。如果你把每根褶皱、每一条压痕都通过高细分和高刚度约束模拟出来很可能得到的反而是一块看起来像被揉皱的纸片。金属的美感在于“有克制的形变”该平的地方保持平该弯的地方才出现细节。所以我在调参时会刻意把Bend Radius调大一点让褶皱更宽更深。第二一定要重视Rest Position的管理。Houdini解算的正常运行依赖rest position属性的正确性。如果模拟中途发现弯曲方向完全混乱通常就是因为某个节点修改了位置但没有更新rest只更新了P。解决办法是在进入Vellum之前强制用Rest节点重设一次rest避免后面各种奇怪问题。第三善用Vellum的几个辅助属性。除了collision_width金属片上还可以设bend_stiffness、bend_damping这些点属性它们能提供比全局参数精细得多的控制。美术做材质贴图时经常已经把划痕和脏旧分布画在贴图上了完全可以把这些贴图的灰度值直接映射到bend_stiffness上让模拟出来的形变自动贴合贴图就能形成一个“材质不动几何也不动材质磨损多的地方先弯曲”的联动逻辑。第四协作流程中早点做缓存和版本管理。Houdini节点图很容易做到一半想回头改个上游参数结果整个解算全部重跑很费时间。建议定稿前把上游绑定和约束数据单独设为缓存节点下游只改解算参数。这样解算版本管理会高效很多。最后再分享一个小技巧如果你希望弯曲发生后金属表面显示出微小的“光亮条痕”不用真的去让材质系统读取弯曲模拟结果可以直接提取bend_angle属性用Color节点做可视化映射再通过“convert attribute to Cd”就能让美术一眼看到哪里弯曲最大方便他们在贴图上加反射强度。这个调试技巧多次帮我快速定位问题效率比依赖肉眼去观察形变细节要高得多。