"Copy to selected" copies the complete location X, Y and Z to all the selected objects. I wish to copy only Z location. Please see the images bellow to get idea of what I intend to achieve.
Before
After
Blender Stack Exchange is a question and answer site for people who use Blender to create 3D graphics, animations, or games. It only takes a minute to sign up.
Sign up to join this community"Copy to selected" copies the complete location X, Y and Z to all the selected objects. I wish to copy only Z location. Please see the images bellow to get idea of what I intend to achieve.
Before
After
You can also try another way:
Thanks to Bastien Montagne (aka mont29)'s commit, you can find this feature in latest version, now only for Location, but also Rotation, Scale, Dimensions, etc:
The position of the object is defined by it's origin point, but you can't always assume that the origin is centered when selecting multiple and more complex objects than a cube.
That the origins are prefectly centered is a special case, because of the different dimensions or diffenrent kinds of geometry. In this case the result of the test scene above would look like:
One way to get around this is to calculate the object position differences of the meshes and move the objects by adding or subtracting this differences in the axis from the current locations of the objects.
For this case I wrote a small addon to align multiple objects to the geometry of the active one. The script calculates the dimensions of every object that is selected and move the objects to the right spot, independent of the origin's position.
Align objects to the second suzanne
bl_info = {
"name": "Align Geometry",
"description": "",
"author": "poor",
"version": (0, 0, 1),
"blender": (2, 73, 0),
"location": "Tool Shelf > Tools",
"warning": "",
"wiki_url": "",
"tracker_url": "",
"category": "3D View"
}
import bpy
from bpy.props import (EnumProperty,
PointerProperty,
)
from bpy.types import (Panel,
Operator,
AddonPreferences,
PropertyGroup,
)
# ------------------------------------------------------------------------
# logic
# ------------------------------------------------------------------------
# get x,y,z min or max of geometry
def get_geo_min_max(obj, axis):
axis_coords = []
# iterate through all vertices
for face in obj.data.polygons:
verts_in_face = face.vertices[:]
for vert in verts_in_face:
local_point = obj.data.vertices[vert].co
world_point = obj.matrix_world * local_point
axis_coords.append(world_point[axis])
# return the geometry minimum and maximum
return min(axis_coords), max(axis_coords)
# align objects to min or max of the reference object
def align_objects_to_min_or_max_of_reference_object(ob_reference, mesh_ob_transform_list, align_axis, extreme_point):
for i in mesh_ob_transform_list:
# get the difference of obj maximums
if extreme_point == "MAX":
diff = abs(get_geo_min_max(ob_reference, align_axis)[1] - get_geo_min_max(i, align_axis)[1])
# get the difference of obj minimums
if extreme_point == "MIN":
diff = abs(get_geo_min_max(ob_reference, align_axis)[0] - get_geo_min_max(i, align_axis)[0])
# if current position is higher the reference
if get_geo_min_max(ob_reference, align_axis)[0] > get_geo_min_max(i, align_axis)[0]:
i.location[align_axis] += diff
# if current position is same the reference
if get_geo_min_max(ob_reference, align_axis)[0] == get_geo_min_max(i, align_axis)[0]:
i.location[align_axis] -= diff
# if current position is below the reference
if get_geo_min_max(ob_reference, align_axis)[0] < get_geo_min_max(i, align_axis)[0]:
i.location[align_axis] -= diff
# align objects to the center of the reference object
def align_objects_to_center_of_reference_object(ob_reference, mesh_ob_transform_list, align_axis):
# get extreme points of reference
ob_ref_extremes = get_geo_min_max(ob_reference, align_axis)
# calculate axis center
ob_ref_axis_center = ob_ref_extremes[0] + (0.5 * (ob_ref_extremes[1] - ob_ref_extremes[0]))
for i in mesh_ob_transform_list:
# get extreme points of i
i_extremes = get_geo_min_max(i, align_axis)
# calculate center
i_axis_center = i_extremes[0] + (0.5 * (i_extremes[1] - i_extremes[0]))
# calculate difference
diff = abs(ob_ref_axis_center - i_axis_center)
# if current position is above the reference
if ob_ref_axis_center > i_axis_center:
i.location[align_axis] += diff
# if current position is same as reference
if ob_ref_axis_center == i_axis_center:
i.location[align_axis] += diff
# if current position is below as reference
if ob_ref_axis_center < i_axis_center:
i.location[align_axis] -= diff
# ------------------------------------------------------------------------
# ui
# ------------------------------------------------------------------------
def axisStringToInt(axis_str):
axes = {
'X': 0,
'Y': 1,
'Z': 2
}
return axes[axis_str]
class GeometryAlignSettings(PropertyGroup):
axes = [
('X', "X Axis", ""),
('Y', "Y Axis", ""),
('Z', "Z Axis", ""),
]
transform = EnumProperty(
name="Transformation Axes:",
description="Apply transformation to",
items=axes
)
class OBJECT_PT_geometry_align_panel(Panel):
bl_idname = "OBJECT_PT_geometry_align_panel"
bl_label = "Align Geometry"
bl_space_type = "VIEW_3D"
bl_region_type = "TOOLS"
bl_category = "Tools"
bl_context = "objectmode"
def draw(self, context):
layout = self.layout
scene = context.scene
active_obj = context.active_object
col = layout.column(align=True)
col.prop(scene.geometry_align, "transform", text="")
row = col.row(align=True)
row.operator("geometryalign.to_max_geo", icon="ZOOMIN")
row.operator("geometryalign.to_min_geo", icon="ZOOMOUT")
row = col.row(align=True)
row.operator("geometryalign.to_center_geo", icon="CURSOR")
if active_obj != None:
if active_obj.type == "MESH" and active_obj != None:
layout.label( "Snap to " + active_obj.name )
else:
layout.label( "No active mesh" )
class OBJECT_OT_AlignMaxButton(bpy.types.Operator):
bl_idname = "geometryalign.to_max_geo"
bl_label = "Maximum"
bl_description = "Align objects to maximum of active object"
#bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
scn = context.scene # get the scene
objs = bpy.context.selected_objects # get selected objects
mesh_objs = [m for m in objs if m.type == "MESH"] # get all mesh objects in selection
active_obj = scn.objects.active # get active object
if active_obj != None: # error handling
if active_obj.type == "MESH":
axis = axisStringToInt(scn.geometry_align.transform) # set transform axis: x=0, y=1, z=2
align_objects_to_min_or_max_of_reference_object (active_obj, mesh_objs, axis, 'MAX')
else:
self.report({'INFO'}, "%s is not a mesh object" % (active_obj.name))
return{'FINISHED'}
class OBJECT_OT_AlignMinButton(bpy.types.Operator):
bl_idname = "geometryalign.to_min_geo"
bl_label = "Minimum"
bl_description = "Align objects to minimum of active object"
#bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
scn = context.scene # get the scene
objs = bpy.context.selected_objects # get selected objects
mesh_objs = [m for m in objs if m.type == "MESH"] # get all mesh objects in selection
active_obj = scn.objects.active # get active object
if active_obj != None: # error handling
if active_obj.type == "MESH":
axis = axisStringToInt(scn.geometry_align.transform) # set transform axis: x=0, y=1, z=2
align_objects_to_min_or_max_of_reference_object (active_obj, mesh_objs, axis, 'MIN')
else:
self.report({'INFO'}, "%s is not a mesh object" % (active_obj.name))
return{'FINISHED'}
class OBJECT_OT_AlignCenterButton(bpy.types.Operator):
bl_idname = "geometryalign.to_center_geo"
bl_label = "Center"
bl_description = "Align objects to center of active object"
#bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
scn = context.scene # get the scene
objs = bpy.context.selected_objects # get selected objects
mesh_objs = [m for m in objs if m.type == "MESH"] # get all mesh objects in selection
active_obj = scn.objects.active # get active object
if active_obj != None: # error handling
if active_obj.type == "MESH":
axis = axisStringToInt(scn.geometry_align.transform) # set transform axis: x=0, y=1, z=2
align_objects_to_center_of_reference_object (active_obj, mesh_objs, axis)
else:
self.report({'INFO'}, "%s is not a mesh object" % (active_obj.name))
return{'FINISHED'}
# ------------------------------------------------------------------------
# register and unregister functions
# ------------------------------------------------------------------------
def register():
bpy.utils.register_module(__name__)
bpy.types.Scene.geometry_align = PointerProperty(type=GeometryAlignSettings)
def unregister():
bpy.utils.unregister_module(__name__)
del bpy.types.Scene.geometry_align
if __name__ == "__main__":
register()
Ctrl Shift Alt C
> Origin to geometry (or whatever centering method you like).
$\endgroup$
– gandalf3♦
Feb 10 '15 at 5:31