В ряде случаев бывает необходимо определить, виден ли в данный момент определенный объект в окне 3D вьюпорта в Blender, или – нет. В общем случае определить видимость объекта во вьюпорте можно при помощи функции location_3d_to_region_2d из модуля view3d_utils.
Для начала получим рабочую область вьюпорта, пробежав в цикле по всем открытым в Blender в данный момент рабочим областям:
1 2 |
for area in bpy.context.screen.areas: if area.type == 'VIEW_3D': |
Для вызова функции location_3d_to_region_2d нам нужно получить ссылку на 3D регион рабочей области вьюпорта.
1 |
region_3d = area.spaces[0].region_3d |
Кроме 3D региона, рабочая область сама по себе разбита на несколько отдельных регионов:
- HEADER – регион заголовка рабочей области, в нем размещается меню
- TOOL_HEADER – регион инструментов заголовка. Здесь размещаются кнопки выбора режима выделения и меню Options
- TOOLS – регион с панелью инструментов (Т – панель)
- UI – регион для интерфейса пользователя (N – панель)
- HUD – регион для динамических панелей
- WINDOW – основной регион окна вьюпорта.
Нам нужно получить указатель на регион WINDOW:
1 2 |
for region in area.regions: if region.type == 'WINDOW': |
Теперь, имея указатели на два типа регионов вьюпорта, мы можем вызвать функцию location_3d_to_region_2d, передав ей в параметрах эти указатели на регионы.
Функция location_3d_to_region_2d проецирует точку из сцены на экран вьюпорта. Иными словами – по координатам точки в трехмерном пространстве сцены функция высчитывает 2d координаты этой точки на экране.
Координаты центральной точки (origin) текущего активного объекта передадим в функцию третьим параметром.
1 2 3 4 5 |
origin_2d = view3d_utils.location_3d_to_region_2d( region, region_3d, bpy.context.object.location ) |
В результате мы получили координаты точки на плоскости вьюпорта.
Теперь мы можем проверить – если точка попадает в границы рабочей области 3D вьюпорта, значит объект виден во вьюпорте, а если выходит за границы – не виден.
1 2 3 4 5 6 |
if 0 <= origin_2d.x <= area.width and 0 <= origin_2d.y <= area.height: print(bpy.context.object, 'Visible') else: print(bpy.context.object, 'Not visible') # <bpy_struct, Object("Suzanne") at 0x000002C884027908> Visible |
Полный код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
for area in bpy.context.screen.areas: if area.type == 'VIEW_3D': region_3d = area.spaces[0].region_3d for region in area.regions: if region.type == 'WINDOW': origin_2d = view3d_utils.location_3d_to_region_2d( region, region_3d, bpy.context.object.location ) if 0 <= origin_2d.x <= area.width and 0 <= origin_2d.y <= area.height: print(bpy.context.object, 'Visible') else: print(bpy.context.object, 'Not visible') |