Merge branch 'claude/quirky-jepsen-fd60f1' — N.2 dependency tracking
This commit is contained in:
commit
82a003cc65
2 changed files with 74 additions and 4 deletions
|
|
@ -46,6 +46,63 @@ Copy this block when adding a new issue:
|
||||||
|
|
||||||
# Active issues
|
# Active issues
|
||||||
|
|
||||||
|
## #51 — WB's terrain-split formula diverges from retail's `FSplitNESW`
|
||||||
|
|
||||||
|
**Status:** OPEN
|
||||||
|
**Severity:** MEDIUM (blocks isolated N.2; affects sequencing of N-phase migration)
|
||||||
|
**Filed:** 2026-05-08
|
||||||
|
**Component:** terrain math / Phase N (WorldBuilder rendering migration)
|
||||||
|
|
||||||
|
**Description:** WB's `TerrainUtils.CalculateSplitDirection`
|
||||||
|
([references/WorldBuilder/WorldBuilder.Shared/Modules/Landscape/Lib/TerrainUtils.cs:44](references/WorldBuilder/WorldBuilder.Shared/Modules/Landscape/Lib/TerrainUtils.cs:44))
|
||||||
|
uses a different math expression from retail's `FSplitNESW`
|
||||||
|
(documented in CLAUDE.md as **the** real AC terrain split formula,
|
||||||
|
constants `0x0CCAC033` / `0x421BE3BD` / `0x6C1AC587` / `0x519B8F25`).
|
||||||
|
Ours is a degree-2 polynomial in (x,y); WB's is linear in (x,y).
|
||||||
|
They cannot be algebraically equivalent and disagree on a meaningful
|
||||||
|
fraction of cells.
|
||||||
|
|
||||||
|
**Concrete impact:** On any cell where the formulas pick different
|
||||||
|
diagonals, the same world position (X, Y) maps to different terrain
|
||||||
|
heights — up to ~2m for a sloped cell with one elevated corner. If a
|
||||||
|
caller mixes "WB-formula path" and "AC2D-formula path" for the same
|
||||||
|
cell, the player physics floats above or sinks below the visible
|
||||||
|
ground. This is the bug class fixed in
|
||||||
|
[src/AcDream.Core/Physics/TerrainSurface.cs:113-120](src/AcDream.Core/Physics/TerrainSurface.cs:113)
|
||||||
|
(diagonal-direction inversion).
|
||||||
|
|
||||||
|
**Files implicated:**
|
||||||
|
- `src/AcDream.Core/Physics/TerrainSurface.cs` — uses AC2D formula via
|
||||||
|
`IsSplitSWtoNE`
|
||||||
|
- `src/AcDream.Core/World/TerrainBlending.cs` — visual mesh, also AC2D
|
||||||
|
- `references/WorldBuilder/WorldBuilder.Shared/Modules/Landscape/Lib/TerrainUtils.cs:44`
|
||||||
|
— WB's diverging formula
|
||||||
|
- `references/WorldBuilder/Chorizite.OpenGLSDLBackend/Lib/TerrainGeometryGenerator.cs`
|
||||||
|
— WB's render mesh (presumably also uses WB's formula in lockstep)
|
||||||
|
|
||||||
|
**Sequencing implication:** Phase N.2 (terrain math helpers
|
||||||
|
substitution) cannot be shipped in isolation — it must land alongside
|
||||||
|
N.5 (visual terrain renderer migration), at which point both physics
|
||||||
|
and visual mesh switch to WB's formula together. Roadmap N.2 entry
|
||||||
|
flags this dependency.
|
||||||
|
|
||||||
|
**Research needed (when N.5 picks this up):**
|
||||||
|
1. Quantify divergence: run WB's `CalculateSplitDirection` and our
|
||||||
|
`IsSplitSWtoNE` across all (lbX, lbY, cellX, cellY) tuples for a
|
||||||
|
representative landblock set; record disagreement rate.
|
||||||
|
2. Confirm WB's `TerrainGeometryGenerator` uses WB's formula in its
|
||||||
|
render mesh — if so, switching everything to WB's formula keeps
|
||||||
|
visual + physics synced. (Highly likely.)
|
||||||
|
3. Decide whether ANY retail-conformance test (e.g., physics matching
|
||||||
|
server-authoritative Z within tolerance) is invalidated by the
|
||||||
|
formula change.
|
||||||
|
|
||||||
|
**Acceptance:** Resolved when N.5 lands and both physics + visual
|
||||||
|
mesh use WB's split formula, OR when we decide to keep the AC2D
|
||||||
|
formula and patch WB's renderer in our fork.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## #50 — Road-edge tree at 0xA9B1 visible in acdream but not retail
|
## #50 — Road-edge tree at 0xA9B1 visible in acdream but not retail
|
||||||
|
|
||||||
**Status:** OPEN
|
**Status:** OPEN
|
||||||
|
|
|
||||||
|
|
@ -574,10 +574,23 @@ for our deletions/additions; merge upstream `master` periodically.
|
||||||
formula was ~180° off from retail's actual `Frame::set_heading` atan2
|
formula was ~180° off from retail's actual `Frame::set_heading` atan2
|
||||||
round-trip). One known cosmetic difference filed in ISSUES.md
|
round-trip). One known cosmetic difference filed in ISSUES.md
|
||||||
(road-edge tree at landblock 0xA9B1).
|
(road-edge tree at landblock 0xA9B1).
|
||||||
- **N.2 — Terrain math helpers.** Refactor `TerrainSurface.SampleZ` /
|
- **N.2 — Terrain math helpers.** ⚠️ **Blocked on N.5 — do not attempt
|
||||||
`SampleNormal` / `SampleSurface` to call WB's `TerrainUtils.GetHeight`
|
in isolation.** Originally scoped as a 1-2 day low-risk substitution
|
||||||
/ `GetNormal` internally. ~1-2 days. Smallest remaining N phase, low
|
of `TerrainSurface.SampleZ` / `SampleSurface` / `SampleSurfacePolygon`
|
||||||
risk after N.1's conformance proof on GetNormal.
|
with WB's `TerrainUtils.GetHeight` / `GetNormal`. Audit during N.3
|
||||||
|
follow-up uncovered that **WB's `CalculateSplitDirection` uses a
|
||||||
|
different formula than retail's `FSplitNESW`** (the AC2D-cited
|
||||||
|
polynomial `0x0CCAC033` / `0x421BE3BD` / `0x6C1AC587` / `0x519B8F25`
|
||||||
|
that our visual terrain mesh and physics already share). The
|
||||||
|
formulas pick different cell-diagonals on disputed cells, producing
|
||||||
|
up to ~2m Z divergence at the same world position. Substituting
|
||||||
|
physics-side alone would un-sync physics from the still-ours visual
|
||||||
|
mesh — exactly the triangle-Z hover bug class. N.1's conformance
|
||||||
|
test proved WB's `GetNormal` is good enough for slope-filtering
|
||||||
|
(boolean walkable check) but NOT that WB's height formula matches
|
||||||
|
retail. Resolution: fold this work into **N.5** when the visual
|
||||||
|
mesh switches to WB's renderer in lockstep with physics. Until
|
||||||
|
then, leave `TerrainSurface` alone. See ISSUE #51.
|
||||||
- **✓ SHIPPED — N.3 — Texture decoding.** Shipped 2026-05-08. `SurfaceDecoder`
|
- **✓ SHIPPED — N.3 — Texture decoding.** Shipped 2026-05-08. `SurfaceDecoder`
|
||||||
now delegates INDEX16 / P8 / A8R8G8B8 / R8G8B8 / A8 to WB's
|
now delegates INDEX16 / P8 / A8R8G8B8 / R8G8B8 / A8 to WB's
|
||||||
`TextureHelpers.Fill*`. The A8 divergence (our old code did R=G=B=A=val
|
`TextureHelpers.Fill*`. The A8 divergence (our old code did R=G=B=A=val
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue