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