diff --git a/src/Three.d.ts b/src/Three.d.ts index 5b3370a1048991..4086386c47254a 100644 --- a/src/Three.d.ts +++ b/src/Three.d.ts @@ -172,6 +172,9 @@ export * from './renderers/webgl/WebGLShadowMap'; export * from './renderers/webgl/WebGLState'; export * from './renderers/webgl/WebGLTextures'; export * from './renderers/webgl/WebGLUniforms'; +export * from './renderers/webxr/WebXR'; +export * from './renderers/webxr/WebXRController'; +export * from './renderers/webxr/WebXRManager'; export * from './constants'; export * from './Three.Legacy'; diff --git a/src/renderers/WebGLRenderer.d.ts b/src/renderers/WebGLRenderer.d.ts index ade28640b5ada9..a943eac989415b 100644 --- a/src/renderers/WebGLRenderer.d.ts +++ b/src/renderers/WebGLRenderer.d.ts @@ -20,6 +20,7 @@ import { RenderTarget } from './webgl/WebGLRenderLists'; import { Geometry } from './../core/Geometry'; import { BufferGeometry } from './../core/BufferGeometry'; import { Texture } from '../textures/Texture'; +import { XRAnimationLoopCallback } from './webxr/WebXR'; export interface Renderer { domElement: HTMLCanvasElement; @@ -348,7 +349,7 @@ export class WebGLRenderer implements Renderer { * A build in function that can be used instead of requestAnimationFrame. For WebXR projects this function must be used. * @param callback The function will be called every available frame. If `null` is passed it will stop any already ongoing animation. */ - setAnimationLoop( callback: Function | null ): void; + setAnimationLoop( callback: XRAnimationLoopCallback | null ): void; /** * @deprecated Use {@link WebGLRenderer#setAnimationLoop .setAnimationLoop()} instead. diff --git a/src/renderers/webxr/WebXR.d.ts b/src/renderers/webxr/WebXR.d.ts new file mode 100644 index 00000000000000..9e1dfb97ddea8b --- /dev/null +++ b/src/renderers/webxr/WebXR.d.ts @@ -0,0 +1,324 @@ +export declare type XRSessionMode = 'inline' | 'immersive-vr' | 'immersive-ar'; + +export declare type XRReferenceSpaceType = 'viewer' | 'local' | 'local-floor' | 'bounded-floor' | 'unbounded'; + +export declare type XREnvironmentBlendMode = 'opaque' | 'additive' | 'alpha-blend'; + +export declare type XRVisibilityState = 'visible' | 'visible-blurred' | 'hidden'; + +export declare type XRHandedness = 'none' | 'left' | 'right'; + +export declare type XRTargetRayMode = 'gaze' | 'tracked-pointer' | 'screen'; + +export declare type XREye = 'none' | 'left' | 'right'; + +export declare type XREventType = 'end' | 'select' | 'selectstart' | 'selectend' | 'squeeze' | 'squeezestart' | 'squeezeend' | 'inputsourceschange'; + +export interface XRSpace extends EventTarget {} + +export declare type XRAnimationLoopCallback = ( time: number, frame?: XRFrame ) => void; + +export declare type XRFrameRequestCallback = ( time: number, frame: XRFrame ) => void; + +export interface XR extends EventTarget { + requestSession( mode: XRSessionMode, options?: XRSessionInit ): Promise; + isSessionSupported( mode: XRSessionMode ): Promise; +} + +export interface Window { + XRSession?: Constructor; + XR?: Constructor; +} + +export interface Navigator { + xr?: XR; +} + +export interface XRReferenceSpace extends XRSpace { + getOffsetReferenceSpace( originOffset: XRRigidTransform ): XRReferenceSpace; +} +export interface XRHitTestOptionsInit { + space: XRSpace; + offsetRay?: XRRay; +} + +export interface XRTransientInputHitTestOptionsInit { + profile: string; + offsetRay?: XRRay; +} + +export interface XRViewport { + readonly x: number; + readonly y: number; + readonly width: number; + readonly height: number; +} + +export interface WebGLRenderingContext { + makeXRCompatible(): Promise; +} + +export interface XRRenderState { + readonly depthNear: number; + readonly depthFar: number; + readonly inlineVerticalFieldOfView?: number; + readonly baseLayer?: XRWebGLLayer; +} + +export interface XRRenderStateInit { + depthNear?: number; + depthFar?: number; + inlineVerticalFieldOfView?: number; + baseLayer?: XRWebGLLayer; +} + +export interface XRInputSource { + readonly handedness: XRHandedness; + readonly targetRayMode: XRTargetRayMode; + readonly targetRaySpace: XRSpace; + readonly gripSpace?: XRSpace; + readonly profiles: Array; + readonly gamepad: Gamepad; + readonly hand?: XRHand; +} + +export interface XRSessionInit { + optionalFeatures?: string[]; + requiredFeatures?: string[]; +} + +export interface XRSession { + addEventListener: Function; + removeEventListener: Function; + requestReferenceSpace( type: XRReferenceSpaceType ): Promise; + updateRenderState( renderStateInit: XRRenderStateInit ): Promise; + requestAnimationFrame( callback: XRFrameRequestCallback ): number; + cancelAnimationFrame( id: number ): void; + end(): Promise; + renderState: XRRenderState; + inputSources: Array; + environmentBlendMode: XREnvironmentBlendMode; + visibilityState: XRVisibilityState; + + // hit test + requestHitTestSource( options: XRHitTestOptionsInit ): Promise; + requestHitTestSourceForTransientInput( options: XRTransientInputHitTestOptionsInit ): Promise; + + // legacy AR hit test + requestHitTest( ray: XRRay, referenceSpace: XRReferenceSpace ): Promise; + + // legacy plane detection + updateWorldTrackingState( options: { planeDetectionState?: { enabled: boolean } } ): void; +} + +export interface XRReferenceSpace extends XRSpace { + getOffsetReferenceSpace( originOffset: XRRigidTransform ): XRReferenceSpace; + onreset: any; +} + +export declare type XRPlaneSet = Set; +export declare type XRAnchorSet = Set; + +export interface XRFrame { + readonly session: XRSession; + getViewerPose( referenceSpace: XRReferenceSpace ): XRViewerPose | undefined; + getPose( space: XRSpace, baseSpace: XRSpace ): XRPose | undefined; + + // AR + getHitTestResults( hitTestSource: XRHitTestSource ): Array; + getHitTestResultsForTransientInput( hitTestSource: XRTransientInputHitTestSource ): Array; + // Anchors + trackedAnchors?: XRAnchorSet; + createAnchor( pose: XRRigidTransform, space: XRSpace ): Promise; + // Planes + worldInformation: { + detectedPlanes?: XRPlaneSet; + }; + // Hand tracking + getJointPose( joint: XRJointSpace, baseSpace: XRSpace ): XRJointPose; +} + +export interface XRViewerPose { + readonly transform: XRRigidTransform; + readonly views: Array +} + +export interface XRPose { + readonly emulatedPosition: boolean; + readonly transform: XRRigidTransform; +} + +export interface XRWebGLLayerInit { + antialias?: boolean; + depth?: boolean; + stencil?: boolean; + alpha?: boolean; + ignoreDepthValues?: boolean; + framebufferScaleFactor?: number; +} + +export interface XRLayer {} + +export interface XRWebGLLayer extends XRLayer{ + framebuffer: WebGLFramebuffer; + framebufferWidth: number; + framebufferHeight: number; + getViewport( view: XRView ): XRViewport; +} + +export declare class XRWebGLLayer implements XRWebGLLayer { + + constructor( session: XRSession, gl: WebGLRenderingContext | undefined, options?: XRWebGLLayerInit ) + +} + +export interface DOMPointInit { + w?: number; + x?: number; + y?: number; + z?: number; +} + +export declare class XRRigidTransform { + + constructor( matrix: Float32Array | DOMPointInit, direction?: DOMPointInit ); + position: DOMPointReadOnly; + orientation: DOMPointReadOnly; + matrix: Float32Array; + inverse: XRRigidTransform; + +} + +export interface XRView { + readonly eye: XREye; + readonly projectionMatrix: Float32Array; + readonly viewMatrix: Float32Array; + readonly transform: XRRigidTransform; +} + +export interface XRRayDirectionInit { + x?: number; + y?: number; + z?: number; + w?: number; +} + +export declare class XRRay { + + readonly origin: DOMPointReadOnly; + readonly direction: XRRayDirectionInit; + matrix: Float32Array; + + constructor( transformOrOrigin: XRRigidTransform | DOMPointInit, direction?: XRRayDirectionInit ) + +} + +export declare enum XRHitTestTrackableType { + 'point', 'plane', 'mesh', +} + +export interface XRHitResult { + hitMatrix: Float32Array; +} + +export interface XRTransientInputHitTestResult { + readonly inputSource: XRInputSource; + readonly results: Array; +} + +export interface XRHitTestResult { + getPose( baseSpace: XRSpace ): XRPose | undefined | null; + // When anchor system is enabled + createAnchor?( pose: XRRigidTransform ): Promise; +} + +export interface XRHitTestSource { + cancel(): void; +} + +export interface XRTransientInputHitTestSource { + cancel(): void; +} + +export interface XRHitTestOptionsInit { + space: XRSpace; + entityTypes?: Array; + offsetRay?: XRRay; +} + +export interface XRTransientInputHitTestOptionsInit { + profile: string; + entityTypes?: Array; + offsetRay?: XRRay; +} + +export interface XRAnchor { + anchorSpace: XRSpace; + delete(): void; +} + +export interface XRPlane { + orientation: 'Horizontal' | 'Vertical'; + planeSpace: XRSpace; + polygon: Array; + lastChangedTime: number; +} + +export interface XRJointSpace extends XRSpace {} + +export interface XRJointPose extends XRPose { + radius: number | undefined; +} + +export declare class XRHand extends Array { + + readonly length: number; + + static readonly WRIST = 0; + + static readonly THUMB_METACARPAL = 1; + static readonly THUMB_PHALANX_PROXIMAL = 2; + static readonly THUMB_PHALANX_DISTAL = 3; + static readonly THUMB_PHALANX_TIP = 4; + + static readonly INDEX_METACARPAL = 5; + static readonly INDEX_PHALANX_PROXIMAL = 6; + static readonly INDEX_PHALANX_INTERMEDIATE = 7; + static readonly INDEX_PHALANX_DISTAL = 8; + static readonly INDEX_PHALANX_TIP = 9; + + static readonly MIDDLE_METACARPAL = 10; + static readonly MIDDLE_PHALANX_PROXIMAL = 11; + static readonly MIDDLE_PHALANX_INTERMEDIATE = 12; + static readonly MIDDLE_PHALANX_DISTAL = 13; + static readonly MIDDLE_PHALANX_TIP = 14; + + static readonly RING_METACARPAL = 15; + static readonly RING_PHALANX_PROXIMAL = 16; + static readonly RING_PHALANX_INTERMEDIATE = 17; + static readonly RING_PHALANX_DISTAL = 18; + static readonly RING_PHALANX_TIP = 19; + + static readonly LITTLE_METACARPAL = 20; + static readonly LITTLE_PHALANX_PROXIMAL = 21; + static readonly LITTLE_PHALANX_INTERMEDIATE = 22; + static readonly LITTLE_PHALANX_DISTAL = 23; + static readonly LITTLE_PHALANX_TIP = 24; + +} + +declare type Constructor = { + new ( ...args: any[] ): T, + prototype: T +}; + +export interface XRInputSourceChangeEvent { + session: XRSession; + removed: Array; + added: Array; +} + +export interface XRInputSourceEvent extends Event { + readonly frame: XRFrame; + readonly inputSource: XRInputSource; +} diff --git a/src/renderers/webxr/WebXRController.d.ts b/src/renderers/webxr/WebXRController.d.ts index 5b4e046913ffa0..94056f962ec559 100644 --- a/src/renderers/webxr/WebXRController.d.ts +++ b/src/renderers/webxr/WebXRController.d.ts @@ -1,4 +1,7 @@ import { Group } from '../../objects/Group'; +import { XREventType, XRFrame, XRInputSource, XRReferenceSpace } from './WebXR'; + +export type XRControllerEventType = XREventType | 'disconnected' | 'connected' export class WebXRController { @@ -6,8 +9,8 @@ export class WebXRController { getTargetRaySpace(): Group; getGripSpace(): Group; - dispatchEvent( event: object ): this; - disconnect( inputSource: object ): this; - update( inputSource: object, frame: object, referenceSpace: string ): this; + dispatchEvent( event: { type: XRControllerEventType, data?: XRInputSource } ): this; + disconnect( inputSource: XRInputSource ): this; + update( inputSource: XRInputSource, frame: XRFrame, referenceSpace: XRReferenceSpace ): this; } diff --git a/src/renderers/webxr/WebXRManager.d.ts b/src/renderers/webxr/WebXRManager.d.ts index a4122e82ae20f8..be463d1a02c273 100644 --- a/src/renderers/webxr/WebXRManager.d.ts +++ b/src/renderers/webxr/WebXRManager.d.ts @@ -1,6 +1,7 @@ import { Group } from '../../objects/Group'; import { Camera } from '../../cameras/Camera'; import { EventDispatcher } from '../../core/EventDispatcher'; +import { XRFrameRequestCallback, XRReferenceSpace, XRReferenceSpaceType, XRSession } from './WebXR'; export class WebXRManager extends EventDispatcher { @@ -19,12 +20,12 @@ export class WebXRManager extends EventDispatcher { getController( id: number ): Group; getControllerGrip( id: number ): Group; setFramebufferScaleFactor( value: number ): void; - setReferenceSpaceType( value: string ): void; - getReferenceSpace(): any; - getSession(): any; - setSession( value: any ): void; + setReferenceSpaceType( value: XRReferenceSpaceType ): void; + getReferenceSpace(): XRReferenceSpace; + getSession(): XRSession; + setSession( value: XRSession ): void; getCamera( camera: Camera ): Camera; - setAnimationLoop( callback: Function ): void; + setAnimationLoop( callback: XRFrameRequestCallback ): void; dispose(): void; } diff --git a/src/renderers/webxr/WebXRManager.js b/src/renderers/webxr/WebXRManager.js index 862e06e194f174..d8669cfe595a58 100644 --- a/src/renderers/webxr/WebXRManager.js +++ b/src/renderers/webxr/WebXRManager.js @@ -100,7 +100,7 @@ function WebXRManager( renderer, gl ) { if ( controller ) { - controller.dispatchEvent( { type: event.type } ); + controller.dispatchEvent( { type: event.type, data: event.inputSource } ); }