"""Render high/final Studio accessory and audit geometry/UV without changing it.""" import json import sys from pathlib import Path import bpy import numpy as np from mathutils import Vector folder = Path(sys.argv[sys.argv.index('--') + 1]).resolve() report = [] filenames = ('model.glb',) if '--high-only' in sys.argv else ('model_ex.glb',) if '--final-only' in sys.argv else ('model.glb', 'model_ex.glb') for filename in filenames: bpy.ops.wm.read_factory_settings(use_empty=True) bpy.ops.import_scene.gltf(filepath=str(folder / filename)) objects = [o for o in bpy.context.scene.objects if o.type == 'MESH'] points = [o.matrix_world @ v.co for o in objects for v in o.data.vertices] lo = Vector([min(v[i] for v in points) for i in range(3)]) hi = Vector([max(v[i] for v in points) for i in range(3)]) uv = np.array([tuple(v.uv) for o in objects if o.data.uv_layers.active for v in o.data.uv_layers.active.data]) assert len(objects) == 1 and np.isfinite(uv).all() and len(uv) > 0 triangles = sum(len(p.vertices) - 2 for o in objects for p in o.data.polygons) report.append(dict(file=filename, objects=len(objects), triangles=triangles, vertices=sum(len(o.data.vertices) for o in objects), minimum=list(lo), maximum=list(hi), uvLoops=len(uv), finiteUV=True)) scene = bpy.context.scene scene.render.engine = 'CYCLES' scene.cycles.samples = 16 scene.render.resolution_x = scene.render.resolution_y = 640 scene.render.resolution_percentage = 100 world = bpy.data.worlds.new('ReviewWorld') world.use_nodes = True world.node_tree.nodes['Background'].inputs[0].default_value = (.32, .38, .44, 1) world.node_tree.nodes['Background'].inputs[1].default_value = .6 scene.world = world center = (lo + hi) / 2 extent = max(hi - lo) camera = bpy.data.objects.new('ReviewCamera', bpy.data.cameras.new('ReviewCamera')) scene.collection.objects.link(camera) scene.camera = camera camera.data.type = 'ORTHO' camera.data.ortho_scale = extent * 1.3 for direction, power in (((2, -3, 4), 400), ((-3, -1, 2), 250)): light = bpy.data.objects.new('ReviewLight', bpy.data.lights.new('ReviewLight', 'AREA')) scene.collection.objects.link(light) light.location = center + Vector(direction) * extent light.rotation_euler = (center - light.location).to_track_quat('-Z', 'Y').to_euler() light.data.energy = power * extent ** 2 light.data.size = extent * 3 for name, direction in [('front', (0, -3, .5)), ('side', (3, 0, .5)), ('back', (0, 3, .5)), ('perspective', (2, -3, 1))]: camera.location = center + Vector(direction) * extent camera.rotation_euler = (center - camera.location).to_track_quat('-Z', 'Y').to_euler() scene.render.filepath = str(folder / ('audit_' + Path(filename).stem + '_' + name + '.png')) bpy.ops.render.render(write_still=True) (folder / ('geometry_high.json' if '--high-only' in sys.argv else 'geometry_audit.json')).write_text(json.dumps(report, indent=2) + '\n', encoding='utf-8') print('MT_SUMMARY ' + json.dumps(report))