diff --git a/analyze_flap_live.py b/analyze_flap_live.py
new file mode 100644
index 00000000..b1b32b45
--- /dev/null
+++ b/analyze_flap_live.py
@@ -0,0 +1,44 @@
+import sys, re, math
+from collections import Counter
+
+pat = re.compile(
+ r'outRoot=(\w) flood=(\d+) eye=\(([^)]+)\) player=\(([^)]+)\) '
+ r'rawPlayer=\(([^)]+)\) yaw=([-\d.]+)')
+rows = []
+for l in sys.stdin:
+ m = pat.search(l)
+ if not m:
+ continue
+ rows.append((
+ m.group(1), int(m.group(2)),
+ tuple(float(x) for x in m.group(3).split(',')), # eye
+ tuple(float(x) for x in m.group(4).split(',')), # player (RenderPosition)
+ tuple(float(x) for x in m.group(5).split(',')), # rawPlayer (physics body)
+ float(m.group(6)))) # yaw
+print("parsed pv-input rows:", len(rows))
+if not rows:
+ raise SystemExit
+
+print("flood histogram (outRoot,flood)->count:", dict(Counter((r[0], r[1]) for r in rows)))
+
+def rng(idx):
+ return [max(r[idx][k] for r in rows) - min(r[idx][k] for r in rows) for k in range(3)]
+print(f"eye range over window (m): {[round(v,6) for v in rng(2)]}")
+print(f"render-pos range over window (m): {[round(v,6) for v in rng(3)]}")
+print(f"raw-phys range over window (m): {[round(v,6) for v in rng(4)]}")
+print(f"yaw range over window (rad): {round(max(r[5] for r in rows)-min(r[5] for r in rows),6)}")
+
+flips = 0
+samples = []
+for i in range(1, len(rows)):
+ a, b = rows[i-1], rows[i]
+ if a[1] == b[1]:
+ continue
+ flips += 1
+ ed = math.dist(a[2], b[2]); pd = math.dist(a[3], b[3])
+ rd = math.dist(a[4], b[4]); yd = abs(b[5]-a[5])
+ if len(samples) < 18:
+ samples.append(f"{b[0]} {a[1]}->{b[1]:<2} eye={ed*1000:7.3f}mm rend={pd*1e6:8.1f}um raw={rd*1e6:8.1f}um yaw={yd*1000:8.4f}mrad")
+print(f"flood flips in window: {flips}")
+for s in samples:
+ print(" ", s)
diff --git a/docs/research/2026-06-08-flap-physics-diagnosis-REFUTED-its-render-membership.md b/docs/research/2026-06-08-flap-physics-diagnosis-REFUTED-its-render-membership.md
new file mode 100644
index 00000000..8e6b733e
--- /dev/null
+++ b/docs/research/2026-06-08-flap-physics-diagnosis-REFUTED-its-render-membership.md
@@ -0,0 +1,127 @@
+# Handoff/Findings — the "physics rest µm-jitter" flap diagnosis is REFUTED; the flap is a RENDER membership instability at the grazing doorway portal — 2026-06-08 (PM)
+
+> **Supersedes** `docs/research/2026-06-08-flap-rootcause-physics-rest-handoff.md` (the AM handoff). That
+> handoff asked to be treated as a suspect statement and verified — this session verified it with primary
+> evidence and it does **not** hold. The flap is **not physics** and **not camera drift**. It is the
+> portal-flood **membership flickering non-monotonically at the grazing doorway portal as the camera eye
+> sweeps** (i.e. while you turn the camera at the doorway). This is the SPEC's §2.2 diagnosis
+> (`2026-06-08-portal-flood-membership-stability-design.md`), NOT its refuted §4 enqueue-once fix.
+
+---
+
+## 1. What was claimed (AM handoff) vs what the evidence shows
+
+**AM claim:** the flap's varying input is a **physics resting-position µm jitter** — `_body.Position`
+blips ~1 ULP between ticks at rest → `RenderPosition` (Lerp of physics) jitters → eye jitters → flood
+flips. Fix = physics rest-stability (broaden `kill_velocity`, hold contact plane).
+
+**Refuted by three independent pieces of primary evidence:**
+
+### A. The physics body is bit-stable at standstill — it does NOT blip
+`door-recheck-capture.jsonl` (515 MB, 238,342 `ResolveWithTransition` records, captured standing at the
+doorway, cells `0xA9B40170/0171/0174/0175/0031`):
+- **216,300 true-standstill records** (zero velocity, `currentPos==targetPos`).
+- **0** resolve re-snaps (`result.position != input` never happens at standstill).
+- **0** cross-tick `currentPos` drift (the body position is carried forward byte-identically).
+- The `grounded-but-cp=none` contradictory state DOES occur (3.5% of frames) but produces **no** position
+ blip.
+
+Confirmed independently with **4 new deterministic tests** (all GREEN — they PROVE rest is bit-stable):
+- `PlayerMovementControllerTests.Update_AtRestNoInput_RenderPositionBitStableAcrossManyFrames` (flat terrain)
+- `PlayerMovementControllerTests.Update_WalkThenStop_SettlesToBitStableRest` (flat terrain, post-motion)
+- `CellarUpTrajectoryReplayTests.IndoorCellarFloor_AtRestZeroOffset_BodyPositionBitStable` (indoor cell, resolver loop)
+- `CellarUpTrajectoryReplayTests.IndoorCell_FullController_AtRestNoInput_RenderPositionBitStable` (indoor cell, full controller loop)
+
+### B. On the actual flap frames, the PLAYER position is byte-identical
+`pvinput.log` window 7748–7758 (a clean `flood 6↔2` flap), player `RenderPosition` for **11 consecutive
+frames**: `(155.632858, 13.527222, 94.000000)` — **byte-identical**. The physics output the camera reads
+does not move at all during the flap. (The 1-ULP *player* blip the AM handoff cited is at the **outdoor**
+`flood=1` records — a red herring, not the indoor flap.)
+
+### C. The EYE moves while the player is still — and the camera DOES settle when idle
+Same window: the eye orbits smoothly ~1 mm/frame (X ↓, Y ↑, Z constant) — a slow **camera rotation**
+around the stationary player. And:
+- Of **888** flood flips in the capture, only **1** had a byte-identical eye (and that one is the
+ outdoor→indoor root switch). Every other flip had a moved eye → **the flood is deterministic in the
+ eye; it changes only when the eye moves** (matches `Build_IsDeterministic_*`).
+- Longest **indoor byte-identical-eye runs: 203 / 181 / 178 frames (~3.4 s)** — within each, the flood is
+ a **single constant value** (no flicker). **61%** of indoor frames have a byte-stable eye.
+- ⇒ The camera **settles** at rest (no boom drift, no spring oscillation). When the eye is still, the
+ flood is stable. The flap fires **only while the eye is moving**.
+
+## 2. The actual mechanism
+
+When the camera eye **sweeps** through the grazing doorway portal (you turn the camera at the threshold),
+the deep cell cluster `{0172,0173,0174,0175}` flickers in/out — flood `6,6,6,2,2,6,6,6,2,6,2` — i.e.
+**non-monotonic membership across a monotonic eye sweep**. A correct visibility flood would transition
+the deep cluster in/out **once** as the grazing portal closes; instead its clip flips empty↔non-empty as
+the eye crosses and re-crosses the knife-edge. This is the SPEC's §2.2 diagnosis (the grazing portal's
+clip / re-clip drift makes `clippedRegion.Count` flip `0↔N`, dropping the deep cluster on empty-clip
+frames).
+
+It is **NOT** physics (A, B). It is **NOT** camera drift/oscillation (C: eye byte-stable ~3.4 s when
+idle). It is a **render-side portal-flood membership instability at grazing angles**, surfaced by camera
+rotation.
+
+## 3. Status of prior fixes / diagnoses
+
+- **AM physics-rest fix** — would not have fixed the flap (physics rest is already bit-stable). Do not pursue.
+- **SPEC §2.2 diagnosis (grazing-portal membership instability)** — CONFIRMED by this evidence.
+- **SPEC §4 enqueue-once fix** — already refuted in the AM handoff (retail propagates late slices via
+ `AddToCell`, decomp :433494; broke `Build_ViewGrowthAfterDoneCell_PropagatesNewSlicesToExit`). So the
+ correct fix is a render-side membership stabilization that is monotonic under a sweeping eye **without**
+ breaking late-slice propagation — design TBD (brainstorm).
+
+## 4. Apparatus (this session)
+- 4 GREEN rest-stability tests (above) — keep as regression guards + evidence that physics rest is bit-stable.
+- Analysis scripts (ad-hoc, `/tmp`): door-recheck standstill survey; pvinput flood-flip vs eye/player
+ delta buckets; indoor byte-stable-eye-run scan. Re-derivable from `pvinput.log` + `door-recheck-capture.jsonl`.
+- Existing probes `[pv-input]` (`ACDREAM_PROBE_PVINPUT`) and `[render-sig]` remain the live gate.
+
+## 5. Next step (proposed)
+Brainstorm + design a render-side fix that makes the deep-cluster membership **monotonic/stable as the eye
+sweeps the grazing portal** (candidates: more robust grazing-portal clip, a retail-faithful single-process
+traversal that doesn't re-clip-drift, or matching retail's exact `GetClip`/`polyClipFinish` epsilon). Then
+TDD a builder test that sweeps the eye across the grazing angle and asserts monotonic membership, and
+visual-gate by turning the camera at the cottage doorway.
+
+## 6. LIVE-CONFIRMED (2026-06-08 PM, targeted doorway capture, user-driven)
+
+A fresh instrumented capture (`launch-flap-capture.ps1`; `[pv-input]` enhanced with `rawPlayer`=raw
+physics body pos + `yaw`; cells `0170-0175` dumped to `tests/.../Fixtures/flap-doorway/`; 84K frames)
+confirms the diagnosis across every state and decomposes the flap into THREE render sub-issues. **In
+every case the player render-pos AND raw physics-pos are byte-identical (0 µm) — physics is conclusively
+exonerated; the flap is 100% camera-eye-driven.**
+
+| State (user-driven) | player moves | eye moves | flood |
+|---|---|---|---|
+| Idle, hands fully off | no (0 µm) | **no (0 µm)** | **stable** (no flap) |
+| Turn / walk | no (0 µm) | yes (mm, yaw) | oscillates |
+| Camera smoothing-glide after a turn (yaw byte-constant, eye glides monotonically, decelerating) | no | yes (mm) | **oscillates 8↔3** ← this is the "flickers while idle" the user perceived |
+
+Key burst (row 11167): **yaw byte-constant**, eye X glides monotonically 155.109→155.435 (18→5 mm/frame,
+decelerating), flood `8→3→8…3→8`. Monotonic eye ⇒ non-monotonic membership ⇒ **render** instability (not
+camera hunting).
+
+**Three sub-issues (all eye-driven, physics out):**
+- **A — Membership oscillation:** flood non-monotonic as the eye sweeps within a *stable* root.
+ outside-looking-in `8↔3`; outdoor-root `17↔33` (21 flips/2500 frames); indoor-root `2↔6`.
+- **B — Root toggle (the big one):** at the threshold, `outRoot` flips outdoor↔indoor as the eye crosses
+ the door plane → wholesale visible-set swap **≈18-33 cells ↔ 2 cells** (4 toggles in 2500 frames). This
+ is the "two-branch" outdoor-node-vs-indoor-cell root switch the unification was meant to remove — still
+ present.
+- **C — Indoor-root under-inclusion:** eye just inside ⇒ `outRoot=n` flood **= 2, stable** for 2438
+ frames → outdoors + other rooms missing (the indoor flood does not reach back out the exit portal / to
+ adjacent cells). C is B's partner: the swap *to* indoor loses the scene → "textures missing."
+
+**Fix scope:** core render pipeline (root resolution + flood + grazing-clip), NOT physics, NOT camera.
+Spec §2.2 (membership instability) is right for A; B+C are the threshold root-resolution/flood issues.
+Spec §4 enqueue-once stays refuted. Design needs brainstorming (saga has reverted speculative render
+fixes — see `feedback_render_one_gate`, `feedback_verify_render_seal_before_layering`).
+
+Apparatus added: `launch-flap-capture.ps1`, `analyze_flap_live.py`, `find_burst.py`, fixtures
+`tests/AcDream.Core.Tests/Fixtures/flap-doorway/0xA9B4017{0..5}.json`, `flap-doorway-resolve.jsonl`.
+
+**Memory to correct:** `project_indoor_flap_rootcause` (root is render: A membership instability + B
+root-toggle + C indoor under-inclusion, all under a moving camera eye — NOT physics rest, NOT camera
+drift; the "two-branch split" B is still live).
diff --git a/docs/superpowers/specs/2026-06-08-portal-flood-enqueue-once-port-design.md b/docs/superpowers/specs/2026-06-08-portal-flood-enqueue-once-port-design.md
new file mode 100644
index 00000000..4b7ca68e
--- /dev/null
+++ b/docs/superpowers/specs/2026-06-08-portal-flood-enqueue-once-port-design.md
@@ -0,0 +1,219 @@
+# Portal-Flood Enqueue-Once Port — the indoor "flap" fix (verified design)
+
+**Date:** 2026-06-08
+**Branch:** `claude/thirsty-goldberg-51bb9b`
+**Status:** Design approved (brainstorm). Pending implementation plan.
+
+> **Supersedes** the enqueue logic in `docs/superpowers/specs/2026-06-08-portal-flood-membership-stability-design.md`
+> (whose §4 enqueue-once was an *incomplete* attempt — it dropped the `AddToCell` growth half) and the
+> physics-rest direction in `docs/research/2026-06-08-flap-rootcause-physics-rest-handoff.md` (refuted).
+> **Diagnosis evidence:** `docs/research/2026-06-08-flap-physics-diagnosis-REFUTED-its-render-membership.md`
+> + this session's two adversarial verification agents (retail decomp + acdream code/data).
+
+---
+
+## 1. Summary
+
+The indoor render **flap** (interior textures battling / popping in and out at a building doorway) is a
+**render-side portal-flood membership instability**: as the camera **eye** moves (turning the camera, or
+the camera's smoothing-glide after a turn), the set of cells the flood deems visible **oscillates**
+(e.g. `8↔3`) even though the eye sweeps **monotonically**. The root is acdream's **re-enqueue-on-growth
+"drift"** in `PortalVisibilityBuilder.Build` (`cs:322`, `MaxReprocessPerCell = 16`): a cell whose view
+grows is re-enqueued and its portals **re-clipped from the grown (drifted) view** each round; under
+sub-cm eye motion each frame re-clips slightly differently → the visible set flips.
+
+The fix is a **verbatim port of retail's enqueue-once portal traversal** (`PView::ConstructView` +
+`AddViewToPortals`): a cell is enqueued **only on first discovery**; its portals are clipped **exactly
+once** (at pop); later growth into an already-discovered cell is unioned **incrementally in place**
+(`AddToCell`) and its draw-list slot re-ordered (`FixCellList`) — **never re-enqueued, never re-clipped
+from scratch**. This makes the visible set a deterministic function of the **root + geometry**, so it no
+longer drifts with eye jitter. Localized to `PortalVisibilityBuilder`. No camera, physics, rooting, clip-
+math, or seal change.
+
+---
+
+## 2. Root cause — verified this session
+
+### 2.1 What the flap is NOT (refuted with primary evidence)
+- **Not physics.** `door-recheck-capture.jsonl`: **216,300 standstill physics records, 0 position
+ re-snaps** — the body is byte-stable at rest. Deterministic tests (flat terrain + indoor cell, resolver
+ + full controller) confirm: a resting body holds a byte-identical position. The 2026-06-08 AM
+ "physics rest µm-jitter" diagnosis is refuted.
+- **Not the camera rooting or the inside/outside toggle.** Verified against retail (agent 1):
+ `SmartBox::RenderNormalMode` (0x453aa0) calls **`DrawInside(viewer_cell)`** (decomp 92675), and
+ `SmartBox::update_viewer` (0x453ce0) sets `viewer_cell` from a **swept `CTransition`** seeded at the
+ **player's cell** (`init_path(cell_1, …)` 92866 → `viewer_cell = sphere_path.curr_cell` 92871). So
+ rooting at the camera's `viewer_cell` and toggling `DrawInside`/`LScape::draw` are **retail-faithful**.
+ The locked-design claim "root at the player cell" (`2026-06-02 …redesign-design.md` §1.5) is **wrong**;
+ acdream's current `clipRoot = viewerRoot ?? _outdoorNode` (eye-cell rooting) is correct and stays.
+- **Not camera drift at rest.** When the eye is byte-stable (hands-off idle), the flood is rock-stable
+ (203/181/178-frame byte-identical-eye runs hold a single flood value). The camera settles; the flap
+ fires **only while the eye moves**.
+
+### 2.2 What the flap IS (verified — agent 2 + live capture)
+- The flood oscillates **only when the eye moves**: across ~7,800 flood flips, **3** had a byte-identical
+ eye (all startup/streaming); **~87 %** of eye-motion flips have a **byte-identical player** position.
+ A clean burst (yaw byte-constant, eye gliding monotonically 18→5 mm/frame as the camera settles) shows
+ flood `8→3→8…` — **non-monotonic membership under a monotonic eye sweep**.
+- The mechanism is the **re-enqueue/re-clip drift**: `PortalVisibilityBuilder.cs:322`
+ `if (grew && popCounts.GetValueOrDefault(neighbourId) < MaxReprocessPerCell && queued.Add(neighbourId))
+ todo.Insert(neighbour, dist);` re-enqueues a grown neighbour up to 16×; each re-process re-clips the
+ cell's portals from its grown view, so sub-cm eye jitter walks `ClipToRegion`'s surviving-vertex count
+ across the empty/non-empty boundary → the deep cluster `{0172-0175}` drops/returns → the flap.
+- **Sub-issue "C" (indoor flood=2 / "missing textures") is mostly a *symptom* of this drift**, not a
+ missing seal: the landscape-through-the-door seal **is** present in the indoor path
+ (`RetailPViewRenderer.DrawInside` → `DrawLandscapeThroughOutsideView`). When the flood drops `8→3`,
+ the `OutsideView`/terrain/cell clip shrinks → things vanish. Fixing the drift removes the symptom.
+
+---
+
+## 3. Retail grounding (the traversal being ported)
+
+All from `docs/research/named-retail/acclient_2013_pseudo_c.txt`:
+
+- **`PView::ConstructView`** (0x5a57b0, :433750): `InitCell(root)` + `InsCellTodoList(root)`, then a loop
+ that **pops one cell at a time** from the todo list, **appends it to the draw list** (← that is
+ membership), sets `cell_view_done = 1` (:433784), runs `ClipPortals` once, then `AddViewToPortals`.
+- **`PView::AddViewToPortals`** (0x5a52d0, :433446): for each visible portal to a neighbour, three cases
+ keyed on the neighbour's stamps (`processed_stamp` = `*(view+0x44)`, `view_stamp` = `*(view+0x38)`):
+ - **First discovery** (`processed_stamp == 0`, :433478): `InitCell(neighbour)` + `InsCellTodoList`
+ (**enqueue once**).
+ - **Growth** (`processed_stamp != view_stamp`, :433492): `AddToCell(neighbour)` + if already drawn
+ `FixCellList`; then `processed_stamp = view_stamp`. **No re-enqueue. No re-clip from scratch.**
+ - **Already current** (`processed_stamp == view_stamp`): **nothing**.
+- **`PView::AddToCell`** (0x5a4d90, :433050): clips the cell's portals against **only the newly-added
+ view slices** (`for i = esi[0x11]; i < esi[0xe]`) — an **incremental** union, not a full re-clip; it
+ does **not** re-contribute to `OutsideView`.
+- **`PView::FixCellList`** (0x5a5250, :433407) → `AdjustDrawList` (:433107): **re-orders** the grown cell
+ in the draw list to preserve draw order. No re-flood.
+- **`PView::InitCell`** (0x5a4b70, :432896): seeds the cell's view, clips its portals against the full
+ incoming view, stamps with `master_timestamp`; returns whether the cell is non-empty (→ enqueue).
+
+So retail clips each cell's portals **exactly once** (at pop). Late growth refines a cell's own view +
+draw order, never its downstream flood. This is the `cell_view_done` "process each cell once" guarantee.
+
+---
+
+## 4. The fix (design)
+
+**Scope: `PortalVisibilityBuilder.Build` only.** Replace the re-enqueue-on-growth fixpoint with retail's
+enqueue-once traversal. Concretely:
+
+**Change A — enqueue-once (`Build` ~308-328).** Today:
+
+ var nview = GetOrCreate(frame.CellViews, neighbourId);
+ bool grew = AddRegion(nview, clippedRegion); // union in place (= retail AddToCell)
+ if (grew && popCounts.GetValueOrDefault(neighbourId) < MaxReprocessPerCell && queued.Add(neighbourId))
+ todo.Insert(neighbour, dist); // RE-ENQUEUE on growth ← the drift
+
+New: enqueue a neighbour into `todo` **only on first discovery** — i.e. when it has **no `CellViews`
+entry yet** (retail `processed_stamp == 0` → `InitCell` + `InsCellTodoList`). On growth into an
+already-discovered neighbour, **keep `AddRegion`** (incremental union = `AddToCell`) and re-order it in
+the draw list if already present (`FixCellList`, §Change C), but **do not** re-insert into `todo`.
+
+**Change B — remove the re-enqueue machinery.** Delete `MaxReprocessPerCell`, `popCounts`, and the
+per-pop re-enqueue / `queued`-reset logic in the pop loop. Termination is now by construction (each cell
+enqueued ≤1, popped ≤1; ≤N cells total), matching retail `cell_view_done`. The `MaxReprocessPerCell` cap
+existed **only** as a termination band-aid for the re-enqueue — with enqueue-once it is dead.
+
+**Change C — draw-list re-order on growth (`FixCellList`).** When growth unions into an
+already-discovered cell that is **already in `OrderedVisibleCells`**, re-position it to preserve
+closest-first draw order (retail `AdjustDrawList` :433107). If acdream's `OrderedVisibleCells` is already
+distance-sorted at assembly time and order is not load-bearing for correctness, this degrades to a no-op
+— confirm during implementation; do **not** add ordering machinery the renderer doesn't consume.
+
+**Unchanged (explicitly):** the per-portal clip (`ProjectToClip`/`ClipToRegion`), the
+`EyeInsidePortalOpening` degenerate-portal guard (`Build:235-244`), the reciprocal `OtherPortalClip`, the
+`OutsideView` exit contribution, the rooting (`clipRoot = viewerRoot ?? _outdoorNode`), the camera, and
+the landscape-through-door seal. No new predicate, no robustness heuristic, no hysteresis.
+
+**Why this is the flap fix, not a band-aid:** with each cell's portals clipped once, the visible set is a
+deterministic function of `(root, geometry)` — independent of the per-round re-clip path. Sub-cm eye
+jitter changes the *projection* (and thus what's drawn within each clipped cell, correctly) but no longer
+changes *which cells are members*. The membership stops oscillating; the textures stop battling.
+
+---
+
+## 5. The `Build_ViewGrowthAfterDoneCell` question (open item, resolve during implementation)
+
+The re-enqueue was added 2026-06-07 "to propagate late-discovered slices to exit portals," and
+`PortalVisibilityBuilderTests.Build_ViewGrowthAfterDoneCell_PropagatesNewSlicesToExit` encodes that. But
+the decomp shows retail's `AddToCell` (:433050) only clips the cell's **own** portals against new slices
++ re-orders draw position — it does **not** re-contribute to `OutsideView` (the exit slice is emitted by
+`ClipPortals` at pop, once). So "late growth reaches the exit/OutsideView" appears to be **non-retail**.
+
+**Action:** read `PView::ClipPortals` (the OutsideView contribution site) during implementation to
+confirm. If confirmed, this test encodes the non-faithful re-enqueue behavior and is **corrected to
+match retail** (late growth refines the cell's view + draw order, not the OutsideView). It will **not**
+be satisfied by reinstating the re-enqueue. If the OutsideView tests
+(`Builder_Cellar_WindowClippedToStairwell`, look-in tests) shrink, that is the retail behavior, handled
+retail's way — not by re-adding the drift.
+
+---
+
+## 6. Testing (TDD)
+
+The flap manifests only under live µm/mm eye motion at a specific grazing geometry, so the **visual gate
+is acceptance**; the unit layer pins determinism + guards regressions.
+
+1. **Deterministic eye-sweep stability (new, the RED→GREEN driver).** In `AcDream.App.Tests`
+ (alongside `PortalVisibilityBuilderTests`, since `PortalVisibilityBuilder` is an App-layer type), build
+ the flood at a sequence of eye positions stepping across the grazing door angle (sub-cm steps
+ reproducing the live sweep). **Assert each cell's membership across the sweep is a single contiguous
+ run** — no `present→absent→present` (or `absent→present→absent`) flicker for any cell. That is the
+ precise anti-flap property (the live capture showed `8→3→8→3`, multiple transitions per cell). RED
+ under the re-enqueue drift; GREEN after enqueue-once. *Fixture note:* the captured dumps live at
+ `tests/AcDream.Core.Tests/Fixtures/flap-doorway/0xA9B4017{0..5}.json`; the test must reach them
+ (shared path or copied into `AcDream.App.Tests/Fixtures`) and the cells must carry the portal graph +
+ clip planes `Build` consumes. If the cell-dump format omits portals/clip-planes, the impl plan either
+ extends the dump or synthesizes a minimal doorway portal topology reproducing the grazing geometry —
+ surface this as the first implementation step, do not silently weaken the test.
+2. **Enqueue-once termination + dedup (new).** Diamond (a cell reachable from two parents) + cycle
+ fixtures: assert the flood terminates with `MaxReprocessPerCell` removed, `OrderedVisibleCells` is
+ deduped, each reachable cell present exactly once, and (if a per-cell pop counter is cheap to surface)
+ each cell popped ≤1.
+3. **No membership regression.** `Build_IsDeterministic_*`, `Build_EyeStandingInInteriorPortal_FloodsNeighbour`,
+ `Build_CollapsedInteriorPortalNearEyeBeyondHalfMeter_FloodsNeighbour`,
+ `Build_DegeneratePortalToTheSide_NotFlooded_NoOverInclusion` (#95 guard), and the cellar/window/look-in
+ tests stay **green**. `Build_ViewGrowthAfterDoneCell_PropagatesNewSlicesToExit` is handled per §5.
+4. **Visual gate (user) — acceptance.** At the cottage doorway: turn the camera back and forth and walk
+ through — the interior rooms render steadily, no battling/popping; the `[pv-input]` flood is stable
+ for a given eye pose. Re-run with `launch-flap-capture.ps1`.
+
+`dotnet build` + `dotnet test` green before the visual gate.
+
+---
+
+## 7. Scope / non-goals
+
+- **In scope:** `PortalVisibilityBuilder.Build` enqueue logic (enqueue-once; remove
+ `MaxReprocessPerCell`/`popCounts`/re-enqueue; incremental union on growth; draw-order re-position) + the
+ new/updated tests; reading `ClipPortals` to settle §5.
+- **Non-goals (deferred / untouched):**
+ - **No rooting change** — eye-cell rooting (`clipRoot = viewerRoot ?? _outdoorNode`) is retail-faithful
+ (§2.1). The locked design's "root at player cell" is refuted, not implemented.
+ - **No clip-math change** (`ProjectToClip`/`ClipToRegion`), no `EyeInsidePortalOpening` change, no
+ overlap predicate, no hysteresis/robustness heuristic.
+ - **No camera, physics, or seal change.** The landscape-through-door seal already exists; C is a symptom
+ of the drift and resolves with it.
+ - The 4 GREEN physics rest-stability tests added this session stay as regression guards (they document
+ that physics rest is bit-stable → the flap is not physics).
+
+---
+
+## 8. Apparatus + references
+
+- **Diagnosis + verification:** `docs/research/2026-06-08-flap-physics-diagnosis-REFUTED-its-render-membership.md`;
+ this session's two adversarial verification agents (retail decomp CONFIRMED rooting/seal; acdream
+ code/data CONFIRMED physics-out + eye-driven + the `cs:322` drift).
+- **Captured fixtures:** `tests/AcDream.Core.Tests/Fixtures/flap-doorway/0xA9B4017{0..5}.json`;
+ `flap-doorway-resolve.jsonl`. Apparatus: `launch-flap-capture.ps1`, `analyze_flap_live.py`,
+ `find_burst.py`, the `[pv-input]` probe (`ACDREAM_PROBE_PVINPUT`, now logs eye/player/rawPlayer/yaw).
+- **Retail decomp anchors:** `ConstructView` :433750, `AddViewToPortals` :433446, `InitCell` :432896,
+ `AddToCell` :433050, `FixCellList` :433407 / `AdjustDrawList` :433107, `InsCellTodoList` :433183,
+ `SmartBox::update_viewer` :92761, `SmartBox::RenderNormalMode` :92635.
+- **Superseded:** `2026-06-08-portal-flood-membership-stability-design.md` §4 (incomplete enqueue-once);
+ `2026-06-08-flap-rootcause-physics-rest-handoff.md` (physics direction, refuted).
+- **Memory to correct after ship:** `project_indoor_flap_rootcause` (root = the `PortalVisibilityBuilder`
+ re-enqueue/re-clip **drift** under a moving eye; rooting/toggle is retail-faithful; physics + camera
+ exonerated).
diff --git a/find_burst.py b/find_burst.py
new file mode 100644
index 00000000..ef58eca9
--- /dev/null
+++ b/find_burst.py
@@ -0,0 +1,30 @@
+import sys, re
+path = sys.argv[1]
+pat = re.compile(r'flood=(\d+) eye=\(([^)]+)\) player=\(([^)]+)\) rawPlayer=\(([^)]+)\) yaw=([-\d.]+)')
+rows = []
+with open(path, encoding='utf-8', errors='ignore') as fh:
+ for l in fh:
+ m = pat.search(l)
+ if m:
+ rows.append((int(m.group(1)),
+ tuple(float(x) for x in m.group(2).split(',')),
+ float(m.group(5))))
+print("total pv-input rows:", len(rows))
+# find first window of 25 frames containing >=4 flood changes (an oscillation burst)
+def changes(seg): return sum(1 for i in range(1, len(seg)) if seg[i][0] != seg[i-1][0])
+W = 25
+start = None
+for i in range(len(rows)-W):
+ if changes(rows[i:i+W]) >= 4:
+ start = i; break
+if start is None:
+ print("no oscillation burst found"); sys.exit()
+print(f"burst at row {start}; dumping {W+8} frames (flood, eyeX,eyeY,eyeZ, dEyeX_mm,dEyeY_mm, yaw):")
+prev = None
+for r in rows[start:start+W+8]:
+ fl, e, yaw = r
+ dx = (e[0]-prev[0])*1000 if prev else 0.0
+ dy = (e[1]-prev[1])*1000 if prev else 0.0
+ mark = " <" if (prev and fl != prevfl) else ""
+ print(f" flood={fl} eye=({e[0]:.6f},{e[1]:.6f},{e[2]:.6f}) dX={dx:+7.3f}mm dY={dy:+7.3f}mm yaw={yaw:.6f}{mark}")
+ prev = e; prevfl = fl
diff --git a/launch-flap-capture.ps1 b/launch-flap-capture.ps1
new file mode 100644
index 00000000..7530998a
--- /dev/null
+++ b/launch-flap-capture.ps1
@@ -0,0 +1,23 @@
+$env:ACDREAM_DAT_DIR = "$env:USERPROFILE\Documents\Asheron's Call"
+$env:ACDREAM_LIVE = "1"
+$env:ACDREAM_TEST_HOST = "127.0.0.1"
+$env:ACDREAM_TEST_PORT = "9000"
+$env:ACDREAM_TEST_USER = "testaccount"
+$env:ACDREAM_TEST_PASS = "testpassword"
+
+# Targeted flap capture (2026-06-08). Goal: pin what VARIES at the grazing
+# doorway pose when the deep rooms flicker — especially the IDLE case.
+#
+# 1. [pv-input] : per frame — eye + player(RenderPos) + rawPlayer(physics) + yaw + flood.
+# If the flood flickers, exactly one of those is the varying input.
+# 2. CAPTURE_RESOLVE : full physics body JSONL per resolve (confirm body bit-stable at the doorway).
+# 3. DUMP_CELLS : dump doorway cell geometry as fixtures so a deterministic
+# eye-sweep builder test can be written without the live client.
+Remove-Item Env:\ACDREAM_PROBE_FLAP -ErrorAction SilentlyContinue
+$env:ACDREAM_PROBE_PVINPUT = "1"
+$env:ACDREAM_CAPTURE_RESOLVE = "flap-doorway-resolve.jsonl"
+$env:ACDREAM_DUMP_CELLS = "0xA9B40170,0xA9B40171,0xA9B40172,0xA9B40173,0xA9B40174,0xA9B40175,0xA9B40031"
+$env:ACDREAM_DUMP_CELLS_DIR = "tests\AcDream.Core.Tests\Fixtures\flap-doorway"
+
+dotnet run --project src\AcDream.App\AcDream.App.csproj --no-build -c Debug 2>&1 |
+ Tee-Object -FilePath "flap-doorway-pvinput.log"
diff --git a/src/AcDream.App/Rendering/GameWindow.cs b/src/AcDream.App/Rendering/GameWindow.cs
index a0b7aa60..63f3cc48 100644
--- a/src/AcDream.App/Rendering/GameWindow.cs
+++ b/src/AcDream.App/Rendering/GameWindow.cs
@@ -7569,8 +7569,14 @@ public sealed class GameWindow : IDisposable
{
var vp = envCellViewProj;
char pvOutRoot = ReferenceEquals(clipRoot, _outdoorNode) ? 'Y' : 'n';
+ // 2026-06-08: disambiguate the idle flap. eye=camera eye-point (drives the flood);
+ // player=RenderPosition (Lerp of physics, what the eye chases); rawPlayer=raw physics
+ // body Position; yaw=camera/player heading (F8 rad to catch micro-drift). If the flood
+ // flickers while idle, exactly one of {eye, player, rawPlayer, yaw} is the varying input.
+ var pvRawPlayer = _playerController?.Position ?? playerViewPos;
+ float pvYaw = _playerController?.Yaw ?? 0f;
Console.WriteLine(System.FormattableString.Invariant(
- $"[pv-input] outRoot={pvOutRoot} flood={pvFrame.OrderedVisibleCells.Count} eye=({camPos.X:F6},{camPos.Y:F6},{camPos.Z:F6}) player=({playerViewPos.X:F6},{playerViewPos.Y:F6},{playerViewPos.Z:F6}) vp=[{vp.M11:F6} {vp.M13:F6} {vp.M22:F6} {vp.M31:F6} {vp.M33:F6} {vp.M41:F6} {vp.M42:F6} {vp.M43:F6}]"));
+ $"[pv-input] outRoot={pvOutRoot} flood={pvFrame.OrderedVisibleCells.Count} eye=({camPos.X:F6},{camPos.Y:F6},{camPos.Z:F6}) player=({playerViewPos.X:F6},{playerViewPos.Y:F6},{playerViewPos.Z:F6}) rawPlayer=({pvRawPlayer.X:F6},{pvRawPlayer.Y:F6},{pvRawPlayer.Z:F6}) yaw={pvYaw:F8} vp=[{vp.M11:F6} {vp.M13:F6} {vp.M22:F6} {vp.M31:F6} {vp.M33:F6} {vp.M41:F6} {vp.M42:F6} {vp.M43:F6}]"));
}
sigPvFrame = pviewResult.PortalFrame;
diff --git a/tests/AcDream.Core.Tests/Fixtures/flap-doorway/0xA9B40170.json b/tests/AcDream.Core.Tests/Fixtures/flap-doorway/0xA9B40170.json
new file mode 100644
index 00000000..346b1e55
--- /dev/null
+++ b/tests/AcDream.Core.Tests/Fixtures/flap-doorway/0xA9B40170.json
@@ -0,0 +1,413 @@
+{
+ "CellId": 2847146352,
+ "WorldTransform": {
+ "M11": -1,
+ "M12": 8.74228E-08,
+ "M13": 0,
+ "M14": 0,
+ "M21": -8.74228E-08,
+ "M22": -1,
+ "M23": 0,
+ "M24": 0,
+ "M31": 0,
+ "M32": 0,
+ "M33": 1,
+ "M34": 0,
+ "M41": 161.929,
+ "M42": 7.50315,
+ "M43": 94,
+ "M44": 1
+ },
+ "InverseWorldTransform": {
+ "M11": -1,
+ "M12": -8.74228E-08,
+ "M13": 0,
+ "M14": -0,
+ "M21": 8.74228E-08,
+ "M22": -1,
+ "M23": 0,
+ "M24": 0,
+ "M31": 0,
+ "M32": 0,
+ "M33": 1,
+ "M34": -0,
+ "M41": 161.929,
+ "M42": 7.5031643,
+ "M43": -94,
+ "M44": 1
+ },
+ "ResolvedPolygons": [
+ {
+ "Id": 0,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 7.45189
+ },
+ "Vertices": [
+ {
+ "X": 7.45189,
+ "Y": -8.609,
+ "Z": 0
+ },
+ {
+ "X": 7.45189,
+ "Y": -8.34616,
+ "Z": 2.5
+ },
+ {
+ "X": 7.45189,
+ "Y": -7.65,
+ "Z": 2.5
+ },
+ {
+ "X": 7.45189,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 1,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1.2430552E-08,
+ "Z": 1
+ },
+ "D": 1.0701463E-07
+ },
+ "Vertices": [
+ {
+ "X": 5.54731,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 5.54731,
+ "Y": -8.609,
+ "Z": 0
+ },
+ {
+ "X": 7.45189,
+ "Y": -8.609,
+ "Z": 0
+ },
+ {
+ "X": 7.45189,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 2,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": -5.54731
+ },
+ "Vertices": [
+ {
+ "X": 5.54731,
+ "Y": -7.65,
+ "Z": 2.5
+ },
+ {
+ "X": 5.54731,
+ "Y": -8.34616,
+ "Z": 2.5
+ },
+ {
+ "X": 5.54731,
+ "Y": -8.609,
+ "Z": 0
+ },
+ {
+ "X": 5.54731,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 3,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 0,
+ "Z": -1
+ },
+ "D": 2.5
+ },
+ "Vertices": [
+ {
+ "X": 7.45189,
+ "Y": -7.65,
+ "Z": 2.5
+ },
+ {
+ "X": 7.45189,
+ "Y": -8.34616,
+ "Z": 2.5
+ },
+ {
+ "X": 5.54731,
+ "Y": -8.34616,
+ "Z": 2.5
+ },
+ {
+ "X": 5.54731,
+ "Y": -7.65,
+ "Z": 2.5
+ }
+ ]
+ }
+ ],
+ "PortalPolygons": [
+ {
+ "Id": 0,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 0,
+ "Z": -1
+ },
+ "D": 2.5
+ },
+ "Vertices": [
+ {
+ "X": 7.45189,
+ "Y": -7.65,
+ "Z": 2.5
+ },
+ {
+ "X": 7.45189,
+ "Y": -8.34616,
+ "Z": 2.5
+ },
+ {
+ "X": 5.54731,
+ "Y": -8.34616,
+ "Z": 2.5
+ },
+ {
+ "X": 5.54731,
+ "Y": -7.65,
+ "Z": 2.5
+ }
+ ]
+ },
+ {
+ "Id": 1,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 7.45189
+ },
+ "Vertices": [
+ {
+ "X": 7.45189,
+ "Y": -8.609,
+ "Z": 0
+ },
+ {
+ "X": 7.45189,
+ "Y": -8.34616,
+ "Z": 2.5
+ },
+ {
+ "X": 7.45189,
+ "Y": -7.65,
+ "Z": 2.5
+ },
+ {
+ "X": 7.45189,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 2,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1.2430552E-08,
+ "Z": 1
+ },
+ "D": 1.0701463E-07
+ },
+ "Vertices": [
+ {
+ "X": 5.54731,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 5.54731,
+ "Y": -8.609,
+ "Z": 0
+ },
+ {
+ "X": 7.45189,
+ "Y": -8.609,
+ "Z": 0
+ },
+ {
+ "X": 7.45189,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 3,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": -5.54731
+ },
+ "Vertices": [
+ {
+ "X": 5.54731,
+ "Y": -7.65,
+ "Z": 2.5
+ },
+ {
+ "X": 5.54731,
+ "Y": -8.34616,
+ "Z": 2.5
+ },
+ {
+ "X": 5.54731,
+ "Y": -8.609,
+ "Z": 0
+ },
+ {
+ "X": 5.54731,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 4,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -0.99451864,
+ "Z": 0.10455982
+ },
+ "D": -8.5618105
+ },
+ "Vertices": [
+ {
+ "X": 5.54731,
+ "Y": -8.609,
+ "Z": 0
+ },
+ {
+ "X": 7.45189,
+ "Y": -8.609,
+ "Z": 0
+ },
+ {
+ "X": 7.45189,
+ "Y": -8.34616,
+ "Z": 2.5
+ },
+ {
+ "X": 5.54731,
+ "Y": -8.34616,
+ "Z": 2.5
+ }
+ ]
+ },
+ {
+ "Id": 5,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": -7.65
+ },
+ "Vertices": [
+ {
+ "X": 7.45189,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 7.45189,
+ "Y": -7.65,
+ "Z": 2.5
+ },
+ {
+ "X": 5.54731,
+ "Y": -7.65,
+ "Z": 2.5
+ },
+ {
+ "X": 5.54731,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ }
+ ]
+ }
+ ],
+ "Portals": [
+ {
+ "OtherCellId": 65535,
+ "PolygonId": 4,
+ "Flags": 5
+ },
+ {
+ "OtherCellId": 369,
+ "PolygonId": 5,
+ "Flags": 3
+ }
+ ],
+ "VisibleCellIds": [
+ 2847146351,
+ 2847146353,
+ 2847146354,
+ 2847146355,
+ 2847146356,
+ 2847146357
+ ]
+}
\ No newline at end of file
diff --git a/tests/AcDream.Core.Tests/Fixtures/flap-doorway/0xA9B40171.json b/tests/AcDream.Core.Tests/Fixtures/flap-doorway/0xA9B40171.json
new file mode 100644
index 00000000..48ea0445
--- /dev/null
+++ b/tests/AcDream.Core.Tests/Fixtures/flap-doorway/0xA9B40171.json
@@ -0,0 +1,3773 @@
+{
+ "CellId": 2847146353,
+ "WorldTransform": {
+ "M11": -1,
+ "M12": 8.74228E-08,
+ "M13": 0,
+ "M14": 0,
+ "M21": -8.74228E-08,
+ "M22": -1,
+ "M23": 0,
+ "M24": 0,
+ "M31": 0,
+ "M32": 0,
+ "M33": 1,
+ "M34": 0,
+ "M41": 161.929,
+ "M42": 7.50315,
+ "M43": 94,
+ "M44": 1
+ },
+ "InverseWorldTransform": {
+ "M11": -1,
+ "M12": -8.74228E-08,
+ "M13": 0,
+ "M14": -0,
+ "M21": 8.74228E-08,
+ "M22": -1,
+ "M23": 0,
+ "M24": 0,
+ "M31": 0,
+ "M32": 0,
+ "M33": 1,
+ "M34": -0,
+ "M41": 161.929,
+ "M42": 7.5031643,
+ "M43": -94,
+ "M44": 1
+ },
+ "ResolvedPolygons": [
+ {
+ "Id": 0,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 1.15
+ },
+ "Vertices": [
+ {
+ "X": 5.6728,
+ "Y": 1.15,
+ "Z": 6
+ },
+ {
+ "X": 5.6728,
+ "Y": 1.15,
+ "Z": 7.3
+ },
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": 7.3
+ },
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 1,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 1.15
+ },
+ "Vertices": [
+ {
+ "X": 7.4113,
+ "Y": 1.15,
+ "Z": 7.3
+ },
+ {
+ "X": 5.6728,
+ "Y": 1.15,
+ "Z": 7.3
+ },
+ {
+ "X": 5.6728,
+ "Y": 1.15,
+ "Z": 6
+ },
+ {
+ "X": 7.4113,
+ "Y": 1.15,
+ "Z": 6
+ }
+ ]
+ },
+ {
+ "Id": 2,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 1.15
+ },
+ "Vertices": [
+ {
+ "X": 7.4113,
+ "Y": 1.15,
+ "Z": 8.52
+ },
+ {
+ "X": 5.6728,
+ "Y": 1.15,
+ "Z": 8.52
+ },
+ {
+ "X": 5.6728,
+ "Y": 1.15,
+ "Z": 7.3
+ },
+ {
+ "X": 7.4113,
+ "Y": 1.15,
+ "Z": 7.3
+ }
+ ]
+ },
+ {
+ "Id": 3,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 1.15
+ },
+ "Vertices": [
+ {
+ "X": 5.6728,
+ "Y": 1.15,
+ "Z": 8.52
+ },
+ {
+ "X": 7.4113,
+ "Y": 1.15,
+ "Z": 8.52
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 9.2
+ }
+ ]
+ },
+ {
+ "Id": 4,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 1.15
+ },
+ "Vertices": [
+ {
+ "X": 7.4113,
+ "Y": 1.15,
+ "Z": 8.52
+ },
+ {
+ "X": 7.4113,
+ "Y": 1.15,
+ "Z": 7.3
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 7.3
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 9.2
+ }
+ ]
+ },
+ {
+ "Id": 5,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 1.15
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 4.3
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 7.3
+ },
+ {
+ "X": 7.4113,
+ "Y": 1.15,
+ "Z": 7.3
+ },
+ {
+ "X": 7.4113,
+ "Y": 1.15,
+ "Z": 6
+ }
+ ]
+ },
+ {
+ "Id": 6,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 9
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": -1.336,
+ "Z": 6
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 7.3
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 0
+ }
+ ]
+ },
+ {
+ "Id": 7,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 9
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": -1.336,
+ "Z": 6
+ },
+ {
+ "X": 9,
+ "Y": -1.336,
+ "Z": 7.3
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 7.3
+ }
+ ]
+ },
+ {
+ "Id": 8,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 9
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": -1.336,
+ "Z": 6
+ },
+ {
+ "X": 9,
+ "Y": -4.57,
+ "Z": 6
+ },
+ {
+ "X": 9,
+ "Y": -4.57,
+ "Z": 9
+ },
+ {
+ "X": 9,
+ "Y": -1.336,
+ "Z": 9
+ }
+ ]
+ },
+ {
+ "Id": 9,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 9
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": -4.57,
+ "Z": 6
+ },
+ {
+ "X": 9,
+ "Y": -1.336,
+ "Z": 6
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 0
+ }
+ ]
+ },
+ {
+ "Id": 10,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 9
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": 7.3
+ },
+ {
+ "X": 9,
+ "Y": -4.57,
+ "Z": 6
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 0
+ },
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 11,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 9
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": 7.3
+ },
+ {
+ "X": 9,
+ "Y": -4.57,
+ "Z": 7.3
+ },
+ {
+ "X": 9,
+ "Y": -4.57,
+ "Z": 6
+ }
+ ]
+ },
+ {
+ "Id": 12,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 9
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": -4.57,
+ "Z": 7.3
+ },
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": 7.3
+ },
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": 9.2
+ }
+ ]
+ },
+ {
+ "Id": 13,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 7.65
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": 7.3
+ },
+ {
+ "X": 7.4113,
+ "Y": -7.65,
+ "Z": 7.3
+ },
+ {
+ "X": 7.4113,
+ "Y": -7.65,
+ "Z": 8.52
+ },
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": 9.2
+ }
+ ]
+ },
+ {
+ "Id": 14,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 7.65
+ },
+ "Vertices": [
+ {
+ "X": 7.4113,
+ "Y": -7.65,
+ "Z": 6
+ },
+ {
+ "X": 7.4113,
+ "Y": -7.65,
+ "Z": 7.3
+ },
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": 7.3
+ },
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 15,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 7.65
+ },
+ "Vertices": [
+ {
+ "X": 5.6728,
+ "Y": -7.65,
+ "Z": 7.3
+ },
+ {
+ "X": 7.4113,
+ "Y": -7.65,
+ "Z": 7.3
+ },
+ {
+ "X": 7.4113,
+ "Y": -7.65,
+ "Z": 6
+ },
+ {
+ "X": 5.6728,
+ "Y": -7.65,
+ "Z": 6
+ }
+ ]
+ },
+ {
+ "Id": 16,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 7.65
+ },
+ "Vertices": [
+ {
+ "X": 5.6728,
+ "Y": -7.65,
+ "Z": 7.3
+ },
+ {
+ "X": 5.6728,
+ "Y": -7.65,
+ "Z": 8.52
+ },
+ {
+ "X": 7.4113,
+ "Y": -7.65,
+ "Z": 8.52
+ },
+ {
+ "X": 7.4113,
+ "Y": -7.65,
+ "Z": 7.3
+ }
+ ]
+ },
+ {
+ "Id": 17,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 7.65
+ },
+ "Vertices": [
+ {
+ "X": 5.6728,
+ "Y": -7.65,
+ "Z": 8.52
+ },
+ {
+ "X": 5.6728,
+ "Y": -7.65,
+ "Z": 7.3
+ },
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 7.3
+ },
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 9.2
+ }
+ ]
+ },
+ {
+ "Id": 18,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 7.65
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 4.3
+ },
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 7.3
+ },
+ {
+ "X": 5.6728,
+ "Y": -7.65,
+ "Z": 7.3
+ },
+ {
+ "X": 5.6728,
+ "Y": -7.65,
+ "Z": 6
+ }
+ ]
+ },
+ {
+ "Id": 19,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": -4.1
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": 4.3
+ },
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": 7.3
+ },
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 7.3
+ },
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 20,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": -4.1
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 9.2
+ },
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 7.3
+ },
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": 7.3
+ },
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": 9.2
+ }
+ ]
+ },
+ {
+ "Id": 21,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 1.15
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": 7.3
+ },
+ {
+ "X": 5.6728,
+ "Y": 1.15,
+ "Z": 7.3
+ },
+ {
+ "X": 5.6728,
+ "Y": 1.15,
+ "Z": 8.52
+ },
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": 9.2
+ }
+ ]
+ },
+ {
+ "Id": 22,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 1.15
+ },
+ "Vertices": [
+ {
+ "X": 5.6728,
+ "Y": 1.15,
+ "Z": 8.52
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 9.2
+ },
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": 9.2
+ }
+ ]
+ },
+ {
+ "Id": 23,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 0,
+ "Z": -1
+ },
+ "D": 9.2
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": 9.2
+ },
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 9.2
+ },
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": 9.2
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 9.2
+ }
+ ]
+ },
+ {
+ "Id": 24,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 7.65
+ },
+ "Vertices": [
+ {
+ "X": 7.4113,
+ "Y": -7.65,
+ "Z": 8.52
+ },
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 9.2
+ },
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": 9.2
+ }
+ ]
+ },
+ {
+ "Id": 25,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 7.65
+ },
+ "Vertices": [
+ {
+ "X": 7.4113,
+ "Y": -7.65,
+ "Z": 8.52
+ },
+ {
+ "X": 5.6728,
+ "Y": -7.65,
+ "Z": 8.52
+ },
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 9.2
+ }
+ ]
+ },
+ {
+ "Id": 26,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 9
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 9.2
+ },
+ {
+ "X": 9,
+ "Y": -1.336,
+ "Z": 9
+ },
+ {
+ "X": 9,
+ "Y": -4.57,
+ "Z": 9
+ },
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": 9.2
+ }
+ ]
+ },
+ {
+ "Id": 27,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 9
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 9.2
+ },
+ {
+ "X": 9,
+ "Y": -1.336,
+ "Z": 7.3
+ },
+ {
+ "X": 9,
+ "Y": -1.336,
+ "Z": 9
+ }
+ ]
+ },
+ {
+ "Id": 28,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 9
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 9.2
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 7.3
+ },
+ {
+ "X": 9,
+ "Y": -1.336,
+ "Z": 7.3
+ }
+ ]
+ },
+ {
+ "Id": 29,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 9
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": -4.57,
+ "Z": 9
+ },
+ {
+ "X": 9,
+ "Y": -4.57,
+ "Z": 7.3
+ },
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": 9.2
+ }
+ ]
+ },
+ {
+ "Id": 30,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": -4.1
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": 4.3
+ },
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 4.3
+ },
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 2.85
+ },
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": 2.85
+ }
+ ]
+ },
+ {
+ "Id": 31,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 7.65
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 4.3
+ },
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": 4.3
+ },
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": 2.85
+ },
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 2.85
+ }
+ ]
+ },
+ {
+ "Id": 32,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 7.65
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 4.3
+ },
+ {
+ "X": 5.6728,
+ "Y": -7.65,
+ "Z": 6
+ },
+ {
+ "X": 7.4113,
+ "Y": -7.65,
+ "Z": 6
+ },
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 33,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 7.65
+ },
+ "Vertices": [
+ {
+ "X": 7.8,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 7.8,
+ "Y": -7.65,
+ "Z": 2.85
+ },
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": 2.85
+ },
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 34,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 7.65
+ },
+ "Vertices": [
+ {
+ "X": 7.8,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 7.45189,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 7.45189,
+ "Y": -7.65,
+ "Z": 2.5
+ },
+ {
+ "X": 7.8,
+ "Y": -7.65,
+ "Z": 2.85
+ }
+ ]
+ },
+ {
+ "Id": 35,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 0,
+ "Z": 1
+ },
+ "D": 1.19209E-08
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 7,
+ "Y": -2.85,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 36,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 7.65
+ },
+ "Vertices": [
+ {
+ "X": 7.45189,
+ "Y": -7.65,
+ "Z": 2.5
+ },
+ {
+ "X": 5.2,
+ "Y": -7.65,
+ "Z": 2.85
+ },
+ {
+ "X": 7.8,
+ "Y": -7.65,
+ "Z": 2.85
+ }
+ ]
+ },
+ {
+ "Id": 37,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 7.65
+ },
+ "Vertices": [
+ {
+ "X": 7.45189,
+ "Y": -7.65,
+ "Z": 2.5
+ },
+ {
+ "X": 5.54731,
+ "Y": -7.65,
+ "Z": 2.5
+ },
+ {
+ "X": 5.2,
+ "Y": -7.65,
+ "Z": 2.85
+ }
+ ]
+ },
+ {
+ "Id": 38,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 7.65
+ },
+ "Vertices": [
+ {
+ "X": 5.54731,
+ "Y": -7.65,
+ "Z": 2.5
+ },
+ {
+ "X": 5.54731,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 5.2,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 5.2,
+ "Y": -7.65,
+ "Z": 2.85
+ }
+ ]
+ },
+ {
+ "Id": 39,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 7.65
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 2.85
+ },
+ {
+ "X": 5.2,
+ "Y": -7.65,
+ "Z": 2.85
+ },
+ {
+ "X": 5.2,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 40,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": -4.1
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": -2.2,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 4.1,
+ "Y": -2.2,
+ "Z": 2.85
+ },
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 2.85
+ },
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 41,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": -4.1
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": -2.2,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 4.1,
+ "Y": -1.85189,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 4.1,
+ "Y": -1.85189,
+ "Z": 2.5
+ },
+ {
+ "X": 4.1,
+ "Y": -2.2,
+ "Z": 2.85
+ }
+ ]
+ },
+ {
+ "Id": 42,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": -4.1
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": -1.85189,
+ "Z": 2.5
+ },
+ {
+ "X": 4.1,
+ "Y": 0.4,
+ "Z": 2.85
+ },
+ {
+ "X": 4.1,
+ "Y": -2.2,
+ "Z": 2.85
+ }
+ ]
+ },
+ {
+ "Id": 43,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": -4.1
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": 0.052686,
+ "Z": 2.5
+ },
+ {
+ "X": 4.1,
+ "Y": 0.0526863,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 4.1,
+ "Y": 0.4,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 4.1,
+ "Y": 0.4,
+ "Z": 2.85
+ }
+ ]
+ },
+ {
+ "Id": 44,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": -4.1
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": 0.4,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": 2.85
+ },
+ {
+ "X": 4.1,
+ "Y": 0.4,
+ "Z": 2.85
+ }
+ ]
+ },
+ {
+ "Id": 45,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 1.15
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 5.35,
+ "Y": 1.15,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 5.35,
+ "Y": 1.15,
+ "Z": 4.3
+ },
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 46,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 0,
+ "Z": 1
+ },
+ "D": 1.19209E-08
+ },
+ "Vertices": [
+ {
+ "X": 7,
+ "Y": -2.85,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 7,
+ "Y": 1.15,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 47,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": -4.1
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": -1.85189,
+ "Z": 2.5
+ },
+ {
+ "X": 4.1,
+ "Y": 0.052686,
+ "Z": 2.5
+ },
+ {
+ "X": 4.1,
+ "Y": 0.4,
+ "Z": 2.85
+ }
+ ]
+ },
+ {
+ "Id": 48,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -5.96045E-09,
+ "Y": -2.4835207E-09,
+ "Z": 1
+ },
+ "D": 4.6566015E-08
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 9,
+ "Y": -2.85,
+ "Z": 1.11022E-16
+ },
+ {
+ "X": 7,
+ "Y": -2.85,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 49,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 1.15
+ },
+ "Vertices": [
+ {
+ "X": 7.7,
+ "Y": 1.15,
+ "Z": 4.3
+ },
+ {
+ "X": 7.7,
+ "Y": 1.15,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 0
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 50,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 1.15
+ },
+ "Vertices": [
+ {
+ "X": 7.7,
+ "Y": 1.15,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 7.7,
+ "Y": 1.15,
+ "Z": 1.35
+ },
+ {
+ "X": 5.35,
+ "Y": 1.15,
+ "Z": 1.35
+ },
+ {
+ "X": 5.35,
+ "Y": 1.15,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 51,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 1.15
+ },
+ "Vertices": [
+ {
+ "X": 7.7,
+ "Y": 1.15,
+ "Z": 3.9
+ },
+ {
+ "X": 5.35,
+ "Y": 1.15,
+ "Z": 3.9
+ },
+ {
+ "X": 5.35,
+ "Y": 1.15,
+ "Z": 1.35
+ },
+ {
+ "X": 7.7,
+ "Y": 1.15,
+ "Z": 1.35
+ }
+ ]
+ },
+ {
+ "Id": 52,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 1.15
+ },
+ "Vertices": [
+ {
+ "X": 5.35,
+ "Y": 1.15,
+ "Z": 4.3
+ },
+ {
+ "X": 5.35,
+ "Y": 1.15,
+ "Z": 3.9
+ },
+ {
+ "X": 7.7,
+ "Y": 1.15,
+ "Z": 3.9
+ },
+ {
+ "X": 7.7,
+ "Y": 1.15,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 53,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 1.15
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 4.3
+ },
+ {
+ "X": 7.4113,
+ "Y": 1.15,
+ "Z": 6
+ },
+ {
+ "X": 5.6728,
+ "Y": 1.15,
+ "Z": 6
+ },
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": 4.3
+ }
+ ]
+ }
+ ],
+ "PortalPolygons": [
+ {
+ "Id": 0,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 1.15
+ },
+ "Vertices": [
+ {
+ "X": 5.6728,
+ "Y": 1.15,
+ "Z": 6
+ },
+ {
+ "X": 5.6728,
+ "Y": 1.15,
+ "Z": 7.3
+ },
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": 7.3
+ },
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 1,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 7.65
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 4.3
+ },
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 7.3
+ },
+ {
+ "X": 5.6728,
+ "Y": -7.65,
+ "Z": 7.3
+ },
+ {
+ "X": 5.6728,
+ "Y": -7.65,
+ "Z": 6
+ }
+ ]
+ },
+ {
+ "Id": 2,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 7.65
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 4.3
+ },
+ {
+ "X": 5.6728,
+ "Y": -7.65,
+ "Z": 6
+ },
+ {
+ "X": 7.4113,
+ "Y": -7.65,
+ "Z": 6
+ },
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 3,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 0,
+ "Z": -1
+ },
+ "D": 9.2
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": 9.2
+ },
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 9.2
+ },
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": 9.2
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 9.2
+ }
+ ]
+ },
+ {
+ "Id": 4,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 7.65
+ },
+ "Vertices": [
+ {
+ "X": 7.4113,
+ "Y": -7.65,
+ "Z": 6
+ },
+ {
+ "X": 7.4113,
+ "Y": -7.65,
+ "Z": 7.3
+ },
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": 7.3
+ },
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 5,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 7.65
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 2.85
+ },
+ {
+ "X": 5.2,
+ "Y": -7.65,
+ "Z": 2.85
+ },
+ {
+ "X": 5.2,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 6,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 1.15
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 5.35,
+ "Y": 1.15,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 5.35,
+ "Y": 1.15,
+ "Z": 4.3
+ },
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 7,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 1.15
+ },
+ "Vertices": [
+ {
+ "X": 7.7,
+ "Y": 1.15,
+ "Z": 4.3
+ },
+ {
+ "X": 7.7,
+ "Y": 1.15,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 0
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 8,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 1.15
+ },
+ "Vertices": [
+ {
+ "X": 7.7,
+ "Y": 1.15,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 7.7,
+ "Y": 1.15,
+ "Z": 1.35
+ },
+ {
+ "X": 5.35,
+ "Y": 1.15,
+ "Z": 1.35
+ },
+ {
+ "X": 5.35,
+ "Y": 1.15,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 9,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 1.15
+ },
+ "Vertices": [
+ {
+ "X": 7.7,
+ "Y": 1.15,
+ "Z": 3.9
+ },
+ {
+ "X": 5.35,
+ "Y": 1.15,
+ "Z": 3.9
+ },
+ {
+ "X": 5.35,
+ "Y": 1.15,
+ "Z": 1.35
+ },
+ {
+ "X": 7.7,
+ "Y": 1.15,
+ "Z": 1.35
+ }
+ ]
+ },
+ {
+ "Id": 10,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 1.15
+ },
+ "Vertices": [
+ {
+ "X": 5.35,
+ "Y": 1.15,
+ "Z": 4.3
+ },
+ {
+ "X": 5.35,
+ "Y": 1.15,
+ "Z": 3.9
+ },
+ {
+ "X": 7.7,
+ "Y": 1.15,
+ "Z": 3.9
+ },
+ {
+ "X": 7.7,
+ "Y": 1.15,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 11,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": -4.1
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": 4.3
+ },
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": 7.3
+ },
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 7.3
+ },
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 12,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": -4.1
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 9.2
+ },
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 7.3
+ },
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": 7.3
+ },
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": 9.2
+ }
+ ]
+ },
+ {
+ "Id": 13,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 1.15
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 4.3
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 7.3
+ },
+ {
+ "X": 7.4113,
+ "Y": 1.15,
+ "Z": 7.3
+ },
+ {
+ "X": 7.4113,
+ "Y": 1.15,
+ "Z": 6
+ }
+ ]
+ },
+ {
+ "Id": 14,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 1.15
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 4.3
+ },
+ {
+ "X": 7.4113,
+ "Y": 1.15,
+ "Z": 6
+ },
+ {
+ "X": 5.6728,
+ "Y": 1.15,
+ "Z": 6
+ },
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 15,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 9
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": -1.336,
+ "Z": 6
+ },
+ {
+ "X": 9,
+ "Y": -4.57,
+ "Z": 6
+ },
+ {
+ "X": 9,
+ "Y": -4.57,
+ "Z": 9
+ },
+ {
+ "X": 9,
+ "Y": -1.336,
+ "Z": 9
+ }
+ ]
+ },
+ {
+ "Id": 16,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 1.15
+ },
+ "Vertices": [
+ {
+ "X": 7.4113,
+ "Y": 1.15,
+ "Z": 7.3
+ },
+ {
+ "X": 5.6728,
+ "Y": 1.15,
+ "Z": 7.3
+ },
+ {
+ "X": 5.6728,
+ "Y": 1.15,
+ "Z": 6
+ },
+ {
+ "X": 7.4113,
+ "Y": 1.15,
+ "Z": 6
+ }
+ ]
+ },
+ {
+ "Id": 17,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 9
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": -4.57,
+ "Z": 9
+ },
+ {
+ "X": 9,
+ "Y": -4.57,
+ "Z": 7.3
+ },
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": 9.2
+ }
+ ]
+ },
+ {
+ "Id": 18,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 1.15
+ },
+ "Vertices": [
+ {
+ "X": 7.4113,
+ "Y": 1.15,
+ "Z": 8.52
+ },
+ {
+ "X": 5.6728,
+ "Y": 1.15,
+ "Z": 8.52
+ },
+ {
+ "X": 5.6728,
+ "Y": 1.15,
+ "Z": 7.3
+ },
+ {
+ "X": 7.4113,
+ "Y": 1.15,
+ "Z": 7.3
+ }
+ ]
+ },
+ {
+ "Id": 19,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 7.65
+ },
+ "Vertices": [
+ {
+ "X": 5.6728,
+ "Y": -7.65,
+ "Z": 7.3
+ },
+ {
+ "X": 7.4113,
+ "Y": -7.65,
+ "Z": 7.3
+ },
+ {
+ "X": 7.4113,
+ "Y": -7.65,
+ "Z": 6
+ },
+ {
+ "X": 5.6728,
+ "Y": -7.65,
+ "Z": 6
+ }
+ ]
+ },
+ {
+ "Id": 20,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 9
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": -4.57,
+ "Z": 7.3
+ },
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": 7.3
+ },
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": 9.2
+ }
+ ]
+ },
+ {
+ "Id": 21,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 7.65
+ },
+ "Vertices": [
+ {
+ "X": 5.6728,
+ "Y": -7.65,
+ "Z": 7.3
+ },
+ {
+ "X": 5.6728,
+ "Y": -7.65,
+ "Z": 8.52
+ },
+ {
+ "X": 7.4113,
+ "Y": -7.65,
+ "Z": 8.52
+ },
+ {
+ "X": 7.4113,
+ "Y": -7.65,
+ "Z": 7.3
+ }
+ ]
+ },
+ {
+ "Id": 22,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 7.65
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 4.3
+ },
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": 4.3
+ },
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": 2.85
+ },
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 2.85
+ }
+ ]
+ },
+ {
+ "Id": 23,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 7.65
+ },
+ "Vertices": [
+ {
+ "X": 7.8,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 7.8,
+ "Y": -7.65,
+ "Z": 2.85
+ },
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": 2.85
+ },
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 24,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 9
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 9.2
+ },
+ {
+ "X": 9,
+ "Y": -1.336,
+ "Z": 7.3
+ },
+ {
+ "X": 9,
+ "Y": -1.336,
+ "Z": 9
+ }
+ ]
+ },
+ {
+ "Id": 25,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 9
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 9.2
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 7.3
+ },
+ {
+ "X": 9,
+ "Y": -1.336,
+ "Z": 7.3
+ }
+ ]
+ },
+ {
+ "Id": 26,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": -4.1
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": 4.3
+ },
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 4.3
+ },
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 2.85
+ },
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": 2.85
+ }
+ ]
+ },
+ {
+ "Id": 27,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": -4.1
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": -2.2,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 4.1,
+ "Y": -2.2,
+ "Z": 2.85
+ },
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 2.85
+ },
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 28,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": -4.1
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": 0.4,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": 2.85
+ },
+ {
+ "X": 4.1,
+ "Y": 0.4,
+ "Z": 2.85
+ }
+ ]
+ },
+ {
+ "Id": 29,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 9
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 9.2
+ },
+ {
+ "X": 9,
+ "Y": -1.336,
+ "Z": 9
+ },
+ {
+ "X": 9,
+ "Y": -4.57,
+ "Z": 9
+ },
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": 9.2
+ }
+ ]
+ },
+ {
+ "Id": 30,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 0,
+ "Z": 1
+ },
+ "D": 1.19209E-08
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 7,
+ "Y": -2.85,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 31,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 0,
+ "Z": 1
+ },
+ "D": 1.19209E-08
+ },
+ "Vertices": [
+ {
+ "X": 7,
+ "Y": -2.85,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 7,
+ "Y": 1.15,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 32,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -5.96045E-09,
+ "Y": -2.4835207E-09,
+ "Z": 1
+ },
+ "D": 4.6566015E-08
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 9,
+ "Y": -2.85,
+ "Z": 1.11022E-16
+ },
+ {
+ "X": 7,
+ "Y": -2.85,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 33,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 9
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": 7.3
+ },
+ {
+ "X": 9,
+ "Y": -4.57,
+ "Z": 7.3
+ },
+ {
+ "X": 9,
+ "Y": -4.57,
+ "Z": 6
+ }
+ ]
+ },
+ {
+ "Id": 34,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 9
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": 7.3
+ },
+ {
+ "X": 9,
+ "Y": -4.57,
+ "Z": 6
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 0
+ },
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 35,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 9
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": -4.57,
+ "Z": 6
+ },
+ {
+ "X": 9,
+ "Y": -1.336,
+ "Z": 6
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 0
+ }
+ ]
+ },
+ {
+ "Id": 36,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 9
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": -1.336,
+ "Z": 6
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 7.3
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 0
+ }
+ ]
+ },
+ {
+ "Id": 37,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 9
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": -1.336,
+ "Z": 6
+ },
+ {
+ "X": 9,
+ "Y": -1.336,
+ "Z": 7.3
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 7.3
+ }
+ ]
+ },
+ {
+ "Id": 38,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 1.15
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": 7.3
+ },
+ {
+ "X": 5.6728,
+ "Y": 1.15,
+ "Z": 7.3
+ },
+ {
+ "X": 5.6728,
+ "Y": 1.15,
+ "Z": 8.52
+ },
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": 9.2
+ }
+ ]
+ },
+ {
+ "Id": 39,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 1.15
+ },
+ "Vertices": [
+ {
+ "X": 5.6728,
+ "Y": 1.15,
+ "Z": 8.52
+ },
+ {
+ "X": 7.4113,
+ "Y": 1.15,
+ "Z": 8.52
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 9.2
+ }
+ ]
+ },
+ {
+ "Id": 40,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 1.15
+ },
+ "Vertices": [
+ {
+ "X": 5.6728,
+ "Y": 1.15,
+ "Z": 8.52
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 9.2
+ },
+ {
+ "X": 4.1,
+ "Y": 1.15,
+ "Z": 9.2
+ }
+ ]
+ },
+ {
+ "Id": 41,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 1.15
+ },
+ "Vertices": [
+ {
+ "X": 7.4113,
+ "Y": 1.15,
+ "Z": 8.52
+ },
+ {
+ "X": 7.4113,
+ "Y": 1.15,
+ "Z": 7.3
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 7.3
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 9.2
+ }
+ ]
+ },
+ {
+ "Id": 42,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 7.65
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": 7.3
+ },
+ {
+ "X": 7.4113,
+ "Y": -7.65,
+ "Z": 7.3
+ },
+ {
+ "X": 7.4113,
+ "Y": -7.65,
+ "Z": 8.52
+ },
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": 9.2
+ }
+ ]
+ },
+ {
+ "Id": 43,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 7.65
+ },
+ "Vertices": [
+ {
+ "X": 7.4113,
+ "Y": -7.65,
+ "Z": 8.52
+ },
+ {
+ "X": 5.6728,
+ "Y": -7.65,
+ "Z": 8.52
+ },
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 9.2
+ }
+ ]
+ },
+ {
+ "Id": 44,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 7.65
+ },
+ "Vertices": [
+ {
+ "X": 7.4113,
+ "Y": -7.65,
+ "Z": 8.52
+ },
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 9.2
+ },
+ {
+ "X": 9,
+ "Y": -7.65,
+ "Z": 9.2
+ }
+ ]
+ },
+ {
+ "Id": 45,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 7.65
+ },
+ "Vertices": [
+ {
+ "X": 5.6728,
+ "Y": -7.65,
+ "Z": 8.52
+ },
+ {
+ "X": 5.6728,
+ "Y": -7.65,
+ "Z": 7.3
+ },
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 7.3
+ },
+ {
+ "X": 4.1,
+ "Y": -7.65,
+ "Z": 9.2
+ }
+ ]
+ },
+ {
+ "Id": 46,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 7.65
+ },
+ "Vertices": [
+ {
+ "X": 7.8,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 7.45189,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 7.45189,
+ "Y": -7.65,
+ "Z": 2.5
+ },
+ {
+ "X": 7.8,
+ "Y": -7.65,
+ "Z": 2.85
+ }
+ ]
+ },
+ {
+ "Id": 47,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 7.65
+ },
+ "Vertices": [
+ {
+ "X": 7.45189,
+ "Y": -7.65,
+ "Z": 2.5
+ },
+ {
+ "X": 5.54731,
+ "Y": -7.65,
+ "Z": 2.5
+ },
+ {
+ "X": 5.2,
+ "Y": -7.65,
+ "Z": 2.85
+ }
+ ]
+ },
+ {
+ "Id": 48,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 7.65
+ },
+ "Vertices": [
+ {
+ "X": 7.45189,
+ "Y": -7.65,
+ "Z": 2.5
+ },
+ {
+ "X": 5.2,
+ "Y": -7.65,
+ "Z": 2.85
+ },
+ {
+ "X": 7.8,
+ "Y": -7.65,
+ "Z": 2.85
+ }
+ ]
+ },
+ {
+ "Id": 49,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 7.65
+ },
+ "Vertices": [
+ {
+ "X": 5.54731,
+ "Y": -7.65,
+ "Z": 2.5
+ },
+ {
+ "X": 5.54731,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 5.2,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 5.2,
+ "Y": -7.65,
+ "Z": 2.85
+ }
+ ]
+ },
+ {
+ "Id": 50,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": -4.1
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": -2.2,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 4.1,
+ "Y": -1.85189,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 4.1,
+ "Y": -1.85189,
+ "Z": 2.5
+ },
+ {
+ "X": 4.1,
+ "Y": -2.2,
+ "Z": 2.85
+ }
+ ]
+ },
+ {
+ "Id": 51,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": -4.1
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": -1.85189,
+ "Z": 2.5
+ },
+ {
+ "X": 4.1,
+ "Y": 0.052686,
+ "Z": 2.5
+ },
+ {
+ "X": 4.1,
+ "Y": 0.4,
+ "Z": 2.85
+ }
+ ]
+ },
+ {
+ "Id": 52,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": -4.1
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": -1.85189,
+ "Z": 2.5
+ },
+ {
+ "X": 4.1,
+ "Y": 0.4,
+ "Z": 2.85
+ },
+ {
+ "X": 4.1,
+ "Y": -2.2,
+ "Z": 2.85
+ }
+ ]
+ },
+ {
+ "Id": 53,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": -4.1
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": 0.052686,
+ "Z": 2.5
+ },
+ {
+ "X": 4.1,
+ "Y": 0.0526863,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 4.1,
+ "Y": 0.4,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 4.1,
+ "Y": 0.4,
+ "Z": 2.85
+ }
+ ]
+ },
+ {
+ "Id": 54,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": -7.65
+ },
+ "Vertices": [
+ {
+ "X": 7.45189,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 7.45189,
+ "Y": -7.65,
+ "Z": 2.5
+ },
+ {
+ "X": 5.54731,
+ "Y": -7.65,
+ "Z": 2.5
+ },
+ {
+ "X": 5.54731,
+ "Y": -7.65,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 55,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 4.1
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": 0.052686,
+ "Z": 2.5
+ },
+ {
+ "X": 4.1,
+ "Y": 0.0526863,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 4.1,
+ "Y": -1.85189,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 4.1,
+ "Y": -1.85189,
+ "Z": 2.5
+ }
+ ]
+ },
+ {
+ "Id": 56,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 5.96045E-09,
+ "Y": -1.387775E-17,
+ "Z": -1
+ },
+ "D": -5.364405E-08
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": -2.85,
+ "Z": 1.11022E-16
+ },
+ {
+ "X": 7,
+ "Y": -2.85,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 7,
+ "Y": 1.15,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 0
+ }
+ ]
+ }
+ ],
+ "Portals": [
+ {
+ "OtherCellId": 368,
+ "PolygonId": 54,
+ "Flags": 1
+ },
+ {
+ "OtherCellId": 371,
+ "PolygonId": 55,
+ "Flags": 1
+ },
+ {
+ "OtherCellId": 373,
+ "PolygonId": 56,
+ "Flags": 1
+ }
+ ],
+ "VisibleCellIds": [
+ 2847146351,
+ 2847146352,
+ 2847146354,
+ 2847146355,
+ 2847146356,
+ 2847146357
+ ]
+}
\ No newline at end of file
diff --git a/tests/AcDream.Core.Tests/Fixtures/flap-doorway/0xA9B40172.json b/tests/AcDream.Core.Tests/Fixtures/flap-doorway/0xA9B40172.json
new file mode 100644
index 00000000..1be3dfce
--- /dev/null
+++ b/tests/AcDream.Core.Tests/Fixtures/flap-doorway/0xA9B40172.json
@@ -0,0 +1,1963 @@
+{
+ "CellId": 2847146354,
+ "WorldTransform": {
+ "M11": -1,
+ "M12": 8.74228E-08,
+ "M13": 0,
+ "M14": 0,
+ "M21": -8.74228E-08,
+ "M22": -1,
+ "M23": 0,
+ "M24": 0,
+ "M31": 0,
+ "M32": 0,
+ "M33": 1,
+ "M34": 0,
+ "M41": 161.929,
+ "M42": 7.50315,
+ "M43": 94,
+ "M44": 1
+ },
+ "InverseWorldTransform": {
+ "M11": -1,
+ "M12": -8.74228E-08,
+ "M13": 0,
+ "M14": -0,
+ "M21": 8.74228E-08,
+ "M22": -1,
+ "M23": 0,
+ "M24": 0,
+ "M31": 0,
+ "M32": 0,
+ "M33": 1,
+ "M34": -0,
+ "M41": 161.929,
+ "M42": 7.5031643,
+ "M43": -94,
+ "M44": 1
+ },
+ "ResolvedPolygons": [
+ {
+ "Id": 0,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0.8289255,
+ "Y": 0,
+ "Z": -0.55935895
+ },
+ "D": 4.809128
+ },
+ "Vertices": [
+ {
+ "X": -2.9,
+ "Y": 3,
+ "Z": 4.3
+ },
+ {
+ "X": -1.14552,
+ "Y": 2.38419E-08,
+ "Z": 6.9
+ },
+ {
+ "X": -2.9,
+ "Y": -3.2,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 1,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -0.65493053,
+ "Z": -0.7556891
+ },
+ "D": 5.214255
+ },
+ "Vertices": [
+ {
+ "X": 1.94952,
+ "Y": 2.38419E-08,
+ "Z": 6.9
+ },
+ {
+ "X": -1.14552,
+ "Y": 2.38419E-08,
+ "Z": 6.9
+ },
+ {
+ "X": -2.9,
+ "Y": 3,
+ "Z": 4.3
+ },
+ {
+ "X": 3.9,
+ "Y": 3,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 2,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 0.63059264,
+ "Z": -0.776114
+ },
+ "D": 5.3551865
+ },
+ "Vertices": [
+ {
+ "X": -1.14552,
+ "Y": 2.38419E-08,
+ "Z": 6.9
+ },
+ {
+ "X": 1.94952,
+ "Y": 2.38419E-08,
+ "Z": 6.9
+ },
+ {
+ "X": 3.9,
+ "Y": -3.2,
+ "Z": 4.3
+ },
+ {
+ "X": -2.9,
+ "Y": -3.2,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 3,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -0.7999291,
+ "Y": 0,
+ "Z": -0.60009456
+ },
+ "D": 5.7001305
+ },
+ "Vertices": [
+ {
+ "X": 3.9,
+ "Y": -3.2,
+ "Z": 4.3
+ },
+ {
+ "X": 1.94952,
+ "Y": 2.38419E-08,
+ "Z": 6.9
+ },
+ {
+ "X": 3.9,
+ "Y": 3,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 4,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 3.9
+ },
+ "Vertices": [
+ {
+ "X": 3.9,
+ "Y": 3,
+ "Z": 4.3
+ },
+ {
+ "X": 3.9,
+ "Y": 3,
+ "Z": 2.9
+ },
+ {
+ "X": 3.9,
+ "Y": -3.2,
+ "Z": 2.9
+ },
+ {
+ "X": 3.9,
+ "Y": -3.2,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 5,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 3
+ },
+ "Vertices": [
+ {
+ "X": -2.9,
+ "Y": 3,
+ "Z": 2.9
+ },
+ {
+ "X": 3.9,
+ "Y": 3,
+ "Z": 2.9
+ },
+ {
+ "X": 3.9,
+ "Y": 3,
+ "Z": 4.3
+ },
+ {
+ "X": -2.9,
+ "Y": 3,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 6,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 3
+ },
+ "Vertices": [
+ {
+ "X": -1,
+ "Y": 3,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": -1,
+ "Y": 3,
+ "Z": 2.9
+ },
+ {
+ "X": -2.9,
+ "Y": 3,
+ "Z": 2.9
+ },
+ {
+ "X": -2.9,
+ "Y": 3,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 7,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 3
+ },
+ "Vertices": [
+ {
+ "X": -1,
+ "Y": 3,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 2,
+ "Y": 3,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 2,
+ "Y": 3,
+ "Z": 1
+ },
+ {
+ "X": -1,
+ "Y": 3,
+ "Z": 1
+ }
+ ]
+ },
+ {
+ "Id": 8,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 0,
+ "Z": 1
+ },
+ "D": 1.19209E-08
+ },
+ "Vertices": [
+ {
+ "X": 3.9,
+ "Y": 3,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": -2.9,
+ "Y": 3,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": -2.9,
+ "Y": -3.2,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 3.9,
+ "Y": -3.2,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 9,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 3
+ },
+ "Vertices": [
+ {
+ "X": 2,
+ "Y": 3,
+ "Z": 2.9
+ },
+ {
+ "X": 2,
+ "Y": 3,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 3.9,
+ "Y": 3,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 3.9,
+ "Y": 3,
+ "Z": 2.9
+ }
+ ]
+ },
+ {
+ "Id": 10,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 3
+ },
+ "Vertices": [
+ {
+ "X": 2,
+ "Y": 3,
+ "Z": 2.9
+ },
+ {
+ "X": -1,
+ "Y": 3,
+ "Z": 2.9
+ },
+ {
+ "X": -1,
+ "Y": 3,
+ "Z": 1
+ },
+ {
+ "X": 2,
+ "Y": 3,
+ "Z": 1
+ }
+ ]
+ },
+ {
+ "Id": 11,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 3.9
+ },
+ "Vertices": [
+ {
+ "X": 3.9,
+ "Y": 0.0526863,
+ "Z": 0
+ },
+ {
+ "X": 3.9,
+ "Y": 0.052686,
+ "Z": 2.9
+ },
+ {
+ "X": 3.9,
+ "Y": 3,
+ "Z": 2.9
+ },
+ {
+ "X": 3.9,
+ "Y": 3,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 12,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 3.9
+ },
+ "Vertices": [
+ {
+ "X": 3.9,
+ "Y": 0.0526863,
+ "Z": 2.5
+ },
+ {
+ "X": 3.9,
+ "Y": -1.8519,
+ "Z": 2.5
+ },
+ {
+ "X": 3.9,
+ "Y": -1.8519,
+ "Z": 2.9
+ },
+ {
+ "X": 3.9,
+ "Y": 0.052686,
+ "Z": 2.9
+ }
+ ]
+ },
+ {
+ "Id": 13,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 3.2
+ },
+ "Vertices": [
+ {
+ "X": 1.68,
+ "Y": -3.2,
+ "Z": 1
+ },
+ {
+ "X": 1.68,
+ "Y": -3.2,
+ "Z": 2.9
+ },
+ {
+ "X": 3.9,
+ "Y": -3.2,
+ "Z": 2.9
+ },
+ {
+ "X": 3.9,
+ "Y": -3.2,
+ "Z": 1
+ }
+ ]
+ },
+ {
+ "Id": 14,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 3.9
+ },
+ "Vertices": [
+ {
+ "X": 3.9,
+ "Y": -1.8519,
+ "Z": 2.9
+ },
+ {
+ "X": 3.9,
+ "Y": -1.85189,
+ "Z": 0
+ },
+ {
+ "X": 3.9,
+ "Y": -3.2,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 3.9,
+ "Y": -3.2,
+ "Z": 2.9
+ }
+ ]
+ },
+ {
+ "Id": 15,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 3.2
+ },
+ "Vertices": [
+ {
+ "X": -2.9,
+ "Y": -3.2,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": -2.9,
+ "Y": -3.2,
+ "Z": 1
+ },
+ {
+ "X": 3.9,
+ "Y": -3.2,
+ "Z": 1
+ },
+ {
+ "X": 3.9,
+ "Y": -3.2,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 16,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 2.9
+ },
+ "Vertices": [
+ {
+ "X": -2.9,
+ "Y": -1.05,
+ "Z": 1
+ },
+ {
+ "X": -2.9,
+ "Y": -1.05,
+ "Z": 2.9
+ },
+ {
+ "X": -2.9,
+ "Y": -3.2,
+ "Z": 2.9
+ },
+ {
+ "X": -2.9,
+ "Y": -3.2,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 17,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 3.2
+ },
+ "Vertices": [
+ {
+ "X": 1.68,
+ "Y": -3.2,
+ "Z": 1
+ },
+ {
+ "X": -1,
+ "Y": -3.2,
+ "Z": 1
+ },
+ {
+ "X": -1,
+ "Y": -3.2,
+ "Z": 2.9
+ },
+ {
+ "X": 1.68,
+ "Y": -3.2,
+ "Z": 2.9
+ }
+ ]
+ },
+ {
+ "Id": 18,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 2.9000003
+ },
+ "Vertices": [
+ {
+ "X": -2.9,
+ "Y": -1.05,
+ "Z": 3.55
+ },
+ {
+ "X": -2.9,
+ "Y": 0.85,
+ "Z": 3.55
+ },
+ {
+ "X": -2.9,
+ "Y": 3,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 19,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 2.9000003
+ },
+ "Vertices": [
+ {
+ "X": -2.9,
+ "Y": 0.85,
+ "Z": 3.55
+ },
+ {
+ "X": -2.9,
+ "Y": 3,
+ "Z": 2.9
+ },
+ {
+ "X": -2.9,
+ "Y": 3,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 20,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 2.9000003
+ },
+ "Vertices": [
+ {
+ "X": -2.9,
+ "Y": 0.85,
+ "Z": 3.55
+ },
+ {
+ "X": -2.9,
+ "Y": 0.85,
+ "Z": 2.9
+ },
+ {
+ "X": -2.9,
+ "Y": 3,
+ "Z": 2.9
+ }
+ ]
+ },
+ {
+ "Id": 21,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 2.9
+ },
+ "Vertices": [
+ {
+ "X": -2.9,
+ "Y": 3,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": -2.9,
+ "Y": 3,
+ "Z": 2.9
+ },
+ {
+ "X": -2.9,
+ "Y": 0.85,
+ "Z": 2.9
+ },
+ {
+ "X": -2.9,
+ "Y": 0.85,
+ "Z": 1
+ }
+ ]
+ },
+ {
+ "Id": 22,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 2.9
+ },
+ "Vertices": [
+ {
+ "X": -2.9,
+ "Y": 0.85,
+ "Z": 1
+ },
+ {
+ "X": -2.9,
+ "Y": -1.05,
+ "Z": 1
+ },
+ {
+ "X": -2.9,
+ "Y": -3.2,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": -2.9,
+ "Y": 3,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 23,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 2.9000003
+ },
+ "Vertices": [
+ {
+ "X": -2.9,
+ "Y": -1.05,
+ "Z": 3.55
+ },
+ {
+ "X": -2.9,
+ "Y": 3,
+ "Z": 4.3
+ },
+ {
+ "X": -2.9,
+ "Y": -3.2,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 24,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 2.9
+ },
+ "Vertices": [
+ {
+ "X": -2.9,
+ "Y": -3.2,
+ "Z": 2.9
+ },
+ {
+ "X": -2.9,
+ "Y": -1.05,
+ "Z": 2.9
+ },
+ {
+ "X": -2.9,
+ "Y": -1.05,
+ "Z": 3.55
+ },
+ {
+ "X": -2.9,
+ "Y": -3.2,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 25,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 3.2
+ },
+ "Vertices": [
+ {
+ "X": 3.9,
+ "Y": -3.2,
+ "Z": 2.9
+ },
+ {
+ "X": -2.9,
+ "Y": -3.2,
+ "Z": 2.9
+ },
+ {
+ "X": -2.9,
+ "Y": -3.2,
+ "Z": 4.3
+ },
+ {
+ "X": 3.9,
+ "Y": -3.2,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 26,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 3.2
+ },
+ "Vertices": [
+ {
+ "X": -2.9,
+ "Y": -3.2,
+ "Z": 2.9
+ },
+ {
+ "X": -1,
+ "Y": -3.2,
+ "Z": 2.9
+ },
+ {
+ "X": -1,
+ "Y": -3.2,
+ "Z": 1
+ },
+ {
+ "X": -2.9,
+ "Y": -3.2,
+ "Z": 1
+ }
+ ]
+ }
+ ],
+ "PortalPolygons": [
+ {
+ "Id": 0,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0.8289255,
+ "Y": 0,
+ "Z": -0.55935895
+ },
+ "D": 4.809128
+ },
+ "Vertices": [
+ {
+ "X": -2.9,
+ "Y": 3,
+ "Z": 4.3
+ },
+ {
+ "X": -1.14552,
+ "Y": 2.38419E-08,
+ "Z": 6.9
+ },
+ {
+ "X": -2.9,
+ "Y": -3.2,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 1,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -0.7999291,
+ "Y": 0,
+ "Z": -0.60009456
+ },
+ "D": 5.7001305
+ },
+ "Vertices": [
+ {
+ "X": 3.9,
+ "Y": -3.2,
+ "Z": 4.3
+ },
+ {
+ "X": 1.94952,
+ "Y": 2.38419E-08,
+ "Z": 6.9
+ },
+ {
+ "X": 3.9,
+ "Y": 3,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 2,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 3
+ },
+ "Vertices": [
+ {
+ "X": 2,
+ "Y": 3,
+ "Z": 2.9
+ },
+ {
+ "X": -1,
+ "Y": 3,
+ "Z": 2.9
+ },
+ {
+ "X": -1,
+ "Y": 3,
+ "Z": 1
+ },
+ {
+ "X": 2,
+ "Y": 3,
+ "Z": 1
+ }
+ ]
+ },
+ {
+ "Id": 3,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 3.2
+ },
+ "Vertices": [
+ {
+ "X": 3.9,
+ "Y": -3.2,
+ "Z": 2.9
+ },
+ {
+ "X": -2.9,
+ "Y": -3.2,
+ "Z": 2.9
+ },
+ {
+ "X": -2.9,
+ "Y": -3.2,
+ "Z": 4.3
+ },
+ {
+ "X": 3.9,
+ "Y": -3.2,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 4,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 3
+ },
+ "Vertices": [
+ {
+ "X": -2.9,
+ "Y": 3,
+ "Z": 2.9
+ },
+ {
+ "X": 3.9,
+ "Y": 3,
+ "Z": 2.9
+ },
+ {
+ "X": 3.9,
+ "Y": 3,
+ "Z": 4.3
+ },
+ {
+ "X": -2.9,
+ "Y": 3,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 5,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 3.9
+ },
+ "Vertices": [
+ {
+ "X": 3.9,
+ "Y": 3,
+ "Z": 4.3
+ },
+ {
+ "X": 3.9,
+ "Y": 3,
+ "Z": 2.9
+ },
+ {
+ "X": 3.9,
+ "Y": -3.2,
+ "Z": 2.9
+ },
+ {
+ "X": 3.9,
+ "Y": -3.2,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 6,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 3
+ },
+ "Vertices": [
+ {
+ "X": -1,
+ "Y": 3,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": -1,
+ "Y": 3,
+ "Z": 2.9
+ },
+ {
+ "X": -2.9,
+ "Y": 3,
+ "Z": 2.9
+ },
+ {
+ "X": -2.9,
+ "Y": 3,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 7,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 3
+ },
+ "Vertices": [
+ {
+ "X": 2,
+ "Y": 3,
+ "Z": 2.9
+ },
+ {
+ "X": 2,
+ "Y": 3,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 3.9,
+ "Y": 3,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 3.9,
+ "Y": 3,
+ "Z": 2.9
+ }
+ ]
+ },
+ {
+ "Id": 8,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 3
+ },
+ "Vertices": [
+ {
+ "X": -1,
+ "Y": 3,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 2,
+ "Y": 3,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 2,
+ "Y": 3,
+ "Z": 1
+ },
+ {
+ "X": -1,
+ "Y": 3,
+ "Z": 1
+ }
+ ]
+ },
+ {
+ "Id": 9,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 3.9
+ },
+ "Vertices": [
+ {
+ "X": 3.9,
+ "Y": -1.8519,
+ "Z": 2.9
+ },
+ {
+ "X": 3.9,
+ "Y": -1.85189,
+ "Z": 0
+ },
+ {
+ "X": 3.9,
+ "Y": -3.2,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 3.9,
+ "Y": -3.2,
+ "Z": 2.9
+ }
+ ]
+ },
+ {
+ "Id": 10,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 3.9
+ },
+ "Vertices": [
+ {
+ "X": 3.9,
+ "Y": 0.0526863,
+ "Z": 0
+ },
+ {
+ "X": 3.9,
+ "Y": 0.052686,
+ "Z": 2.9
+ },
+ {
+ "X": 3.9,
+ "Y": 3,
+ "Z": 2.9
+ },
+ {
+ "X": 3.9,
+ "Y": 3,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 11,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 3.9
+ },
+ "Vertices": [
+ {
+ "X": 3.9,
+ "Y": 0.0526863,
+ "Z": 2.5
+ },
+ {
+ "X": 3.9,
+ "Y": -1.8519,
+ "Z": 2.5
+ },
+ {
+ "X": 3.9,
+ "Y": -1.8519,
+ "Z": 2.9
+ },
+ {
+ "X": 3.9,
+ "Y": 0.052686,
+ "Z": 2.9
+ }
+ ]
+ },
+ {
+ "Id": 12,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 3.2
+ },
+ "Vertices": [
+ {
+ "X": -2.9,
+ "Y": -3.2,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": -2.9,
+ "Y": -3.2,
+ "Z": 1
+ },
+ {
+ "X": 3.9,
+ "Y": -3.2,
+ "Z": 1
+ },
+ {
+ "X": 3.9,
+ "Y": -3.2,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 13,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 3.2
+ },
+ "Vertices": [
+ {
+ "X": 1.68,
+ "Y": -3.2,
+ "Z": 1
+ },
+ {
+ "X": 1.68,
+ "Y": -3.2,
+ "Z": 2.9
+ },
+ {
+ "X": 3.9,
+ "Y": -3.2,
+ "Z": 2.9
+ },
+ {
+ "X": 3.9,
+ "Y": -3.2,
+ "Z": 1
+ }
+ ]
+ },
+ {
+ "Id": 14,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 3.2
+ },
+ "Vertices": [
+ {
+ "X": 1.68,
+ "Y": -3.2,
+ "Z": 1
+ },
+ {
+ "X": -1,
+ "Y": -3.2,
+ "Z": 1
+ },
+ {
+ "X": -1,
+ "Y": -3.2,
+ "Z": 2.9
+ },
+ {
+ "X": 1.68,
+ "Y": -3.2,
+ "Z": 2.9
+ }
+ ]
+ },
+ {
+ "Id": 15,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 3.2
+ },
+ "Vertices": [
+ {
+ "X": -2.9,
+ "Y": -3.2,
+ "Z": 2.9
+ },
+ {
+ "X": -1,
+ "Y": -3.2,
+ "Z": 2.9
+ },
+ {
+ "X": -1,
+ "Y": -3.2,
+ "Z": 1
+ },
+ {
+ "X": -2.9,
+ "Y": -3.2,
+ "Z": 1
+ }
+ ]
+ },
+ {
+ "Id": 16,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 0.63059264,
+ "Z": -0.776114
+ },
+ "D": 5.3551865
+ },
+ "Vertices": [
+ {
+ "X": -1.14552,
+ "Y": 2.38419E-08,
+ "Z": 6.9
+ },
+ {
+ "X": 1.94952,
+ "Y": 2.38419E-08,
+ "Z": 6.9
+ },
+ {
+ "X": 3.9,
+ "Y": -3.2,
+ "Z": 4.3
+ },
+ {
+ "X": -2.9,
+ "Y": -3.2,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 17,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -0.65493053,
+ "Z": -0.7556891
+ },
+ "D": 5.214255
+ },
+ "Vertices": [
+ {
+ "X": 1.94952,
+ "Y": 2.38419E-08,
+ "Z": 6.9
+ },
+ {
+ "X": -1.14552,
+ "Y": 2.38419E-08,
+ "Z": 6.9
+ },
+ {
+ "X": -2.9,
+ "Y": 3,
+ "Z": 4.3
+ },
+ {
+ "X": 3.9,
+ "Y": 3,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 18,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 0,
+ "Z": 1
+ },
+ "D": 1.19209E-08
+ },
+ "Vertices": [
+ {
+ "X": 3.9,
+ "Y": 3,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": -2.9,
+ "Y": 3,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": -2.9,
+ "Y": -3.2,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 3.9,
+ "Y": -3.2,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 19,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 2.9
+ },
+ "Vertices": [
+ {
+ "X": -2.9,
+ "Y": 0.85,
+ "Z": 1
+ },
+ {
+ "X": -2.9,
+ "Y": -1.05,
+ "Z": 1
+ },
+ {
+ "X": -2.9,
+ "Y": -3.2,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": -2.9,
+ "Y": 3,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 20,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 2.9
+ },
+ "Vertices": [
+ {
+ "X": -2.9,
+ "Y": -1.05,
+ "Z": 1
+ },
+ {
+ "X": -2.9,
+ "Y": -1.05,
+ "Z": 2.9
+ },
+ {
+ "X": -2.9,
+ "Y": -3.2,
+ "Z": 2.9
+ },
+ {
+ "X": -2.9,
+ "Y": -3.2,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 21,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 2.9
+ },
+ "Vertices": [
+ {
+ "X": -2.9,
+ "Y": 3,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": -2.9,
+ "Y": 3,
+ "Z": 2.9
+ },
+ {
+ "X": -2.9,
+ "Y": 0.85,
+ "Z": 2.9
+ },
+ {
+ "X": -2.9,
+ "Y": 0.85,
+ "Z": 1
+ }
+ ]
+ },
+ {
+ "Id": 22,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 2.9
+ },
+ "Vertices": [
+ {
+ "X": -2.9,
+ "Y": -3.2,
+ "Z": 2.9
+ },
+ {
+ "X": -2.9,
+ "Y": -1.05,
+ "Z": 2.9
+ },
+ {
+ "X": -2.9,
+ "Y": -1.05,
+ "Z": 3.55
+ },
+ {
+ "X": -2.9,
+ "Y": -3.2,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 23,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 2.9000003
+ },
+ "Vertices": [
+ {
+ "X": -2.9,
+ "Y": -1.05,
+ "Z": 3.55
+ },
+ {
+ "X": -2.9,
+ "Y": 0.85,
+ "Z": 3.55
+ },
+ {
+ "X": -2.9,
+ "Y": 3,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 24,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 2.9000003
+ },
+ "Vertices": [
+ {
+ "X": -2.9,
+ "Y": -1.05,
+ "Z": 3.55
+ },
+ {
+ "X": -2.9,
+ "Y": 3,
+ "Z": 4.3
+ },
+ {
+ "X": -2.9,
+ "Y": -3.2,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 25,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 2.9000003
+ },
+ "Vertices": [
+ {
+ "X": -2.9,
+ "Y": 0.85,
+ "Z": 3.55
+ },
+ {
+ "X": -2.9,
+ "Y": 3,
+ "Z": 2.9
+ },
+ {
+ "X": -2.9,
+ "Y": 3,
+ "Z": 4.3
+ }
+ ]
+ },
+ {
+ "Id": 26,
+ "NumPoints": 3,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 2.9000003
+ },
+ "Vertices": [
+ {
+ "X": -2.9,
+ "Y": 0.85,
+ "Z": 3.55
+ },
+ {
+ "X": -2.9,
+ "Y": 0.85,
+ "Z": 2.9
+ },
+ {
+ "X": -2.9,
+ "Y": 3,
+ "Z": 2.9
+ }
+ ]
+ },
+ {
+ "Id": 27,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": -3.9
+ },
+ "Vertices": [
+ {
+ "X": 3.9,
+ "Y": -1.8519,
+ "Z": 2.5
+ },
+ {
+ "X": 3.9,
+ "Y": -1.85189,
+ "Z": 0
+ },
+ {
+ "X": 3.9,
+ "Y": 0.0526863,
+ "Z": 0
+ },
+ {
+ "X": 3.9,
+ "Y": 0.0526863,
+ "Z": 2.5
+ }
+ ]
+ },
+ {
+ "Id": 28,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 2.9
+ },
+ "Vertices": [
+ {
+ "X": -2.9,
+ "Y": 0.85,
+ "Z": 3.55
+ },
+ {
+ "X": -2.9,
+ "Y": -1.05,
+ "Z": 3.55
+ },
+ {
+ "X": -2.9,
+ "Y": -1.05,
+ "Z": 1
+ },
+ {
+ "X": -2.9,
+ "Y": 0.85,
+ "Z": 1
+ }
+ ]
+ }
+ ],
+ "Portals": [
+ {
+ "OtherCellId": 371,
+ "PolygonId": 27,
+ "Flags": 1
+ },
+ {
+ "OtherCellId": 367,
+ "PolygonId": 28,
+ "Flags": 3
+ }
+ ],
+ "VisibleCellIds": [
+ 2847146351,
+ 2847146352,
+ 2847146353,
+ 2847146355,
+ 2847146356,
+ 2847146357
+ ]
+}
\ No newline at end of file
diff --git a/tests/AcDream.Core.Tests/Fixtures/flap-doorway/0xA9B40173.json b/tests/AcDream.Core.Tests/Fixtures/flap-doorway/0xA9B40173.json
new file mode 100644
index 00000000..aa6a9d84
--- /dev/null
+++ b/tests/AcDream.Core.Tests/Fixtures/flap-doorway/0xA9B40173.json
@@ -0,0 +1,413 @@
+{
+ "CellId": 2847146355,
+ "WorldTransform": {
+ "M11": -1,
+ "M12": 8.74228E-08,
+ "M13": 0,
+ "M14": 0,
+ "M21": -8.74228E-08,
+ "M22": -1,
+ "M23": 0,
+ "M24": 0,
+ "M31": 0,
+ "M32": 0,
+ "M33": 1,
+ "M34": 0,
+ "M41": 161.929,
+ "M42": 7.50315,
+ "M43": 94,
+ "M44": 1
+ },
+ "InverseWorldTransform": {
+ "M11": -1,
+ "M12": -8.74228E-08,
+ "M13": 0,
+ "M14": -0,
+ "M21": 8.74228E-08,
+ "M22": -1,
+ "M23": 0,
+ "M24": 0,
+ "M31": 0,
+ "M32": 0,
+ "M33": 1,
+ "M34": -0,
+ "M41": 161.929,
+ "M42": 7.5031643,
+ "M43": -94,
+ "M44": 1
+ },
+ "ResolvedPolygons": [
+ {
+ "Id": 0,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 5.9604556E-08,
+ "Y": 0,
+ "Z": 1
+ },
+ "D": -2.3245777E-07
+ },
+ "Vertices": [
+ {
+ "X": 3.9,
+ "Y": 0.0526863,
+ "Z": 0
+ },
+ {
+ "X": 3.9,
+ "Y": -1.85189,
+ "Z": 0
+ },
+ {
+ "X": 4.1,
+ "Y": -1.85189,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 4.1,
+ "Y": 0.0526863,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 1,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -7.54372E-07,
+ "Y": -1,
+ "Z": -6.0349706E-08
+ },
+ "D": 0.052689318
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": 0.052686,
+ "Z": 2.5
+ },
+ {
+ "X": 3.9,
+ "Y": 0.0526863,
+ "Z": 2.5
+ },
+ {
+ "X": 3.9,
+ "Y": 0.0526863,
+ "Z": 0
+ },
+ {
+ "X": 4.1,
+ "Y": 0.0526863,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 2,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 0,
+ "Z": -1
+ },
+ "D": 2.5
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": -1.85189,
+ "Z": 2.5
+ },
+ {
+ "X": 3.9,
+ "Y": -1.8519,
+ "Z": 2.5
+ },
+ {
+ "X": 3.9,
+ "Y": 0.0526863,
+ "Z": 2.5
+ },
+ {
+ "X": 4.1,
+ "Y": 0.052686,
+ "Z": 2.5
+ }
+ ]
+ },
+ {
+ "Id": 3,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -2.5033974E-05,
+ "Y": 1,
+ "Z": 2.002716E-06
+ },
+ "D": 1.8519901
+ },
+ "Vertices": [
+ {
+ "X": 3.9,
+ "Y": -1.85189,
+ "Z": 0
+ },
+ {
+ "X": 3.9,
+ "Y": -1.8519,
+ "Z": 2.5
+ },
+ {
+ "X": 4.1,
+ "Y": -1.85189,
+ "Z": 2.5
+ },
+ {
+ "X": 4.1,
+ "Y": -1.85189,
+ "Z": -1.19209E-08
+ }
+ ]
+ }
+ ],
+ "PortalPolygons": [
+ {
+ "Id": 0,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 0,
+ "Z": -1
+ },
+ "D": 2.5
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": -1.85189,
+ "Z": 2.5
+ },
+ {
+ "X": 3.9,
+ "Y": -1.8519,
+ "Z": 2.5
+ },
+ {
+ "X": 3.9,
+ "Y": 0.0526863,
+ "Z": 2.5
+ },
+ {
+ "X": 4.1,
+ "Y": 0.052686,
+ "Z": 2.5
+ }
+ ]
+ },
+ {
+ "Id": 1,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -2.5033974E-05,
+ "Y": 1,
+ "Z": 2.002716E-06
+ },
+ "D": 1.8519901
+ },
+ "Vertices": [
+ {
+ "X": 3.9,
+ "Y": -1.85189,
+ "Z": 0
+ },
+ {
+ "X": 3.9,
+ "Y": -1.8519,
+ "Z": 2.5
+ },
+ {
+ "X": 4.1,
+ "Y": -1.85189,
+ "Z": 2.5
+ },
+ {
+ "X": 4.1,
+ "Y": -1.85189,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 2,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 5.9604556E-08,
+ "Y": 0,
+ "Z": 1
+ },
+ "D": -2.3245777E-07
+ },
+ "Vertices": [
+ {
+ "X": 3.9,
+ "Y": 0.0526863,
+ "Z": 0
+ },
+ {
+ "X": 3.9,
+ "Y": -1.85189,
+ "Z": 0
+ },
+ {
+ "X": 4.1,
+ "Y": -1.85189,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 4.1,
+ "Y": 0.0526863,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 3,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -7.54372E-07,
+ "Y": -1,
+ "Z": -6.0349706E-08
+ },
+ "D": 0.052689318
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": 0.052686,
+ "Z": 2.5
+ },
+ {
+ "X": 3.9,
+ "Y": 0.0526863,
+ "Z": 2.5
+ },
+ {
+ "X": 3.9,
+ "Y": 0.0526863,
+ "Z": 0
+ },
+ {
+ "X": 4.1,
+ "Y": 0.0526863,
+ "Z": -1.19209E-08
+ }
+ ]
+ },
+ {
+ "Id": 4,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 4.1
+ },
+ "Vertices": [
+ {
+ "X": 4.1,
+ "Y": 0.052686,
+ "Z": 2.5
+ },
+ {
+ "X": 4.1,
+ "Y": 0.0526863,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 4.1,
+ "Y": -1.85189,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 4.1,
+ "Y": -1.85189,
+ "Z": 2.5
+ }
+ ]
+ },
+ {
+ "Id": 5,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": -3.9
+ },
+ "Vertices": [
+ {
+ "X": 3.9,
+ "Y": -1.8519,
+ "Z": 2.5
+ },
+ {
+ "X": 3.9,
+ "Y": -1.85189,
+ "Z": 0
+ },
+ {
+ "X": 3.9,
+ "Y": 0.0526863,
+ "Z": 0
+ },
+ {
+ "X": 3.9,
+ "Y": 0.0526863,
+ "Z": 2.5
+ }
+ ]
+ }
+ ],
+ "Portals": [
+ {
+ "OtherCellId": 369,
+ "PolygonId": 4,
+ "Flags": 3
+ },
+ {
+ "OtherCellId": 370,
+ "PolygonId": 5,
+ "Flags": 3
+ }
+ ],
+ "VisibleCellIds": [
+ 2847146351,
+ 2847146352,
+ 2847146353,
+ 2847146354,
+ 2847146356,
+ 2847146357
+ ]
+}
\ No newline at end of file
diff --git a/tests/AcDream.Core.Tests/Fixtures/flap-doorway/0xA9B40174.json b/tests/AcDream.Core.Tests/Fixtures/flap-doorway/0xA9B40174.json
new file mode 100644
index 00000000..a47a8941
--- /dev/null
+++ b/tests/AcDream.Core.Tests/Fixtures/flap-doorway/0xA9B40174.json
@@ -0,0 +1,583 @@
+{
+ "CellId": 2847146356,
+ "WorldTransform": {
+ "M11": -1,
+ "M12": 8.74228E-08,
+ "M13": 0,
+ "M14": 0,
+ "M21": -8.74228E-08,
+ "M22": -1,
+ "M23": 0,
+ "M24": 0,
+ "M31": 0,
+ "M32": 0,
+ "M33": 1,
+ "M34": 0,
+ "M41": 161.929,
+ "M42": 7.50315,
+ "M43": 94,
+ "M44": 1
+ },
+ "InverseWorldTransform": {
+ "M11": -1,
+ "M12": -8.74228E-08,
+ "M13": 0,
+ "M14": -0,
+ "M21": 8.74228E-08,
+ "M22": -1,
+ "M23": 0,
+ "M24": 0,
+ "M31": 0,
+ "M32": 0,
+ "M33": 1,
+ "M34": -0,
+ "M41": 161.929,
+ "M42": 7.5031643,
+ "M43": -94,
+ "M44": 1
+ },
+ "ResolvedPolygons": [
+ {
+ "Id": 0,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 0,
+ "Z": 1
+ },
+ "D": 3.999
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": -2.85,
+ "Z": -3.999
+ },
+ {
+ "X": 9,
+ "Y": 2.98,
+ "Z": -3.999
+ },
+ {
+ "X": -2.664,
+ "Y": 2.98,
+ "Z": -3.999
+ },
+ {
+ "X": -2.664,
+ "Y": -2.85,
+ "Z": -3.999
+ }
+ ]
+ },
+ {
+ "Id": 1,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 9
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": -2.85,
+ "Z": -0.364
+ },
+ {
+ "X": 9,
+ "Y": 2.98,
+ "Z": -0.364
+ },
+ {
+ "X": 9,
+ "Y": 2.98,
+ "Z": -3.999
+ },
+ {
+ "X": 9,
+ "Y": -2.85,
+ "Z": -3.999
+ }
+ ]
+ },
+ {
+ "Id": 2,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 0,
+ "Z": -1
+ },
+ "D": -0.364
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": 2.98,
+ "Z": -0.364
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": -0.364
+ },
+ {
+ "X": 7,
+ "Y": 1.15,
+ "Z": -0.364
+ },
+ {
+ "X": -2.664,
+ "Y": 2.98,
+ "Z": -0.364
+ }
+ ]
+ },
+ {
+ "Id": 3,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 2.98
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": 2.98,
+ "Z": -3.999
+ },
+ {
+ "X": 9,
+ "Y": 2.98,
+ "Z": -0.364
+ },
+ {
+ "X": -2.664,
+ "Y": 2.98,
+ "Z": -0.364
+ },
+ {
+ "X": -2.664,
+ "Y": 2.98,
+ "Z": -3.999
+ }
+ ]
+ },
+ {
+ "Id": 4,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 0,
+ "Z": -1
+ },
+ "D": -0.364
+ },
+ "Vertices": [
+ {
+ "X": 7,
+ "Y": 1.15,
+ "Z": -0.364
+ },
+ {
+ "X": 7,
+ "Y": -2.85,
+ "Z": -0.364
+ },
+ {
+ "X": -2.664,
+ "Y": -2.85,
+ "Z": -0.364
+ },
+ {
+ "X": -2.664,
+ "Y": 2.98,
+ "Z": -0.364
+ }
+ ]
+ },
+ {
+ "Id": 5,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 2.85
+ },
+ "Vertices": [
+ {
+ "X": -2.664,
+ "Y": -2.85,
+ "Z": -0.364
+ },
+ {
+ "X": 9,
+ "Y": -2.85,
+ "Z": -0.364
+ },
+ {
+ "X": 9,
+ "Y": -2.85,
+ "Z": -3.999
+ },
+ {
+ "X": -2.664,
+ "Y": -2.85,
+ "Z": -3.999
+ }
+ ]
+ },
+ {
+ "Id": 6,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 2.664
+ },
+ "Vertices": [
+ {
+ "X": -2.664,
+ "Y": 2.98,
+ "Z": -3.999
+ },
+ {
+ "X": -2.664,
+ "Y": 2.98,
+ "Z": -0.364
+ },
+ {
+ "X": -2.664,
+ "Y": -2.85,
+ "Z": -0.364
+ },
+ {
+ "X": -2.664,
+ "Y": -2.85,
+ "Z": -3.999
+ }
+ ]
+ }
+ ],
+ "PortalPolygons": [
+ {
+ "Id": 0,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 0,
+ "Z": 1
+ },
+ "D": 3.999
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": -2.85,
+ "Z": -3.999
+ },
+ {
+ "X": 9,
+ "Y": 2.98,
+ "Z": -3.999
+ },
+ {
+ "X": -2.664,
+ "Y": 2.98,
+ "Z": -3.999
+ },
+ {
+ "X": -2.664,
+ "Y": -2.85,
+ "Z": -3.999
+ }
+ ]
+ },
+ {
+ "Id": 1,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 2.85
+ },
+ "Vertices": [
+ {
+ "X": -2.664,
+ "Y": -2.85,
+ "Z": -0.364
+ },
+ {
+ "X": 9,
+ "Y": -2.85,
+ "Z": -0.364
+ },
+ {
+ "X": 9,
+ "Y": -2.85,
+ "Z": -3.999
+ },
+ {
+ "X": -2.664,
+ "Y": -2.85,
+ "Z": -3.999
+ }
+ ]
+ },
+ {
+ "Id": 2,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 9
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": -2.85,
+ "Z": -0.364
+ },
+ {
+ "X": 9,
+ "Y": 2.98,
+ "Z": -0.364
+ },
+ {
+ "X": 9,
+ "Y": 2.98,
+ "Z": -3.999
+ },
+ {
+ "X": 9,
+ "Y": -2.85,
+ "Z": -3.999
+ }
+ ]
+ },
+ {
+ "Id": 3,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 2.98
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": 2.98,
+ "Z": -3.999
+ },
+ {
+ "X": 9,
+ "Y": 2.98,
+ "Z": -0.364
+ },
+ {
+ "X": -2.664,
+ "Y": 2.98,
+ "Z": -0.364
+ },
+ {
+ "X": -2.664,
+ "Y": 2.98,
+ "Z": -3.999
+ }
+ ]
+ },
+ {
+ "Id": 4,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 2.664
+ },
+ "Vertices": [
+ {
+ "X": -2.664,
+ "Y": 2.98,
+ "Z": -3.999
+ },
+ {
+ "X": -2.664,
+ "Y": 2.98,
+ "Z": -0.364
+ },
+ {
+ "X": -2.664,
+ "Y": -2.85,
+ "Z": -0.364
+ },
+ {
+ "X": -2.664,
+ "Y": -2.85,
+ "Z": -3.999
+ }
+ ]
+ },
+ {
+ "Id": 5,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 0,
+ "Z": -1
+ },
+ "D": -0.364
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": 2.98,
+ "Z": -0.364
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": -0.364
+ },
+ {
+ "X": 7,
+ "Y": 1.15,
+ "Z": -0.364
+ },
+ {
+ "X": -2.664,
+ "Y": 2.98,
+ "Z": -0.364
+ }
+ ]
+ },
+ {
+ "Id": 6,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 0,
+ "Z": -1
+ },
+ "D": -0.364
+ },
+ "Vertices": [
+ {
+ "X": 7,
+ "Y": 1.15,
+ "Z": -0.364
+ },
+ {
+ "X": 7,
+ "Y": -2.85,
+ "Z": -0.364
+ },
+ {
+ "X": -2.664,
+ "Y": -2.85,
+ "Z": -0.364
+ },
+ {
+ "X": -2.664,
+ "Y": 2.98,
+ "Z": -0.364
+ }
+ ]
+ },
+ {
+ "Id": 7,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 0,
+ "Z": 1
+ },
+ "D": 0.364
+ },
+ "Vertices": [
+ {
+ "X": 7,
+ "Y": 1.15,
+ "Z": -0.364
+ },
+ {
+ "X": 7,
+ "Y": -2.85,
+ "Z": -0.364
+ },
+ {
+ "X": 9,
+ "Y": -2.85,
+ "Z": -0.364
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": -0.364
+ }
+ ]
+ }
+ ],
+ "Portals": [
+ {
+ "OtherCellId": 373,
+ "PolygonId": 7,
+ "Flags": 1
+ }
+ ],
+ "VisibleCellIds": [
+ 2847146351,
+ 2847146352,
+ 2847146353,
+ 2847146354,
+ 2847146355,
+ 2847146357
+ ]
+}
\ No newline at end of file
diff --git a/tests/AcDream.Core.Tests/Fixtures/flap-doorway/0xA9B40175.json b/tests/AcDream.Core.Tests/Fixtures/flap-doorway/0xA9B40175.json
new file mode 100644
index 00000000..49a53370
--- /dev/null
+++ b/tests/AcDream.Core.Tests/Fixtures/flap-doorway/0xA9B40175.json
@@ -0,0 +1,413 @@
+{
+ "CellId": 2847146357,
+ "WorldTransform": {
+ "M11": -1,
+ "M12": 8.74228E-08,
+ "M13": 0,
+ "M14": 0,
+ "M21": -8.74228E-08,
+ "M22": -1,
+ "M23": 0,
+ "M24": 0,
+ "M31": 0,
+ "M32": 0,
+ "M33": 1,
+ "M34": 0,
+ "M41": 161.929,
+ "M42": 7.50315,
+ "M43": 94,
+ "M44": 1
+ },
+ "InverseWorldTransform": {
+ "M11": -1,
+ "M12": -8.74228E-08,
+ "M13": 0,
+ "M14": -0,
+ "M21": 8.74228E-08,
+ "M22": -1,
+ "M23": 0,
+ "M24": 0,
+ "M31": 0,
+ "M32": 0,
+ "M33": 1,
+ "M34": -0,
+ "M41": 161.929,
+ "M42": 7.5031643,
+ "M43": -94,
+ "M44": 1
+ },
+ "ResolvedPolygons": [
+ {
+ "Id": 0,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 1.15
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 0
+ },
+ {
+ "X": 7,
+ "Y": 1.15,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 7,
+ "Y": 1.15,
+ "Z": -0.364
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": -0.364
+ }
+ ]
+ },
+ {
+ "Id": 1,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 2.85
+ },
+ "Vertices": [
+ {
+ "X": 7,
+ "Y": -2.85,
+ "Z": -0.364
+ },
+ {
+ "X": 7,
+ "Y": -2.85,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 9,
+ "Y": -2.85,
+ "Z": 1.11022E-16
+ },
+ {
+ "X": 9,
+ "Y": -2.85,
+ "Z": -0.364
+ }
+ ]
+ },
+ {
+ "Id": 2,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": -7
+ },
+ "Vertices": [
+ {
+ "X": 7,
+ "Y": 1.15,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 7,
+ "Y": -2.85,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 7,
+ "Y": -2.85,
+ "Z": -0.364
+ },
+ {
+ "X": 7,
+ "Y": 1.15,
+ "Z": -0.364
+ }
+ ]
+ },
+ {
+ "Id": 3,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 9
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": -2.85,
+ "Z": 1.11022E-16
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 0
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": -0.364
+ },
+ {
+ "X": 9,
+ "Y": -2.85,
+ "Z": -0.364
+ }
+ ]
+ }
+ ],
+ "PortalPolygons": [
+ {
+ "Id": 0,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": -1,
+ "Z": 0
+ },
+ "D": 1.15
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 0
+ },
+ {
+ "X": 7,
+ "Y": 1.15,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 7,
+ "Y": 1.15,
+ "Z": -0.364
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": -0.364
+ }
+ ]
+ },
+ {
+ "Id": 1,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": -7
+ },
+ "Vertices": [
+ {
+ "X": 7,
+ "Y": 1.15,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 7,
+ "Y": -2.85,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 7,
+ "Y": -2.85,
+ "Z": -0.364
+ },
+ {
+ "X": 7,
+ "Y": 1.15,
+ "Z": -0.364
+ }
+ ]
+ },
+ {
+ "Id": 2,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 1,
+ "Z": 0
+ },
+ "D": 2.85
+ },
+ "Vertices": [
+ {
+ "X": 7,
+ "Y": -2.85,
+ "Z": -0.364
+ },
+ {
+ "X": 7,
+ "Y": -2.85,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 9,
+ "Y": -2.85,
+ "Z": 1.11022E-16
+ },
+ {
+ "X": 9,
+ "Y": -2.85,
+ "Z": -0.364
+ }
+ ]
+ },
+ {
+ "Id": 3,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": -1,
+ "Y": 0,
+ "Z": 0
+ },
+ "D": 9
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": -2.85,
+ "Z": 1.11022E-16
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 0
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": -0.364
+ },
+ {
+ "X": 9,
+ "Y": -2.85,
+ "Z": -0.364
+ }
+ ]
+ },
+ {
+ "Id": 4,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 5.96045E-09,
+ "Y": -1.387775E-17,
+ "Z": -1
+ },
+ "D": -5.364405E-08
+ },
+ "Vertices": [
+ {
+ "X": 9,
+ "Y": -2.85,
+ "Z": 1.11022E-16
+ },
+ {
+ "X": 7,
+ "Y": -2.85,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 7,
+ "Y": 1.15,
+ "Z": -1.19209E-08
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": 0
+ }
+ ]
+ },
+ {
+ "Id": 5,
+ "NumPoints": 4,
+ "SidesType": 0,
+ "Plane": {
+ "Normal": {
+ "X": 0,
+ "Y": 0,
+ "Z": 1
+ },
+ "D": 0.364
+ },
+ "Vertices": [
+ {
+ "X": 7,
+ "Y": 1.15,
+ "Z": -0.364
+ },
+ {
+ "X": 7,
+ "Y": -2.85,
+ "Z": -0.364
+ },
+ {
+ "X": 9,
+ "Y": -2.85,
+ "Z": -0.364
+ },
+ {
+ "X": 9,
+ "Y": 1.15,
+ "Z": -0.364
+ }
+ ]
+ }
+ ],
+ "Portals": [
+ {
+ "OtherCellId": 369,
+ "PolygonId": 4,
+ "Flags": 3
+ },
+ {
+ "OtherCellId": 372,
+ "PolygonId": 5,
+ "Flags": 3
+ }
+ ],
+ "VisibleCellIds": [
+ 2847146351,
+ 2847146352,
+ 2847146353,
+ 2847146354,
+ 2847146355,
+ 2847146356
+ ]
+}
\ No newline at end of file
diff --git a/tests/AcDream.Core.Tests/Input/PlayerMovementControllerTests.cs b/tests/AcDream.Core.Tests/Input/PlayerMovementControllerTests.cs
index add3dae9..1dd41b37 100644
--- a/tests/AcDream.Core.Tests/Input/PlayerMovementControllerTests.cs
+++ b/tests/AcDream.Core.Tests/Input/PlayerMovementControllerTests.cs
@@ -34,6 +34,97 @@ public class PlayerMovementControllerTests
Assert.Equal(96f, result.Position.Y, precision: 1);
}
+ // ── Indoor-flap root cause: resting-body bit-stability ────────────────────
+ //
+ // The indoor render "flap" (textures battling at the cottage doorway) is
+ // portal-flood membership instability. PortalVisibilityBuilder.Build is a
+ // proven-deterministic pure function, so the membership can only flip if its
+ // INPUT (the camera eye, derived from the player RenderPosition) varies.
+ // Live 6-dp capture (pvinput.log:54) shows the player RenderPosition carries
+ // a perpetual ~1-ULP flicker at rest (Z 94.000000 <-> 93.999992 — exactly one
+ // float mantissa step). ComputeRenderPosition is Vector3.Lerp(_prevPhysicsPos,
+ // _currPhysicsPos, alpha), and Lerp(a, a, t) == a exactly, so a jittering
+ // RenderPosition at rest means the physics body's resting Position is NOT
+ // bit-stable between ticks. Retail's authoritative local position is bit-stable
+ // at rest (validate_transition -> kill_velocity on every grounded contact), so
+ // retail never flaps.
+ //
+ // This test pins the physics-side invariant: a grounded body with no input
+ // must hold a byte-identical position across many frames. It PASSES — which
+ // is itself the evidence: the physics resting position is bit-stable, so the
+ // doorway flap is NOT a physics-rest jitter. See
+ // docs/research/2026-06-08-flap-physics-diagnosis-REFUTED-its-render-membership.md
+ // (the flap is render-side portal-flood membership instability at the grazing
+ // doorway portal under a sweeping camera eye). Kept as a regression guard.
+ [Fact]
+ public void Update_AtRestNoInput_RenderPositionBitStableAcrossManyFrames()
+ {
+ var engine = MakeFlatEngine();
+ var controller = new PlayerMovementController(engine);
+ var rest = new Vector3(96f, 96f, 50f);
+ controller.SetPosition(rest, 0x0001);
+
+ // Settle one frame so the resolver establishes its rest state, then
+ // capture the baseline the body must hold.
+ var settled = controller.Update(1f / 60f, new MovementInput());
+ Vector3 baselineRender = settled.RenderPosition;
+ Vector3 baselinePhysics = settled.Position;
+
+ // Hold still for ~10 s of 60 Hz frames (crosses MinQuantum every ~2
+ // frames, so the 30 Hz physics tick fires throughout — same cadence as
+ // live). Any deviation, even one ULP, is the flap's root cause.
+ float maxRenderDev = 0f;
+ float maxPhysicsDev = 0f;
+ for (int i = 0; i < 600; i++)
+ {
+ var r = controller.Update(1f / 60f, new MovementInput());
+ maxRenderDev = MathF.Max(maxRenderDev, (r.RenderPosition - baselineRender).Length());
+ maxPhysicsDev = MathF.Max(maxPhysicsDev, (r.Position - baselinePhysics).Length());
+ }
+
+ Assert.True(
+ maxRenderDev == 0f && maxPhysicsDev == 0f,
+ $"resting body drifted: render={maxRenderDev * 1e6f:F3} µm, " +
+ $"physics={maxPhysicsDev * 1e6f:F3} µm; expected byte-identical rest");
+ }
+
+ // After walking then releasing input, the body must SETTLE to a
+ // byte-identical resting position — not keep blipping a residual velocity.
+ // This models the live flap: the player walks to the cottage doorway and
+ // stops, and the eye then carries a ~1-ULP jitter that flips portal-flood
+ // membership. Flat-terrain variant: if even this drifts, the residual-after-
+ // motion path is the root and it is not indoor-specific.
+ [Fact]
+ public void Update_WalkThenStop_SettlesToBitStableRest()
+ {
+ var engine = MakeFlatEngine();
+ var controller = new PlayerMovementController(engine);
+ controller.SetPosition(new Vector3(96f, 96f, 50f), 0x0001);
+ controller.Yaw = 0f;
+
+ // Walk forward ~0.5 s, then release.
+ for (int i = 0; i < 30; i++)
+ controller.Update(1f / 60f, new MovementInput(Forward: true));
+ // Let velocity decay / state settle.
+ for (int i = 0; i < 30; i++)
+ controller.Update(1f / 60f, new MovementInput());
+
+ var settled = controller.Update(1f / 60f, new MovementInput());
+ Vector3 basePos = settled.Position;
+ Vector3 baseRender = settled.RenderPosition;
+
+ float maxPos = 0f, maxRender = 0f;
+ for (int i = 0; i < 600; i++)
+ {
+ var r = controller.Update(1f / 60f, new MovementInput());
+ maxPos = MathF.Max(maxPos, (r.Position - basePos).Length());
+ maxRender = MathF.Max(maxRender, (r.RenderPosition - baseRender).Length());
+ }
+
+ Assert.True(maxPos == 0f && maxRender == 0f,
+ $"post-walk rest drifted: pos={maxPos * 1e6f:F3} µm, render={maxRender * 1e6f:F3} µm");
+ }
+
[Fact]
public void Update_ForwardInput_MovesInFacingDirection()
{
diff --git a/tests/AcDream.Core.Tests/Physics/CellarUpTrajectoryReplayTests.cs b/tests/AcDream.Core.Tests/Physics/CellarUpTrajectoryReplayTests.cs
index 0054a823..04b73dbb 100644
--- a/tests/AcDream.Core.Tests/Physics/CellarUpTrajectoryReplayTests.cs
+++ b/tests/AcDream.Core.Tests/Physics/CellarUpTrajectoryReplayTests.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Numerics;
+using AcDream.App.Input;
using AcDream.Core.Physics;
using DatReaderWriter.Enums;
using DatReaderWriter.Types;
@@ -136,6 +137,137 @@ public class CellarUpTrajectoryReplayTests : IDisposable
// Tests
// ───────────────────────────────────────────────────────────────
+ ///
+ /// Indoor-flap root cause (2026-06-08). A body resting on the cellar
+ /// floor with ZERO requested motion must hold a byte-identical position
+ /// across many ticks — retail's authoritative local position is bit-stable
+ /// at rest (validate_transition → kill_velocity + SetWalkable on every
+ /// grounded contact, decomp :272567/:274467).
+ ///
+ ///
+ /// The indoor render "flap" (textures battling at the cottage doorway) is
+ /// portal-flood membership instability. PortalVisibilityBuilder.Build is a
+ /// proven-deterministic pure function, so the membership can only flip if its
+ /// INPUT (the camera eye, from the player RenderPosition) varies.
+ /// RenderPosition = Lerp(_prevPhysicsPos, _currPhysicsPos), and Lerp(a,a,t)==a,
+ /// so a jittering eye at rest means the physics body's resting Position is not
+ /// bit-stable. Flat LandCell terrain rest IS bit-stable
+ /// (.
+ /// Update_AtRestNoInput_RenderPositionBitStableAcrossManyFrames passes); the
+ /// instability is the INDOOR path — the floor-touch is classified
+ /// walkable=False (no walkable-polygon anchor), so each tick re-fires a
+ /// step-down probe whose re-found Z is not bit-stable.
+ ///
+ ///
+ /// PASSES — the indoor resting body is bit-stable even with the
+ /// grounded/cp=none contradictory state present. This is evidence (with the
+ /// flat-terrain variant) that the doorway flap is NOT a physics-rest jitter;
+ /// it is render-side portal-flood membership instability under a sweeping eye.
+ /// See docs/research/2026-06-08-flap-physics-diagnosis-REFUTED-its-render-membership.md.
+ /// The diagnostic log (on any future regression) names the failing per-tick
+ /// condition. Kept as a regression guard.
+ ///
+ [Fact]
+ public void IndoorCellarFloor_AtRestZeroOffset_BodyPositionBitStable()
+ {
+ var (engine, _) = BuildEngineWithCellarFixtures();
+
+ // Body seeded exactly at its natural resting pose on the cellar floor,
+ // WITH the walkable-polygon + contact-plane anchor (BuildInitialBody) —
+ // i.e. the most-favourable starting state. If even this drifts, the rest
+ // path fails to PERSIST the anchor.
+ var body = BuildInitialBody();
+ var rest = body.Position;
+ uint cell = CellarId;
+ bool grounded = true;
+
+ var log = new List();
+ float maxDrift = 0f;
+ for (int tick = 1; tick <= 200; tick++)
+ {
+ // ZERO requested motion: currentPos == targetPos == rest pose.
+ var result = engine.ResolveWithTransition(
+ currentPos: body.Position,
+ targetPos: body.Position,
+ cellId: cell,
+ sphereRadius: SphereRadius,
+ sphereHeight: SphereHeight,
+ stepUpHeight: StepUpHeight,
+ stepDownHeight: StepDownHeight,
+ isOnGround: grounded,
+ body: body,
+ moverFlags: ObjectInfoState.IsPlayer | ObjectInfoState.EdgeSlide,
+ movingEntityId: 0);
+
+ body.Position = result.Position;
+ cell = result.CellId;
+ grounded = result.IsOnGround;
+
+ float drift = (body.Position - rest).Length();
+ maxDrift = MathF.Max(maxDrift, drift);
+
+ if (tick <= 6 || drift > 0f)
+ {
+ log.Add(string.Format(System.Globalization.CultureInfo.InvariantCulture,
+ "tick{0,3}: pos=({1:F7},{2:F7},{3:F7}) drift={4:F3}µm grounded={5} " +
+ "walkable={6} cpV={7} ts=0x{8:X}",
+ tick, body.Position.X, body.Position.Y, body.Position.Z,
+ drift * 1e6f, grounded, body.WalkablePolygonValid,
+ body.ContactPlaneValid, (uint)body.TransientState));
+ }
+ }
+
+ Assert.True(maxDrift == 0f,
+ $"cellar-floor rest drifted {maxDrift * 1e6f:F3} µm (expected byte-identical):\n "
+ + string.Join("\n ", log.Take(24)));
+ }
+
+ ///
+ /// Indoor-flap investigation (2026-06-08) — the FULL production loop. Drives
+ /// (integration + flag logic + velocity,
+ /// not just the resolver) on the indoor cellar engine with NO input. PASSES —
+ /// the RenderPosition the camera reads is byte-identical at rest, confirming
+ /// the flap is not produced by the indoor controller rest loop. Kept as a
+ /// regression guard. See
+ /// docs/research/2026-06-08-flap-physics-diagnosis-REFUTED-its-render-membership.md.
+ ///
+ [Fact]
+ public void IndoorCell_FullController_AtRestNoInput_RenderPositionBitStable()
+ {
+ var (engine, _) = BuildEngineWithCellarFixtures();
+ var controller = new PlayerMovementController(engine);
+ controller.SetPosition(InitialSphereWorld, CellarId);
+
+ var settled = controller.Update(1f / 60f, new MovementInput());
+ var basePos = settled.Position;
+ var baseRender = settled.RenderPosition;
+
+ var log = new List();
+ float maxPos = 0f, maxRender = 0f;
+ for (int i = 1; i <= 600; i++)
+ {
+ var r = controller.Update(1f / 60f, new MovementInput());
+ float dp = (r.Position - basePos).Length();
+ float dr = (r.RenderPosition - baseRender).Length();
+ maxPos = MathF.Max(maxPos, dp);
+ maxRender = MathF.Max(maxRender, dr);
+ if (i <= 4 || dp > 0f || dr > 0f)
+ {
+ log.Add(string.Format(System.Globalization.CultureInfo.InvariantCulture,
+ "f{0,3}: pos=({1:F7},{2:F7},{3:F7}) render=({4:F7},{5:F7},{6:F7}) " +
+ "grounded={7} cell=0x{8:X8}",
+ i, r.Position.X, r.Position.Y, r.Position.Z,
+ r.RenderPosition.X, r.RenderPosition.Y, r.RenderPosition.Z,
+ r.IsOnGround, r.CellId));
+ }
+ }
+
+ Assert.True(maxPos == 0f && maxRender == 0f,
+ $"indoor controller rest drifted: pos={maxPos * 1e6f:F3} µm, "
+ + $"render={maxRender * 1e6f:F3} µm (expected byte-identical):\n "
+ + string.Join("\n ", log.Take(24)));
+ }
+
///
/// Confirms the harness compiles, the engine runs the simulation,
/// and a trajectory comes back with the expected number of points.