diff --git a/README.md b/README.md index 7ee2c3c04..e3606d42a 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,7 @@ Next, see our ["Hello World" example](docs/HelloWorld.md) to generate an image & - [Extended ground-truth](docs/GroundTruthAnnotations.md) - [Generating individual assets](docs/GeneratingIndividualAssets.md) - [Implementing new materials & assets](docs/ImplementingAssets.md) +- [Generating fluid simulations](docs/GeneratingFluidSimulations.md) ### Coming Soon Please see our [project roadmap](https://infinigen.org/roadmap) and follow us at [https://twitter.com/PrincetonVL](https://twitter.com/PrincetonVL) for updates. @@ -67,7 +68,7 @@ Please post this repository's Github Issues page for help. Please run your comma ### Acknowledgements -Infinigen wouldn't be possible without the fantastic work of the [Blender Foundation](https://www.blender.org/) and it's open-source contributors. Infinigen uses many open source projects, with special thanks to [Land-Lab](https://github.com/landlab/landlab), [BlenderProc](https://github.com/DLR-RM/BlenderProc) and [Blender-Differential-Growth](https://github.com/inca/blender-differential-growth). +Infinigen wouldn't be possible without the fantastic work of the [Blender Foundation](https://www.blender.org/) and it's open-source contributors. Infinigen uses many open source projects, with special thanks to [Land-Lab](https://github.com/landlab/landlab), [BlenderProc](https://github.com/DLR-RM/BlenderProc) [Blender-FLIP-Fluids](https://github.com/rlguy/Blender-FLIP-Fluids) and [Blender-Differential-Growth](https://github.com/inca/blender-differential-growth). We thank [Thomas Kole](https://blenderartists.org/u/ThomasKole) for providing procedural clouds (which are more photorealistic than our original version) and [Pedro P. Lopes](https://blendswap.com/blend/30728) for the autoexposure nodegraph. diff --git a/docs/GeneratingFluidSimulations.md b/docs/GeneratingFluidSimulations.md new file mode 100644 index 000000000..ff700e17e --- /dev/null +++ b/docs/GeneratingFluidSimulations.md @@ -0,0 +1,27 @@ +# Generating Fluid Simulations + +This documentation details how to generate fire and water simulations like those shown in the Infinigen launch video. It assumes you have already completed [Installation.md] and [HelloWorld.md]. Fluid simulations require *significant* computational resources. + +## Setup + +To generate fluids, you run install.sh with the optional FLIP-Fluids setup step (`bash install.sh flip_fluids`), or, please run `bash worldgen/tools/install/compile_flip_fluids.sh` to install flip fluids now. + +## Example Commands + +#### Generate videos of random scene types, with simulated fire generated on the fly when needed +``` +python -m tools.manage_datagen_jobs --output_folder outputs/onthefly --num_scenes 10 \ + --pipeline_config slurm_high_memory.gin monocular_video.gin \ + --config fast_terrain_assets.gin use_on_the_fly_fire.gin \ + --wandb_mode online --cleanup none --warmup_sec 12000 +``` + +#### Generate videos of valley scenes with simulated rivers +``` +python -m tools.manage_datagen_jobs --output_folder /n/fs/pvl-renders/kkayan/river --num_scenes 10 \ + --pipeline_config slurm_high_memory.gin monocular_video.gin opengl_gt.gin cuda_terrain.gin \ + --pipeline_overrides iterate_scene_tasks.frame_range=[100,244] \ + --config simulated_river.gin no_assets.gin no_creatures.gin fast_terrain_assets.gin \ + --wandb_mode online --cleanup none --warmup_sec 12000 +``` + diff --git a/docs/Installation.md b/docs/Installation.md index ddfa57ea5..dd842ce44 100644 --- a/docs/Installation.md +++ b/docs/Installation.md @@ -26,9 +26,10 @@ conda activate infinigen bash install.sh ``` `install.sh` may take significant time to download Blender and compile all source files. - Ignore non-fatal warnings. See [Getting Help](#getting-help) for guidelines on posting github issues +:bulb: If you anticipate you will want to enable our custom ground-truth system, or generate fluid simulatios, consider running `bash install.sh opengl` or `bash install.sh flip_fluids` to enable these optional extras as specified in [GroundTruthAnnotations.md](./GroundTruthAnnotations.md) and [GeneratingFluidSimulations](./GeneratingFluidSimulations.md). + Run the following or add it to your `~/.bashrc` (Linux/WSL) or `~/.bash_profile` (Mac) ``` # on Linux/WSL diff --git a/install.sh b/install.sh index fd367663c..2f49f2cb0 100755 --- a/install.sh +++ b/install.sh @@ -120,20 +120,11 @@ rm -rf build cd - if [ "$1" = "opengl" ]; then - bash ./worldgen/tools/compile_opengl.sh + bash ./worldgen/tools/install/compile_opengl.sh fi # Build Flip Fluids addon -FLIP_FLUIDS="https://github.com/rlguy/Blender-FLIP-Fluids" -FLIP_FLUIDS_FOLDER="Blender-FLIP-Fluids" -FLIP_FLUIDS_ADDON_FOLDER="${FLIP_FLUIDS_FOLDER}/build/bl_flip_fluids/flip_fluids_addon" - -if [ ! -d "${FLIP_FLUIDS_ADDON_FOLDER}" ]; then - git clone "${FLIP_FLUIDS}" - cd "${FLIP_FLUIDS_FOLDER}" - python build.py - cd - - cp -r "${FLIP_FLUIDS_ADDON_FOLDER}" "${BLENDER_ADDONS}" - "${BLENDER_EXE}" --background -noaudio -P ./worldgen/fluid/flip_init.py +if [ "$1" = "flip_fluids" ] || if [ "$2" = "flip_fluids" ]; then + bash ./worldgen/tools/install/compile_flip_fluids.sh fi \ No newline at end of file diff --git a/worldgen/assets/boulder.py b/worldgen/assets/boulder.py index bf8c03d8a..d12ebd0a5 100644 --- a/worldgen/assets/boulder.py +++ b/worldgen/assets/boulder.py @@ -145,7 +145,4 @@ def create_asset(self, i, placeholder, face_size=0.01, distance=0, **params): detail.adapt_mesh_resolution(skin_obj, face_size, method=self.adapt_mesh_method, apply=True) tag_object(skin_obj, 'boulder') - return skin_obj - -class CachedBoulderFactory(BoulderFactory): - pass \ No newline at end of file + return skin_obj \ No newline at end of file diff --git a/worldgen/assets/cactus/__init__.py b/worldgen/assets/cactus/__init__.py index 716b17609..2b6e36f4b 100644 --- a/worldgen/assets/cactus/__init__.py +++ b/worldgen/assets/cactus/__init__.py @@ -5,7 +5,7 @@ # Date: April 13 2023 from .generate import CactusFactory, ColumnarCactusFactory, GlobularCactusFactory, PrickyPearCactusFactory, \ - KalidiumCactusFactory, CachedCactusFactory + KalidiumCactusFactory from .columnar import ColumnarBaseCactusFactory from .globular import GlobularBaseCactusFactory from .pricky_pear import PrickyPearBaseCactusFactory diff --git a/worldgen/assets/cactus/generate.py b/worldgen/assets/cactus/generate.py index 7e49659d8..52a63275c 100644 --- a/worldgen/assets/cactus/generate.py +++ b/worldgen/assets/cactus/generate.py @@ -98,7 +98,3 @@ class KalidiumCactusFactory(CactusFactory): def __init__(self, factory_seed, coarse=False): super(KalidiumCactusFactory, self).__init__(factory_seed, coarse, KalidiumBaseCactusFactory) - - -class CachedCactusFactory(CactusFactory): - pass \ No newline at end of file diff --git a/worldgen/assets/creatures/__init__.py b/worldgen/assets/creatures/__init__.py index 0ac95588a..b12add155 100644 --- a/worldgen/assets/creatures/__init__.py +++ b/worldgen/assets/creatures/__init__.py @@ -1,6 +1,6 @@ from .genomes.beetle import BeetleFactory, AntSwarmFactory from .genomes.bird import BirdFactory, FlyingBirdFactory -from .genomes.carnivore import CarnivoreFactory, CachedCreatureFactory +from .genomes.carnivore import CarnivoreFactory from .genomes.fish import FishFactory, FishSchoolFactory from .genomes.herbivore import HerbivoreFactory from .genomes.crustacean import CrustaceanFactory, CrabFactory, LobsterFactory, SpinyLobsterFactory diff --git a/worldgen/assets/creatures/genomes/carnivore.py b/worldgen/assets/creatures/genomes/carnivore.py index d299d4e0f..205f19eca 100644 --- a/worldgen/assets/creatures/genomes/carnivore.py +++ b/worldgen/assets/creatures/genomes/carnivore.py @@ -221,7 +221,4 @@ def create_asset(self, i, placeholder, hair=True, simulate=False, **kwargs): cloth_sim.bake_cloth(joined, genome.postprocess_params['skin'], attributes=dict(vertex_group_mass=rigidity)) - return root - -class CachedCreatureFactory(CarnivoreFactory): - pass \ No newline at end of file + return root \ No newline at end of file diff --git a/worldgen/assets/trees/__init__.py b/worldgen/assets/trees/__init__.py index 42d98fbc2..15bdcecfa 100644 --- a/worldgen/assets/trees/__init__.py +++ b/worldgen/assets/trees/__init__.py @@ -1 +1 @@ -from .generate import BushFactory, TreeFactory, CachedTreeFactory, CachedBushFactory +from .generate import BushFactory, TreeFactory diff --git a/worldgen/assets/trees/generate.py b/worldgen/assets/trees/generate.py index d1d71202b..1a0dfc03d 100644 --- a/worldgen/assets/trees/generate.py +++ b/worldgen/assets/trees/generate.py @@ -418,11 +418,4 @@ def __init__(self, seed, coarse=False, **kwargs): self.child_col.name = colname assert self.child_col.name == colname, f'Blender truncated {colname} to {self.child_col.name}' else: - self.child_col = bpy.data.collections[colname] - - -class CachedBushFactory(BushFactory): - pass - -class CachedTreeFactory(TreeFactory): - pass \ No newline at end of file + self.child_col = bpy.data.collections[colname] \ No newline at end of file diff --git a/worldgen/config/base.gin b/worldgen/config/base.gin index 96430c15d..672ae5bab 100644 --- a/worldgen/config/base.gin +++ b/worldgen/config/base.gin @@ -27,6 +27,9 @@ compose_scene.lighting_enabled = True compose_scene.coarse_terrain_enabled = True compose_scene.terrain_surface_enabled = True +compose_scene.simulated_river_enabled=False +compose_scene.tilted_river_enabled=False + compose_scene.fancy_clouds_chance = 0.6 compose_scene.trees_chance = 0.85 @@ -100,13 +103,12 @@ populate_scene.snow_layer_chance = 0 populate_scene.snow_layer_chance=0.0 - populate_scene.fire_warmup = 50 -populate_scene.trees_fire_chance_on_the_fly = 0 -populate_scene.bushes_fire_chance_on_the_fly = 0 -populate_scene.creatures_fire_chance_on_the_fly = 0 -populate_scene.boulders_fire_chance_on_the_fly = 0 -populate_scene.cactus_fire_chance_on_the_fly = 0 +populate_scene.trees_fire_on_the_fly_chance = 0 +populate_scene.bushes_fire_on_the_fly_chance = 0 +populate_scene.creatures_fire_on_the_fly_chance = 0 +populate_scene.boulders_fire_on_the_fly_chance = 0 +populate_scene.cactus_fire_on_the_fly_chance = 0 target_face_size.global_multiplier = 2 scatter_res_distance.dist = 4 diff --git a/worldgen/config/scene_types/simulated_river.gin b/worldgen/config/scene_types/simulated_river.gin deleted file mode 100644 index 9005df2e1..000000000 --- a/worldgen/config/scene_types/simulated_river.gin +++ /dev/null @@ -1,61 +0,0 @@ -surface.registry.erosion_collection = [ - ('sand', 2), - ('cracked_ground', 2), - ('dirt', 1), - ('stone', 3), - ('soil', 1), -] - -compose_scene.ground_creatures_chance = 0.1 -compose_scene.ground_creature_registry = [ - (@CarnivoreFactory, 2), - (@HerbivoreFactory, 0.5), - (@SnakeFactory, 0.5) -] - -compose_scene.flying_creatures_chance = 0.7 -compose_scene.flying_creature_registry = [ - (@DragonflyFactory, 1), - (@FlyingBirdFactory, 0.2) -] - -compose_scene.rain_particles_chance = 0.4 -populate_scene.slime_mold_chance = 0.3 -populate_scene.ivy_chance = 0.3 -populate_scene.lichen_chance = 0.3 -populate_scene.moss_chance = 0.3 - -random_season.weights = {'autumn': 1, 'summer': 1, 'spring': 1, 'winter': 0.1} - -# scene composition config -LandTiles.tiles = ["Mountain", "River", "Mountain"] -LandTiles.tile_heights = [1.75, -0.75, 1.75] -LandTiles.randomness = 1 - -scene.waterbody_chance = 1 -scene.ground_chance = 0 -scene.warped_rocks_chance = 0 - -# camera selection config -UniformMesher.dimensions = (-25, 25, -25, 25, -15, 35) -UniformMesher.enclosed=1 -#UniformMesher.dimensions = (-12, 12, -12, 12, -12, 17) - -compose_scene.hero_boulders_chance = 0.0 - -terrain.elements.landtiles.LandTiles.y_tilt = 0 -terrain.elements.landtiles.LandTiles.y_tilt_clip = 0 -camera_pose_proposal.loc_specified = (0.45, -24, 8) -camera_pose_proposal.rot_specified = (-120, 180, -178) -camera_pose_proposal.simulated_scene = 'simulated_river' - - -assets.boulder.create_placeholder.boulder_scale = 1 -LandTiles.land_process = None -camera_selection_preprocessing.terrain_tags_ratio = {("altitude", -1e9, 0.75): (0, 1), "liquid": (0, 1)} - -core.execute_tasks.specified_scenes = ['simulated_river'] -core.render.hide_water = True -compute_base_views.min_candidates_ratio = 1 -walk_same_altitude.simulated = True - diff --git a/worldgen/config/scene_types/tilted_river.gin b/worldgen/config/scene_types/tilted_river.gin deleted file mode 100644 index ddb8b04eb..000000000 --- a/worldgen/config/scene_types/tilted_river.gin +++ /dev/null @@ -1,64 +0,0 @@ -surface.registry.erosion_collection = [ - ('sand', 2), - ('cracked_ground', 2), - ('dirt', 1), - ('stone', 3), - ('soil', 1), -] - -compose_scene.ground_creatures_chance = 0.1 -compose_scene.ground_creature_registry = [ - (@CarnivoreFactory, 2), - (@HerbivoreFactory, 0.5), - (@SnakeFactory, 0.5) -] - -compose_scene.flying_creatures_chance = 0.7 -compose_scene.flying_creature_registry = [ - (@DragonflyFactory, 1), - (@FlyingBirdFactory, 0.2) -] - -compose_scene.inview_distance = 100 -compose_scene.near_distance = 30 - -compose_scene.rain_particles_chance = 0.4 -populate_scene.slime_mold_chance = 0.3 -populate_scene.ivy_chance = 0.3 -populate_scene.lichen_chance = 0.3 -populate_scene.moss_chance = 0.3 - -random_season.weights = {'autumn': 1, 'summer': 1, 'spring': 1, 'winter': 0.1} - -# scene composition config -LandTiles.tiles = ["Mountain", "River", "Mountain"] -LandTiles.tile_heights = [1.75, -0.75, 1.75] -LandTiles.randomness = 1 - -scene.waterbody_chance = 1 -scene.ground_chance = 0 -scene.warped_rocks_chance = 0 - -# camera selection config -UniformMesher.dimensions = (-25, 25, -25, 25, -15, 35) -UniformMesher.enclosed=1 -#UniformMesher.dimensions = (-12, 12, -12, 12, -12, 17) - - -compose_scene.hero_boulders_chance = 1.0 - -terrain.elements.landtiles.LandTiles.y_tilt = 0.7 -terrain.elements.landtiles.LandTiles.y_tilt_clip = 11 -camera_pose_proposal.loc_specified = (0.678843,-30.5532, 11.7858) -camera_pose_proposal.rot_specified = (-110, 180, -178) -camera_pose_proposal.simulated_scene = 'tilted_river' - - -assets.boulder.create_placeholder.boulder_scale = 3 -LandTiles.land_process = None -camera_selection_preprocessing.terrain_tags_ratio = {("altitude", -1e9, 0.75): (0, 1), "liquid": (0, 1)} - -core.execute_tasks.specified_scenes = ['tilted_river'] -core.render.hide_water = True -compute_base_views.min_candidates_ratio = 1 -walk_same_altitude.simulated = True \ No newline at end of file diff --git a/worldgen/config/scene_types_fluidsim/simulated_river.gin b/worldgen/config/scene_types_fluidsim/simulated_river.gin new file mode 100644 index 000000000..cff612585 --- /dev/null +++ b/worldgen/config/scene_types_fluidsim/simulated_river.gin @@ -0,0 +1,30 @@ +include 'config/scene_types/river.gin' + +UniformMesher.enclosed=1 +animate_cameras.policy_registry = @cam/AnimPolicyRandomForwardWalk +cam/AnimPolicyRandomForwardWalk.forward_vec = (0,0,-1) +cam/AnimPolicyRandomForwardWalk.speed = 1 +cam/AnimPolicyRandomForwardWalk.step_range = (5, 10) +cam/AnimPolicyRandomForwardWalk.yaw_dist = ("uniform",-10, 10) + +keep_cam_pose_proposal.min_terrain_distance = 1 + +compose_scene.hero_boulders_chance = 0.0 +compose_scene.simulated_river_enabled = True + +terrain.elements.landtiles.LandTiles.y_tilt = 0 +terrain.elements.landtiles.LandTiles.y_tilt_clip = 0 + +camera_pose_proposal.override_loc = (0.45, -24, 8) +camera_pose_proposal.roll = 180 +camera_pose_proposal.pitch = ("normal", -120, 5) +camera_pose_proposal.yaw = ('normal', -180, 3) + +assets.boulder.create_placeholder.boulder_scale = 1 +LandTiles.land_process = None +camera_selection_preprocessing.terrain_tags_ratio = {("altitude", -1e9, 0.75): (0, 1), "liquid": (0, 1)} + +core.render.hide_water = True +compute_base_views.min_candidates_ratio = 1 +walk_same_altitude.ignore_missed_rays = True + diff --git a/worldgen/config/scene_types_fluidsim/tilted_river.gin b/worldgen/config/scene_types_fluidsim/tilted_river.gin new file mode 100644 index 000000000..40407e675 --- /dev/null +++ b/worldgen/config/scene_types_fluidsim/tilted_river.gin @@ -0,0 +1,30 @@ +include 'config/scene_types/river.gin' + +UniformMesher.enclosed=1 +animate_cameras.policy_registry = @cam/AnimPolicyRandomForwardWalk +cam/AnimPolicyRandomForwardWalk.forward_vec = (0,0,-1) +cam/AnimPolicyRandomForwardWalk.speed = 1 +cam/AnimPolicyRandomForwardWalk.step_range = (5, 10) +cam/AnimPolicyRandomForwardWalk.yaw_dist = ("uniform",-10, 10) + + +keep_cam_pose_proposal.min_terrain_distance = 1 + +compose_scene.hero_boulders_chance = 1.0 + +terrain.elements.landtiles.LandTiles.y_tilt = 0.7 +terrain.elements.landtiles.LandTiles.y_tilt_clip = 11 +camera_pose_proposal.override_loc = (0.678843,-30.5532, 11.7858) +camera_pose_proposal.roll = ('normal', -110, 5) +camera_pose_proposal.pitch = 180 +camera_pose_proposal.yaw = ('normal', -180, 3) + +compose_scene.tilted_river_enabled = True + +assets.boulder.create_placeholder.boulder_scale = 3 +LandTiles.land_process = None +camera_selection_preprocessing.terrain_tags_ratio = {("altitude", -1e9, 0.75): (0, 1), "liquid": (0, 1)} + +core.render.hide_water = True +compute_base_views.min_candidates_ratio = 1 +walk_same_altitude.ignore_missed_rays = True \ No newline at end of file diff --git a/worldgen/config/trailer_river.gin b/worldgen/config/trailer_river.gin deleted file mode 100644 index 7c97e4496..000000000 --- a/worldgen/config/trailer_river.gin +++ /dev/null @@ -1,31 +0,0 @@ -animate_cameras.policy_registry = @cam/AnimPolicyRandomForwardWalk - -cam/AnimPolicyRandomForwardWalk.forward_vec = (0,0,-1) -cam/AnimPolicyRandomForwardWalk.speed = 1 -cam/AnimPolicyRandomForwardWalk.step_range = (5, 10) -cam/AnimPolicyRandomForwardWalk.yaw_dist = ("uniform",-10, 10) - - -keep_cam_pose_proposal.min_terrain_distance = 1 - - -full/render_image.passes_to_save = [ - #['diffuse_direct', 'DiffDir'], - #['diffuse_color', 'DiffCol'], - #['diffuse_indirect', 'DiffInd'], - #['glossy_direct', 'GlossDir'], - #['glossy_color', 'GlossCol'], - #['glossy_indirect', 'GlossInd'], - #['transmission_direct', 'TransDir'], - #['transmission_color', 'TransCol'], - #['transmission_indirect', 'TransInd'], - #['emit', 'Emit'], - #['environment', 'Env'], - ['ambient_occlusion', 'AO'] -] -flat/render_image.passes_to_save = [ - #['z', 'Depth'], - #['normal', 'Normal'], - #['vector', 'Vector'], - ['object_index', 'IndexOB'] -] \ No newline at end of file diff --git a/worldgen/config/use_cached_fire.gin b/worldgen/config/use_cached_fire.gin index d18b52ad8..aa4975c0d 100644 --- a/worldgen/config/use_cached_fire.gin +++ b/worldgen/config/use_cached_fire.gin @@ -1,8 +1,8 @@ -populate_scene.trees_fire_chance_on_the_fly = 0 -populate_scene.bushes_fire_chance_on_the_fly = 0 -populate_scene.creatures_fire_chance_on_the_fly = 0 -populate_scene.boulders_fire_chance_on_the_fly = 0 -populate_scene.cactus_fire_chance_on_the_fly = 0 +populate_scene.trees_fire_on_the_fly_chance = 0 +populate_scene.bushes_fire_on_the_fly_chance = 0 +populate_scene.creatures_fire_on_the_fly_chance = 0 +populate_scene.boulders_fire_on_the_fly_chance = 0 +populate_scene.cactus_fire_on_the_fly_chance = 0 compose_scene.cached_fire_trees_chance= 0.5 compose_scene.cached_fire_bushes_chance = 1 diff --git a/worldgen/config/use_on_the_fly_fire.gin b/worldgen/config/use_on_the_fly_fire.gin index e4885cda1..c1af08d7a 100644 --- a/worldgen/config/use_on_the_fly_fire.gin +++ b/worldgen/config/use_on_the_fly_fire.gin @@ -1,10 +1,10 @@ -populate_scene.trees_fire_chance_on_the_fly = 0.1 +populate_scene.trees_fire_on_the_fly_chance = 0.1 #compose_scene.trees_chance = 1 -populate_scene.bushes_fire_chance_on_the_fly = 0.8 +populate_scene.bushes_fire_on_the_fly_chance = 0.8 #compose_scene.bushes_chance = 1 -populate_scene.creatures_fire_chance_on_the_fly = 0 -populate_scene.boulders_fire_chance_on_the_fly = 0.1 -populate_scene.cactus_fire_chance_on_the_fly = 0.1 +populate_scene.creatures_fire_on_the_fly_chance = 0 +populate_scene.boulders_fire_on_the_fly_chance = 0.1 +populate_scene.cactus_fire_on_the_fly_chance = 0.1 compose_scene.glowing_rocks_chance = 0.0 diff --git a/worldgen/core.py b/worldgen/core.py index 3ecd528bb..ed34e2075 100644 --- a/worldgen/core.py +++ b/worldgen/core.py @@ -35,29 +35,29 @@ from placement.split_in_view import split_inview from lighting import lighting, kole_clouds -from assets.trees.generate import TreeFactory, BushFactory, random_season, random_leaf_collection, CachedBushFactory, CachedTreeFactory -from assets import boulder +from assets.trees.generate import TreeFactory, BushFactory, random_season +from assets.boulder import BoulderFactory from assets.glowing_rocks import GlowingRocksFactory -from assets.creatures import CarnivoreFactory, HerbivoreFactory, FishFactory, FishSchoolFactory, \ +from assets.creatures import ( + CarnivoreFactory, HerbivoreFactory, FishFactory, FishSchoolFactory, \ BeetleFactory, AntSwarmFactory, BirdFactory, SnakeFactory, \ CrustaceanFactory, FlyingBirdFactory, CrabFactory, LobsterFactory, SpinyLobsterFactory +) from assets.insects.assembled.dragonfly import DragonflyFactory from assets.cloud.generate import CloudFactory -from assets.cactus import CactusFactory, CachedCactusFactory +from assets.cactus import CactusFactory from assets.creatures import boid_swarm from placement import placement, camera as cam_util -from assets.utils.misc import log_uniform from rendering.render import render_image from rendering.resample import resample_scene from assets.monocot import kelp from surfaces import surface -from fluid.fluid import set_fire_to_assets, is_fire_in_scene -from fluid.flip_fluid import create_flip_fluid_domain, set_flip_fluid_domain, create_flip_fluid_inflow, set_flip_fluid_obstacle, get_objs_inside_domain, make_beach, make_river, make_tilted_river +from fluid.fluid import set_fire_to_assets from fluid.asset_cache import FireCachingSystem - +from fluid.cached_factory_wrappers import CachedBoulderFactory, CachedBushFactory, CachedCactusFactory, CachedCreatureFactory, CachedTreeFactory import surfaces.scatters from surfaces.scatters import ground_mushroom, slime_mold, moss, ivy, lichen, snow_layer @@ -91,7 +91,9 @@ def sanitize_gin_override(overrides: list): @gin.configurable def populate_scene( - output_folder, scene_seed, **params + output_folder, + scene_seed, + **params ): p = RandomStageExecutor(scene_seed, output_folder, params) camera = bpy.context.scene.camera @@ -104,28 +106,29 @@ def populate_scene( populated['trees'] = p.run_stage('populate_trees', use_chance=False, default=[], fn=lambda: placement.populate_all(TreeFactory, camera, season=season, vis_cull=4))#, #meshing_camera=camera, adapt_mesh_method='subdivide', cam_meshing_max_dist=8)) - populated['cached_fire_trees'] = p.run_stage('populate_cached_fire_trees', use_chance=False, default=[], - fn=lambda: placement.populate_all(CachedTreeFactory, camera, season=season, vis_cull=4, dist_cull=70, cache_system=fire_cache_system)) populated['boulders'] = p.run_stage('populate_boulders', use_chance=False, default=[], - fn=lambda: placement.populate_all(boulder.BoulderFactory, camera, vis_cull=3))#, + fn=lambda: placement.populate_all(BoulderFactory, camera, vis_cull=3))#, #meshing_camera=camera, adapt_mesh_method='subdivide', cam_meshing_max_dist=8)) - populated['cached_fire_boulders'] = p.run_stage('populate_cached_fire_boulders', use_chance=False, default=[], - fn=lambda: placement.populate_all(boulder.CachedBoulderFactory, camera, vis_cull=3, dist_cull=70, cache_system=fire_cache_system)) populated['bushes'] = p.run_stage('populate_bushes', use_chance=False, fn=lambda: placement.populate_all(BushFactory, camera, vis_cull=1, adapt_mesh_method='subdivide')) - populated['cached_fire_bushes'] = p.run_stage('populate_cached_fire_bushes', use_chance=False, - fn=lambda: placement.populate_all(CachedBushFactory, camera, vis_cull=1, adapt_mesh_method='subdivide', cache_system=fire_cache_system)) p.run_stage('populate_kelp', use_chance=False, fn=lambda: placement.populate_all(kelp.KelpMonocotFactory, camera, vis_cull=5)) populated['cactus'] = p.run_stage('populate_cactus', use_chance=False, fn=lambda: placement.populate_all(CactusFactory, camera, vis_cull=6)) - populated['cached_fire_cactus'] = p.run_stage('populate_cached_fire_cactus', use_chance=False, - fn=lambda: placement.populate_all(CachedCactusFactory, camera, vis_cull=6, cache_system=fire_cache_system)) p.run_stage('populate_clouds', use_chance=False, fn=lambda: placement.populate_all(CloudFactory, camera, dist_cull=None, vis_cull=None)) p.run_stage('populate_glowing_rocks', use_chance=False, fn=lambda: placement.populate_all(GlowingRocksFactory, camera, dist_cull=None, vis_cull=None)) + populated['cached_fire_trees'] = p.run_stage('populate_cached_fire_trees', use_chance=False, default=[], + fn=lambda: placement.populate_all(CachedTreeFactory, camera, season=season, vis_cull=4, dist_cull=70, cache_system=fire_cache_system)) + populated['cached_fire_boulders'] = p.run_stage('populate_cached_fire_boulders', use_chance=False, default=[], + fn=lambda: placement.populate_all(CachedBoulderFactory, camera, vis_cull=3, dist_cull=70, cache_system=fire_cache_system)) + populated['cached_fire_bushes'] = p.run_stage('populate_cached_fire_bushes', use_chance=False, + fn=lambda: placement.populate_all(CachedBushFactory, camera, vis_cull=1, adapt_mesh_method='subdivide', cache_system=fire_cache_system)) + populated['cached_fire_cactus'] = p.run_stage('populate_cached_fire_cactus', use_chance=False, + fn=lambda: placement.populate_all(CachedCactusFactory, camera, vis_cull=6, cache_system=fire_cache_system)) + grime_selection_funcs = { 'trees': scatter_lower, 'boulders': scatter_upward, @@ -179,19 +182,19 @@ def apply_snow_layer(surface_cls): p.run_stage(f'populate_{k}', use_chance=False, fn=lambda: placement.populate_all(fac, camera=None)) - logging.info(f'Setting assets on fire') + fire_warmup = params.get('fire_warmup', 50) simulation_duration = bpy.context.scene.frame_end - bpy.context.scene.frame_start + fire_warmup + + def set_fire(assets): + objs = [o for *_, a in assets for _, o in a] + with butil.EnableParentCollections(objs): + set_fire_to_assets(assets, bpy.context.scene.frame_start-fire_warmup, simulation_duration, output_folder) - - if uniform() < params.get('trees_fire_chance_on_the_fly') and 'trees' in populated: - set_fire_to_assets(populated['trees'], bpy.context.scene.frame_start-fire_warmup, simulation_duration, output_folder) - if uniform() < params.get('bushes_fire_chance_on_the_fly') and 'bushes' in populated: - set_fire_to_assets(populated['bushes'], bpy.context.scene.frame_start-fire_warmup, simulation_duration, output_folder) - if uniform() < params.get('boulders_fire_chance_on_the_fly') and 'boulders' in populated: - set_fire_to_assets(populated['boulders'], bpy.context.scene.frame_start-fire_warmup, simulation_duration, output_folder) - if uniform() < params.get('cactus_fire_chance_on_the_fly') and 'cactus' in populated: - set_fire_to_assets(populated['cactus'], bpy.context.scene.frame_start-fire_warmup, simulation_duration, output_folder) + p.run_stage('trees_fire_on_the_fly', set_fire, populated['trees'], prereq='populate_trees') + p.run_stage('bushes_fire_on_the_fly', set_fire, populated['bushes'], prereq='populate_bushes') + p.run_stage('boulders_fire_on_the_fly', set_fire, populated['boulders'], prereq='populate_boulders') + p.run_stage('cactus_fire_on_the_fly', set_fire, populated['cactus'], prereq='populate_cactus') p.save_results(output_folder/'pipeline_fine.csv') @@ -264,8 +267,6 @@ def execute_tasks( reset_assets=True, focal_length=None, dryrun=False, - specified_scenes = [], - flip_caustics = False, ): if input_folder != output_folder: if reset_assets: @@ -297,9 +298,13 @@ def execute_tasks( bpy.context.view_layer.update() surface.registry.initialize_from_gin() - bpy.ops.preferences.addon_enable(module='ant_landscape') - bpy.ops.preferences.addon_enable(module='real_snow') - bpy.ops.preferences.addon_enable(module='flip_fluids_addon') + + for name in ['ant_landscape', 'real_snow', 'flip_fluids_addon']: + try: + bpy.ops.preferences.addon_enable(module='ant_landscape') + except ModuleNotFoundError as e: + logging.warning(f'Could not load addon "{name}". {e}') + bpy.context.preferences.system.scrollback = 0 bpy.context.preferences.edit.undo_steps = 0 bpy.context.scene.render.resolution_x = generate_resolution[0] @@ -322,23 +327,12 @@ def execute_tasks( group_collections() - if Task.Coarse in task: - #if 'simulated_river' in specified_scenes: - # make_river(terrain_mesh, list(bpy.data.collections['placeholders'].all_objects), output_folder = output_folder) - #elif 'tilted_river' in specified_scenes: - # make_tilted_river(terrain_mesh, list(bpy.data.collections['placeholders'].all_objects), output_folder = output_folder) - if Task.Populate in task: populate_scene(output_folder, scene_seed) if Task.FineTerrain in task: terrain = Terrain(scene_seed, surface.registry, task=task, on_the_fly_asset_folder=output_folder/"assets") terrain.fine_terrain(output_folder) - if (("tilted_river" in specified_scenes) or ('simulated_river' in specified_scenes)) and flip_caustics: - bpy.data.objects['OpaqueTerrain_fine'].cycles.is_caustics_receiver = True - bpy.ops.flip_fluid_operators.helper_select_surface() - fluid_surface = bpy.context.object - fluid_surface.cycles.is_caustics_caster = True group_collections() diff --git a/worldgen/fluid/asset_cache.py b/worldgen/fluid/asset_cache.py index 71118b88d..b6a89fa9d 100644 --- a/worldgen/fluid/asset_cache.py +++ b/worldgen/fluid/asset_cache.py @@ -44,7 +44,6 @@ SPECIES_MAX = 20 I_MAX = 20 - @gin.configurable class FireCachingSystem: def __init__(self, asset_folder = None, create=False, max_fire_assets = 3, max_per_kind = 1) -> None: diff --git a/worldgen/fluid/cached_factory_wrappers.py b/worldgen/fluid/cached_factory_wrappers.py new file mode 100644 index 000000000..f2f698248 --- /dev/null +++ b/worldgen/fluid/cached_factory_wrappers.py @@ -0,0 +1,20 @@ + +from assets.trees import TreeFactory, BushFactory +from assets.creatures import CarnivoreFactory +from assets.cactus import CactusFactory +from assets.boulder import BoulderFactory + +class CachedBoulderFactory(BoulderFactory): + pass + +class CachedCactusFactory(CactusFactory): + pass + +class CachedCreatureFactory(CarnivoreFactory): + pass + +class CachedBushFactory(BushFactory): + pass + +class CachedTreeFactory(TreeFactory): + pass \ No newline at end of file diff --git a/worldgen/fluid/fluid.py b/worldgen/fluid/fluid.py index 095495cee..596f41ffe 100644 --- a/worldgen/fluid/fluid.py +++ b/worldgen/fluid/fluid.py @@ -5,6 +5,7 @@ import os import sys +from itertools import chain from pathlib import Path from numpy.random import uniform, normal, randint from mathutils import Vector @@ -32,7 +33,6 @@ from util import blender as butil - # find next available number for fluid cache folder def find_available_cache(cache_folder): Path(cache_folder).mkdir(parents=True, exist_ok=True) @@ -525,6 +525,7 @@ def set_obj_on_fire( butil.select_none() fire_dfs(obj, fluid_type) + # disabled for now # with Timer('Decimating and Realizing Instance'): # instanced_obj = get_instanced_part(obj) @@ -724,6 +725,7 @@ def find_root(node): @gin.configurable def set_fire_to_assets(assets, start_frame, simulation_duration, output_folder=None, max_fire_assets=1): + if len(assets) == 0: return @@ -737,32 +739,27 @@ def set_fire_to_assets(assets, start_frame, simulation_duration, output_folder=N obj_dist.sort(key=lambda x: x[0]) obj_vis_dist.sort(key=lambda x: x[0]) - print("sorted obj dist", obj_dist) if len(obj_dist) == 0: return - with Timer("Processing Fire Assets"): - for i in range(max_fire_assets): - closest = obj_dist[i] - obj = closest[1] - print("setting fire on obj", obj) - # obj = find_root(obj) - - # if obj.name not in bpy.data.collections[col[0]].objects: - # bpy.data.collections[col[0]].objects.link(obj) - set_obj_on_fire( - obj, - start_frame, - simulation_duration=simulation_duration, - noise_scale=2, - add_turbulence=True, - adaptive_domain=True, - output_folder=output_folder, - estimate_domain=False, - dom_scale=1.1, - ) + for i in range(max_fire_assets): + closest = obj_dist[i] + obj = closest[1] + logging.info(f"Setting fire to {i=} {obj.name=}") + + set_obj_on_fire( + obj, + start_frame, + simulation_duration=simulation_duration, + noise_scale=2, + add_turbulence=True, + adaptive_domain=True, + output_folder=output_folder, + estimate_domain=False, + dom_scale=1.1, + ) def duplicate_fluid_obj(obj): bpy.ops.mesh.primitive_plane_add() @@ -770,7 +767,6 @@ def duplicate_fluid_obj(obj): duplication_geomod.apply(new_obj=new_obj, old_obj=obj) return new_obj - @gin.configurable def estimate_smoke_domain(obj, start_frame, simulation_duration): bpy.ops.object.select_all(action="DESELECT") diff --git a/worldgen/fluid/fluid_scenecomp_additions.py b/worldgen/fluid/fluid_scenecomp_additions.py new file mode 100644 index 000000000..070d28329 --- /dev/null +++ b/worldgen/fluid/fluid_scenecomp_additions.py @@ -0,0 +1,78 @@ +import bpy +import mathutils +from mathutils import Vector +import gin +import numpy as np +from numpy.random import uniform, normal, randint + +from util.pipeline import RandomStageExecutor +from placement import placement, density + +from fluid.cached_factory_wrappers import ( + CachedTreeFactory, + CachedCreatureFactory, + CachedBoulderFactory, + CachedBushFactory, + CachedCactusFactory +) +from fluid.asset_cache import FireCachingSystem +from fluid.fluid import is_fire_in_scene +from fluid.flip_fluid import create_flip_fluid_domain, set_flip_fluid_domain, create_flip_fluid_inflow, set_flip_fluid_obstacle, get_objs_inside_domain, make_beach, make_river, make_tilted_river + +def fire_scenecomp_options(p: RandomStageExecutor, terrain_mesh, params, tree_species_params): + + land_domain = params.get('land_domain_tags') + underwater_domain = params.get('underwater_domain_tags') + nonliving_domain = params.get('nonliving_domain_tags') + + if params.get('cached_fire'): + fire_cache_system = FireCachingSystem() + + def add_cached_fire_trees(terrain_mesh): + params = tree_species_params[0] + species = fire_cache_system.get_cached_species(CachedTreeFactory) + ind = np.random.choice(len(species)) + s = species[ind] + fac = CachedTreeFactory(s, coarse=True) + selection = density.placement_mask(params['select_scale'], tag=land_domain) + placement.scatter_placeholders_mesh(terrain_mesh, fac, selection=selection, altitude=-0.1, + overall_density=params['density'], distance_min=params['distance_min']) + p.run_stage('cached_fire_trees', add_cached_fire_trees, terrain_mesh) + + def add_cached_fire_bushes(terrain_mesh): + n_bush_species = randint(1, params.get("max_bush_species", 2) + 1) + spec_density = params.get("bush_density", uniform(0.03, 0.12)) / n_bush_species + species = fire_cache_system.get_cached_species(CachedBushFactory) + ind = np.random.choice(len(species)) + s = species[ind] + fac = CachedBushFactory(s, coarse=True) + selection = density.placement_mask(uniform(0.015, 0.2), normal_thresh=0.3, + select_thresh=uniform(0.5, 0.6), tag=land_domain) + placement.scatter_placeholders_mesh(terrain_mesh, fac, altitude=-0.05, + overall_density=spec_density, distance_min=uniform(0.05, 0.3), + selection=selection) + p.run_stage('cached_fire_bushes', add_cached_fire_bushes, terrain_mesh) + + def add_cached_fire_boulders(terrain_mesh): + n_boulder_species = randint(1, params.get("max_boulder_species", 5)) + species = fire_cache_system.get_cached_species(CachedBoulderFactory) + ind = np.random.choice(len(species)) + s = species[ind] + fac = CachedBoulderFactory(s, coarse=True) + selection = density.placement_mask(0.05, tag=nonliving_domain, select_thresh=uniform(0.55, 0.6)) + placement.scatter_placeholders_mesh(terrain_mesh, fac, + overall_density=params.get("boulder_density", uniform(.02, .05)) / n_boulder_species, + selection=selection, altitude=-0.25) + p.run_stage('cached_fire_boulders', add_cached_fire_boulders, terrain_mesh) + + def add_cached_fire_cactus(terrain_mesh): + n_cactus_species = randint(2, params.get("max_cactus_species", 4)) + species = fire_cache_system.get_cached_species(CachedCactusFactory) + ind = np.random.choice(len(species)) + s = species[ind] + fac = CachedCactusFactory(s, coarse=True) + selection = density.placement_mask(scale=.05, tag=land_domain, select_thresh=0.57) + placement.scatter_placeholders_mesh(terrain_mesh, fac, altitude=-0.05, + overall_density=params.get('cactus_density', uniform(.02, .1) / n_cactus_species), + selection=selection, distance_min=1) + p.run_stage('cached_fire_cactus', add_cached_fire_cactus, terrain_mesh) diff --git a/worldgen/generate.py b/worldgen/generate.py index 6589f570f..bdaa5fa30 100644 --- a/worldgen/generate.py +++ b/worldgen/generate.py @@ -2,16 +2,11 @@ # This source code is licensed under the BSD 3-Clause license found in the LICENSE file in the root directory of this source tree. import argparse -import ast import os -import random import sys -import cProfile from pathlib import Path import logging -from functools import partial -import pprint -from collections import defaultdict +import itertools import bpy import mathutils @@ -19,41 +14,47 @@ import gin import numpy as np from numpy.random import uniform, normal, randint -from tqdm import tqdm -from frozendict import frozendict sys.path.append(os.getcwd()) from terrain import Terrain from util.organization import Task, Attributes, Tags, ElementNames -from placement import placement, density, camera as cam_util -from placement.split_in_view import split_inview from lighting import lighting, kole_clouds -from fluid.asset_cache import FireCachingSystem -from assets.trees.generate import TreeFactory, BushFactory, random_season, random_leaf_collection, CachedBushFactory, CachedTreeFactory +from assets.trees.generate import TreeFactory, BushFactory, random_season, random_leaf_collection from assets.glowing_rocks import GlowingRocksFactory -from assets.creatures import CarnivoreFactory, HerbivoreFactory, FishFactory, FishSchoolFactory, \ +from assets.creatures import ( + CarnivoreFactory, HerbivoreFactory, FishFactory, FishSchoolFactory, \ BeetleFactory, AntSwarmFactory, BirdFactory, SnakeFactory, \ - CrustaceanFactory, FlyingBirdFactory, CrabFactory, LobsterFactory, SpinyLobsterFactory, CachedCreatureFactory + CrustaceanFactory, FlyingBirdFactory, CrabFactory, LobsterFactory, SpinyLobsterFactory +) from assets.insects.assembled.dragonfly import DragonflyFactory from assets.cloud.generate import CloudFactory -from assets.cactus import CactusFactory,CachedCactusFactory -from assets.creatures import boid_swarm +from assets.cactus import CactusFactory + +from fluid.flip_fluid import make_river, make_tilted_river +from fluid.fluid_scenecomp_additions import fire_scenecomp_options import surfaces.scatters -from fluid.fluid import is_fire_in_scene -from fluid.flip_fluid import create_flip_fluid_domain, set_flip_fluid_domain, create_flip_fluid_inflow, set_flip_fluid_obstacle, get_objs_inside_domain, make_beach, make_river, make_tilted_river -from surfaces.scatters import rocks, grass, snow_layer, ground_leaves, ground_twigs, \ +from surfaces.scatters import ( + rocks, grass, snow_layer, ground_leaves, ground_twigs, \ chopped_trees, pinecone, fern, flowerplant, monocot, ground_mushroom, \ slime_mold, moss, ivy, lichen, mushroom, decorative_plants, seashells +) from surfaces.scatters.utils.selection import scatter_lower, scatter_upward -from surfaces.templates import mountain, sand, water, atmosphere_light_haze, sandstone, cracked_ground, \ +from surfaces.templates import ( + mountain, sand, water, atmosphere_light_haze, sandstone, cracked_ground, \ soil, dirt, cobble_stone, chunkyrock, stone, lava, ice, mud +) from infinigen_gpl.surfaces import snow -from placement import particles, placement, density, camera as cam_util, animation_policy, instance_scatter, detail +from placement import ( + particles, placement, density, + camera as cam_util, + animation_policy, instance_scatter, detail +) +from placement.split_in_view import split_inview from assets import particles as particle_assets from surfaces.scatters import pine_needle, seaweed, coral_reef, jellyfish, urchin @@ -90,9 +91,6 @@ def add_coarse_terrain(): terrain_bvh = mathutils.bvhtree.BVHTree.FromObject(terrain_mesh, bpy.context.evaluated_depsgraph_get()) - if params.get('cached_fire'): - fire_cache_system = FireCachingSystem() - land_domain = params.get('land_domain_tags') underwater_domain = params.get('underwater_domain_tags') nonliving_domain = params.get('nonliving_domain_tags') @@ -121,17 +119,6 @@ def add_trees(terrain_mesh): overall_density=params['density'], distance_min=params['distance_min']) p.run_stage('trees', add_trees, terrain_mesh) - def add_cached_fire_trees(terrain_mesh): - params = tree_species_params[0] - species = fire_cache_system.get_cached_species(CachedTreeFactory) - ind = np.random.choice(len(species)) - s = species[ind] - fac = CachedTreeFactory(s, coarse=True) - selection = density.placement_mask(params['select_scale'], tag=land_domain) - placement.scatter_placeholders_mesh(terrain_mesh, fac, selection=selection, altitude=-0.1, - overall_density=params['density'], distance_min=params['distance_min']) - p.run_stage('cached_fire_trees', add_cached_fire_trees, terrain_mesh) - def add_bushes(terrain_mesh): n_bush_species = randint(1, params.get("max_bush_species", 2) + 1) for i in range(n_bush_species): @@ -144,20 +131,6 @@ def add_bushes(terrain_mesh): selection=selection) p.run_stage('bushes', add_bushes, terrain_mesh) - def add_cached_fire_bushes(terrain_mesh): - n_bush_species = randint(1, params.get("max_bush_species", 2) + 1) - spec_density = params.get("bush_density", uniform(0.03, 0.12)) / n_bush_species - species = fire_cache_system.get_cached_species(CachedBushFactory) - ind = np.random.choice(len(species)) - s = species[ind] - fac = CachedBushFactory(s, coarse=True) - selection = density.placement_mask(uniform(0.015, 0.2), normal_thresh=0.3, - select_thresh=uniform(0.5, 0.6), tag=land_domain) - placement.scatter_placeholders_mesh(terrain_mesh, fac, altitude=-0.05, - overall_density=spec_density, distance_min=uniform(0.05, 0.3), - selection=selection) - p.run_stage('cached_fire_bushes', add_cached_fire_bushes, terrain_mesh) - def add_clouds(terrain_mesh): cloud_factory = CloudFactory(int_hash((scene_seed, 0)), coarse=True, terrain_mesh=terrain_mesh) placement.scatter_placeholders(cloud_factory.spawn_locations(), cloud_factory) @@ -173,17 +146,7 @@ def add_boulders(terrain_mesh): selection=selection, altitude=-0.25) p.run_stage('boulders', add_boulders, terrain_mesh) - def add_cached_fire_boulders(terrain_mesh): - n_boulder_species = randint(1, params.get("max_boulder_species", 5)) - species = fire_cache_system.get_cached_species(boulder.CachedBoulderFactory) - ind = np.random.choice(len(species)) - s = species[ind] - fac = boulder.CachedBoulderFactory(s, coarse=True) - selection = density.placement_mask(0.05, tag=nonliving_domain, select_thresh=uniform(0.55, 0.6)) - placement.scatter_placeholders_mesh(terrain_mesh, fac, - overall_density=params.get("boulder_density", uniform(.02, .05)) / n_boulder_species, - selection=selection, altitude=-0.25) - p.run_stage('cached_fire_boulders', add_cached_fire_boulders, terrain_mesh) + fire_scenecomp_options(p, terrain_mesh, params, tree_species_params) def add_glowing_rocks(terrain_mesh): selection = density.placement_mask(uniform(0.03, 0.3), normal_thresh=-1.1, select_thresh=0, tag=Tags.Cave) @@ -210,18 +173,6 @@ def add_cactus(terrain_mesh): selection=selection, distance_min=1) p.run_stage('cactus', add_cactus, terrain_mesh) - def add_cached_fire_cactus(terrain_mesh): - n_cactus_species = randint(2, params.get("max_cactus_species", 4)) - species = fire_cache_system.get_cached_species(CachedCactusFactory) - ind = np.random.choice(len(species)) - s = species[ind] - fac = CachedCactusFactory(s, coarse=True) - selection = density.placement_mask(scale=.05, tag=land_domain, select_thresh=0.57) - placement.scatter_placeholders_mesh(terrain_mesh, fac, altitude=-0.05, - overall_density=params.get('cactus_density', uniform(.02, .1) / n_cactus_species), - selection=selection, distance_min=1) - p.run_stage('cached_fire_cactus', add_cached_fire_cactus, terrain_mesh) - def camera_preprocess(): camera_rigs = cam_util.spawn_camera_rigs() scene_preprocessed = cam_util.camera_selection_preprocessing(terrain, terrain_mesh) @@ -418,7 +369,7 @@ def add_snow_particles(): emitter=butil.spawn_plane(location=emitter_off, size=60), subject=make_asset_collection(particle_assets.SnowflakeFactory(scene_seed), 5), settings=particles.snow_settings()) - + particle_systems = [ p.run_stage('leaf_particles', add_leaf_particles, prereq='trees'), p.run_stage('rain_particles', add_rain_particles), @@ -433,8 +384,18 @@ def add_snow_particles(): particles.bake(emitter, system) butil.put_in_collection(emitter, butil.get_collection('particles')) - p.save_results(output_folder/'pipeline_coarse.csv') + placeholders = list(itertools.chain.from_iterable( + c.all_objects for c in bpy.data.collections if c.name.startswith('placeholders:') + )) + + add_simulated_river = lambda: make_river(terrain_mesh, placeholders, output_folder=output_folder) + p.run_stage('simulated_river', add_simulated_river, use_chance=False) + + add_tilted_river = lambda: make_tilted_river(terrain_mesh, placeholders, output_folder=output_folder) + p.run_stage('tilted_river', add_tilted_river, use_chance=False) + + p.save_results(output_folder/'pipeline_coarse.csv') return terrain, terrain_mesh def main(): diff --git a/worldgen/placement/animation_policy.py b/worldgen/placement/animation_policy.py index 8a8bbc5dd..aeb5f08d0 100644 --- a/worldgen/placement/animation_policy.py +++ b/worldgen/placement/animation_policy.py @@ -33,7 +33,16 @@ def get_altitude(loc, terrain_bvh, dir=Vector((0.,0.,-1.))): return straight_down_dist @gin.configurable -def walk_same_altitude(start_loc, sampler, bvh, filter_func=None, fall_ratio=1.5, retries=30, step_up_height=2, simulated = False): +def walk_same_altitude( + start_loc, + sampler, + bvh, + filter_func=None, + fall_ratio=1.5, + retries=30, + step_up_height=2, + ignore_missed_rays=False +): ''' fall_ratio: what is the slope at which the camera is willing to go down / glide @@ -48,7 +57,7 @@ def walk_same_altitude(start_loc, sampler, bvh, filter_func=None, fall_ratio=1.5 curr_alt = get_altitude(start_loc, bvh) new_alt = get_altitude(pos, bvh) - if simulated: + if ignore_missed_rays: if curr_alt is None: curr_alt = start_loc.z if new_alt is None: diff --git a/worldgen/placement/camera.py b/worldgen/placement/camera.py index 55bf2d45f..9a003eb58 100644 --- a/worldgen/placement/camera.py +++ b/worldgen/placement/camera.py @@ -215,15 +215,17 @@ def camera_pose_proposal( terrain_bvh, terrain_bbox, altitude=2, - pitch=90, roll=0, - headspace_retries=10, - loc_specified = None, - rot_specified = None, - simulated_scene = None + yaw=('uniform', -180, 180), + pitch=90, + headspace_retries=30, + override_loc=None, ): - loc = np.random.uniform(*terrain_bbox) + if override_loc is None: + loc = np.random.uniform(*terrain_bbox) + else: + loc = Vector(random_general(override_loc)) alt = animation_policy.get_altitude(loc, terrain_bvh) if alt is None: return None @@ -245,19 +247,10 @@ def camera_pose_proposal( return None loc[2] = loc[2] + zoff - if loc[2] > terrain_bbox[1][2] or loc[2] < terrain_bbox[0][2]: return None - - yaw = np.random.uniform(-180, 180) - rot = np.deg2rad([random_general(pitch), random_general(roll), yaw]) - - if simulated_scene: - loc = np.array(loc_specified) - if simulated_scene == "tilted_river": - rot = np.deg2rad((rot_specified[0]+np.random.normal(0, 5),rot_specified[1],rot_specified[2])) - else: - rot = np.deg2rad(rot_specified) - + if loc[2] > terrain_bbox[1][2] or loc[2] < terrain_bbox[0][2]: + return None + rot = np.deg2rad([random_general(pitch), random_general(roll), random_general(yaw)]) return loc, rot diff --git a/worldgen/placement/placement.py b/worldgen/placement/placement.py index 3ff841f07..9a63f7b14 100644 --- a/worldgen/placement/placement.py +++ b/worldgen/placement/placement.py @@ -199,7 +199,7 @@ def populate_collection( asset_col_target.hide_viewport = False factory.finalize_assets([r for i, r in all_objs]) - asset_col_target.hide_viewport = False + asset_col_target.hide_viewport = True return all_objs, updated_pholders diff --git a/worldgen/terrain/core.py b/worldgen/terrain/core.py index 644fec204..396afcb44 100644 --- a/worldgen/terrain/core.py +++ b/worldgen/terrain/core.py @@ -83,8 +83,6 @@ def __init__( self.on_the_fly_asset_folder = Path(on_the_fly_asset_folder) self.reused_asset_folder = asset_path - os.environ["ASSET_PATH"] = str(asset_path) - self.elements, scene_infos = scene(seed, Path(on_the_fly_asset_folder), asset_path, device) self.elements_list = list(self.elements.values()) diff --git a/worldgen/tools/install/compile_flip_fluids.sh b/worldgen/tools/install/compile_flip_fluids.sh new file mode 100644 index 000000000..62d4e9087 --- /dev/null +++ b/worldgen/tools/install/compile_flip_fluids.sh @@ -0,0 +1,12 @@ +FLIP_FLUIDS="https://github.com/rlguy/Blender-FLIP-Fluids" +FLIP_FLUIDS_FOLDER="Blender-FLIP-Fluids" +FLIP_FLUIDS_ADDON_FOLDER="${FLIP_FLUIDS_FOLDER}/build/bl_flip_fluids/flip_fluids_addon" + +if [ ! -d "${FLIP_FLUIDS_ADDON_FOLDER}" ]; then + git clone "${FLIP_FLUIDS}" + cd "${FLIP_FLUIDS_FOLDER}" + python build.py + cd - + cp -r "${FLIP_FLUIDS_ADDON_FOLDER}" "${BLENDER_ADDONS}" + "${BLENDER_EXE}" --background -noaudio -P ./worldgen/fluid/flip_init.py +fi \ No newline at end of file diff --git a/worldgen/tools/compile_opengl.sh b/worldgen/tools/install/compile_opengl.sh similarity index 100% rename from worldgen/tools/compile_opengl.sh rename to worldgen/tools/install/compile_opengl.sh diff --git a/worldgen/tools/pipeline_configs/compute_platform/slurm_high_memory.gin b/worldgen/tools/pipeline_configs/compute_platform/slurm_high_memory.gin new file mode 100644 index 000000000..ffb4086d8 --- /dev/null +++ b/worldgen/tools/pipeline_configs/compute_platform/slurm_high_memory.gin @@ -0,0 +1,13 @@ +include 'tools/pipeline_configs/compute_platform/slurm.gin' + +# Combined (only used when `stereo_combined.gin` or similar is included) +queue_combined.mem_gb = 48 +queue_combined.cpus = 4 +queue_coarse.mem_gb = 48 +queue_coarse.cpus = 4 +queue_fine_terrain.mem_gb = 48 +queue_fine_terrain.cpus = 4 +queue_populate.mem_gb = 48 +queue_populate.cpus = 4 +queue_populate.hours = 24 +renderbackup/queue_populate.mem_gb = 48 diff --git a/worldgen/tools/pipeline_configs/monocular_video_river.gin b/worldgen/tools/pipeline_configs/monocular_video_river.gin deleted file mode 100644 index f8c8284d3..000000000 --- a/worldgen/tools/pipeline_configs/monocular_video_river.gin +++ /dev/null @@ -1,18 +0,0 @@ - -iterate_scene_tasks.num_resamples = 1 -iterate_scene_tasks.frame_range = [100, 244] -iterate_scene_tasks.view_block_size = 16 -iterate_scene_tasks.cam_id_ranges = [1, 1] - -iterate_scene_tasks.global_tasks = [ - {'name': 'coarse', 'func': @queue_coarse}, - {'name': "populate", 'func': @queue_populate}, - {'name': 'backuppopulate', 'func': @renderbackup/queue_populate, 'condition': 'prev_failed'} -] -iterate_scene_tasks.view_dependent_tasks = [ - {'name': "fineterrain", 'func': @queue_fine_terrain}, -] -iterate_scene_tasks.camera_dependent_tasks = [ - {'name': 'shortrender', 'func': @rendershort/queue_render}, - {'name': 'backuprender', 'func': @renderbackup/queue_render, 'condition': 'prev_failed'}, -] diff --git a/worldgen/tools/pipeline_configs/slurm_fluid.gin b/worldgen/tools/pipeline_configs/slurm_fluid.gin deleted file mode 100644 index c779a5e6a..000000000 --- a/worldgen/tools/pipeline_configs/slurm_fluid.gin +++ /dev/null @@ -1,87 +0,0 @@ - -PARTITION = None - -manage_datagen_jobs.num_concurrent = 800 -get_slurm_banned_nodes.config_path = None # add a white-space separated txt file path here - -# Combined (only used when `stereo_combined.gin` or similar is included) -queue_combined.mem_gb = 48 -queue_combined.cpus = 2 -queue_combined.hours = 48 -queue_combined.slurm_account = %PARTITION -queue_combined.submit_cmd = @slurm_submit_cmd -renderbackup/queue_combined.mem_gb = 24 - -# Coarse -queue_coarse.mem_gb = 48 -queue_coarse.cpus = 4 -queue_coarse.hours = 48 -queue_coarse.slurm_account = %PARTITION -queue_coarse.submit_cmd = @slurm_submit_cmd - -# Fine terrain -queue_fine_terrain.mem_gb = 48 -queue_fine_terrain.cpus = 4 -queue_fine_terrain.hours = 24 -queue_fine_terrain.slurm_account = %PARTITION -queue_fine_terrain.submit_cmd = @slurm_submit_cmd - -# Fine -queue_populate.mem_gb = 48 -queue_populate.cpus = 4 -queue_populate.hours = 24 -queue_populate.slurm_account = %PARTITION -queue_populate.submit_cmd = @slurm_submit_cmd -renderbackup/queue_populate.mem_gb = 48 - -# Rendering -queue_render.submit_cmd = @slurm_submit_cmd -queue_render.hours = 48 - -rendershort/queue_render.exclude_gpus = [] -# no point requesting less than 48GB RAM, 8CPUs, due to ratios of RAM:GPUs on pvl -rendershort/queue_render.mem_gb = 48 -rendershort/queue_render.cpus = 8 -rendershort/queue_render.slurm_account = %PARTITION -rendershort/queue_render.gpus = 1 -rendershort/queue_render.render_type = "full" - -queue_render.exclude_gpus = ['gtx_1080', 'k80'] -renderbackup/queue_render.exclude_gpus = ['gtx_1080', 'k80', 'rtx_2080'] - -renderbackup/queue_render.mem_gb = 64 -renderbackup/queue_render.cpus = 12 -renderbackup/queue_render.slurm_account = %PARTITION -renderbackup/queue_render.gpus = 1 -renderbackup/queue_render.render_type = "full" - -# Upload -queue_upload.submit_cmd = @slurm_submit_cmd -queue_upload.slurm_account = %PARTITION -queue_upload.mem_gb = 6 -queue_upload.cpus = 2 -queue_upload.hours = 24 -queue_upload.method = 'smbclient' -queue_upload.dir_prefix_len = 2 - -# Ground Truth -queue_mesh_save.submit_cmd = @slurm_submit_cmd -queue_mesh_save.mem_gb = 48 -queue_mesh_save.cpus = 4 -queue_mesh_save.hours = 24 -queue_mesh_save.slurm_account = %PARTITION -queue_mesh_save.gpus = 0 - -queue_opengl.submit_cmd = @slurm_submit_cmd -queue_opengl.mem_gb = 48 -queue_opengl.cpus = 4 -queue_opengl.hours = 24 -queue_opengl.slurm_account = %PARTITION -queue_opengl.gpus = 1 - -ground_truth/queue_render.exclude_gpus = [] -ground_truth/queue_render.mem_gb = 48 -ground_truth/queue_render.hours = 24 -ground_truth/queue_render.slurm_account = %PARTITION -ground_truth/queue_render.gpus = 0 -ground_truth/queue_render.render_type = "flat" diff --git a/worldgen/tools/scripts/render_river_video.sh b/worldgen/tools/scripts/render_river_video.sh index 64e8c624a..8c9def4fb 100644 --- a/worldgen/tools/scripts/render_river_video.sh +++ b/worldgen/tools/scripts/render_river_video.sh @@ -3,9 +3,9 @@ HOSTFIRST=$(hostname | tr "." "\n" | head -n 1) JOBNAME=$(date '+%m_%d_%H_%M').$HOSTFIRST.$1 if [ "$2" = "dev" ]; then - python -m tools.manage_datagen_jobs --blender_path ../blender/blender --output_folder $3/$JOBNAME --num_scenes 20 \ + python -m tools.manage_datagen_jobs --output_folder $3/$JOBNAME --num_scenes 20 \ --pipeline_config $1 monocular_video_river enable_gpu opengl_gt --wandb_mode online --cleanup none --warmup_sec 12000 --config trailer_river dev reuse_terrain_assets simulated_river else - python -m tools.manage_datagen_jobs --blender_path ../blender/blender --output_folder $3/$JOBNAME --num_scenes 50 \ + python -m tools.manage_datagen_jobs --output_folder $3/$JOBNAME --num_scenes 50 \ --pipeline_config $1 monocular_video_river enable_gpu opengl_gt --wandb_mode online --cleanup big_files --warmup_sec 12000 --config trailer_river reuse_terrain_assets simulated_river high_quality_terrain fi diff --git a/worldgen/tools/scripts/render_video_1080p.sh b/worldgen/tools/scripts/render_video_1080p.sh index 5b54f3d97..18944b2ca 100644 --- a/worldgen/tools/scripts/render_video_1080p.sh +++ b/worldgen/tools/scripts/render_video_1080p.sh @@ -1,7 +1,7 @@ HOSTFIRST=$(hostname | tr "." "\n" | head -n 1) JOBNAME=$(date '+%m_%d_%H_%M').$HOSTFIRST.$1 -python -m tools.manage_datagen_jobs --blender_path ../blender/blender --output_folder outputs/$JOBNAME \ +python -m tools.manage_datagen_jobs --output_folder outputs/$JOBNAME \ --num_scenes 100 --pipeline_config $@ stereo_video cuda_terrain opengl_gt_noshortrender \ --wandb_mode online --cleanup big_files --upload \ --warmup_sec 40000 \ diff --git a/worldgen/tools/scripts/render_video_fire.sh b/worldgen/tools/scripts/render_video_fire.sh index 3c41beb81..4660c09f5 100644 --- a/worldgen/tools/scripts/render_video_fire.sh +++ b/worldgen/tools/scripts/render_video_fire.sh @@ -2,5 +2,5 @@ HOSTFIRST=$(hostname | tr "." "\n" | head -n 1) JOBNAME=$(date '+%m_%d_%H_%M').$HOSTFIRST.$1 -python -m tools.manage_datagen_jobs --blender_path ../blender/blender --output_folder $3/$JOBNAME --num_scenes $2 \ +python -m tools.manage_datagen_jobs --output_folder $3/$JOBNAME --num_scenes $2 \ --pipeline_config $1 monocular_video enable_gpu opengl_gt --wandb_mode online --cleanup none --warmup_sec 10000 --config trailer high_quality_terrain reuse_terrain_assets use_on_the_fly_fire diff --git a/worldgen/util/blender.py b/worldgen/util/blender.py index 4736e3599..aefc212da 100644 --- a/worldgen/util/blender.py +++ b/worldgen/util/blender.py @@ -142,6 +142,23 @@ def __exit__(self, *_): for m in self.modifiers_disabled: m.show_viewport = True +class EnableParentCollections: + + def __init__(self, objs, target_key='hide_viewport', target_value=False): + self.objs = objs + self.target_key = target_key + self.target_value = target_value + + def __enter__(self): + self.enable_cols = set(chain.from_iterable([o.users_collection for o in self.objs])) + self.enable_cols_startstate = [getattr(c, self.target_key) for c in self.enable_cols] + + for c in self.enable_cols: + setattr(c, self.target_key, self.target_value) + + def __exit__(self, *_, **__): + for c, s in zip(self.enable_cols, self.enable_cols_startstate): + setattr(c, self.target_key, s) class TemporaryObject: