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

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


you could do something like this in Edit mode.

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.matrix_world.translation += new_origin
  • 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 Aug 16 '15 at 19:11
  • $\begingroup$ @CoDEmanX tell me why not .location ? $\endgroup$ – zeffii Aug 16 '15 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 Aug 16 '15 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 Aug 25 '15 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 Sep 19 '20 at 7:05

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
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)

  • $\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 Dec 22 '20 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 Dec 22 '20 at 4:19
  • $\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 Dec 22 '20 at 7:45

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.