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
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)