def sample_new_object_poses_on_face(self, current_obj, face_bb): """ Sample new object poses on the current `self.floor_obj`. :param face_bb: :return: True, if there is no collision """ random_placed_value = [ random.uniform(face_bb[0][i], face_bb[1][i]) for i in range(2) ] random_placed_value.append(0.0) # floor z value random_placed_rotation = [0, 0, random.uniform(0, np.pi * 2.0)] current_obj = MeshObject(current_obj) current_obj.set_location(random_placed_value) current_obj.set_rotation_euler(random_placed_rotation) bpy.context.view_layer.update() # Remove bvh cache, as object has changed if current_obj.get_name() in self.bvh_cache_for_intersection: del self.bvh_cache_for_intersection[current_obj.get_name()] # perform check if object can be placed there no_collision = CollisionUtility.check_intersections( current_obj, bvh_cache=self.bvh_cache_for_intersection, objects_to_check_against=self.placed_objects, list_of_objects_with_no_inside_check=[MeshObject(self.wall_obj)]) return no_collision
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