@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.
Files changed (101) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/needle-engine.d.ts +847 -757
  3. package/dist/needle-engine.js +347 -343
  4. package/dist/needle-engine.js.map +4 -4
  5. package/dist/needle-engine.min.js +16 -12
  6. package/dist/needle-engine.min.js.map +4 -4
  7. package/lib/engine/engine.d.ts +1 -0
  8. package/lib/engine/engine_physics.d.ts +19 -8
  9. package/lib/engine/engine_physics.js +57 -48
  10. package/lib/engine/engine_physics.js.map +1 -1
  11. package/lib/engine/engine_serialization.d.ts +1 -0
  12. package/lib/engine/engine_serialization.js +1 -0
  13. package/lib/engine/engine_serialization.js.map +1 -1
  14. package/lib/engine/engine_setup.d.ts +5 -0
  15. package/lib/engine/engine_setup.js +6 -0
  16. package/lib/engine/engine_setup.js.map +1 -1
  17. package/lib/engine/engine_utils.d.ts +1 -1
  18. package/lib/engine/engine_utils.js +25 -8
  19. package/lib/engine/engine_utils.js.map +1 -1
  20. package/lib/engine/extensions/NEEDLE_deferred_texture.d.ts +1 -1
  21. package/lib/engine/extensions/NEEDLE_deferred_texture.js +26 -14
  22. package/lib/engine/extensions/NEEDLE_deferred_texture.js.map +1 -1
  23. package/lib/engine/extensions/extension_utils.js +24 -13
  24. package/lib/engine/extensions/extension_utils.js.map +1 -1
  25. package/lib/engine/extensions/extensions.js +3 -1
  26. package/lib/engine/extensions/extensions.js.map +1 -1
  27. package/lib/engine-components/Camera.js +7 -1
  28. package/lib/engine-components/Camera.js.map +1 -1
  29. package/lib/engine-components/Component.d.ts +10 -0
  30. package/lib/engine-components/Component.js +53 -0
  31. package/lib/engine-components/Component.js.map +1 -1
  32. package/lib/engine-components/OrbitControls.js +2 -1
  33. package/lib/engine-components/OrbitControls.js.map +1 -1
  34. package/lib/engine-components/Renderer.d.ts +1 -0
  35. package/lib/engine-components/Renderer.js +10 -3
  36. package/lib/engine-components/Renderer.js.map +1 -1
  37. package/lib/engine-components/Rigidbody.d.ts +1 -1
  38. package/lib/engine-components/Rigidbody.js +3 -3
  39. package/lib/engine-components/Rigidbody.js.map +1 -1
  40. package/lib/engine-components/ScreenCapture.d.ts +35 -5
  41. package/lib/engine-components/ScreenCapture.js +542 -25
  42. package/lib/engine-components/ScreenCapture.js.map +1 -1
  43. package/lib/engine-components/SpectatorCamera.js +29 -5
  44. package/lib/engine-components/SpectatorCamera.js.map +1 -1
  45. package/lib/engine-components/SyncedRoom.js +2 -0
  46. package/lib/engine-components/SyncedRoom.js.map +1 -1
  47. package/lib/engine-components/VideoPlayer.d.ts +14 -1
  48. package/lib/engine-components/VideoPlayer.js +86 -16
  49. package/lib/engine-components/VideoPlayer.js.map +1 -1
  50. package/lib/engine-components/Volume.d.ts +4 -0
  51. package/lib/engine-components/Volume.js +44 -3
  52. package/lib/engine-components/Volume.js.map +1 -1
  53. package/lib/engine-components/WebARSessionRoot.d.ts +9 -2
  54. package/lib/engine-components/WebARSessionRoot.js +69 -24
  55. package/lib/engine-components/WebARSessionRoot.js.map +1 -1
  56. package/lib/engine-components/WebXR.d.ts +6 -3
  57. package/lib/engine-components/WebXR.js +42 -7
  58. package/lib/engine-components/WebXR.js.map +1 -1
  59. package/lib/engine-components/WebXRAvatar.js +4 -0
  60. package/lib/engine-components/WebXRAvatar.js.map +1 -1
  61. package/lib/engine-components/WebXRController.js +13 -7
  62. package/lib/engine-components/WebXRController.js.map +1 -1
  63. package/lib/engine-components/ui/CanvasGroup.d.ts +1 -0
  64. package/lib/engine-components/ui/CanvasGroup.js +1 -0
  65. package/lib/engine-components/ui/CanvasGroup.js.map +1 -1
  66. package/lib/engine-components/ui/EventSystem.js +13 -4
  67. package/lib/engine-components/ui/EventSystem.js.map +1 -1
  68. package/lib/engine-components/ui/Graphic.d.ts +1 -0
  69. package/lib/engine-components/ui/Graphic.js +2 -0
  70. package/lib/engine-components/ui/Graphic.js.map +1 -1
  71. package/lib/engine-components/ui/Interfaces.d.ts +2 -0
  72. package/lib/needle-engine.d.ts +1 -0
  73. package/lib/needle-engine.js +1 -0
  74. package/lib/needle-engine.js.map +1 -1
  75. package/package.json +2 -2
  76. package/src/engine/engine_physics.ts +74 -57
  77. package/src/engine/engine_serialization.ts +3 -1
  78. package/src/engine/engine_setup.ts +6 -0
  79. package/src/engine/engine_utils.ts +34 -8
  80. package/src/engine/extensions/NEEDLE_deferred_texture.ts +25 -19
  81. package/src/engine/extensions/extension_utils.ts +24 -12
  82. package/src/engine/extensions/extensions.ts +3 -2
  83. package/src/engine-components/Camera.ts +9 -2
  84. package/src/engine-components/Component.ts +58 -0
  85. package/src/engine-components/OrbitControls.ts +2 -1
  86. package/src/engine-components/Renderer.ts +11 -3
  87. package/src/engine-components/RigidBody.ts +2 -2
  88. package/src/engine-components/ScreenCapture.ts +610 -28
  89. package/src/engine-components/SpectatorCamera.ts +28 -5
  90. package/src/engine-components/SyncedRoom.ts +1 -0
  91. package/src/engine-components/VideoPlayer.ts +123 -23
  92. package/src/engine-components/Volume.ts +47 -4
  93. package/src/engine-components/WebARSessionRoot.ts +78 -28
  94. package/src/engine-components/WebXR.ts +50 -15
  95. package/src/engine-components/WebXRAvatar.ts +5 -0
  96. package/src/engine-components/WebXRController.ts +20 -14
  97. package/src/engine-components/ui/CanvasGroup.ts +2 -0
  98. package/src/engine-components/ui/EventSystem.ts +21 -15
  99. package/src/engine-components/ui/Graphic.ts +3 -0
  100. package/src/engine-components/ui/Interfaces.ts +2 -0
  101. 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
- renderer.setClearColor(new THREE.Color(1, 1, 1));
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.follow.followFactor = 20;
388
- this.follow.rotateFactor = 20;
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
- if (this.context.time.time - downTime > 1) {
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
  }
@@ -44,6 +44,7 @@ export class SyncedRoom extends Behaviour {
44
44
  }
45
45
 
46
46
  tryJoinRoom(call: number = 0): boolean {
47
+ if(call === undefined) call = 0;
47
48
  let hasRoomParameter = false;
48
49
  if (this.urlParameterName) {
49
50
  const val = utils.getParam(this.urlParameterName);
@@ -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
- /// <summary>
24
- /// <para>Disable the embedded audio.</para>
25
- /// </summary>
26
- None,
27
- /// <summary>
28
- /// <para>Send the embedded audio into a specified AudioSource.</para>
29
- /// </summary>
30
- AudioSource,
31
- /// <summary>
32
- /// <para>Send the embedded audio direct to the platform's audio hardware.</para>
33
- /// </summary>
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
- targetMaterialProperty?: string;
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
- const mat = this.gameObject["material"];
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
- this.gameObject["material"] = this.videoMaterial;
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
- console.log(colorAdjustments.postExposure);
92
+ if (debug)
93
+ console.log(colorAdjustments.postExposure);
70
94
  const exposure = Math.pow(2, colorAdjustments.postExposure?.value ?? 0);
71
- context.renderer.toneMappingExposure = colorAdjustments.postExposure?.overrideState ? exposure : 1;
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
- session.addEventListener('selectstart', this.onSelectStart.bind(this));
39
- session.addEventListener('selectend', this.onSelectEnd.bind(this));
40
- setTimeout(() => this.gameObject.visible = false, 1000);
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._placementPose = new THREE.Matrix4().fromArray(pose.transform.matrix).invert();
49
- if (rig) {
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
- if (this._startPose)
117
+ this.gameObject.matrixAutoUpdate = false;
118
+ if (this._startPose) {
82
119
  this.gameObject.matrix.copy(this._startPose);
83
- this.gameObject.matrixAutoUpdate = true;
84
- if (rig) rig.matrixAutoUpdate = true;
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(() => this.gameObject.visible = true, 100);
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
  }