@needle-tools/engine 2.29.0-pre → 2.31.0-pre
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.
- package/CHANGELOG.md +13 -0
- package/dist/needle-engine.d.ts +847 -757
- package/dist/needle-engine.js +347 -343
- package/dist/needle-engine.js.map +4 -4
- package/dist/needle-engine.min.js +16 -12
- package/dist/needle-engine.min.js.map +4 -4
- package/lib/engine/engine.d.ts +1 -0
- package/lib/engine/engine_physics.d.ts +19 -8
- package/lib/engine/engine_physics.js +57 -48
- package/lib/engine/engine_physics.js.map +1 -1
- package/lib/engine/engine_serialization.d.ts +1 -0
- package/lib/engine/engine_serialization.js +1 -0
- package/lib/engine/engine_serialization.js.map +1 -1
- package/lib/engine/engine_setup.d.ts +5 -0
- package/lib/engine/engine_setup.js +6 -0
- package/lib/engine/engine_setup.js.map +1 -1
- package/lib/engine/engine_utils.d.ts +1 -1
- package/lib/engine/engine_utils.js +25 -8
- package/lib/engine/engine_utils.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_deferred_texture.d.ts +1 -1
- package/lib/engine/extensions/NEEDLE_deferred_texture.js +26 -14
- package/lib/engine/extensions/NEEDLE_deferred_texture.js.map +1 -1
- package/lib/engine/extensions/extension_utils.js +24 -13
- package/lib/engine/extensions/extension_utils.js.map +1 -1
- package/lib/engine/extensions/extensions.js +3 -1
- package/lib/engine/extensions/extensions.js.map +1 -1
- package/lib/engine-components/Camera.js +7 -1
- package/lib/engine-components/Camera.js.map +1 -1
- package/lib/engine-components/Component.d.ts +10 -0
- package/lib/engine-components/Component.js +53 -0
- package/lib/engine-components/Component.js.map +1 -1
- package/lib/engine-components/OrbitControls.js +2 -1
- package/lib/engine-components/OrbitControls.js.map +1 -1
- package/lib/engine-components/Renderer.d.ts +1 -0
- package/lib/engine-components/Renderer.js +10 -3
- package/lib/engine-components/Renderer.js.map +1 -1
- package/lib/engine-components/Rigidbody.d.ts +1 -1
- package/lib/engine-components/Rigidbody.js +3 -3
- package/lib/engine-components/Rigidbody.js.map +1 -1
- package/lib/engine-components/ScreenCapture.d.ts +35 -5
- package/lib/engine-components/ScreenCapture.js +542 -25
- package/lib/engine-components/ScreenCapture.js.map +1 -1
- package/lib/engine-components/SpectatorCamera.js +29 -5
- package/lib/engine-components/SpectatorCamera.js.map +1 -1
- package/lib/engine-components/SyncedRoom.js +2 -0
- package/lib/engine-components/SyncedRoom.js.map +1 -1
- package/lib/engine-components/VideoPlayer.d.ts +14 -1
- package/lib/engine-components/VideoPlayer.js +86 -16
- package/lib/engine-components/VideoPlayer.js.map +1 -1
- package/lib/engine-components/Volume.d.ts +4 -0
- package/lib/engine-components/Volume.js +44 -3
- package/lib/engine-components/Volume.js.map +1 -1
- package/lib/engine-components/WebARSessionRoot.d.ts +9 -2
- package/lib/engine-components/WebARSessionRoot.js +69 -24
- package/lib/engine-components/WebARSessionRoot.js.map +1 -1
- package/lib/engine-components/WebXR.d.ts +6 -3
- package/lib/engine-components/WebXR.js +42 -7
- package/lib/engine-components/WebXR.js.map +1 -1
- package/lib/engine-components/WebXRAvatar.js +4 -0
- package/lib/engine-components/WebXRAvatar.js.map +1 -1
- package/lib/engine-components/WebXRController.js +13 -7
- package/lib/engine-components/WebXRController.js.map +1 -1
- package/lib/engine-components/ui/CanvasGroup.d.ts +1 -0
- package/lib/engine-components/ui/CanvasGroup.js +1 -0
- package/lib/engine-components/ui/CanvasGroup.js.map +1 -1
- package/lib/engine-components/ui/EventSystem.js +13 -4
- package/lib/engine-components/ui/EventSystem.js.map +1 -1
- package/lib/engine-components/ui/Graphic.d.ts +1 -0
- package/lib/engine-components/ui/Graphic.js +2 -0
- package/lib/engine-components/ui/Graphic.js.map +1 -1
- package/lib/engine-components/ui/Interfaces.d.ts +2 -0
- package/lib/needle-engine.d.ts +1 -0
- package/lib/needle-engine.js +1 -0
- package/lib/needle-engine.js.map +1 -1
- package/package.json +2 -2
- package/src/engine/engine_physics.ts +74 -57
- package/src/engine/engine_serialization.ts +3 -1
- package/src/engine/engine_setup.ts +6 -0
- package/src/engine/engine_utils.ts +34 -8
- package/src/engine/extensions/NEEDLE_deferred_texture.ts +25 -19
- package/src/engine/extensions/extension_utils.ts +24 -12
- package/src/engine/extensions/extensions.ts +3 -2
- package/src/engine-components/Camera.ts +9 -2
- package/src/engine-components/Component.ts +58 -0
- package/src/engine-components/OrbitControls.ts +2 -1
- package/src/engine-components/Renderer.ts +11 -3
- package/src/engine-components/RigidBody.ts +2 -2
- package/src/engine-components/ScreenCapture.ts +610 -28
- package/src/engine-components/SpectatorCamera.ts +28 -5
- package/src/engine-components/SyncedRoom.ts +1 -0
- package/src/engine-components/VideoPlayer.ts +123 -23
- package/src/engine-components/Volume.ts +47 -4
- package/src/engine-components/WebARSessionRoot.ts +78 -28
- package/src/engine-components/WebXR.ts +50 -15
- package/src/engine-components/WebXRAvatar.ts +5 -0
- package/src/engine-components/WebXRController.ts +20 -14
- package/src/engine-components/ui/CanvasGroup.ts +2 -0
- package/src/engine-components/ui/EventSystem.ts +21 -15
- package/src/engine-components/ui/Graphic.ts +3 -0
- package/src/engine-components/ui/Interfaces.ts +2 -0
- package/src/needle-engine.ts +1 -0
|
@@ -170,6 +170,7 @@ export class SpectatorCamera extends Behaviour {
|
|
|
170
170
|
|
|
171
171
|
private onXRSessionStart(_evt) {
|
|
172
172
|
if (!this.isSupportedPlatform()) return;
|
|
173
|
+
if (debug) console.log(this.context.mainCamera);
|
|
173
174
|
if (this.context.mainCamera) {
|
|
174
175
|
this.followSelf();
|
|
175
176
|
}
|
|
@@ -188,6 +189,7 @@ export class SpectatorCamera extends Behaviour {
|
|
|
188
189
|
|
|
189
190
|
private followSelf() {
|
|
190
191
|
this.target = this.context.players.getPlayerView(this.context.connection.connectionId);
|
|
192
|
+
if (debug) console.log("Follow self", this.target);
|
|
191
193
|
}
|
|
192
194
|
|
|
193
195
|
// TODO: only show Spectator cam for DesktopVR;
|
|
@@ -219,6 +221,8 @@ export class SpectatorCamera extends Behaviour {
|
|
|
219
221
|
|
|
220
222
|
this.setAvatarFlagsBeforeRender();
|
|
221
223
|
|
|
224
|
+
const mainCam = this.context.mainCameraComponent;
|
|
225
|
+
|
|
222
226
|
// these should not be needed if we don't override viewport/scissor
|
|
223
227
|
// renderer.getViewport(this.currentViewport);
|
|
224
228
|
// renderer.getScissor(this.currentScissor);
|
|
@@ -231,7 +235,17 @@ export class SpectatorCamera extends Behaviour {
|
|
|
231
235
|
// renderer.setViewport(left, bottom, width, height);
|
|
232
236
|
// renderer.setScissor(left, bottom, width, height);
|
|
233
237
|
// renderer.setScissorTest(true);
|
|
234
|
-
|
|
238
|
+
if (mainCam) {
|
|
239
|
+
const backgroundColor = mainCam.backgroundColor;
|
|
240
|
+
if (backgroundColor)
|
|
241
|
+
renderer.setClearColor(backgroundColor, backgroundColor.alpha);
|
|
242
|
+
this.cam.backgroundColor = backgroundColor;
|
|
243
|
+
this.cam.clearFlags = mainCam.clearFlags;
|
|
244
|
+
this.cam.nearClipPlane = mainCam.nearClipPlane;
|
|
245
|
+
this.cam.farClipPlane = mainCam.farClipPlane;
|
|
246
|
+
}
|
|
247
|
+
else
|
|
248
|
+
renderer.setClearColor(new THREE.Color(1, 1, 1));
|
|
235
249
|
renderer.setRenderTarget(null); // null: direct to Canvas
|
|
236
250
|
renderer.xr.enabled = false;
|
|
237
251
|
const cam = this.cam?.cam;
|
|
@@ -384,8 +398,16 @@ class SpectatorHandler implements ISpectatorHandler {
|
|
|
384
398
|
if (!target || !this.follow) return;
|
|
385
399
|
switch (mode) {
|
|
386
400
|
case SpectatorMode.FirstPerson:
|
|
387
|
-
this.
|
|
388
|
-
|
|
401
|
+
if (this.view?.viewDevice !== ViewDevice.Browser) {
|
|
402
|
+
// soft follow for AR and VR
|
|
403
|
+
this.follow.followFactor = 5;
|
|
404
|
+
this.follow.rotateFactor = 5;
|
|
405
|
+
}
|
|
406
|
+
else {
|
|
407
|
+
// snappy follow for desktop
|
|
408
|
+
this.follow.followFactor = 50;
|
|
409
|
+
this.follow.rotateFactor = 50;
|
|
410
|
+
}
|
|
389
411
|
target.position.set(0, 0, 0);
|
|
390
412
|
break;
|
|
391
413
|
case SpectatorMode.ThirdPerson:
|
|
@@ -427,10 +449,11 @@ class SpectatorSelectionController {
|
|
|
427
449
|
downTime = this.context.time.time;
|
|
428
450
|
});
|
|
429
451
|
this.context.input.addEventListener(InputEvents.PointerUp, _ => {
|
|
430
|
-
|
|
452
|
+
const dt = this.context.time.time - downTime;
|
|
453
|
+
if (dt > 1) {
|
|
431
454
|
this.spectator.stopSpectating();
|
|
432
455
|
}
|
|
433
|
-
else
|
|
456
|
+
else if (this.context.input.getPointerClicked(0) && dt < .3)
|
|
434
457
|
this.trySelectObject();
|
|
435
458
|
});
|
|
436
459
|
}
|
|
@@ -2,9 +2,10 @@ import { Behaviour } from "./Component";
|
|
|
2
2
|
import * as THREE from "three";
|
|
3
3
|
import { Material } from "material/Material";
|
|
4
4
|
import { serializeable } from "../engine/engine_serialization_decorator";
|
|
5
|
-
import { Object3D } from "three";
|
|
5
|
+
import { LinearFilter, Object3D, Texture } from "three";
|
|
6
6
|
import { awaitInput } from "../engine/engine_input_utils";
|
|
7
7
|
import { getParam } from "../engine/engine_utils";
|
|
8
|
+
import { Renderer } from "./Renderer";
|
|
8
9
|
|
|
9
10
|
const debug = getParam("debugvideo");
|
|
10
11
|
|
|
@@ -20,22 +21,17 @@ export enum VideoSource {
|
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
export enum VideoAudioOutputMode {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
Direct,
|
|
35
|
-
/// <summary>
|
|
36
|
-
/// <para>Send the embedded audio to the associated AudioSampleProvider.</para>
|
|
37
|
-
/// </summary>
|
|
38
|
-
APIOnly,
|
|
24
|
+
None = 0,
|
|
25
|
+
AudioSource = 1,
|
|
26
|
+
Direct = 2,
|
|
27
|
+
APIOnly = 3,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export enum VideoRenderMode {
|
|
31
|
+
CameraFarPlane = 0,
|
|
32
|
+
CameraNearPlane = 1,
|
|
33
|
+
RenderTexture = 2,
|
|
34
|
+
MaterialOverride = 3,
|
|
39
35
|
}
|
|
40
36
|
|
|
41
37
|
export class VideoPlayer extends Behaviour {
|
|
@@ -48,7 +44,16 @@ export class VideoPlayer extends Behaviour {
|
|
|
48
44
|
playOnEnable?: boolean;
|
|
49
45
|
|
|
50
46
|
@serializeable()
|
|
51
|
-
|
|
47
|
+
private renderMode?: VideoRenderMode;
|
|
48
|
+
|
|
49
|
+
@serializeable()
|
|
50
|
+
private targetMaterialProperty?: string;
|
|
51
|
+
|
|
52
|
+
@serializeable(Renderer)
|
|
53
|
+
private targetMaterialRenderer?: Renderer;
|
|
54
|
+
|
|
55
|
+
@serializeable(Texture)
|
|
56
|
+
private targetTexture?: Texture;
|
|
52
57
|
|
|
53
58
|
@serializeable()
|
|
54
59
|
private time: number = 0;
|
|
@@ -120,13 +125,26 @@ export class VideoPlayer extends Behaviour {
|
|
|
120
125
|
private _isPlaying: boolean = false;
|
|
121
126
|
private wasPlaying: boolean = false;
|
|
122
127
|
|
|
128
|
+
setVideo(video: MediaStream) {
|
|
129
|
+
this.clip = video;
|
|
130
|
+
this.source = VideoSource.VideoClip;
|
|
131
|
+
if (!this.videoElement) this.create(true);
|
|
132
|
+
else {
|
|
133
|
+
// TODO: how to prevent interruption error when another video is already playing
|
|
134
|
+
this.videoElement.srcObject = video;
|
|
135
|
+
if (this._isPlaying)
|
|
136
|
+
this.videoElement.play();
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
123
140
|
setClipURL(url: string) {
|
|
124
141
|
if (this.url === url) return;
|
|
125
142
|
// console.log("SET URL", url);
|
|
126
143
|
this.url = url;
|
|
127
144
|
this.source = VideoSource.Url;
|
|
128
145
|
if (debug) console.log("set url", url);
|
|
129
|
-
if (this.videoElement)
|
|
146
|
+
if (!this.videoElement) this.create(true);
|
|
147
|
+
else {
|
|
130
148
|
this.videoElement.src = url;
|
|
131
149
|
if (this._isPlaying)
|
|
132
150
|
this.videoElement.play();
|
|
@@ -177,7 +195,8 @@ export class VideoPlayer extends Behaviour {
|
|
|
177
195
|
awaitInput(() => {
|
|
178
196
|
this._receivedInput = true;
|
|
179
197
|
this.updateVideoElementSettings();
|
|
180
|
-
})
|
|
198
|
+
});
|
|
199
|
+
this._targetObjects = [];
|
|
181
200
|
}
|
|
182
201
|
|
|
183
202
|
play() {
|
|
@@ -238,6 +257,12 @@ export class VideoPlayer extends Behaviour {
|
|
|
238
257
|
this.handleBeginPlaying(playAutomatically);
|
|
239
258
|
}
|
|
240
259
|
|
|
260
|
+
private _targetObjects: Array<Object3D>;
|
|
261
|
+
|
|
262
|
+
getTargetObjects(): Array<Object3D> {
|
|
263
|
+
return Array.from(this._targetObjects);
|
|
264
|
+
}
|
|
265
|
+
|
|
241
266
|
private createVideoElement(): HTMLVideoElement {
|
|
242
267
|
const video = document.createElement("video") as HTMLVideoElement;
|
|
243
268
|
if (this._crossOrigin)
|
|
@@ -250,11 +275,30 @@ export class VideoPlayer extends Behaviour {
|
|
|
250
275
|
if (!this.enabled) return;
|
|
251
276
|
if (!this.videoElement) return;
|
|
252
277
|
|
|
253
|
-
|
|
278
|
+
this._targetObjects.length = 0;
|
|
279
|
+
|
|
280
|
+
let target: Object3D | undefined = this.gameObject;
|
|
281
|
+
|
|
282
|
+
switch (this.renderMode) {
|
|
283
|
+
case VideoRenderMode.MaterialOverride:
|
|
284
|
+
target = this.targetMaterialRenderer?.gameObject;
|
|
285
|
+
break;
|
|
286
|
+
case VideoRenderMode.RenderTexture:
|
|
287
|
+
console.error("VideoPlayer renderTexture not implemented yet. Please use material override instead");
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (!target) {
|
|
292
|
+
console.error("Missing target for video material renderer", this);
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
const mat = target["material"];
|
|
254
296
|
if (mat) {
|
|
297
|
+
this._targetObjects.push(target);
|
|
298
|
+
|
|
255
299
|
if (mat !== this.videoMaterial) {
|
|
256
300
|
this.videoMaterial = mat.clone();
|
|
257
|
-
|
|
301
|
+
target["material"] = this.videoMaterial;
|
|
258
302
|
}
|
|
259
303
|
|
|
260
304
|
if (!this.targetMaterialProperty) {
|
|
@@ -305,4 +349,60 @@ export class VideoPlayer extends Behaviour {
|
|
|
305
349
|
this.videoElement.style.visibility = "hidden";
|
|
306
350
|
this.videoElement.style.display = "none";
|
|
307
351
|
}
|
|
308
|
-
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
// class VideoTexture extends Texture {
|
|
358
|
+
|
|
359
|
+
// get isVideoTexture() { return true; }
|
|
360
|
+
|
|
361
|
+
// constructor( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
|
|
362
|
+
|
|
363
|
+
// super( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
|
|
364
|
+
|
|
365
|
+
// this.minFilter = minFilter !== undefined ? minFilter : LinearFilter;
|
|
366
|
+
// this.magFilter = magFilter !== undefined ? magFilter : LinearFilter;
|
|
367
|
+
|
|
368
|
+
// this.generateMipmaps = false;
|
|
369
|
+
|
|
370
|
+
// const scope = this;
|
|
371
|
+
|
|
372
|
+
// function updateVideo() {
|
|
373
|
+
|
|
374
|
+
// scope.needsUpdate = true;
|
|
375
|
+
// video.requestVideoFrameCallback( updateVideo );
|
|
376
|
+
|
|
377
|
+
// }
|
|
378
|
+
|
|
379
|
+
// if ( 'requestVideoFrameCallback' in video ) {
|
|
380
|
+
|
|
381
|
+
// video.requestVideoFrameCallback( updateVideo );
|
|
382
|
+
|
|
383
|
+
// }
|
|
384
|
+
|
|
385
|
+
// }
|
|
386
|
+
|
|
387
|
+
// // clone() {
|
|
388
|
+
|
|
389
|
+
// // return new this.constructor( this.image ).copy( this );
|
|
390
|
+
|
|
391
|
+
// // }
|
|
392
|
+
|
|
393
|
+
// update() {
|
|
394
|
+
|
|
395
|
+
// const video = this.image;
|
|
396
|
+
// const hasVideoFrameCallback = 'requestVideoFrameCallback' in video;
|
|
397
|
+
|
|
398
|
+
// if ( hasVideoFrameCallback === false && video.readyState >= video.HAVE_CURRENT_DATA ) {
|
|
399
|
+
|
|
400
|
+
// this.needsUpdate = true;
|
|
401
|
+
|
|
402
|
+
// }
|
|
403
|
+
|
|
404
|
+
// }
|
|
405
|
+
|
|
406
|
+
// }
|
|
407
|
+
|
|
408
|
+
// export { VideoTexture };
|
|
@@ -2,6 +2,9 @@ import { Behaviour } from "./Component";
|
|
|
2
2
|
import { NoToneMapping, LinearToneMapping, ACESFilmicToneMapping, ReinhardToneMapping } from "three";
|
|
3
3
|
import { serializeable } from "../engine/engine_serialization_decorator";
|
|
4
4
|
import { Context } from "../engine/engine_setup";
|
|
5
|
+
import { getParam } from "../engine/engine_utils";
|
|
6
|
+
|
|
7
|
+
const debug = getParam("debugvolume");
|
|
5
8
|
|
|
6
9
|
export enum TonemappingMode {
|
|
7
10
|
None = 0,
|
|
@@ -35,21 +38,41 @@ function resolveComponentType(data) {
|
|
|
35
38
|
return VolumeComponent;
|
|
36
39
|
}
|
|
37
40
|
|
|
41
|
+
const volumeKey = Symbol("volumeprofile");
|
|
42
|
+
|
|
38
43
|
export class VolumeProfile {
|
|
39
44
|
@serializeable([d => resolveComponentType(d), VolumeComponent])
|
|
40
45
|
components?: VolumeComponent[];
|
|
41
46
|
|
|
42
|
-
|
|
43
47
|
apply(context: Context) {
|
|
48
|
+
this.onUpdate(context, false);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
unapply(context: Context) {
|
|
52
|
+
this.onUpdate(context, true);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private onUpdate(context: Context, remove: boolean) {
|
|
44
56
|
if (!this.components) return;
|
|
57
|
+
const renderer = context.renderer;
|
|
58
|
+
const currentProfile = renderer[volumeKey];
|
|
59
|
+
const isActive = currentProfile !== undefined;
|
|
60
|
+
if (remove) {
|
|
61
|
+
// can not remove volume profile that is not active
|
|
62
|
+
if (!isActive) return;
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
renderer[volumeKey] = this;
|
|
66
|
+
}
|
|
45
67
|
for (const component of this.components) {
|
|
46
68
|
|
|
47
69
|
if (component instanceof ToneMapping) {
|
|
48
70
|
const tonemapping = component as ToneMapping;
|
|
49
|
-
if (!component.active) {
|
|
71
|
+
if (!component.active || remove) {
|
|
50
72
|
context.renderer.toneMapping = LinearToneMapping;
|
|
51
73
|
continue;
|
|
52
74
|
}
|
|
75
|
+
if (debug) console.log("VOLUME:", TonemappingMode[tonemapping.mode?.value ?? 0]);
|
|
53
76
|
switch (tonemapping.mode?.value ?? 0) {
|
|
54
77
|
case TonemappingMode.None:
|
|
55
78
|
context.renderer.toneMapping = LinearToneMapping;
|
|
@@ -66,9 +89,11 @@ export class VolumeProfile {
|
|
|
66
89
|
const colorAdjustments = component as ColorAdjustments;
|
|
67
90
|
// unity range goes from -15..15
|
|
68
91
|
// three.js range goes from 0..inf
|
|
69
|
-
|
|
92
|
+
if (debug)
|
|
93
|
+
console.log(colorAdjustments.postExposure);
|
|
70
94
|
const exposure = Math.pow(2, colorAdjustments.postExposure?.value ?? 0);
|
|
71
|
-
|
|
95
|
+
const useExposure = colorAdjustments.postExposure?.overrideState && !remove;
|
|
96
|
+
context.renderer.toneMappingExposure = useExposure ? exposure : 1;
|
|
72
97
|
}
|
|
73
98
|
}
|
|
74
99
|
}
|
|
@@ -80,7 +105,25 @@ export class Volume extends Behaviour {
|
|
|
80
105
|
@serializeable(VolumeProfile)
|
|
81
106
|
sharedProfile?: VolumeProfile;
|
|
82
107
|
|
|
108
|
+
awake() {
|
|
109
|
+
if (debug) {
|
|
110
|
+
console.log(this);
|
|
111
|
+
console.log("Press P to toggle post processing");
|
|
112
|
+
window.addEventListener("keydown", (e) => {
|
|
113
|
+
if (e.key === "p") {
|
|
114
|
+
console.log("Toggle volume: " + this.name, !this.enabled);
|
|
115
|
+
this.enabled = !this.enabled;
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
83
121
|
onEnable() {
|
|
122
|
+
if (debug) console.log("APPLY VOLUME", this)
|
|
84
123
|
this.sharedProfile?.apply(this.context);
|
|
85
124
|
}
|
|
125
|
+
|
|
126
|
+
onDisable() {
|
|
127
|
+
this.sharedProfile?.unapply(this.context);
|
|
128
|
+
}
|
|
86
129
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Behaviour } from "./Component";
|
|
1
|
+
import { Behaviour, GameObject } from "./Component";
|
|
2
2
|
import * as THREE from 'three'
|
|
3
|
-
import { Object3D, XRPose } from "three";
|
|
4
|
-
import { WebAR } from "./WebXR";
|
|
3
|
+
import { Matrix4, Object3D, XRPose } from "three";
|
|
4
|
+
import { WebAR, WebXR } from "./WebXR";
|
|
5
5
|
import { InstancingUtil } from "./Renderer";
|
|
6
6
|
import { serializeable } from "../engine/engine_serialization_decorator";
|
|
7
7
|
|
|
@@ -11,6 +11,10 @@ export class WebARSessionRoot extends Behaviour {
|
|
|
11
11
|
|
|
12
12
|
webAR: WebAR | null = null;
|
|
13
13
|
|
|
14
|
+
get rig(): THREE.Object3D | undefined {
|
|
15
|
+
return this.webAR?.webxr.Rig;
|
|
16
|
+
}
|
|
17
|
+
|
|
14
18
|
@serializeable()
|
|
15
19
|
invertForward: boolean = false;
|
|
16
20
|
|
|
@@ -24,46 +28,57 @@ export class WebARSessionRoot extends Behaviour {
|
|
|
24
28
|
this.setScale(val);
|
|
25
29
|
}
|
|
26
30
|
|
|
31
|
+
private readonly _initalMatrix = new THREE.Matrix4();
|
|
32
|
+
private readonly _selectStartFn = this.onSelectStart.bind(this);
|
|
33
|
+
private readonly _selectEndFn = this.onSelectEnd.bind(this);
|
|
34
|
+
|
|
35
|
+
start() {
|
|
36
|
+
const xr = GameObject.findObjectOfType(WebXR);
|
|
37
|
+
if (xr) {
|
|
38
|
+
xr.Rig.updateMatrix();
|
|
39
|
+
this._initalMatrix.copy(xr.Rig.matrix);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
27
43
|
private _arScale: number = 5;
|
|
28
44
|
private _rig: THREE.Object3D | null = null;
|
|
29
45
|
private _startPose: THREE.Matrix4 | null = null;
|
|
30
46
|
private _placementPose: THREE.Matrix4 | null = null;
|
|
31
47
|
private _isTouching: boolean = false;
|
|
48
|
+
private _rigStartPose: THREE.Matrix4 | undefined | null = null;
|
|
32
49
|
|
|
33
50
|
onBegin(session: THREE.XRSession) {
|
|
34
51
|
this._placementPose = null;
|
|
35
52
|
this.gameObject.visible = false;
|
|
36
53
|
this.gameObject.matrixAutoUpdate = false;
|
|
37
54
|
this._startPose = this.gameObject.matrix.clone();
|
|
38
|
-
|
|
39
|
-
session.addEventListener('
|
|
40
|
-
|
|
55
|
+
this._rigStartPose = this.rig?.matrix.clone();
|
|
56
|
+
session.addEventListener('selectstart', this._selectStartFn);
|
|
57
|
+
session.addEventListener('selectend', this._selectEndFn);
|
|
58
|
+
// setTimeout(() => this.gameObject.visible = false, 1000); // TODO test on phone AR and Hololens if this was still needed
|
|
59
|
+
|
|
60
|
+
// console.log(this.rig?.position, this.rig?.quaternion, this.rig?.scale);
|
|
61
|
+
this.gameObject.visible = false;
|
|
62
|
+
|
|
63
|
+
if (this.rig) {
|
|
64
|
+
// reset rig to initial pose, this is helping the mix of immersive AR and immersive VR that we now have on quest
|
|
65
|
+
// where the rig can be moved and scaled by the user in VR mode and we use the rig position when entering
|
|
66
|
+
// immersive Ar right now to place the user/offset the session
|
|
67
|
+
this.rig.matrixAutoUpdate = true;
|
|
68
|
+
this._initalMatrix.decompose(this.rig.position, this.rig.quaternion, this.rig.scale);
|
|
69
|
+
}
|
|
41
70
|
}
|
|
42
71
|
|
|
43
|
-
onUpdate(rig: THREE.Object3D | null, _session: THREE.XRSession, pose: XRPose | null | undefined) {
|
|
72
|
+
onUpdate(rig: THREE.Object3D | null, _session: THREE.XRSession, pose: XRPose | null | undefined): boolean {
|
|
44
73
|
|
|
45
74
|
if (pose && !this._placementPose) {
|
|
46
75
|
if (this._isTouching) {
|
|
47
76
|
if (this.webAR) this.webAR.setReticleActive(false);
|
|
48
|
-
this.
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (this.invertForward) {
|
|
52
|
-
const rot = new THREE.Matrix4().makeRotationY(Math.PI);
|
|
53
|
-
this._placementPose.premultiply(rot);
|
|
54
|
-
}
|
|
55
|
-
this._rig = rig;
|
|
56
|
-
|
|
57
|
-
this.setScale(this.arScale);
|
|
58
|
-
}
|
|
59
|
-
else this._rig = null;
|
|
60
|
-
// this.gameObject.matrix.copy(this._placementPose);
|
|
61
|
-
// if (rig) {
|
|
62
|
-
// this.gameObject.matrix.premultiply(rig.matrixWorld)
|
|
63
|
-
// }
|
|
64
|
-
this.gameObject.visible = true;
|
|
77
|
+
this.placeAt(rig, new THREE.Matrix4().fromArray(pose.transform.matrix).invert());
|
|
78
|
+
return true;
|
|
65
79
|
}
|
|
66
80
|
}
|
|
81
|
+
return false;
|
|
67
82
|
|
|
68
83
|
// if (this._placementPose) {
|
|
69
84
|
// this.gameObject.matrixAutoUpdate = false;
|
|
@@ -75,16 +90,47 @@ export class WebARSessionRoot extends Behaviour {
|
|
|
75
90
|
// }
|
|
76
91
|
}
|
|
77
92
|
|
|
93
|
+
placeAt(rig: THREE.Object3D | null, mat: Matrix4) {
|
|
94
|
+
if (!this._placementPose) this._placementPose = new THREE.Matrix4();
|
|
95
|
+
this._placementPose.copy(mat);
|
|
96
|
+
if (rig) {
|
|
97
|
+
|
|
98
|
+
if (this.invertForward) {
|
|
99
|
+
const rot = new THREE.Matrix4().makeRotationY(Math.PI);
|
|
100
|
+
this._placementPose.premultiply(rot);
|
|
101
|
+
}
|
|
102
|
+
this._rig = rig;
|
|
103
|
+
|
|
104
|
+
this.setScale(this.arScale);
|
|
105
|
+
}
|
|
106
|
+
else this._rig = null;
|
|
107
|
+
// this.gameObject.matrix.copy(this._placementPose);
|
|
108
|
+
// if (rig) {
|
|
109
|
+
// this.gameObject.matrix.premultiply(rig.matrixWorld)
|
|
110
|
+
// }
|
|
111
|
+
this.gameObject.visible = true;
|
|
112
|
+
}
|
|
113
|
+
|
|
78
114
|
onEnd(rig: THREE.Object3D | null, _session: THREE.XRSession) {
|
|
79
115
|
this._placementPose = null;
|
|
80
116
|
this.gameObject.visible = false;
|
|
81
|
-
|
|
117
|
+
this.gameObject.matrixAutoUpdate = false;
|
|
118
|
+
if (this._startPose) {
|
|
82
119
|
this.gameObject.matrix.copy(this._startPose);
|
|
83
|
-
|
|
84
|
-
if (rig)
|
|
120
|
+
}
|
|
121
|
+
if (rig) {
|
|
122
|
+
rig.matrixAutoUpdate = true;
|
|
123
|
+
if (this._rigStartPose) {
|
|
124
|
+
this._rigStartPose.decompose(rig.position, rig.quaternion, rig.scale);
|
|
125
|
+
// console.log(rig.position, rig.quaternion, rig.scale);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
85
128
|
InstancingUtil.markDirty(this.gameObject, true);
|
|
86
129
|
// HACK to fix physics being not in correct place after exiting AR
|
|
87
|
-
setTimeout(() =>
|
|
130
|
+
setTimeout(() => {
|
|
131
|
+
this.gameObject.matrixAutoUpdate = true;
|
|
132
|
+
this.gameObject.visible = true;
|
|
133
|
+
}, 100);
|
|
88
134
|
}
|
|
89
135
|
|
|
90
136
|
|
|
@@ -101,9 +147,13 @@ export class WebARSessionRoot extends Behaviour {
|
|
|
101
147
|
if (!rig || !this._placementPose) {
|
|
102
148
|
return;
|
|
103
149
|
}
|
|
150
|
+
if (!this._rigStartPose) {
|
|
151
|
+
this._rigStartPose = rig.matrix.clone();
|
|
152
|
+
}
|
|
104
153
|
rig.matrixAutoUpdate = false;
|
|
105
154
|
rig.matrix.multiplyMatrices(new THREE.Matrix4().makeScale(scale, scale, scale), this._placementPose);
|
|
106
155
|
rig.matrix.decompose(rig.position, rig.quaternion, rig.scale);
|
|
107
156
|
rig.updateMatrixWorld();
|
|
157
|
+
console.log("Place", rig.position);
|
|
108
158
|
}
|
|
109
159
|
}
|