|
- import bpy
- from mathutils import Vector, Euler
- from math import pi, sqrt
- import json
- import os
- import pathlib
-
- VIEW_DATA = {
- "Front": [0, 1, 2, "Front"],
- "Angled": [0.25, 1, 2, "Angled"],
- "Corner": [0.5, 1, 2, "Corner"],
- "Side": [1, 1, 2, "Side"],
- "Back Angled": [1.5, 1, 2, "Back Angled"],
- "Back": [2, 1, 2, "Back"],
- "Top": [0, 0, 1, "Top"],
- "Bottom": [0, 2, 1, "Bottom"],
- "Bottom Flipped": [2, 2, 1, "Bottom Flipped"],
- }
-
- def get_bounds(objects):
- xl = []
- yl = []
- zl = []
-
- for obj in objects:
- if not obj.hide_render:
- 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)])
- )
-
-
- path_info = pathlib.Path(bpy.data.filepath).parent.joinpath("macrovision-directory.txt")
- config_path = pathlib.Path(open(path_info).read().strip())
-
- json_path = config_path.joinpath("config.json")
- config = json.load(open(json_path.resolve(), encoding="utf-8"))
-
- parent_workdir = config["work-directory"]
- c = bpy.data.objects["cam"]
- lineart = bpy.data.objects["lineart"]
- c.data.type = "ORTHO"
-
- bpy.data.scenes["Scene"].render.resolution_x = 2000
- bpy.data.scenes["Scene"].render.resolution_y = 2000
- 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
-
- mv = bpy.data.collections["Macrovision"]
- collections = mv.children
-
- all_data = {}
-
- all_data["name"] = mv["MVName"]
- all_data["kind"] = mv["MVKind"]
- all_data["forms"] = []
-
- default_views = []
-
- for view in mv["MVViews"].split(","):
- default_views.append(VIEW_DATA[view.strip()])
-
- if "MVViewLabels" in mv:
- for pair in mv["MVViewLabels"].split(","):
- key, val = pair.split(":")
- VIEW_DATA[key.strip()][3] = val.strip()
-
-
- workdir = pathlib.Path(parent_workdir).joinpath(all_data["name"])
-
- os.makedirs(workdir, exist_ok=True)
-
- 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 = default_views
-
- for angles in view_list:
- c.location = global_bbox_center
- c.rotation_euler = Euler([angles[1] * pi / 2, 0, angles[0] * pi / 2])
- print(list(bound_min) + list(bound_max))
- _, c.data.ortho_scale = c.camera_fit_coords(bpy.context.evaluated_depsgraph_get(), list(bound_min) + list(bound_max))
- c.location = Vector([c.location[0], c.location[1], c.location[2]])
- c.data.ortho_scale *= 1.2
- rot = c.rotation_euler.to_matrix()
- rot.invert()
- c.location += Vector([0, 0, size * 2]) @ rot
- c.data.clip_start = size / 4
- c.data.clip_end = size * 8
- data["views"].append({
- "name": angles[3],
- "height": dimensions[angles[2]]
- })
-
- if "Volume" in coll:
- data["views"][-1]["volume"] = coll["Volume"]
- if "Mass" in coll:
- data["views"][-1]["mass"] = coll["Mass"]
-
- lineart.hide_render = False
- filename = f"{coll.name}-{angles[3]}.png"
- bpy.context.scene.render.filepath = workdir.joinpath(filename).resolve().__str__()
- bpy.ops.render.render(write_still = True)
- lineart.hide_render = True
- filename = f"{coll.name}-{angles[3]}-noline.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)
|