UNPKG

@shopware-ag/dive

Version:

Shopware Spatial Framework

132 lines (106 loc) 3.78 kB
import { Matrix4, Mesh, Vector3 } from 'three'; import { DIVERenderer } from '../../../renderer/Renderer'; import { DIVEWebXRRaycasterAR } from './ar/WebXRRaycasterAR'; import { DIVEWebXRRaycasterTHREE } from './three/WebXRRaycasterTHREE'; import { DIVEScene } from '../../../scene/Scene'; import { DIVEEventExecutor } from '../../../events/EventExecutor'; /** * object is undefined when AR world is hit. */ export type DIVEHitResult = { point: Vector3; matrix: Matrix4; object?: Mesh; }; export type DIVEWebXRRaycasterEvents = { AR_HIT_FOUND: { hit: DIVEHitResult; }; AR_HIT_LOST: undefined; SCENE_HIT_FOUND: { hit: DIVEHitResult; }; SCENE_HIT_LOST: undefined; }; export class DIVEWebXRRaycaster extends DIVEEventExecutor<DIVEWebXRRaycasterEvents> { private _session: XRSession; private _initialized: boolean = false; private _threeRaycaster: DIVEWebXRRaycasterTHREE; private _arRaycaster: DIVEWebXRRaycasterAR; private _arHitResultBuffer: DIVEHitResult[] = []; private _sceneHitResultBuffer: DIVEHitResult[] = []; // buffers private _hasHit: boolean = false; constructor(session: XRSession, renderer: DIVERenderer, scene: DIVEScene) { super(); this._session = session; this._threeRaycaster = new DIVEWebXRRaycasterTHREE(renderer, scene); this._arRaycaster = new DIVEWebXRRaycasterAR(session, renderer); } public Dispose(): void { // dispose code here this._initialized = false; } public async Init(): Promise<this> { if (!this._session) { console.error( 'DIVEWebXRRaycaster: No session set in Init()! Aborting initialization...', ); return Promise.reject(); } if (this._initialized) { console.error( 'DIVEWebXRRaycaster: Already initialized! Aborting initialization...', ); return Promise.reject(); } await this._threeRaycaster.Init(); await this._arRaycaster.Init(); console.log('DIVEWebXRRaycaster: Initialized'); this._initialized = true; return Promise.resolve(this); } public GetARIntersections(frame: XRFrame): DIVEHitResult[] { // check for ar hits this._arHitResultBuffer = this._arRaycaster.GetIntersections(frame); if (this._arHitResultBuffer.length > 0) { // hit found this.onARHitFound(this._arHitResultBuffer[0]); } else { // hit nothing this.onARHitLost(); } return this._arHitResultBuffer; } public GetSceneIntersections(): DIVEHitResult[] { // check for scene hits this._sceneHitResultBuffer = this._threeRaycaster.GetIntersections(); if (this._sceneHitResultBuffer.length > 0) { // scene hit found this.onSceneHitFound(this._sceneHitResultBuffer[0]); // early return to prevent ar raycaster from overriding scene hit } else { // scene hit nothing this.onSceneHitLost(); } return this._sceneHitResultBuffer; } private onARHitFound(hit: DIVEHitResult): void { this._hasHit = true; this.dispatch('AR_HIT_FOUND', { hit }); } private onARHitLost(): void { if (!this._hasHit) return; this._hasHit = false; this.dispatch('AR_HIT_LOST'); } private onSceneHitFound(hit: DIVEHitResult): void { this._hasHit = true; this.dispatch('SCENE_HIT_FOUND', { hit }); } private onSceneHitLost(): void { if (!this._hasHit) return; this._hasHit = false; this.dispatch('SCENE_HIT_LOST'); } }