個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證Open, hackable 3d digital twin builder that supports 3d gaussian splatting, 360 images, and vfx
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗SPHR is an open source 3D space viewer you can host yourself. It is built for lidar scans, 3D Gaussian Splatting (3DGS) captures, and 360 image or video tours, and it runs entirely in the browser. Clone it, point it at your own scans, and serve tours from your own domain.
Self-host SPHR with this repository, or use paid hosting at spacery.dev.
This branch is the Next.js + Three.js migration. It removes the old separate backend requirement and ships as a client-rendered viewer that can load a default demo, a remote JSON config, or embedded bootstrap data from a host page.
https://github.com/user-attachments/assets/169c7729-e4d7-4889-99d2-42d81e33a6d8
https://github.com/user-attachments/assets/2a181774-616f-445d-8eed-7d4ed589bd88
Import a Matterport export ZIP or E57 into a complete local tour:
python3 -m venv .venv-matterport
.venv-matterport/bin/pip install -r scripts/matterport/requirements.txt
npm run import:matterport -- --e57 /path/to/export.zip
npm run dev
Open / to browse thumbnails, search, sort and copy permanent scene links. /library
redirects to this collection. See collection and hosting.
The importer derives image orientation from camera
poses, preserves meters, fuses measured depth into a mesh of at most 50,000 triangles,
and validates every scan before publishing. See the migration guide
for configuration, geometry conventions, quality checks, and output files.
The reworked SPHR is centered on 3D Gaussian Splatting. The runtime can load splat assets or 360 images, etc directly in the browser, place them in a Three.js scene, animate camera movement through the capture, and layer guided tour text, UI controls, skyboxes, annotations, models, and effects over the scene.
SPHR uses @sparkjsdev/spark for splat rendering. The current splat layer supports:
.splat, .ply, .spz, .ksplat, .sog, and .rad sourcesfetchExample splat config:
{
"space": {
"title": "Research Garden Capture",
"type": "splat",
"space_data": {
"noPanos": true,
"initialPosition": { "x": 4, "y": 1.5, "z": 4 },
"initialRotation": { "azimuth": 0, "polar": 90 },
"splats": [
{
"id": "garden",
"url": "https://your-asset-host.example/captures/garden.splat",
"fileType": "splat",
"position": [0, 2.6, 0],
"rotation": [-2.56518, -2.66973, 0.2615546],
"scale": 1,
"lod": false,
"reveal": true
}
]
}
}
}
Large splat files are intentionally not meant to live in git. Host captures in object storage, a CDN, a research artifact mirror, or a local static directory that is excluded from version control.
SPHR currently supports these runtime layers:
SparkSplatLayerPanoramaLayerIiifImageLayerSceneGraphLayerAnnotationLayerThe runtime is not a visual authoring tool. It is the viewer/runtime that renders a structured SPHR scene.
Install dependencies:
npm install
Run the Next.js dev server:
npm run dev
Open http://localhost:3000.
Build and serve a production build:
npm run build
npm run start
Run TypeScript validation:
npm run typecheck
npm run start is for production builds. Use npm run dev while developing.
To open your own capture:
.splat, .ply, .spz, .ksplat, .sog, or .rad.space.type of splat and a space.space_data.splats entry./?config=/path/to/bootstrap.json.Useful prompts for coding agents:
Find an openly available 3D Gaussian Splatting research capture with a downloadable .splat, .ply, .spz, .ksplat, .sog, or .rad asset. Confirm the license and whether the URL is browser-fetchable, then generate a SPHR bootstrap JSON that opens it.
Use the Garden scene from recent 3DGS research as the target scene. Locate or prepare a compatible splat asset, keep large binaries out of git, and wire SPHR to it through ?config with correct position, rotation, scale, and optional skybox settings.
Open my local 3DGS capture in SPHR. Inspect the asset format, serve it from an ignored local static path or external asset host, create a bootstrap JSON, and tune the camera start position until the scene opens correctly.
The homepage lists imported scenes. A /s/<sceneId>/<title-slug> route selects a package
by its saved ID and passes its config to components/SphrApp.tsx. Older title slugs
redirect to the current title. Existing query-based scene URLs remain supported.
Inside the viewer, loadBootstrapData() from lib/bootstrap.ts resolves data in this order:
?config=/path/to/bootstrap.jsonwindow.__SPHR_BOOTSTRAP__space_data, tour_data, ordered_spaces_data, and ui_data?demo=garden opens the bundled demo)The recommended integration path is a single bootstrap JSON file:
{
"space": {
"id": "my-space",
"title": "My Space",
"type": "splat",
"mesh": "/models/dollhouse.glb",
"space_data": {
"initialPosition": { "x": 0, "y": 1.6, "z": 4 },
"initialRotation": { "azimuth": 0, "polar": 0 },
"splats": [
{
"id": "capture",
"url": "/captures/scene.splat",
"scale": 1
}
],
"sceneGraph": []
}
},
"tour": {
"id": "my-tour",
"title": "My Tour",
"tour_data": {
"defaultShowText": true,
"spaces": [
{
"id": "my-space",
"title": "My Space",
"tourpoints": [
{
"viewMode": "FPV",
"targetType": "FREE",
"text": "Start here.",
"position": { "x": 0, "y": 1.6, "z": 4 },
"rotation": { "azimuth": 0, "polar": 0 },
"zoom": 0
}
]
}
]
}
},
"ui": {
"titlePart1": "SPHR",
"titlePart2": "Demo",
"enterButtonText": "Enter",
"exploreButtonText": "Explore"
}
}
The authoritative schema lives in lib/types.ts.
SPHR also supports classic 360-image tours. A 360 space is defined as a set of nodes. Each node has a camera position and either an equirectangular image, six cube faces, or a texture template that resolves to cube faces.
Minimal node example:
{
"space": {
"title": "360 Tour",
"type": "spaces",
"space_data": {
"initialNode": "scan-000",
"nodes": [
{
"uuid": "scan-000",
"image": "/panos/scan-000.jpg",
"position": { "x": 0, "y": 1.6, "z": 0 },
"floorPosition": { "x": 0, "y": 0, "z": 0 },
"rotation": { "x": 0, "y": 0, "z": 0 }
},
{
"uuid": "scan-001",
"faces": [
"/panos/scan-001/face0.jpg",
"/panos/scan-001/face1.jpg",
"/panos/scan-001/face2.jpg",
"/panos/scan-001/face3.jpg",
"/panos/scan-001/face4.jpg",
"/panos/scan-001/face5.jpg"
],
"position": { "x": 2.5, "y": 1.6, "z": 0 },
"floorPosition": { "x": 2.5, "y": 0, "z": 0 },
"rotation": { "x": 0, "y": 0, "z": 0 }
}
]
}
}
}
The basic 360 transition crossfades between the outgoing panorama and the incoming panorama while the camera animates to the next node.
SPHR also includes a stronger mesh-based transition for moving between 360 images. During navigation, SphrRuntime captures the outgoing panorama into a WebGLCubeRenderTarget with a CubeCamera. That cube texture is temporarily applied to configured scene graph meshes, usually a low-poly dollhouse or scan mesh, while the main camera flies to the next node. The transition mesh fades out as the new panorama becomes active. This makes the movement feel spatial instead of just cutting between two photos.
Transition config example:
{
"space_data": {
"navigationTransition": {
"enabled": true,
"meshIds": ["dollhouse"],
"opacity": 0.2,
"meshFadeMs": 400,
"navigationMs": 1100,
"cubeRenderTargetSize": 2048
},
"sceneGraph": [
{
"id": "dollhouse",
"type": "model",
"file": "/models/dollhouse.glb",
"visible": true,
"persistent": true,
"raycast": true,
"fpvOpacity": 0,
"orbitOpacity": 1,
"transitionMesh": true,
"transitionOpacity": 0.2,
"transitionFadeMs": 400,
"transitionTexture": "cube-render-target"
}
]
}
}
For this transition to run, the space needs:
navigationTransition.enabled not set to falseSet noPanos: true for splat-only spaces where panorama rendering should be disabled.
Tours are arrays of spaces and tourpoints. A tourpoint can move the camera, switch view mode, show text, reveal models, show annotations, play sounds, or trigger runtime modes through the extra field.
Common tourpoint fields:
viewMode: FPV or ORBITtargetType: NODE, FREE, or MODELnodeUUID: node to navigate to in a 360 tourposition: free camera position for splat or free-flight pointsrotation: camera azimuth and polar angleszoom: camera FOV adjustmenttext and secondaryText: guided tour copymodels: scene graph IDs to show at this stepannotations or overlays: annotation IDs to show at this stepsounds: audio IDs to play at this stepextra: runtime mode such as nightMode, shrinkToPoints, or projectToSplatsThe scene graph lets a tour add persistent or step-specific 3D content around the main capture.
Supported node uses include:
Transforms use arrays for scene graph nodes:
{
"id": "artifact",
"type": "model",
"file": "/models/artifact.glb",
"position": [0, 1.2, -2],
"rotation": [0, 0.4, 0],
"scale": 1,
"visible": false,
"raycast": true
}
MIT, but if this is useful to you, please cite this repo because it helps the work continue.
@misc{hollis2024sphr,
author = {Luke Hollis},
title = {SPHR - Spatial Human Reality in a web browser},
year = {2024},
publisher = {GitHub},
journal = {GitHub repository},
howpublished = {\url{https://github.com/lukehollis/sphr}}
}