{"id":51037970,"url":"https://github.com/n-engine/3dtiles-viewer","last_synced_at":"2026-06-22T08:01:51.345Z","repository":{"id":366455004,"uuid":"1264440618","full_name":"n-engine/3dtiles-viewer","owner":"n-engine","description":"A lean, native C++ 3D Tiles viewer.","archived":false,"fork":false,"pushed_at":"2026-06-21T22:09:57.000Z","size":3996,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-22T00:04:49.440Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/n-engine.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-09T22:17:28.000Z","updated_at":"2026-06-21T22:10:00.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/n-engine/3dtiles-viewer","commit_stats":null,"previous_names":["n-engine/3dtiles-viewer"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/n-engine/3dtiles-viewer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/n-engine%2F3dtiles-viewer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/n-engine%2F3dtiles-viewer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/n-engine%2F3dtiles-viewer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/n-engine%2F3dtiles-viewer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/n-engine","download_url":"https://codeload.github.com/n-engine/3dtiles-viewer/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/n-engine%2F3dtiles-viewer/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34639715,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-22T02:00:06.391Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-22T08:01:50.394Z","updated_at":"2026-06-22T08:01:51.339Z","avatar_url":"https://github.com/n-engine.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 3dtiles-viewer\n\n[![CI](https://github.com/n-engine/3dtiles-viewer/actions/workflows/ci.yml/badge.svg)](https://github.com/n-engine/3dtiles-viewer/actions/workflows/ci.yml)\n[![License: Apache-2.0 OR MIT](https://img.shields.io/badge/license-Apache--2.0%20OR%20MIT-blue.svg)](#license)\n![C++17](https://img.shields.io/badge/C%2B%2B-17-blue.svg)\n\n![Angkor Wat photogrammetry streamed in 3dtiles-viewer](screenshots/angkor-wat.png)\n\nA lean, native C++ 3D Tiles viewer for Linux (Wayland and X11, via GLFW). Loads a\n`tileset.json` (3D Tiles 1.0 with the `3DTILES_content_gltf` extension and 3D\nTiles 1.1 native glTF), walks the tile tree with screen-space-error driven LOD\nselection, frustum-culls off-screen nodes, streams `.glb` leaves on demand via a\nworker thread pool (closest tiles first), and renders the scene under a free-fly\ncamera. The GL context is negotiated down a version ladder (desktop core\n3.3..4.6, or GL ES 3.0 via `--gles`), so it runs on real GPUs and on software /\nvirtualized stacks (llvmpipe, virgl) alike.\n\nDesigned for:\n\n- Offline desktop preview of photogrammetry tilesets (drone scans, aerial LiDAR,\n  Reality Capture / Pix4D outputs).\n- Embedded touch surfaces where a thin, no-runtime viewer is preferable to a\n  web-engine stack -- there is a built-in touchscreen control overlay (two\n  panels + 4-way D-pads + auto-hide after 30 s of idle).\n- Cross-compiling to a portable static binary against musl (see\n  `scripts/build-static.sh`).\n\nThe renderer is intentionally simple: hemisphere ambient + sun NdL + cheap\nspecular, full sRGB pipeline in the fragment shader, area-weighted face-normal\nsynthesis when the source mesh ships no per-vertex normals (common in\nphotogrammetry exports).\n\n## A note on untrusted data\n\nThe viewer can load `tileset.json` and `.glb` from arbitrary URLs, so it treats\nthat content as untrusted: the parsers are hardened to skip a malformed (or\nmalicious) tile with a logged reason instead of crashing. If you point it at data\nyou do not control, that is the intended safety net. The how is in the source.\n\n## Build\n\n### Native (recommended for development)\n\nRequirements: `cmake \u003e= 3.16`, `pkg-config`, GCC/Clang with C++17, plus\nsystem packages:\n\n```\nglfw3 libepoxy egl wayland-client libcurl   # libcurl optional, see below\n```\n\nOn Debian/Ubuntu:\n\n```\nsudo apt install build-essential cmake pkg-config \\\n    libglfw3-dev libepoxy-dev libegl-dev libwayland-dev libcurl4-openssl-dev\n```\n\nThen:\n\n```\ncmake -B build\ncmake --build build -j\n./build/3dtiles-viewer --mode file --source path/to/tileset.json\n```\n\nTo stream a public hosted tileset:\n\n```\n./build/3dtiles-viewer --mode http \\\n    --source https://storage.googleapis.com/open-cogs/planet-stac/angkor-wat/3d-geofox.ai/3DTiles/tileset.json\n```\n\n(Angkor Wat photogrammetry, ~5k tiles; the window opens immediately and\ntiles stream in as you fly around.)\n\n### Build options\n\n| Option              | Default | Effect                                                        |\n|---------------------|---------|---------------------------------------------------------------|\n| `ENABLE_HTTP_LOADER`| `ON`    | Build the libcurl-backed `--mode http` loader.                |\n| `ENABLE_WEBP_TEXTURE`| `ON`   | Decode `EXT_texture_webp` textures via libwebp.               |\n| `WAYLAND_ONLY`      | `OFF`   | Hard-fail at startup if GLFW selects anything other than Wayland. |\n| `BUILD_STATIC_MUSL` | `OFF`   | Static-link via the musl-cross toolchain (used by `build-static.sh`). |\n| `BUILD_TESTS`       | `OFF`   | Build the unit tests; run them with `ctest`.                  |\n\n### Portable static binary\n\n`scripts/build-static.sh` cross-compiles the viewer, GLFW, libepoxy,\nwayland-client and friends against a musl-cross toolchain so the result runs\non any modern Linux without per-distro `.so` chasing. See the script header\nfor the toolchain expectations.\n\n### Tests\n\nThe pure-logic units (currently the RFC 3986 URI resolver) have unit tests that\nneed no GL, network, or filesystem:\n\n```\ncmake -B build -DBUILD_TESTS=ON\ncmake --build build -j\nctest --test-dir build --output-on-failure\n```\n\nCI (`.github/workflows/ci.yml`) builds the GCC and Clang matrix with the HTTP\nloader both on and off, runs the tests, and enforces `clang-format`.\n\n## Usage\n\n```\n3dtiles-viewer --mode {file|http} --source \u003ctileset.json | URL\u003e [options]\n```\n\n| Flag             | Default  | Effect                                                       |\n|------------------|----------|--------------------------------------------------------------|\n| `--width N`      | `1600`   | Initial window width in pixels. |\n| `--height N`     | `1000`   | Initial window height in pixels. |\n| `--fullscreen`   | windowed | Open full-screen on the primary monitor. |\n| `--sse-pixels N` | `16`     | Refine into children when the projected geometric error exceeds N pixels. Lower values pull in more detail at the cost of more I/O and VRAM. |\n| `--max-leaves N` | `256`    | LRU cap on resident GPU tiles. Pass `0` to disable the cap (useful on machines with plenty of VRAM and small tilesets). |\n| `--no-cull`      | cull on  | Disable frustum culling and traverse/draw off-screen tiles too (handy for measuring the cull win or debugging traversal). |\n| `--gles`         | desktop  | Request a GL ES 3.0 context instead of desktop core (embedded / mobile GPUs). |\n| `--no-msaa`      | 4x on    | Disable MSAA. Recommended on software / VM rasterizers (llvmpipe, virgl) where multisampling is costly. |\n| `--version`      |          | Print the version and exit. |\n\nControls (keyboard + mouse):\n\n- WASD / arrow keys: translate\n- Mouse drag: orbit\n- Mouse wheel: zoom / speed\n- `Home`: reset camera\n- `F`: fit-to-view\n\nControls (touch overlay, top-right OBJECT / bottom-right CAMERA):\n\n- Coloured buttons drive object yaw/pitch (top panel) and camera dolly/lift\n  (bottom panel).\n- 4-way D-pads under each panel drive the corresponding translation/orbit.\n- Bottom-left strip: `Home`, `Fit`, camera speed `-` / `+`.\n\nThe overlay fades out after 30 s of inactivity and reappears on the next\ntouch / click. Override the timeout with `VIEWER_UI_HIDE_AFTER=\u003cseconds\u003e`\n(`0` disables the auto-hide).\n\n## Project layout\n\n```\nsrc/                  C++ source\ndata/shaders/         GLSL shaders (copied next to the binary at build time)\nthird_party/          Vendored header-only deps (glm, stb, cgltf, nlohmann,\n                      Dear ImGui)\ncmake/                CMake toolchain files\nscripts/              build-static.sh (musl cross-build helper)\n```\n\n## LOD streaming\n\nThe renderer walks the tile tree every frame and computes a screen-space\nerror for each node:\n\n```\nsse_pixels = geometric_error * viewport_height / (2 * distance * tan(fov_y / 2))\n```\n\nWhen `sse_pixels \u003e --sse-pixels`, the node is refined into its children;\notherwise it is drawn and traversal stops. The `refine` field of the spec is\nhonoured (`REPLACE` skips the parent, `ADD` keeps it).\n\nBefore the error test, each node's bounding sphere is checked against the view\nfrustum (Gribb-Hartmann plane extraction); a node that is fully off-screen is\nskipped together with its entire subtree, so off-screen detail is never\ntraversed or fetched. Pass `--no-cull` to disable this.\n\nTile fetches go through a 4-thread pool. Worker threads pull bytes via the\nselected loader (`file` or `http`); the render thread parses glTF and uploads\nGL objects up to 8 tiles per frame. Tiles not yet resident are simply skipped\nfor that frame -- the camera can fly freely while the world loads in.\n\nFetches are ordered by camera distance, so the tiles you are looking at arrive\nbefore the ones behind you; a tile still waiting in the queue is re-prioritized\nas the camera moves.\n\nThe resident set is bounded by an LRU cache (`--max-leaves`). Eviction frees\nboth CPU and GPU memory; tiles touched in the current frame are never evicted.\n\n## Status\n\nPre-release (v0.2). LOD streaming, hierarchical frustum culling and\ndistance-prioritized fetching are in place. The GL context is negotiated at\nstartup down a version ladder (desktop core 3.3..4.6, or GL ES 3.0 via\n`--gles`) and the renderer adapts to what the driver reports -- so it also runs\non software / virtualized stacks (llvmpipe, virgl) instead of hard-requiring a\nsingle GL version. Still on the to-do list:\n\n- Region-type bounding volumes are over-approximated to a generous sphere;\n  proper WGS84 -\u003e ECEF math is a follow-up.\n- Occlusion culling (frustum + distance + SSE culling only, today).\n- Loader priority is a fetch-ordering hint, not a cancel: a tile already handed\n  to a worker finishes its fetch even if it scrolls off-screen meanwhile.\n\nThe codebase is small enough that the source itself is the canonical\ndocumentation; this README is the entry point, the rest is in the comments.\n\n## Roadmap\n\nSee [ROADMAP.md](ROADMAP.md) for what has shipped and what is planned: stability\nwork, fuzzing, and features -- an online path tracer, live vehicle position\ninjection, navmesh routing, and scene-object / UI plugins.\n\n## Contributing\n\nContributions are welcome -- see [CONTRIBUTING.md](CONTRIBUTING.md). In short:\nuntrusted input is the threat model, portability beats GL features, and\n`clang-format` plus the test suite gate CI.\n\n## License\n\nDual-licensed under [Apache-2.0](LICENSE-APACHE) OR [MIT](LICENSE-MIT) at\nyour choice.\n\nVendored third-party libraries keep their own licenses -- see each subtree\nunder `third_party/`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fn-engine%2F3dtiles-viewer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fn-engine%2F3dtiles-viewer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fn-engine%2F3dtiles-viewer/lists"}