@needle-tools/engine 3.0.1-alpha.5 → 3.1.0-alpha
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 +7 -0
- package/dist/needle-engine.js +24245 -24524
- package/dist/needle-engine.min.js +367 -354
- package/dist/needle-engine.umd.cjs +366 -353
- package/lib/engine/api.d.ts +1 -1
- package/lib/engine/api.js +1 -1
- package/lib/engine/api.js.map +1 -1
- package/lib/engine/codegen/register_types.js +8 -0
- package/lib/engine/codegen/register_types.js.map +1 -1
- package/lib/engine/engine_addressables.d.ts +21 -1
- package/lib/engine/engine_addressables.js +83 -7
- package/lib/engine/engine_addressables.js.map +1 -1
- package/lib/engine/engine_serialization.d.ts +2 -2
- package/lib/engine/engine_serialization.js +2 -3
- package/lib/engine/engine_serialization.js.map +1 -1
- package/lib/engine/engine_serialization_builtin_serializer.d.ts +5 -0
- package/lib/engine/engine_serialization_builtin_serializer.js +16 -0
- package/lib/engine/engine_serialization_builtin_serializer.js.map +1 -1
- package/lib/engine/engine_serialization_core.d.ts +1 -0
- package/lib/engine/engine_serialization_core.js +26 -20
- package/lib/engine/engine_serialization_core.js.map +1 -1
- package/lib/engine/engine_utils.d.ts +9 -0
- package/lib/engine/engine_utils.js +33 -13
- package/lib/engine/engine_utils.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_animator_controller_model.d.ts +1 -0
- package/lib/engine/extensions/NEEDLE_animator_controller_model.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_progressive.js +2 -2
- package/lib/engine/extensions/NEEDLE_progressive.js.map +1 -1
- package/lib/engine-components/AnimatorController.js +22 -3
- package/lib/engine-components/AnimatorController.js.map +1 -1
- package/lib/engine-components/AudioSource.js +3 -2
- package/lib/engine-components/AudioSource.js.map +1 -1
- package/lib/engine-components/Component.js.map +1 -1
- package/lib/engine-components/ParticleSystem.d.ts +5 -2
- package/lib/engine-components/ParticleSystem.js +34 -4
- package/lib/engine-components/ParticleSystem.js.map +1 -1
- package/lib/engine-components/ParticleSystemModules.d.ts +1 -0
- package/lib/engine-components/ParticleSystemModules.js +1 -1
- package/lib/engine-components/ParticleSystemModules.js.map +1 -1
- package/lib/engine-components/Skybox.js +2 -2
- package/lib/engine-components/Skybox.js.map +1 -1
- package/lib/engine-components/VideoPlayer.d.ts +1 -2
- package/lib/engine-components/VideoPlayer.js +6 -7
- package/lib/engine-components/VideoPlayer.js.map +1 -1
- package/lib/engine-components/WebXR.d.ts +4 -1
- package/lib/engine-components/WebXR.js +10 -2
- package/lib/engine-components/WebXR.js.map +1 -1
- package/lib/engine-components/WebXRController.js +2 -2
- package/lib/engine-components/WebXRController.js.map +1 -1
- package/lib/engine-components/WebXRImageTracking.d.ts +39 -0
- package/lib/engine-components/WebXRImageTracking.js +173 -0
- package/lib/engine-components/WebXRImageTracking.js.map +1 -0
- package/lib/engine-components/codegen/components.d.ts +4 -0
- package/lib/engine-components/codegen/components.js +4 -0
- package/lib/engine-components/codegen/components.js.map +1 -1
- package/lib/engine-components/postprocessing/Effects/DepthOfField.d.ts +1 -0
- package/lib/engine-components/postprocessing/Effects/DepthOfField.js +4 -0
- package/lib/engine-components/postprocessing/Effects/DepthOfField.js.map +1 -1
- package/lib/engine-components/postprocessing/Effects/TiltShiftEffect.d.ts +13 -0
- package/lib/engine-components/postprocessing/Effects/TiltShiftEffect.js +63 -0
- package/lib/engine-components/postprocessing/Effects/TiltShiftEffect.js.map +1 -0
- package/lib/engine-components/timeline/TimelineTracks.js +2 -2
- package/lib/engine-components/timeline/TimelineTracks.js.map +1 -1
- package/lib/engine-components/ui/Text.js +7 -7
- package/lib/engine-components/ui/Text.js.map +1 -1
- package/lib/include/three/ARButton.d.ts +1 -1
- package/lib/include/three/ARButton.js +2 -1
- package/lib/include/three/ARButton.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/plugins/vite/config.js +8 -0
- package/plugins/vite/copyfiles.js +12 -3
- package/plugins/vite/drop.js +1 -0
- package/plugins/vite/index.js +2 -0
- package/plugins/vite/transform-codegen.js +45 -0
- package/src/engine/api.ts +1 -1
- package/src/engine/codegen/register_types.js +8 -0
- package/src/engine/engine_addressables.ts +102 -8
- package/src/engine/engine_serialization.ts +5 -4
- package/src/engine/engine_serialization_builtin_serializer.ts +23 -3
- package/src/engine/engine_serialization_core.ts +27 -20
- package/src/engine/engine_utils.ts +35 -14
- package/src/engine/extensions/NEEDLE_animator_controller_model.ts +1 -0
- package/src/engine/extensions/NEEDLE_progressive.ts +2 -2
- package/src/engine-components/AnimatorController.ts +18 -3
- package/src/engine-components/AudioSource.ts +2 -2
- package/src/engine-components/Component.ts +1 -1
- package/src/engine-components/ParticleSystem.ts +34 -4
- package/src/engine-components/ParticleSystemModules.ts +1 -1
- package/src/engine-components/Skybox.ts +2 -2
- package/src/engine-components/VideoPlayer.ts +6 -6
- package/src/engine-components/WebXR.ts +11 -2
- package/src/engine-components/WebXRController.ts +2 -2
- package/src/engine-components/WebXRImageTracking.ts +192 -0
- package/src/engine-components/codegen/components.ts +4 -0
- package/src/engine-components/postprocessing/Effects/DepthOfField.ts +3 -0
- package/src/engine-components/postprocessing/Effects/TiltShiftEffect.ts +56 -0
- package/src/engine-components/timeline/TimelineTracks.ts +2 -2
- package/src/engine-components/ui/Text.ts +7 -7
- package/src/include/three/ARButton.js +2 -2
|
@@ -193,6 +193,7 @@ class ParticleSystemEmissionOverTime extends BaseValueGenerator {
|
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
genValue(): number {
|
|
196
|
+
if (!this.system.isPlaying) return 0;
|
|
196
197
|
if (!this.system.emission.enabled) return 0;
|
|
197
198
|
if (this.system.currentParticles >= this.system.maxParticles) return 0;
|
|
198
199
|
// emission over time
|
|
@@ -220,6 +221,7 @@ class ParticleSystemEmissionOverTime extends BaseValueGenerator {
|
|
|
220
221
|
class ParticleSystemEmissionOverDistance extends BaseValueGenerator {
|
|
221
222
|
|
|
222
223
|
genValue(): number {
|
|
224
|
+
if (!this.system.isPlaying) return 0;
|
|
223
225
|
// this seems not be called yet
|
|
224
226
|
return 0;
|
|
225
227
|
// if (this.system.currentParticles >= this.system.maxParticles) return 0;
|
|
@@ -547,7 +549,7 @@ class ParticleSystemInterface implements ParticleSystemParameters {
|
|
|
547
549
|
}
|
|
548
550
|
switch (this.system.renderer.renderMode) {
|
|
549
551
|
case ParticleSystemRenderMode.Billboard: return RenderMode.BillBoard;
|
|
550
|
-
|
|
552
|
+
case ParticleSystemRenderMode.Stretch: return RenderMode.StretchedBillBoard;
|
|
551
553
|
case ParticleSystemRenderMode.HorizontalBillboard: return RenderMode.LocalSpace;
|
|
552
554
|
case ParticleSystemRenderMode.VerticalBillboard: return RenderMode.LocalSpace;
|
|
553
555
|
case ParticleSystemRenderMode.Mesh: return RenderMode.LocalSpace;
|
|
@@ -597,8 +599,8 @@ export class ParticleSystem extends Behaviour implements IParticleSystem {
|
|
|
597
599
|
}
|
|
598
600
|
}, true)
|
|
599
601
|
}
|
|
602
|
+
|
|
600
603
|
this._isPlaying = true;
|
|
601
|
-
this._time = 0;
|
|
602
604
|
|
|
603
605
|
// https://github.com/Alchemist0823/three.quarks/pull/35
|
|
604
606
|
if (this._particleSystem) {
|
|
@@ -608,12 +610,40 @@ export class ParticleSystem extends Behaviour implements IParticleSystem {
|
|
|
608
610
|
this.emission?.reset();
|
|
609
611
|
}
|
|
610
612
|
|
|
611
|
-
pause() {
|
|
613
|
+
pause(includeChildren = true) {
|
|
614
|
+
if (includeChildren) {
|
|
615
|
+
GameObject.foreachComponent(this.gameObject, comp => {
|
|
616
|
+
if (comp instanceof ParticleSystem && comp !== this) {
|
|
617
|
+
comp.pause(false);
|
|
618
|
+
}
|
|
619
|
+
}, true)
|
|
620
|
+
}
|
|
612
621
|
this._isPlaying = false;
|
|
613
622
|
}
|
|
614
|
-
|
|
623
|
+
|
|
624
|
+
/** clear=true removes all emitted particles */
|
|
625
|
+
stop(includeChildren = true, clear: boolean = false) {
|
|
626
|
+
if (includeChildren) {
|
|
627
|
+
GameObject.foreachComponent(this.gameObject, comp => {
|
|
628
|
+
if (comp instanceof ParticleSystem && comp !== this) {
|
|
629
|
+
comp.stop(false, clear);
|
|
630
|
+
}
|
|
631
|
+
}, true)
|
|
632
|
+
}
|
|
615
633
|
this._isPlaying = false;
|
|
616
634
|
this._time = 0;
|
|
635
|
+
if (clear) this.reset();
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
/** remove emitted particles and reset time */
|
|
639
|
+
reset() {
|
|
640
|
+
this._time = 0;
|
|
641
|
+
if (this._particleSystem) {
|
|
642
|
+
this._particleSystem.particleNum = 0;
|
|
643
|
+
this._particleSystem["emissionState"].time = 0;
|
|
644
|
+
this._particleSystem["emitEnded"] = false;
|
|
645
|
+
this.emission?.reset();
|
|
646
|
+
}
|
|
617
647
|
}
|
|
618
648
|
|
|
619
649
|
private _state?: ParticlesEmissionState;
|
|
@@ -5,7 +5,7 @@ import { EXRLoader } from "three/examples/jsm/loaders/EXRLoader";
|
|
|
5
5
|
import { EquirectangularRefractionMapping, sRGBEncoding, Texture, TextureLoader } from "three"
|
|
6
6
|
import { syncField } from "../engine/engine_networking_auto";
|
|
7
7
|
import { Camera } from "./Camera";
|
|
8
|
-
import { getParam,
|
|
8
|
+
import { getParam, resolveUrl } from "../engine/engine_utils";
|
|
9
9
|
|
|
10
10
|
const debug = getParam("debugskybox");
|
|
11
11
|
|
|
@@ -56,7 +56,7 @@ export class RemoteSkybox extends Behaviour {
|
|
|
56
56
|
if(debug) console.log("Remote skybox url?: " + url);
|
|
57
57
|
|
|
58
58
|
if (!url.startsWith("http") && !url.startsWith("www.") && !url.startsWith("data:")) {
|
|
59
|
-
url =
|
|
59
|
+
url = resolveUrl(this.sourceId, url);
|
|
60
60
|
if(debug) console.log("Remote skybox resolved to " + url);
|
|
61
61
|
}
|
|
62
62
|
|
|
@@ -3,7 +3,7 @@ import * as THREE from "three";
|
|
|
3
3
|
import { serializable } from "../engine/engine_serialization_decorator";
|
|
4
4
|
import { LinearFilter, Material, Mesh, Object3D, RawShaderMaterial, ShaderMaterial, Texture, TextureLoader, Vector2, Vector4, VideoTexture } from "three";
|
|
5
5
|
import { awaitInput } from "../engine/engine_input_utils";
|
|
6
|
-
import { getParam } from "../engine/engine_utils";
|
|
6
|
+
import { getParam, resolveUrl } from "../engine/engine_utils";
|
|
7
7
|
import { Renderer } from "./Renderer";
|
|
8
8
|
import { getWorldScale } from "../engine/engine_three_utils";
|
|
9
9
|
import { ObjectUtils, PrimitiveType } from "../engine/engine_create_objects";
|
|
@@ -49,11 +49,12 @@ export class VideoPlayer extends Behaviour {
|
|
|
49
49
|
renderer: THREE.Object3D | null = null;
|
|
50
50
|
@serializable()
|
|
51
51
|
playOnAwake: boolean = true;
|
|
52
|
-
@serializable()
|
|
53
|
-
playOnEnable?: boolean;
|
|
54
52
|
|
|
55
53
|
@serializable()
|
|
56
54
|
aspectMode: AspectMode = AspectMode.None;
|
|
55
|
+
|
|
56
|
+
@serializable(URL)
|
|
57
|
+
private clip?: string | MediaStream | null = null;
|
|
57
58
|
|
|
58
59
|
@serializable()
|
|
59
60
|
private renderMode?: VideoRenderMode;
|
|
@@ -153,7 +154,6 @@ export class VideoPlayer extends Behaviour {
|
|
|
153
154
|
private audioOutputMode: VideoAudioOutputMode = VideoAudioOutputMode.AudioSource;
|
|
154
155
|
|
|
155
156
|
private source!: VideoSource;
|
|
156
|
-
private clip?: string | MediaStream | null = null;
|
|
157
157
|
private url?: string | null = null;
|
|
158
158
|
|
|
159
159
|
private _videoElement: HTMLVideoElement | null = null;
|
|
@@ -209,7 +209,7 @@ export class VideoPlayer extends Behaviour {
|
|
|
209
209
|
}
|
|
210
210
|
|
|
211
211
|
onEnable(): void {
|
|
212
|
-
if (this.
|
|
212
|
+
if (this.playOnAwake === true) {
|
|
213
213
|
this.handleBeginPlaying(true);
|
|
214
214
|
}
|
|
215
215
|
if (this.screenspace) {
|
|
@@ -422,7 +422,7 @@ export class VideoPlayer extends Behaviour {
|
|
|
422
422
|
let muted = !this._receivedInput && this.audioOutputMode !== VideoAudioOutputMode.None;
|
|
423
423
|
if(!muted && this._muted) muted = true;
|
|
424
424
|
this._videoElement.muted = muted;
|
|
425
|
-
if (this.playOnAwake
|
|
425
|
+
if (this.playOnAwake)
|
|
426
426
|
this._videoElement.autoplay = true;
|
|
427
427
|
}
|
|
428
428
|
|
|
@@ -47,6 +47,7 @@ export enum WebXREvent {
|
|
|
47
47
|
XRStopped = "xrStopped",
|
|
48
48
|
XRUpdate = "xrUpdate",
|
|
49
49
|
RequestVRSession = "requestVRSession",
|
|
50
|
+
ModifyAROptions = "modify-ar-options",
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
export declare type CreateButtonOptions = {
|
|
@@ -91,6 +92,9 @@ export class WebXR extends Behaviour {
|
|
|
91
92
|
this.events.removeEventListener(type, listener);
|
|
92
93
|
return listener;
|
|
93
94
|
}
|
|
95
|
+
private static dispatchEvent(type: string, event: any): void {
|
|
96
|
+
this.events.dispatchEvent({ type, detail: event });
|
|
97
|
+
}
|
|
94
98
|
|
|
95
99
|
public static createVRButton(webXR: WebXR, opts?: CreateButtonOptions): HTMLButtonElement | HTMLAnchorElement {
|
|
96
100
|
if (!WebXR.XRSupported) {
|
|
@@ -122,7 +126,7 @@ export class WebXR extends Behaviour {
|
|
|
122
126
|
console.warn("No dom overlay root found, HTML overlays on top of screen-based AR will not work.");
|
|
123
127
|
}
|
|
124
128
|
|
|
125
|
-
const arButton = ARButton.createButton(webXR.context.renderer, options);
|
|
129
|
+
const arButton = ARButton.createButton(webXR.context.renderer, options, this.onModifyAROptions.bind(this));
|
|
126
130
|
arButton.classList.add('webxr-ar-button');
|
|
127
131
|
arButton.classList.add('webxr-button');
|
|
128
132
|
WebXR.resetButtonStyles(arButton);
|
|
@@ -131,6 +135,10 @@ export class WebXR extends Behaviour {
|
|
|
131
135
|
return arButton;
|
|
132
136
|
}
|
|
133
137
|
|
|
138
|
+
private static onModifyAROptions(options){
|
|
139
|
+
WebXR.dispatchEvent(WebXREvent.ModifyAROptions, options);
|
|
140
|
+
}
|
|
141
|
+
|
|
134
142
|
public static resetButtonStyles(button) {
|
|
135
143
|
if (!button) return;
|
|
136
144
|
button.style.position = "";
|
|
@@ -233,7 +241,8 @@ export class WebXR extends Behaviour {
|
|
|
233
241
|
this.context.domElement.append(buttonsContainer);
|
|
234
242
|
|
|
235
243
|
// AR support
|
|
236
|
-
if (this.enableAR && this.createARButton && arSupported)
|
|
244
|
+
// if (this.enableAR && this.createARButton && arSupported)
|
|
245
|
+
{
|
|
237
246
|
arButton = WebXR.createARButton(this);
|
|
238
247
|
this._arButton = arButton;
|
|
239
248
|
buttonsContainer.appendChild(arButton);
|
|
@@ -8,7 +8,7 @@ import { InstancingUtil } from "../engine/engine_instancing";
|
|
|
8
8
|
import { Mathf } from "../engine/engine_math";
|
|
9
9
|
import { RaycastOptions } from "../engine/engine_physics";
|
|
10
10
|
import { getWorldPosition, getWorldQuaternion, setWorldPosition, setWorldQuaternion } from "../engine/engine_three_utils";
|
|
11
|
-
import { getParam,
|
|
11
|
+
import { getParam, resolveUrl } from "../engine/engine_utils";
|
|
12
12
|
import { addDracoAndKTX2Loaders } from "../engine/engine_loaders";
|
|
13
13
|
|
|
14
14
|
import { Avatar_POI } from "./avatar/Avatar_Brain_LookAt";
|
|
@@ -85,7 +85,7 @@ export class WebXRController extends Behaviour {
|
|
|
85
85
|
const loader = new GLTFLoader();
|
|
86
86
|
addDracoAndKTX2Loaders(loader, context);
|
|
87
87
|
if (ctrl.webXR.handModelPath && ctrl.webXR.handModelPath !== "")
|
|
88
|
-
loader.setPath(
|
|
88
|
+
loader.setPath(resolveUrl(owner.sourceId, ctrl.webXR.handModelPath));
|
|
89
89
|
else
|
|
90
90
|
// from XRHandMeshModel.js
|
|
91
91
|
loader.setPath('https://cdn.jsdelivr.net/npm/@webxr-input-profiles/assets@1.0/dist/profiles/generic-hand/');
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { WebXR } from "./WebXR";
|
|
2
|
+
import { serializable } from "../engine/engine_serialization";
|
|
3
|
+
import { Behaviour } from "./Component";
|
|
4
|
+
import { Matrix4, Object3D, Quaternion, Vector, Vector3 } from "three";
|
|
5
|
+
import { CircularBuffer, getParam } from "../engine/engine_utils";
|
|
6
|
+
|
|
7
|
+
// https://github.com/immersive-web/marker-tracking/blob/main/explainer.md
|
|
8
|
+
|
|
9
|
+
const debug = getParam("debugimagetracking");
|
|
10
|
+
|
|
11
|
+
const _scaleTemp = new Vector3();
|
|
12
|
+
|
|
13
|
+
export class WebXRTrackedImage {
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
get url(): string { return this._trackedImage.image ?? ""; }
|
|
17
|
+
get widthInMeters() { return this._trackedImage.widthInMeters ?? undefined; }
|
|
18
|
+
get bitmap(): ImageBitmap { return this._bitmap; }
|
|
19
|
+
readonly measuredSize: number;
|
|
20
|
+
readonly state: "tracked" | "emulated";
|
|
21
|
+
|
|
22
|
+
// private _matrix: Matrix4 | null = null;
|
|
23
|
+
// private get matrix(): Matrix4 {
|
|
24
|
+
// if (!this._matrix) {
|
|
25
|
+
// // this._matrix = WebXRTrackedImage._matrixBuffer.get();
|
|
26
|
+
// // const matrix = this._pose.transform.matrix;
|
|
27
|
+
// // this._matrix.fromArray(matrix);
|
|
28
|
+
// }
|
|
29
|
+
// return this._matrix!;
|
|
30
|
+
// }
|
|
31
|
+
|
|
32
|
+
/** Copy the image position to a vector */
|
|
33
|
+
getPosition(vec: Vector3) {
|
|
34
|
+
this.ensureTransformData();
|
|
35
|
+
vec.copy(this._position);
|
|
36
|
+
return vec;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Copy the image rotation to a quaternion */
|
|
40
|
+
getQuaternion(quat: Quaternion) {
|
|
41
|
+
this.ensureTransformData();
|
|
42
|
+
quat.copy(this._rotation);
|
|
43
|
+
return quat;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
applyToObject(object: Object3D) {
|
|
47
|
+
this.ensureTransformData();
|
|
48
|
+
object.position.copy(this._position);
|
|
49
|
+
object.quaternion.copy(this._rotation);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// private static _matrixBuffer: CircularBuffer<Matrix4> = new CircularBuffer(() => new Matrix4(), 20);
|
|
53
|
+
private static _positionBuffer: CircularBuffer<Vector3> = new CircularBuffer(() => new Vector3(), 20);
|
|
54
|
+
private static _rotationBuffer: CircularBuffer<Quaternion> = new CircularBuffer(() => new Quaternion(), 20);
|
|
55
|
+
private _position!: Vector3;
|
|
56
|
+
private _rotation!: Quaternion;
|
|
57
|
+
private ensureTransformData() {
|
|
58
|
+
if (!this._position) {
|
|
59
|
+
this._position = WebXRTrackedImage._positionBuffer.get();
|
|
60
|
+
this._rotation = WebXRTrackedImage._rotationBuffer.get();
|
|
61
|
+
const t = this._pose.transform;
|
|
62
|
+
this._position.set(-t.position.x, t.position.y, -t.position.z);
|
|
63
|
+
this._rotation.set(-t.orientation.x, t.orientation.y, -t.orientation.z, t.orientation.w);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
private readonly _trackingComponent: WebXRImageTracking;;
|
|
68
|
+
private readonly _trackedImage: WebXRImageTrackingModel;
|
|
69
|
+
private readonly _bitmap: ImageBitmap;
|
|
70
|
+
private readonly _pose: any;
|
|
71
|
+
|
|
72
|
+
constructor(context: WebXRImageTracking, trackedImage: WebXRImageTrackingModel, bitmap: ImageBitmap, measuredSize: number, state: "tracked" | "emulated", pose: any) {
|
|
73
|
+
this._trackingComponent = context;;
|
|
74
|
+
this._trackedImage = trackedImage;
|
|
75
|
+
this._bitmap = bitmap;
|
|
76
|
+
this.measuredSize = measuredSize;
|
|
77
|
+
this.state = state;
|
|
78
|
+
this._pose = pose;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
declare type WebXRImageTrackingEvent = (images: WebXRImageTrackingEvent[]) => void;
|
|
84
|
+
|
|
85
|
+
export class WebXRImageTrackingModel {
|
|
86
|
+
|
|
87
|
+
@serializable()
|
|
88
|
+
image?: string;
|
|
89
|
+
|
|
90
|
+
@serializable()
|
|
91
|
+
widthInMeters!: number;
|
|
92
|
+
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export class WebXRImageTracking extends Behaviour {
|
|
96
|
+
|
|
97
|
+
@serializable(WebXRImageTrackingModel)
|
|
98
|
+
trackedImages!: WebXRImageTrackingModel[];
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
private readonly trackedImageIndexMap: Map<number, WebXRImageTrackingModel> = new Map();
|
|
104
|
+
|
|
105
|
+
private static _imageElements: Map<string, ImageBitmap | null> = new Map();
|
|
106
|
+
|
|
107
|
+
awake(): void {
|
|
108
|
+
for (const trackedImage of this.trackedImages) {
|
|
109
|
+
if (trackedImage.image) {
|
|
110
|
+
if (WebXRImageTracking._imageElements.has(trackedImage.image)) {
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
const url = trackedImage.image;
|
|
114
|
+
WebXRImageTracking._imageElements.set(url, null);
|
|
115
|
+
const imageElement = document.createElement("img") as HTMLImageElement;
|
|
116
|
+
imageElement.src = url;
|
|
117
|
+
imageElement.addEventListener("load", async () => {
|
|
118
|
+
const img = await createImageBitmap(imageElement);
|
|
119
|
+
WebXRImageTracking._imageElements.set(url, img);
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
onEnable(): void {
|
|
127
|
+
WebXR.addEventListener("modify-ar-options", this.onModifyAROptions);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
onDisable(): void {
|
|
131
|
+
WebXR.removeEventListener("modify-ar-options", this.onModifyAROptions);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
private onModifyAROptions = (event: any) => {
|
|
136
|
+
const options = event.detail;
|
|
137
|
+
const features = options.optionalFeatures || [];
|
|
138
|
+
features.push("image-tracking");
|
|
139
|
+
options.optionalFeatures = features;
|
|
140
|
+
|
|
141
|
+
options.trackedImages = [];
|
|
142
|
+
for (const trackedImage of this.trackedImages) {
|
|
143
|
+
if (trackedImage.image?.length && trackedImage.widthInMeters > 0) {
|
|
144
|
+
const bitmap = WebXRImageTracking._imageElements.get(trackedImage.image);
|
|
145
|
+
if (bitmap) {
|
|
146
|
+
this.trackedImageIndexMap.set(options.trackedImages.length, trackedImage);
|
|
147
|
+
options.trackedImages.push({
|
|
148
|
+
image: bitmap,
|
|
149
|
+
widthInMeters: trackedImage.widthInMeters
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
onBeforeRender(frame: XRFrame | null): void {
|
|
157
|
+
//@ts-ignore
|
|
158
|
+
if (frame?.session && typeof frame.getImageTrackingResults === "function") {
|
|
159
|
+
//@ts-ignore
|
|
160
|
+
const results = frame.getImageTrackingResults();
|
|
161
|
+
if (results.length) {
|
|
162
|
+
const space = this.context.renderer.xr.getReferenceSpace();
|
|
163
|
+
if (space) {
|
|
164
|
+
const images: WebXRTrackedImage[] = [];
|
|
165
|
+
for (const result of results) {
|
|
166
|
+
const imageIndex = result.index;
|
|
167
|
+
const trackedImage = this.trackedImageIndexMap.get(imageIndex);
|
|
168
|
+
if (trackedImage) {
|
|
169
|
+
const pose = frame.getPose(result.imageSpace, space);
|
|
170
|
+
const state = result.trackingState;
|
|
171
|
+
const imageData = new WebXRTrackedImage(this, trackedImage, result.image, result.measuredSize, state, pose);
|
|
172
|
+
images.push(imageData);
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
if (debug) {
|
|
176
|
+
console.warn("No tracked image for index", imageIndex);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (images.length > 0) {
|
|
181
|
+
try {
|
|
182
|
+
this.dispatchEvent(new CustomEvent("image-tracking", { detail: images }));
|
|
183
|
+
}
|
|
184
|
+
catch (e) {
|
|
185
|
+
console.error(e);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
@@ -145,6 +145,7 @@ export { TestRunner } from "../TestRunner";
|
|
|
145
145
|
export { TestSimulateUserData } from "../TestRunner";
|
|
146
146
|
export { Text } from "../ui/Text";
|
|
147
147
|
export { TextureSheetAnimationModule } from "../ParticleSystemModules";
|
|
148
|
+
export { TiltShiftEffect } from "../postprocessing/Effects/TiltShiftEffect";
|
|
148
149
|
export { ToneMapping } from "../postprocessing/Effects/Tonemapping";
|
|
149
150
|
export { TrailModule } from "../ParticleSystemModules";
|
|
150
151
|
export { TransformData } from "../export/usdz/extensions/Animation";
|
|
@@ -168,7 +169,10 @@ export { WebARSessionRoot } from "../WebARSessionRoot";
|
|
|
168
169
|
export { WebXR } from "../WebXR";
|
|
169
170
|
export { WebXRAvatar } from "../WebXRAvatar";
|
|
170
171
|
export { WebXRController } from "../WebXRController";
|
|
172
|
+
export { WebXRImageTracking } from "../WebXRImageTracking";
|
|
173
|
+
export { WebXRImageTrackingModel } from "../WebXRImageTracking";
|
|
171
174
|
export { WebXRSync } from "../WebXRSync";
|
|
175
|
+
export { WebXRTrackedImage } from "../WebXRImageTracking";
|
|
172
176
|
export { XRFlag } from "../XRFlag";
|
|
173
177
|
export { XRGrabModel } from "../WebXRGrabRendering";
|
|
174
178
|
export { XRGrabRendering } from "../WebXRGrabRendering";
|
|
@@ -36,6 +36,9 @@ export class DepthOfField extends PostProcessingEffect {
|
|
|
36
36
|
@serializable(VolumeParameter)
|
|
37
37
|
resolutionScale?: VolumeParameter;
|
|
38
38
|
|
|
39
|
+
@serializable(VolumeParameter)
|
|
40
|
+
bokehScale?: VolumeParameter;
|
|
41
|
+
|
|
39
42
|
init() {
|
|
40
43
|
this.focalLength.valueProcessor = v => {
|
|
41
44
|
const t = v / 300;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { registerCustomEffectType } from "../VolumeProfile";
|
|
2
|
+
import { EffectProviderResult, PostProcessingEffect } from "../PostProcessingEffect";
|
|
3
|
+
import { KernelSize, TiltShiftEffect as TiltShift } from "postprocessing";
|
|
4
|
+
import { VolumeParameter } from "../VolumeParameter";
|
|
5
|
+
import { serializable } from "../../../engine/engine_serialization";
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
export class TiltShiftEffect extends PostProcessingEffect {
|
|
9
|
+
get typeName(): string {
|
|
10
|
+
return "TiltShiftEffect";
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
@serializable(VolumeParameter)
|
|
14
|
+
offset!: VolumeParameter;
|
|
15
|
+
@serializable(VolumeParameter)
|
|
16
|
+
rotation!: VolumeParameter;
|
|
17
|
+
@serializable(VolumeParameter)
|
|
18
|
+
focusArea!: VolumeParameter;
|
|
19
|
+
@serializable(VolumeParameter)
|
|
20
|
+
feather!: VolumeParameter
|
|
21
|
+
@serializable(VolumeParameter)
|
|
22
|
+
kernelSize!: VolumeParameter;
|
|
23
|
+
@serializable(VolumeParameter)
|
|
24
|
+
resolutionScale!: VolumeParameter;
|
|
25
|
+
|
|
26
|
+
init(): void {
|
|
27
|
+
this.offset.defaultValue = 0;
|
|
28
|
+
this.rotation.defaultValue = 0;
|
|
29
|
+
this.focusArea.defaultValue = 0.4;
|
|
30
|
+
this.feather.defaultValue = 0.3;
|
|
31
|
+
this.kernelSize.defaultValue = KernelSize.MEDIUM;
|
|
32
|
+
this.resolutionScale.defaultValue = 1 / window.devicePixelRatio;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
onCreateEffect(): EffectProviderResult | undefined {
|
|
37
|
+
|
|
38
|
+
console.log(this);
|
|
39
|
+
|
|
40
|
+
const effect = new TiltShift({
|
|
41
|
+
kernelSize: KernelSize.VERY_LARGE,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
this.offset.onValueChanged = v => effect.offset = v;
|
|
45
|
+
this.rotation.onValueChanged = v => effect.rotation = v;
|
|
46
|
+
this.focusArea.onValueChanged = v => effect.focusArea = v;
|
|
47
|
+
this.feather.onValueChanged = v => effect.feather = v;
|
|
48
|
+
this.kernelSize.onValueChanged = v => effect.blurPass.kernelSize = v;
|
|
49
|
+
this.resolutionScale.onValueChanged = v => effect.resolution.scale = v / window.devicePixelRatio;
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
return effect;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
}
|
|
56
|
+
registerCustomEffectType("TiltShiftEffect", TiltShiftEffect);
|
|
@@ -5,7 +5,7 @@ import { GameObject } from "../Component";
|
|
|
5
5
|
import { Context } from "../../engine/engine_setup";
|
|
6
6
|
import { SignalReceiver } from "./SignalAsset";
|
|
7
7
|
import { AnimationClip, Quaternion, Vector3 } from "three";
|
|
8
|
-
import { getParam,
|
|
8
|
+
import { getParam, resolveUrl } from "../../engine/engine_utils";
|
|
9
9
|
import { AudioSource } from "../AudioSource";
|
|
10
10
|
import { Animator } from "../Animator"
|
|
11
11
|
|
|
@@ -517,7 +517,7 @@ export class AudioTrackHandler extends TrackHandler {
|
|
|
517
517
|
private getAudioFilePath(path: string) {
|
|
518
518
|
// TODO: this should be the timeline asset location probably which MIGHT be different
|
|
519
519
|
const glbLocation = this.director.sourceId;
|
|
520
|
-
return
|
|
520
|
+
return resolveUrl(glbLocation, path);
|
|
521
521
|
}
|
|
522
522
|
|
|
523
523
|
onAllowAudioChanged(allow: boolean) {
|
|
@@ -7,7 +7,7 @@ import { FrameEvent } from '../../engine/engine_setup';
|
|
|
7
7
|
import { updateRenderSettings } from './Utils';
|
|
8
8
|
import { Canvas } from './Canvas';
|
|
9
9
|
import { serializable } from '../../engine/engine_serialization_decorator';
|
|
10
|
-
import { getParam,
|
|
10
|
+
import { getParam, resolveUrl } from '../../engine/engine_utils';
|
|
11
11
|
|
|
12
12
|
const debug = getParam("debugtext");
|
|
13
13
|
|
|
@@ -481,24 +481,24 @@ export class Text extends Graphic {
|
|
|
481
481
|
|
|
482
482
|
// if a font path has a known suffix we remove it
|
|
483
483
|
if (fontName.endsWith("-regular")) {
|
|
484
|
-
if (style === FontStyle.Normal) return
|
|
484
|
+
if (style === FontStyle.Normal) return resolveUrl(this.sourceId, fontName);
|
|
485
485
|
fontName = fontName.substring(0, fontName.length - "-regular".length);
|
|
486
486
|
}
|
|
487
487
|
else if (fontName.endsWith("-bold")) {
|
|
488
|
-
if (style === FontStyle.Bold)return
|
|
488
|
+
if (style === FontStyle.Bold)return resolveUrl(this.sourceId, fontName);
|
|
489
489
|
fontName = fontName.substring(0, fontName.length - "-bold".length);
|
|
490
490
|
}
|
|
491
491
|
else if (fontName.endsWith("-italic")) {
|
|
492
|
-
if (style === FontStyle.Italic)return
|
|
492
|
+
if (style === FontStyle.Italic)return resolveUrl(this.sourceId, fontName);
|
|
493
493
|
fontName = fontName.substring(0, fontName.length - "-italic".length);
|
|
494
494
|
}
|
|
495
495
|
else if (fontName.endsWith("-bolditalic")) {
|
|
496
|
-
if (style === FontStyle.BoldAndItalic)return
|
|
496
|
+
if (style === FontStyle.BoldAndItalic)return resolveUrl(this.sourceId, fontName);
|
|
497
497
|
fontName = fontName.substring(0, fontName.length - "-bolditalic".length);
|
|
498
498
|
}
|
|
499
499
|
else
|
|
500
500
|
// If a font does not have a specific style suffic we dont support getting the correct font style
|
|
501
|
-
return
|
|
501
|
+
return resolveUrl(this.sourceId, fontName);
|
|
502
502
|
|
|
503
503
|
switch (style) {
|
|
504
504
|
case FontStyle.Normal:
|
|
@@ -515,7 +515,7 @@ export class Text extends Graphic {
|
|
|
515
515
|
break;
|
|
516
516
|
}
|
|
517
517
|
|
|
518
|
-
return
|
|
518
|
+
return resolveUrl(this.sourceId, fontName);
|
|
519
519
|
}
|
|
520
520
|
}
|
|
521
521
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
class ARButton {
|
|
2
2
|
|
|
3
|
-
static createButton( renderer, options = {} ) {
|
|
3
|
+
static createButton( renderer, options = {}, beforeRequestSession ) {
|
|
4
4
|
|
|
5
5
|
const button = document.createElement( 'button' );
|
|
6
6
|
let ARButtonControlsDomOverlay = false;
|
|
@@ -126,7 +126,7 @@ class ARButton {
|
|
|
126
126
|
button.onclick = function () {
|
|
127
127
|
|
|
128
128
|
if ( currentSession === null ) {
|
|
129
|
-
|
|
129
|
+
beforeRequestSession?.call(this, options);
|
|
130
130
|
navigator.xr.requestSession( 'immersive-ar', options ).then( onSessionStarted );
|
|
131
131
|
|
|
132
132
|
} else {
|