| 128 | |
| 129 | |
| 130 | def init_random_lighting(camera_dir: np.ndarray) -> None: |
| 131 | # Clear existing lights |
| 132 | bpy.ops.object.select_all(action="DESELECT") |
| 133 | bpy.ops.object.select_by_type(type="LIGHT") |
| 134 | bpy.ops.object.delete() |
| 135 | |
| 136 | # Create environment light |
| 137 | if bpy.context.scene.world is None: |
| 138 | world = bpy.data.worlds.new("World") |
| 139 | bpy.context.scene.world = world |
| 140 | else: |
| 141 | world = bpy.context.scene.world |
| 142 | |
| 143 | # Enabling nodes |
| 144 | world.use_nodes = True |
| 145 | node_tree = world.node_tree |
| 146 | nodes = node_tree.nodes |
| 147 | links = node_tree.links |
| 148 | |
| 149 | # Remove default nodes |
| 150 | for node in nodes: |
| 151 | nodes.remove(node) |
| 152 | |
| 153 | # Random place lights |
| 154 | num_lights = np.random.randint(1, 4) |
| 155 | total_strength = 1.5 |
| 156 | for i in range(num_lights): |
| 157 | new_light = bpy.data.objects.new(f"Light_{i}", bpy.data.lights.new(f"Light_{i}", type="POINT")) |
| 158 | bpy.context.collection.objects.link(new_light) |
| 159 | |
| 160 | new_light_distance = 1 / np.random.uniform(1/100, 1/10) |
| 161 | new_light_dir = np.random.randn(3) |
| 162 | new_light_dir[2] += 0.6 |
| 163 | new_light_dir = new_light_dir / np.linalg.norm(new_light_dir) |
| 164 | new_light_location = new_light_dir * new_light_distance |
| 165 | new_light_camera_strength_ratio = max(np.sum(camera_dir * new_light_dir) * 0.5 + 0.5, 0) |
| 166 | new_light_max_energy = total_strength / (np.sum(camera_dir * new_light_dir) * 0.45 + 0.55) |
| 167 | new_light_strength = np.sqrt(np.random.uniform(0.01, 1)) * new_light_max_energy |
| 168 | new_light_camera_strength = new_light_camera_strength_ratio * new_light_strength |
| 169 | total_strength -= new_light_camera_strength |
| 170 | |
| 171 | new_light.location = (new_light_location[0], new_light_location[1], new_light_location[2]) |
| 172 | new_light.data.color = (1.0, 1.0, 1.0) |
| 173 | new_light.data.energy = new_light_strength * new_light_distance**2 * 31.4 |
| 174 | new_light.data.shadow_soft_size = np.random.uniform(0.1, 0.1 * new_light_distance) |
| 175 | |
| 176 | # Create background node |
| 177 | bg_node = nodes.new(type="ShaderNodeBackground") |
| 178 | bg_node.inputs["Color"].default_value = (1.0, 1.0, 1.0, 1.0) |
| 179 | bg_node.inputs["Strength"].default_value = total_strength |
| 180 | output_node = nodes.new(type="ShaderNodeOutputWorld") |
| 181 | links.new(bg_node.outputs["Background"], output_node.inputs["Surface"]) |
| 182 | |
| 183 | |
| 184 | def load_object(object_path: str) -> None: |