Bounding Box – это прямоугольный параллелепипед, описанный вокруг всех точек меша. Обычно Bounding Box используется для
упрощенного просчета физического взаимодействия объектов, например, столкновений.
Для каждого меша в сцене Bounding Box рассчитывается автоматически, и пересчитывается при каждом изменении меша.
Получить координаты всех углов Bounding Box для любого объекта можно через его свойство bound_box, которое представляет собой массив bpy_prop_array с набором координат. Каждый элемент массива bound_box в свою очередь представляет собой массив из трех координат точки:
1 2 3 |
[bbox_co[:] for bbox_co in bpy.context.object.bound_box[:]] # [(-1.328185796737671, -0.8224414587020874, -0.9786988496780396), (-1.328185796737671, -0.8224414587020874, 0.9557293057441711), ...] |
Координаты Bounding Box объекта считаются в его локальной системе координат. Чтобы получить глобальные координаты Bounding Box (в системе координат сцены) нужно ее локальные координаты умножить на матрицу мира объекта.
1 2 3 |
[bpy.context.object.matrix_world @ Vector(bbox_co[:]) for bbox_co in bpy.context.object.bound_box[:]] # [Vector((-0.8632605671882629, -0.7490095496177673, 0.94121915102005)), Vector((-0.8632605671882629, ... ] |
Также следует учитывать, что Bounding Box рассчитывается для базового объекта, т.е. получаемые координаты зависят, например, от того, включены ли модификаторы в стеке объекта или нет.
Для того, чтобы получить финальные координаты Bounding Box нужно использовать рассчитанный evaluated меш. Получить рассчитанный объект из текущего можно при помощи Depsgraph:
1 2 |
depsgraph = bpy.context.evaluated_depsgraph_get() object_evaluated = bpy.context.object.evaluated_get(depsgraph) |
Теперь мы можем получить финальные координаты углов Bounding Box:
1 2 3 |
[bpy.context.object.matrix_world @ Vector(bbox_co[:]) for bbox_co in object_evaluated.bound_box[:]] # [Vector((0.14480701088905334, 1.7784899473190308, 1.9723942279815674)), Vector((0.7954444885253906, ... ] |
Для примера поставим в каждый угол Bounding Box объекта пустышку. Пройдясь по списку финальных координат углов Bounding Box, создадим для каждого из них пустышку и поместим в координаты угла:
1 2 3 4 5 6 7 8 9 |
for co in bbox_cos_global: empty = bpy.data.objects.new( name='empty', object_data=None ) bpy.context.scene.collection.objects.link( object=empty ) empty.location = co |
Весь код целиком:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import bpy from mathutils import Vector depsgraph = bpy.context.evaluated_depsgraph_get() object_evaluated = bpy.context.object.evaluated_get(depsgraph) bbox_cos_local = [bbox_co[:] for bbox_co in object_evaluated.bound_box[:]] bbox_cos_global = [bpy.context.object.matrix_world @ Vector(bbox_co) for bbox_co in bbox_cos_local] for co in bbox_cos_global: empty = bpy.data.objects.new( name='empty', object_data=None ) bpy.context.scene.collection.objects.link( object=empty ) empty.location = co |
*.blend и *.py файлы с примером для моих подписчиков на Patreon.