Cutaway v3: regione preservata per raggiungibilita + rimozione per occlusione screen-space #279
Labels
No labels
alpha:wave-0
alpha:wave-1
alpha:wave-2
alpha:wave-3
area:assets
area:combat
area:ecology
area:infra
area:render
area:scripting
area:ui
area:world
enhancement
epic
migration
post-alpha
roadmap
tech-debt
type:bug
type:chore
type:design
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
marco/IsoMmo#279
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Il cutaway rimuove il terreno con una regola "tutto sopra una quota strutturale". Funziona come interruttore, ma cancella anche il terreno percorribile: una strada che sale da un cratere sparisce nell'istante in cui inizia a salire, e il contatto a terra del personaggio si perde.
Questa issue sostituisce la forma della rimozione. L'attivazione (UNDER / SHUT IN,
TerrainCutaway) non cambia.Il modello — tre insiemi distinti
TileMapRuleswalkable +maxSlopeZ,|Δz| ≤ WorldRules.MaxWalkStepZ), esteso a tutta la componente raggiungibile dentro la finestra di rendering.Proprietà emergente: si rimuove solo terreno non raggiungibile. Una collina camminabile è preservata, quindi mai rimossa — il danno si limita da sé.
Regola in una frase: vedi ovunque tu possa camminare, e sparisce solo ciò che te lo copre.
Limite del flood fill — nessuna euristica in v1
Niente budget geodetico né raggio. Motivo: un raggio geodetico di N celle percorre N celle in un corridoio ma riempie un'area di raggio N su un pianoro (migliaia di celle), quindi non produce il comportamento "corridoio lungo, pianoro corto" che sembrerebbe promettere. Un budget sul numero di celle visitate non garantisce comunque la strada fino al bordo: il BFS può esaurirlo riempiendo il fondo largo del cratere prima di risalire la rampa.
Truncated; mai spegnere il cutaway, che farebbe sfarfallare l'attivazione camminando su una rampa.Il rischio "rampa → pianoro" si verifica dal vivo. Se produce uno squarcio enorme, allora è l'invariante "preserva tutto ciò che è raggiungibile" a essere sbagliato in quella topologia: un budget arbitrario lo nasconderebbe soltanto, e renderebbe il risultato dipendente dalla posizione.
Implementazione — pre-pass GPU su RT colore
Pass P (pre-pass). La stessa mesh di finestra su un
RenderTarget2Da virgola mobile,clip()sui frammenti non preservati, scrive(validità, cameraDepth, 0, 0). Canale colore, non depth texture: non dipendiamo da niente di campionabile che SM3/DesktopGL non garantisca. LacameraDepthcontiene interpolazioni e trasformazioni frazionarie — non è "esatta", ma è ampiamente precisa nel range ±32768 (IsoCamera.DepthWorldExtent); l'epsilonva determinato con un test, non dedotto dall'interezza del range.Pass G (ground). Ogni frammento campiona il RT al proprio pixel:
I frammenti preservati sono disegnati incondizionatamente: altrimenti la correttezza dipenderebbe dall'uguaglianza numerica perfetta fra i due pass, cioè proprio ciò che l'epsilon esiste per evitare.
Fallback. Se il render target non è creabile: flag di sessione, ricaduta sulla regola a quota attuale (
RevealZstrutturale) — non "nessun taglio", così su una macchina che non regge il RT resti comunque visibile dentro una caverna — e flag diagnostico visibile nell'overlay admin. Stessa strategia di_visibilityUnsupportednel visibility buffer del deferred shading.Il pass P gira solo quando
cutModeè attivo.Invariants Check
adminPanel.IsAdmin.subochar.ClientMessage/ServerMessage, enum o DTO wire cambia;ProtocolVersion.Currentresta 21.terrain-z.Worldnon viene toccato, nessunInvokeAsync.World.csHARD GATE N/A — nessun metodo diWorldaggiunto o modificato.ScreenHARD GATE ✓ —ReachableRegioninClient.Core, i due pass inGroundBlendRenderer, l'overlay inWorldRenderer.GameScreennon guadagna né uncasené una passata di disegno.IReadOnlyTileMapinClient.Core, senza MonoGame: è ciò che rende scrivibile il test rampa/pianoro. Nel progettoClientrestano solo RT, pass e uniform.switchsu tipo di terreno: un nuovo terreno scalabile entra nella regione con una riga di tiledata, zero codice.IConfigurationletto in un servizio.RenderTarget2D+ SM3 sono il percorso già in produzione per il visibility buffer (Win/macOS), con fallback obbligatorio se il formato non è creabile.TileMapRules(walkable +maxSlopeZ+MaxWalkStepZ), non da una copia: è il motivo per cui la parete del cratere non entra e la strada sì.DisplayZrestano presentazione. La regione si calcola sulla Z autoritativa (raggiungibilità = simulazione) e si rasterizza aDisplayZ(render): i due non vanno mescolati, ed è la crepa da cui esce il KO 3.CLAUDE.md, sezione Level-focus visibility nel design doc del modello a volumi, e la DoD qui sotto.Piano di verifica
Unit puri in
Client.Core(nessun MonoGame, mappe costruite a mano):Nessun test server — niente cambia lato server.
Screenshot (DB fresco + harness): fondo cratere con la strada visibile fino a bordo schermo · la stessa scena camminando 8-10 passi, per giudicare se il bordo "respira" · foresta, dove
cutModeè False e nulla deve cambiare · fallback forzato.Gap dichiarato: i casi UNDER (caverna) non sono dimostrabili dal vivo finché non esiste una cavità autorata; restano coperti dai test.
Definition of Done
cutMode False) nessun frammento viene rimosso:removedSheets 0e nessuna area vuota.Truncated, stato del fallback.CLAUDE.md(bullet + invariante) e il design doc del modello a volumi aggiornati nello stesso commit.