强制在Blender中重新计算matrix_world

时间:2012-12-12 13:02:32

标签: python matrix blender

我正在为搅拌机设计一个附加组件,它可以改变对象某些顶点的位置。 blender中的每个对象都有一个matrix_world属性,它包含一个矩阵,用于将顶点坐标从对象转换为世界框架。

print(object.matrix_world) # unit matrix (as expected)
object.location += mathutils.Vector((5,0,0))
object.rotation_quaternion *= mathutils.Quaternion((0.0, 1.0, 0.0), math.radians(45))
print(object.matrix_world) # Also unit matrix!?!

上面的代码段显示翻译后,您仍然拥有相同的matrix_world。我如何强制搅拌机重新计算matrix_world?

3 个答案:

答案 0 :(得分:5)

您应该在更改这些值后调用Scene.update,否则Blender将不会重新计算matrix_world,直到需要[其他地方]。根据API文档中的"Gotcha's" section,原因是这个重新计算是一项昂贵的操作,因此不会马上完成:

  

有时你想修改python中的值并立即访问更新的值,例如:

     

更改对象bpy.types.Object.location后,您可能希望在bpy.types.Object.matrix_world之后立即访问其转换,但这不会像您预期的那样有效。

     

考虑可能用于计算对象最终转换的计算,其中包括:

     
      
  • 动画功能曲线。
  •   
  • 司机和他们的蟒蛇表达。
  •   
  • 约束
  •   
  • 父对象及其所有f曲线,约束等。
  •   
     

为避免每次修改属性时进行昂贵的重新计算,Blender推迟进行实际计算,直到需要它们为止。

     

但是,当脚本运行时,您可能希望访问更新的值。

     

这可以通过在修改重新计算标记为要更新的所有数据的值后调用bpy.types.Scene.update来完成。

答案 1 :(得分:1)

在循环中调用bpy.context.scene.update()可能会变得昂贵

如果您的对象没有复杂的约束(例如普通约束或父约束),则可以在更改对象的.location.rotation_euler\quaternion.scale之后,使用以下内容重新计算世界矩阵。 / p>

def update_matrices(obj):
    if obj.parent is None:
        obj.matrix_world = obj.matrix_basis

    else:
        obj.matrix_world = obj.parent.matrix_world * \
                           obj.matrix_parent_inverse * \
                           obj.matrix_basis

一些注意事项:

  • 设置对象位置/旋转/比例后立即更新对象的matrix_basis
  • 但是matrix_local(有父母)和matrix_world仅在scene.update()期间更新
  • 手动matrix_world(使用上面的代码)重新计算时,matrix_local也被重新计算
  • 如果对象是父母,则其世界矩阵取决于父母的世界矩阵以及创建父母关系时父母的逆矩阵。

答案 2 :(得分:0)

我也需要这样做但是在我导入一个包含数万个对象的大型场景时需要更新这个值。 调用' scene.update()'变得指数级变慢,所以我需要找到一种方法来做到这一点,而不需要调用该函数。 这就是我想出的:

def BuildScaleMatrix(s):
    return Matrix.Scale(s[0],4,(1,0,0)) * Matrix.Scale(s[1],4,(0,1,0)) * Matrix.Scale(s[2],4,(0,0,1))

def BuildRotationMatrixXYZ(r):
    return  Matrix.Rotation(r[2],4,'Z') * Matrix.Rotation(r[1],4,'Y') * Matrix.Rotation(r[0],4,'X')

def BuildMatrix(t,r,s):
    return   Matrix.Translation(t) * BuildRotationMatrixXYZ(r) * BuildScaleMatrix(s)

def UpdateObjectTransform(ob):
    ob.matrix_world = BuildMatrix(ob.location, ob.rotation_euler, ob.scale)

这不是建立矩阵的最有效方法(如果你知道在混合器中有更好的方法,请添加),这只适用于XYZ顺序变换,但这可以避免在处理大数据集时呈指数减速