Work-Package: M03-RND-STREAMING-PLANNER-001 Agent: sindo-main-codex Tests: planner/facade/focus/coordinate/manifest/shutdown contracts, seven-checkpoint dry-run, repository gates Fidelity: preserves wanted/retained radii, boundary prefetch, editor preview, queue priority and cache/render behavior
24 KiB
World Renderer
Metadata
| Field | Value |
|---|---|
| Status | Partial |
| Target/work package | M00 baseline; M01-RND-STREAMING-FOCUS-001; M01-QAR-SERVER-SPAWN-RENDERER-001; M03-RND-FACADE-001 |
| Owners | Renderer workstream / milestone integrator |
| Last verified | Worktree work/sindo-main-codex/m03-renderer-facade, 2026-07-15 |
| Profiles/capabilities | Performance, Balanced, High, Custom; Blizzlike fidelity incomplete |
Purpose
Загрузить и визуализировать мир WoW 3.3.5a вокруг streaming focus: terrain, ADT placements, M2, WMO, liquids, sky/light и character/world presentation experiments. Система должна скрывать I/O/parsing/finalization latency за prewarm и per-frame budgets.
Non-goals
- Не владеет gameplay/world authoritative state.
- Не читает network packets или server DB.
- Не определяет player input/movement rules.
- Не является Content Project или editor source of truth.
- Текущий module не заявляет визуальное соответствие
1:1; gaps ведутся в../../RENDER.md.
Context and boundaries
flowchart LR
Player[Player or spectator Node3D] --> Adapter[Explicit source adapter]
Editor[Editor viewport adapter] --> Focus[StreamingFocus]
Capture[Capture tool] --> Adapter
SpawnFixture[Pinned server spawn fixture] --> SpawnManifest[Spawn render manifest]
SpawnManifest --> Capture
Adapter --> Focus
Focus --> Facade[WorldRenderFacade]
Facade --> Loader[StreamingWorldLoader internal]
Loader --> Planner[StreamingTargetPlanner]
Planner --> TargetPlan[StreamingTargetPlan]
TargetPlan --> Loader
Assets[Extracted WDT/ADT/M2/WMO/BLP] --> Native[Native loaders]
Cache[Baked terrain/M2/WMO caches] --> Loader
Native --> Parsed[Parsed tile/model data]
Parsed --> Loader
Loader --> Scene[SceneTree nodes]
Loader --> RS[RenderingServer RIDs/MultiMesh]
Sky[DBC sky/light data] --> SkyController[WowSkyController]
SkyController --> Scene
Allowed dependencies:
- native format loaders;
- render builders/material helpers;
- immutable/cached render resources;
- renderer configuration and focus;
- Godot rendering/scene APIs.
Forbidden dependencies:
- packet codecs/world session;
- gameplay reducers/quest/combat state;
- runtime UI Controls;
- direct TrinityCore/AzerothCore database access.
Public API
Runtime, capture and probe callers use WorldRenderFacade for focus and metrics.
StreamingWorldLoader remains the internal scene implementation while later M03
packages add environment, entity-visual and ground-query contracts.
| Symbol | Kind | Purpose | Thread/lifetime | Errors |
|---|---|---|---|---|
map_name |
Exported property | WDT/map directory name | Set before world load | Missing WDT produces diagnostic/empty world |
extracted_dir |
Exported property | Root of legally extracted client data | Session lifetime | Missing files reported per loader path |
StreamingFocus |
Immutable value | Typed Godot-basis position without Node/Camera dependency | Any thread; caller-owned reference | Null position is a caller contract violation |
WorldRenderFacade.streaming_focus_source_path |
Exported adapter property | Samples any explicit Node3D source into StreamingFocus |
Main thread, scene lifetime | Missing/wrong node warns once and retains prior focus |
WorldRenderFacade.set_streaming_focus |
Public method | Accepts focus from app/editor/tool composition | Main thread/session | Missing internal renderer is diagnosed; no state is duplicated |
WorldRenderFacade.refresh_streaming_focus |
Public method | Samples configured source and delegates existing refresh thresholds | Main thread/session | Returns false when dependency/focus is unavailable |
WorldRenderFacade.renderer_metrics_snapshot |
Public method | Returns a deep-detached queue/cache/activity snapshot | Main thread/caller-owned result | Missing/invalid implementation result returns empty snapshot with diagnostic |
WorldRenderFacade.streaming_world_loader_path |
Internal adapter property | Resolves the existing implementation without exposing it to consumers | Main thread, scene lifetime | Missing method/path produces one diagnostic until recovery |
camera_path |
Exported property | Camera used only by optional automatic overview positioning | Main thread, scene lifetime | Missing camera skips automatic positioning |
quality_preset |
Exported property | Applies renderer budgets/radii | Before/at runtime depending property | Invalid combination should be diagnosed |
runtime_stats_enabled |
Exported property | Enables periodic performance snapshot | Runtime mutable | Logging overhead only |
hitch_profiler_enabled |
Exported property | Enables named hitch sections | Runtime mutable | Logging overhead only |
Публичным contract не считаются StreamingWorldLoader methods/properties,
внутренние dictionaries, queues, job records и generated node names. Scene-owned
loader configuration remains transitional composition data, not a caller API.
Inputs and outputs
| Direction | Contract/data | Producer | Consumer | Ownership | Thread/lifetime |
|---|---|---|---|---|---|
| Input | StreamingFocus |
Player/spectator/editor/capture adapter | WorldRenderFacade |
Immutable caller value | Main thread/session |
| Input | Focus-source NodePath |
Runtime/test scene composition | WorldRenderFacade source adapter |
Scene-owned node, sampled position | Main thread/scene lifetime |
| Input | Map/configuration | Scene/app/editor | StreamingWorldLoader |
Caller config, copied/read | Main thread/session |
| Input | WDT/ADT/M2/WMO/BLP bytes | Extracted asset repository | Native loaders/builders | Loader result owns parsed data | Worker or controlled load |
| Input | Baked resources | Cache build tools | Streamer/builders | Shared immutable resource/cache entry | Session/cache lifetime |
| Test input | Server-spawn render manifest | Coordinate fixture/verifier | Checkpoint capture tool | Repository-owned diagnostic data | Test-process lifetime |
| Output | StreamingTargetPlan |
StreamingTargetPlanner |
Streamer queue/state apply | Immutable ephemeral value | One refresh |
| Output | Desired tile/detail operations | Streamer plan application | Finalize queues | Loader-owned | Cross-frame |
| Output | Terrain/M2/WMO/liquid instances | Loader/builders | Godot world/renderer | Loader/world owner | Main-thread attach |
| Output | Detached renderer metrics | WorldRenderFacade |
Capture/baseline tools | Caller-owned deep copy | On demand |
| Output | Logs/diagnostics | Hitch/stat instrumentation | Logs/baseline tools | Immutable records | Periodic/frame |
| Test output | Diagnostic spawn marker and cold/warm PNGs | Checkpoint capture tool | Human/integrator review | SceneTree marker; user:// files |
One capture process |
Side effects:
- reads extracted files and generated caches;
- creates/frees scene nodes, meshes, materials, MultiMeshes and RIDs;
- submits worker tasks;
- mutates shader globals/environment through render/sky paths;
- writes logs and baseline captures through tools.
Data flow
flowchart TD
PlayerSource[Player/spectator Node3D] --> A[Explicit scene adapter]
C[Capture camera] --> A
SF[Pinned server spawn] --> SM[Validated spawn manifest]
SM --> C
SM --> Marker[Renderer-native origin marker]
E[Editor viewport] --> EA[Editor adapter]
A --> F[StreamingFocus]
EA --> F
F --> RF[WorldRenderFacade]
RF --> Planner[StreamingTargetPlanner]
Planner --> T[StreamingTargetPlan apply]
WDT[WDT tile catalog] --> Planner
T --> Q[Tile load queue]
Q --> Parse[Worker parse/cache load]
Parse --> R[Result queues]
R --> B[Per-frame budget scheduler]
B --> Terrain[Terrain attach/upgrade]
B --> M2[M2 group/MultiMesh attach]
B --> WMO[WMO instance/group attach]
B --> Liquid[Liquid attach]
Terrain --> World[Godot world]
M2 --> World
WMO --> World
Liquid --> World
Marker --> World
F --> Eviction[Eviction/retention decisions]
Eviction --> World
Lifecycle/state
stateDiagram-v2
[*] --> Initializing
Initializing --> WaitingForFocus: WDT/catalog/config ready
Initializing --> Degraded: missing loaders/data/cache
WaitingForFocus --> Streaming: valid StreamingFocus
Streaming --> Streaming: load/finalize/evict ticks
Streaming --> WaitingForFocus: world reset without replacement focus
Streaming --> SwitchingMap: map/focus reset
SwitchingMap --> Initializing
WaitingForFocus --> ShuttingDown
Degraded --> ShuttingDown
Streaming --> ShuttingDown
ShuttingDown --> [*]
Main sequence
sequenceDiagram
participant Source as Player/Editor/Capture source
participant Focus as StreamingFocus adapter
participant Facade as WorldRenderFacade
participant Stream as StreamingWorldLoader internal
participant Planner as StreamingTargetPlanner
participant Worker as Worker task
participant Budget as Main-thread budget
participant Render as SceneTree/RenderingServer
Source->>Focus: sample explicit Godot position
Focus->>Facade: set/refresh typed focus
Facade->>Stream: delegate focus and refresh
Stream->>Planner: typed focus, catalog and target policy
Planner-->>Stream: immutable wanted/retained plan
Stream->>Stream: queue priority and loaded-tile LOD/detail state
Stream->>Worker: parse/load tile and detail data
Worker-->>Stream: immutable result
Stream->>Budget: enqueue finalize operations
Budget->>Render: attach bounded terrain/M2/WMO/liquid work
Stream->>Render: evict outside retention range
Stream->>Worker: shutdown: wait for WorkerThreadPool tasks
Stream->>Stream: shutdown: finish registered ResourceLoader requests
Stream->>Render: clear queues and owned tree nodes/RIDs
Stream->>Stream: free detached prototypes and release resource caches
Ownership, threading and resources
StreamingWorldLoaderвладеет tile states, queues, task registries, active world instances и render caches session scope.WorldRenderFacadeowns only scene-relative adapter paths. It does not own the streamer, focus source, returned metrics, queues, caches, nodes or RIDs.StreamingTargetPlanneris stateless and owns only call-local calculations; its immutable plan is consumed synchronously by the streamer.- Focus producers own the immutable
StreamingFocusreference; the loader retains the latest reference and converts it toVector3only inside the render boundary. - Worker tasks не должны менять SceneTree и shared Resource concurrently.
- Parsed/grouped results передаются обратно через guarded result queues.
- Mesh/material/node/RID finalization выполняется main thread и ограничивается exported budgets.
- Shutdown/map switch обязан дождаться WorkerThreadPool jobs и зарегистрированных threaded ResourceLoader requests до очистки очередей, nodes, caches и RIDs.
- Parented streamed nodes остаются owned by SceneTree during shutdown; detached M2/WMO prototype caches are explicitly
free()d after asynchronous work drains. - A temporary liquid root with no generated child geometry is explicitly freed by
ADTBuilderinstead of being returned or abandoned. - Cache resources считаются immutable после публикации.
Errors, cancellation and recovery
| Failure | Detection | Behavior | Diagnostic | Recovery |
|---|---|---|---|---|
| Missing WDT/ADT | File/catalog check | Tile/map unavailable | Loader warning/error | Fix extraction/profile, reload |
| Missing focus source | Explicit NodePath resolution | Retain current streamed content and prior valid focus | One warning until source recovers | Fix composition path or call set_streaming_focus |
| Missing renderer implementation | Facade path/method validation | Focus/metrics call fails without mutation | One facade diagnostic until recovery | Fix scene composition path/implementation |
| Invalid metrics result | Facade return-type validation | Return empty caller snapshot | Facade error | Restore Dictionary implementation contract |
| No focus supplied | Refresh contract | No target recomputation; queues continue draining | refresh_streaming_focus() returns false |
Supply player/editor/capture focus |
| Cache version mismatch | Required format constant | Reject stale cache/fallback | Version diagnostic | Rebuild matching cache |
| Worker failure | Task result/empty data | Skip/degrade affected asset | Queue/task warning | Retry/rebuild source |
| Main-thread hitch | Named section timing | Frame spike, work remains queued | HITCH log |
Lower budget/fix finalize path |
| D3D12 descriptor exhaustion | Rendering backend error | Render failure/fallback backend | Godot error + baseline report | Dedup resources/fix settings |
| Teleport/map change | Focus/session transition | Old jobs become stale | Target/session generation | Cancel/drop stale results |
| Shutdown leak | Godot leak/RID diagnostics | Resource retained | Verbose shutdown report + cache shutdown verifier | Drain requests, preserve tree ownership, then free detached prototypes and clear resource caches |
Configuration and capabilities
| Setting/capability | Default | Profile | Runtime mutable | Effect |
|---|---|---|---|---|
| Quality preset | Scene-specific | All | Limited | Applies radii and finalize budgets |
| Terrain control splat | Enabled in current High paths | Render | Limited | Near terrain texture quality |
| M2/WMO/liquids | Scene/profile-specific | Render | Debug/config | Enables asset categories |
| Runtime stats/hitch profiler | Usually debug | Dev/test | Yes | Observability cost |
| Shadow flags | Mostly disabled/limited | Blizzlike/Enhanced | Profile | CPU/GPU cost and visuals |
Exact exported settings and cache versions remain documented in ../../RENDER.md until extracted services receive individual specs.
Persistence, cache and migration
StreamingFocusis runtime-only and is not serialized. Scene migration addsstreaming_focus_source_path; existingcamera_pathremains valid only for optional automatic overview positioning.- Renderer reads caches under
data/cache; caches are not committed. - Format changes require
FORMAT_VERSION/required-version bump and rebuild instructions. - Atomic cache publication and unified manifest are target-state work from FND/M03.
- Material-only changes may refresh without geometry rebake only when documented safe.
Diagnostics and observability
- Logs:
HITCH,PERF,TERRAIN_QUALITY,SKY_LIGHT,SKYBOX_MODEL. - API snapshot:
WorldRenderFacade.renderer_metrics_snapshot()returns detached queue/cache/activity counts without exposing mutable renderer state. - Metrics: queue depths, active tiles/assets, named finalize times, frame percentiles and max hitch.
- Debug views: render checkpoint scenes/captures; future streaming/LOD/portal overlays.
- Correlation IDs: currently mostly tile/path keys; target architecture adds session/job IDs.
Verification
- Unit/contract tests: streaming-focus contract/wiring, material mapping, unique-ID dedupe, placement probes, baseline manifest, five-point coordinate calibration, synthetic perceptual checkpoint diff, camera-pose grid plan.
- Pure planner contract: center/corner/catalog/clamp/editor cases plus bounded High-like iteration timing without loading a world scene.
- Integration/E2E: Eastern Kingdoms/Kalimdor streaming scenes, seven M00 cold/warm checkpoints and one dedicated mapped server-spawn checkpoint.
- Fidelity evidence: семь локальных build 12340 reference JPG покрывают terrain/ADT/M2/WMO/liquid/sky и реальный
GryphonRoost01; automated cold/warm metrics имеютcompared=14,missing=0. Sky использует приблизительно paired camera, а animated-M2 остаётся asset-paired/placement-unpaired из-за synthetic probe. - Performance budgets: M00 report records cold/warm p95 and max hitch; no final acceptance threshold yet.
- Manual diagnostics:
../RENDER_BASELINE.mdand../../RENDER.md.
Extension points
- Target
WorldRenderFacadefor runtime/editor/capture callers. - Extend
StreamingFocuswith measured direction/velocity needs when the pure planner is extracted. - Extracted planner, budget scheduler, terrain, M2, WMO, liquid, sky and character services.
- Separate Blizzlike/Enhanced material and quality profiles.
Capability status
| Capability | Status | Evidence | Gap/next step |
|---|---|---|---|
| ADT streaming/terrain | Partial | M00 checkpoints and current scenes | Fidelity/performance gaps remain |
| Static M2 placement | Partial | MultiMesh/dedupe probes | Full materials/animation/effects |
| WMO rendering | Partial | Cached group rendering | Portals/rooms/material parity |
| Liquids | Partial | MH2O/MLIQ paths | LiquidType/depth/shore fidelity |
| Sky/light | Partial | DBC controller/logs | Zone transition paired validation |
| Character presentation | Prototype | Character creator/player experiment | Full customization/equipment states |
| Camera-independent streaming focus | Implemented | Typed contract, two player-focused runtime scenes and three explicitly camera-focused diagnostic tools | Multi-focus/direction/velocity belong to planner extraction |
| Golden server-spawn visualization | Implemented | Pinned AzerothCore fixture, validated renderer manifest and diagnostic origin-marker capture at ADT (32,48)/MCNK (3,12) |
No TrinityCore row or original-client visual-parity claim |
| Stable renderer facade | Partial | M03-RND-FACADE-001 contract/runtime/tool regressions |
Focus and metrics migrated; environment/entity visuals/ground query remain |
| Pure streaming target planner | Implemented | M03-RND-STREAMING-PLANNER-001 asset-free contract/performance regression |
Queue scheduling and loaded-tile LOD application remain in streamer |
Known gaps and risks
- Monolithic streamer mixes planning, jobs, caches and presentation.
camera_pathremains only for optional automatic overview positioning; it no longer drives runtime streaming or discovers the active viewport camera.- Original-client paired fidelity evidence incomplete.
- Первый paired run выявил coordinate/placement mismatch: несколько совпадающих server-derived camera positions оказываются под terrain или внутри WMO/rocks OpenWC.
- Terrain-height probe исключил under-terrain состояние для всех пяти точек; waterfall exact-XZ miss классифицирован как TriangleMesh seam/edge и подтверждён nearby sample в 2 units.
- Camera-occluder probe не нашёл camera containment в пяти точках; paired mismatch локализован прежде всего в manual look direction/target/FOV calibration, с явным ограничением по RID-only geometry.
- Empirical FOV sweep выявил, что checkpoint camera должна явно вызывать
make_current(); после исправления projection ranking остаётся inconclusive из-за неизвестного manual yaw/pitch/framing reference. - Camera-pose sweep can now rank bounded yaw/pitch grids without changing manifest defaults; perceptual ranking remains diagnostic and requires human framing approval.
- The first Goldshire pose grid was invalidated by WMO readiness: the inn is absent after 2 seconds but visible after the manifest-standard 8-second wait. Pose comparisons must stabilize asynchronous checkpoint content first.
- A ready-scene Goldshire 3x3 grid improved mean error from
0.101402at zero offsets to0.087952at yaw10/pitch-10; pitch/FOV refinement remains required before manifest calibration. - Joint Goldshire pitch/FOV refinement had no human-approved optimum: full-frame error preferred grass-heavy FOV 62/pitch -25, while FOV 38/pitch -10 better matched building scale. Landmark/region scoring is required before calibration.
- Common-region scoring
[300,100,1400,650]moved Goldshire's numeric optimum to FOV 38/yaw 10/pitch -15, but human inspection still found an oversized/cropped facade; semantic landmarks or masks remain required. - Final paired audit compared fourteen cold/warm images for seven private build 12340 references with zero missing pairs; mean error ranges
0.066893..0.176955. Animated-M2 native motion is observed across two original-client phases, but its real Lakeshire placement differs from the synthetic Goldshire probe. Sky-transition evidence uses the checkpoint map position/time with manually approved approximate framing. - D3D12 descriptor issues remain. Explicit shutdown ownership removes the GUI capture's Node/resource/RID leaks in focused and seven-checkpoint runs; a timing-dependent ObjectDB warning for anonymous zero-reference
RefCountedobjects remains as a separate engine-teardown diagnostic. - M2/WMO/material/particle/ribbon/portal parity incomplete.
- Public API is mostly exported configuration rather than stable contracts.
Source map
| Path | Responsibility |
|---|---|
src/render/world_render_facade.gd |
Stable caller boundary for typed focus and detached renderer metrics |
src/render/streaming/streaming_target_planner.gd |
Scene-free wanted/retained ADT target calculation |
src/render/streaming/streaming_target_policy.gd |
Immutable renderer radius/prefetch policy |
src/render/streaming/streaming_target_plan.gd |
Immutable planner result with read-only tile-key sets |
src/scenes/streaming/streaming_world_loader.gd |
Current runtime orchestration, queues, caches and attachment |
src/domain/streaming/streaming_focus.gd |
Immutable camera-independent streaming position contract |
src/tools/verify_streaming_focus.gd |
Headless contract, dependency and runtime/tool wiring regression |
src/tools/verify_world_render_facade.gd |
Facade delegation, snapshot isolation and consumer wiring regression |
src/tools/verify_streaming_target_planner.gd |
Planner behavior, dependency and bounded timing regression |
addons/mpq_extractor/loaders/adt_builder.gd |
Terrain/material/liquid construction |
addons/mpq_extractor/loaders/m2_builder.gd |
Static M2 mesh/material construction |
addons/mpq_extractor/loaders/m2_native_animated_builder.gd |
Native animated M2 experiment |
addons/mpq_extractor/loaders/wmo_builder.gd |
WMO groups/doodads/liquids construction |
src/scenes/sky/wow_sky_controller.gd |
DBC-driven sky/light/environment |
src/native/src/*_loader.cpp |
Native binary parsing |
src/tools/build_*cache.gd, src/tools/bake_*cache.gd |
Offline cache generation |
tools/run_render_baseline.ps1 |
Unified M00 baseline runner |
src/tools/compare_render_checkpoints.gd |
Offline JPG/PNG paired-image perceptual metrics and JSON pass/fail report |
src/tools/verify_render_runtime_cache_shutdown.gd |
Headless ownership regression for detached runtime prototypes, resource caches and empty liquid roots |
src/tools/capture_render_checkpoints.gd |
Deterministic no-roll checkpoint camera, performance and visual capture |
src/tools/server_spawn_render_manifest.json |
Dedicated mapped AzerothCore spawn checkpoint and diagnostic marker configuration |
src/tools/verify_server_spawn_renderer.gd |
Fixture-to-renderer checkpoint contract verification |
tools/sweep_render_checkpoint_camera_pose.ps1 |
Offline yaw/pitch capture grid and paired-error ranking |
src/tools/verify_render_coordinate_calibration.gd |
Build 12340 camera-coordinate golden point round-trip diagnostic |
src/tools/probe_render_terrain_height.gd |
Offline active-mesh terrain height and camera-clearance report |
src/tools/probe_render_camera_occluders.gd |
Scene-tree placement containment and camera-to-target AABB intersection report |