8
$\begingroup$

Read through a lot of questions but I didn't find a simple answer.

How do I move an object on it's local axis using a vector? I don't want to use bpy.ops.transform.translate, because it's slow.

Given an object that is rotated and an example vector (1,2,3). How can I do a translation on the local axis, so the object is moved 1 on it's local x-axis, 2 on the local y-axis, 3 on the local z-axis. Just like in the viewport, when you move an object pressing "g" and then pressing the x-axis key (or y / z) twice.

EDIT: So from a C++ post I understand the math behind it, still I'm unable to reproduce it in Blender. For the local translation T you have to do the translation first, then multiply it with the rotation matrix R. So (pseudocode)

myobject.location = T(1,2,3) * R

Problems: 1.) How do I get R of the object that is already rotated. 2.) Can I just multiply a vector with that matrix? 3.) What about the location that the object had before? Just add it?

$\endgroup$
5
$\begingroup$

This seems to work the inverse of the world matrix is used to align the translation vector to the local axis:

import bpy
import mathutils

cube = bpy.data.objects["Cube"]
# one blender unit in x-direction
vec = mathutils.Vector((1.0, 0.0, 0.0))
inv = cube.matrix_world.copy()
inv.invert()
# vec aligned to local axis
vec_rot = vec * inv
cube.location = cube.location + vec_rot
$\endgroup$
  • $\begingroup$ Thanks you Sir! For completeness, this works also in a condensed form: cube.location += vec * inv. $\endgroup$ – bortran Mar 9 '15 at 11:02
  • 1
    $\begingroup$ This fails if the object is scaled. Using cube.rotation_euler.to_matrix() as invmatrix seems to be better $\endgroup$ – florian h Oct 3 '18 at 16:34
5
$\begingroup$

In order to make it faster you could also assign the values directly to the location property:

import bpy
import mathutils

# get the object
obj = bpy.data.objects["Object"]

# store the current location
loc = obj.location

# adjustment values
(x,y,z) = (1.0,2.0,3.0)

# adding adjustment values to the property
obj.location = loc + mathutils.Vector((x,y,z))

Assigning and adding the values in one line:

bpy.data.objects["Object"].location = bpy.data.objects['Object'].location + Vector((x,y,z))

Simple and fast is adding the adjustment values to each axis:

bpy.data.objects["Object"].location.x += 1.0
bpy.data.objects["Object"].location.y += 2.0
bpy.data.objects["Object"].location.z += 3.0
$\endgroup$
  • 3
    $\begingroup$ But that's a global translation. $\endgroup$ – bortran Mar 9 '15 at 9:05
  • $\begingroup$ It's not a global translation. An object with ob.location = (0, 0, 0) can be placed anywhere in the scene using constraints or parenting. There is only one global origin. $\endgroup$ – batFINGER Nov 15 at 11:41
1
$\begingroup$

So I made this now, but I don't know if it's correct.

import bpy
import mathutils
from mathutils import Vector, Matrix

myobject = bpy.context.active_object
rotMat = myobject.rotation_euler.to_matrix()
pos = myobject.location
newPos = Vector([1, 2, 3])
myobject.location = newPos * rotMat + pos
$\endgroup$
0
$\begingroup$

Try this blender 2.8 script to displace all cylinders in a scene, with respect to their axis in the -ve Z direction:

        if obj.name.startswith('Cylinder'):

      # print(obj.location)

      # one blender unit in x-direction
        distz = mathutils.Vector((0.0, 0.0, -0.001))
        rotationMAT = obj.rotation_euler.to_matrix()
        rotationMAT.invert()
        # project the vector to the world using the rotation matrix
        zVector = distz @ rotationMAT
        obj.location = obj.location + zVector
$\endgroup$

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.