Ejemplo n.º 1
0
        def extract_plane_from_room(obj: MeshObject, used_split_height: float,
                                    up_vec: mathutils.Vector,
                                    new_name_for_obj: str):
            """
            Extract a plane from the current room object. This uses the FloorExtractor Module functions

            :param obj: The current room object
            :param used_split_height: The height at which the split should be performed. Usually 0 or wall_height
            :param up_vec: The up_vec corresponds to the face.normal of the selected faces
            :param new_name_for_obj: This will be the new name of the created object
            :return: (bool, bpy.types.Object): Returns True if the object was split and also returns the object. \
                                               Else it returns (False, None).
            """
            compare_height = 0.15
            compare_angle = math.radians(7.5)
            obj.edit_mode()
            bpy.ops.mesh.select_all(action='DESELECT')
            bm = obj.mesh_as_bmesh()
            bm.faces.ensure_lookup_table()
            # Select faces at given height that should be separate from the mesh
            counter = FloorExtractor.select_at_height_value(
                bm, used_split_height, compare_height,
                mathutils.Vector(up_vec), compare_angle,
                obj.get_local2world_mat())
            # if any faces are selected split them up
            if counter:
                bpy.ops.mesh.separate(type='SELECTED')
                obj.update_from_bmesh(bm)
                obj.object_mode()
                cur_selected_objects = bpy.context.selected_objects
                if cur_selected_objects:
                    if len(cur_selected_objects) == 2:
                        cur_selected_objects = [
                            o for o in cur_selected_objects
                            if o != bpy.context.view_layer.objects.active
                        ]
                        cur_selected_objects[0].name = new_name_for_obj
                        cur_created_obj = MeshObject(cur_selected_objects[0])
                    else:
                        raise Exception(
                            "There is more than one selection after splitting, this should not happen!"
                        )
                else:
                    raise Exception("No floor object was constructed!")
                bpy.ops.object.select_all(action='DESELECT')
                return True, cur_created_obj
            else:
                obj.object_mode()
                bpy.ops.object.select_all(action='DESELECT')
                return False, None
Ejemplo n.º 2
0
        def cut_plane(plane: MeshObject):
            """
            Cuts the floor plane in several pieces randomly. This is used for selecting random edges for the extrusions
            later on. This function assumes the current `plane` object is already selected and no other object is
            selected.

            :param plane: The object, which should be split in edit mode.
            """

            # save the size of the plane to determine a best split value
            x_size = plane.get_scale()[0]
            y_size = plane.get_scale()[1]

            # switch to edit mode and select all faces
            bpy.ops.object.mode_set(mode='EDIT')
            bpy.ops.mesh.select_all(action='SELECT')
            bpy.ops.object.mode_set(mode='OBJECT')

            # convert plane to BMesh object
            bm = plane.mesh_as_bmesh(True)
            bm.faces.ensure_lookup_table()
            # find all selected edges
            edges = [e for e in bm.edges if e.select]

            biggest_face_id = np.argmax([f.calc_area() for f in bm.faces])
            biggest_face = bm.faces[biggest_face_id]
            # find the biggest face
            faces = [f for f in bm.faces if f == biggest_face]
            geom = []
            geom.extend(edges)
            geom.extend(faces)

            # calculate cutting point
            cutting_point = [
                x_size * random.uniform(-1, 1), y_size * random.uniform(-1, 1),
                0
            ]
            # select a random axis to specify in which direction to cut
            direction_axis = [1, 0, 0
                              ] if random.uniform(0, 1) < 0.5 else [0, 1, 0]

            # cut the plane and update the final mesh
            bmesh.ops.bisect_plane(bm,
                                   dist=0.01,
                                   geom=geom,
                                   plane_co=cutting_point,
                                   plane_no=direction_axis)
            plane.update_from_bmesh(bm)