In some cases, it may be necessary to determine whether a certain object is currently visible in the 3D viewport area in Blender or not. We can determine the visibility of an object in a viewport with the Blender Python API using the location_3d_to_region_2d function of the view3d_utils module.
First, we need to get the area of the 3D viewport by looping through all currently opened in Blender areas:
1 2 |
for area in bpy.context.screen.areas: if area.type == 'VIEW_3D': |
To call the location_3d_to_region_2d function, we need to get a pointer to the 3D region of the viewport area.
1 |
region_3d = area.spaces[0].region_3d |
In addition to the 3D region, the workspace itself is divided into several separate regions:
- HEADER – area menu region,
- TOOL_HEADER – tools header region. Here are the buttons for changing the selection mode and the Options menu,
- TOOLS – region with tools toolbar (Т – panel),
- UI – region for user interface (N – panel),
- HUD – region for floating panels,
- WINDOW – main 3D viewport region.
We need to get a pointer to the WINDOW region:
1 2 |
for region in area.regions: if region.type == 'WINDOW': |
Now, having pointers to two required regions of the viewport, we can call the location_3d_to_region_2d function, passing these pointers as parameters.
The location_3d_to_region_2d function projects a point from the scene onto the viewport screen. In other words, from the coordinates of a point in the three-dimensional space of the scene, this function calculates the two-dimensional coordinates of this point on the screen.
The coordinates of the central point (origin) of the currently active object we will pass to the function as the third parameter.
1 2 3 4 5 |
origin_2d = view3d_utils.location_3d_to_region_2d( region, region_3d, bpy.context.object.location ) |
In a result, we got the coordinates of a point on the viewport screen.
Now we can check, if the point falls within the boundaries of the 3D viewport area, then the object is visible in the viewport, and if it goes beyond the boundaries – it is not visible.
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 |
Full code:
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') |