I am doing a visualization where I need to transform a sphere with a matrix. Easiest solution would be to just set the matrix as local transform but this gives me unexpected results.
I was trying around a little and found out, that setting matrix_local
, delta_...
and operating on vertex positions directly yields very different results. As an example, I tried it with a simple shear matrix. Here are the results:
Using matrix on vertex positions
Using local transformation matrix
Using delta transform
This is the code:
import bpy
from mathutils import *
def transform_verts(context):
obj = context.active_object
mat = Matrix.Shear('XY', 4, (3,3))
#this does what it is supposed to do
for j in range(0, len(obj.data.vertices)):
obj.data.vertices[j].co = mat @ obj.data.vertices[j].co
def transform_delta(context):
obj = context.active_object
# This does NOT work as intended :(
# this deforms the sphere into an elongated Ellipsoide
d_loc, d_rot, d_sc = Matrix.Shear('XY', 4, (3,3)).decompose()
obj.delta_location = d_loc
obj.delta_rotation_quaternion = d_rot
obj.delta_scale = d_sc
def transform_matrix_local(context):
obj = context.active_object
# for unknown reasons it is not possible to do this with an object transformation matrix
# setting matrix_local yields similar weird results as setting delta transform
# I suppose it may have to do with Blender internally decomposing it
obj.matrix_local = Matrix.Shear('XY', 4, (3,3))
class SimpleOperator(bpy.types.Operator):
"""Tooltip"""
bl_idname = "object.simple_operator"
bl_label = "Simple Object Operator"
@classmethod
def poll(cls, context):
return context.active_object is not None
def execute(self, context):
#transform_verts(context)
#transform_delta(context)
transform_matrix_local(context)
return {'FINISHED'}
def register():
bpy.utils.register_class(SimpleOperator)
def unregister():
bpy.utils.unregister_class(SimpleOperator)
if __name__ == "__main__":
register()
# test call
bpy.ops.object.simple_operator()
Why does setting the matrix_local also does something very different from what is intended? In my understanding, setting the matrix_local should do exactly the same as applying the matrix to vertex positions.
Is there a workaround for this issue that does not involve looping through vertices and setting the position manually? The above is just an example. My actual use case is a modal operator and right now I need to store the original vertex positions and loop through them each time modal
is called. That is really slow compared to just setting the local transformation matrix.
If there isn't, any idea how to speed it up?
Edit: obj.data.transform()
is not possible because I need to apply the matrix to the sphere each time. This matrix is not necessarily invertable, so I can't just do the inverse transformation from the previous call and then do the current transformation. I would only be able to use it if I can somehow restore the positions the vertices had before the transformation.