File size: 3,388 Bytes
5c331a4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
"""Blender CPU review renders, including labeled component previews."""
import argparse
import math
from pathlib import Path
import sys

import bpy
from mathutils import Vector

sys.path.insert(0, str(Path(__file__).resolve().parent))
from render_settings import configure_cpu_render

parser = argparse.ArgumentParser()
parser.add_argument('--input', required=True)
parser.add_argument('--output', required=True)
parser.add_argument('--components', action='store_true')
args = parser.parse_args(sys.argv[sys.argv.index('--') + 1:])
folder = Path(args.output)
folder.mkdir(parents=True, exist_ok=True)
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete(use_global=False)
bpy.ops.import_scene.gltf(filepath=args.input)
meshes = [obj for obj in bpy.context.scene.objects if obj.type == 'MESH']
if not meshes:
    raise RuntimeError('No mesh to render')
scene = bpy.context.scene
configure_cpu_render(scene)
scene.cycles.samples = 8 if scene.cycles.use_denoising else 32
scene.render.resolution_x = scene.render.resolution_y = 384
scene.render.resolution_percentage = 100
scene.render.image_settings.file_format = 'PNG'
scene.world.use_nodes = True
scene.world.node_tree.nodes['Background'].inputs['Color'].default_value = (.15, .17, .2, 1)
scene.world.node_tree.nodes['Background'].inputs['Strength'].default_value = .6
points = [obj.matrix_world @ Vector(corner) for obj in meshes for corner in obj.bound_box]
low = Vector([min(p[i] for p in points) for i in range(3)])
high = Vector([max(p[i] for p in points) for i in range(3)])
center, size = (low + high) / 2, max(high - low)
if not math.isfinite(size) or size <= 0:
    raise RuntimeError('Invalid model bounds')
for name, xyz, energy in [('key', (3, -4, 5), 1000), ('fill', (-3, -2, 2), 600), ('rim', (2, 4, 4), 900)]:
    data = bpy.data.lights.new(name, 'AREA')
    data.energy = energy * size * size / 9
    data.shape = 'DISK'
    data.size = size * 1.5
    obj = bpy.data.objects.new(name, data)
    scene.collection.objects.link(obj)
    obj.location = center + Vector(xyz) * size / 3
    obj.rotation_euler = (center - obj.location).to_track_quat('-Z', 'Y').to_euler()
camera_data = bpy.data.cameras.new('Review')
camera = bpy.data.objects.new('Review', camera_data)
scene.collection.objects.link(camera)
scene.camera = camera
camera_data.type = 'ORTHO'
camera_data.clip_end = size * 100 + 100


def render(name, direction, target=center, scale=size):
    camera_data.ortho_scale = scale * 1.3
    camera.location = target + Vector(direction).normalized() * size * 3
    camera.rotation_euler = (target - camera.location).to_track_quat('-Z', 'Y').to_euler()
    scene.render.filepath = str(folder / (name + '.png'))
    bpy.ops.render.render(write_still=True)


for name, direction in [('front', (0, -1, .1)), ('back', (0, 1, .1)), ('left', (-1, 0, .1)),
                        ('right', (1, 0, .1)), ('top', (0, .001, 1)), ('quarter', (1, -1.4, .7))]:
    render(name, direction)
if args.components:
    for obj in meshes:
        for other in meshes:
            other.hide_render = other != obj
        bounds = [obj.matrix_world @ Vector(corner) for corner in obj.bound_box]
        minimum = Vector([min(p[i] for p in bounds) for i in range(3)])
        maximum = Vector([max(p[i] for p in bounds) for i in range(3)])
        render(obj.name, (1, -1.4, .7), (minimum + maximum) / 2, max(maximum - minimum))