This commit is contained in:
Nicholas Butzke
2026-08-02 02:20:02 -04:00
parent 61669627db
commit 922983429e
226 changed files with 34032 additions and 18521 deletions
+96
View File
@@ -0,0 +1,96 @@
extends SceneTree
## Photograph Sakura Crossing from a fixed set of authored viewpoints.
##
## godot --path . --windowed --resolution 1600x900 \
## -s res://debug/sakura_detail_capture.gd -- <out_dir>
##
## `visual_capture.gd` shoots the real game through a real match, which is the
## right regression tool but the wrong review tool: it spawns the player at
## random, so half its frames are of a rooftop or a wall and no two runs compare.
## Reviewing DETAIL needs the opposite — the same handful of angles every time,
## chosen because each one is where a particular piece of work has to hold up.
const SCENE := "res://scenes/maps/sakura_crossing/sakura_crossing.tscn"
const SETTLE_FRAMES := 120
## [name, eye, look_at, fov]
const VIEWS := [
["crossing", Vector3(0, 1.7, 20.0), Vector3(0, 2.2, -16.0), 70.0],
["shopfront", Vector3(-30.0, 1.7, -29.0), Vector3(-24.0, 3.2, -22.0), 62.0],
["shopping_street", Vector3(-4.0, 1.7, -30.0), Vector3(46.0, 4.0, -30.0), 68.0],
["station", Vector3(30.0, 2.6, 14.0), Vector3(46.0, 2.4, 9.0), 66.0],
["platform", Vector3(52.0, 2.2, 8.8), Vector3(30.0, 2.6, 8.4), 66.0],
["torii", Vector3(-22.0, 1.7, 34.0), Vector3(-22.0, 3.0, 56.0), 68.0],
["alley", Vector3(-52.0, 1.7, -11.2), Vector3(10.0, 2.6, -11.2), 70.0],
["footbridge", Vector3(-40.0, 7.6, 8.0), Vector3(30.0, 3.0, -1.0), 72.0],
["road_paint", Vector3(0.0, 1.7, 16.0), Vector3(0.0, 0.0, 6.0), 66.0],
["houses", Vector3(-8.0, 1.7, 26.0), Vector3(-24.0, 3.0, 33.0), 66.0],
["aerial", Vector3(-30.0, 150.0, 150.0), Vector3(20.0, 0.0, -10.0), 62.0],
["rail_curve", Vector3(40.0, 18.0, 30.0), Vector3(95.0, 2.0, -22.0), 66.0],
["east_district", Vector3(64.0, 1.8, 30.0), Vector3(64.0, 3.0, 78.0), 68.0],
["east_street", Vector3(20.0, 1.8, 54.0), Vector3(104.0, 4.0, 54.0), 66.0],
# Looking OUT from inside the map, over the boundary, which is the only
# angle that tells you whether the world continues past the wall.
["beyond_west", Vector3(-104.0, 3.0, 20.0), Vector3(-200.0, 10.0, 20.0), 70.0],
["beyond_south", Vector3(0.0, 3.0, 74.0), Vector3(0.0, 12.0, 200.0), 70.0],
["catenary", Vector3(20.0, 3.0, 12.0), Vector3(-30.0, 6.5, 0.0), 60.0],
["vehicles", Vector3(-30.0, 2.2, 27.0), Vector3(-8.0, 1.4, 22.0), 55.0],
["rail_east_wall", Vector3(96.0, 9.0, -6.0), Vector3(126.0, 2.0, -38.0), 66.0],
["north_park", Vector3(-30.0, 3.0, -78.0), Vector3(30.0, 4.0, -60.0), 70.0],
["north_park_overview", Vector3(-34.0, 32.0, -45.0), Vector3(-20.0, 0.0, -70.0), 68.0],
["pond_bridge", Vector3(-58.0, 2.5, -64.0), Vector3(-34.0, 1.0, -73.0), 66.0],
["park_road", Vector3(60.0, 6.0, -22.0), Vector3(100.0, 1.0, -60.0), 68.0],
["shrine_precinct", Vector3(-22.0, 2.0, 58.0), Vector3(-22.0, 4.0, 84.0), 70.0],
["shrine_lawn", Vector3(-70.0, 8.0, 42.0), Vector3(-25.0, 2.0, 53.0), 68.0],
["playground", Vector3(-72.0, 2.0, 36.0), Vector3(-72.0, 1.4, 52.0), 70.0],
["playground_reverse", Vector3(-92.0, 5.0, 63.0), Vector3(-72.0, 1.5, 51.0), 68.0],
["shrine_intersection", Vector3(-2.0, 2.0, 54.0), Vector3(20.0, 1.0, 54.0), 66.0],
["sidewalk_corner", Vector3(13.0, 10.0, 7.0), Vector3(5.9, 0.2, 14.1), 52.0],
["street_sign", Vector3(3.5, 1.8, -18.0), Vector3(8.15, 2.0, -21.85), 46.0],
["bikes", Vector3(20.0, 2.0, 8.0), Vector3(32.0, 1.2, 13.0), 55.0],
]
var _out_dir := "."
func _initialize() -> void:
var args := OS.get_cmdline_user_args()
if args.size() > 0:
_out_dir = args[0]
if not _out_dir.is_absolute_path():
_out_dir = ProjectSettings.globalize_path(_out_dir)
DirAccess.make_dir_recursive_absolute(_out_dir)
_run()
func _run() -> void:
await process_frame
var packed: PackedScene = load(SCENE)
var level: Node = packed.instantiate()
root.add_child(level)
for _i in SETTLE_FRAMES:
await process_frame
var cam := Camera3D.new()
cam.far = 1200.0
level.add_child(cam)
cam.current = true
for v in VIEWS:
cam.fov = float(v[3])
cam.global_position = v[1]
cam.look_at(v[2], Vector3.UP)
# Three frames: one for the transform, one for the frame drawn with it,
# and one because the ink pass reads a screen copy of the frame before.
for _i in 3:
await process_frame
var img := root.get_texture().get_image()
var path := "%s/%s.png" % [_out_dir, v[0]]
img.save_png(path)
print("sakura_detail: saved ", path)
level.queue_free()
for _i in 6:
await process_frame
quit(0)