
在Blender中对受骨骼动画影响的网格顶点施加力(如重力)时,直接修改 vertices[i].co 会导致位移始终基于物体局部坐标系,无法正确响应形变后的世界空间位置;需借助 crazyspace_eval() 与 crazyspace_displacement_to_original() 实现世界空间位移的逆向映射。
在blender中对受骨骼动画影响的网格顶点施加力(如重力)时,直接修改 `vertices[i].co` 会导致位移始终基于物体局部坐标系,无法正确响应形变后的世界空间位置;需借助 `crazyspace_eval()` 与 `crazyspace_displacement_to_original()` 实现世界空间位移的逆向映射。
当网格受 Armature 修改器驱动并处于动画帧中时,其顶点在视口中的实际位置是经过骨架变形、修改器链(如形变、细分等)计算后的最终世界空间位置,而 obj.data.vertices[i].co 存储的仍是原始网格的局部静止姿态坐标(即“绑定姿态”下的坐标)。因此,若想让顶点沿世界空间方向(例如全局向下 -Z)偏移(如模拟重力),不能简单执行 v.co += world_vector —— 因为该操作会破坏形变一致性,且偏移方向被锁定在未变形的局部轴上。
Blender 提供了 crazyspace 相关 API(非官方但稳定存在于 bpy.types.Object 中),专用于处理此类“世界空间位移 → 原始顶点坐标修正”的映射问题。其核心逻辑是:
- 评估依赖图(depsgraph):获取当前帧下经所有修改器(含 Armature)作用后的最终顶点位置;
- 计算反向位移量(displacement_to_original):给定一个世界空间向量(如 (0,0,-0.3)),该方法自动计算出应加到原始顶点坐标上的局部偏移量 delta,使得应用后,该顶点在最终形变结果中恰好产生指定的世界空间位移。
以下是完整、健壮的实现示例:
import bpy
import mathutils
def apply_world_space_force(vertex_index=0, world_force: mathutils.Vector = mathutils.Vector((0.0, 0.0, -0.3))):
obj = bpy.context.object
if not obj or not obj.type == 'MESH' or not obj.data.vertices:
raise RuntimeError("Active object must be a mesh with vertices")
# 获取当前场景和依赖图
depsgraph = bpy.context.evaluated_depsgraph_get()
# 执行 crazyspace 预计算(必须调用)
obj.crazyspace_eval(depsgraph, bpy.context.scene)
try:
# 将世界空间力向量转换为需施加到原始顶点坐标的局部增量
delta = obj.crazyspace_displacement_to_original(
vertex_index=vertex_index,
displacement=world_force
)
# 安全更新顶点坐标(注意:仅修改原始数据,不触发实时重绘)
obj.data.vertices[vertex_index].co += delta
# 可选:刷新网格显示(尤其在编辑模式下)
obj.data.update()
finally:
# 必须清理,避免内存泄漏或后续评估异常
obj.crazyspace_eval_clear()
# 使用示例:对选中网格的第一个顶点施加向下重力
apply_world_space_force(vertex_index=0, world_force=mathutils.Vector((0, 0, -0.3)))⚠️ 重要注意事项:
- crazyspace_eval() 和 crazyspace_eval_clear() 必须成对使用,且 clear() 应置于 try/finally 块中,确保异常时也能释放资源;
- crazyspace_displacement_to_original() 的 vertex_index 必须在有效范围内,否则抛出 IndexError;
- 此方法适用于已绑定 Armature 修改器且启用形变的网格;若无形变修改器,delta ≈ world_force(因局部空间与世界空间一致);
- 修改 obj.data.vertices[i].co 不会自动更新 UV、顶点组权重或面法线——如需物理仿真级精度,建议结合 bmesh 或在几何节点中实现;
- 该 API 在 Blender 3.6+ 中稳定可用,但属内部机制,官方文档未正式收录,使用时请保持版本兼容性验证。
通过此方案,无论网格处于静止姿态还是任意动画帧的形变状态,你添加的位移都将精确作用于视觉可见的世界空间方向,真正实现“所见即所得”的物理式交互控制。

















