M2 Runtime Mesh Rebuild Classifier
Metadata
| Field |
Value |
| Status |
Implemented extraction |
| Target/work package |
M03 / M03-RND-M2-RUNTIME-REBUILD-CLASSIFIER-001 |
| Owners |
Billboard/UV-rotation rebuild decision and per-path memoization |
| Last verified |
Worktree work/sindo-main-codex/m03-m2-runtime-rebuild-classifier, 2026-07-17 |
| Profiles/capabilities |
Existing M2 material-refresh path; profile-independent |
Purpose
Determine whether a stale cached M2 mesh must be rebuilt in memory from raw M2
data to restore billboard custom attributes or UV-rotation material inputs. The
first decision is memoized by normalized relative path for the current map/
runtime-cache lifetime.
Non-goals
- Read M2 files or invoke
M2Loader/M2Builder.
- Own cached Meshes, scenes, materials, Nodes or RIDs.
- Select cache paths, perform ResourceLoader transitions or consume permits.
- Change refresh/cache format versions or shader behavior.
- Classify animation, particles, ribbons or general visual fidelity.
Context and boundaries
Allowed dependencies are Dictionary/Array, PackedInt32Array, Vector4 and
scalar math. Files, ResourceLoader, parser/builder classes, SceneTree,
WorkerThreadPool, Mesh/Node/RID ownership and other layers are forbidden.
Public API
| Symbol |
Kind |
Purpose |
Thread/lifetime |
Errors |
needs_runtime_mesh_rebuild(normalized_relative_path, raw_m2_data) |
Memoized query |
Detect billboard or referenced UV rotation requirements |
Renderer main thread; cached until clear |
Invalid variants/indices are skipped; first path decision wins |
clear() |
Command |
Drop all memoized path decisions |
Main thread; map reset/shutdown |
Idempotent |
cached_path_count() |
Query |
Return memoized path count |
Main thread |
None |
diagnostic_snapshot() |
Query |
Return detached path/decision map |
Main thread; caller-owned |
None |
Inputs and outputs
| Direction |
Contract/data |
Producer |
Consumer |
Ownership |
Thread/lifetime |
| Input |
Normalized M2 relative path |
Loader cache lookup |
Classifier cache key |
String value copied |
Until clear |
| Input |
Raw M2 batches/transforms/combos Dictionary |
Native M2Loader adapter |
Classifier |
Borrowed; not mutated |
First classification call per path |
| Output |
Rebuild-required boolean |
Classifier |
Loader material-refresh adapter |
Scalar |
Memoized until clear |
| Output |
Detached decision Dictionary |
Classifier |
Verifier/future diagnostics |
Caller-owned copy |
Snapshot lifetime |
Side effects are limited to inserting and clearing boolean memoization entries.
Data flow
Lifecycle/state
Each path moves from unknown to one immutable cached boolean. Clear returns all
paths to unknown; no resource lifecycle participates.
Main sequence
Dependency diagram
Ownership, threading and resources
- The classifier owns only normalized-path boolean entries.
- The loader owns raw loading, cache/resource selection, Mesh replacement and
material refresh metadata.
- Raw Dictionaries are borrowed and never retained; only the computed boolean is cached.
- Current calls and clears are serialized on the renderer main thread.
- No Node, Resource, Mesh, material or RID reference crosses into the classifier.
Errors, cancellation and recovery
| Failure |
Detection |
Behavior |
Diagnostic |
Recovery |
| Non-Dictionary batch/transform |
Type guard |
Skip entry or use identity defaults |
Synthetic verifier |
Correct parser data on next cleared lifetime |
| Missing transforms/combos |
Empty guard |
No UV-driven rebuild |
Synthetic verifier |
Billboard classification still applies |
| Invalid combo/transform index |
Bounds guard |
Skip stage |
Synthetic verifier |
Correct raw data and clear |
| Repeated path with changed data |
Cache hit |
Preserve first decision |
Memoization fixture |
Map/reset clear recomputes |
| Load/build failure |
Outside classifier |
Existing mesh fallback remains |
Loader diagnostics |
Existing reload/fallback path |
Configuration and capabilities
| Setting/capability |
Default |
Profile |
Runtime mutable |
Effect |
| Maximum texture stages inspected |
4 |
Existing M2 material path |
No |
Preserves historical four-stage shader boundary |
| UV rotation-speed epsilon |
0.000001 exclusive |
Existing M2 material path |
No |
Larger absolute speed requires rebuild |
M2_MATERIAL_REFRESH_VERSION |
Loader constant 2 |
All |
Code version |
Gates whether classifier is called |
Persistence, cache and migration
Memoized booleans are runtime-only and are cleared at the two historical loader
reset/shutdown sites. No persisted cache version or rebuild instruction changes.
Diagnostics and observability
- Logs: none.
- Metrics:
cached_path_count is contract-level only and not added to runtime logs.
- Debug views: detached path-to-boolean snapshot.
- Correlation IDs: normalized M2 relative path.
Verification
verify_m2_runtime_mesh_rebuild_classifier.gd: billboard flag/count, invalid
variants, identity/non-identity rotation, positive/negative speed, exact
epsilon, four-stage cap, invalid indices, memoization, clear, source boundary
and 100-by-256 timing.
- Existing M2 builder/material verifiers cover downstream shader/cache behavior.
- Fidelity evidence is exact predicate/cache extraction. No new asset-backed or
original-client parity claim is made.
- Performance budget: 25,600 classifications and clears under one second.
Extension points
- A typed raw M2 material descriptor may replace the Dictionary only with parser
fixtures and a compatibility adapter.
- Mesh request/cache/finalization state can be extracted separately without
changing this rebuild predicate.
Capability status
| Capability |
Status |
Evidence |
Gap/next step |
| Billboard rebuild classification |
Implemented extraction |
Flag/count fixtures |
Asset-backed cache refresh timing pending |
| UV-rotation rebuild classification |
Implemented extraction |
Combo/stage/threshold fixtures |
More build-12340 material fixtures pending |
| Runtime memoization lifetime |
Implemented extraction |
First-decision/clear/source fixtures |
Byte/count runtime metric not exposed |
| M2 mesh loading/finalization |
Existing loader-owned |
Material/shutdown regressions |
Separate state extraction pending |
Known gaps and risks
- Raw parser data remains Dictionary-based.
- The first decision wins even if different raw data is passed for the same path;
this intentionally preserves prior cache behavior.
- Only four texture stages are inspected, matching current material support.
- No private asset traversal, descriptor-pressure, p95/p99 or paired visual run is included.
Source map
| Path |
Responsibility |
src/render/m2/m2_runtime_mesh_rebuild_classifier.gd |
Predicate, thresholds and boolean memoization |
src/scenes/streaming/streaming_world_loader.gd |
Raw loading, Mesh rebuild/adoption, refresh version and clear calls |
addons/mpq_extractor/loaders/m2_builder.gd |
Mesh/material rebuild implementation |
src/tools/verify_m2_runtime_mesh_rebuild_classifier.gd |
Synthetic predicate/cache/boundary/timing regression |
Related decisions and references