Skip to content

Commit

Permalink
Merge branch 'develop' for v1.11.1
Browse files Browse the repository at this point in the history
  • Loading branch information
pvl-bot committed Nov 18, 2024
2 parents 75cb36e + e91a4fd commit 368ffff
Show file tree
Hide file tree
Showing 19 changed files with 230 additions and 108 deletions.
9 changes: 9 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,12 @@ v1.10.1

v1.11.0
- Update to Blender == 4.2.0

v1.11.1
- Fix failed camera search when canyon/cliff/cave loaded as nature background
- Fix scrambled GT maps in blender_gt due to incorrect OpenEXR pixel unpack ordering
- Fix save_mesh kwarg mismatch from v1.10.0
- Remove `frozendict` dependency, make `geomdl` optional if not using creatures
- Make `submitit` optional if not using SLURM
- Make blender addons optional if not using relevant assets (rocks/terrain/snowlayer)
- Make `bnurbs` CPython module optional and not installed by default
2 changes: 1 addition & 1 deletion infinigen/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import logging
from pathlib import Path

__version__ = "1.11.0"
__version__ = "1.11.1"


def repo_root():
Expand Down
5 changes: 5 additions & 0 deletions infinigen/assets/fluid/fluid.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
water,
waterfall_material,
)
from infinigen.core.init import require_blender_addon
from infinigen.core.nodes.node_wrangler import (
Nodes,
NodeWrangler,
Expand All @@ -34,6 +35,8 @@

FLUID_INITIALIZED = False

require_blender_addon("antlandscape", fail="warn")


def check_initalize_fluids():
if FLUID_INITIALIZED:
Expand Down Expand Up @@ -621,6 +624,8 @@ def generate_waterfall(

seed = np.random.randint(10000)

require_blender_addon("antlandscape")

bpy.ops.mesh.landscape_add(
ant_terrain_name="Landscape",
land_material="",
Expand Down
5 changes: 5 additions & 0 deletions infinigen/assets/objects/rocks/blender_rock.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@
import numpy as np
from numpy.random import uniform as U

from infinigen.core.init import require_blender_addon
from infinigen.core.placement.factory import AssetFactory
from infinigen.core.tagging import tag_object
from infinigen.core.util import blender as butil

require_blender_addon("extra_mesh_objects", fail="warn")


class BlenderRockFactory(AssetFactory):
def __init__(self, factory_seed, detail=1):
Expand All @@ -21,6 +24,8 @@ def __init__(self, factory_seed, detail=1):
__repr__ = AssetFactory.__repr__

def create_asset(self, **params):
require_blender_addon("extra_mesh_objects")

seed = np.random.randint(0, 99999)

zscale = U(0.2, 0.8)
Expand Down
5 changes: 5 additions & 0 deletions infinigen/assets/scatters/snow_layer.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@

import bpy

from infinigen.core.init import require_blender_addon
from infinigen.core.tagging import tag_object
from infinigen.core.util import blender as butil

require_blender_addon("real_snow", fail="warn")


class Snowlayer:
def apply(self, obj, **kwargs):
require_blender_addon("real_snow")

bpy.context.scene.snow.height = 0.1
with butil.SelectObjects(obj):
bpy.ops.snow.create()
Expand Down
36 changes: 30 additions & 6 deletions infinigen/assets/utils/geometry/nurbs.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,25 @@
import bmesh
import bpy
import numpy as np
from geomdl import NURBS

from infinigen.core.util import blender as butil

logger = logging.getLogger(__name__)

try:
import bnurbs
from geomdl import NURBS
except ImportError:
logger.warning(
"Failed to import compiled `bnurbs` package, either installation failed or we are running a minimal install"
"Failed to import `geomdl` package, generation will crash if `geomdl` is used"
)
NURBS = None

try:
import bnurbs
except ImportError:
# logger.warning(
# "Failed to import compiled `bnurbs` package, either installation failed or we are running a minimal install"
# )
bnurbs = None


Expand Down Expand Up @@ -147,6 +154,12 @@ def blender_nurbs(
spline.use_cyclic_v = cyclic_v
spline.resolution_u, spline.resolution_v = resolution

if (kv_u is not None or kv_v is not None) and bnurbs is None:
logger.warning(
"Failed to import compiled `bnurbs` package. `bnurbs` extension is no longer compiled by default, "
f"please either install it via BUILD_BNURBS=True during install, or avoid calling {blender_nurbs.__name__}"
)

if kv_u is not None:
bnurbs.set_knotsu(spline, kv_u)
if kv_v is not None:
Expand Down Expand Up @@ -208,7 +221,12 @@ def blender_mesh_from_pydata(points, edges, faces, uvs=None, name="pydata_mesh")
return obj


def blender_nurbs_to_geomdl(s: bpy.types.Spline) -> NURBS.Surface:
def blender_nurbs_to_geomdl(s: bpy.types.Spline):
if NURBS is None:
raise ImportError(
f"geomdl was not found at runtime, please either install `geomdl` or avoid calling {blender_nurbs_to_geomdl.__name__}"
)

surf = NURBS.Surface(normalize_kv=False)

surf.degree_u, surf.degree_v = (s.order_u - 1, s.order_v - 1)
Expand All @@ -217,7 +235,8 @@ def blender_nurbs_to_geomdl(s: bpy.types.Spline) -> NURBS.Surface:

if bnurbs is None:
logger.warning(
"Failed to import compiled `bnurbs` package, either installation failed or we are running a minimal install"
"Failed to import compiled `bnurbs` package. `bnurbs` extension is no longer compiled by default, "
f"please either install it via BUILD_BNURBS=True during install, or avoid calling {blender_nurbs_to_geomdl.__name__}"
)
surf.knotvector_u = bnurbs.get_knotsu(s)
surf.knotvector_v = bnurbs.get_knotsv(s)
Expand All @@ -241,7 +260,7 @@ def blender_nurbs_to_geomdl(s: bpy.types.Spline) -> NURBS.Surface:
return surf


def geomdl_to_mesh(surf: NURBS.Surface, eval_delta, name="geomdl_mesh"):
def geomdl_to_mesh(surf, eval_delta, name="geomdl_mesh"):
surf.delta = eval_delta
points = np.array(surf.evalpts)

Expand Down Expand Up @@ -277,6 +296,11 @@ def map_uv_to_valid_domain(s: bpy.types.Spline, uv: np.array):
def geomdl_nurbs(
ctrlpts, eval_delta, ws=None, kv_u=None, kv_v=None, name="loft_nurbs", cyclic_v=True
):
if NURBS is None:
raise ImportError(
f"geomdl was not found at runtime, please either install `geomdl` or avoid calling {geomdl_nurbs}"
)

n, m, _ = ctrlpts.shape
degree_u, degree_v = (3, 3)

Expand Down
21 changes: 11 additions & 10 deletions infinigen/core/execute_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

import bpy
import gin
from frozendict import frozendict

import infinigen.assets.scatters
from infinigen.core import init, surface
Expand Down Expand Up @@ -102,7 +101,7 @@ def save_meshes(
for col in bpy.data.collections:
col.hide_viewport = col.hide_render

previous_frame_mesh_id_mapping = frozendict()
previous_frame_mesh_id_mapping = dict()
current_frame_mesh_id_mapping = defaultdict(dict)

# save static meshes
Expand All @@ -118,7 +117,7 @@ def save_meshes(
previous_frame_mesh_id_mapping,
current_frame_mesh_id_mapping,
)
previous_frame_mesh_id_mapping = frozendict(current_frame_mesh_id_mapping)
previous_frame_mesh_id_mapping = dict(current_frame_mesh_id_mapping)
current_frame_mesh_id_mapping.clear()

for obj in bpy.data.objects:
Expand All @@ -139,12 +138,13 @@ def save_meshes(
previous_frame_mesh_id_mapping,
current_frame_mesh_id_mapping,
)
cam_util.save_camera_parameters(
camera_ids=cameras,
output_folder=frame_info_folder / "cameras",
frame=frame_idx,
)
previous_frame_mesh_id_mapping = frozendict(current_frame_mesh_id_mapping)
for cam in cameras:
cam_util.save_camera_parameters(
camera_obj=cam,
output_folder=frame_info_folder / "cameras",
frame=frame_idx,
)
previous_frame_mesh_id_mapping = dict(current_frame_mesh_id_mapping)
current_frame_mesh_id_mapping.clear()


Expand Down Expand Up @@ -341,13 +341,14 @@ def execute_tasks(
save_meshes(
scene_seed,
output_folder=output_folder,
cameras=[c for rig in camera_rigs for c in rig.children],
frame_range=frame_range,
point_trajectory_src_frame=point_trajectory_src_frame,
)


def main(input_folder, output_folder, scene_seed, task, task_uniqname, **kwargs):
version_req = ["3.6.0", "4.2.0"]
version_req = ["4.2.0"]
assert bpy.app.version_string in version_req, (
f"You are using blender={bpy.app.version_string} which is "
f"not supported. Please use {version_req}"
Expand Down
64 changes: 47 additions & 17 deletions infinigen/core/init.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,53 @@ def configure_cycles_devices(use_gpu=True):
return use_devices


def require_blender_addon(addon: str, fail: str = "fatal", allow_online=False):
def report_fail(msg):
if fail == "warn":
logger.warning(
msg + ". Generation may crash at runtime if certain assets are used."
)
elif fail == "fatal":
raise ValueError(msg)
else:
raise ValueError(
f"{require_blender_addon.__name__} got unrecognized {fail=}"
)

long = f"bl_ext.blender_org.{addon}"

addon_present = long in bpy.context.preferences.addons.keys()

if addon_present:
logger.debug(f"Addon {addon} already present.")
return True

builtin_local_addons = set(a.__name__ for a in addon_utils.modules(refresh=True))

if addon not in builtin_local_addons and not allow_online:
report_fail(f"{addon=} not found and online install is disabled")

try:
if long in builtin_local_addons:
logger.info(f"Addon {addon} already in blender local addons, attempt to enable it.")
bpy.ops.preferences.addon_enable(module=long)
else:
bpy.ops.extensions.userpref_allow_online()
logger.info(f"Installing Add-on {addon}.")
bpy.ops.extensions.repo_sync(repo_index=0)
bpy.ops.extensions.package_install(
repo_index=0, pkg_id=addon, enable_on_install=True
)
bpy.ops.preferences.addon_enable(module=long)
except Exception as e:
report_fail(f"Failed to install {addon=} due to {e=}")

if long not in bpy.context.preferences.addons.keys():
report_fail(f"Attempted to install {addon=} but wasnt found after install")

return True


@gin.configurable
def configure_blender(
render_engine="CYCLES",
Expand All @@ -293,20 +340,3 @@ def configure_blender(
if motion_blur:
bpy.context.scene.cycles.motion_blur_position = "START"
bpy.context.scene.render.motion_blur_shutter = motion_blur_shutter

addons = ["extra_mesh_objects", "real_snow", "antlandscape"]
for addon in addons:
long = f"bl_ext.blender_org.{addon}"
all_addons = set(a.__name__ for a in addon_utils.modules(refresh=True))
if long in all_addons:
bpy.ops.preferences.addon_enable(module=long)
else:
bpy.ops.extensions.userpref_allow_online()
logger.info(f"Installing Add-on {addon}.")
bpy.ops.extensions.repo_sync(repo_index=0)
bpy.ops.extensions.package_install(
repo_index=0, pkg_id=addon, enable_on_install=True
)
bpy.ops.preferences.addon_enable(module=long)
assert long in bpy.context.preferences.addons.keys()
logger.info(f"{addon} enabled.")
16 changes: 8 additions & 8 deletions infinigen/core/placement/camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ def keep_cam_pose_proposal(
return None

coverage = len(dists) / n_pix
if (
if terrain_coverage_range is not None and (
coverage < terrain_coverage_range[0]
or coverage > terrain_coverage_range[1]
or coverage == 0
Expand Down Expand Up @@ -435,12 +435,10 @@ def compute_base_views(
radius=None,
bbox=None,
placeholders_kd=None,
camera_selection_answers={},
vertexwise_min_dist=None,
camera_selection_ratio=None,
min_candidates_ratio=20,
max_tries=30000,
visualize=False,
**kwargs,
):
potential_views = []
n_min_candidates = int(min_candidates_ratio * n_views)
Expand Down Expand Up @@ -475,9 +473,7 @@ def compute_base_views(
terrain,
scene_bvh,
placeholders_kd,
camera_selection_answers=camera_selection_answers,
vertexwise_min_dist=vertexwise_min_dist,
camera_selection_ratio=camera_selection_ratio,
**kwargs,
)
all_scores.append(score)

Expand Down Expand Up @@ -660,6 +656,7 @@ def configure_cameras(
nonroom_objs=None,
mvs_setting=False,
mvs_radius=("uniform", 12, 18),
**kwargs,
):
bpy.context.view_layer.update()

Expand Down Expand Up @@ -716,6 +713,7 @@ def contain_keywords(name, keywords):
radius=mvs_radius,
bbox=init_bounding_box,
**scene_preprocessed,
**kwargs,
)

score, props, focus_dist = views[0]
Expand All @@ -740,6 +738,7 @@ def animate_cameras(
pois=None,
follow_poi_chance=0.0,
policy_registry=None,
**kwargs,
):
animation_ratio = {}
animation_answers = {}
Expand All @@ -760,6 +759,7 @@ def anim_valid_camrig_pose_func(cam_rig: bpy.types.Object):
vertexwise_min_dist=scene_preprocessed["vertexwise_min_dist"],
camera_selection_answers=animation_answers,
camera_selection_ratio=animation_ratio,
**kwargs,
)

if score is None:
Expand Down Expand Up @@ -793,7 +793,7 @@ def anim_valid_camrig_pose_func(cam_rig: bpy.types.Object):

@gin.configurable
def save_camera_parameters(
camera_obj: bpy.types.Object, output_folder, frame, use_dof=False
camera_obj: bpy.types.Object, output_folder: Path, frame: int, use_dof=False
):
output_folder = Path(output_folder)
output_folder.mkdir(exist_ok=True, parents=True)
Expand Down
Loading

0 comments on commit 368ffff

Please sign in to comment.