Try this.
How to perform at low level
import bpy
from mathutils import Matrix, Vector
def set_mesh_origin(ob, pos):
'''Given a mesh object, set its origin to a given position.'''
# Create a translation matrix from the position
mat = Matrix.Translation(pos - ob.location)
# Update the object's location
ob.location = pos
# Transform the object's data using the inverse of the translation matrix
ob.data.transform(mat.inverted())
ob.data.update()
for obj in bpy.context.selected_objects:
# Check if the object is a mesh
if obj.type == 'MESH':
# Get the local coordinates of vertex 1
vloc_local = obj.data.vertices[1].co
# Convert local coordinates to world coordinates
vloc_world = obj.matrix_world @ vloc_local
# Set the object's origin to the world coordinates
set_mesh_origin(obj, vloc_world)
![enter image description here](https://cdn.statically.io/img/i.sstatic.net/65GyH7LB.gif)
As james_t said, avoiding the use of OPS as much as possible and running the API at a low level provides stability in scripting.
This script is originally a method to move to world coordinates,
The application used it as it is in the function.
The function is executed after converting the local coordinates of vertex 1 to world coordinates in a FOR loop.
Reference URL
https://blenderartists.org/t/modifying-object-origin-with-python/507305/7?u=makorin
Extra snooping
If you want to make the position of the bottom vertex of an object the origin, you can use the script below.
import bpy
from mathutils import Matrix, Vector
def set_mesh_origin(ob, pos):
'''Given a mesh object, set its origin to a given position.'''
# Create a translation matrix from the position
mat = Matrix.Translation(pos - ob.location)
# Update the object's location
ob.location = pos
# Transform the object's data using the inverse of the translation matrix
ob.data.transform(mat.inverted())
ob.data.update()
def get_lowest_z_vertex(obj):
'''Find the vertex with the lowest Z value in the given object.'''
lowest_vertex = None
lowest_z = float('inf') # Initialize to positive infinity
# Iterate through the vertices to find the lowest Z
for vertex in obj.data.vertices:
# Convert local vertex coordinates to world coordinates
world_coord = obj.matrix_world @ vertex.co
if world_coord.z < lowest_z:
lowest_z = world_coord.z
lowest_vertex = world_coord
return lowest_vertex
for obj in bpy.context.selected_objects:
# Check if the object is a mesh
if obj.type == 'MESH':
# Find the vertex with the lowest Z value
lowest_vertex = get_lowest_z_vertex(obj)
if lowest_vertex:
# Set the object's origin to the lowest vertex's world coordinates
set_mesh_origin(obj, lowest_vertex)
![enter image description here](https://cdn.statically.io/img/i.sstatic.net/GVhui3QE.gif)
Objects do not take rotation into account, so prior apply of rotation is required
![enter image description here](https://cdn.statically.io/img/i.sstatic.net/2P5Q4tM6.png)