mesh-avatar-studio
일러스트를 코딩 에이전트와 로컬 편집기로 2D 메쉬 애니메이션 아바타로 변환
수백만 스플랫, 10GB 이상 PLY 파일을 GPU에서 SuperSplat용 스트리밍 SOG .zip으로 레벨·압축 변환
Convert huge 3D Gaussian Splatting PLY files (hundreds of millions of splats, 10+ GB) into a SuperSplat-ready Streamed SOG .zip with real levels of detail and SOG compression — on your own GPU, in you
디자인TypeScript · PythonGitHub @AndriiShramko온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기Convert giant 3D Gaussian Splatting PLY (100M+ splats, 10+ GB) into a SuperSplat-ready Streamed SOG .zip with real LODs, in your browser on your own GPU (WebGPU). No upload, no install. By Andrii Shramko.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Shramko SOG LOD Converter — giant PLY → Streamed SOG with real LODs for SuperSplat, in your browser
Convert huge 3D Gaussian Splatting .ply files (hundreds of millions of splats, 10+ GB) into a SuperSplat-ready Streamed SOG .zip with real levels of detail (LOD) and SOG compression — on your own GPU and CPU, in the browser. Nothing is uploaded, nothing to install.README 전문 보기 ↗Convert huge 3D Gaussian Splatting .ply files (hundreds of millions of splats, 10+ GB) into a SuperSplat-ready Streamed SOG .zip with real levels of detail (LOD) and SOG compression — on your own GPU and CPU, in the browser. Nothing is uploaded, nothing to install.
Live tool: https://sog.flyreelstudio.eu · Author: Andrii Shramko · License: MIT
Status (2 Oct 2026): live at https://sog.flyreelstudio.eu. Verified end to end in Chrome on a 259-million-splat / 17.6 GB drone city scan: 10 levels of detail, 5.9 GB archive, 1 h 53 min on an RTX 4090 workstation, archive checked by three independent readers. See Measured.
New in 1.2: a queue — add file after file (each with its own orientation and preset), choose an output folder once, and they are converted one by one, e.g. overnight; a failed file does not stop the queue, and a closed tab resumes with one click.
New in 1.1: a preview to set the scene's orientation before converting (scans from different tools come out on their side or upside down — SuperSplat cannot rotate an uploaded streamed scene), and levels down to ≤ 100K splats by default, so city-scale scenes start light on VR headsets and phones (0.5–1M splat budgets).
superspl.at accepts at most 10 GB per upload. City-scale drone scans are bigger than that: the test scan for this tool is 258,951,032 splats / 17.6 GB. SuperSplat streams large scenes as Streamed SOG — a lod-meta.json spatial tree plus many small SOG chunks at several levels of detail — and it publishes a pre-built Streamed SOG .zip exactly as uploaded.
Two problems kept coming up:
splat-transform CLI and a two-step command per level.lodLevels: 1.)This tool fixes both, in a browser tab.
1 + ⌈log₂(N / 1M)⌉ levels, the policy superspl.at uses when it generates LODs on its servers (10 levels for 259M).ArrayBuffer at ~2 GiB and a tab at ~16 GB (measured in Chrome 154). The scene is split with a k-d tree into spatial tiles sized to the RAM you allow; a few sequential passes over the file load them. Each tile is Z-order (Morton) sorted in memory.lod-meta.json at the root; the tile trees are joined under the same k-d split. When done, the archive is read back from disk and verified: every level, every chunk and texture, splat counts, and the file names superspl.at's upload form accepts.Your file never leaves your computer. The server only delivers the static page (plus a tiny API for feedback and anonymous error reports).
.ply. The page reads the header instantly and shows the level plan, estimated time and archive size.<name>-SSOG.zip, keep the tab open — or click Add to queue and go on with the next file (see Queue). Progress, ETA, the current step and a live log are shown; if something fails, the error and its step are shown and (if you allow) an anonymous report is sent so it can be fixed..zip at superspl.at → Upload.| Setting | Default | What it does |
|---|---|---|
| Keep per level | 0.5 | Fraction of splats each coarser level keeps (SuperSplat's halving). |
| Stop at | 100,000 | No new level once a level holds this many splats or fewer (1,000,000 = SuperSplat's own policy). |
| Max levels | auto (≤ 24) | Upper bound on the number of levels. |
| Simplification | adaptive | Allocates removal by local error — better on skies / mixed scale; ~2.4× slower than uniform. |
| SH bands | keep | Drop view-dependent colour bands for a smaller archive. |
| SH iterations | 10 | k-means iterations for SH palettes (only with SH > 0). |
| WebP effort | libwebp default | Lossless WebP effort 0–9. |
| Remove NaN/Inf | on | Broken splats would stop the LOD writer. |
| Chunk splats / size / min | 256K / 16 m / 16K | How the scene is cut into streamable chunks (SuperSplat uses 512K / 16 m / 8K). |
| Orientation | per file | Rotation in degrees (same convention as splat-transform -r) set on the preview, plus optional centring (ground at 0). |
| RAM to use | 8 GB (auto) | Tile size and number of reading passes follow from it. |
| GPU (WebGPU) | on | ~4× faster decimation than CPU. |
| Encoder threads | auto (≤ 4) | Parallel WebP/SOG encoders. |
Pick the kind of scene instead of guessing settings. A preset sets only what the file controls; the splat budget, LOD distances and penalties belong to the viewer (SuperSplat uses 1M splats on phones and Quest/Pico in XR, 2–4M on desktops; standalone headsets run smoothest at ~0.5M).
| Preset | Coarsest level ≤ | Simplification | SH | Chunk K / size / min | Best for |
|---|---|---|---|---|---|
| All devices (default) | 100,000 | adaptive | keep | 256 / 16 m / 16 | One archive for desktops, phones and VR headsets |
| City from a drone | 100,000 | adaptive | none | 256 / 32 m / 32 | Large areas seen from above |
| Streets at eye level | 100,000 | adaptive | keep | 256 / 16 m / 8 | Walking through streets and squares |
| Rooms & interiors | 100,000 | adaptive | keep | 256 / 8 m / 4 | Inside buildings, room by room |
| Object / small scan | 100,000 | uniform | keep | 256 / 16 m / 8 | A statue, a car, one building |
| Light — phones & VR | 50,000 | adaptive | none | 128 / 16 m / 16 | Old phones, standalone headsets first |
| SuperSplat standard | 1,000,000 | uniform | keep | 512 / 16 m / 8 | Exactly what superspl.at builds itself; desktops |
Every level keeps 50% of the previous one in all presets. Why these values (measured 2026-10-02 with the PlayCanvas engine 2.22.6 LOD classes on public superspl.at manifests and on a 259M-splat drone city scan):
chunkMin/chunkExtent; 32 m / 32K gives 4× fewer nodes (manifest 31 → 7.9 MB, LOD pass ~5× cheaper) with identical views, flying down to street level included.<name>-SSOG.zip without further dialogs; an existing file is never overwritten (-2, -3 … are added).tools/bg-test.mjs, plain Chrome without test switches).Verified (tools/queue.mjs): 4 files (two presets, two orientations, one broken file) with a page reload after the first — statuses done, done, failed, done, names -SSOG.zip, -SSOG-2.zip, -SSOG-3.zip, every archive passes verify-zip, and the queued result is identical to a single conversion of the same file (every entry's CRC equal; only the generator string differs).
Scans come out of different tools in different orientations (Z up, Y down, …) — there is no single right rotation, so it is chosen per file on the preview, and remembered in the browser by file name and size.
world = R(you) · Rz(180°) · file, Y up, a grid at ground level. Orbit, zoom, side and top views.splat-transform -r.splat-transform -r -90,0,0 to 0.01 m in every position quantile (apart from the centring shift), and a top-down render shows roofs, the render from below shows only undersides. The Euler math matches the PlayCanvas engine to 1e-8 (tools/test-orientation.ts).| Input | Where | Levels | Time | Archive | Check |
|---|---|---|---|---|---|
| 258,951,032 splats (17.6 GB, SH0), same scan, v1.1: turned −90° X + centred | Chrome 154, RTX 4090, i9-7980XE, RAM to use 12 GB, preset City from a drone (adaptive) | 13 (259M → 63K) | 2 h 51 min (16 tiles, 4 passes; other test runs shared the GPU for part of it) | 6.03 GB (1,853 chunks, 11,119 files, ZIP64) | page read-back ✓, verify-zip.ts ✓, Python zipfile CRC ✓, splat-transform --info → lods: 13 ✓, decoded LOD 8 rendered from above shows roofs, from the side stands upright |
| 258,951,032 splats (17.6 GB, SH0), drone city scan ~1.1 × 0.9 km | Chrome 154, RTX 4090, i9-7980XE, RAM to use 12 GB, preset SuperSplat standard | 10 (259M → 506K) | 1 h 53 min (16 tiles, 4 reading passes) | 5.89 GB (977 chunks, 5,863 files, ZIP64) | page read-back ✓, tools/verify-zip.ts ✓, Python zipfile CRC of every entry ✓, splat-transform --info → lods: 10 ✓ |
| 20,000,000 splats (1.27 GB, SH0) | Chrome 154, RTX 4090, i9-7980XE, 12 GB RAM setting | 6 (20M → 625K) | 8 min 23 s | 465 MB | read-back ✓, splat-transform --info ✓ |
| 2,000,000 splats (130 MB, SH0), turned −90° X + centred | same, preset All devices (adaptive) | 6 (2M → 62.5K) | 1 min 04 s | 47.8 MB | read-back ✓, verify-zip.ts ✓, upright top-down render ✓ |
| 2,000,000 splats (130 MB, SH0) | same, SuperSplat standard | 2 | 37 s | 36 MB | read-back ✓ |
Per-level counts of the 259M run: 258,951,032 / 129,475,520 / 64,737,762 / 32,368,885 / 16,184,446 / 8,092,227 / 4,046,119 / 2,023,064 / 1,011,536 / 505,772 — 12.2 bytes per splat over all levels; lod-meta.json 6.35 MB with 9,976 leaves. The time estimate shown before the run was 2 h 06 min.
Round-trip quality on the 2M sample: rendering LOD 0 decoded from the archive vs the source PLY from the same camera — PSNR 49.9 dB (negative control: the same render shifted by 40 px — 16.7 dB).
| This converter | superspl.at upload (Auto LODs) | superspl.at/convert | splat-transform CLI | |
|---|---|---|---|---|
| Largest input | No fixed limit (tiles); tested on 259M splats / 17.6 GB | 10 GB per upload | What fits in one tab | Your RAM |
| Levels of detail | Yes — halving to ≤ 100K (VR-ready) or ≤ 1M like SuperSplat | Yes (server side, ≤ 1M) | No Streamed SOG output | Yes — two manual steps per level |
| Fix orientation | Preview + turn before converting | Not for streamed scenes | — | -r x,y,z |
| Runs on | Your browser (your GPU + CPU) | Their servers | Your browser | Your PC |
| Install | Nothing | Nothing | Nothing | Node.js 22 + npm |
| Output check | Reads the archive back | — | Statistics table | --info |
How can I upload a Gaussian splat PLY larger than 10 GB to SuperSplat?
Convert it here into a Streamed SOG .zip (typically 5–10% of the PLY size) and upload the .zip. The levels of detail are already inside, so SuperSplat publishes it as-is.
Is there a way to make Streamed SOG with LODs without installing Node.js? Yes — this page runs splat-transform in your browser. Everything happens locally.
Why does my Streamed SOG have no levels of detail?
It was built from one PLY without decimated levels: splat-transform scene.ply lod-meta.json writes a single level cut into chunks. Check lodLevels in lod-meta.json — real LODs need it to be > 1. npx tsx tools/verify-zip.ts your.zip reports it.
How many LOD levels should a 3DGS scene have for SuperSplat?
SuperSplat halves the count per level until a level holds ≤ 1M splats: 1 + ⌈log₂(N / 1M)⌉. 100M splats → 8 levels; 259M → 10. For phones and VR headsets go deeper — to ≤ 100K: 259M → 13 levels, a first view of 63K splats.
Can a 250-million-splat Gaussian splat city run on a Quest / VR headset? Yes, if the levels go deep enough: the viewer always draws at least the coarsest level, and headsets run at 0.5–1M splats. With the default All devices preset the coarsest level is ≤ 100K, so the headset starts light and refines only near you.
Can I batch-convert several Gaussian splat PLY files overnight? Yes: add them to the queue one by one (each with its own orientation and preset), press Start the queue, choose a folder once — they are converted one after another, a failure does not stop the rest, and a closed tab resumes with one click.
My Gaussian splat scene is sideways or upside down on SuperSplat. How do I rotate it? Drop the PLY here, turn it on the preview until the ground is at the bottom, convert. The rotation is baked into the Streamed SOG, so SuperSplat shows it upright (its editor cannot rotate an uploaded streamed scene).
Can I convert a 250-million-splat city scan in a browser? Yes — the scene is processed in spatial tiles, so memory stays bounded. It takes hours, not minutes: 259M splats took 1 h 53 min on an RTX 4090 workstation (see Measured).
Is my scan uploaded anywhere? No. Only optional feedback and anonymous error reports (no file, no file name) reach the server.
Can I use the result outside SuperSplat? Yes: unzip it and load lod-meta.json with the PlayCanvas engine's LOD streaming, or read it back with splat-transform.
Works (verified): binary PLY (little/big-endian, SH 0–3) → multi-LOD Streamed SOG .zip; spatial tiling beyond one tab's memory; ZIP64 archives > 4 GB (read back by our verifier and by Python zipfile with CRC check); WebGPU acceleration in Chrome; read-back verification; live progress with ETA; visible errors and anonymous error reports; feedback (bug / idea / cooperation); 4 languages (EN, ES, PL, RU).
Also works (1.2): queue of many files into one folder, auto-retries, resume after a closed tab.
Also works (1.1): orientation preview and per-file rotation baked into the archive; levels down to ≤ 100K (≤ 50K Light) for VR headsets and phones; 7 scene presets.
In progress: publishing the upright 13-level conversion of the 259M-splat test scan on superspl.at (the archive is built and verified).
Next: resume a single file mid-way after a crash (the queue restarts that file today) · optional direct upload to SuperSplat with your API token · separate sky/environment layer · compressed PLY and SPZ input · processing several tiles in parallel on many-core CPUs.
docs/warnings.md and SECURITY.md.git clone https://github.com/AndriiShramko/shramko-sog-lod-converter
cd shramko-sog-lod-converter
npm install # Node.js 22+
npm run dev # http://localhost:5180/en/
npm run build # static site → dist/
Tests:
npx tsx tools/node-convert.ts input.ply out.zip # the same engine under Node (CPU), then verification
npx tsx tools/verify-zip.ts out.zip # check any Streamed SOG zip (exit 1 on problems)
npx tsx tools/test-zip64.ts <dir> && python tools/test-zip64.py <dir> # ZIP64 > 4 GiB, 70k entries
node tools/e2e.mjs input.ply out.zip --mem 12 # real Chrome end to end (Playwright)
python -m unittest discover -s api/tests # feedback / report API
Production runs as two small Docker containers behind nginx-proxy (deploy/): nginx:alpine for the static site and a stdlib-only Python API for feedback and error reports, with tight memory/CPU limits — the conversion never runs on the server. Runbook: deploy/README.md.
Repository layout: web/src/engine/ (pipeline, tiling, Morton sort, ZIP64 writer, LOD merge, verifier, worker), web/src/ui/ (page), api/ (feedback API), deploy/ (Docker, nginx, deploy/rollback scripts), tools/ (tests, reports reader). For AI coding agents: AGENTS.md, AGENT_SETUP.md, SKILL.md, llms.txt.
Andrii Shramko — I scan whole cities and buildings as 3D/4D Gaussian splats with drones and 360° cameras, and build tools around them. I made this converter because my own scans (250M+ splats) did not fit SuperSplat's upload and the existing tools didn't build real LODs.
Open to interesting people and ready to help teams build ambitious projects — scanning, splat pipelines, viewers, VR, partnerships, licensing or funding. Get in touch:
NOTICE.CITATION.cff.