Spaces:
Running
on
Zero
Running
on
Zero
import os | |
import sys | |
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | |
import numpy as np | |
import cv2 | |
import gin | |
import bpy | |
import gc | |
import logging | |
import argparse | |
from pathlib import Path | |
import importlib | |
import yaml | |
logging.basicConfig( | |
format="[%(asctime)s.%(msecs)03d] [%(module)s] [%(levelname)s] | %(message)s", | |
datefmt="%H:%M:%S", | |
level=logging.INFO, | |
) | |
logger = logging.getLogger(__name__) | |
import infinigen | |
from infinigen.core import init, surface | |
from infinigen.assets.utils.decorate import read_co | |
from infinigen.assets.utils.misc import assign_material | |
from infinigen.core.util import blender as butil | |
from infinigen.assets.lighting import ( | |
hdri_lighting, | |
holdout_lighting, | |
sky_lighting, | |
three_point_lighting, | |
) | |
from core.utils.vis_utils import colorObj, setMat_plastic | |
def generate(generator, params, seed, mesh_save_path, no_mod=False, no_ground=True): | |
print(params) | |
print("Generating") | |
# reset to default | |
bpy.ops.wm.read_homefile(app_template="") | |
butil.clear_scene() | |
# Suppress info messages | |
bpy.ops.outliner.orphans_purge() | |
gc.collect() | |
# configurate infinigen | |
gin.add_config_file_search_path("./configs/infinigen") | |
gin.parse_config_files_and_bindings( | |
["configs/infinigen/base.gin"], | |
bindings=[], | |
skip_unknown=True, | |
finalize_config=False, | |
) | |
surface.registry.initialize_from_gin() | |
print("Configured") | |
# setup the scene | |
scene = bpy.context.scene | |
scene.render.engine = "CYCLES" | |
scene.cycles.device = "GPU" | |
scene.render.film_transparent = True | |
bpy.context.preferences.system.scrollback = 0 | |
bpy.context.preferences.edit.undo_steps = 0 | |
prefs = bpy.context.preferences.addons["cycles"].preferences | |
for dt in prefs.get_device_types(bpy.context): | |
prefs.get_devices_for_type(dt[0]) | |
bpy.context.preferences.addons["cycles"].preferences.compute_device_type = "CUDA" | |
use_devices = [d for d in prefs.devices if d.type == "CUDA"] | |
for d in prefs.devices: | |
d.use = False | |
for d in use_devices: | |
d.use = True | |
bpy.context.scene.world.node_tree.nodes["Background"].inputs[0].default_value[0:3] = (0.0, 0.0, 0.0) | |
print("Setup done") | |
# update the parameters | |
generator.update_params(params) | |
# generate the object | |
asset = generator.spawn_asset(seed) | |
generator.finalize_assets(asset) | |
print("Generated") | |
parent = asset | |
if asset.type == "EMPTY": | |
meshes = [o for o in asset.children_recursive if o.type == "MESH"] | |
sizes = [] | |
for m in meshes: | |
co = read_co(m) | |
sizes.append((np.amax(co, 0) - np.amin(co, 0)).sum()) | |
i = np.argmax(np.array(sizes)) | |
asset = meshes[i] | |
if not no_mod: | |
if parent.animation_data is not None: | |
drivers = parent.animation_data.drivers.values() | |
for d in drivers: | |
parent.driver_remove(d.data_path) | |
co = read_co(asset) | |
x_min, x_max = np.amin(co, 0), np.amax(co, 0) | |
parent.location = -(x_min[0] + x_max[0]) / 2, -(x_min[1] + x_max[1]) / 2, 0 | |
butil.apply_transform(parent, loc=True) | |
if not no_ground: | |
bpy.ops.mesh.primitive_grid_add( | |
size=5, x_subdivisions=400, y_subdivisions=400 | |
) | |
plane = bpy.context.active_object | |
plane.location[-1] = x_min[-1] | |
plane.is_shadow_catcher = True | |
material = bpy.data.materials.new("plane") | |
material.use_nodes = True | |
material.node_tree.nodes["Principled BSDF"].inputs[0].default_value = ( | |
0.015, | |
0.009, | |
0.003, | |
1, | |
) | |
assign_material(plane, material) | |
# dump mesh model | |
save_mesh_filepath = mesh_save_path | |
bpy.ops.export_scene.gltf(filepath=save_mesh_filepath) | |
print("Mesh saved in {}".format(save_mesh_filepath)) | |
if __name__ == "__main__": | |
argparser = argparse.ArgumentParser() | |
argparser.add_argument("--config", type=str, required=True) | |
argparser.add_argument('--output_path', type=str, required=True) | |
argparser.add_argument('--params_path', type=str, required=True) | |
argparser.add_argument('--seed', type=int, default=0) | |
args = argparser.parse_args() | |
# load config | |
with open(args.config) as f: | |
cfg = yaml.load(f, Loader=yaml.FullLoader) | |
# load generators | |
generators_choices = ["chair", "table", "vase", "basket", "flower", "dandelion"] | |
factory_names = ["ChairFactory", "TableDiningFactory", "VaseFactory", "BasketBaseFactory", "FlowerFactory", "DandelionFactory"] | |
category = args.config.split("/")[-1].split("_")[0] | |
idx = generators_choices.index(category) | |
# load generator | |
module = importlib.import_module(f"core.assets.{category}") | |
gen = getattr(module, factory_names[idx]) | |
generator = gen(args.seed) | |
# load params | |
params = np.load(args.params_path, allow_pickle=True).item() | |
generate(generator, params, args.seed, args.output_path) |