import * as THREE from 'three'; import {describe, it, expect} from 'vitest'; import {XRDeviceCamera} from './XRDeviceCamera'; import { getCameraParametersSnapshot, isDeviceCameraPoseAvailable, } from './CameraUtils'; function makeXrCameras(count: number): THREE.WebXRArrayCamera { return { cameras: new Array(count).fill({}), } as unknown as THREE.WebXRArrayCamera; } function makeDeviceCamera(withSimulatorCamera: boolean): XRDeviceCamera { return { simulatorCamera: withSimulatorCamera ? new THREE.PerspectiveCamera() : undefined, } as unknown as XRDeviceCamera; } describe('isDeviceCameraPoseAvailable', () => { it('is false with no device camera and no XR cameras', () => { expect(isDeviceCameraPoseAvailable(undefined, null)).toBe(false); }); it('is false when the XR array camera has no cameras yet', () => { expect(isDeviceCameraPoseAvailable(undefined, makeXrCameras(0))).toBe( false ); }); it('is true once the simulator camera is registered', () => { expect(isDeviceCameraPoseAvailable(makeDeviceCamera(true), null)).toBe( true ); }); it('is true once the XR session exposes cameras', () => { expect(isDeviceCameraPoseAvailable(undefined, makeXrCameras(2))).toBe(true); }); }); describe('getCameraParametersSnapshot', () => { const renderCamera = new THREE.PerspectiveCamera(75, 1.5, 0.1, 100); renderCamera.updateMatrixWorld(); it('returns null while no camera pose is available', () => { const snapshot = getCameraParametersSnapshot( renderCamera, null, makeDeviceCamera(false), 'galaxyxr' ); expect(snapshot).toBeNull(); }); it('returns a full snapshot once the simulator camera is available', () => { const snapshot = getCameraParametersSnapshot( renderCamera, null, makeDeviceCamera(true), 'galaxyxr' ); expect(snapshot).not.toBeNull(); expect(snapshot!.clipFromView).toBeInstanceOf(THREE.Matrix4); expect(snapshot!.viewFromClip).toBeInstanceOf(THREE.Matrix4); expect(snapshot!.worldFromView).toBeInstanceOf(THREE.Matrix4); expect(snapshot!.worldFromClip).toBeInstanceOf(THREE.Matrix4); }); });