Files
open-wc/docs/modules/m2-runtime-mesh-finalizer.md
T

225 lines
10 KiB
Markdown

# M2 Runtime Mesh Finalizer
## Metadata
| Field | Value |
|---|---|
| Status | Implemented extraction |
| Target/work package | M03 / `M03-RND-M2-RUNTIME-MESH-FINALIZER-001` |
| Owners | Stale Mesh refresh version, rebuild classification, M2Builder rebuild and fallback |
| Last verified | Worktree `work/sindo-main-codex/m03-m2-runtime-mesh-finalizer`, 2026-07-17 |
| Profiles/capabilities | Static cached and prototype M2 runtime material preparation |
## Purpose
Finalize an extracted static M2 Mesh for runtime use by accepting already-loaded
raw M2 data, preserving material refresh version `2`, rebuilding only billboard/
UV-rotation cases and returning the historical original-Mesh fallback.
## Non-goals
- Read raw `.m2` files or call ClassDB/FileAccess/ResourceLoader.
- Own request/finalize queues, Mesh/missing/prototype caches or MultiMeshes.
- Select cache paths or extract a Mesh from the originally loaded Resource.
- Change classifier predicates, builder materials, refresh version or profiles.
## Context and boundaries
```mermaid
flowchart LR
Extractor[M2MeshResourceExtractor] --> Loader[StreamingWorldLoader]
Loader -->|is raw data required?| Finalizer[M2RuntimeMeshFinalizer]
Loader --> Raw[M2RawModelRepository]
Raw --> Finalizer
Finalizer --> Classifier[M2RuntimeMeshRebuildClassifier]
Finalizer --> Builder[M2Builder]
Builder --> Subtree[M2MeshResourceExtractor]
Finalizer -->|prepared Mesh| Cache[M2MeshResourceCacheState]
```
The finalizer may use Mesh metadata, raw value Dictionaries, M2Builder and the
two existing scene-free M2 services. Raw-file I/O, cache state, render permits,
Nodes outside temporary rebuild roots and other application layers are forbidden.
## Public API
| Symbol | Kind | Purpose | Thread/lifetime | Errors |
|---|---|---|---|---|
| `requires_raw_data_for_refresh(mesh)` | Query | Tell loader whether stale Mesh needs raw-file lookup | Renderer main thread | Null/current false |
| `finalize_mesh(path, mesh, raw_data, extracted_directory)` | Command/query | Return current, marked, rebuilt or fallback Mesh | Renderer main thread; one finalize operation | Null Mesh returns null; invalid rebuild falls back |
| `clear()` | Command | Clear memoized classifier decisions | Map reset/final shutdown | Idempotent |
| `cached_rebuild_decision_count()` | Diagnostic query | Expose memoized path-decision count | Tests/diagnostics | None |
## Inputs and outputs
| Direction | Contract/data | Producer | Consumer | Ownership | Thread/lifetime |
|---|---|---|---|---|---|
| Input | Extracted Mesh and normalized M2 path | Loader/extractor adapter | Finalizer | Borrowed Mesh reference/String copy | One call |
| Input | Already-loaded raw M2 Dictionary | `M2RawModelRepository` through loader adapter | Classifier/M2Builder | Caller-owned value container | One call |
| Input | Extracted directory path | Loader configuration | M2Builder texture resolution | Copied String | One rebuild |
| Output | Original or rebuilt current Mesh | Finalizer | Cache/prototype adapter | Borrowed/new Resource reference | Cache may retain |
Side effects are Mesh refresh metadata, classifier memoization and temporary
M2Builder prototype creation/destruction during required rebuilds.
## Data flow
```mermaid
flowchart TD
Mesh[Extracted Mesh] --> Current{Refresh version >= 2?}
Current -->|yes| ReturnOriginal[Return original unchanged]
Current -->|no| NeedRaw[Repository supplies raw M2 data through loader]
NeedRaw --> HasData{Raw data available?}
HasData -->|no| Mark[Mark original version 2]
HasData -->|yes| Classify{Billboard or UV rotation?}
Classify -->|no| Mark
Classify -->|yes| Build[M2Builder temporary prototype]
Build --> Extract[M2MeshResourceExtractor first Mesh]
Extract --> Rebuilt{Rebuilt Mesh exists?}
Rebuilt -->|yes| ReturnRebuilt[Return rebuilt Mesh]
Rebuilt -->|no| Mark
Mark --> ReturnOriginal
```
## Lifecycle/state
```mermaid
stateDiagram-v2
[*] --> Current: Mesh metadata >= 2
[*] --> Stale: Mesh metadata < 2
Stale --> Current: empty/ordinary data marks original
Stale --> Rebuilding: classifier requires rebuild
Rebuilding --> Current: rebuilt Mesh returned
Rebuilding --> Current: failure marks original fallback
Current --> Current: later preparation is no-op
```
Classifier decisions are memoized per normalized path until either existing
map/reset clear site calls `clear()`.
## Main sequence
```mermaid
sequenceDiagram
participant Loader as StreamingWorldLoader
participant Finalizer as M2RuntimeMeshFinalizer
participant Raw as M2Loader boundary
participant Classifier as RebuildClassifier
participant Builder as M2Builder
Loader->>Finalizer: requires_raw_data_for_refresh(mesh)
alt current Mesh
Finalizer-->>Loader: false; reuse Mesh
else stale Mesh
Finalizer-->>Loader: true
Loader->>Raw: load static raw Dictionary
Loader->>Finalizer: finalize_mesh(path, mesh, raw, extracted dir)
Finalizer->>Classifier: needs_runtime_mesh_rebuild(path, raw)
opt rebuild required
Finalizer->>Builder: build(raw, extracted dir)
Finalizer->>Finalizer: extract first Mesh; free prototype
end
Finalizer-->>Loader: rebuilt or marked fallback Mesh
end
```
## Dependency diagram
```mermaid
flowchart TB
Loader[StreamingWorldLoader] --> Finalizer[M2RuntimeMeshFinalizer]
Finalizer --> Classifier[M2RuntimeMeshRebuildClassifier]
Finalizer --> Extractor[M2MeshResourceExtractor]
Finalizer --> Builder[M2Builder]
Loader --> Raw[M2RawModelRepository]
Loader --> Cache[M2MeshResourceCacheState]
Finalizer -. no dependency .-> Raw
Finalizer -. no dependency .-> Cache
```
## Ownership, threading and resources
- Renderer main thread executes metadata changes and M2Builder work.
- `M2RawModelRepository` owns raw M2 file/native calls; loader supplies its value result.
- Finalizer owns classifier memoization and temporary rebuild prototype lifetime.
- M2Builder owns construction rules; extractor selects the first rebuilt Mesh.
- Cache/prototype adapters decide where the returned Mesh reference is retained.
## Errors, cancellation and recovery
| Failure/state | Detection | Behavior | Diagnostic | Recovery |
|---|---|---|---|---|
| Null Mesh | Guard | Return null | Contract verifier | Caller marks missing |
| Current Mesh | Metadata query | Return exact reference; no raw load | Contract verifier | None needed |
| Raw file/parse unavailable | Empty Dictionary from loader | Mark/reuse original | Existing renderer behavior | Source/cache repair |
| Ordinary stale Mesh | Classifier false | Mark/reuse original | Classifier verifier | None needed |
| Builder produces no Mesh | Extractor null | Mark/reuse original | Finalizer fallback fixture | Source/builder repair |
| Reset/shutdown | Loader lifecycle | Clear classifier decisions | Source/clear verifier | Recompute next session |
## Configuration and capabilities
`MATERIAL_REFRESH_VERSION` remains `2` and is now owned by this finalizer.
Finalize permits, cache paths, extracted directory configuration and quality
profiles remain unchanged in the loader.
## Persistence, cache and migration
No new format is serialized. Existing Mesh metadata key
`wow_m2_material_refresh_version`, M2Builder `MATERIAL_FORMAT_VERSION == 2` and
`.tscn/.glb` caches are unchanged; no migration or rebake is introduced.
## Diagnostics and observability
`cached_rebuild_decision_count` exposes only a scalar count. Existing renderer
logs/queue metrics are unchanged. Normalized M2 path remains the correlation key.
## Verification
- `verify_m2_runtime_mesh_finalizer.gd`: null/current/raw requirement, empty and
ordinary marking, synthetic triangle billboard rebuild, rebuild failure
fallback, refresh metadata, classifier clear, source boundary and 100-by-256
bounded finalization.
- Classifier/extractor/cache/pipeline/material/shutdown/M2 build regressions cover
adjacent behavior. No asset-backed or original-client visual claim is made.
## Extension points
- Asset-backed fixture coverage can be added without changing the finalizer's
value-data contract.
- Refresh versions above `2` require explicit cache/fidelity evidence and docs.
## Capability status
| Capability | Status | Evidence | Gap/next step |
|---|---|---|---|
| Runtime Mesh refresh/fallback | Implemented extraction | Synthetic transition/rebuild verifier | Asset-backed corrupt/stale cache pending |
| Rebuild predicate | Implemented extraction dependency | Classifier fixtures | Original-client material comparison pending |
| Raw M2 refresh I/O | Implemented repository dependency | Repository source/invalid verifier | Legal success fixture pending |
## Known gaps and risks
- Required rebuild remains synchronous main-thread work behind existing permits.
- Synthetic geometry proves transition/build behavior, not full asset materials.
- No proprietary M2 traversal, descriptor-pressure/leak, p95/p99 or paired
original-client capture is included.
## Source map
| Path | Responsibility |
|---|---|
| `src/render/m2/m2_runtime_mesh_finalizer.gd` | Refresh version, classification, rebuild and fallback |
| `src/render/m2/m2_raw_model_repository.gd` | Raw-file/native I/O and Dictionary result |
| `src/scenes/streaming/streaming_world_loader.gd` | Repository call and returned-Mesh adoption |
| `src/render/m2/m2_runtime_mesh_rebuild_classifier.gd` | Memoized billboard/UV-rotation predicate |
| `src/render/m2/m2_mesh_resource_extractor.gd` | First rebuilt-Mesh selection |
| `src/tools/verify_m2_runtime_mesh_finalizer.gd` | Transition/rebuild/boundary/timing regression |
## Related decisions and references
- [`m2-runtime-mesh-rebuild-classifier.md`](m2-runtime-mesh-rebuild-classifier.md)
- [`m2-mesh-resource-extractor.md`](m2-mesh-resource-extractor.md)
- [`m2-mesh-resource-cache-state.md`](m2-mesh-resource-cache-state.md)
- [`m2-raw-model-repository.md`](m2-raw-model-repository.md)
- [`world-renderer.md`](world-renderer.md)
- [`../../RENDER.md`](../../RENDER.md)
- [`../../targets/roadmap/02-rendering-and-graphics.md`](../../targets/roadmap/02-rendering-and-graphics.md)