1
$\begingroup$

Suppose we have two cube objects: Obj1 and Obj2. Let's say Obj1's Euler rotation is Vector((0,0,0)) and Obj2's rotation is Vector((0,0,45)) How can I rotate Obj1's mesh so that it matches Obj2's rotation? I know that BMesh lets me rotate vertices of an object but I don't know how to implement it properly. I tried this and it didn't work:

import bpy
import mathutils
from mathutils import  Quaternion, Vector, Matrix
import bmesh
import math
from math import radians

context = bpy.context
data = bpy.data

obj1 = data.objects['Obj1']
obj2 = data.objects['Obj2']

from_quat_rot = obj1.rotation_quaternion
to_quat_rot = obj2.rotation_quaternion

difference_quat = from_quat_rot.rotation_difference(to_quat_rot)
difference_angle = difference_quat.angle

print(f"difference quaternion: {difference_quat}")
print(f"difference angle: {difference_angle}")


vector_zero = Vector((0, 0, 0))
bm = bmesh.new()
bm.from_mesh(obj1.data)
#bmesh.ops.rotate(bm, cent=vector_zero, verts=bm.verts, matrix=Matrix.Rotation(radians(difference_angle), 4, 'Z'))
bmesh.ops.rotate(bm, cent=vector_zero, verts=bm.verts, matrix=difference_quat.to_matrix())
bm.to_mesh(obj1.data)
bm.free()

Unfortunately I don't know linear algebra so I probably won't understand if you provide me with an equation, I'd rather prefer a bit of python code. Thanks.

$\endgroup$
4
  • $\begingroup$ Matrix.Rotation(q.angle, 3, q.axis) The angle is already in radians. Theoretically same as usingq.to_matrix() . Can also transform every vert in a mesh directly with ob.data.transform(Matrix) $\endgroup$
    – batFINGER
    Commented Nov 14, 2019 at 12:45
  • $\begingroup$ I maybe misunderstood you but I tried this and it didn't work either: bmesh.ops.rotate(bm, cent=vector_zero, verts=bm.verts, matrix=Matrix.Rotation(to_quat_rot.angle, 3, to_quat_rot.axis)) $\endgroup$
    – blablaalb
    Commented Nov 14, 2019 at 12:52
  • $\begingroup$ Once a rotation is applied the mesh is no longer "aligned" running again will have an accumulative effect. Can you add an illustration of before and after explaining what isn't working? $\endgroup$
    – batFINGER
    Commented Nov 14, 2019 at 12:54
  • $\begingroup$ I'm trying to illustrate my problem with GIF images. Please bear with me a little $\endgroup$
    – blablaalb
    Commented Nov 14, 2019 at 12:59

1 Answer 1

2
$\begingroup$

If your objects are in Euler rotation mode, then the quaternion wont be set. For any mode using

ob.matrix_world.to_euler()
ob.matrix_world.to_quaternion()

will give the global euler and quaternion rotation respectively.

import bpy
import mathutils
from mathutils import  Quaternion, Vector, Matrix
import bmesh
import math
from math import radians

context = bpy.context
data = bpy.data

obj1 = data.objects['Cube']
obj2 = data.objects['Cube.001']

from_quat_rot = obj1.matrix_world.to_quaternion()
to_quat_rot = obj2.matrix_world.to_quaternion()
from_euler_rot = obj1.rotation_euler
to_euler_rot = obj2.rotation_euler

difference_quat = from_quat_rot.rotation_difference(to_quat_rot)
difference_angle = difference_quat.angle

print(f"difference angle: {difference_angle}")

vector_zero = Vector((0, 0, 0))
bm = bmesh.new()
bm.from_mesh(obj1.data)
bmesh.ops.rotate(bm, 
        cent=vector_zero, 
        verts=bm.verts, 
        matrix=Matrix.Rotation(difference_angle, 4, difference_quat.axis))
bm.to_mesh(obj1.data)
bm.free()

This rotates the mesh as expected. Running again will have an accumulative effect.

could also

M = difference_quat.to_matrix()
obj1.data.transform(M)
obj1.data.update()
$\endgroup$
1
  • $\begingroup$ Thank you very much. $\endgroup$
    – blablaalb
    Commented Nov 14, 2019 at 13:08

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .