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
相关产品推荐
相关产品推荐

