7
$\begingroup$

I'd like to select only the visible vertices (from the camera), using python interface.

I use bpy.types.SpaceView3D.use_occlude_geometry = True to limit the selection, but when it is followed by bpy.ops.object.select_all(action='SELECT'), it results in all mesh vertices being selected and not only the visible ones.

I probably don't understand how to use the bpy.types.SpaceView3D.use_occlude_geometry or the selection operator correctly - will appreciate your help with it.

Anastasia

$\endgroup$
2
  • 1
    $\begingroup$ Related blender.stackexchange.com/a/40826/15543 $\endgroup$
    – batFINGER
    Oct 4, 2016 at 16:34
  • $\begingroup$ Thanks, @batFINGER, it's related but I need to do everything via Python API. Is there any way to replace the manual vertex selection by a set of python commands? Thanks! $\endgroup$
    – Anastasia
    Oct 4, 2016 at 19:39

1 Answer 1

12
$\begingroup$

First of all, as for the select_all behavior, that is by design.
Calling bpy.ops.object.select_all(action='SELECT') is the same thing as pressing the A key, which selects ALL items, even ones outside of the view frustum, even ones occluded and not visible.

To select visible vertices in python similar to border or circle select honoring bpy.types.SpaceView3D.use_occlude_geometry and bpy.ops.mesh.select_mode:

import bpy

def getView3dAreaAndRegion(context):
  for area in context.screen.areas:
      if area.type == "VIEW_3D":
        for region in area.regions:
          if region.type == "WINDOW":
            return area, region

def select_border(context, view3dAreaAndRegion=None, extend=True):
  if not view3dAreaAndRegion:
    view3dAreaAndRegion = getView3dAreaAndRegion(context)
  view3dArea, view3dRegion = view3dAreaAndRegion
  override = context.copy()
  override['area'] = view3dArea
  override['region'] = view3dRegion
  bpy.ops.view3d.select_border(override,
                               gesture_mode=3,
                               xmin=0,
                               xmax=view3dArea.width,
                               ymin=0,
                               ymax=view3dArea.height,
                               extend=extend)
  return view3dAreaAndRegion

Then to use this, just add after the function definitions:

select_border(bpy.context)

Blender >2.8

def getView3dAreaAndRegion(context):
  for area in context.screen.areas: 
      if area.type == "VIEW_3D":    
        for region in area.regions:
          if region.type == "WINDOW":
            print("Found WINDOW") 
            return area, region

def select_border(context, view3dAreaAndRegion=None, extend=True):
  if not view3dAreaAndRegion:
    view3dAreaAndRegion = getView3dAreaAndRegion(context)
    print(view3dAreaAndRegion)
  view3dArea, view3dRegion = view3dAreaAndRegion
  override = context.copy()
  override['area'] = view3dArea
  override['region'] = view3dRegion
  bpy.ops.view3d.select_box(override,xmin=0,xmax=view3dArea.width,ymin=0,ymax=view3dArea.height,mode='ADD')

and then, with a selected object in Edit mode, run

select_border(bpy.context)

Very important: This code needs to be run in a window that has a 3D Editor view in it. So if you're running the code editor in a separate detached window, it won't work !

$\endgroup$
2
  • 1
    $\begingroup$ Uh...why the downvote, sirs? $\endgroup$
    – swooby
    Oct 23, 2017 at 22:54
  • 2
    $\begingroup$ Dunno who downvoted, but it worked nicely when I tested it. $\endgroup$
    – TLousky
    Oct 26, 2017 at 11:39

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .