Пример #1
0
    def _move_and_duplicate_furniture(self, data: dir,
                                      all_loaded_furniture: list):
        """
        Move and duplicate the furniture depending on the data in the data json dir.
        After loading each object gets a location based on the data in the json file. Some objects are used more than
        once these are duplicated and then placed.

        :param data: json data dir. Should contain "scene", which should contain "room"
        :param all_loaded_furniture: all objects which have been loaded in _load_furniture_objs
        """
        # this rotation matrix rotates the given quaternion into the blender coordinate system
        blender_rot_mat = mathutils.Matrix.Rotation(radians(-90), 4, 'X')
        if "scene" not in data:
            raise Exception(
                "There is no scene data in this json file: {}".format(
                    self.json_path))
        # for each room
        for room_id, room in enumerate(data["scene"]["room"]):
            # for each object in that room
            for child in room["children"]:
                if "furniture" in child["instanceid"]:
                    # find the object where the uid matches the child ref id
                    for obj in all_loaded_furniture:
                        if obj["uid"] == child["ref"]:
                            # if the object was used before, duplicate the object and move that duplicated obj
                            if obj["is_used"]:
                                new_obj = duplicate_objects(obj)[0]
                            else:
                                # if it is the first time use the object directly
                                new_obj = obj
                            self.created_objects.append(new_obj)
                            new_obj["is_used"] = True
                            new_obj["room_id"] = room_id
                            new_obj[
                                "type"] = "Object"  # is an object used for the interesting score
                            new_obj["coarse_grained_class"] = new_obj[
                                "category_id"]
                            # this flips the y and z coordinate to bring it to the blender coordinate system
                            new_obj.location = mathutils.Vector(
                                child["pos"]).xzy
                            new_obj.scale = child["scale"]
                            # extract the quaternion and convert it to a rotation matrix
                            rotation_mat = mathutils.Quaternion(
                                child["rot"]).to_euler().to_matrix().to_4x4()
                            # transform it into the blender coordinate system and then to an euler
                            new_obj.rotation_euler = (
                                blender_rot_mat @ rotation_mat).to_euler()
Пример #2
0
    def run(self):
        """ Replaces mesh objects with another mesh objects and scales them accordingly, the replaced objects and the objects to replace with in following steps:
        1. Find which object to replace.
        2. Place the new object in place of the object to be replaced and scale accordingly.
        2. If there is no collision, between that object and the objects in the scene, then do replace and delete the original object.

        """
        self._objects_to_be_replaced = self.config.get_list(
            "objects_to_be_replaced", [])
        self._objects_to_replace_with = self.config.get_list(
            "objects_to_replace_with", [])
        self._ignore_collision_with = self.config.get_list(
            "ignore_collision_with", [])

        # Hide new objects from renderers until they are added
        for obj in self._objects_to_replace_with:
            obj.hide_render = True

        # amount of replacements depends on the amount of objects and the replace ratio
        amount_of_replacements = int(
            len(self._objects_to_be_replaced) * self._replace_ratio)
        if amount_of_replacements == 0:
            print(
                "Warning: The amount of objects, which should be replace is zero!"
            )
        amount_of_already_replaced = 0
        tries = 0

        # tries to replace objects until the amount of requested objects are replaced or the amount
        # of maximum tries was reached
        while amount_of_already_replaced < amount_of_replacements and tries < self._max_tries:
            current_object_to_be_replaced = np.random.choice(
                self._objects_to_be_replaced)
            current_object_to_replace_with = np.random.choice(
                self._objects_to_replace_with)
            if self._replace_and_edit(current_object_to_be_replaced,
                                      current_object_to_replace_with):

                # Duplicate the added object to be able to add it again
                duplicates = duplicate_objects(current_object_to_replace_with)
                if len(duplicates) == 1:
                    duplicate_new_object = duplicates[0]
                else:
                    raise Exception(
                        "The duplication failed, amount of objects are: {}".
                        format(len(duplicates)))

                # Copy properties to the newly duplicated object
                if self._copy_properties:
                    for key, value in current_object_to_be_replaced.items():
                        duplicate_new_object[key] = value

                duplicate_new_object.hider_render = False

                print('Replaced ', current_object_to_replace_with.name, ' by ',
                      duplicate_new_object.name)

                # Delete the original object and remove it from the list
                self._objects_to_replace_with.remove(
                    current_object_to_replace_with)
                bpy.ops.object.select_all(action='DESELECT')
                current_object_to_replace_with.select_set(True)
                bpy.ops.object.delete()

                amount_of_already_replaced += 1

            tries += 1
        bpy.context.view_layer.update()