2

I am currently writing a python script to automate creation of flats from polygons. Currently I am trying to correctly identify the insides of the generated rooms. An example for a room looks like this:

enter image description here

Each wall is a generated mesh with six faces. Generally each wall has one to three faces that are pointed outwards or inwards at a time. I want to correctly identify the faces that are inside, to add different materials to them, or even add baseboards to the insides of the flat.

So my question now is: Is there a way to select all faces of each wall, that is a face that points inwards automatically, using Blender Python? (Like the example below)

enter image description here

aaronabebe
  • 61
  • 6
  • Hello, it's not that straightforward since the wall parts don't look like they are connected. You can't check face neighbors to see if they are concave or convex. Did you apply the solidify modifiers ? – Gorgious May 03 '21 at 16:22
  • Hi @Gorgious! It would be possible to join the walls into a single object pretty easily. Would it be easier then? I haven't tried the solidify modifiers, what would they do? – aaronabebe May 03 '21 at 16:30
  • It would be possible but would require a bit of work, see the cross hatch on the wall in the lower right ? that's because there are 2 faces overlapping, and there is the same issue at each corner. Scratch that about the solidify modifier, that's not relevant – Gorgious May 03 '21 at 16:52
  • 3
    Consider using scene raycast. https://blender.stackexchange.com/questions/192799/how-can-i-remove-object-by-raycast/192830#192830 in this example a raycast in direction of outer wall normal will hit nothing. (pre-hide any non contributing objects) – batFINGER May 03 '21 at 16:59

1 Answers1

4

So with the tip from @batFINGER I was able to build a solution using scene raycast.

for obj in bpy.data.objects:
        if 'wall_' in obj.name:
            bpy.context.view_layer.objects.active = obj

            mesh = obj.data
            bm = bmesh.new()
            bm.from_mesh(mesh)
            bm.faces.ensure_lookup_table()

            for i in range(len(bm.faces)):
                mesh.polygons[i].select = False
                face_location = bm.faces[i].calc_center_median()

                # side face
                if face_location[2] != self.wall_height and face_location[2] != 0:
                    hit, loc, norm, idx, ob, M = bpy.context.scene.ray_cast(
                        bpy.context.view_layer,
                        face_location + mesh.polygons[i].normal,
                        mesh.polygons[i].normal
                    )

                    if hit: 
                        mesh.polygons[i].select = True

            # toggle to edit mode
            bpy.ops.object.mode_set(mode='EDIT')

            # make sure face select mode is enabled
            bpy.context.tool_settings.mesh_select_mode = [False, False, True]

            # use second material slot
            obj.active_material_index = 2

            # assign the material
            bpy.ops.object.material_slot_assign()

            # toggle to object mode
            bpy.ops.object.mode_set(mode='OBJECT')

enter image description here

aaronabebe
  • 61
  • 6
  • 1
    Good one. Quicker to set the face.material_index directly. – batFINGER May 07 '21 at 19:31
  • Nice ! Side note, it fails in this configuration : https://i.stack.imgur.com/dHsLG.png (Concave rooms) – Gorgious May 14 '21 at 17:23
  • 1
    Also, in newer versions of blender you need to pass the Depsgraph instead of the view layer as the first argument of ray_cast (eg bpy.context.scene.ray_cast( bpy.context.evaluated_depsgraph_get(),...) – Gorgious May 14 '21 at 17:24
  • I wonder if this is still valid for Blender 3.3? I get an error "NameError: name 'self' is not defined". – user2404987 Jan 31 '23 at 09:34
  • @user2404987 the error probably stems from the reference to self.wall_height. i just copied an excerpt from the class i implemented it in. so to reuse this you would have to change some of the variables that reference things in my particular implementation. – aaronabebe Feb 14 '23 at 13:37