champions-of-luneraria/tools/meshy/render_reference.py
Martin Stickelbroeck 714d0c697c U5.5 Schlackenklaue: zweite Meshy-Figur (g02)
Konzept aus Icon, Phase-4-Modell und Kohlenbeißer-Konzept als Stilvorlage,
Modell, Skelett und sieben Bibliotheks-Clips für 68 Credits; Figurendatei
vom Kohlenbeißer übernommen, Lane-Fassung inklusive. Bildwerkzeug und
Stresstest nehmen aufgewertete Truppen. Stresstest 35 Schlackenklauen:
Mid 152,5 -> 135,8 fps, Karte 116,7 -> 115,6. Tests grün, Fingerabdrücke
unverändert.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 16:44:03 +02:00

39 lines
1.8 KiB
Python

"""Reference picture of a Phase-4 figure for the Meshy concept step (U5.5 series): 3/4 front view,
key and rim sun, neutral grey, 1000 px. The .blend of the Godot reference is opened read-only.
blender --background <figure.blend> --python tools/meshy/render_reference.py -- <out.png>"""
import bpy, math, sys
from mathutils import Vector
out = sys.argv[sys.argv.index('--') + 1]
scene = bpy.context.scene
meshes = [o for o in scene.objects if o.type == 'MESH' and o.visible_get()]
lo = Vector((1e9,) * 3)
hi = Vector((-1e9,) * 3)
for o in meshes:
for c in o.bound_box:
w = o.matrix_world @ Vector(c)
lo = Vector(min(lo[i], w[i]) for i in range(3))
hi = Vector(max(hi[i], w[i]) for i in range(3))
center = (lo + hi) * .5
size = (hi - lo).length
cam = bpy.data.objects.new('C', bpy.data.cameras.new('C'))
cam.data.lens = 85
scene.collection.objects.link(cam)
cam.location = center + Vector((.55, -1.0, .45)).normalized() * size * 2.4
cam.rotation_euler = (center - cam.location).to_track_quat('-Z', 'Y').to_euler()
scene.camera = cam
for name, energy, rot in [('Key', 3.2, (48, 0, 150)), ('Rim', 2.0, (25, 0, -30))]:
light = bpy.data.lights.new(name, 'SUN')
light.energy = energy
obj = bpy.data.objects.new(name, light)
scene.collection.objects.link(obj)
obj.rotation_euler = tuple(math.radians(a) for a in rot)
world = bpy.data.worlds.new('W')
scene.world = world
world.use_nodes = True
world.node_tree.nodes['Background'].inputs[0].default_value = (.30, .34, .40, 1)
engines = [e.identifier for e in bpy.types.RenderSettings.bl_rna.properties['engine'].enum_items]
scene.render.engine = 'BLENDER_EEVEE_NEXT' if 'BLENDER_EEVEE_NEXT' in engines else 'BLENDER_EEVEE'
scene.render.resolution_x = scene.render.resolution_y = 1000
scene.render.filepath = out
bpy.ops.render.render(write_still=True)