0
$\begingroup$

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.

$\endgroup$
0
$\begingroup$

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

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.