Created
November 26, 2021 19:45
-
-
Save hariedo/adefafa70311874a6de135729fe9e64d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# 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