extends SceneTree ## RENDER-PROBE Karte t_6c1027c1 (K1d: Startansicht = Kartenmitte, 80 m) — 2 Bilder 1600×900: ## (a) Karte „frisch geladen“ (main._refresh_all → fit_to_document): Blick aus ## 80 m auf die Kartenmitte, Lager im Nahbereich groß im Bild ## (b) Pos1 (Home) → GANZE Karte im Bild (Startansicht ist bewusst NICHT Pos1) ## Ausführen (KEIN --headless, sonst rendert nichts): ## xvfb-run -a /opt/data/home/bin/godot4 --path . --rendering-driver opengl3 -s res://tests/probe_k1d_render.gd ## PNGs landen in /opt/data/scopedvr/work/k1d_bilder/ (Scratch-Ordner stirbt nach der Karte). ## Echte GLB-Modelle: die Probe braucht ein Mesh-Lager als Sibling ## (../scopedvr-client/assets/objekte) — ohne das zeigen die Marker Platzhalter. const OUT_DIR := "/opt/data/scopedvr/work/k1d_bilder/" var main: Control var camera: Camera3D var subvp: SubViewport func _initialize() -> void: _run.call_deferred() func _shot(name: String) -> void: await process_frame await RenderingServer.frame_post_draw var img := subvp.get_texture().get_image() var path := OUT_DIR + name var err := img.save_png(path) print("PROBE_PNG=%s (%dx%d, err=%d)" % [path, img.get_width(), img.get_height(), err]) func _find_subvp(node: Node) -> SubViewport: if node is SubViewport: return node as SubViewport for c in node.get_children(): var f := _find_subvp(c) if f != null: return f return null func _key(code: Key) -> void: var ev := InputEventKey.new() ev.keycode = code ev.physical_keycode = code ev.pressed = true subvp.push_input(ev) ## Lager um die Kartenmitte: Gebäude/Container/Fässer im Nahbereich (das soll ## die 80-m-Ansicht „groß und greifbar“ zeigen) + ein paar Objekte weiter ## draußen für den Karten-Kontext. func _lager_doc() -> Dictionary: var doc: Dictionary = SvmapDocument.create_new("K1d-Beweis", 1024.0, "mittag") doc["objects"] = [ {"id": "barracks_001", "pos": [-16.0, 0.0, -8.0], "scale": 1.0, "rot_y_deg": 20.0}, {"id": "building_001", "pos": [14.0, 0.0, -14.0], "scale": 1.0, "rot_y_deg": -35.0}, {"id": "container_001", "pos": [3.0, 0.0, 7.0], "scale": 1.0, "rot_y_deg": 90.0}, {"id": "container_004", "pos": [7.5, 0.0, 7.0], "scale": 1.0, "rot_y_deg": 90.0}, {"id": "barrel_001", "pos": [-4.0, 0.0, -2.0], "scale": 1.0, "rot_y_deg": 0.0}, {"id": "barrel_003", "pos": [-3.0, 0.0, -4.0], "scale": 1.0, "rot_y_deg": 0.0}, {"id": "barrel_005", "pos": [-4.6, 0.0, -4.6], "scale": 1.0, "rot_y_deg": 0.0}, {"id": "barrier_001", "pos": [10.0, 0.0, 22.0], "scale": 1.0, "rot_y_deg": 0.0}, {"id": "apc_001", "pos": [22.0, 0.0, 6.0], "scale": 1.0, "rot_y_deg": 140.0}, {"id": "air_defense_001", "pos": [-24.0, 0.0, 16.0], "scale": 1.0, "rot_y_deg": 70.0}, {"id": "container_007", "pos": [-80.0, 0.0, -90.0], "scale": 1.0, "rot_y_deg": 15.0}, {"id": "barracks_001", "pos": [130.0, 0.0, 90.0], "scale": 1.0, "rot_y_deg": -60.0}, ] return doc func _run() -> void: var scene: PackedScene = load("res://core/scenes/main.tscn") main = scene.instantiate() root.add_child(main) await process_frame await process_frame camera = main.get("camera") subvp = _find_subvp(main) var container: SubViewportContainer = subvp.get_parent() container.stretch = false subvp.size = Vector2i(1600, 900) await process_frame var doc := _lager_doc() main.set("doc", doc) main.call("_refresh_all") await process_frame await process_frame var target: Vector3 = camera.get("target") print("ZAHLEN (a) target=", target, " distance=", camera.get("distance"), " yaw=", camera.get("yaw_deg"), " pitch=", camera.get("pitch_deg")) print("ZAHLEN (a) Kamera-Position=", camera.position, " Höhe über Kartenmitte=", camera.position.y - target.y) print("ZAHLEN (a) Status: ", main.status_label.text) # Wie viele Objekt-Marker liegen wirklich im Bild? var builder = main.get("view_builder") var markers: Array = builder.get("object_markers") var drin := 0 var rect: Rect2 = Rect2(Vector2.ZERO, Vector2(subvp.size)) for m in markers: if not (m is Node3D) or not is_instance_valid(m): continue # unbekannte Objekt-ID → kein Marker (Platzhalter-Zweig) var mp: Vector3 = (m as Node3D).global_position var p := camera.unproject_position(mp) if rect.has_point(p) and camera.is_position_in_frustum(mp): drin += 1 print("ZAHLEN (a) Objekt-Marker im Bild: %d / %d" % [drin, markers.size()]) await _shot("k1d_a_startansicht_80m.png") _key(KEY_HOME) await process_frame await process_frame print("ZAHLEN (b) nach Pos1: target=", camera.get("target"), " distance=", camera.get("distance"), " Status: ", main.status_label.text) var ecken := 0 for x in [-512.0, 512.0]: for y in [-10.0, 80.0]: for z in [-512.0, 512.0]: if camera.is_position_in_frustum(Vector3(x, y, z)): ecken += 1 print("ZAHLEN (b) Map-Ecken im Frustum: %d/8" % ecken) await _shot("k1d_b_pos1_ganze_karte.png") print("PROBE_FERTIG") quit(0)