You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blender提取带Cloth修改器对象顶点坐标并复现动画失败问题

解决Cloth修改器下顶点坐标提取无变化的问题

问题根源

Cloth修改器是Blender的动态物理模拟修改器,它的顶点变形效果是实时计算的,不会直接修改对象的原始网格数据(obj.data.vertices)。你之前的脚本直接读取原始顶点,自然拿不到模拟后的动态坐标。

修改顶点提取脚本

要获取布料模拟后的顶点坐标,需要先获取当前帧的评估后网格(Evaluated Mesh)——也就是经过所有修改器计算后的最终网格数据。修改后的提取函数如下:

def get_vertices_info(obj_name):
    obj = bpy.data.objects[obj_name]
    vertices_data = {}

    # 遍历所有目标帧
    for frame in range(bpy.context.scene.frame_start, bpy.context.scene.frame_end + 1):
        bpy.context.scene.frame_set(frame)
        # 获取当前帧的评估依赖图与计算后的网格
        depsgraph = bpy.context.evaluated_depsgraph_get()
        evaluated_obj = obj.evaluated_get(depsgraph)
        evaluated_mesh = evaluated_obj.data.copy()

        # 记录每个顶点的世界坐标
        for vertex_index, vertex in enumerate(evaluated_mesh.vertices):
            vertex_world_co = evaluated_obj.matrix_world @ vertex.co
            frame_data = tuple(vertex_world_co)
            # 初始化顶点数据列表
            vertex_key = f"Vertex {vertex_index + 1}"
            if vertex_key not in vertices_data:
                vertices_data[vertex_key] = []
            vertices_data[vertex_key].append(frame_data)
        
        # 清理临时网格,避免内存占用
        bpy.data.meshes.remove(evaluated_mesh)

    return vertices_data

# 提取Plane的顶点数据
vertices_data = get_vertices_info("Plane")

# 整理存储数据(修正原代码中"verticies"的拼写错误)
data = {
    "wind": {
        "strength": wind_strength,
        "directions": wind_directions,
        "coordinates": wind_coordinates
    },
    "vertices": vertices_data
}

修正复现脚本的问题

原复现脚本存在几处逻辑错误,修改后如下:

new_scene = bpy.data.scenes.new("Animated Scene")

original_obj = bpy.data.objects['Plane']
flag = original_obj.copy()
flag.data = original_obj.data.copy()
# 移除布料修改器,避免模拟干扰
cloth_mod = flag.modifiers.get("Cloth")
if cloth_mod:
    flag.modifiers.remove(cloth_mod)

new_scene.collection.objects.link(flag)
bpy.context.window.scene = new_scene

# 读取存储的顶点数据(对应修正后的键名"vertices")
vertex_data = list(data["vertices"].values())

def insert_keyframe(fcurves, frame, values):
    for fcu, val in zip(fcurves, values):
        fcu.keyframe_points.insert(frame, val, options={'FAST'})

mesh = flag.data
action = bpy.data.actions.new("MeshAnimation")

mesh.animation_data_create()
mesh.animation_data.action = action

data_path = "vertices[%d].co"

# 与提取时的帧范围保持一致
frame_start = bpy.context.scene.frame_start
frame_end = bpy.context.scene.frame_end
frames = list(range(frame_start, frame_end + 1))

for i, v in enumerate(mesh.vertices):
    # 创建XYZ三个轴的关键帧曲线
    fcurves = [action.fcurves.new(data_path % v.index, index=axis) for axis in range(3)]
    # 逐帧插入顶点坐标关键帧
    for t, value in zip(frames, vertex_data[i]):
        insert_keyframe(fcurves, t, value)

额外注意事项

  • 提取数据时,每次获取评估网格后记得用bpy.data.meshes.remove()清理,避免内存泄漏
  • 复现时要确保新对象的顶点数量和原始对象完全一致,否则会出现索引不匹配问题
  • 坐标方向问题可通过检查matrix_world的转换逻辑调整,确认是局部坐标还是世界坐标的混淆

内容的提问来源于stack exchange,提问作者Salih Erdem Kaymak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 15:32:32