10
$\begingroup$

Is there a way to change the origin of an object to an arbitrary point (via scripting) without using the operator origin_set()? I.e., isn't there a method or property on the object to do this?

I know I can do it like this:

bpy.context.scene.cursor_location = pt
bpy.ops.object.origin_set(type='ORIGIN_CURSOR')

but this can get tedious, e.g., if I have other objects selected.

$\endgroup$

2 Answers 2

10
$\begingroup$

you could do something like this in Edit mode.

obj.data.transform(mathutils.Matrix.Translation(-new_origin))
obj.location += new_origin

I use it in this addon which sets the origin to the selected vertex, or median.


or as CoDEmanX points out

obj.data.transform(mathutils.Matrix.Translation(-new_origin))
obj.matrix_world.translation += new_origin
$\endgroup$
7
  • 4
    $\begingroup$ Note that transform() does nothing in Edit Mode (you could conditional use the bmesh module to translate the edit mesh). You might wanna use obj.matrix_world.translation += new_origin instead of .location. Not sure what you concern is about local coordinate @zeffii? $\endgroup$
    – CodeManX
    Commented Aug 16, 2015 at 19:11
  • $\begingroup$ @CoDEmanX tell me why not .location ? $\endgroup$
    – zeffii
    Commented Aug 16, 2015 at 19:21
  • 3
    $\begingroup$ Because it's not always the final location IIRC (parenting, drivers etc. might cause it to differ from the final matrix' translation). $\endgroup$
    – CodeManX
    Commented Aug 16, 2015 at 19:23
  • $\begingroup$ I wish I could give @CoDEmanX an additional check mark. It sounds like this .location vs. .matrix_world issue could answer another problem I recently ran across. $\endgroup$
    – Jabberwock
    Commented Aug 25, 2015 at 16:53
  • $\begingroup$ Run Zeffi's answer in Object Mode, otherwise the transform action will be ignored and you'll just end up moving the origin and the geometry data. Tested successfully in Blender 2.83. $\endgroup$
    – Prime007
    Commented Sep 19, 2020 at 7:05
6
$\begingroup$

Transform origin locally and object globally

To set the origin of an objects mesh to the global location of the scene cursor while maintaining the global location of the vertices, calculate the local coordinate of cursor, transform the mesh by subtracting it from all vert coordinates.

Then move the object back by the vector difference of starting global location (matrix world translation) and cursor location.

Test script: run in object mode.

import bpy
from mathutils import Matrix

context = bpy.context
scene = context.scene
ob = context.object
mw = ob.matrix_world
imw = mw.inverted()
me = ob.data

origin = scene.cursor.location
local_origin = imw @ origin
me.transform(Matrix.Translation(-local_origin))
mw.translation += (origin - mw.translation)

Note this will however move other objects that share the mesh.

For an edit mode version see

Setting mesh's origin in python (2.8)

$\endgroup$
4
  • $\begingroup$ Nice! Can your code be modified to resposition the origin along the object's local axes while leaving the mesh in place relative to the world? To move an object's origin 3.0 local Z (-3.0 relative to the mesh data) I modified a line of your code to: me.transform(Matrix.Translation( (0.0, 0.0, -3.0) )) but the object moves as well, and I don't know how to counter that offset. $\endgroup$
    – Mentalist
    Commented Dec 22, 2020 at 4:15
  • $\begingroup$ Make the global location that of the local coord now the origin. ob.matrix_world.translation = mw @ Vector((0, 0, -3)) ( Which is what last line above is doing.) $\endgroup$
    – batFINGER
    Commented Dec 22, 2020 at 4:19
  • 2
    $\begingroup$ Thank you! With that knowledge I was able to get it working. Here's the full script for anyone who wants it: import bpy from mathutils import Matrix from mathutils import Vector context = bpy.context scene = context.scene ob = context.object mw = ob.matrix_world imw = mw.inverted() me = ob.data offset = Vector((0, 0, 3)) me.transform(Matrix.Translation( -offset )) ob.matrix_world.translation = mw @ offset $\endgroup$
    – Mentalist
    Commented Dec 22, 2020 at 7:45
  • $\begingroup$ the problem this is not taking into account rotation and with the option parent_only option I don't find how to do it $\endgroup$
    – FkNWO
    Commented Nov 29, 2021 at 0:32

You must log in to answer this question.

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