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 check_mesh_intersection(obj1: MeshObject, obj2: MeshObject, skip_inside_check: bool = False, bvh_cache: dict = None): """ Checks if the two objects are intersecting. This will use BVH trees to check whether the objects are overlapping. It is further also checked if one object is completely inside the other. This check requires that both objects are watertight, have correct normals and are coherent. If this is not the case it can be disabled via the parameter skip_inside_check. :param obj1: object 1 to check for intersection, must be a mesh :param obj2: object 2 to check for intersection, must be a mesh :param skip_inside_check: Disables checking whether one object is completely inside the other. :return: True, if they are intersecting """ if bvh_cache is None: bvh_cache = {} # If one of the objects has no vertices, collision is impossible if len(obj1.get_mesh().vertices) == 0 or len( obj2.get_mesh().vertices) == 0: return False, bvh_cache # create bvhtree for obj1 if obj1.get_name() not in bvh_cache: obj1_BVHtree = obj1.create_bvh_tree() bvh_cache[obj1.get_name()] = obj1_BVHtree else: obj1_BVHtree = bvh_cache[obj1.get_name()] # create bvhtree for obj2 if obj2.get_name() not in bvh_cache: obj2_BVHtree = obj2.create_bvh_tree() bvh_cache[obj2.get_name()] = obj2_BVHtree else: obj2_BVHtree = bvh_cache[obj2.get_name()] # Check whether both meshes intersect inter = len(obj1_BVHtree.overlap(obj2_BVHtree)) > 0 # Optionally check whether obj2 is contained in obj1 if not inter and not skip_inside_check: inter = CollisionUtility.is_point_inside_object( obj1, obj1_BVHtree, Matrix(obj2.get_local2world_mat()) @ obj2.get_mesh().vertices[0].co) if inter: print( "Warning: Detected that " + obj2.get_name() + " is completely inside " + obj1.get_name() + ". This might be wrong, if " + obj1.get_name() + " is not water tight or has incorrect normals. If that is the case, consider setting " "skip_inside_check to True.") # Optionally check whether obj1 is contained in obj2 if not inter and not skip_inside_check: inter = CollisionUtility.is_point_inside_object( obj2, obj2_BVHtree, Matrix(obj1.get_local2world_mat()) @ obj1.get_mesh().vertices[0].co) if inter: print("Warning: Detected that " + obj1.get_name() + " is completely inside " + obj2.get_name() + ". This might be wrong, if " + obj2.get_name() + " is not water tight or has incorrect " "normals. If that is the case, consider " "setting skip_inside_check to True.") return inter, bvh_cache