import * as THREE from 'three'; import { PointerLockControls } from 'three/examples/jsm/controls/PointerLockControls.js'; import { STATE } from '../core/State.js'; import { PALETTE_3D } from './palette.js'; export function initScene() { const scene = new THREE.Scene(); STATE.scene = scene; // Expose scene for visualizer helpers scene.background = new THREE.Color(PALETTE_3D.BACKGROUND); scene.fog = new THREE.FogExp2(PALETTE_3D.FOG, 0.02); const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.01, 1000); camera.rotation.reorder('YXZ'); camera.position.set(0, 5, 20); const renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); document.querySelector('#app').innerHTML = ''; document.querySelector('#app').appendChild(renderer.domElement); const controls = new PointerLockControls(camera, document.body); // Patch requestPointerLock to pass { unadjustedMovement: true } with a fallback if unsupported/rejected const domEl = controls.domElement || document.body; const originalRequest = domEl.requestPointerLock || Element.prototype.requestPointerLock; if (originalRequest) { domEl.requestPointerLock = function(options) { try { const promise = originalRequest.call(this, { unadjustedMovement: true, ...options }); if (promise && typeof promise.catch === 'function') { promise.catch((err) => { console.warn("PointerLock with options rejected, falling back:", err); originalRequest.call(this); }); } return promise; } catch (e) { console.warn("PointerLock with options threw error, falling back:", e); try { return originalRequest.call(this); } catch (fallbackErr) { console.error("PointerLock fallback failed:", fallbackErr); } } }; } const gridHelper = new THREE.GridHelper(200, 200, PALETTE_3D.GRID_PRIMARY, PALETTE_3D.GRID_SECONDARY); gridHelper.position.y = -5; scene.add(gridHelper); window.addEventListener('resize', () => { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); }); return { scene, camera, renderer, controls }; }