Skip to content

Instantly share code, notes, and snippets.

@hariedo
Created November 26, 2021 19:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hariedo/adefafa70311874a6de135729fe9e64d to your computer and use it in GitHub Desktop.
Save hariedo/adefafa70311874a6de135729fe9e64d to your computer and use it in GitHub Desktop.
#
# Object > Set Mesh Origin to Bottom
# A python script compatible with Blender 2.90 API.
#
# Takes the currently selected mesh-type objects,
# and moves the object origin location to the "bottom" of the mesh.
# The bottom is calculated as the average X and Y and the minimum Z.
#
# This is useful in 3D Printing, for example, when importing published
# STL geometry files. Typically the bottom of the shape is flat and
# meant to align to the build plate. The center of many published
# files is offset to random position that was convenient to the
# designer, in whatever software they used to export STL data.
#
bl_info = {
"name": "Set Mesh Origin to Bottom",
"category": "Object",
"blender": (2, 90, 0),
}
import bpy
import mathutils
from mathutils import Vector
class ObjectSetMeshOriginToBottom(bpy.types.Operator):
"""Realigns Object's Origin to Mesh's Average X, Y and Minimum Z.""" # tooltip
bl_idname = "object.set_mesh_origin_to_bottom" # unique identifier
bl_label = "Set Mesh Origin to Bottom" # display name
bl_options = {'REGISTER', 'UNDO'} # enable undo
def execute(self, context):
Z = bpy.context.scene.cursor.location
for ob in context.selected_objects:
if ob.type == "MESH":
self.execute_per_mesh(context, ob)
bpy.context.scene.cursor.location = Z
return {'FINISHED'} # success
def execute_per_mesh(self, context, ob):
V = ob.data.vertices
if not len(V):
return
Px = sum(v.co.x for v in V) / len(V)
Py = sum(v.co.y for v in V) / len(V)
Pz = min(v.co.z for v in V)
P = ob.matrix_world @ Vector((Px, Py, Pz))
context.scene.cursor.location = P
M = ob.mode
if M == "EDIT":
bpy.ops.object.editmode_toggle()
bpy.ops.object.origin_set(type='ORIGIN_CURSOR', center='MEDIAN')
if M == "EDIT":
bpy.ops.object.editmode_toggle()
def menu_func(self, context):
# blender 2.90+ will hide registered operators unless they are added to a menu
self.layout.operator(ObjectSetMeshOriginToBottom.bl_idname)
def register():
bpy.utils.register_class(ObjectSetMeshOriginToBottom)
bpy.types.VIEW3D_MT_object.append(menu_func)
def unregister():
bpy.utils.unregister_class(ObjectSetMeshOriginToBottom)
# run the script directly from blenders text editor
# to test the addon without having to install it
#
if __name__ == "__main__":
register()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment