3dtiled-to-3dtiles
Reference & Planning

Handoff — 2026-10-29

State of the work, what is open, and what a new agent needs, written at the end of the roadmap-2026-09 session

Handoff — 2026-10-29

Written for the agent taking over from here. main and feat/roadmap-2026-09 have identical trees (every commit is cherry-picked onto main; main additionally has one squash commit from an earlier round). Prod (3dtiled.iconem.com, demo.3dtiled.iconem.com) auto-deploys from main. Start from remote main unless you need the machine-local files listed at the end.

Rules that are not in the code

  • Never commit an Iconem share link (api.iconem.com/s/…). They are bearer credentials. The Angkor and iconem-open mosaics exist only as machine-local manifests in .local/aggregate-sets/.
  • Angkor and Geghard repos are private; do not worry about them in open-data work.
  • Commits end with Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>.
  • On Windows, start Node servers with PowerShell Start-Process, not from the Bash tool (sandboxed servers die); they take ~10 s to come up (canvas/GLib load). Screenshots via headless Chrome/CDP.
  • Memory for this project lives in ~/.claude/projects/C--Dev-Iconem-3d-tiles-converters/memory/.

What happened today (see CHANGELOG 2026-10-29, 2026-10-29b)

  1. Upstream (3DTilesRendererJS), all awaiting Garrett. PR #1780 (Potree 1.8, LAZ/BROTLI error, failed-download error, maxPointSize, sizeAttenuation, R3F JSDoc note; review items answered, open question: default maxPointSize 0 or 50). Issue #1781 + PR #1782 (ADD-skip regression, fork branch fix-implicit-add-skip, one commit). Issue #1783 (adaptive point size for implicit ADD octrees; PR offered, ~200 lines, design in the issue). Public reproducer repo jo-chemla/3dtiles-samples (GitHub Pages): lion_takanawa/implicit-octree/tileset.json and tileset-x100.json. The local clone is .local/3DTilesRendererJS (remotes origin=NASA-AMMOS, fork=jo-chemla); headless traversal harness .local/addskip-harness.mjs + .local/src-loader.mjs.
  2. tile-server prod stall, fixed in two commits. range-getter.js (coalesced, capped, retried range reads; memoizeAsync failure TTL + promise dedupe; copc-live page restore), then the real root cause: curved COPC explicit trees (15–25 k tiles, proj4 per corner) built 113 times for the flai/open mosaics on the event loop. Now /stream?depth=0 root-only for the aggregate, 8-corner sampling under 20 km, curved tree cached. Local cold flai: 2.4 s.

Open items, in priority order

  1. Verify prod after the deploy of e4939d7. curl -w '%{time_total}' on /aggregate/tileset.json?set=open&nest=geodetic should be seconds, not minutes; the root page under 1 s; Portainer logs should show [range] … retrying lines at most, no FetchError. If the mosaic is still slow, the next suspect is childInfo on non-/stream children (cities, Esri, Aerometrex through /proxy), which are fetched from third-party hosts.
  2. When PR #1780 merges, re-sync apps/viewer/src/potree-lab/vendor/* to the merged commits and rewrite the PR #1780, <sha> links (vendored headers, potree-lab.mdx, viewer.mdx, CHANGELOG). When a release ships #1782, delete apps/viewer/src/lib/implicitAddFix.ts. When #1783 lands, drop the LOCAL PATCH child-box sizing in the vendored PointCloudMaterial.js.
  3. Potree LAZ / BROTLI nodes fail loudly on purpose (PotreeConverter 1.7 LAZ output, Potree 2.0). Decoders exist (laz-perf WASM, brotli-wasm); an optional decoder hook was discussed, not started.
  4. Lion quadtree sample for jo-chemla/3dtiles-samples (Garrett's "implicit octree and quadtree"): flatten the octree's z cells per level into one tile. Not started.
  5. Iconem STAC /api/stac/search?collections=pointcloud returns 500 at offset≥80 and for limit>80 (platform bug, not ours); 45 of 94 items are Potree 1.8. Asset hrefs are day-long SAS URLs whose query string must be forwarded on node requests.
  6. Roadmap items untouched this session: see todo-future-work.mdx Summary (fastest point-cloud tiler research, native 3DTRjs plugin for the middleware, potree-to-copc blocked on a JS LAZ encoder, SH colour for splats, WorkerPool wiring, browser runtime audit).

When the upstream PRs land: what to change in this repo

The viewer runs the release of 3d-tiles-renderer (apps/viewer/package.json, 0.5.2 today) plus vendored copies of three upstream files carrying our patches, plus three local plugins that work around upstream behaviour. Each upstream event retires a specific piece:

Upstream eventDelete / change hereKeep
A release ≥ 0.5.4 ships PR #1780 (Potree 1.8 attributes, LAZ/BROTLI error, failed-download error, maxPointSize, sizeAttenuation)Bump 3d-tiles-renderer in apps/viewer/package.json. Delete apps/viewer/src/potree-lab/vendor/potree/ (the loader is upstream verbatim once merged) and import PotreePlugin from 3d-tiles-renderer/plugins in lib/nativeLeaves.ts (line 43) and potree-lab/main.js (line 34). In vendor/pointcloud/ re-copy the four release files (PointCloudEffectsPlugin.js, PointCloudMaterial.js, both .d.ts), which drops every block marked PATCH (PR #1780, <sha>), then re-apply only the LOCAL PATCH child-box block (next rows). Update the PR #1780 links in potree-lab.mdx ("Why the plugins are vendored"), viewer.mdx and CHANGELOG.The LOCAL PATCH child-box sizing in PointCloudMaterial.js (CHILD_BOXES, the uChildInv/Min/Max/Size uniforms, the shader branch), until #1783 lands.
Garrett changes the maxPointSize default to 50Nothing in code (the viewer sets it from its store); one line in potree-lab.mdx.
A release ships PR #1782 (ADD-skip fix)Delete apps/viewer/src/lib/implicitAddFix.ts and its registration in components/Viewport/ThreeDTRjsViewer.tsx (import line 35, new ImplicitAddRefineFixPlugin() near line 1147) and potree-lab/main.js (lines 37 and 197). Remove the ADD-skip paragraphs in viewer.mdx and potree-lab.mdx.The reproducer repo jo-chemla/3dtiles-samples, useful for regression tests.
#1783 lands (adaptive point size for implicit ADD octrees, in whatever form Garrett picks)Delete apps/viewer/src/lib/addRefinePointSize.ts (AddRefinePointSizePlugin, imported in ThreeDTRjsViewer.tsx line 37) and the LOCAL PATCH child-box block in the vendored PointCloudMaterial.js. vendor/pointcloud/ then has no local change left: delete it and import PointCloudEffectsPlugin from 3d-tiles-renderer/plugins in ThreeDTRjsViewer.tsx (line 39) and potree-lab/main.js (line 35). If it ships as an option on PointCloudEffectsPlugin, pass it from the viewer store.The /stream implicit octree output, which is exactly what the driver consumes.
PR #1780 is squashed or rebased on mergeThe pull/1780/commits/<sha> links in the vendored headers, potree-lab.mdx, viewer.mdx and CHANGELOG then point at commits that no longer exist on master; rewrite them to the merged commit with a (from, to) string-pair pass over those files, as was done when the PR opened.

potree-lab.mdx ("Why the plugins are vendored") lists the same patches from the user's side and must agree with the vendored headers after every re-sync.

Machine-local files you may need (not in git)

PathWhatNeeded for
.local/aggregate-sets/angkor.json, iconem-open.jsonSet manifests with Iconem share links ({label, provider, attribution, entries})the Angkor / Iconem demo pills; regenerate with scripts/iconem-share-links.mjs (needs ICONEM_EMAIL/ICONEM_PASSWORD)
.local/aggregate-sets/iconem.json (692 entries), iconem-public.jsonFull platform manifest and the public subsetsame
.local/tile-server.envVEXCEL_API_KEY=…the Vexcel cities in world
.local/3DTilesRendererJSUpstream clone with the fork branchesupstream PR follow-ups
.local/addskip-harness.mjs, addskip-diag.mjs, addskip-tree.mjs, src-loader.mjsHeadless 3DTRjs traversal checksreproducing #1781
C:\Users\jonathan\AppData\Local\Temp\3dtiles-samples-repoWorking copy of the samples repoadding samples (or re-clone from GitHub)

Copy .local/ from this worktree (C:\Users\jonathan\.t3\worktrees\3d-tiles-converters\t3code-44db18b4\.local) into the new checkout; the server reads .local/tile-server.env and .local/aggregate-sets/ relative to the repo root (AGGREGATE_SETS_DIR overrides).

Running

pnpm install
npm run dev            # viewer + docs + tile server (port 3001)
node packages/tile-server/server.js --port 3001
node packages/convert/cli.js export <tileset-url> <outDir> --keep-implicit

On this page