SPHR is an open-source virtual tour builder that enables the creation of hackable and customizable 3D spaces shared in web browsers.
Built with Three.js, it allows you to build interactive virtual experiences with full control over the environment, transitions, and user interactions.
compressed_sphr_example_1.mp4
- Tomb of Nefetari - Basic
- Garden dataset - 3d Gaussian Splatting using mkkellogg/GaussianSplats3D
- Great Sphinx of Giza - Matterport Integration
- Tomb of Ramesses I - More custom vfx
- Museum of the Ancient Near East - Custom vfx / video player
I'm just extracting the frontend from my current implmentation and making some features more modular and hackable. More to come.
- Custom 3D space navigation and transitions
- Support for multiple viewing modes (First Person, Orbit)
- Integration with Matterport spaces
- Customizable tour points and annotations
- Mobile-responsive design
- Multi-language support
compressed_sphr_360_viewer_example.mp4
Any sort of equirectangular 360 image can be used and displayed in the EnvCube component, but greater than 8k resolution is recommended. EnvCube.js
There are two envCubes to support transition between the visible 360 image and the next that is navigated to. More on this in a later section.
In this implementation, to progressively load low-to-high resolution textures on the faces of the cube, I've used a IIIF image server for interoperability between projects. I'll remove this in future versions.
compressed_sphr_cursor_example.mp4
One of the most essential pieces of this implementation is the cursor that renders on the 3d mesh of the space but appears on the top of the 360 images. This is where your users get the photorealistic 3d experience, interacting with the 3d mesh but viewing the 360 images.
You can see the current implementation here: Cursor.js. There are many optimization to be made with the cursor, but it is currently functional as seen in the demos, and can be used as a starting point for your own custom cursor.
compressed_sphr_dollhouse_example.mp4
The dollhouse is the low resolution version of a 3d capture of your space Dollhouse.js
It's used for cursor interactions and the Orbit view mode. I generally aim for less than 50k verts in my dollhouse and less than 2MB in texture size, but you can use much larger if it's important for you.
compressed_sphr_navigation_example.mp4
This is a complex interaction that has little documentation in other place online--and one of the main reasons why I thought it would be useful to release this code.
When navigating between two 360 images, the main camera lerps between the position of your first 360 image and second 360 image, and uses a WebGLCubeRenderTarget to render the transition onto the Environment Map of the Dollhouse to simulate movement between two points.
This is an atypical custom use of the envMap, more here at (MeshBasicMaterial](https://threejs.org/docs/#api/en/materials/MeshBasicMaterial). The current implementation is memory inefficient and requires further work in custom shader development.
compressed_sphr_model_example.mp4
Unlike other tour builder software, this implementation offers a fully customizable scene graph to allow for changing between spaces and items in focus. You can customize this in the space and tour files in the next section.
You can see both SceneGraph.js for 3d models and AnnotationGraph.js for 2d annotations such as images and video embedded in your scenes.
To build your spaces and tours, reference the example_space.json and [example_tour.json] in the data
directory.
These use the Nefertari dataset to demonstrate the expected format of the data required by the frontend.
Each node in the nodes
array represents a viewpoint in the 3D space and contains:
uuid
: Unique identifier for the nodeimage
: Path to the 360° image for this viewpointindex
: Numeric index of the nodeposition
: 3D coordinates (x,y,z) for camera positionrotation
: Rotation angles (x,y,z) in radiansresolution
: Image resolution (e.g. "4096")floorPosition
: 3D coordinates (x,y,z) for position on floor
The sceneSettings
object contains configuration for:
scale
: Scale factor for node groupoffsetPosition
: Position offset (x,y,z)offsetRotation
: Rotation offset (x,y,z)
scale
: Scale factor for dollhouse modeloffsetPosition
: Position offset (x,y,z)offsetRotation
: Rotation offset (x,y,z)
offsetPosition
: Global position offsetoffsetRotation
: Global rotation offset
initialNode
: UUID of starting nodeinitialRotation
: Starting camera rotationpolar
: Polar angle in degreesazimuth
: Azimuth angle in degrees
This format allows defining a complete 3D space with multiple viewpoints, their positions, rotations, and global scene settings. The data is used by the application to render the 3D environment and handle navigation between viewpoints.
The audio
object defines different audio tracks and their settings:
start
: Audio played at tour startdefault
: Background music/audionavigate
: Sound effect for navigation Each audio entry contains:url
: Path to audio fileoptions
:loop
: Boolean for loopingvolume
: Value between 0-1autoplay
: Boolean to autoplay
Each space in the spaces
array contains:
id
: Unique identifier for the spaceurl
: URL to the space (optional)type
: Type of space (e.g. "spaces")title
: Display title for the spacetourpoints
: Array of navigation points
Each tourpoint defines a stop in the tour:
pan
: Direction of camera movement ("left", "right")text
: Main descriptive textzoom
: Camera zoom level (0-100)files
: Array of associated filesmodels
: Array of 3D model IDs to displaysounds
: Array of audio IDs to playnodeUUID
: ID of the node to move torotation
: Camera rotationpolar
: Vertical angle in degreesazimuth
: Horizontal angle in degrees
viewMode
: View mode ("FPV" or "ORBIT")targetType
: Type of target ("NODE" or "MODEL")annotations
: Array of annotationstextPosition
: Position of text overlaysecondaryText
: Additional text (optional)
Array of 3D models that can be shown during the tour. Each model has:
id
: Unique identifierfile
: URL to model filetype
: Type of asset ("model")scale
: Array of [x,y,z] scale factorsfileType
: Format of model fileisSketch
: Boolean for sketch renderingposition
: Array of [x,y,z] coordinatesrotation
: Array of [x,y,z] rotation angles
autoplay
: Boolean to auto-advance tournextTour
: ID of next tour or "random"defaultShowText
: Boolean to show text by default
compressed_sphr_gaussian_splats.mp4
This supports out of the box FPV exploration of 3d Gaussian Splats using @mkkellogg's excellent Three.js splat implementation and adding the custom cursor and tour support.
Building for different languages: You can build for a specific language by setting the LANG environment variable:
LANG=en npm run build # for English
LANG=ar npm run build # for Arabic
LANG=es npm run build # for Spanish
- Clone the repository
- Install dependencies:
npm install
- Start development server:
npm run start
- Build for production:
npm run build
The project is designed to be highly customizable. You can:
- Add custom scene effects and transitions
- Implement your own tour navigation logic
- Create custom UI components
- Extend the annotation system
- Add new language support
MIT, but if this is useful to you, I request that you 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}}
}