@epicgames-ps/lib-pixelstreamingfrontend-ue5.5 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. package/dist/commonjs/AFK/AFKController.js +109 -109
  2. package/dist/commonjs/Config/Config.js +559 -559
  3. package/dist/commonjs/Config/SettingBase.js +98 -98
  4. package/dist/commonjs/Config/SettingFlag.js +49 -49
  5. package/dist/commonjs/Config/SettingNumber.js +83 -83
  6. package/dist/commonjs/Config/SettingOption.js +84 -84
  7. package/dist/commonjs/Config/SettingText.js +42 -42
  8. package/dist/commonjs/DataChannel/DataChannelController.js +106 -106
  9. package/dist/commonjs/DataChannel/DataChannelLatencyTestController.js +94 -94
  10. package/dist/commonjs/DataChannel/DataChannelLatencyTestResults.js +18 -18
  11. package/dist/commonjs/DataChannel/DataChannelSender.js +43 -43
  12. package/dist/commonjs/DataChannel/InitialSettings.js +41 -41
  13. package/dist/commonjs/DataChannel/LatencyTestResults.js +60 -60
  14. package/dist/commonjs/FreezeFrame/FreezeFrame.js +93 -93
  15. package/dist/commonjs/FreezeFrame/FreezeFrameController.js +95 -95
  16. package/dist/commonjs/Inputs/GamepadController.js +188 -188
  17. package/dist/commonjs/Inputs/GamepadTypes.js +21 -21
  18. package/dist/commonjs/Inputs/IInputController.js +2 -2
  19. package/dist/commonjs/Inputs/InputClassesFactory.js +96 -96
  20. package/dist/commonjs/Inputs/KeyCodes.js +112 -112
  21. package/dist/commonjs/Inputs/KeyboardController.js +137 -137
  22. package/dist/commonjs/Inputs/MouseButtons.js +28 -28
  23. package/dist/commonjs/Inputs/MouseController.js +97 -97
  24. package/dist/commonjs/Inputs/MouseControllerHovering.js +93 -93
  25. package/dist/commonjs/Inputs/MouseControllerLocked.js +153 -153
  26. package/dist/commonjs/Inputs/SpecialKeyCodes.js +19 -19
  27. package/dist/commonjs/Inputs/TouchController.js +123 -123
  28. package/dist/commonjs/Inputs/TouchControllerFake.js +91 -91
  29. package/dist/commonjs/Inputs/XRGamepadController.js +124 -124
  30. package/dist/commonjs/PeerConnectionController/AggregatedStats.js +252 -252
  31. package/dist/commonjs/PeerConnectionController/CandidatePairStats.js +10 -10
  32. package/dist/commonjs/PeerConnectionController/CandidateStat.js +10 -10
  33. package/dist/commonjs/PeerConnectionController/CodecStats.js +10 -10
  34. package/dist/commonjs/PeerConnectionController/DataChannelStats.js +10 -10
  35. package/dist/commonjs/PeerConnectionController/InboundRTPStats.js +22 -22
  36. package/dist/commonjs/PeerConnectionController/InboundTrackStats.js +10 -10
  37. package/dist/commonjs/PeerConnectionController/OutBoundRTPStats.js +16 -16
  38. package/dist/commonjs/PeerConnectionController/PeerConnectionController.js +584 -584
  39. package/dist/commonjs/PeerConnectionController/SessionStats.js +10 -10
  40. package/dist/commonjs/PeerConnectionController/StreamStats.js +10 -10
  41. package/dist/commonjs/PixelStreaming/PixelStreaming.js +607 -607
  42. package/dist/commonjs/UI/OnScreenKeyboard.js +82 -82
  43. package/dist/commonjs/UeInstanceMessage/ResponseController.js +38 -38
  44. package/dist/commonjs/UeInstanceMessage/SendMessageController.js +120 -120
  45. package/dist/commonjs/UeInstanceMessage/StreamMessageController.js +210 -210
  46. package/dist/commonjs/UeInstanceMessage/ToStreamerMessagesController.js +49 -49
  47. package/dist/commonjs/Util/EventEmitter.js +386 -386
  48. package/dist/commonjs/Util/FileUtil.js +108 -108
  49. package/dist/commonjs/Util/IURLSearchParams.js +25 -25
  50. package/dist/commonjs/Util/InputCoordTranslator.js +49 -49
  51. package/dist/commonjs/Util/RTCUtils.js +40 -40
  52. package/dist/commonjs/VideoPlayer/StreamController.js +67 -67
  53. package/dist/commonjs/VideoPlayer/VideoPlayer.js +177 -177
  54. package/dist/commonjs/WebRtcPlayer/WebRtcPlayerController.js +1221 -1221
  55. package/dist/commonjs/WebXR/WebXRController.js +335 -335
  56. package/dist/commonjs/pixelstreamingfrontend.js +70 -70
  57. package/dist/esm/AFK/AFKController.js +105 -105
  58. package/dist/esm/Config/Config.js +551 -551
  59. package/dist/esm/Config/SettingBase.js +94 -94
  60. package/dist/esm/Config/SettingFlag.js +45 -45
  61. package/dist/esm/Config/SettingNumber.js +79 -79
  62. package/dist/esm/Config/SettingOption.js +80 -80
  63. package/dist/esm/Config/SettingText.js +38 -38
  64. package/dist/esm/DataChannel/DataChannelController.js +102 -102
  65. package/dist/esm/DataChannel/DataChannelLatencyTestController.js +90 -90
  66. package/dist/esm/DataChannel/DataChannelLatencyTestResults.js +14 -14
  67. package/dist/esm/DataChannel/DataChannelSender.js +39 -39
  68. package/dist/esm/DataChannel/InitialSettings.js +34 -34
  69. package/dist/esm/DataChannel/LatencyTestResults.js +56 -56
  70. package/dist/esm/FreezeFrame/FreezeFrame.js +89 -89
  71. package/dist/esm/FreezeFrame/FreezeFrameController.js +91 -91
  72. package/dist/esm/Inputs/GamepadController.js +184 -184
  73. package/dist/esm/Inputs/GamepadTypes.js +17 -17
  74. package/dist/esm/Inputs/IInputController.js +1 -1
  75. package/dist/esm/Inputs/InputClassesFactory.js +91 -91
  76. package/dist/esm/Inputs/KeyCodes.js +109 -109
  77. package/dist/esm/Inputs/KeyboardController.js +133 -133
  78. package/dist/esm/Inputs/MouseButtons.js +23 -23
  79. package/dist/esm/Inputs/MouseController.js +93 -93
  80. package/dist/esm/Inputs/MouseControllerHovering.js +89 -89
  81. package/dist/esm/Inputs/MouseControllerLocked.js +149 -149
  82. package/dist/esm/Inputs/SpecialKeyCodes.js +15 -15
  83. package/dist/esm/Inputs/TouchController.js +119 -119
  84. package/dist/esm/Inputs/TouchControllerFake.js +87 -87
  85. package/dist/esm/Inputs/XRGamepadController.js +120 -120
  86. package/dist/esm/PeerConnectionController/AggregatedStats.js +248 -248
  87. package/dist/esm/PeerConnectionController/CandidatePairStats.js +6 -6
  88. package/dist/esm/PeerConnectionController/CandidateStat.js +6 -6
  89. package/dist/esm/PeerConnectionController/CodecStats.js +6 -6
  90. package/dist/esm/PeerConnectionController/DataChannelStats.js +6 -6
  91. package/dist/esm/PeerConnectionController/InboundRTPStats.js +16 -16
  92. package/dist/esm/PeerConnectionController/InboundTrackStats.js +6 -6
  93. package/dist/esm/PeerConnectionController/OutBoundRTPStats.js +11 -11
  94. package/dist/esm/PeerConnectionController/PeerConnectionController.js +580 -580
  95. package/dist/esm/PeerConnectionController/SessionStats.js +6 -6
  96. package/dist/esm/PeerConnectionController/StreamStats.js +6 -6
  97. package/dist/esm/PixelStreaming/PixelStreaming.js +603 -603
  98. package/dist/esm/UI/OnScreenKeyboard.js +78 -78
  99. package/dist/esm/UeInstanceMessage/ResponseController.js +34 -34
  100. package/dist/esm/UeInstanceMessage/SendMessageController.js +116 -116
  101. package/dist/esm/UeInstanceMessage/StreamMessageController.js +205 -205
  102. package/dist/esm/UeInstanceMessage/ToStreamerMessagesController.js +45 -45
  103. package/dist/esm/Util/EventEmitter.js +345 -345
  104. package/dist/esm/Util/FileUtil.js +103 -103
  105. package/dist/esm/Util/IURLSearchParams.js +21 -21
  106. package/dist/esm/Util/InputCoordTranslator.js +45 -45
  107. package/dist/esm/Util/RTCUtils.js +36 -36
  108. package/dist/esm/VideoPlayer/StreamController.js +63 -63
  109. package/dist/esm/VideoPlayer/VideoPlayer.js +173 -173
  110. package/dist/esm/WebRtcPlayer/WebRtcPlayerController.js +1217 -1217
  111. package/dist/esm/WebXR/WebXRController.js +331 -331
  112. package/dist/esm/pixelstreamingfrontend.js +24 -24
  113. package/dist/types/AFK/AFKController.d.ts +38 -38
  114. package/dist/types/Config/Config.d.ts +220 -220
  115. package/dist/types/Config/SettingBase.d.ts +43 -43
  116. package/dist/types/Config/SettingFlag.d.ts +24 -24
  117. package/dist/types/Config/SettingNumber.d.ts +41 -41
  118. package/dist/types/Config/SettingOption.d.ts +41 -41
  119. package/dist/types/Config/SettingText.d.ts +21 -21
  120. package/dist/types/DataChannel/DataChannelController.d.ts +59 -59
  121. package/dist/types/DataChannel/DataChannelLatencyTestController.d.ts +25 -25
  122. package/dist/types/DataChannel/DataChannelLatencyTestResults.d.ts +46 -46
  123. package/dist/types/DataChannel/DataChannelSender.d.ts +21 -21
  124. package/dist/types/DataChannel/InitialSettings.d.ts +44 -44
  125. package/dist/types/DataChannel/LatencyTestResults.d.ts +31 -31
  126. package/dist/types/FreezeFrame/FreezeFrame.d.ts +36 -36
  127. package/dist/types/FreezeFrame/FreezeFrameController.d.ts +37 -37
  128. package/dist/types/Inputs/GamepadController.d.ts +61 -61
  129. package/dist/types/Inputs/GamepadTypes.d.ts +15 -15
  130. package/dist/types/Inputs/IInputController.d.ts +16 -16
  131. package/dist/types/Inputs/InputClassesFactory.d.ts +53 -53
  132. package/dist/types/Inputs/KeyCodes.d.ts +5 -5
  133. package/dist/types/Inputs/KeyboardController.d.ts +34 -34
  134. package/dist/types/Inputs/MouseButtons.d.ts +22 -22
  135. package/dist/types/Inputs/MouseController.d.ts +40 -40
  136. package/dist/types/Inputs/MouseControllerHovering.d.ts +26 -26
  137. package/dist/types/Inputs/MouseControllerLocked.d.ts +31 -31
  138. package/dist/types/Inputs/SpecialKeyCodes.d.ts +14 -14
  139. package/dist/types/Inputs/TouchController.d.ts +28 -28
  140. package/dist/types/Inputs/TouchControllerFake.d.ts +29 -29
  141. package/dist/types/Inputs/XRGamepadController.d.ts +15 -15
  142. package/dist/types/PeerConnectionController/AggregatedStats.d.ts +82 -82
  143. package/dist/types/PeerConnectionController/CandidatePairStats.d.ts +22 -22
  144. package/dist/types/PeerConnectionController/CandidateStat.d.ts +13 -13
  145. package/dist/types/PeerConnectionController/CodecStats.d.ts +14 -14
  146. package/dist/types/PeerConnectionController/DataChannelStats.d.ts +15 -15
  147. package/dist/types/PeerConnectionController/InboundRTPStats.d.ts +141 -141
  148. package/dist/types/PeerConnectionController/InboundTrackStats.d.ts +32 -32
  149. package/dist/types/PeerConnectionController/OutBoundRTPStats.d.ts +23 -23
  150. package/dist/types/PeerConnectionController/PeerConnectionController.d.ts +143 -143
  151. package/dist/types/PeerConnectionController/SessionStats.d.ts +8 -8
  152. package/dist/types/PeerConnectionController/StreamStats.d.ts +9 -9
  153. package/dist/types/PixelStreaming/PixelStreaming.d.ts +271 -271
  154. package/dist/types/UI/OnScreenKeyboard.d.ts +30 -30
  155. package/dist/types/UeInstanceMessage/ResponseController.d.ts +19 -19
  156. package/dist/types/UeInstanceMessage/SendMessageController.d.ts +18 -18
  157. package/dist/types/UeInstanceMessage/StreamMessageController.d.ts +29 -29
  158. package/dist/types/UeInstanceMessage/ToStreamerMessagesController.d.ts +32 -32
  159. package/dist/types/Util/EventEmitter.d.ts +429 -429
  160. package/dist/types/Util/FileUtil.d.ts +32 -32
  161. package/dist/types/Util/IURLSearchParams.d.ts +9 -9
  162. package/dist/types/Util/InputCoordTranslator.d.ts +29 -29
  163. package/dist/types/Util/RTCUtils.d.ts +8 -8
  164. package/dist/types/VideoPlayer/StreamController.d.ts +22 -22
  165. package/dist/types/VideoPlayer/VideoPlayer.d.ts +78 -78
  166. package/dist/types/WebRtcPlayer/WebRtcPlayerController.d.ts +379 -379
  167. package/dist/types/WebXR/WebXRController.d.ts +42 -42
  168. package/dist/types/pixelstreamingfrontend.d.ts +23 -23
  169. package/package.json +45 -45
@@ -1,65 +1,65 @@
1
- // Copyright Epic Games, Inc. All Rights Reserved.
2
- import { Logger } from '@epicgames-ps/lib-pixelstreamingcommon-ue5.5';
3
- import { XRGamepadController } from '../Inputs/XRGamepadController';
4
- import { XrFrameEvent } from '../Util/EventEmitter';
5
- import { Flags } from '../pixelstreamingfrontend';
6
- export class WebXRController {
7
- constructor(webRtcPlayerController) {
8
- this.xrViewerPose = null;
9
- // Used for comparisons to ensure two numbers are close enough.
10
- this.EPSILON = 0.0000001;
11
- this.videoTexture = null;
12
- this.prevVideoWidth = 0;
13
- this.prevVideoHeight = 0;
14
- this.leftView = null;
15
- this.rightView = null;
16
- // Store the HMD data we have last sent (not all of it is needed every frame unless it changes)
17
- this.lastSentLeftEyeProj = null;
18
- this.lastSentRightEyeProj = null;
19
- this.lastSentRelativeLeftEyePos = null;
20
- this.lastSentRelativeRightEyePos = null;
21
- this.xrSession = null;
22
- this.webRtcController = webRtcPlayerController;
23
- this.xrGamepadController = new XRGamepadController(this.webRtcController.streamMessageController);
24
- this.onSessionEnded = new EventTarget();
25
- this.onSessionStarted = new EventTarget();
26
- this.onFrame = new EventTarget();
27
- }
28
- xrClicked() {
29
- if (!this.xrSession) {
30
- if (!navigator.xr) {
31
- Logger.Error('This browser does not support XR.');
32
- return;
33
- }
34
- navigator.xr
35
- /* Request immersive-vr session without any optional features. */
36
- .requestSession('immersive-vr', { optionalFeatures: [] })
37
- .then((session) => {
38
- this.onXrSessionStarted(session);
39
- });
40
- }
41
- else {
42
- this.xrSession.end();
43
- }
44
- }
45
- onXrSessionEnded() {
46
- Logger.Info('XR Session ended');
47
- this.xrSession = null;
48
- this.onSessionEnded.dispatchEvent(new Event('xrSessionEnded'));
49
- }
50
- initGL() {
51
- if (this.gl) {
52
- return;
53
- }
54
- const canvas = document.createElement('canvas');
55
- this.gl = canvas.getContext('webgl2', {
56
- xrCompatible: true
57
- });
58
- // Set our clear color
59
- this.gl.clearColor(0.0, 0.0, 0.0, 1);
60
- }
61
- initShaders() {
62
- // shader source code
1
+ // Copyright Epic Games, Inc. All Rights Reserved.
2
+ import { Logger } from '@epicgames-ps/lib-pixelstreamingcommon-ue5.5';
3
+ import { XRGamepadController } from '../Inputs/XRGamepadController';
4
+ import { XrFrameEvent } from '../Util/EventEmitter';
5
+ import { Flags } from '../pixelstreamingfrontend';
6
+ export class WebXRController {
7
+ constructor(webRtcPlayerController) {
8
+ this.xrViewerPose = null;
9
+ // Used for comparisons to ensure two numbers are close enough.
10
+ this.EPSILON = 0.0000001;
11
+ this.videoTexture = null;
12
+ this.prevVideoWidth = 0;
13
+ this.prevVideoHeight = 0;
14
+ this.leftView = null;
15
+ this.rightView = null;
16
+ // Store the HMD data we have last sent (not all of it is needed every frame unless it changes)
17
+ this.lastSentLeftEyeProj = null;
18
+ this.lastSentRightEyeProj = null;
19
+ this.lastSentRelativeLeftEyePos = null;
20
+ this.lastSentRelativeRightEyePos = null;
21
+ this.xrSession = null;
22
+ this.webRtcController = webRtcPlayerController;
23
+ this.xrGamepadController = new XRGamepadController(this.webRtcController.streamMessageController);
24
+ this.onSessionEnded = new EventTarget();
25
+ this.onSessionStarted = new EventTarget();
26
+ this.onFrame = new EventTarget();
27
+ }
28
+ xrClicked() {
29
+ if (!this.xrSession) {
30
+ if (!navigator.xr) {
31
+ Logger.Error('This browser does not support XR.');
32
+ return;
33
+ }
34
+ navigator.xr
35
+ /* Request immersive-vr session without any optional features. */
36
+ .requestSession('immersive-vr', { optionalFeatures: [] })
37
+ .then((session) => {
38
+ this.onXrSessionStarted(session);
39
+ });
40
+ }
41
+ else {
42
+ this.xrSession.end();
43
+ }
44
+ }
45
+ onXrSessionEnded() {
46
+ Logger.Info('XR Session ended');
47
+ this.xrSession = null;
48
+ this.onSessionEnded.dispatchEvent(new Event('xrSessionEnded'));
49
+ }
50
+ initGL() {
51
+ if (this.gl) {
52
+ return;
53
+ }
54
+ const canvas = document.createElement('canvas');
55
+ this.gl = canvas.getContext('webgl2', {
56
+ xrCompatible: true
57
+ });
58
+ // Set our clear color
59
+ this.gl.clearColor(0.0, 0.0, 0.0, 1);
60
+ }
61
+ initShaders() {
62
+ // shader source code
63
63
  const vertexShaderSource = `
64
64
  attribute vec2 a_position;
65
65
  attribute vec2 a_texCoord;
@@ -73,7 +73,7 @@ export class WebXRController {
73
73
  // The GPU will interpolate this value between points.
74
74
  v_texCoord = a_texCoord;
75
75
  }
76
- `;
76
+ `;
77
77
  const fragmentShaderSource = `
78
78
  precision mediump float;
79
79
 
@@ -86,272 +86,272 @@ export class WebXRController {
86
86
  void main() {
87
87
  gl_FragColor = texture2D(u_image, v_texCoord);
88
88
  }
89
- `;
90
- // setup vertex shader
91
- const vertexShader = this.gl.createShader(this.gl.VERTEX_SHADER);
92
- this.gl.shaderSource(vertexShader, vertexShaderSource);
93
- this.gl.compileShader(vertexShader);
94
- // setup fragment shader
95
- const fragmentShader = this.gl.createShader(this.gl.FRAGMENT_SHADER);
96
- this.gl.shaderSource(fragmentShader, fragmentShaderSource);
97
- this.gl.compileShader(fragmentShader);
98
- // setup GLSL program
99
- const shaderProgram = this.gl.createProgram();
100
- this.gl.attachShader(shaderProgram, vertexShader);
101
- this.gl.attachShader(shaderProgram, fragmentShader);
102
- this.gl.linkProgram(shaderProgram);
103
- this.gl.useProgram(shaderProgram);
104
- // look up where vertex data needs to go
105
- this.positionLocation = this.gl.getAttribLocation(shaderProgram, 'a_position');
106
- this.texcoordLocation = this.gl.getAttribLocation(shaderProgram, 'a_texCoord');
107
- }
108
- updateVideoTexture() {
109
- if (!this.videoTexture) {
110
- // Create our texture that we use in our shader
111
- // and bind it once because we never use any other texture.
112
- this.videoTexture = this.gl.createTexture();
113
- this.gl.bindTexture(this.gl.TEXTURE_2D, this.videoTexture);
114
- // Set the parameters so we can render any size image.
115
- this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);
116
- this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);
117
- this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);
118
- this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);
119
- }
120
- const videoHeight = this.webRtcController.videoPlayer.getVideoElement().videoHeight;
121
- const videoWidth = this.webRtcController.videoPlayer.getVideoElement().videoWidth;
122
- if (this.prevVideoHeight != videoHeight || this.prevVideoWidth != videoWidth) {
123
- // Do full update of texture if dimensions do not match
124
- this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, videoWidth, videoHeight, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, this.webRtcController.videoPlayer.getVideoElement());
125
- }
126
- else {
127
- // If dimensions match just update the sub region
128
- this.gl.texSubImage2D(this.gl.TEXTURE_2D, 0, 0, 0, videoWidth, videoHeight, this.gl.RGBA, this.gl.UNSIGNED_BYTE, this.webRtcController.videoPlayer.getVideoElement());
129
- }
130
- // Update prev video width/height
131
- this.prevVideoHeight = videoHeight;
132
- this.prevVideoWidth = videoWidth;
133
- }
134
- initBuffers() {
135
- // Create out position buffer and its vertex shader attribute
136
- {
137
- // Create a buffer to put the the vertices of the plane we will draw the video stream onto
138
- this.positionBuffer = this.gl.createBuffer();
139
- // Bind the position buffer
140
- this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.positionBuffer);
141
- // Enable `positionLocation` to be used as vertex shader attribute
142
- this.gl.enableVertexAttribArray(this.positionLocation);
143
- // Note: positions are passed in clip-space coordinates [-1..1] so no need to convert in-shader
144
- // prettier-ignore
145
- this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array([
146
- -1.0, 1.0,
147
- 1.0, 1.0,
148
- -1.0, -1.0,
149
- -1.0, -1.0,
150
- 1.0, 1.0,
151
- 1.0, -1.0
152
- ]), this.gl.STATIC_DRAW);
153
- // Tell position attribute of the vertex shader how to get data out of the bound buffer (the positionBuffer)
154
- this.gl.vertexAttribPointer(this.positionLocation, 2 /*size*/, this.gl.FLOAT /*type*/, false /*normalize*/, 0 /*stride*/, 0 /*offset*/);
155
- }
156
- // Create our texture coordinate buffers for accessing our texture
157
- {
158
- this.texcoordBuffer = this.gl.createBuffer();
159
- // Bind the texture coordinate buffer
160
- this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.texcoordBuffer);
161
- // Enable `texcoordLocation` to be used as a vertex shader attribute
162
- this.gl.enableVertexAttribArray(this.texcoordLocation);
163
- // The texture coordinates to apply for rectangle we are drawing
164
- this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0]), this.gl.STATIC_DRAW);
165
- // Tell texture coordinate attribute of the vertex shader how to get data out of the bound buffer (the texcoordBuffer)
166
- this.gl.vertexAttribPointer(this.texcoordLocation, 2 /*size*/, this.gl.FLOAT /*type*/, false /*normalize*/, 0 /*stride*/, 0 /*offset*/);
167
- }
168
- }
169
- onXrSessionStarted(session) {
170
- Logger.Info('XR Session started');
171
- this.xrSession = session;
172
- this.xrSession.addEventListener('end', () => {
173
- this.onXrSessionEnded();
174
- });
175
- // Initialization
176
- this.initGL();
177
- this.initShaders();
178
- this.initBuffers();
179
- session.requestReferenceSpace('local').then((refSpace) => {
180
- this.xrRefSpace = refSpace;
181
- // Set up our base layer (i.e. a projection layer that fills the entire XR viewport).
182
- this.xrSession.updateRenderState({
183
- baseLayer: new XRWebGLLayer(this.xrSession, this.gl)
184
- });
185
- // Update target framerate to 90 fps if 90 fps is supported in this XR device
186
- if (this.xrSession.supportedFrameRates) {
187
- for (const frameRate of this.xrSession.supportedFrameRates) {
188
- if (frameRate == 90) {
189
- session.updateTargetFrameRate(90);
190
- }
191
- }
192
- }
193
- // Binding to each new frame to get latest XR updates
194
- this.xrSession.requestAnimationFrame(this.onXrFrame.bind(this));
195
- });
196
- this.onSessionStarted.dispatchEvent(new Event('xrSessionStarted'));
197
- }
198
- areArraysEqual(a, b) {
199
- return (a.length === b.length && a.every((element, index) => Math.abs(element - b[index]) <= this.EPSILON));
200
- }
201
- arePointsEqual(a, b) {
202
- return (Math.abs(a.x - b.x) >= this.EPSILON &&
203
- Math.abs(a.y - b.y) >= this.EPSILON &&
204
- Math.abs(a.z - b.z) >= this.EPSILON);
205
- }
206
- sendXRDataToUE() {
207
- if (this.leftView == null || this.rightView == null) {
208
- return;
209
- }
210
- // We selectively send either the `XREyeViews` or `XRHMDTransform`
211
- // messages over the datachannel. The reason for this selective sending is that
212
- // the `XREyeViews` is a much larger message and changes infrequently (e.g. only when user changes headset IPD).
213
- // Therefore, we only need to send it once on startup and then any time it changes.
214
- // The rest of the time we can send the `XRHMDTransform` message.
215
- let shouldSendEyeViews = this.lastSentLeftEyeProj == null ||
216
- this.lastSentRightEyeProj == null ||
217
- this.lastSentRelativeLeftEyePos == null ||
218
- this.lastSentRelativeRightEyePos == null;
219
- const leftEyeTrans = this.leftView.transform.matrix;
220
- const leftEyeProj = this.leftView.projectionMatrix;
221
- const rightEyeTrans = this.rightView.transform.matrix;
222
- const rightEyeProj = this.rightView.projectionMatrix;
223
- const hmdTrans = this.xrViewerPose.transform.matrix;
224
- // Check if projection matrices have changed
225
- if (!shouldSendEyeViews && this.lastSentLeftEyeProj != null && this.lastSentRightEyeProj != null) {
226
- const leftEyeProjUnchanged = this.areArraysEqual(leftEyeProj, this.lastSentLeftEyeProj);
227
- const rightEyeProjUnchanged = this.areArraysEqual(rightEyeProj, this.lastSentRightEyeProj);
228
- shouldSendEyeViews = leftEyeProjUnchanged == false || rightEyeProjUnchanged == false;
229
- }
230
- const leftEyeRelativePos = new DOMPointReadOnly(this.leftView.transform.position.x - this.xrViewerPose.transform.position.x, this.leftView.transform.position.y - this.xrViewerPose.transform.position.y, this.leftView.transform.position.z - this.xrViewerPose.transform.position.z, 1.0);
231
- const rightEyeRelativePos = new DOMPointReadOnly(this.leftView.transform.position.x - this.xrViewerPose.transform.position.x, this.leftView.transform.position.y - this.xrViewerPose.transform.position.y, this.leftView.transform.position.z - this.xrViewerPose.transform.position.z, 1.0);
232
- // Check if relative eye pos has changed (e.g IPD changed)
233
- if (!shouldSendEyeViews &&
234
- this.lastSentRelativeLeftEyePos != null &&
235
- this.lastSentRelativeRightEyePos != null) {
236
- const leftEyePosUnchanged = this.arePointsEqual(leftEyeRelativePos, this.lastSentRelativeLeftEyePos);
237
- const rightEyePosUnchanged = this.arePointsEqual(rightEyeRelativePos, this.lastSentRelativeRightEyePos);
238
- shouldSendEyeViews = leftEyePosUnchanged == false || rightEyePosUnchanged == false;
239
- // Note: We are not checking if EyeView rotation changes (as far as I know no HMD supports changing this value at runtime).
240
- }
241
- if (shouldSendEyeViews) {
242
- // send transform (4x4) and projection matrix (4x4) data for each eye (left first, then right)
243
- // prettier-ignore
244
- this.webRtcController.streamMessageController.toStreamerHandlers.get('XREyeViews')([
245
- // Left eye 4x4 transform matrix
246
- leftEyeTrans[0], leftEyeTrans[4], leftEyeTrans[8], leftEyeTrans[12],
247
- leftEyeTrans[1], leftEyeTrans[5], leftEyeTrans[9], leftEyeTrans[13],
248
- leftEyeTrans[2], leftEyeTrans[6], leftEyeTrans[10], leftEyeTrans[14],
249
- leftEyeTrans[3], leftEyeTrans[7], leftEyeTrans[11], leftEyeTrans[15],
250
- // Left eye 4x4 projection matrix
251
- leftEyeProj[0], leftEyeProj[4], leftEyeProj[8], leftEyeProj[12],
252
- leftEyeProj[1], leftEyeProj[5], leftEyeProj[9], leftEyeProj[13],
253
- leftEyeProj[2], leftEyeProj[6], leftEyeProj[10], leftEyeProj[14],
254
- leftEyeProj[3], leftEyeProj[7], leftEyeProj[11], leftEyeProj[15],
255
- // Right eye 4x4 transform matrix
256
- rightEyeTrans[0], rightEyeTrans[4], rightEyeTrans[8], rightEyeTrans[12],
257
- rightEyeTrans[1], rightEyeTrans[5], rightEyeTrans[9], rightEyeTrans[13],
258
- rightEyeTrans[2], rightEyeTrans[6], rightEyeTrans[10], rightEyeTrans[14],
259
- rightEyeTrans[3], rightEyeTrans[7], rightEyeTrans[11], rightEyeTrans[15],
260
- // right eye 4x4 projection matrix
261
- rightEyeProj[0], rightEyeProj[4], rightEyeProj[8], rightEyeProj[12],
262
- rightEyeProj[1], rightEyeProj[5], rightEyeProj[9], rightEyeProj[13],
263
- rightEyeProj[2], rightEyeProj[6], rightEyeProj[10], rightEyeProj[14],
264
- rightEyeProj[3], rightEyeProj[7], rightEyeProj[11], rightEyeProj[15],
265
- // HMD 4x4 transform
266
- hmdTrans[0], hmdTrans[4], hmdTrans[8], hmdTrans[12],
267
- hmdTrans[1], hmdTrans[5], hmdTrans[9], hmdTrans[13],
268
- hmdTrans[2], hmdTrans[6], hmdTrans[10], hmdTrans[14],
269
- hmdTrans[3], hmdTrans[7], hmdTrans[11], hmdTrans[15],
270
- ]);
271
- this.lastSentLeftEyeProj = leftEyeProj;
272
- this.lastSentRightEyeProj = rightEyeProj;
273
- this.lastSentRelativeLeftEyePos = leftEyeRelativePos;
274
- this.lastSentRelativeRightEyePos = rightEyeRelativePos;
275
- }
276
- else {
277
- // If we don't need to the entire eye views being sent just send the HMD transform
278
- this.webRtcController.streamMessageController.toStreamerHandlers.get('XRHMDTransform')([
279
- // HMD 4x4 transform
280
- hmdTrans[0],
281
- hmdTrans[4],
282
- hmdTrans[8],
283
- hmdTrans[12],
284
- hmdTrans[1],
285
- hmdTrans[5],
286
- hmdTrans[9],
287
- hmdTrans[13],
288
- hmdTrans[2],
289
- hmdTrans[6],
290
- hmdTrans[10],
291
- hmdTrans[14],
292
- hmdTrans[3],
293
- hmdTrans[7],
294
- hmdTrans[11],
295
- hmdTrans[15]
296
- ]);
297
- }
298
- }
299
- onXrFrame(time, frame) {
300
- this.xrViewerPose = frame.getViewerPose(this.xrRefSpace);
301
- if (this.xrViewerPose) {
302
- this.updateViews();
303
- if (this.leftView == null || this.rightView == null) {
304
- return;
305
- }
306
- this.sendXRDataToUE();
307
- this.updateVideoTexture();
308
- this.render();
309
- }
310
- if (this.webRtcController.config.isFlagEnabled(Flags.XRControllerInput)) {
311
- this.xrSession.inputSources.forEach((source, _index, _array) => {
312
- this.xrGamepadController.updateStatus(source, frame, this.xrRefSpace);
313
- }, this);
314
- }
315
- this.xrSession.requestAnimationFrame((time, frame) => this.onXrFrame(time, frame));
316
- this.onFrame.dispatchEvent(new XrFrameEvent({ time, frame }));
317
- }
318
- updateViews() {
319
- if (!this.xrViewerPose) {
320
- return;
321
- }
322
- for (const view of this.xrViewerPose.views) {
323
- if (view.eye === 'left') {
324
- this.leftView = view;
325
- }
326
- else if (view.eye === 'right') {
327
- this.rightView = view;
328
- }
329
- }
330
- }
331
- render() {
332
- if (!this.gl) {
333
- return;
334
- }
335
- // Bind the framebuffer to the base layer's framebuffer
336
- const glLayer = this.xrSession.renderState.baseLayer;
337
- this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, glLayer.framebuffer);
338
- // Set the relevant portion of clip space
339
- this.gl.viewport(0, 0, glLayer.framebufferWidth, glLayer.framebufferHeight);
340
- // Draw the rectangle we will show the video stream texture on
341
- this.gl.drawArrays(this.gl.TRIANGLES /*primitiveType*/, 0 /*offset*/, 6 /*count*/);
342
- }
343
- static isSessionSupported(mode) {
344
- if (location.protocol !== 'https:') {
345
- Logger.Info('WebXR requires https, if you want WebXR use https.');
346
- }
347
- if (navigator.xr) {
348
- return navigator.xr.isSessionSupported(mode);
349
- }
350
- else {
351
- return new Promise(() => {
352
- return false;
353
- });
354
- }
355
- }
356
- }
89
+ `;
90
+ // setup vertex shader
91
+ const vertexShader = this.gl.createShader(this.gl.VERTEX_SHADER);
92
+ this.gl.shaderSource(vertexShader, vertexShaderSource);
93
+ this.gl.compileShader(vertexShader);
94
+ // setup fragment shader
95
+ const fragmentShader = this.gl.createShader(this.gl.FRAGMENT_SHADER);
96
+ this.gl.shaderSource(fragmentShader, fragmentShaderSource);
97
+ this.gl.compileShader(fragmentShader);
98
+ // setup GLSL program
99
+ const shaderProgram = this.gl.createProgram();
100
+ this.gl.attachShader(shaderProgram, vertexShader);
101
+ this.gl.attachShader(shaderProgram, fragmentShader);
102
+ this.gl.linkProgram(shaderProgram);
103
+ this.gl.useProgram(shaderProgram);
104
+ // look up where vertex data needs to go
105
+ this.positionLocation = this.gl.getAttribLocation(shaderProgram, 'a_position');
106
+ this.texcoordLocation = this.gl.getAttribLocation(shaderProgram, 'a_texCoord');
107
+ }
108
+ updateVideoTexture() {
109
+ if (!this.videoTexture) {
110
+ // Create our texture that we use in our shader
111
+ // and bind it once because we never use any other texture.
112
+ this.videoTexture = this.gl.createTexture();
113
+ this.gl.bindTexture(this.gl.TEXTURE_2D, this.videoTexture);
114
+ // Set the parameters so we can render any size image.
115
+ this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);
116
+ this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);
117
+ this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);
118
+ this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);
119
+ }
120
+ const videoHeight = this.webRtcController.videoPlayer.getVideoElement().videoHeight;
121
+ const videoWidth = this.webRtcController.videoPlayer.getVideoElement().videoWidth;
122
+ if (this.prevVideoHeight != videoHeight || this.prevVideoWidth != videoWidth) {
123
+ // Do full update of texture if dimensions do not match
124
+ this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, videoWidth, videoHeight, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, this.webRtcController.videoPlayer.getVideoElement());
125
+ }
126
+ else {
127
+ // If dimensions match just update the sub region
128
+ this.gl.texSubImage2D(this.gl.TEXTURE_2D, 0, 0, 0, videoWidth, videoHeight, this.gl.RGBA, this.gl.UNSIGNED_BYTE, this.webRtcController.videoPlayer.getVideoElement());
129
+ }
130
+ // Update prev video width/height
131
+ this.prevVideoHeight = videoHeight;
132
+ this.prevVideoWidth = videoWidth;
133
+ }
134
+ initBuffers() {
135
+ // Create out position buffer and its vertex shader attribute
136
+ {
137
+ // Create a buffer to put the the vertices of the plane we will draw the video stream onto
138
+ this.positionBuffer = this.gl.createBuffer();
139
+ // Bind the position buffer
140
+ this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.positionBuffer);
141
+ // Enable `positionLocation` to be used as vertex shader attribute
142
+ this.gl.enableVertexAttribArray(this.positionLocation);
143
+ // Note: positions are passed in clip-space coordinates [-1..1] so no need to convert in-shader
144
+ // prettier-ignore
145
+ this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array([
146
+ -1.0, 1.0,
147
+ 1.0, 1.0,
148
+ -1.0, -1.0,
149
+ -1.0, -1.0,
150
+ 1.0, 1.0,
151
+ 1.0, -1.0
152
+ ]), this.gl.STATIC_DRAW);
153
+ // Tell position attribute of the vertex shader how to get data out of the bound buffer (the positionBuffer)
154
+ this.gl.vertexAttribPointer(this.positionLocation, 2 /*size*/, this.gl.FLOAT /*type*/, false /*normalize*/, 0 /*stride*/, 0 /*offset*/);
155
+ }
156
+ // Create our texture coordinate buffers for accessing our texture
157
+ {
158
+ this.texcoordBuffer = this.gl.createBuffer();
159
+ // Bind the texture coordinate buffer
160
+ this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.texcoordBuffer);
161
+ // Enable `texcoordLocation` to be used as a vertex shader attribute
162
+ this.gl.enableVertexAttribArray(this.texcoordLocation);
163
+ // The texture coordinates to apply for rectangle we are drawing
164
+ this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0]), this.gl.STATIC_DRAW);
165
+ // Tell texture coordinate attribute of the vertex shader how to get data out of the bound buffer (the texcoordBuffer)
166
+ this.gl.vertexAttribPointer(this.texcoordLocation, 2 /*size*/, this.gl.FLOAT /*type*/, false /*normalize*/, 0 /*stride*/, 0 /*offset*/);
167
+ }
168
+ }
169
+ onXrSessionStarted(session) {
170
+ Logger.Info('XR Session started');
171
+ this.xrSession = session;
172
+ this.xrSession.addEventListener('end', () => {
173
+ this.onXrSessionEnded();
174
+ });
175
+ // Initialization
176
+ this.initGL();
177
+ this.initShaders();
178
+ this.initBuffers();
179
+ session.requestReferenceSpace('local').then((refSpace) => {
180
+ this.xrRefSpace = refSpace;
181
+ // Set up our base layer (i.e. a projection layer that fills the entire XR viewport).
182
+ this.xrSession.updateRenderState({
183
+ baseLayer: new XRWebGLLayer(this.xrSession, this.gl)
184
+ });
185
+ // Update target framerate to 90 fps if 90 fps is supported in this XR device
186
+ if (this.xrSession.supportedFrameRates) {
187
+ for (const frameRate of this.xrSession.supportedFrameRates) {
188
+ if (frameRate == 90) {
189
+ session.updateTargetFrameRate(90);
190
+ }
191
+ }
192
+ }
193
+ // Binding to each new frame to get latest XR updates
194
+ this.xrSession.requestAnimationFrame(this.onXrFrame.bind(this));
195
+ });
196
+ this.onSessionStarted.dispatchEvent(new Event('xrSessionStarted'));
197
+ }
198
+ areArraysEqual(a, b) {
199
+ return (a.length === b.length && a.every((element, index) => Math.abs(element - b[index]) <= this.EPSILON));
200
+ }
201
+ arePointsEqual(a, b) {
202
+ return (Math.abs(a.x - b.x) >= this.EPSILON &&
203
+ Math.abs(a.y - b.y) >= this.EPSILON &&
204
+ Math.abs(a.z - b.z) >= this.EPSILON);
205
+ }
206
+ sendXRDataToUE() {
207
+ if (this.leftView == null || this.rightView == null) {
208
+ return;
209
+ }
210
+ // We selectively send either the `XREyeViews` or `XRHMDTransform`
211
+ // messages over the datachannel. The reason for this selective sending is that
212
+ // the `XREyeViews` is a much larger message and changes infrequently (e.g. only when user changes headset IPD).
213
+ // Therefore, we only need to send it once on startup and then any time it changes.
214
+ // The rest of the time we can send the `XRHMDTransform` message.
215
+ let shouldSendEyeViews = this.lastSentLeftEyeProj == null ||
216
+ this.lastSentRightEyeProj == null ||
217
+ this.lastSentRelativeLeftEyePos == null ||
218
+ this.lastSentRelativeRightEyePos == null;
219
+ const leftEyeTrans = this.leftView.transform.matrix;
220
+ const leftEyeProj = this.leftView.projectionMatrix;
221
+ const rightEyeTrans = this.rightView.transform.matrix;
222
+ const rightEyeProj = this.rightView.projectionMatrix;
223
+ const hmdTrans = this.xrViewerPose.transform.matrix;
224
+ // Check if projection matrices have changed
225
+ if (!shouldSendEyeViews && this.lastSentLeftEyeProj != null && this.lastSentRightEyeProj != null) {
226
+ const leftEyeProjUnchanged = this.areArraysEqual(leftEyeProj, this.lastSentLeftEyeProj);
227
+ const rightEyeProjUnchanged = this.areArraysEqual(rightEyeProj, this.lastSentRightEyeProj);
228
+ shouldSendEyeViews = leftEyeProjUnchanged == false || rightEyeProjUnchanged == false;
229
+ }
230
+ const leftEyeRelativePos = new DOMPointReadOnly(this.leftView.transform.position.x - this.xrViewerPose.transform.position.x, this.leftView.transform.position.y - this.xrViewerPose.transform.position.y, this.leftView.transform.position.z - this.xrViewerPose.transform.position.z, 1.0);
231
+ const rightEyeRelativePos = new DOMPointReadOnly(this.leftView.transform.position.x - this.xrViewerPose.transform.position.x, this.leftView.transform.position.y - this.xrViewerPose.transform.position.y, this.leftView.transform.position.z - this.xrViewerPose.transform.position.z, 1.0);
232
+ // Check if relative eye pos has changed (e.g IPD changed)
233
+ if (!shouldSendEyeViews &&
234
+ this.lastSentRelativeLeftEyePos != null &&
235
+ this.lastSentRelativeRightEyePos != null) {
236
+ const leftEyePosUnchanged = this.arePointsEqual(leftEyeRelativePos, this.lastSentRelativeLeftEyePos);
237
+ const rightEyePosUnchanged = this.arePointsEqual(rightEyeRelativePos, this.lastSentRelativeRightEyePos);
238
+ shouldSendEyeViews = leftEyePosUnchanged == false || rightEyePosUnchanged == false;
239
+ // Note: We are not checking if EyeView rotation changes (as far as I know no HMD supports changing this value at runtime).
240
+ }
241
+ if (shouldSendEyeViews) {
242
+ // send transform (4x4) and projection matrix (4x4) data for each eye (left first, then right)
243
+ // prettier-ignore
244
+ this.webRtcController.streamMessageController.toStreamerHandlers.get('XREyeViews')([
245
+ // Left eye 4x4 transform matrix
246
+ leftEyeTrans[0], leftEyeTrans[4], leftEyeTrans[8], leftEyeTrans[12],
247
+ leftEyeTrans[1], leftEyeTrans[5], leftEyeTrans[9], leftEyeTrans[13],
248
+ leftEyeTrans[2], leftEyeTrans[6], leftEyeTrans[10], leftEyeTrans[14],
249
+ leftEyeTrans[3], leftEyeTrans[7], leftEyeTrans[11], leftEyeTrans[15],
250
+ // Left eye 4x4 projection matrix
251
+ leftEyeProj[0], leftEyeProj[4], leftEyeProj[8], leftEyeProj[12],
252
+ leftEyeProj[1], leftEyeProj[5], leftEyeProj[9], leftEyeProj[13],
253
+ leftEyeProj[2], leftEyeProj[6], leftEyeProj[10], leftEyeProj[14],
254
+ leftEyeProj[3], leftEyeProj[7], leftEyeProj[11], leftEyeProj[15],
255
+ // Right eye 4x4 transform matrix
256
+ rightEyeTrans[0], rightEyeTrans[4], rightEyeTrans[8], rightEyeTrans[12],
257
+ rightEyeTrans[1], rightEyeTrans[5], rightEyeTrans[9], rightEyeTrans[13],
258
+ rightEyeTrans[2], rightEyeTrans[6], rightEyeTrans[10], rightEyeTrans[14],
259
+ rightEyeTrans[3], rightEyeTrans[7], rightEyeTrans[11], rightEyeTrans[15],
260
+ // right eye 4x4 projection matrix
261
+ rightEyeProj[0], rightEyeProj[4], rightEyeProj[8], rightEyeProj[12],
262
+ rightEyeProj[1], rightEyeProj[5], rightEyeProj[9], rightEyeProj[13],
263
+ rightEyeProj[2], rightEyeProj[6], rightEyeProj[10], rightEyeProj[14],
264
+ rightEyeProj[3], rightEyeProj[7], rightEyeProj[11], rightEyeProj[15],
265
+ // HMD 4x4 transform
266
+ hmdTrans[0], hmdTrans[4], hmdTrans[8], hmdTrans[12],
267
+ hmdTrans[1], hmdTrans[5], hmdTrans[9], hmdTrans[13],
268
+ hmdTrans[2], hmdTrans[6], hmdTrans[10], hmdTrans[14],
269
+ hmdTrans[3], hmdTrans[7], hmdTrans[11], hmdTrans[15],
270
+ ]);
271
+ this.lastSentLeftEyeProj = leftEyeProj;
272
+ this.lastSentRightEyeProj = rightEyeProj;
273
+ this.lastSentRelativeLeftEyePos = leftEyeRelativePos;
274
+ this.lastSentRelativeRightEyePos = rightEyeRelativePos;
275
+ }
276
+ else {
277
+ // If we don't need to the entire eye views being sent just send the HMD transform
278
+ this.webRtcController.streamMessageController.toStreamerHandlers.get('XRHMDTransform')([
279
+ // HMD 4x4 transform
280
+ hmdTrans[0],
281
+ hmdTrans[4],
282
+ hmdTrans[8],
283
+ hmdTrans[12],
284
+ hmdTrans[1],
285
+ hmdTrans[5],
286
+ hmdTrans[9],
287
+ hmdTrans[13],
288
+ hmdTrans[2],
289
+ hmdTrans[6],
290
+ hmdTrans[10],
291
+ hmdTrans[14],
292
+ hmdTrans[3],
293
+ hmdTrans[7],
294
+ hmdTrans[11],
295
+ hmdTrans[15]
296
+ ]);
297
+ }
298
+ }
299
+ onXrFrame(time, frame) {
300
+ this.xrViewerPose = frame.getViewerPose(this.xrRefSpace);
301
+ if (this.xrViewerPose) {
302
+ this.updateViews();
303
+ if (this.leftView == null || this.rightView == null) {
304
+ return;
305
+ }
306
+ this.sendXRDataToUE();
307
+ this.updateVideoTexture();
308
+ this.render();
309
+ }
310
+ if (this.webRtcController.config.isFlagEnabled(Flags.XRControllerInput)) {
311
+ this.xrSession.inputSources.forEach((source, _index, _array) => {
312
+ this.xrGamepadController.updateStatus(source, frame, this.xrRefSpace);
313
+ }, this);
314
+ }
315
+ this.xrSession.requestAnimationFrame((time, frame) => this.onXrFrame(time, frame));
316
+ this.onFrame.dispatchEvent(new XrFrameEvent({ time, frame }));
317
+ }
318
+ updateViews() {
319
+ if (!this.xrViewerPose) {
320
+ return;
321
+ }
322
+ for (const view of this.xrViewerPose.views) {
323
+ if (view.eye === 'left') {
324
+ this.leftView = view;
325
+ }
326
+ else if (view.eye === 'right') {
327
+ this.rightView = view;
328
+ }
329
+ }
330
+ }
331
+ render() {
332
+ if (!this.gl) {
333
+ return;
334
+ }
335
+ // Bind the framebuffer to the base layer's framebuffer
336
+ const glLayer = this.xrSession.renderState.baseLayer;
337
+ this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, glLayer.framebuffer);
338
+ // Set the relevant portion of clip space
339
+ this.gl.viewport(0, 0, glLayer.framebufferWidth, glLayer.framebufferHeight);
340
+ // Draw the rectangle we will show the video stream texture on
341
+ this.gl.drawArrays(this.gl.TRIANGLES /*primitiveType*/, 0 /*offset*/, 6 /*count*/);
342
+ }
343
+ static isSessionSupported(mode) {
344
+ if (location.protocol !== 'https:') {
345
+ Logger.Info('WebXR requires https, if you want WebXR use https.');
346
+ }
347
+ if (navigator.xr) {
348
+ return navigator.xr.isSessionSupported(mode);
349
+ }
350
+ else {
351
+ return new Promise(() => {
352
+ return false;
353
+ });
354
+ }
355
+ }
356
+ }
357
357
  //# sourceMappingURL=WebXRController.js.map