Example #1
0
  def __init__(self, cfg):

    self.cfg = cfg
    cfg_sys = cfg.get('particle_system', {})
    self._iterations = cfg_sys.get('iterations', 0)

    # find max number of trainable objects
    n_trainable = 0
    for e in cfg_sys.get('emitters', []):
      for s in e.get('systems'):
        if s.get('trainable'):
          n_trainable += len(s.get('objects'))


    # allocate color spectrum, appending color list to objects
    color_range_rgba = color_utils.create_palette_rgba(n_trainable)

    for e in cfg_sys.get('emitters', []):
      color_idx_offset = 0
      for s in e.get('systems'):
        count = max(s.get('count')) * len(s.get('objects'))
        for object_idx, o in enumerate(s.get('objects')):
          materials = []
          max_emitter_count = np.max(np.array(s.get('count'), dtype=np.uint16))
          if s.get('trainable'):
            # use color range, creating new color shader materials
            rgba = color_range_rgba[color_idx_offset]  # RGBA norm
            color_idx_offset += 1
            rgba_cf_colors = color_utils.create_shaded_range_rgba(rgba, max_emitter_count)
            # create a color fill material for all possible emitter objects
            for c_idx, rgba_cf_color in enumerate(rgba_cf_colors):
              mat_name = f'{o.get("name")}_colorfill_{c_idx}'
              rgba_cf_color_int = [int(x * 255) for x in rgba_cf_color]
              if not mat_name in bpy.data.materials.keys():
                cfm = ColorFillMaterial(mat_name, rgba_cf_color)
              materials.append(mat_name)
          else:
            # single color material for all
            rgba_cf_color = color_utils.rgb_packed_to_rgba_norm(o.get('color', 0x000000))
            mat_name = f'{o.get("material")}_colorfill'
            im_alpha_name = o.get('image')
            if not mat_name in bpy.data.materials.keys():
              cfm = ColorFillMaterial(mat_name, rgba_cf_color, alpha_image=im_alpha_name)
            rgba_cf_colors = [ rgba_cf_color ] * max_emitter_count
            materials = [mat_name] * count
          # create materials for each color
          o['materials'] = materials
          o['colors'] = rgba_cf_colors
          # store reference to material slots
          scene_obj = bpy.data.objects.get(o.get('name'))
          if not scene_obj:
            log.error(f'Object name: {o.get("name")} does not exist')

          o['material_slots'] = [ms.material for ms in scene_obj.material_slots]

    # create emitter objects
    self.emitters = [Emitter(x) for x in cfg_sys.get('emitters', [])]
Example #2
0
    def __init__(self, cfg):

        # get world
        world_cfg = cfg.get('world')
        self.name_world = world_cfg.get('name', 'World')
        self.world = bpy.data.worlds.get(self.name_world)
        self.nodes = self.world.node_tree.nodes
        self.links = self.world.node_tree.links
        # setup world output nodes
        self.node_out = self.nodes.get(world_cfg.get('output', 'World Output'))
        self.node_out_link_id = self.node_out.inputs['Surface']
        # get mapping node for adjusting rotation values
        self.node_mapping = self.nodes.get(
            'Mapping')  # Default name of Mapping nodes
        if not self.node_mapping:
            log.warn(f'No "Mapping" World node. Unable to rotate background.')
        # setup render opts
        self.rotations = world_cfg.get('rotations')
        self.environments = world_cfg.get('backgrounds', [])
        self.environment_texture_node = self.nodes.get('Environment Texture')
        self.jitter = world_cfg.get('jitter')

        # TODO this may cause errors
        # create temporary mask node and add to scene
        mat_name = f'mat_world_mask'
        if not mat_name in bpy.data.worlds.keys():
            color = color_utils.rgb_packed_to_rgba_norm(
                world_cfg.get('color', 0x000000))
            cfm = ColorFillWorld(mat_name, color)
        self.material_mask_name = mat_name
        self.material_default_name = self.name_world

        # store reference to user's current active background
        for link in self.links:
            if link.to_node.name == self.node_out.name:
                try:
                    self.node_orig = link.from_node
                    self.node_orig_link_id = self.node_orig.outputs[
                        'Background']
                    self.node_active = self.node_orig
                    self.node_active_link_id = self.node_active.outputs[
                        'Background']
                except Exception as e:
                    log.error(f'{e}')
Example #3
0
  def __init__(self, cfg):
    # find max number of trainable objects
    self.cfg = cfg
    cfg_sys = self.cfg.get('static_system')
    n_trainable = sum(1 for o in cfg_sys.get('objects') if o.get('trainable', False))
    color_range = color_utils.create_palette_rgba(n_trainable)  # allocate color spectrum

    for idx, o in enumerate(cfg_sys.get('objects')):
      meta = SceneObjectMetadata(**o)
      if meta.trainable:
        # use dynamically allocated color
        rgba_norm = color_range[idx]
        meta.color = color_utils.rgba_norm_to_packed_int(rgba_norm)
        rgba_int = [int(x * 255) for x in rgba_norm]
      else:
        # use fixed color
        rgba_int = color_utils.rgb_packed_to_rgba_norm(o.get('color', 0x000000))

      o['color'] = rgba_int
      self._scene_objects.append(SceneObject(meta))
Example #4
0
 def generate_placeholders(self, cfg):
     '''Generates list of object names in this particle system'''
     placeholders = {}
     for o in cfg.get('objects', []):
         obj_name = o.get('name')
         obj_scene = bpy.data.objects.get(obj_name)
         if not obj_scene:
             log.error(f'{obj_name} is not an object in this scene')
         o['default_material'] = obj_scene.active_material.name
         o['material_slots_defaults'] = [
             ms.material.name for ms in obj_scene.material_slots
         ]
         o['unmask_material'] = o['default_material']
         # o['ground_materials'] = self.ground_materials
         o['ground_materials'] = o.get('material')
         cf_mat_name = f'mat_{obj_name}_colorfill'
         if not cf_mat_name in bpy.data.materials.keys():
             color = color_utils.rgb_packed_to_rgba_norm(
                 o.get('color', 0x000000))
             cfm = ColorFillMaterial(cf_mat_name, color)
         o['colorfill_material'] = cf_mat_name
         placeholders[obj_name] = o
     return placeholders
Example #5
0
    def __init__(self, cfg):

        # get world
        world_cfg = cfg.get("world")
        self.name_world = world_cfg.get("name", "World")
        self.world = bpy.data.worlds.get(self.name_world)
        self.nodes = self.world.node_tree.nodes
        self.links = self.world.node_tree.links
        # setup world output nodes
        self.node_out = self.nodes.get(world_cfg.get("output", "World Output"))
        print(self.node_out)
        self.node_out_link_id = self.node_out.inputs["Surface"]
        # get mapping node for adjusting rotation values
        self.node_mapping = self.nodes.get(
            "Mapping")  # Default name of Mapping nodes
        if not self.node_mapping:
            log.warn(f'No "Mapping" World node. Unable to rotate background.')
            # setup render opts
            self.rotations = world_cfg.get("rotations")
            self.environments = world_cfg.get("backgrounds", [])
            self.environment_texture_node = self.nodes.get(
                "Environment Texture")
            self.jitter = world_cfg.get("jitter")

            # TODO this may cause errors
            # create temporary mask node and add to scene
            mat_name = f"mat_world_mask"
            if not mat_name in bpy.data.worlds.keys():
                color = color_utils.rgb_packed_to_rgba_norm(
                    world_cfg.get("color", 0x000000))
                cfm = ColorFillWorld(mat_name, color)
                self.material_mask_name = mat_name
                self.material_default_name = self.name_world

                # store reference to user's current active background
                for link in self.links:
                    if link.to_node.name == self.node_out.name:
                        try:
                            self.node_orig = link.from_node
                            self.node_orig_link_id = self.node_orig.outputs[
                                "Background"]
                            self.node_active = self.node_orig
                            self.node_active_link_id = self.node_active.outputs[
                                "Background"]
                        except Exception as e:
                            log.error(f"{e}")

        def remove_cur_output(self):
            # find node currently linked to world output and store ref
            for link in self.links:
                if link.to_node.name == self.node_out.name:
                    self.links.remove(link)

        def set_rotation_idx(self, idx):
            """Rotates the background image by degrees to alter lighting"""
            deg = self.rotations[idx]
            self.set_rotation_deg(deg)

        def set_rotation_deg(self, deg):
            """Rotates the background image by degrees to alter lighting"""
            try:
                self.node_mapping.rotation[2] = math.radians(deg)
            except Exception as e:
                # log.warning(f'Could not rorate self.node_mapping')
                pass

        def set_environment(self, idx):
            """Connects image backgroud node to world output"""
            self.environment_texture_node.image = bpy.data.images.get(
                self.environments[idx])

        def randomize(self):
            """Randomizes world material and angle"""
            self.set_environment(random.randint(0, len(self.environments) - 1))
            self.set_rotation_deg(random.randint(0, 360))

        def mask(self):
            """Converts World into black background for masked render"""
            bpy.context.scene.world = bpy.data.worlds.get(
                self.material_mask_name)
            # self.remove_cur_output()

        def unmask(self):
            """'Resets World material to original"""
            # relink
            # self.links.new(self.node_orig_link_id, self.node_out_link_id)
            bpy.context.scene.world = bpy.data.worlds.get(
                self.material_default_name)

        def cleanup(self):
            """Removes temporary nodes and restores previous settings"""
            if self.node_orig is not None:
                self.remove_cur_output()
                self.links.new(self.node_orig_link_id, self.node_out_link_id)
                # delete temp node
                # self.nodes.remove(self.node_mask)
                # delete colorfill mask
                if self.material_mask_name in bpy.data.worlds.keys():
                    bpy.data.worlds.remove(
                        bpy.data.worlds.get(self.material_mask_name))

                # reset to orig material
                bpy.context.scene.world = bpy.data.worlds.get(
                    self.material_default_name)

        @property
        def num_environments(self):
            return len(self.environments)

        @property
        def num_rotations(self):
            return len(self.rotations)
Example #6
0
 def rgba_norm(self):
   return color_utils.rgb_packed_to_rgba_norm(self.color)