Utility_Apps/Blender/simple scripts/Move origin to the lowest or highest in the XYZ/Move origin to the lowest or highest in the XYZ.py
2025-07-11 08:27:54 -05:00

48 lines
1.7 KiB
Python

import bpy
from mathutils import Vector
def move_origin_to_bbox_edge_keep_world_position(obj, axis='Z', direction='lowest'):
if obj.type != 'MESH':
return
axis = axis.upper()
if axis not in {'X', 'Y', 'Z'}:
raise ValueError("Axis must be 'X', 'Y', or 'Z'")
if direction not in {'lowest', 'highest'}:
raise ValueError("Direction must be 'lowest' or 'highest'")
axis_index = {'X': 0, 'Y': 1, 'Z': 2}[axis]
# Apply scale to get accurate bounding box
bpy.context.view_layer.objects.active = obj
bpy.ops.object.transform_apply(location=False, rotation=False, scale=True)
# Get the bounding box in local space
bbox = [Vector(corner) for corner in obj.bound_box]
values = [v[axis_index] for v in bbox]
edge_value = min(values) if direction == 'lowest' else max(values)
# Determine how much to shift the mesh in local space
shift = Vector((0.0, 0.0, 0.0))
shift[axis_index] = -edge_value
# Move all vertices by shift to keep mesh visually in place
for v in obj.data.vertices:
v.co += shift
# Move the object origin to new location in world space
# This is the *world* location where the original origin was + offset
origin_offset_local = Vector((0.0, 0.0, 0.0))
origin_offset_local[axis_index] = edge_value
origin_offset_world = obj.matrix_world.to_3x3() @ origin_offset_local # respect rotation/scale
# Adjust origin without moving the mesh
obj.location += origin_offset_world
# --- USER SETTINGS ---
AXIS = 'Z' # 'X', 'Y', or 'Z'
DIRECTION = 'lowest' # 'lowest' or 'highest'
# Run on all selected mesh objects
for obj in bpy.context.selected_objects:
move_origin_to_bbox_edge_keep_world_position(obj, axis=AXIS, direction=DIRECTION)