### Project Build and Development Commands Source: https://context7.com/umarmf343/sphr/llms.txt This section outlines the standard npm commands for managing the project's build process and development environment. It covers installing dependencies, starting a development server with hot reloading, building for production, and building for specific languages using environment variables. It also briefly mentions webpack configuration differences between development and production. ```bash # Install dependencies npm install # Start development server with hot reload npm run start # Runs webpack-dev-server on http://localhost:3000 # Automatically rebuilds on file changes # Build for production npm run build # Outputs to static/webpack_bundles/ # Creates bundle.[contenthash].js with minification # Build for specific language LANG=en npm run build # English LANG=ar npm run build # Arabic LANG=es npm run build # Spanish # Webpack configuration # Development: webpack.dev.js # - Hot reload enabled # - Source maps included # - Dev server on port 3000 # Production: webpack.prod.js # - Minified output # - Optimized assets # - Content hash for cache busting ``` -------------------------------- ### Camera Navigation and View Modes in JavaScript Source: https://context7.com/umarmf343/sphr/llms.txt Provides examples of navigating the camera between nodes using different view modes (FPV, ORBIT) and custom positions/rotations. It also shows how to set interpolation targets for smooth camera movement. ```javascript // CameraHandlers.js - Navigate between nodes import CameraHandlers from './CameraHandlers'; const cameraHandlers = new CameraHandlers(); // Navigate to node in First Person View cameraHandlers.handleNavigation(targetNode, { viewMode: "FPV", rotation: { polar: -2, azimuth: 46 } // Optional camera rotation }); // Navigate to Orbit view around a target cameraHandlers.handleNavigation(targetNode, { viewMode: "ORBIT", orbitTarget: new THREE.Vector3(64.41, 11.99, 3.75), distance: 10 // Distance from target }); // Navigate to custom position cameraHandlers.handleNavigation(targetNode, { viewMode: "FPV", position: new THREE.Vector3(70, 12, 5), rotation: { polar: 0, azimuth: 90 }, noDollhouse: false // Show/hide dollhouse during navigation }); // Rig component handles camera interpolation const { app } = Store.getState(); // Set lerp target for smooth camera movement app.rig.setLerpTarget( new THREE.Vector3(64.41, 11.99, 3.75), // target position { polar: -2, azimuth: 46 } // target rotation ); // Update in render loop app.rig.update(); // Smoothly interpolates camera to target ``` -------------------------------- ### JavaScript - Store State Management Source: https://context7.com/umarmf343/sphr/llms.txt Demonstrates how to interact with the global state management system. Includes functions to get the current state, update state values, and listen for state changes. It also shows the initial structure of the store, which includes space data, rendering environment, navigation state, and device information. ```javascript // Store.js - Global state management import Store from './Store'; // Get current state const state = Store.getState(); console.log(state.currentNode, state.viewMode, state.isNavigating); // Update state Store.setState({ currentNode: newNode, isNavigating: true, viewMode: "ORBIT" }); // Listen to state changes Store.listen((newState) => { console.log('State updated:', newState.currentNode); }); // Initial store structure const initialStore = { space: spaceData, app: null, camera: new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.02, 10000), scene: new THREE.Scene(), viewMode: "FPV", // or "ORBIT" currentNode: initialNode, outgoingNode: initialNode, isNavigating: false, zoomLvl: 20, fov: 90, tourGuidedMode: false, tourSpaceActiveIdx: 0, tourPointActiveIdx: 0, cursor: { position: new THREE.Vector3(), rotation: new THREE.Quaternion() }, textures: {}, materialCache: {}, isMobile: /Android|webOS|iPhone|iPad|iPod/i.test(navigator.userAgent) }; ``` -------------------------------- ### JavaScript Utility Functions for SPHR Source: https://context7.com/umarmf343/sphr/llms.txt This snippet demonstrates various utility functions used in the SPHR project, including calculating distances, getting initial camera positions and orbit targets, utilizing a texture caching system, and comparing 3D vectors. These functions are essential for scene setup and interaction within the SPHR framework. ```javascript // lib/util.js - Helper functions import { calculateDistance, getInitialCameraPosition, getInitialOrbitTarget, useCachedTexture } from './lib/util'; // Calculate distance between two positions const distance = calculateDistance( { x: 64.41, y: 11.99, z: 3.75 }, { x: 69.19, y: 12.03, z: 5.27 } ); console.log('Distance:', distance); // ~5.1 units // Get initial camera position for space const initialPos = getInitialCameraPosition( space.space_data, initialNode, { polar: -2, azimuth: 46 } ); console.log(initialPos); // THREE.Vector3 // Get orbit target position const orbitTarget = getInitialOrbitTarget( space.space_data, node ); console.log(orbitTarget); // THREE.Vector3 at node floor position // Texture caching system const texture = useCachedTexture( 'IMG_20231101_074927_00_479', // nodeUUID 0, // faceIndex "1024", // resolution space.version, () => console.log('Loaded') ); // Returns cached THREE.Texture if available, else loads and caches // Check if vectors are equal import { areVector3Equal } from './lib/util'; const isEqual = areVector3Equal( new THREE.Vector3(1, 2, 3), new THREE.Vector3(1, 2, 3) ); console.log(isEqual); // true ``` -------------------------------- ### Cursor Component for 3D Interaction Source: https://github.com/umarmf343/sphr/blob/main/README.md The Cursor.js component is essential for rendering a cursor on the 3D mesh of a space, which appears on top of the 360 images. This enables users to interact with the 3D mesh while viewing the 360 environment, providing a photorealistic experience. It serves as a starting point for custom cursor implementations. ```javascript import React, { useRef, useEffect } from 'react'; import * as THREE from 'three'; const Cursor = ({ position, size = 0.1, color = 0xff0000 }) => { const meshRef = useRef(); useEffect(() => { const geometry = new THREE.ConeGeometry(size, size * 2, 32); const material = new THREE.MeshBasicMaterial({ color: color, transparent: true, opacity: 0.8 }); meshRef.current = new THREE.Mesh(geometry, material); // Initial position setup if (position) { meshRef.current.position.set(position.x, position.y, position.z); // Orient the cone to point upwards meshRef.current.rotation.x = Math.PI; } return () => { if (meshRef.current && meshRef.current.parent) { meshRef.current.parent.remove(meshRef.current); } }; }, [position, size, color]); useEffect(() => { if (meshRef.current && position) { meshRef.current.position.set(position.x, position.y, position.z); } }, [position]); return null; // The mesh is added directly to a Three.js scene elsewhere }; export default Cursor; ``` -------------------------------- ### JavaScript - Main Application Initialization and Rendering Loop Source: https://context7.com/umarmf343/sphr/llms.txt Sets up the main application using Store, EventManager, and App components. It initializes the global store, sets up event handling, and defines a render loop that updates all components and renders the scene using a post-processing composer. It also handles window resizing to maintain aspect ratio and renderer size. ```javascript // Main application setup (index.js) import Store from './Store'; import EventManager from './EventManager'; import App from './components/App'; // Initialize store with app instance Store.setState({ app: new App() }); // Set up event manager for user interactions const eventManager = new EventManager(); // Get state for rendering const store = Store.getState(); const { app, camera, renderer, scene, space } = store; // Main render loop const render = () => { const { app, space, threejsEnvInited } = Store.getState(); if (space.type === "matterport" || !app.threejsEnvInited) { return; } // Update all components with .update() methods app.update(); // Render post-processing stack app.post.composer.render(); // Render custom space effects if available if (app.spaceCustom) { app.spaceCustom.render(); } }; // Use VR-compatible animation loop renderer.setAnimationLoop(render); // Handle window resize window.addEventListener('resize', () => { const { space, camera, renderer, sizes, app } = Store.getState(); sizes.width = window.innerWidth; sizes.height = window.innerHeight; if (space.type !== "matterport") { camera.aspect = sizes.width / sizes.height; camera.updateProjectionMatrix(); renderer.setSize(sizes.width, sizes.height); renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); app.post.composer.setSize(sizes.width, sizes.height); } }); ``` -------------------------------- ### Node Navigation and Texture Loading in JavaScript Source: https://context7.com/umarmf343/sphr/llms.txt Demonstrates how to navigate to new viewpoints, ensure textures are loaded before proceeding, and manually load textures from cache. It also includes checks for complete texture loading. ```javascript const { app } = Store.getState(); // Find target node const targetNode = space.space_data.nodes.find(n => n.uuid === 'IMG_20231101_075039_00_482'); // Ensure textures loaded before navigation app.ensureFacesLoadedThenNavigate(targetNode); // Preload nearest nodes based on distance app.preloadNearestNodes(targetNode); // Load specific node textures app.loadNode(targetNode, () => { console.log('Node textures loaded'); // Navigate after loading app.cameraHandlers.handleNavigation(targetNode, { viewMode: "FPV" }); }); // Check if node is fully loaded if (app.areAllFacesLoaded(targetNode)) { console.log('All 6 cube faces loaded for node'); } // Manual texture loading from cache import { useCachedTexture } from './lib/util'; const texture = useCachedTexture( 'IMG_20231101_074927_00_479', // nodeUUID 0, // faceIndex (0-5) "1024", // resolution space.version, // version () => console.log('Texture loaded callback') ); ``` -------------------------------- ### Transition Between Spaces with TransitionManager in JavaScript Source: https://context7.com/umarmf343/sphr/llms.txt This snippet details the TransitionManager's role in handling transitions between different types of spaces, including custom Three.js environments and Matterport scenes. It covers initialization, switching logic, and basic Matterport SDK integration for navigation. Dependencies include the TransitionManager class and the Matterport SDK. ```javascript // TransitionManager.js - Handle space type transitions import TransitionManager from './components/TransitionManager'; const transitionManager = new TransitionManager(); // Initialize space based on type transitionManager.initializeSpace(spaceData); // Switch to custom Three.js space transitionManager.switchToCustomSpace(); // Shows webgl canvas, hides Matterport iframe // Initializes Three.js components // Switch to Matterport space await transitionManager.switchToMatterport(); // Hides webgl canvas, shows Matterport iframe // Loads Matterport SDK and initializes viewer // Example: Matterport initialization const spaceId = 'j4RZx7ZGM6T'; // Matterport space ID const iframe = document.getElementById('matterport-iframe'); const sdk = await setupSdk(spaceId, { container: iframe, space: spaceId }); // Matterport SDK interaction sdk.on('sweep.visible', (sweepId) => { console.log('Viewing sweep:', sweepId); }); sdk.moveTo(sweepId, { transition: 'fly', transitionTime: 2000 }); ``` -------------------------------- ### Dollhouse 3D Mesh Interaction in JavaScript Source: https://context7.com/umarmf343/sphr/llms.txt Details the loading and display of a 3D dollhouse mesh using the Dollhouse component. It covers accessing the loaded GLTF scene, setting up raycasting references, managing opacity transitions, and updating the dollhouse in the render loop. ```javascript // Dollhouse.js - Load and display 3D dollhouse mesh import Dollhouse from './components/Dollhouse'; // Space configuration with dollhouse mesh const space = { mesh: 'https://example.com/models/dollhouse.glb', space_data: { sceneSettings: { dollhouse: { scale: 1.0, offsetPosition: { x: 0, y: 0, z: 0 }, offsetRotation: { x: 0, y: 0, z: 0 } } } } }; // Dollhouse loads automatically in App const dollhouse = new Dollhouse(); // Access loaded GLTF after loading dollhouse.gltf.scene.traverse((child) => { if (child.isMesh) { console.log('Mesh:', child.name); child.dollhouse = dollhouse; // Reference for raycasting } }); // Switch to CubeRenderTarget material for transitions dollhouse.setOpacityTransition(0.8); // Set opacity during navigation // Render dollhouse with environment map during transition const { cubeRenderTarget } = Store.getState(); dollhouse.cubeMaterial = new THREE.MeshBasicMaterial({ color: 0xffffff, envMap: cubeRenderTarget.texture }); // Update in render loop dollhouse.update(); // Handles material transitions ``` -------------------------------- ### EnvCube 360° Panorama Display in JavaScript Source: https://context7.com/umarmf343/sphr/llms.txt Illustrates the use of EnvCube for displaying 360° images in a cube geometry. It covers creating the cube, updating its rotation, understanding face rotation mappings, and implementing progressive texture loading. ```javascript // EnvCube.js - Display 360° images in cube geometry import EnvCube from './components/EnvCube'; const { currentNode } = Store.getState(); // Create environment cube for a node const envCube = new EnvCube(currentNode, { isOutgoing: false }); // The cube automatically: // - Creates 6 face planes with cached textures // - Positions at camera location // - Rotates based on node rotation data // - Adds to scene // Update cube rotation for new node envCube.setRotation(newNode); // Face rotation mapping (internal) envCube.getRotation(0); // Returns: [Math.PI / 2, 0, Math.PI] for top face envCube.getRotation(1); // Returns: [0, Math.PI, 0] for front face envCube.getRotation(2); // Returns: [0, Math.PI / 2, 0] for right face envCube.getRotation(3); // Returns: [0, 0, 0] for back face envCube.getRotation(4); // Returns: [0, -Math.PI / 2, 0] for left face envCube.getRotation(5); // Returns: [-Math.PI / 2, 0, Math.PI] for bottom face // Progressive texture loading // Loads 1024px textures first, then upgrades to higher resolution envCube.loadHigherResolutionTextures(faceIndex); // Render loop update envCube.update(); // Handles progressive texture swapping ``` -------------------------------- ### JavaScript - Initialize Space from HTML Data Source: https://context7.com/umarmf343/sphr/llms.txt Initializes a new 'Space' object from configuration data found within the HTML document. It automatically parses embedded JSON data for space, tour, and ordered spaces, falling back to a default JSON file if none are found. The parsed space data is then logged to the console. ```javascript import Space from './Space'; const spaceConfig = new Space(); // Automatically parses space_data, tour_data, and ordered_spaces_data from DOM // Falls back to example_space.json if no data found console.log(spaceConfig.space); // Output: { type: 'spaces', space_data: {...}, version: null } ``` -------------------------------- ### Add Visual Effects with Postprocessing in JavaScript Source: https://context7.com/umarmf343/sphr/llms.txt This snippet illustrates how to implement custom visual effects and post-processing in the project using the Postprocessing component. It shows how to access the Three.js composer, add custom passes like UnrealBloomPass, and manage rendering within the animation loop. It also touches upon custom space effects. Dependencies include the Postprocessing class and Three.js post-processing modules. ```javascript // Postprocessing.js - Add visual effects import Postprocessing from './components/Postprocessing'; const post = new Postprocessing(); // Access composer for custom passes const { composer, bloomComposer } = post; // Add custom pass import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPass'; const bloomPass = new UnrealBloomPass( new THREE.Vector2(window.innerWidth, window.innerHeight), 1.5, // strength 0.4, // radius 0.85 // threshold ); composer.addPass(bloomPass); // Render in animation loop post.composer.render(); // Custom space effects (spaceCustom/index.js) import setupSpaceCustom from './components/spaceCustom'; const spaceCustom = setupSpaceCustom(); // Update and render custom effects spaceCustom.update(); // Called in App.update() spaceCustom.render(); // Called in render loop // Example: Add particle effects, custom shaders, etc. // Custom effects have access to scene, camera, renderer from Store ``` -------------------------------- ### JavaScript Tour Navigation and Audio Management Source: https://context7.com/umarmf343/sphr/llms.txt This JavaScript code handles the user interface and interactions for a tour system. It includes functions to navigate between tour points (next, previous, specific), control autoplay, and manage audio playback using an AudioManager. Navigation involves updating the store with active tour point indices and handling camera movements based on tour point data. ```javascript // TourUI.js - Navigate through tour points import TourUI from './components/tour/TourUI'; import AudioManager from './components/AudioManager'; // Tour UI initializes automatically if tourGuidedMode is true const { app, tour } = Store.getState(); // Navigate to next tour point app.tourUI.tourNavButtons.handleClickNext(); // Navigate to previous tour point app.tourUI.tourNavButtons.handleClickPrev(); // Navigate to specific tour point const spaceIdx = 0; const pointIdx = 2; Store.setState({ tourSpaceActiveIdx: spaceIdx, tourPointActiveIdx: pointIdx }); const tourpoint = tour.tour_data.spaces[spaceIdx].tourpoints[pointIdx]; const node = space.space_data.nodes.find(n => n.uuid === tourpoint.nodeUUID); app.cameraHandlers.handleNavigation(node, { viewMode: tourpoint.viewMode, rotation: tourpoint.rotation, orbitTarget: tourpoint.targetType === "MODEL" ? app.sceneGraph.getModelById(tourpoint.models[0]).position : null }); // Autoplay control app.startAutoplay(); // Advances every 9 seconds app.stopAutoplay(); app.handleToggleAutoplay(); // Toggle on/off // Audio management const audioManager = new AudioManager(); audioManager.playSound('default'); // Plays audio defined in tour JSON audioManager.playSound('navigate'); audioManager.stopAllSounds(); ``` -------------------------------- ### JSON Tour System Configuration Embedded in HTML Source: https://context7.com/umarmf343/sphr/llms.txt This snippet shows the JSON structure for configuring a tour system, embedded within an HTML script tag. It defines audio assets, tour spaces with points of interest, scene graph models, and annotation data. This configuration can be accessed via a store to drive the tour's content and behavior. ```json // Tour JSON structure embedded in HTML // Access tour data const { tour } = Store.getState(); console.log(tour.tour_data.spaces[0].tourpoints); ``` -------------------------------- ### Transition between 360 Images using WebGLCubeRenderTarget Source: https://github.com/umarmf343/sphr/blob/main/README.md This component implements a complex transition between two 360 images. The main camera interpolates between positions, and a WebGLCubeRenderTarget is used to render the transition onto the environment map of the Dollhouse, simulating movement. This is a custom use of envMap and is noted as memory inefficient, requiring further shader development. ```javascript // This is a conceptual example demonstrating the use of WebGLCubeRenderTarget for transitions. // A full implementation would involve managing multiple scenes, cameras, and render targets. import * as THREE from 'three'; // Assume 'scene1', 'scene2' are THREE.Scene objects with 360 imagery setup // Assume 'camera' is the main THREE.PerspectiveCamera // Assume 'renderer' is the main THREE.WebGLRenderer const transitionDuration = 2; // seconds let startTime = null; function startTransition(scene1, scene2, camera, renderer) { startTime = performance.now(); // Create a cube render target for the environment map const cubeRenderTarget = new THREE.WebGLCubeRenderTarget(256, { format: THREE.RGBFormat, generateMipmaps: true, minFilter: THREE.LinearMipmapLinearFilter }); // Assign the cube render target to the envMap of a material // This would typically be applied to the Dollhouse mesh or a similar object const dollhouseMaterial = new THREE.MeshBasicMaterial({ envMap: cubeRenderTarget.texture }); // --- Transition Logic --- const animateTransition = (currentTime) => { if (startTime === null) return; // Transition ended or not started const elapsedTime = (currentTime - startTime) / 1000; // seconds const progress = Math.min(elapsedTime / transitionDuration, 1); // Interpolate camera position (example) // camera.position.lerp(targetCameraPosition, progress); // Render the current state into the cube render target // This requires rendering scene1 and scene2 from specific viewpoints into the faces of the cube target // Simplified example: Render scene1 for now renderer.setRenderTarget(cubeRenderTarget); renderer.render(scene1, camera); // This would need to be more sophisticated, rendering all 6 faces renderer.setRenderTarget(null); // Render the main scene renderer.render(scene1, camera); // In a real scenario, this would be a blended scene or scene2 if (progress < 1) { requestAnimationFrame(animateTransition); } else { // Transition complete startTime = null; // Clean up cubeRenderTarget if necessary // cubeRenderTarget.dispose(); } }; requestAnimationFrame(animateTransition); } // Usage example (within a React component or similar context): // useEffect(() => { // // Setup scenes, camera, renderer... // // const transitionButton = document.getElementById('transitionButton'); // // transitionButton.addEventListener('click', () => { // // startTransition(scene1, scene2, camera, renderer); // // }); // }, []); ``` -------------------------------- ### Manage 3D Models with SceneGraph and Model in JavaScript Source: https://context7.com/umarmf343/sphr/llms.txt This snippet demonstrates how to manage 3D models within a scene using the SceneGraph and Model components. SceneGraph handles the overall organization and visibility of models, while Model represents individual 3D assets. It covers showing, hiding, retrieving, updating, and configuring models. Dependencies include the SceneGraph and Model classes. ```javascript // SceneGraph.js - Manage tour-specific 3D models import SceneGraph from './components/SceneGraph'; const sceneGraph = new SceneGraph(); // Show/hide models by ID sceneGraph.showModelById('model_artifact_01'); sceneGraph.hideModelById('model_artifact_01'); // Get model reference const model = sceneGraph.getModelById('model_artifact_01'); console.log(model.position, model.rotation, model.scale); // Hide all models (useful when switching tour points) sceneGraph.hideAllModels(); // Update models in render loop sceneGraph.update(); // Model.js - Individual model loading import Model from './components/Model'; const modelConfig = { id: 'model_artifact_01', type: 'model', file: 'https://example.com/models/artifact.glb', fileType: 'glb', position: [64.41, 12.5, 3.75], rotation: [0, 1.57, 0], scale: [1, 1, 1], isSketch: false }; const model = new Model(modelConfig); // Show/hide model model.show(); // Sets visible and animates opacity model.hide(); // Sets invisible // Update in render loop model.update(); // Handles animations ``` -------------------------------- ### Dollhouse Component for Low-Resolution Spaces Source: https://github.com/umarmf343/sphr/blob/main/README.md The Dollhouse.js component represents a low-resolution version of a 3D capture of a space. It is primarily used for cursor interactions and the Orbit view mode. Recommendations include keeping the dollhouse under 50k vertices and texture sizes under 2MB for optimal performance. ```javascript import React, { useRef, useEffect } from 'react'; import * as THREE from 'three'; const Dollhouse = ({ modelUrl, onLoad }) => { const mountRef = useRef(null); useEffect(() => { const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); const renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); mountRef.current.appendChild(renderer.domElement); const ambientLight = new THREE.AmbientLight(0x404040); scene.add(ambientLight); const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5); directionalLight.position.set(0, 1, 1); scene.add(directionalLight); const loader = new THREE.ObjectLoader(); // Or GLTFLoader for glTF/GLB files loader.load(modelUrl, (obj) => { scene.add(obj); if (onLoad) { onLoad(obj); } // Center the object and adjust camera const box = new THREE.Box3().setFromObject(obj); const center = box.getCenter(new THREE.Vector3()); obj.position.sub(center); // Move object to origin camera.position.z = box.max.z - box.min.z; // Position camera based on object size const animate = () => { requestAnimationFrame(animate); renderer.render(scene, camera); }; animate(); }, undefined, (error) => { console.error('Error loading dollhouse model:', error); }); const handleResize = () => { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); }; window.addEventListener('resize', handleResize); return () => { window.removeEventListener('resize', handleResize); mountRef.current.removeChild(renderer.domElement); }; }, [modelUrl, onLoad]); return
; }; export default Dollhouse; ``` -------------------------------- ### JavaScript 3D Cursor Interaction with Mouse Tracking Source: https://context7.com/umarmf343/sphr/llms.txt This JavaScript code implements a 3D cursor that follows the user's mouse movements within a dollhouse environment. It utilizes a store for cursor position and opacity, and performs raycasting against the dollhouse scene to update the cursor's position and orientation based on intersections. The cursor is automatically hidden when its position is at the origin (0,0,0). ```javascript // Cursor.js - 3D cursor that follows mouse on dollhouse import Cursor from './components/Cursor'; const cursor = new Cursor(); // Cursor automatically created as ring geometry // Ring specs: innerRadius 0.15, outerRadius 0.19, 64 segments // Store updates cursor position via raycasting Store.setState({ cursor: { position: new THREE.Vector3(64.41, 11.99, 3.75), rotation: new THREE.Quaternion() }, cursorOpacity: 1.0 }); // Update in render loop cursor.update(); // Positions cursor at Store.cursor.position // Cursor visibility handled automatically // Hidden when position is (0,0,0), visible otherwise // Raycasting example (from PointerHandlers) const raycaster = new THREE.Raycaster(); const mouse = new THREE.Vector2(); document.addEventListener('mousemove', (event) => { mouse.x = (event.clientX / window.innerWidth) * 2 - 1; mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; raycaster.setFromCamera(mouse, camera); const intersects = raycaster.intersectObject(dollhouse.gltf.scene, true); if (intersects.length > 0) { Store.setState({ cursor: { position: intersects[0].point, rotation: intersects[0].face.normal }, cursorOpacity: 1.0 }); } }); ``` -------------------------------- ### 360 Imagery Component with EnvCube.js Source: https://github.com/umarmf343/sphr/blob/main/README.md The EnvCube component is used to display equirectangular 360 images. It supports high resolutions (greater than 8k recommended) and utilizes two instances for smooth transitions. The implementation uses a IIIF image server for progressive loading of textures, although this will be removed in future versions. ```javascript import React, { useRef, useEffect } from 'react'; import * as THREE from 'three'; const EnvCube = ({ imageUrl, onLoad }) => { const mountRef = useRef(null); useEffect(() => { const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); const renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); mountRef.current.appendChild(renderer.domElement); const geometry = new THREE.SphereGeometry(500, 60, 40); geometry.scale(-1, 1, 1); const textureLoader = new THREE.TextureLoader(); textureLoader.load(imageUrl, (texture) => { const material = new THREE.MeshBasicMaterial({ map: texture }); const mesh = new THREE.Mesh(geometry, material); scene.add(mesh); camera.position.set(0, 0, 0.1); const animate = () => { requestAnimationFrame(animate); renderer.render(scene, camera); }; animate(); if (onLoad) { onLoad(); } }); const handleResize = () => { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); }; window.addEventListener('resize', handleResize); return () => { window.removeEventListener('resize', handleResize); mountRef.current.removeChild(renderer.domElement); }; }, [imageUrl, onLoad]); return ; }; export default EnvCube; ``` -------------------------------- ### Space Configuration JSON Structure Source: https://context7.com/umarmf343/sphr/llms.txt Defines the structure for space data, including navigation nodes, scene settings, and initial viewing parameters. This JSON is typically embedded within an HTML script tag for direct use by the application. ```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.46, "y": -1.56, "z": -2.69 }, "resolution": "4096", "floorPosition": { "x": 64.41, "y": 6.67, "z": 3.75 } } ], "sceneSettings": { "nodes": { "scale": 1.0, "offsetPosition": { "x": 0, "y": 0, "z": 0 }, "offsetRotation": { "x": 0, "y": 0, "z": 0 } }, "dollhouse": { "scale": 1.0, "offsetPosition": { "x": 0, "y": 0, "z": 0 }, "offsetRotation": { "x": 0, "y": 0, "z": 0 } } }, "initialNode": "IMG_20231101_074927_00_479", "initialRotation": { "polar": -2, "azimuth": 46 } } ``` -------------------------------- ### AnnotationGraph.js for 2D Annotations Source: https://github.com/umarmf343/sphr/blob/main/README.md AnnotationGraph.js handles the integration of 2D annotations, such as images and videos, within the 3D scenes. This allows for embedding multimedia content as interactive elements in your virtual tours, enhancing user engagement and information delivery. ```javascript import React, { useRef, useEffect } from 'react'; import * as THREE from 'three'; const AnnotationGraph = ({ annotations, onAnnotationClick }) => { const annotationMeshesRef = useRef({}); useEffect(() => { const scene = new THREE.Scene(); // This would typically be the main scene object passed in annotations.forEach(annotation => { let annotationMesh; if (annotation.type === 'image') { const textureLoader = new THREE.TextureLoader(); textureLoader.load(annotation.url, (texture) => { const planeGeometry = new THREE.PlaneGeometry(annotation.width, annotation.height); const textureMaterial = new THREE.MeshBasicMaterial({ map: texture, transparent: true }); annotationMesh = new THREE.Mesh(planeGeometry, textureMaterial); annotationMesh.position.set(annotation.position.x, annotation.position.y, annotation.position.z); annotationMesh.userData = { annotationData: annotation }; // Store data for click events scene.add(annotationMesh); annotationMeshesRef.current[annotation.id] = annotationMesh; }); } else if (annotation.type === 'video') { // Video annotation setup would be more complex, likely involving VideoTexture and an HTML video element console.warn('Video annotation type not fully implemented in this example.'); } // Add other annotation types as needed }); // Click handler setup (would typically be attached to the renderer's canvas) const handleClick = (event) => { // Raycasting logic to detect clicks on annotation meshes // ... // if (intersection && intersection.object.userData.annotationData) { // onAnnotationClick(intersection.object.userData.annotationData); // } }; // document.addEventListener('click', handleClick); return () => { // Cleanup: remove meshes and event listeners // document.removeEventListener('click', handleClick); Object.values(annotationMeshesRef.current).forEach(mesh => { if (mesh.parent) { mesh.parent.remove(mesh); // Dispose textures, geometry, etc. } }); annotationMeshesRef.current = {}; }; }, [annotations, onAnnotationClick]); // This component manages scene additions but doesn't render its own DOM element. // The actual rendering is handled by the main Three.js setup. return null; }; export default AnnotationGraph; ``` -------------------------------- ### SceneGraph.js for 3D Model Customization Source: https://github.com/umarmf343/sphr/blob/main/README.md SceneGraph.js provides a customizable scene graph for managing 3D models within SPHR. This allows for flexibility in changing spaces and controlling focus on specific items. The structure enables developers to modify how models are integrated and interact within the scene. ```javascript import React, { useRef, useEffect } from 'react'; import * as THREE from 'three'; const SceneGraph = ({ models, onLoaded }) => { const sceneRef = useRef(new THREE.Scene()); useEffect(() => { const scene = sceneRef.current; const loader = new THREE.ObjectLoader(); // Or GLTFLoader etc. models.forEach(modelInfo => { loader.load(modelInfo.url, (obj) => { obj.position.set(modelInfo.position.x, modelInfo.position.y, modelInfo.position.z); obj.scale.set(modelInfo.scale.x, modelInfo.scale.y, modelInfo.scale.z); obj.rotation.set(modelInfo.rotation.x, modelInfo.rotation.y, modelInfo.rotation.z); scene.add(obj); if (onLoaded) { onLoaded(obj, modelInfo.id); } }, undefined, (error) => { console.error(`Error loading model ${modelInfo.url}:`, error); }); }); // Cleanup function to remove models from the scene when component unmounts or models change return () => { models.forEach(modelInfo => { // Find and remove the corresponding object from the scene const objectToRemove = scene.getObjectByProperty('uuid', modelInfo.uuid); // Assuming you store UUIDs if (objectToRemove) { scene.remove(objectToRemove); // Dispose of geometry and material if necessary } }); }; }, [models, onLoaded]); // Re-run effect if models prop changes // This component doesn't render directly, it modifies a Three.js scene object. // The sceneRef.current would be used by a main Three.js renderer setup. return null; }; export default SceneGraph; ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.