1

Today I'm playing with models downloaded from Thingverse. Some of these models have many parts. When I load all the parts into Blender and arrange them in some way, I would like to be able to select them and get the size of the bounding box that surrounds all of them. I could probably whip something up in Python, but surely Blender has a built-in method?

This is a duplicate of Properties of a selection of objects but that question is six years old and perhaps something has changed since then.

Ron Jensen
  • 3,421
  • 1
  • 9
  • 27

1 Answers1

4

User @sambler provided a script on the linked question, but I found it had bit-rotted in the change to Blender 2.8/2.9

This version worked for me under Blender 2.9.2:

import bpy
import bmesh
from bpy.props import BoolProperty, FloatVectorProperty
import mathutils
from bpy_extras import object_utils

from blender templates

def add_box(width, height, depth): """ This function takes inputs and returns vertex and face arrays. no actual mesh data creation is done here. """

verts = [(+1.0, +1.0, -1.0),
         (+1.0, -1.0, -1.0),
         (-1.0, -1.0, -1.0),
         (-1.0, +1.0, -1.0),
         (+1.0, +1.0, +1.0),
         (+1.0, -1.0, +1.0),
         (-1.0, -1.0, +1.0),
         (-1.0, +1.0, +1.0),
         ]

faces = [(0, 1, 2, 3),
         (4, 7, 6, 5),
         (0, 4, 5, 1),
         (1, 5, 6, 2),
         (2, 6, 7, 3),
         (4, 0, 3, 7),
        ]

# apply size
for i, v in enumerate(verts):
    verts[i] = v[0] * width, v[1] * depth, v[2] * height

return verts, faces

def group_bounding_box(): minx, miny, minz = (999999.0,)3 maxx, maxy, maxz = (-999999.0,)3 location = [0.0,]*3 for obj in bpy.context.selected_objects: for v in obj.bound_box: v_world = obj.matrix_world @ mathutils.Vector((v[0],v[1],v[2]))

        if v_world[0] < minx:
            minx = v_world[0]
        if v_world[0] > maxx:
            maxx = v_world[0]

        if v_world[1] < miny:
            miny = v_world[1]
        if v_world[1] > maxy:
            maxy = v_world[1]

        if v_world[2] < minz:
            minz = v_world[2]
        if v_world[2] > maxz:
            maxz = v_world[2]

verts_loc, faces = add_box((maxx-minx)/2, (maxz-minz)/2, (maxy-miny)/2)
mesh = bpy.data.meshes.new("BoundingBox")
bm = bmesh.new()
for v_co in verts_loc:
    bm.verts.new(v_co)

bm.verts.ensure_lookup_table()

for f_idx in faces:
    bm.faces.new([bm.verts[i] for i in f_idx])

bm.to_mesh(mesh)
mesh.update()
location[0] = minx+((maxx-minx)/2)
location[1] = miny+((maxy-miny)/2)
location[2] = minz+((maxz-minz)/2)
bbox = object_utils.object_data_add(bpy.context, mesh, operator=None)
# does a bounding box need to display more than the bounds??
bbox.location = location
bbox.display_type = 'BOUNDS'
bbox.hide_render = True

group_bounding_box()

something

Ron Jensen
  • 3,421
  • 1
  • 9
  • 27
  • 1
    See https://blender.stackexchange.com/a/218849/15543 can add a cube display type empty instead of an non rendering wire display type mesh. – batFINGER Sep 19 '21 at 18:43
  • Can this script calculate objects AABB under specific collection? – P. Scotty Jul 05 '22 at 01:51
  • @WinertozBotawar I don't quite understand your question? If I remember correctly, this script works on all selected objects so if you select all objects under a specific collection it should work? – Ron Jensen Jul 06 '22 at 16:45
  • Yes it works. Just need to select all objects under a collection. – P. Scotty Jul 12 '22 at 12:28