48 lines
1.7 KiB
Python
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)
|