3
$\begingroup$

I have a mesh that is made of several intersecting mesh islands (here's a simple cube version).

enter image description here

I'd like to be able to automatically select all vertices that are inside another mesh (like these).

enter image description here

Selecting these manually can get super complex super quickly as you add more cubes. Is there a way to automate the process? Other solutions (like using a union boolean modifier to create another object and matching the vertex locations) become unfeasible once you have more than two meshes.

$\endgroup$
1
  • $\begingroup$ There is no automatic way using the built-in tools of Blender. You will have to write a python script or check it via geometry nodes with raytracing but I don't think this is an easy task. $\endgroup$
    – Harry McKenzie
    Commented Jun 1 at 9:25

1 Answer 1

4
$\begingroup$

Go to Object Mode and run this code in the Scripting workspace:

from bpy import context as C

# you might want to disable modifiers before evaluating this depsgraph
dg = C.evaluated_depsgraph_get()

# deselect faces and edges
for fe in C.object.data.polygons[:] + C.object.data.edges[:]:
    fe.select = False
    
for v in C.object.data.vertices:
    co = v.co + v.normal * 0.0001
    
    # https://docs.blender.org/api/current/bpy.types.Scene.html#bpy.types.Scene.ray_cast
    ray_data = C.scene.ray_cast(dg, co, v.normal)
    
    # unpack; underscored variables aren't used
    result, _location, normal, _index, _object, _matrix = ray_data
    # alternatives:
    # result, _, normal, _, _, _ = ray_data
    # or 
    # result = ray_data[0], normal = ray_data[2]

    # positive dot product says the angle between directions is less than 180d
    is_hit_from_inside = v.normal @ normal > 0
    v.select = result and is_hit_from_inside

You can codegolf this code into a macro:

exec('d=C.evaluated_depsgraph_get()\nm=C.object.data\nfor i in m.polygons[:]+m.edges[:]:i.select=0\nfor v in m.vertices:v.select=(r:=C.scene.ray_cast(d,v.co+(n:=v.normal)*0.0001,n))[0]and n@r[2]>0');C.area.type='VIEW_3D'

[I used inline code formatting so it's easier to select]

You can now hit ⬆ ShiftF4, paste the macro (or type a macro hotstring or whatever), ↩ Enter and it will return to the viewport with the vertices selected. Again you need to be in Object Mode.

After opening the file, press the "Play" ▶ button, then enter edit mode and you should see some edges have gradients because not visible vertices are selected. Pressing ⎇ AltZ should reveal those vertices.

Same raycast principle could be used in geonodes: https://blender.stackexchange.com/a/302336/60486

$\endgroup$
4
  • $\begingroup$ This code doesn't seem to do anything. I'm in object mode. Any ideas? (Blender 4.1) $\endgroup$
    – Legoman
    Commented Jun 5 at 7:10
  • $\begingroup$ @Legoman is your object selected when you start the script? Do you get any errors? Did you try both methods, the long script and the short oneliner to paste in the console? What is your test case that you test it on? Can you record a video of your process? $\endgroup$ Commented Jun 5 at 9:57
  • $\begingroup$ Object is selected, no errors, tried both methods, tested on multiple objects in multiple files (from super complicated intersections to a couple of cubes). All that happens is it deselects any vertices that might be already selected. $\endgroup$
    – Legoman
    Commented Jun 6 at 21:21
  • $\begingroup$ @Legoman .blend file After opening the file, press the "Play" ▶ button, then enter edit mode and you should see some edges have gradients because not visible vertices are selected. Pressing ALT+Z should reveal those vertices. $\endgroup$ Commented Jun 6 at 22:34

You must log in to answer this question.

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