feat(hero): one-command iteration loop, first judged pass, comparison plates
Tools/hero_iterate.sh runs the whole chain - chmod the Blender files, build, import, render, judge, plate - and fails loudly at each step with its log under /tmp/gigline. Tools/hero_compare.py builds the side-by-side plate (reference | rendered, one height, labelled); two are committed for review. This pass: the stone is warmer in Blender (0.66/0.60/0.48 against the near-white blockout) and the banners are 1.35 x 6.2 m hung from 7.2 m, matching the reference proportion instead of the 1.55 x 5.4 that sat too low and too fat. Iteration 1 judge verdict, confidence 0.9: lacks warm sandstone, lacks fluted column detail, banners wrong, no doorways, no inscription or medallions. Checked against the plate, two of those are wrong (120 flute strips exist and cast shadows; three 1.2 m deep doorways with steps exist and read black) and three are real. The split is recorded in TODO.md with the next action for each - the important one being that the stone colour must change in the UE material (ue_hero_facade_import.py), not in the Blender material, which the render does not use.
This commit is contained in:
1 parent
670c692c43
commit
61dd28bc89
116 files changed
+279
-140
No files matched your search
@@ -0,0 +1,56 @@
|
||||
"""Build a side-by-side plate from a reference photograph and a rendered capture.
|
||||
|
||||
python3 Tools/hero_compare.py \
|
||||
--reference Art/reference/hero-masonic/02-masonictemple01.jpg \
|
||||
--render Screenshots/review/review-hero-facade-front.png \
|
||||
--out Screenshots/review/hero-compare-front.png
|
||||
|
||||
Both halves are scaled to the same height and labelled, so the two can be read at a glance instead of
|
||||
flipping between files. Reference photography is git-ignored and never committed; only the plate is.
|
||||
|
||||
Result: the plate path on stdout.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
|
||||
from PIL import Image, ImageDraw
|
||||
|
||||
LABEL_H = 56
|
||||
TARGET_H = 900
|
||||
|
||||
|
||||
def load_scaled(path, height):
|
||||
image = Image.open(path).convert("RGB")
|
||||
width = int(image.width * height / image.height)
|
||||
return image.resize((width, height), Image.LANCZOS)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--reference", required=True)
|
||||
parser.add_argument("--render", required=True)
|
||||
parser.add_argument("--out", required=True)
|
||||
parser.add_argument("--left-label", default="reference")
|
||||
parser.add_argument("--right-label", default="rendered")
|
||||
args = parser.parse_args()
|
||||
|
||||
left = load_scaled(args.reference, TARGET_H)
|
||||
right = load_scaled(args.render, TARGET_H)
|
||||
|
||||
gap = 16
|
||||
width = left.width + right.width + gap * 3
|
||||
plate = Image.new("RGB", (width, TARGET_H + LABEL_H + gap * 2), (24, 24, 26))
|
||||
plate.paste(left, (gap, LABEL_H + gap))
|
||||
plate.paste(right, (gap * 2 + left.width, LABEL_H + gap))
|
||||
|
||||
draw = ImageDraw.Draw(plate)
|
||||
draw.text((gap, 18), args.left_label, fill=(235, 235, 235))
|
||||
draw.text((gap * 2 + left.width, 18), args.right_label, fill=(235, 235, 235))
|
||||
|
||||
os.makedirs(os.path.dirname(os.path.abspath(args.out)), exist_ok=True)
|
||||
plate.save(args.out)
|
||||
print(args.out)
|
||||
|
||||
|
||||
main()
|
||||
Reference in new issue
Block a user