@needle-tools/engine 4.12.3 → 4.12.4-next.4498846
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 +4 -0
- package/components.needle.json +1 -1
- package/dist/{gltf-progressive-Bfpfaz84.umd.cjs → gltf-progressive-BqUnxvCx.umd.cjs} +1 -1
- package/dist/{gltf-progressive-hFPACYio.min.js → gltf-progressive-CSaX5HQb.min.js} +2 -2
- package/dist/{gltf-progressive-DPunMlEM.js → gltf-progressive-ChnIhDXx.js} +27 -27
- package/dist/{loader.worker-DWzfDpAl.js → loader.worker-C1GG9A7C.js} +6 -6
- package/dist/{needle-engine.bundle-u-rSDw6R.js → needle-engine.bundle-C9mGVluu.js} +7444 -7358
- package/dist/{needle-engine.bundle-CLPD2ttK.umd.cjs → needle-engine.bundle-CnmG19ga.umd.cjs} +300 -293
- package/dist/{needle-engine.bundle-B3ssYJS0.min.js → needle-engine.bundle-ZJOekt7-.min.js} +297 -290
- package/dist/needle-engine.d.ts +53 -28
- package/dist/needle-engine.js +4 -4
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- package/dist/{postprocessing-ClLv0reO.min.js → postprocessing-12-UW7je.min.js} +1 -1
- package/dist/{postprocessing-BHQvwehB.umd.cjs → postprocessing-B3Hu0Ryi.umd.cjs} +1 -1
- package/dist/{postprocessing-DLI2N3LL.js → postprocessing-R535krvT.js} +2 -2
- package/dist/{three-Bf2NBxAw.umd.cjs → three-BzxwLtUE.umd.cjs} +176 -176
- package/dist/{three-BCCkyCA5.js → three-D9pcFbxc.js} +4637 -4636
- package/dist/{three-W7zWTcfP.min.js → three-DMvLgxja.min.js} +176 -176
- package/dist/{three-examples-DB5Uoja4.min.js → three-examples-CIv2roOA.min.js} +1 -1
- package/dist/{three-examples-Djbk6WA4.umd.cjs → three-examples-CjSwCv_b.umd.cjs} +1 -1
- package/dist/{three-examples-D4rE49Ui.js → three-examples-F0MJj0vr.js} +1 -1
- package/dist/{three-mesh-ui-zsOOA5Pq.umd.cjs → three-mesh-ui-BLnJQzMl.umd.cjs} +1 -1
- package/dist/{three-mesh-ui-CIez6qJQ.min.js → three-mesh-ui-BllgajJz.min.js} +1 -1
- package/dist/{three-mesh-ui-3nSSizT4.js → three-mesh-ui-DYyiRn5Y.js} +1 -1
- package/dist/{vendor-tyBvnMF-.umd.cjs → vendor-BFgQSG2m.umd.cjs} +1 -1
- package/dist/{vendor-DMZcbVO1.js → vendor-BIFy-gRe.js} +1 -1
- package/dist/{vendor-sURMCFSI.min.js → vendor-ChgmXMYr.min.js} +1 -1
- package/lib/engine/debug/debug_overlay.js +13 -2
- package/lib/engine/debug/debug_overlay.js.map +1 -1
- package/lib/engine/engine_animation.d.ts +7 -0
- package/lib/engine/engine_animation.js +16 -0
- package/lib/engine/engine_animation.js.map +1 -1
- package/lib/engine/engine_input.js +5 -3
- package/lib/engine/engine_input.js.map +1 -1
- package/lib/engine/webcomponents/WebXRButtons.js +8 -1
- package/lib/engine/webcomponents/WebXRButtons.js.map +1 -1
- package/lib/engine/webcomponents/buttons.js +4 -0
- package/lib/engine/webcomponents/buttons.js.map +1 -1
- package/lib/engine/webcomponents/icons.js +44 -5
- package/lib/engine/webcomponents/icons.js.map +1 -1
- package/lib/engine/webcomponents/logo-element.js +0 -1
- package/lib/engine/webcomponents/logo-element.js.map +1 -1
- package/lib/engine/webcomponents/needle menu/needle-menu.d.ts +19 -3
- package/lib/engine/webcomponents/needle menu/needle-menu.js +248 -161
- package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
- package/lib/engine/webcomponents/needle-engine.ar-overlay.js +1 -0
- package/lib/engine/webcomponents/needle-engine.ar-overlay.js.map +1 -1
- package/lib/engine/xr/NeedleXRSession.d.ts +2 -0
- package/lib/engine/xr/NeedleXRSession.js +19 -10
- package/lib/engine/xr/NeedleXRSession.js.map +1 -1
- package/lib/engine-components/Animation.js +2 -0
- package/lib/engine-components/Animation.js.map +1 -1
- package/lib/engine-components/AnimatorController.js +2 -0
- package/lib/engine-components/AnimatorController.js.map +1 -1
- package/lib/engine-components/Light.d.ts +17 -12
- package/lib/engine-components/Light.js +52 -36
- package/lib/engine-components/Light.js.map +1 -1
- package/lib/engine-components/webxr/WebXR.js +6 -8
- package/lib/engine-components/webxr/WebXR.js.map +1 -1
- package/lib/engine-components/webxr/WebXRImageTracking.js +9 -2
- package/lib/engine-components/webxr/WebXRImageTracking.js.map +1 -1
- package/package.json +3 -3
- package/plugins/common/license.js +3 -3
- package/src/engine/debug/debug_overlay.ts +15 -2
- package/src/engine/engine_animation.ts +19 -1
- package/src/engine/engine_input.ts +5 -3
- package/src/engine/webcomponents/WebXRButtons.ts +9 -1
- package/src/engine/webcomponents/buttons.ts +5 -0
- package/src/engine/webcomponents/icons.ts +47 -5
- package/src/engine/webcomponents/index.ts +1 -1
- package/src/engine/webcomponents/logo-element.ts +0 -1
- package/src/engine/webcomponents/needle menu/needle-menu.ts +270 -165
- package/src/engine/webcomponents/needle-engine.ar-overlay.ts +1 -0
- package/src/engine/xr/NeedleXRSession.ts +23 -10
- package/src/engine-components/Animation.ts +4 -1
- package/src/engine-components/AnimatorController.ts +3 -0
- package/src/engine-components/Light.ts +50 -42
- package/src/engine-components/webxr/WebXR.ts +6 -9
- package/src/engine-components/webxr/WebXRImageTracking.ts +12 -2
|
@@ -454,6 +454,9 @@ export class NeedleXRSession implements INeedleXRSession {
|
|
|
454
454
|
*/
|
|
455
455
|
static async start(mode: XRSessionMode | "ar" | "quicklook", init?: XRSessionInit, context?: Context): Promise<NeedleXRSession | null> {
|
|
456
456
|
|
|
457
|
+
// setup session init args, make sure we have default values
|
|
458
|
+
if (!init) init = {};
|
|
459
|
+
|
|
457
460
|
// handle iOS platform where "immersive-ar" is special:
|
|
458
461
|
// - we either launch QuickLook
|
|
459
462
|
// - or forward to the Needle App Clip experience for WebXR AR
|
|
@@ -477,7 +480,9 @@ export class NeedleXRSession implements INeedleXRSession {
|
|
|
477
480
|
}
|
|
478
481
|
|
|
479
482
|
if (!arSupported && (mode === "immersive-ar" || mode === "ar")) {
|
|
480
|
-
|
|
483
|
+
|
|
484
|
+
this.invokeSessionRequestStart("immersive-ar", init);
|
|
485
|
+
|
|
481
486
|
// Forward to the AppClip experience (Using the apple.com url the appclip overlay shows immediately)
|
|
482
487
|
// const url =`https://appclip.needle.tools/ar?url=${(location.href)}`;
|
|
483
488
|
const url = new URL("https://appclip.apple.com/id?p=tools.needle.launch-app.Clip");
|
|
@@ -511,6 +516,10 @@ export class NeedleXRSession implements INeedleXRSession {
|
|
|
511
516
|
else window.location.href = urlStr;
|
|
512
517
|
}
|
|
513
518
|
|
|
519
|
+
setTimeout(() => {
|
|
520
|
+
this.invokeSessionRequestEnd("immersive-ar", init || {}, null);
|
|
521
|
+
}, 3000);
|
|
522
|
+
|
|
514
523
|
return null;
|
|
515
524
|
}
|
|
516
525
|
}
|
|
@@ -549,9 +558,6 @@ export class NeedleXRSession implements INeedleXRSession {
|
|
|
549
558
|
|
|
550
559
|
//performance.mark('NeedleXRSession start');
|
|
551
560
|
|
|
552
|
-
// setup session init args, make sure we have default values
|
|
553
|
-
if (!init) init = {};
|
|
554
|
-
|
|
555
561
|
switch (mode) {
|
|
556
562
|
|
|
557
563
|
// Setup VR initialization parameters
|
|
@@ -615,9 +621,7 @@ export class NeedleXRSession implements INeedleXRSession {
|
|
|
615
621
|
script.onBeforeXR(mode, init);
|
|
616
622
|
}
|
|
617
623
|
}
|
|
618
|
-
|
|
619
|
-
listener({ mode, init });
|
|
620
|
-
}
|
|
624
|
+
this.invokeSessionRequestStart(mode, init);
|
|
621
625
|
if (debug) showBalloonMessage("Requesting " + mode + " session (" + Date.now() + ")");
|
|
622
626
|
Telemetry.sendEvent(Context.Current, "xr", {
|
|
623
627
|
action: "session_request",
|
|
@@ -637,9 +641,7 @@ export class NeedleXRSession implements INeedleXRSession {
|
|
|
637
641
|
});
|
|
638
642
|
this._currentSessionRequest = undefined;
|
|
639
643
|
this._currentSessionRequestMode = null;
|
|
640
|
-
|
|
641
|
-
listener({ mode, init, newSession: newSession || null });
|
|
642
|
-
}
|
|
644
|
+
this.invokeSessionRequestEnd(mode, init, newSession);
|
|
643
645
|
if (!newSession) {
|
|
644
646
|
console.warn("XR Session request was rejected");
|
|
645
647
|
return null;
|
|
@@ -650,6 +652,17 @@ export class NeedleXRSession implements INeedleXRSession {
|
|
|
650
652
|
return session;
|
|
651
653
|
}
|
|
652
654
|
|
|
655
|
+
private static invokeSessionRequestStart(mode: XRSessionMode, init: XRSessionInit) {
|
|
656
|
+
for (const listener of this._sessionRequestStartListeners) {
|
|
657
|
+
listener({ mode, init });
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
private static invokeSessionRequestEnd(mode: XRSessionMode, init: XRSessionInit, session: XRSession | null | undefined | void) {
|
|
661
|
+
for (const listener of this._sessionRequestEndListeners) {
|
|
662
|
+
listener({ mode, init, newSession: session || null });
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
|
|
653
666
|
static setSession(mode: XRSessionMode, session: XRSession, init: XRSessionInit, context: Context) {
|
|
654
667
|
if (this._activeSession) {
|
|
655
668
|
console.error("A XRSession is already running");
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AnimationAction, AnimationClip, AnimationMixer, LoopOnce, LoopRepeat } from "three";
|
|
2
|
+
import { AnimationUtils } from "../engine/engine_animation.js";
|
|
2
3
|
|
|
3
4
|
import { Mathf } from "../engine/engine_math.js";
|
|
4
5
|
import { serializable } from "../engine/engine_serialization_decorator.js";
|
|
@@ -447,7 +448,7 @@ export class Animation extends Behaviour implements IAnimationComponent {
|
|
|
447
448
|
action.time = Mathf.lerp(options.minMaxOffsetNormalized.x, options.minMaxOffsetNormalized.y, Math.random()) * clip.duration;
|
|
448
449
|
}
|
|
449
450
|
// If the animation is at the end, reset the time
|
|
450
|
-
else if(action.time >= action.getClip().duration) {
|
|
451
|
+
else if (action.time >= action.getClip().duration) {
|
|
451
452
|
action.time = 0;
|
|
452
453
|
}
|
|
453
454
|
|
|
@@ -473,6 +474,8 @@ export class Animation extends Behaviour implements IAnimationComponent {
|
|
|
473
474
|
action.paused = false;
|
|
474
475
|
action.play();
|
|
475
476
|
|
|
477
|
+
window.requestAnimationFrame(() => AnimationUtils.testIfRootCanAnimate(action));
|
|
478
|
+
|
|
476
479
|
if (debug) console.log("PLAY", action.getClip().name, action)
|
|
477
480
|
const handle = new AnimationHandle(action, this.mixer!, options, _ => {
|
|
478
481
|
this._handles.splice(this._handles.indexOf(handle), 1);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { AnimationAction, AnimationClip, AnimationMixer, AxesHelper, Euler, KeyframeTrack, LoopOnce, Object3D, Quaternion, Vector3 } from "three";
|
|
2
2
|
|
|
3
3
|
import { isDevEnvironment } from "../engine/debug/index.js";
|
|
4
|
+
import { AnimationUtils } from "../engine/engine_animation.js";
|
|
4
5
|
import { Mathf } from "../engine/engine_math.js";
|
|
5
6
|
import { InstantiateIdProvider } from "../engine/engine_networking_instantiate.js";
|
|
6
7
|
import { assign, SerializationContext, TypeSerializer } from "../engine/engine_serialization_core.js";
|
|
@@ -775,6 +776,8 @@ export class AnimatorController {
|
|
|
775
776
|
else action.weight = 1;
|
|
776
777
|
action.play();
|
|
777
778
|
|
|
779
|
+
window.requestAnimationFrame(() => AnimationUtils.testIfRootCanAnimate(action));
|
|
780
|
+
|
|
778
781
|
if (this.rootMotionHandler) {
|
|
779
782
|
this.rootMotionHandler.onStart(action);
|
|
780
783
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CameraHelper, Color, DirectionalLight, DirectionalLightHelper, Light as ThreeLight, OrthographicCamera, PointLight, SpotLight, Vector3 } from "three";
|
|
2
|
+
import { get } from "three-mesh-ui/build/types/core/DefaultValues.js";
|
|
2
3
|
|
|
3
4
|
import { serializable } from "../engine/engine_serialization_decorator.js";
|
|
4
5
|
import { FrameEvent } from "../engine/engine_setup.js";
|
|
@@ -82,25 +83,64 @@ enum LightShadows {
|
|
|
82
83
|
export class Light extends Behaviour implements ILight {
|
|
83
84
|
|
|
84
85
|
/**
|
|
85
|
-
* The type of light (spot, directional, point, etc.)
|
|
86
|
+
* The type of light (spot, directional, point, etc.)
|
|
87
|
+
* Can not be changed at runtime.
|
|
86
88
|
*/
|
|
87
89
|
@serializable()
|
|
88
90
|
private type: LightType = 0;
|
|
89
91
|
|
|
90
92
|
/**
|
|
91
|
-
* The maximum distance the light affects
|
|
93
|
+
* The maximum distance the light affects.
|
|
94
|
+
* Only applicable for spot and point lights.
|
|
92
95
|
*/
|
|
93
|
-
|
|
94
|
-
|
|
96
|
+
@serializable()
|
|
97
|
+
get range(): number {
|
|
98
|
+
return this._range;
|
|
99
|
+
}
|
|
100
|
+
set range(value: number) {
|
|
101
|
+
this._range = value;
|
|
102
|
+
if (this.light && (this.light.type === "SpotLight" || this.light.type === "PointLight") && ("distance" in this.light)) {
|
|
103
|
+
this.light.distance = value;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
private _range: number = 1;
|
|
107
|
+
|
|
95
108
|
/**
|
|
96
|
-
* The full outer angle of the spotlight cone in degrees
|
|
109
|
+
* The full outer angle of the spotlight cone in degrees.
|
|
110
|
+
* Only applicable for spot lights.
|
|
97
111
|
*/
|
|
98
|
-
|
|
99
|
-
|
|
112
|
+
@serializable()
|
|
113
|
+
get spotAngle(): number {
|
|
114
|
+
return this._spotAngle;
|
|
115
|
+
}
|
|
116
|
+
set spotAngle(value: number) {
|
|
117
|
+
this._spotAngle = value;
|
|
118
|
+
if (this.light && this.light.type === "SpotLight" && ("angle" in this.light)) {
|
|
119
|
+
(this.light as SpotLight).angle = toRadians(value / 2);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
private _spotAngle: number = 30;
|
|
123
|
+
|
|
124
|
+
|
|
100
125
|
/**
|
|
101
|
-
* The angle of the inner cone in degrees for soft-edge spotlights
|
|
126
|
+
* The angle of the inner cone in degrees for soft-edge spotlights.
|
|
127
|
+
* Must be less than or equal to the outer spot angle.
|
|
128
|
+
* Only applicable for spot lights.
|
|
102
129
|
*/
|
|
103
|
-
|
|
130
|
+
@serializable()
|
|
131
|
+
get innerSpotAngle(): number {
|
|
132
|
+
return this._innerSpotAngle;
|
|
133
|
+
}
|
|
134
|
+
set innerSpotAngle(value: number) {
|
|
135
|
+
this._innerSpotAngle = value;
|
|
136
|
+
if (this.light && this.light.type === "SpotLight" && ("penumbra" in this.light)) {
|
|
137
|
+
const outerAngle = this.spotAngle;
|
|
138
|
+
const innerAngle = value;
|
|
139
|
+
const penumbra = 1 - (toRadians(innerAngle / 2) / toRadians(outerAngle / 2));
|
|
140
|
+
(this.light as SpotLight).penumbra = penumbra;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
private _innerSpotAngle: number = 10;
|
|
104
144
|
|
|
105
145
|
/**
|
|
106
146
|
* The color of the light
|
|
@@ -194,14 +234,7 @@ export class Light extends Behaviour implements ILight {
|
|
|
194
234
|
set intensity(val: number) {
|
|
195
235
|
this._intensity = val;
|
|
196
236
|
if (this.light) {
|
|
197
|
-
|
|
198
|
-
if (this.context.isInXR && this._webARRoot) {
|
|
199
|
-
const scaleFactor = this._webARRoot?.arScale;
|
|
200
|
-
if (typeof scaleFactor === "number" && scaleFactor > 0) {
|
|
201
|
-
factor /= scaleFactor;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
this.light.intensity = val * factor;
|
|
237
|
+
this.light.intensity = val;
|
|
205
238
|
}
|
|
206
239
|
if (debug) console.log("Set light intensity to " + this._intensity, val, this)
|
|
207
240
|
}
|
|
@@ -297,10 +330,6 @@ export class Light extends Behaviour implements ILight {
|
|
|
297
330
|
return vec;
|
|
298
331
|
}
|
|
299
332
|
|
|
300
|
-
// public updateIntensity() {
|
|
301
|
-
// this.intensity = this._intensity;
|
|
302
|
-
// }
|
|
303
|
-
|
|
304
333
|
awake() {
|
|
305
334
|
this.color = new Color(this.color ?? 0xffffff);
|
|
306
335
|
if (debug) console.log(this.name, this);
|
|
@@ -334,27 +363,6 @@ export class Light extends Behaviour implements ILight {
|
|
|
334
363
|
}
|
|
335
364
|
}
|
|
336
365
|
|
|
337
|
-
private _webXRStartedListener?: Function;
|
|
338
|
-
private _webXREndedListener?: Function;
|
|
339
|
-
private _webARRoot?: WebARSessionRoot;
|
|
340
|
-
|
|
341
|
-
onEnterXR(_args: NeedleXREventArgs): void {
|
|
342
|
-
this._webARRoot = GameObject.getComponentInParent(this.gameObject, WebARSessionRoot) ?? undefined;
|
|
343
|
-
// this.startCoroutine(this._updateLightIntensityInARRoutine());
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
// private *_updateLightIntensityInARRoutine() {
|
|
347
|
-
// while (this.context.isInAR) {
|
|
348
|
-
// yield;
|
|
349
|
-
// // this.updateIntensity();
|
|
350
|
-
// for (let i = 0; i < 30; i++) yield;
|
|
351
|
-
// }
|
|
352
|
-
// }
|
|
353
|
-
|
|
354
|
-
onLeaveXR(_args: NeedleXREventArgs): void {
|
|
355
|
-
// this.updateIntensity();
|
|
356
|
-
}
|
|
357
|
-
|
|
358
366
|
/**
|
|
359
367
|
* Creates the appropriate three.js light based on the configured light type
|
|
360
368
|
* and applies all settings like shadows, intensity, and color.
|
|
@@ -551,8 +551,6 @@ export class WebXR extends Behaviour {
|
|
|
551
551
|
* and device capabilities. Handles creating AR, VR, QuickLook buttons and utility buttons like QR codes.
|
|
552
552
|
*/
|
|
553
553
|
private handleCreatingHTML() {
|
|
554
|
-
const xrButtonsPriority = 50;
|
|
555
|
-
|
|
556
554
|
if (this.createARButton || this.createVRButton || this.useQuicklookExport) {
|
|
557
555
|
// Quicklook / iOS
|
|
558
556
|
if ((DeviceUtilities.isiOS() && DeviceUtilities.isSafari()) || debugQuicklook) {
|
|
@@ -560,18 +558,18 @@ export class WebXR extends Behaviour {
|
|
|
560
558
|
const usdzExporter = GameObject.findObjectOfType(USDZExporter);
|
|
561
559
|
if (!usdzExporter || (usdzExporter && usdzExporter.allowCreateQuicklookButton)) {
|
|
562
560
|
const button = this.getButtonsFactory().createQuicklookButton();
|
|
563
|
-
this.addButton(button
|
|
561
|
+
this.addButton(button);
|
|
564
562
|
}
|
|
565
563
|
}
|
|
566
564
|
}
|
|
567
565
|
// WebXR
|
|
568
566
|
if (this.createARButton) {
|
|
569
567
|
const arbutton = this.getButtonsFactory().createARButton();
|
|
570
|
-
this.addButton(arbutton
|
|
568
|
+
this.addButton(arbutton);
|
|
571
569
|
}
|
|
572
570
|
if (this.createVRButton) {
|
|
573
571
|
const vrbutton = this.getButtonsFactory().createVRButton();
|
|
574
|
-
this.addButton(vrbutton
|
|
572
|
+
this.addButton(vrbutton);
|
|
575
573
|
}
|
|
576
574
|
}
|
|
577
575
|
|
|
@@ -579,7 +577,7 @@ export class WebXR extends Behaviour {
|
|
|
579
577
|
NeedleXRSession.isVRSupported().then(supported => {
|
|
580
578
|
if (!supported) {
|
|
581
579
|
const button = this.getButtonsFactory().createSendToQuestButton();
|
|
582
|
-
this.addButton(button
|
|
580
|
+
this.addButton(button);
|
|
583
581
|
}
|
|
584
582
|
});
|
|
585
583
|
}
|
|
@@ -592,7 +590,7 @@ export class WebXR extends Behaviour {
|
|
|
592
590
|
}
|
|
593
591
|
else if (!DeviceUtilities.isMobileDevice()) {
|
|
594
592
|
const qrCode = ButtonsFactory.getOrCreate().createQRCode();
|
|
595
|
-
this.addButton(qrCode,
|
|
593
|
+
this.addButton(qrCode,);
|
|
596
594
|
}
|
|
597
595
|
}
|
|
598
596
|
}
|
|
@@ -607,9 +605,8 @@ export class WebXR extends Behaviour {
|
|
|
607
605
|
* @param button The HTML element to add
|
|
608
606
|
* @param priority The button's priority value (lower numbers appear first)
|
|
609
607
|
*/
|
|
610
|
-
private addButton(button: HTMLElement
|
|
608
|
+
private addButton(button: HTMLElement) {
|
|
611
609
|
this._buttons.push(button);
|
|
612
|
-
button.setAttribute("priority", priority.toString());
|
|
613
610
|
this.context.menu.appendChild(button);
|
|
614
611
|
}
|
|
615
612
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ImageBitmapLoader, Matrix4, Object3D, Quaternion, Vector3 } from "three";
|
|
2
2
|
import { Object3DEventMap } from "three";
|
|
3
3
|
|
|
4
|
-
import { isDevEnvironment, showBalloonWarning } from "../../engine/debug/index.js";
|
|
4
|
+
import { isDevEnvironment, showBalloonMessage, showBalloonWarning } from "../../engine/debug/index.js";
|
|
5
5
|
import { AssetReference } from "../../engine/engine_addressables.js";
|
|
6
6
|
import { Context } from "../../engine/engine_context.js";
|
|
7
7
|
import { serializable } from "../../engine/engine_serialization.js";
|
|
@@ -18,6 +18,8 @@ import { Renderer } from "../Renderer.js";
|
|
|
18
18
|
|
|
19
19
|
const debug = getParam("debugimagetracking");
|
|
20
20
|
|
|
21
|
+
// #region WebXRTrackedImage
|
|
22
|
+
|
|
21
23
|
export class WebXRTrackedImage {
|
|
22
24
|
|
|
23
25
|
get url(): string { return this._trackedImage.image ?? ""; }
|
|
@@ -100,6 +102,10 @@ declare type InitialTrackedObjectState = {
|
|
|
100
102
|
parent: Object3D | undefined | null;
|
|
101
103
|
matrix: Matrix4;
|
|
102
104
|
}
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
// #region Model
|
|
108
|
+
|
|
103
109
|
/**
|
|
104
110
|
* WebXRImageTracking allows you to track images in the real world and place objects on top of them.
|
|
105
111
|
* This component is only available in WebXR sessions.
|
|
@@ -171,6 +177,8 @@ export class WebXRImageTrackingModel {
|
|
|
171
177
|
}
|
|
172
178
|
}
|
|
173
179
|
|
|
180
|
+
|
|
181
|
+
// #region USDZ Extension
|
|
174
182
|
class ImageTrackingExtension implements IUSDExporterExtension {
|
|
175
183
|
|
|
176
184
|
|
|
@@ -289,6 +297,7 @@ class ImageTrackingExtension implements IUSDExporterExtension {
|
|
|
289
297
|
}
|
|
290
298
|
|
|
291
299
|
|
|
300
|
+
// #region Tracking Component
|
|
292
301
|
/**
|
|
293
302
|
* Add this component to a object to enable image tracking in WebXR sessions.
|
|
294
303
|
*
|
|
@@ -394,7 +403,7 @@ export class WebXRImageTracking extends Behaviour {
|
|
|
394
403
|
if (!args.optionalFeatures.includes("image-tracking"))
|
|
395
404
|
args.optionalFeatures.push("image-tracking");
|
|
396
405
|
|
|
397
|
-
args.trackedImages = [];
|
|
406
|
+
if(!args.trackedImages) args.trackedImages = [];
|
|
398
407
|
for (const trackedImage of this.trackedImages) {
|
|
399
408
|
if (trackedImage.image?.length && trackedImage.widthInMeters > 0) {
|
|
400
409
|
const bitmap = _imageElements.get(trackedImage.image);
|
|
@@ -533,6 +542,7 @@ export class WebXRImageTracking extends Behaviour {
|
|
|
533
542
|
if (trackedImage.model === key) {
|
|
534
543
|
// Make sure to keep the object visible if it's marked as static OR is tracked OR was tracked very recently (e.g. low framerate or bad tracking on device)
|
|
535
544
|
const timeSinceLastTracking = Date.now() - value.lastTrackingTime;
|
|
545
|
+
if(debug) showBalloonMessage(key.image + ", State: " + trackedImage.state + (key.imageDoesNotMove ? " (static)" : "") + (timeSinceLastTracking <= hysteresis ? " (hysteresis)" : ""));
|
|
536
546
|
if (key.imageDoesNotMove || trackedImage.state === "tracked" || timeSinceLastTracking <= hysteresis) {
|
|
537
547
|
found = true;
|
|
538
548
|
break;
|