5
$\begingroup$

(This is just a basic example). I want to translate, then rotate and then translate again (in local).

At the moment I have this:

import bpy 
import  mathutils

object = bpy.data.objects["Cube"]


# translate
translation = mathutils.Vector((5.0, 0.0, 0.0))

inv = object.matrix_world.copy()
inv.invert()
vec_rot = translation * inv
object.location = object.location + vec_rot

# rotate
euler = mathutils.Euler((0.0, 0.0, 45.0))
object.rotation_euler.rotate(euler)


# translate again
translation = mathutils.Vector((5.0, 0.0, 0.0))

inv = object.matrix_world.copy()
inv.invert()
vec_rot = translation * inv
object.location = object.location + vec_rot

The problem is that this works as the 2 translates combined followed by the rotate. What I expect is to have the object first move in the x, then rotate, and then move in it's rotated direction.

How can I do this?

$\endgroup$
3
+50
$\begingroup$

Can also obtain the equivalent of keystrokes gxx5 rzz45 gxx5, (ie local transform on x by 5, rotate on z by 45 degrees, local transform again by 5), by creating transform and rotation matrices, and chaining them together via matrix multiplication in the order wanted.

import bpy
from mathutils import Matrix
from math import radians

# Translation matrices
T0 = T1 = Matrix.Translation((5, 0, 0))

# Rotation matrix
R0 = Matrix.Rotation(radians(45), 4, 'Z')

obj = bpy.context.object

#  
M = T0 * R0 * T1

obj.matrix_world = M * obj.matrix_world
| improve this answer | |
$\endgroup$
3
$\begingroup$

enter image description here

What you're missing is a scene update before the 2nd translation. It will recalculate the local matrix before applying the 2nd translation and thus leads to the result you're aiming for:

import bpy 
import  mathutils

object = bpy.data.objects["Cube"]


# translate
translation = mathutils.Vector((5.0, 0.0, 0.0))

inv = object.matrix_world.copy()
inv.invert()
vec_rot = translation * inv
object.location = object.location + vec_rot

# rotate
euler = mathutils.Euler((0.0, 0.0, 45.0))
object.rotation_euler.rotate(euler)

###### SCENE UPDATE ######    
bpy.context.scene.update()
##########################

# translate again
translation = mathutils.Vector((5.0, 0.0, 0.0))

inv = object.matrix_world.copy()
inv.invert()
vec_rot = translation * inv
object.location = object.location + vec_rot
| improve this answer | |
$\endgroup$
  • $\begingroup$ Is it possible to only update a certain part of the scene? $\endgroup$ – clankill3r May 1 '17 at 12:51
  • $\begingroup$ @clankill3r I tried several object / mesh related update methods and none worked. So far seems like the only way as far as I'm aware. $\endgroup$ – TLousky May 1 '17 at 14:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.