### Start Development Server (npm)
Source: https://context7.com/lukehollis/sphr/llms.txt
Starts the development server for local testing and development. This command typically watches for file changes and enables hot-reloading.
```shell
npm run start
```
--------------------------------
### Install Project Dependencies (npm)
Source: https://context7.com/lukehollis/sphr/llms.txt
Installs all necessary dependencies for the project using npm. Ensure Node.js and npm are installed globally.
```shell
npm install
```
--------------------------------
### Configure SPHR Tour with JSON
Source: https://context7.com/lukehollis/sphr/llms.txt
Defines the interactive tour elements and scene graph for a SPHR experience using JSON. It specifies audio sources, tourpoints with associated text and sounds, and 3D models to be loaded into the scene. This configuration enables guided navigation and enriched scene interactions.
```json
{
"audio": {
"default": {
"url": "https://static.mused.org/sounds/default_oud_96k.mp3",
"options": { "loop": true, "volume": 0.1, "autoplay": false }
},
"navigate": {
"url": "https://static.mused.org/sounds/bassdrum_64k.mp3",
"options": { "loop": false, "volume": 0.1, "autoplay": false }
}
},
"spaces": [
{
"id": "2",
"type": "spaces",
"title": "The Tomb of Nefertari",
"tourpoints": [
{
"text": "Welcome to the tomb of Nefertari",
"zoom": 0,
"models": [],
"sounds": ["default"],
"nodeUUID": "IMG_20231104_065739_00_094",
"rotation": { "polar": -2, "azimuth": 46 },
"viewMode": "FPV",
"targetType": "NODE",
"textPosition": "center"
}
]
}
],
"sceneGraph": [
{
"id": "qau_beadnet_dress",
"file": "https://static.mused.org/beadnet_dress3.glb",
"type": "model",
"scale": [1, 1, 1],
"position": [0, 0, 0],
"rotation": [0, 0, 0],
"fileType": "glb"
}
],
"autoplay": false,
"defaultShowText": true
}
```
--------------------------------
### Cursor Component for 3D Interaction - JavaScript
Source: https://github.com/lukehollis/sphr/blob/main/README.md
The Cursor component renders a visual indicator on the 3D mesh of the virtual space, appearing on top of the 360 images. This component is crucial for providing a photorealistic 3D experience where users interact with the mesh while viewing the images. The current implementation serves as a functional starting point for custom cursors.
```javascript
import { Raycaster, Vector2 } from 'three';
export default class Cursor {
constructor(camera, scene, domElement) {
this.camera = camera;
this.scene = scene;
this.domElement = domElement;
this.raycaster = new Raycaster();
this.mouse = new Vector2();
this.intersectedObject = null;
this.domElement.addEventListener('mousemove', this.onMouseMove.bind(this), false);
}
onMouseMove(event) {
// calculate mouse position in normalized device coordinates (-1 to +1) for both components
this.mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
this.mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
}
update() {
this.raycaster.setFromCamera(this.mouse, this.camera);
const intersects = this.raycaster.intersectObjects(this.scene.children);
if (intersects.length > 0) {
if (this.intersectedObject !== intersects[0].object) {
// New object intersected
if (this.intersectedObject) {
// Optionally remove previous cursor effect
}
this.intersectedObject = intersects[0].object;
// Optionally add new cursor effect
console.log('Intersected:', this.intersectedObject.name);
}
} else {
if (this.intersectedObject) {
// No object intersected now
this.intersectedObject = null;
// Optionally remove cursor effect
}
}
}
}
```
--------------------------------
### Initialize and Run Application Controller
Source: https://context7.com/lukehollis/sphr/llms.txt
Initializes and runs the main application controller for the Sphr project. It manages application lifecycle, initializes space components, preloads textures, handles node loading and navigation, and includes an update loop for rendering.
```javascript
// App.js - Initialize and run the application
import App from './components/App';
const app = new App();
// Initialize space components (EnvCube, Dollhouse, Nodes, Cursor)
app.initSpaceComponents();
// Preload initial node textures
app.preload();
// Load a specific node's textures
app.loadNode(node, () => {
console.log('Node loaded:', node.uuid);
});
// Navigate to a node with face loading check
app.ensureFacesLoadedThenNavigate(targetNode);
// Preload nearest nodes for smoother navigation
app.preloadNearestNodes(currentNode);
// Toggle autoplay for guided tours
app.handleToggleAutoplay();
// Update loop (call in animation frame)
function animate() {
app.update();
requestAnimationFrame(animate);
}
animate();
```
--------------------------------
### Build Project for Production (npm)
Source: https://context7.com/lukehollis/sphr/llms.txt
Builds the project for production, optimizing assets and code. Supports internationalization by setting the LANG environment variable.
```shell
LANG=en npm run build
```
```shell
LANG=ar npm run build
```
```shell
LANG=es npm run build
```
```shell
for lang in en ar es fr de it pt ru ja ko zh-hans tr id hi bn el; do
LANG=$lang npm run build
done
```
--------------------------------
### Handle 3D Mesh Navigation with Dollhouse
Source: https://context7.com/lukehollis/sphr/llms.txt
Manages a low-poly 3D model for cursor interactions and orbit view. It supports showing/hiding the dollhouse, special display during navigation, material restoration, transparency updates, adding/removing occluders, and attaching/detaching transform controls for debugging.
```javascript
// Dollhouse.js - Load and manage dollhouse mesh
import Dollhouse from './components/Dollhouse';
const dollhouse = new Dollhouse();
// Show/hide dollhouse
dollhouse.show();
dollhouse.hide();
// Show during navigation with CubeRenderTarget effect
dollhouse.showForNavigation();
// Restore default materials after navigation
dollhouse.restoreDefaultMaterials();
// Update transparency based on view mode
dollhouse.updateTransparency();
// Add occluders for proper depth rendering in FPV mode
dollhouse.addOccluders();
dollhouse.hideOccluders();
dollhouse.showOccluders();
// Transform controls for editing (debug mode)
dollhouse.attachToTransformControls();
dollhouse.detachFromTransformControls();
// Update in render loop
dollhouse.update();
```
--------------------------------
### Configure SPHR Space with JSON
Source: https://context7.com/lukehollis/sphr/llms.txt
Defines the structure of a virtual space in SPHR using a JSON configuration. It includes details for 360° viewpoint nodes, initial camera settings, and scene adjustments for both general nodes and the dollhouse navigation model. This JSON serves as the primary input for initializing a space.
```json
{
"nodes": [
{
"uuid": "IMG_20231101_074927_00_479",
"image": "spaceshare/IMG_20231101_074927_00_479.jpg",
"index": 0,
"position": { "x": 64.41, "y": 11.99, "z": 3.75 },
"rotation": { "x": -0.467, "y": -1.569, "z": -2.694 },
"resolution": "4096",
"floorPosition": { "x": 64.41, "y": 6.67, "z": 3.75 }
}
],
"initialNode": "IMG_20231104_065739_00_094",
"sceneSettings": {
"nodes": {
"scale": 0.26,
"offsetPosition": { "x": 0, "y": 0, "z": 0 },
"offsetRotation": { "x": 0, "y": 0, "z": 0 }
},
"dollhouse": {
"scale": 1.1,
"offsetPosition": { "x": 8.83, "y": 2.16, "z": 2.26 },
"offsetRotation": { "x": 0, "y": -0.22, "z": 0 }
}
},
"initialRotation": {
"polar": -19.4,
"azimuth": 44.86
}
}
```
--------------------------------
### Manage 360° Image Rendering with EnvCube
Source: https://context7.com/lukehollis/sphr/llms.txt
Manages 360° equirectangular images on cube faces with progressive loading. It handles initialization, crossfade navigation between nodes, updating cube faces, progressive loading to full resolution, fade effects, and an update loop.
```javascript
// EnvCube.js - Create and manage environment cubes
import EnvCube from './components/EnvCube';
// Initialize environment cube manager
const envCubeManager = new EnvCube();
// Access main and outgoing cubes
const mainCube = envCubeManager.envCube;
const outgoingCube = envCubeManager.envCubeOutgoing;
// Navigate between nodes with crossfade
envCubeManager.crossfade(); // Smoothly transitions between nodes
// Update faces for a new node
mainCube.node = newNode;
mainCube.updateFaces();
// Progressive loading: upgrade visible faces to full resolution
const visibleFaces = mainCube.getVisibleFaces();
mainCube.updateFacesFullRes(visibleFaces);
// Fade effects
envCubeManager.fadeOut(() => {
console.log('Fade out complete');
});
envCubeManager.fadeIn(() => {
console.log('Fade in complete');
});
// Update in render loop
envCubeManager.update();
```
--------------------------------
### Manage SPHR State with JavaScript Store
Source: https://context7.com/lukehollis/sphr/llms.txt
Implements global state management for SPHR using a JavaScript Store pattern with an observer mechanism. It allows for retrieving the current application state, updating it, and subscribing to state changes to react to modifications in navigation, current nodes, or viewing modes. Dependencies include the Three.js library for camera and scene initialization.
```javascript
// Store.js - Initialize and manage application state
import Store from './Store';
// Get current state
const { space, camera, scene, currentNode } = Store.getState();
// Update state and notify listeners
Store.setState({
isNavigating: true,
currentNode: newNode,
viewMode: "FPV"
});
// Listen to state changes
Store.listen((newState) => {
console.log('Navigation status:', newState.isNavigating);
console.log('Current node:', newState.currentNode.uuid);
});
// Example: Initial store structure
const initialStore = {
space: spaceConfig.space,
camera: new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight),
scene: new THREE.Scene(),
viewMode: "FPV",
currentNode: initialNode,
isNavigating: false,
zoomLvl: 20,
fov: 90,
tourGuidedMode: true,
materialCache: {},
textures: {}
};
```
--------------------------------
### Transition Between 360 Images using WebGLCubeRenderTarget - JavaScript
Source: https://github.com/lukehollis/sphr/blob/main/README.md
This implementation details a complex interaction for transitioning between two 360-degree images using Three.js. It involves the main camera lerping between positions and utilizing a WebGLCubeRenderTarget to render the transition onto the environment map of the Dollhouse. This technique simulates movement between points and is an atypical use of envMap with MeshBasicMaterial, though it is currently memory inefficient and requires further shader development.
```javascript
import { WebGLCubeRenderTarget, RGBFormat, LinearMipmapLinearFilter } from 'three';
// Assuming 'scene' and 'camera' are available in the scope
// Assuming 'transitionDuration' is defined
let currentCubeRenderTarget = null;
let nextCubeRenderTarget = null;
let transitionStartTime = null;
function setupTransition(startImageUrl, endImageUrl, scene, camera, transitionDuration) {
// Create Cube Render Targets for the start and end images
const size = 512; // Example size, adjust as needed
currentCubeRenderTarget = new WebGLCubeRenderTarget(size, {
format: RGBFormat,
magFilter: LinearMipmapLinearFilter,
});
nextCubeRenderTarget = new WebGLCubeRenderTarget(size, {
format: RGBFormat,
magFilter: LinearMipmapLinearFilter,
});
// Load textures and set them to the render targets
// This part would involve creating textures from the images and assigning them
// For brevity, assuming 'loadTexture' function exists and returns a Texture object
const startTexture = loadTexture(startImageUrl); // Placeholder
const endTexture = loadTexture(endImageUrl); // Placeholder
// Simplified assignment for demonstration. Actual CubeRenderTarget setup is more complex.
// You'd typically render a scene from 6 cube camera directions for each.
// For a simple envMap transition, you might apply the texture directly if applicable.
// Example using a single texture for simplicity (not a true CubeRenderTarget setup):
const material = new MeshBasicMaterial({ envMap: currentCubeRenderTarget.texture });
// ... apply this material to the dollhouse or relevant object
transitionStartTime = Date.now();
}
function updateTransition(deltaTime, dollhouseMesh, transitionDuration) {
if (transitionStartTime === null) return;
const elapsedTime = Date.now() - transitionStartTime;
const progress = Math.min(elapsedTime / (transitionDuration * 1000), 1.0);
// Update the envMap of the dollhouse mesh
// This is a conceptual representation. Actual interpolation might be needed.
if (dollhouseMesh && dollhouseMesh.material.envMap) {
// Example: Lerping between two Cube Render Target textures (complex)
// Or, if using a simpler approach, blending textures
// For a true envMap transition, you'd need to interpolate the cube map faces.
// This example simplifies by showing the progress.
console.log(`Transition progress: ${progress * 100}%`);
// A more accurate approach would involve custom shaders to blend the envMaps.
// For MeshBasicMaterial, you might need to create a new texture dynamically or use shaders.
if (progress === 1.0) {
// Transition complete
transitionStartTime = null;
// Clean up render targets if necessary
}
}
}
// Helper function placeholder
function loadTexture(url) {
// Implementation to load texture, e.g., using THREE.TextureLoader
return null;
}
```
--------------------------------
### Control Navigation and View Modes with CameraHandlers
Source: https://context7.com/lukehollis/sphr/llms.txt
Handles camera movement, view modes (FPV, ORBIT), and zoom functionality. It allows navigation to specific nodes with defined view parameters, toggling between view modes, setting a specific view mode, and managing zoom levels with smooth transitions.
```javascript
// CameraHandlers.js - Navigate between viewpoints
import CameraHandlers from './CameraHandlers';
const cameraHandlers = new CameraHandlers();
// Navigate to a node
cameraHandlers.handleNavigation(targetNode, {
viewMode: "FPV",
rotation: { azimuth: 45, polar: -10 },
distance: 10,
orbitTarget: new THREE.Vector3(0, 0, 0),
position: null
});
// Toggle between FPV and ORBIT view modes
cameraHandlers.toggleViewMode();
// Set specific view mode
cameraHandlers.setViewMode("ORBIT", {
doLerp: true,
noDollhouse: false
});
// Handle zoom
cameraHandlers.handleZoom(10); // Zoom in by 10 units
// Smooth zoom transition
cameraHandlers.lerpToZoom(50); // Lerp to zoom level 50
```
--------------------------------
### Webpack Common Configuration (JavaScript)
Source: https://context7.com/lukehollis/sphr/llms.txt
Common Webpack configuration file used for both development and production builds. It defines entry points, module rules for processing different file types (JS, CSS, assets), and plugins like HtmlWebpackPlugin and CopyWebpackPlugin.
```javascript
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
entry: './src/index.js',
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: ['babel-loader']
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader', 'postcss-loader']
},
{
test: /\.(glb|gltf|jpg|png)$/,
type: 'asset/resource'
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
}),
new CopyWebpackPlugin({
patterns: [
{ from: 'static', to: 'static' },
{ from: 'data', to: 'data' }
]
})
]
};
```
--------------------------------
### Render 3D Interactive Cursor
Source: https://context7.com/lukehollis/sphr/llms.txt
Renders an interactive 3D cursor on mesh surfaces for photorealistic interaction. It includes updating the cursor's position and rotation based on raycasting results and allows configuration of cursor parameters like radius and segments. Visibility is controlled via store state.
```javascript
// Cursor.js - Create and update 3D cursor
import Cursor from './components/Cursor';
const cursor = new Cursor();
// Update cursor position and rotation from Store
// The cursor automatically follows raycasting results
cursor.update();
// Cursor parameters
cursor.innerRadius = 0.15;
cursor.outerRadius = 0.19;
cursor.thetaSegments = 64;
// Visibility is controlled by cursor position in Store
Store.setState({
cursor: {
position: new THREE.Vector3(10, 5, 3),
rotation: new THREE.Quaternion()
},
cursorOpacity: 1 // 0 to 1
});
```
--------------------------------
### Manage 3D Models with SceneGraph
Source: https://context7.com/lukehollis/sphr/llms.txt
Loads and manages 3D models within the scene based on tour configuration. It provides functionality to show/hide models by ID, retrieve model references, hide all models simultaneously, update models in the render loop, and add debug helpers like grids and axes.
```javascript
// SceneGraph.js - Manage 3D models from tour configuration
import SceneGraph from './components/SceneGraph';
const sceneGraph = new SceneGraph();
// Show/hide models by ID
sceneGraph.showModelById('qau_beadnet_dress');
sceneGraph.hideModelById('qau_beadnet_dress');
// Get model reference
const model = sceneGraph.getModelById('nefertari_example_jewelry');
if (model) {
model.show();
model.position.set(10, 5, 0);
}
// Hide all models at once
sceneGraph.hideAllModels();
// Update all models in render loop
sceneGraph.update();
// Add debug helpers (grid and axes)
sceneGraph.addHelpers();
```
--------------------------------
### Dollhouse Component for Low-Resolution Preview - JavaScript
Source: https://github.com/lukehollis/sphr/blob/main/README.md
The Dollhouse component provides a low-resolution representation of the 3D captured space. It is primarily used for cursor interactions and the Orbit view mode. The aim is to keep the dollhouse under 50k vertices and 2MB in texture size for performance, though larger sizes are possible depending on project needs.
```javascript
import { Mesh, BoxGeometry, MeshBasicMaterial } from 'three';
export default class Dollhouse extends Mesh {
constructor(width, height, depth, color = 0x00ff00) {
const geometry = new BoxGeometry(width, height, depth);
const material = new MeshBasicMaterial({ color: color, wireframe: true });
super(geometry, material);
this.name = 'dollhouse';
}
// Add methods for updating geometry, material, or position as needed
}
```
--------------------------------
### EnvCube Component for 360 Imagery - JavaScript
Source: https://github.com/lukehollis/sphr/blob/main/README.md
The EnvCube component handles displaying 360-degree equirectangular images within the SPHR environment. It supports high-resolution images (greater than 8k recommended) and utilizes two EnvCube instances to manage transitions between images. The implementation uses a IIIF image server for progressive loading of textures, though this will be removed in future versions.
```javascript
import { Mesh, SphereGeometry, MeshBasicMaterial, TextureLoader } from 'three';
export default class EnvCube extends Mesh {
constructor(renderer, imageUrl) {
const geometry = new SphereGeometry(500, 60, 40);
// invert the geometry on the x-axis so that all faces point inward
geometry.scale(-1, 1, 1);
const material = new MeshBasicMaterial({
map: new TextureLoader().load(imageUrl)
});
super(geometry, material);
this.renderer = renderer;
this.name = 'envCube';
}
updateTexture(newImageUrl) {
const loader = new TextureLoader();
this.material.map = loader.load(newImageUrl);
this.material.needsUpdate = true;
}
}
```
--------------------------------
### SceneGraph and AnnotationGraph for Customizable Scenes - JavaScript
Source: https://github.com/lukehollis/sphr/blob/main/README.md
SPHR allows for a fully customizable scene graph, differentiating it from other tour builder software. This enables dynamic changes between spaces and focused items. SceneGraph.js is used for managing 3D models, while AnnotationGraph.js handles 2D annotations like embedded images and videos within scenes.
```javascript
import { Group } from 'three';
export class SceneGraph extends Group {
constructor() {
super();
this.name = 'SceneGraph';
}
addModel(model, position, rotation, scale) {
// Add a 3D model to the scene graph
// model: THREE.Object3D or similar
// position, rotation, scale: THREE.Vector3 or Euler or similar
if (model) {
model.position.set(position.x, position.y, position.z);
model.rotation.set(rotation.x, rotation.y, rotation.z);
model.scale.set(scale.x, scale.y, scale.z);
this.add(model);
}
}
removeModel(model) {
// Remove a 3D model from the scene graph
if (model && this.children.includes(model)) {
this.remove(model);
}
}
// Add methods for managing scene hierarchy, transformations, etc.
}
export class AnnotationGraph extends Group {
constructor() {
super();
this.name = 'AnnotationGraph';
}
addAnnotation(annotation, position) {
// Add a 2D annotation (e.g., image, video plane) to the scene
// annotation: THREE.Object3D representing the annotation element
// position: THREE.Vector3
if (annotation) {
annotation.position.set(position.x, position.y, position.z);
this.add(annotation);
}
}
removeAnnotation(annotation) {
// Remove a 2D annotation
if (annotation && this.children.includes(annotation)) {
this.remove(annotation);
}
}
// Add methods for managing annotations, visibility, interaction, etc.
}
```
--------------------------------
### Parse SPHR Data from HTML with JavaScript
Source: https://context7.com/lukehollis/sphr/llms.txt
Provides a JavaScript class `Space.js` to parse SPHR configuration data (space and tour) directly from embedded JSON within HTML script tags. It facilitates the initialization of the SPHR application by extracting `space_data`, `tour_data`, and `ordered_spaces_data` from the DOM. This method simplifies the integration of SPHR into existing web pages.
```javascript
// Space.js - Extract configuration from HTML elements
import Space from './Space';
// Initialize space from HTML data elements
const spaceConfig = new Space();
const space = spaceConfig.space;
const tour = spaceConfig.tour;
console.log("Loaded space:", space);
console.log("Loaded tour:", tour);
// HTML structure expected:
//
//
//
```
=== COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.