blender 使用物理骨骼,受物理影响+不影响主观能动性的"物理妥协骨骼" 插件:wiggle bone / rigid bone
类型上: Mesh网格 ≠ Bone骨骼
骨骼物理
代理骨骼(纯物理模拟) + 驱动器
优点:方便解耦,运算速度快
缺点:碰撞箱得再做一个代理,否则碰撞体积不准确;
应用场景:全身都得进入物理模拟
思路:RIG摆姿势骨(非控制骨)→姿态同步到phy骨架→phy原旋转加上物理模拟的后旋转→映射回RIG控制骨
前提:骨骼位置先对齐,2个骨架对应的骨骼命名一致
可调参数q=False
,此时使用Eular_XYZ运算
import bpy q=True #act=bpy.context.selected_pose_bones_from_active_object act=bpy.data.objects['phy.001'].pose.bones src_obj=bpy.data.objects['C'] src=src_obj.pose.bones mode_str='quaternion' if q else 'euler' rot_str='QUATERNION' if q else 'XYZ' # QUATERNION XYZ AXIS_ANGLE axis='xyzw' for bone in src: bone.rotation_mode=rot_str for abone in act: abone.rotation_mode=rot_str # QUATERNION XYZ AXIS_ANGLE abone.driver_remove('rotation_'+mode_str) # continue len=4 if q else 3 dri = [abone.driver_add('rotation_'+mode_str, i) for i in range(len)] i=3 if q else 0 for dr_ in dri: dr=dr_.driver try: transf=dr.variables['Transform'] except: transf = dr.variables.new() transf.name = 'Transform' transf.type = 'TRANSFORMS' target = transf.targets[0] target.id=src_obj target.rotation_mode=rot_str.upper() target.bone_target = abone.name target.transform_type = 'ROT_'+axis[i].upper() target.transform_space='WORLD_SPACE' # WORLD_SPACE LOCAL_SPACE TRANSFORM_SPACE dr.use_self=True if (i!=3): dr.expression = "(self.rotation_"+mode_str+'.'+axis[i]+"+Transform)/2" else: dr.expression = "Transform" # dr.expression = "copysign(1,Transform)*max(abs(Transform),0.1)" # It's hard to solve the sign change while crossing the axis, which cause the bone position suddenly changes i=(i+1)%4 # https://docs.blender.org/api/3.5/bpy.types.DriverTarget.html#bpy.types.DriverTarget.transform_space
代理骨骼+约束器(约束控制骨骼)
已弃用此方法,因为wiggleBone(可能)先于约束器进行运算,导致超过3条链,Mix使用“相加”数值则会太过了,导致不正确的旋转
需要以下bpy脚本,批量添加约束,其中phy是纯粹的物理模拟用的骨骼(可以从metarig复制)
import bpy cpName='phy' cp_obj=bpy.data.objects[cpName] cp_bones=bpy.data.objects[cpName].pose.bones print(cp_bones) selected_bones = [bone for bone in bpy.context.selected_pose_bones] for bone in selected_bones: # for con in bone.constraints: print('bc',bone.constraints) if not bone.constraints: bone.constraints.new('COPY_ROTATION') print('YES') ctmp=bone.constraints["Copy Rotation"] print('ctmp',ctmp) ctmp.target = cp_obj ctmp.subtarget = bone.name ctmp.target_space="LOCAL" ctmp.owner_space='LOCAL' ctmp.influence=0.333 # pose.bones["b_6_0"].constraints["Copy Rotation"].influence
物理↔控制骨骼互相影响:
Wiggle Bone
https://github.com/shteeve3d/blender-wiggle-2
(此方法已弃用,当骨架有1000多跟骨骼时,比如rigify生成的人:human-metarig,耦合的骨骼,运算很慢)
复制需要物理模拟的控制骨,做2层一样的控制骨,在DEF的需要物理模拟的骨骼中加约束,影响:0.5
需要以下脚本来快速找到骨骼约束、被约束的关系:
import bpy ob = bpy.context.selected_objects[0] pose = ob.pose for bonename in pose.bones.keys(): bone = pose.bones[bonename] for const in bone.constraints: try: print(bone.name, '->'+const.subtarget,sep='\t') except: pass
解决wiggle异常抖动
把世界空间
改局部空间
成功!
批量删除选中的骨骼约束
import bpy selected_bones = [bone for bone in bpy.context.selected_pose_bones] for bone in selected_bones: for con in bone.constraints: bone.constraints.remove(con)
bone dynamics + simpliCage代理网格做布料碰撞
没有wiggle bone那么卡,当然没有弹簧特性
https://www.bilibili.com/video/BV1Ye411G74K
rigid bone
https://github.com/Pauan/blender-rigid-body-bones
ps: wiggleBone仅影响旋转
要位移的用rigid bone,但碰撞不好调,容易鬼畜
网格物理+钉固顶点组(不建议)
被钉固的网格顶点,会被上一个修改器修改
布料模拟最蛋疼的地方就是,每次都得从第0帧开始播放模拟
本文作者:Nolca
本文链接:https://www.cnblogs.com/nolca/p/17473214.html
版权声明:本作品采用 收益分享revenue sharing 许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步