import bpy from mathutils import Vector, Euler from math import pi, sqrt import json import os import pathlib import bmesh def get_bounds(objects): xl = [] yl = [] zl = [] for obj in objects: for bounds in obj.bound_box: v = obj.matrix_world @ Vector(bounds) xl += [v[0] for c in obj.bound_box] yl += [v[1] for c in obj.bound_box] zl += [v[2] for c in obj.bound_box] return ( Vector([min(xl), min(yl), min(zl)]), Vector([max(xl), max(yl), max(zl)]) ) GROUP_NAME = "Billboards" GROUP_KIND = "buildings" path_info = pathlib.Path(bpy.data.filepath).parent.joinpath("macrovision-directory.txt") config_path = pathlib.Path(open(path_info).read()) json_path = config_path.joinpath("config.json") config = json.load(open(json_path.resolve(), encoding="utf-8")) parent_workdir = config["work-directory"] workdir = pathlib.Path(parent_workdir).joinpath(GROUP_NAME) c = bpy.data.objects["cam"] c.data.type = "ORTHO" bpy.data.scenes["Scene"].render.resolution_x = 1000 bpy.data.scenes["Scene"].render.resolution_y = 1000 bpy.data.scenes["Scene"].render.film_transparent = True bpy.data.scenes["Scene"].view_settings.view_transform = "Raw" bpy.data.worlds["World"].node_tree.nodes["Background"].inputs[1].default_value = 0 collections = bpy.data.collections["Macrovision"].children all_data = {} all_data["name"] = GROUP_NAME all_data["kind"] = GROUP_KIND all_data["forms"] = [] VOLUME = False os.makedirs(workdir, exist_ok=True) VIEW_DATA = { "Front": [0, 1, 2, "Front"], "Angled": [0.5, 1, 2, "Angled"], "Side": [1, 1, 2, "Side"], "Back": [2, 1, 2, "Back"], "Top": [0, 0, 1, "Top"] } for coll in collections: coll.hide_render = True for coll in collections: coll.hide_render = False bpy.ops.object.select_all(action='DESELECT') for obj in coll.objects: obj.select_set(True) data = {} data["name"] = coll.name data["views"] = [] bound_min, bound_max = get_bounds(coll.objects) dimensions = bound_max - bound_min size = max(dimensions) global_bbox_center = 0.5 * (bound_min + bound_max) view_list = [] if "Views" in coll: for view in coll["Views"].split(","): view_list.append(VIEW_DATA[view]) else: view_list = [VIEW_DATA["Front"]] for angles in view_list: c.location = global_bbox_center largest = size c.data.ortho_scale = largest * 1.2 if angles[0] % 1 != 0: c.data.ortho_scale *= sqrt(2) c.rotation_euler = Euler([angles[1] * pi / 2, 0, angles[0] * pi / 2]) rot = c.rotation_euler.to_matrix() rot.invert() c.location = c.location + Vector([0, 0, largest * 2]) @ rot c.data.clip_start = largest / 4 c.data.clip_end = largest * 4 data["views"].append({ "name": angles[3], "height": dimensions[angles[2]] }) #s.rotation_euler = c.rotation_euler filename = f"{coll.name}-{angles[3]}.png" bpy.context.scene.render.filepath = workdir.joinpath(filename).resolve().__str__() bpy.ops.render.render(write_still = True) all_data["forms"].append(data) coll.hide_render = True with open(workdir.joinpath("data.json"), "w") as file: json.dump(all_data, file)