Detail the NPC avatars and finish the realism follow-ups
Full build / Import + headless tests (push) Successful in 38s
Full build / Full desktop build + optional release (push) Skipped

Blender library
- Rebuild the face: sclera, iris and upper lid per eye, brow ridge, cheekbones,
  nose bridge and tip, ears with lobes, split upper/lower lips.
- Give each hand four fingers plus a thumb and end every sleeve in a cuff ring.
- Raise CHAR_MAX_VERTS 4000 -> 5000 (16 avatars still cost ~6.9 ms of a 50 ms
  frame), decimate the body to 26 %; characters are now 3,974-5,026 tris and
  3,744-4,807 verts. Rebuild all 8 variants and re-bake their AO maps.

Capture tooling
- Add a `portrait` stage to capture_realism.gd: freeze one NPC, park the crowd
  out of frame, stand the subject on open sidewalk, turn it into the camera and
  put the guard on the sunlit side. New --portrait-type=N picks the role.
- Add the npc_portrait_day concept and map the shot to it, so avatar detail is
  scored against a portrait instead of a wide street frame.

Flashlight
- Drop the fake additive beam (Materials.light_beam + the cone mesh): on GL
  Compatibility a first-person camera inside the cone renders it as a filled
  disc with a bright far ring. Keep the tight spot (14 deg, 20 m, energy 4.2)
  and its headless test; the visible shaft is now planned behind a Forward+
  preset.

Docs and task tracking
- Move the finished realism follow-ups (ground exposure, flashlight, NPC detail,
  judge re-check) to DONE.md and expand TODO.md with step-by-step plans for NPC
  gear fit, venue geometry plus the committed gallery, and the Forward+ preset.
- Record the decisions, gotchas and portrait recipe in MEMORY.md; update the
  Blender contract, the concept README and the capture section of README.md.
- Refresh the gallery captures affected by the avatar rebuild.

Checks: headless 228/228, Python 86/86, blender_assets audit exit 0,
scene_concepts audit all GOOD, screen_designs compare 11 good / 0 bad,
smoke_npc_budget OK, boot clean (only the known headless mesh warning).
This commit is contained in:
zwitschi committed 2026-11-01 17:46:25 +01:00
1 parent 2624b54b23
commit 1ee32215b0
53 files changed
+1853 -151

No files matched your search

+2 -22
View File
@@ -191,30 +191,10 @@ func _build_guard() -> GuardController:
# front of the guard instead of the person or door being checked.
flashlight.rotation_degrees = Vector3.ZERO
flashlight.spot_range = 20.0
flashlight.spot_angle = 11.0
flashlight.light_energy = 3.6
flashlight.spot_angle = 14.0
flashlight.light_energy = 4.2
flashlight.spot_attenuation = 0.9
flashlight.spot_angle_attenuation = 0.9
# Visible beam: a fading additive cone parented to the lamp, because the
# Compatibility renderer has no volumetric light. It is offset forward so the
# near cap never fills the first-person view.
var beam := MeshInstance3D.new()
beam.name = "Beam"
var cone := CylinderMesh.new()
cone.top_radius = 3.0
cone.bottom_radius = 0.04
cone.height = 7.0
cone.radial_segments = 16
cone.rings = 1
cone.cap_top = false
cone.cap_bottom = false
beam.mesh = cone
# Cylinder axis is +Y; -90° about X aims the wide end along -Z (forward).
beam.rotation_degrees = Vector3(-90, 0, 0)
beam.position = Vector3(0, 0, -3.9)
beam.material_override = Materials.light_beam()
beam.cast_shadow = GeometryInstance3D.SHADOW_CASTING_SETTING_OFF
flashlight.add_child(beam)
head.add_child(flashlight)
var collider := CollisionShape3D.new()
var shape := CapsuleShape3D.new()