D5 (t_e81aed01): Render-Nachweis tools/probe_d5_render.gd (Fels/Kaktus/Stein/Decal platziert)
This commit is contained in:
parent
0f86182a2c
commit
ebe3dd276b
1 changed files with 97 additions and 0 deletions
97
tools/probe_d5_render.gd
Normal file
97
tools/probe_d5_render.gd
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
extends SceneTree
|
||||
## D5-Bau-Nachweis (t_e81aed01): platziert je 1 Natur-Objekt (Fels, Kaktus, Decal)
|
||||
## ueber die EDITOR-eigene Aufloesung (GlbMeshStore.mesh_fuer — Registry-glb +
|
||||
## Fusspunkt-Normalisierung) auf einer Bodenplatte und rendert ein PNG.
|
||||
## Beweist visuell: Fels/Kaktus STEHEN auf dem Boden, das Decal LIEGT FLACH
|
||||
## (2 cm Lift gegen Z-Fighting).
|
||||
##
|
||||
## xvfb-run -a godot4 --rendering-driver opengl3 --path . --script res://tools/probe_d5_render.gd
|
||||
## Ausgabe: PROBE_D5_RENDER_OK + PNG-Pfad
|
||||
|
||||
const AUSGABE := "user://probe_d5_platzierung.png"
|
||||
const PLANUNG := [
|
||||
{"oid": "rock_003", "pos": Vector3(-3.2, 0.0, 0.0)},
|
||||
{"oid": "cactus_008", "pos": Vector3(0.0, 0.0, 0.0)},
|
||||
{"oid": "stone_016", "pos": Vector3(2.4, 0.0, 1.2)},
|
||||
{"oid": "decal_001", "pos": Vector3(-1.0, 0.02, 3.2)},
|
||||
]
|
||||
|
||||
var vp: SubViewport
|
||||
var kamera: Camera3D
|
||||
var rahmen := 0
|
||||
var fehler: Array = []
|
||||
|
||||
|
||||
func _initialize() -> void:
|
||||
vp = SubViewport.new()
|
||||
vp.size = Vector2i(900, 600)
|
||||
vp.own_world_3d = true
|
||||
vp.render_target_update_mode = SubViewport.UPDATE_ALWAYS
|
||||
root.add_child(vp)
|
||||
|
||||
var env := Environment.new()
|
||||
env.background_mode = Environment.BG_COLOR
|
||||
env.background_color = Color(0.55, 0.62, 0.72)
|
||||
env.ambient_light_source = Environment.AMBIENT_SOURCE_COLOR
|
||||
env.ambient_light_color = Color(1, 1, 1)
|
||||
env.ambient_light_energy = 0.8
|
||||
var we := WorldEnvironment.new()
|
||||
we.environment = env
|
||||
vp.add_child(we)
|
||||
|
||||
var sonne := DirectionalLight3D.new()
|
||||
sonne.rotation_degrees = Vector3(-50.0, 40.0, 0.0)
|
||||
sonne.light_energy = 1.2
|
||||
vp.add_child(sonne)
|
||||
|
||||
# Bodenplatte: genau das, worauf Spieler laufen (Terrain-Ersatz)
|
||||
var boden := MeshInstance3D.new()
|
||||
var pm := PlaneMesh.new()
|
||||
pm.size = Vector2(40.0, 40.0)
|
||||
boden.mesh = pm
|
||||
var mat := StandardMaterial3D.new()
|
||||
mat.albedo_color = Color(0.78, 0.68, 0.45)
|
||||
boden.material_override = mat
|
||||
vp.add_child(boden)
|
||||
|
||||
for e in PLANUNG:
|
||||
var oid := str(e["oid"])
|
||||
var mesh: Mesh = GlbMeshStore.mesh_fuer(oid)
|
||||
if mesh == null:
|
||||
fehler.append("%s: GlbMeshStore liefert kein Mesh" % oid)
|
||||
continue
|
||||
var mi := MeshInstance3D.new()
|
||||
mi.name = "Platz_%s" % oid
|
||||
mi.mesh = mesh
|
||||
var pos: Vector3 = e["pos"]
|
||||
mi.position = pos
|
||||
vp.add_child(mi)
|
||||
var ab: AABB = mesh.get_aabb()
|
||||
print("%-11s pos.y=%.2f mesh-Unterkante=%.3f m Oberkante=%.3f m XZ-Zentrum=(%.3f, %.3f)" % [
|
||||
oid, pos.y, pos.y + ab.position.y, pos.y + ab.position.y + ab.size.y,
|
||||
ab.position.x + ab.size.x * 0.5, ab.position.z + ab.size.z * 0.5])
|
||||
|
||||
kamera = Camera3D.new()
|
||||
kamera.current = true
|
||||
kamera.fov = 60.0
|
||||
vp.add_child(kamera)
|
||||
|
||||
|
||||
func _process(_delta: float) -> bool:
|
||||
rahmen += 1
|
||||
if rahmen < 4:
|
||||
return false
|
||||
if rahmen == 4:
|
||||
kamera.look_at_from_position(Vector3(2.0, 2.4, 9.0), Vector3(-0.4, 0.8, 0.8), Vector3.UP)
|
||||
return false
|
||||
if rahmen == 8:
|
||||
var pfad := ProjectSettings.globalize_path(AUSGABE)
|
||||
var img := vp.get_texture().get_image()
|
||||
img.save_png(pfad)
|
||||
print("Bild: %s (%dx%d)" % [pfad, img.get_width(), img.get_height()])
|
||||
for f in fehler:
|
||||
print(" FEHLER: %s" % f)
|
||||
print("PROBE_D5_RENDER_%s" % ("FAIL" if not fehler.is_empty() else "OK"))
|
||||
quit(0)
|
||||
return true
|
||||
return false
|
||||
Loading…
Reference in a new issue