def _cam2world_matrix_from_cam_extrinsics(self, config: Config) -> np.ndarray: """ Determines camera extrinsics by using the given config and returns them in form of a cam to world frame transformation matrix. :param config: The configuration object. :return: The 4x4 cam to world transformation matrix. """ if not config.has_param("cam2world_matrix"): position = MathUtility.change_coordinate_frame_of_point( config.get_vector3d("location", [0, 0, 0]), self.source_frame) # position = Vector((-0.01111459918320179, -0.051188092678785324, 0.19301876425743103)) rotation_format = config.get_string("rotation/format", "euler") value = config.get_vector3d("rotation/value", [0, 0, 0]) # Transform to blender coord frame value = MathUtility.change_coordinate_frame_of_point( value, self.source_frame) if rotation_format == "euler": # Rotation, specified as euler angles rotation_matrix = Euler(value, 'XYZ').to_matrix() elif rotation_format == "forward_vec": # Convert forward vector to euler angle (Assume Up = Z) rotation_matrix = CameraUtility.rotation_from_forward_vec( value) elif rotation_format == "look_at": # Convert forward vector to euler angle (Assume Up = Z) rotation_matrix = CameraUtility.rotation_from_forward_vec( value - position) else: raise Exception("No such rotation format:" + str(rotation_format)) if rotation_format == "look_at" or rotation_format == "forward_vec": inplane_rot = config.get_float("rotation/inplane_rot", 0.0) rotation_matrix = np.matmul( rotation_matrix, Euler((0.0, 0.0, inplane_rot)).to_matrix()) extra_rot = config.get_vector("rotation/extra_rot", mathutils.Vector([0., 0., 0.])) #extra_rot = Vector([0.3,-0.3,-0.7841]) rotation_matrix = rotation_matrix @ Euler( extra_rot).to_matrix() # cam2world_matrix = Matrix.Translation(Vector(position)) @ rotation_matrix.to_4x4() cam2world_matrix = MathUtility.build_transformation_mat( position, rotation_matrix) else: cam2world_matrix = np.array( config.get_list("cam2world_matrix")).reshape(4, 4).astype( np.float32) cam2world_matrix = MathUtility.change_target_coordinate_frame_of_transformation_matrix( cam2world_matrix, self.source_frame) return cam2world_matrix
def run(self): """ Returns the result of processing of the list of values. """ transform_by = self.config.get_string("transform_by") elements = self.config.get_list("elements") raw_result = [] for element in elements: element_conf = Config({"element": element}) if isinstance(element, list): raw_result.append(element_conf.get_vector3d("element")) else: raw_result.append(element_conf.get_raw_value("element")) if len(raw_result) > 0: if self._check_compatibility(raw_result): if transform_by == "sum": ref_result = self._sum(raw_result) elif transform_by == "avg": ref_result = self._avg(raw_result) else: raise RuntimeError("Unknown 'transform_by' operation: " + transform_by) else: raise RuntimeError( "Provider output types don't match. All must either int, float, or mathutils.Vector." ) else: raise RuntimeError( "List of resulting values of `elements` is empty. Please, check Provider configuration." ) return ref_result
def run(self): """ Loads rocks.""" rocks_settings = self.config.get_list("batches", []) for subsec_num, subsec_settings in enumerate(rocks_settings): subsec_config = Config(subsec_settings) subsec_objects = RockEssentialsRockLoader.load_rocks( path=subsec_config.get_string("path"), subsec_num=subsec_num, objects=subsec_config.get_list("objects", []), sample_objects=subsec_config.get_bool("sample_objects", False), amount=subsec_config.get_int("amount") if subsec_config.has_param("amount") else None ) RockEssentialsRockLoader.set_rocks_properties( objects=subsec_objects, physics=subsec_config.get_bool("physics", False), render_levels=subsec_config.get_int("render_levels", 3), high_detail_mode=subsec_config.get_bool("high_detail_mode", False), scale=subsec_config.get_vector3d("scale", [1, 1, 1]), reflection_amount=subsec_config.get_float("reflection_amount") if subsec_config.has_param("reflection_amount") else None, reflection_roughness=subsec_config.get_float("reflection_roughness") if subsec_config.has_param("reflection_roughness") else None, hsv=subsec_config.get_list("HSV") if subsec_config.has_param("HSV") else None )
def run(self): """ Adds specified basic empty objects to the scene and sets at least their names to the user-defined ones. 1. Get configuration parameters' values. 2. Add an object. 3. Set attribute values. """ empties_to_add = self.config.get_list("empties_to_add") for empty in empties_to_add: empty_conf = Config(empty) obj_name = empty_conf.get_string("name") obj_type = empty_conf.get_string("type", "plain_axes") entity = Entity.create_empty(obj_name, obj_type) entity.set_location(empty_conf.get_vector3d("location", [0, 0, 0])) entity.set_rotation_euler( empty_conf.get_vector3d("rotation", [0, 0, 0])) entity.set_scale(empty_conf.get_vector3d("scale", [1, 1, 1]))
def run(self): """ Adds specified basic mesh objects to the scene and sets at least their names to the user-defined ones. 1. Get configuration parameters' values. 2. Add an object. 3. Set attribute values. 4. Initialize a material, if needed. """ meshes_to_add = self.config.get_list("meshes_to_add") init_objs_mats = self.config.get_bool("init_materials", True) for mesh in meshes_to_add: mesh_conf = Config(mesh) obj_type = mesh_conf.get_string("type") obj_name = mesh_conf.get_string("name") obj_location = mesh_conf.get_vector3d("location", [0, 0, 0]) obj_rotation = mesh_conf.get_vector3d("rotation", [0, 0, 0]) obj_scale = mesh_conf.get_vector3d("scale", [1, 1, 1]) new_obj = self._add_obj(obj_type) self._set_attrs(new_obj, obj_name, obj_location, obj_rotation, obj_scale) if init_objs_mats: self._init_material(obj_name)
def perform_and_condition_check(self, and_condition, objects): """ Checks all objects in the scene if all given conditions are true for an object, it is added to the list. :param and_condition: Given conditions. Type: dict. :param objects: Objects, that are already in the return list. Type: list. :return: Objects that fulfilled given conditions. Type: list. """ new_objects = [] # through every object for obj in bpy.context.scene.objects: # if object is in list, skip it if obj in objects: continue select_object = True # run over all conditions and check if any one of them holds, if one does not work -> go to next obj for key, value in and_condition.items(): # check if the key is a requested custom property requested_custom_property = False requested_custom_function = False if key.startswith('cp_'): requested_custom_property = True key = key[3:] if key.startswith('cf_'): requested_custom_function = True key = key[3:] # check if an attribute with this name exists and the key was not a requested custom property if hasattr(obj, key) and not requested_custom_property: # check if the type of the value of attribute matches desired if isinstance(getattr(obj, key), type(value)): new_value = value # if not, try to enforce some mathutils-specific type else: if isinstance(getattr(obj, key), mathutils.Vector): new_value = mathutils.Vector(value) elif isinstance(getattr(obj, key), mathutils.Euler): new_value = mathutils.Euler(value) elif isinstance(getattr(obj, key), mathutils.Color): new_value = mathutils.Color(value) # raise an exception if it is none of them else: raise Exception( "Types are not matching: %s and %s !" % (type(getattr(obj, key)), type(value))) # or check for equality if not ((isinstance(getattr(obj, key), str) and re.fullmatch(value, getattr(obj, key)) is not None) or getattr(obj, key) == new_value): select_object = False break # check if a custom property with this name exists elif key in obj and requested_custom_property: # check if the type of the value of such custom property matches desired if isinstance(obj[key], type(value)) or (isinstance( obj[key], int) and isinstance(value, bool)): # if is a string and if the whole string matches the given pattern if not ((isinstance(obj[key], str) and re.fullmatch(value, obj[key]) is not None) or obj[key] == value): select_object = False break # raise an exception if not else: raise Exception( "Types are not matching: {} and {} for key: {}". format(type(obj[key]), type(value), key)) elif requested_custom_function and any( [key == "inside", key == "outside"]): conditions = Config(value) if conditions.has_param("min") and conditions.has_param( "max"): if any( conditions.has_param(key) for key in [ "x_min", "x_max", "y_min", "y_max", "z_min", "z_max" ]): raise RuntimeError( "An inside/outside condition cannot mix the min/max vector syntax with " "the x_min/x_max/y_min/... syntax.") bb_min = conditions.get_vector3d("min") bb_max = conditions.get_vector3d("max") is_inside = all(bb_min[i] < obj.location[i] < bb_max[i] for i in range(3)) else: if any( conditions.has_param(key) for key in ["min", "max"]): raise RuntimeError( "An inside/outside condition cannot mix the min/max syntax with " "the x_min/x_max/y_min/... syntax.") is_inside = True for axis_index in range(3): axis_name = "xyz"[axis_index] for direction in ["min", "max"]: key_name = "{}_{}".format(axis_name, direction) if key_name in value: real_position = obj.location[axis_index] border_position = float(value[key_name]) if (direction == "max" and real_position > border_position ) or (direction == "min" and real_position < border_position): is_inside = False if (key == "inside" and not is_inside) or (key == "outside" and is_inside): select_object = False break else: select_object = False break if select_object: new_objects.append(obj) return new_objects
def perform_and_condition_check(self, and_condition, objects): """ Checks all objects in the scene if all given conditions are true for an object, it is added to the list. :param and_condition: Given conditions. Type: dict. :param objects: Objects, that are already in the return list. Type: list. :return: Objects that fulfilled given conditions. Type: list. """ # run over all conditions and check if any one of them holds, if one does not work -> go to next obj for key, value in and_condition.items(): # check if the key is a requested custom property requested_custom_property = False requested_custom_function = False if key.startswith('cp_'): requested_custom_property = True key = key[3:] if key.startswith('cf_'): requested_custom_function = True key = key[3:] if not requested_custom_property and not requested_custom_function: # Filter by normal attributes objects = Filter.by_attr(objects, key, value, regex=True) elif requested_custom_property: # Filter by custom property objects = Filter.by_cp(objects, key, value, regex=True) elif requested_custom_function: # Build boundaries of interval conditions = Config(value) if conditions.has_param("min") and conditions.has_param("max"): if any( conditions.has_param(key) for key in ["x_min", "x_max", "y_min", "y_max", "z_min", "z_max" ]): raise RuntimeError( "An inside/outside condition cannot mix the min/max vector syntax with " "the x_min/x_max/y_min/... syntax.") bb_min = conditions.get_vector3d("min") bb_max = conditions.get_vector3d("max") else: if any( conditions.has_param(key) for key in ["min", "max"]): raise RuntimeError( "An inside/outside condition cannot mix the min/max syntax with " "the x_min/x_max/y_min/... syntax.") # Set the interval +/- inf per default, so they will be ignored if they are not set bb_min = mathutils.Vector((-np.inf, -np.inf, -np.inf)) bb_max = mathutils.Vector((np.inf, np.inf, np.inf)) # Set boundaries given by config for axis_index in range(3): axis_name = "xyz"[axis_index] for direction in ["min", "max"]: key_name = "{}_{}".format(axis_name, direction) if key_name in value: if direction == "min": bb_min[axis_index] = float(value[key_name]) else: bb_max[axis_index] = float(value[key_name]) if key == "inside": objects = Filter.by_attr_in_interval( objects, "location", bb_min, bb_max) elif key == "outside": objects = Filter.by_attr_outside_interval( objects, "location", bb_min, bb_max) else: raise Exception("No such custom function: " + str(key)) return objects