@needle-tools/engine 2.35.4-pre → 2.36.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 +26 -0
- package/dist/needle-engine.d.ts +213 -144
- package/dist/needle-engine.js +414 -358
- package/dist/needle-engine.js.map +4 -4
- package/dist/needle-engine.min.js +99 -43
- package/dist/needle-engine.min.js.map +4 -4
- package/lib/engine/api.d.ts +3 -0
- package/lib/engine/api.js +3 -0
- package/lib/engine/api.js.map +1 -1
- package/lib/engine/debug/debug.d.ts +3 -0
- package/lib/engine/debug/debug.js +8 -0
- package/lib/engine/debug/debug.js.map +1 -0
- package/lib/engine/debug/debug_overlay.d.ts +7 -0
- package/lib/engine/debug/debug_overlay.js +213 -0
- package/lib/engine/debug/debug_overlay.js.map +1 -0
- package/lib/engine/engine.js +1 -1
- package/lib/engine/engine.js.map +1 -1
- package/lib/engine/engine_element_loading.js +1 -1
- package/lib/engine/engine_element_loading.js.map +1 -1
- package/lib/engine/engine_gameobject.d.ts +1 -0
- package/lib/engine/engine_gameobject.js +13 -1
- package/lib/engine/engine_gameobject.js.map +1 -1
- package/lib/engine/engine_gltf_builtin_components.js +4 -0
- package/lib/engine/engine_gltf_builtin_components.js.map +1 -1
- package/lib/engine/engine_mainloop_utils.d.ts +1 -1
- package/lib/engine/engine_mainloop_utils.js +7 -3
- package/lib/engine/engine_mainloop_utils.js.map +1 -1
- package/lib/engine/engine_physics.d.ts +29 -28
- package/lib/engine/engine_physics.js +85 -86
- package/lib/engine/engine_physics.js.map +1 -1
- package/lib/engine/engine_serialization_core.js +43 -0
- package/lib/engine/engine_serialization_core.js.map +1 -1
- package/lib/engine/engine_setup.js +1 -1
- package/lib/engine/engine_setup.js.map +1 -1
- package/lib/engine/engine_time.d.ts +1 -0
- package/lib/engine/engine_time.js +1 -0
- package/lib/engine/engine_time.js.map +1 -1
- package/lib/engine/engine_types.d.ts +6 -1
- package/lib/engine/engine_types.js.map +1 -1
- package/lib/engine/engine_typestore.d.ts +1 -0
- package/lib/engine/engine_typestore.js +1 -0
- package/lib/engine/engine_typestore.js.map +1 -1
- package/lib/engine/engine_utils.js +1 -1
- package/lib/engine/engine_utils.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_animator_controller_model.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_render_objects.d.ts +2 -2
- package/lib/engine/extensions/NEEDLE_render_objects.js +2 -2
- package/lib/engine/extensions/NEEDLE_render_objects.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_techniques_webgl.js +5 -0
- package/lib/engine/extensions/NEEDLE_techniques_webgl.js.map +1 -1
- package/lib/engine-components/Animation.d.ts +5 -1
- package/lib/engine-components/Animation.js +21 -0
- package/lib/engine-components/Animation.js.map +1 -1
- package/lib/engine-components/AnimatorController.d.ts +1 -0
- package/lib/engine-components/AnimatorController.js +14 -7
- package/lib/engine-components/AnimatorController.js.map +1 -1
- package/lib/engine-components/AudioSource.d.ts +1 -1
- package/lib/engine-components/AudioSource.js +2 -2
- package/lib/engine-components/AudioSource.js.map +1 -1
- package/lib/engine-components/BoxHelperComponent.d.ts +2 -2
- package/lib/engine-components/BoxHelperComponent.js +27 -9
- package/lib/engine-components/BoxHelperComponent.js.map +1 -1
- package/lib/engine-components/Component.d.ts +2 -1
- package/lib/engine-components/Component.js +11 -5
- package/lib/engine-components/Component.js.map +1 -1
- package/lib/engine-components/GroundProjection.d.ts +2 -0
- package/lib/engine-components/GroundProjection.js +18 -6
- package/lib/engine-components/GroundProjection.js.map +1 -1
- package/lib/engine-components/ReflectionProbe.d.ts +22 -0
- package/lib/engine-components/ReflectionProbe.js +134 -0
- package/lib/engine-components/ReflectionProbe.js.map +1 -0
- package/lib/engine-components/Renderer.d.ts +16 -4
- package/lib/engine-components/Renderer.js +96 -45
- package/lib/engine-components/Renderer.js.map +1 -1
- package/lib/engine-components/WebARSessionRoot.d.ts +7 -7
- package/lib/engine-components/WebARSessionRoot.js +7 -7
- package/lib/engine-components/WebARSessionRoot.js.map +1 -1
- package/lib/engine-components/WebXR.d.ts +9 -8
- package/lib/engine-components/WebXR.js +40 -24
- package/lib/engine-components/WebXR.js.map +1 -1
- package/lib/engine-components/WebXRAvatar.d.ts +4 -5
- package/lib/engine-components/WebXRAvatar.js +9 -8
- package/lib/engine-components/WebXRAvatar.js.map +1 -1
- package/lib/engine-components/WebXRController.d.ts +21 -21
- package/lib/engine-components/WebXRController.js +83 -63
- package/lib/engine-components/WebXRController.js.map +1 -1
- package/lib/engine-components/WebXRGrabRendering.d.ts +3 -3
- package/lib/engine-components/WebXRGrabRendering.js +2 -2
- package/lib/engine-components/WebXRGrabRendering.js.map +1 -1
- package/lib/engine-components/WebXRSync.d.ts +8 -8
- package/lib/engine-components/WebXRSync.js +15 -15
- package/lib/engine-components/WebXRSync.js.map +1 -1
- package/lib/engine-components/codegen/components.d.ts +1 -0
- package/lib/engine-components/codegen/components.js +1 -0
- package/lib/engine-components/codegen/components.js.map +1 -1
- package/lib/engine-components/js-extensions/ExtensionUtils.js +1 -1
- package/lib/engine-components/js-extensions/ExtensionUtils.js.map +1 -1
- package/lib/engine-components/ui/EventSystem.d.ts +1 -0
- package/lib/engine-components/ui/EventSystem.js +21 -1
- package/lib/engine-components/ui/EventSystem.js.map +1 -1
- package/package.json +1 -1
- package/src/engine/api.ts +3 -0
- package/src/engine/codegen/register_types.js +293 -0
- package/src/engine/debug/debug.ts +9 -0
- package/src/engine/debug/debug_overlay.ts +224 -0
- package/src/engine/engine.ts +1 -1
- package/src/engine/engine_element_loading.ts +1 -1
- package/src/engine/engine_gameobject.ts +17 -4
- package/src/engine/engine_gltf_builtin_components.ts +5 -1
- package/src/engine/engine_mainloop_utils.ts +7 -3
- package/src/engine/engine_physics.ts +130 -130
- package/src/engine/engine_serialization_core.ts +41 -0
- package/src/engine/engine_setup.ts +1 -1
- package/src/engine/engine_time.ts +2 -0
- package/src/engine/engine_types.ts +7 -1
- package/src/engine/engine_typestore.ts +2 -0
- package/src/engine/engine_utils.ts +3 -2
- package/src/engine/extensions/EXT_texture_exr.js +1 -1
- package/src/engine/extensions/NEEDLE_animator_controller_model.ts +2 -1
- package/src/engine/extensions/NEEDLE_render_objects.ts +4 -4
- package/src/engine/extensions/NEEDLE_techniques_webgl.ts +7 -0
- package/src/engine-components/Animation.ts +16 -1
- package/src/engine-components/AnimatorController.ts +19 -9
- package/src/engine-components/AudioSource.ts +3 -3
- package/src/engine-components/BoxHelperComponent.ts +29 -9
- package/src/engine-components/Component.ts +11 -5
- package/src/engine-components/GroundProjection.ts +22 -7
- package/src/engine-components/ReflectionProbe.ts +141 -0
- package/src/engine-components/Renderer.ts +116 -54
- package/src/engine-components/WebARSessionRoot.ts +16 -16
- package/src/engine-components/WebXR.ts +53 -48
- package/src/engine-components/WebXRAvatar.ts +16 -16
- package/src/engine-components/WebXRController.ts +133 -107
- package/src/engine-components/WebXRGrabRendering.ts +6 -6
- package/src/engine-components/WebXRSync.ts +20 -20
- package/src/engine-components/codegen/components.ts +1 -0
- package/src/engine-components/js-extensions/ExtensionUtils.ts +1 -1
- package/src/engine-components/ui/EventSystem.ts +26 -3
- package/lib/engine/debug/error_overlay.d.ts +0 -1
- package/lib/engine/debug/error_overlay.js +0 -114
- package/lib/engine/debug/error_overlay.js.map +0 -1
- package/src/engine/debug/error_overlay.ts +0 -126
|
@@ -5,11 +5,12 @@ import { RendererLightmap } from "./RendererLightmap";
|
|
|
5
5
|
import { Context } from "../engine/engine_setup";
|
|
6
6
|
import { getParam } from "../engine/engine_utils";
|
|
7
7
|
import { serializeable } from "../engine/engine_serialization_decorator";
|
|
8
|
-
import { Material, Mesh, Texture, Vector4 } from "three";
|
|
8
|
+
import { AxesHelper, Material, Mesh, Object3D, Texture, Vector4 } from "three";
|
|
9
9
|
import { NEEDLE_render_objects } from "../engine/extensions/NEEDLE_render_objects";
|
|
10
10
|
import { NEEDLE_deferred_texture } from "../engine/extensions/NEEDLE_deferred_texture";
|
|
11
11
|
import { NEED_UPDATE_INSTANCE_KEY } from "../engine/engine_instancing";
|
|
12
|
-
import { IRenderer } from "../engine/engine_types";
|
|
12
|
+
import { IRenderer, ISharedMaterials } from "../engine/engine_types";
|
|
13
|
+
import { debug, ReflectionProbe } from "./ReflectionProbe";
|
|
13
14
|
|
|
14
15
|
// for staying compatible with old code
|
|
15
16
|
export { InstancingUtil } from "../engine/engine_instancing";
|
|
@@ -20,6 +21,15 @@ const debugInstancing = getParam("debuginstancing");
|
|
|
20
21
|
const debugProgressiveLoading = getParam("debugprogressive");
|
|
21
22
|
const suppressProgressiveLoading = getParam("noprogressive");
|
|
22
23
|
|
|
24
|
+
|
|
25
|
+
export enum ReflectionProbeUsage {
|
|
26
|
+
Off = 0,
|
|
27
|
+
BlendProbes = 1,
|
|
28
|
+
BlendProbesAndSkybox = 2,
|
|
29
|
+
Simple = 3,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
23
33
|
export class FieldWithDefault {
|
|
24
34
|
public path: string | null = null;
|
|
25
35
|
public asset: object | null = null;
|
|
@@ -34,11 +44,14 @@ export enum RenderState {
|
|
|
34
44
|
|
|
35
45
|
|
|
36
46
|
// support sharedMaterials[index] assigning materials directly to the objects
|
|
37
|
-
class SharedMaterialArray {
|
|
47
|
+
class SharedMaterialArray implements ISharedMaterials {
|
|
48
|
+
|
|
49
|
+
[num: number]: THREE.Material;
|
|
38
50
|
|
|
39
51
|
private _renderer: Renderer;
|
|
40
52
|
private _targets: THREE.Object3D[] = [];
|
|
41
53
|
|
|
54
|
+
|
|
42
55
|
is(renderer: Renderer) {
|
|
43
56
|
return this._renderer === renderer;
|
|
44
57
|
}
|
|
@@ -88,7 +101,7 @@ class SharedMaterialArray {
|
|
|
88
101
|
private setMaterial(mat: Material, index: number) {
|
|
89
102
|
if (index < 0 || index >= this._targets.length) return;
|
|
90
103
|
const target = this._targets[index];
|
|
91
|
-
if (!target) return;
|
|
104
|
+
if (!target || target["material"] === undefined) return;
|
|
92
105
|
target["material"] = mat;
|
|
93
106
|
}
|
|
94
107
|
|
|
@@ -120,6 +133,11 @@ export class Renderer extends Behaviour implements IRenderer {
|
|
|
120
133
|
@serializeable()
|
|
121
134
|
allowOcclusionWhenDynamic: boolean = true;
|
|
122
135
|
|
|
136
|
+
@serializeable(Object3D)
|
|
137
|
+
probeAnchor?: Object3D;
|
|
138
|
+
@serializeable()
|
|
139
|
+
reflectionProbeUsage: ReflectionProbeUsage = ReflectionProbeUsage.Off;
|
|
140
|
+
|
|
123
141
|
// custom shader
|
|
124
142
|
// get materialProperties(): Array<MaterialProperties> | undefined {
|
|
125
143
|
// return this._materialProperties;
|
|
@@ -200,6 +218,10 @@ export class Renderer extends Behaviour implements IRenderer {
|
|
|
200
218
|
awake() {
|
|
201
219
|
this.clearInstancingState();
|
|
202
220
|
|
|
221
|
+
if(this.probeAnchor && debug) this.probeAnchor.add(new AxesHelper(.2));
|
|
222
|
+
|
|
223
|
+
this._reflectionProbe = null;
|
|
224
|
+
|
|
203
225
|
const type = this.gameObject.type;
|
|
204
226
|
if (type === "Group") {
|
|
205
227
|
for (const child of this.gameObject.children) {
|
|
@@ -344,6 +366,8 @@ export class Renderer extends Behaviour implements IRenderer {
|
|
|
344
366
|
this.gameObject.visible = true;
|
|
345
367
|
this.applyStencil();
|
|
346
368
|
}
|
|
369
|
+
|
|
370
|
+
this.updateReflectionProbe();
|
|
347
371
|
}
|
|
348
372
|
|
|
349
373
|
onDisable() {
|
|
@@ -368,60 +392,15 @@ export class Renderer extends Behaviour implements IRenderer {
|
|
|
368
392
|
NEEDLE_render_objects.applyStencil(this);
|
|
369
393
|
}
|
|
370
394
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
// progressive load before rendering so we only load textures for visible materials
|
|
374
|
-
if (!suppressProgressiveLoading && material._didRequestTextureLOD === undefined) {
|
|
375
|
-
material._didRequestTextureLOD = 0;
|
|
376
|
-
if (debugProgressiveLoading) {
|
|
377
|
-
console.log("Load material LOD (with delay)", material.name);
|
|
378
|
-
setTimeout(() => {
|
|
379
|
-
NEEDLE_deferred_texture.assignTextureLOD(this.context, this.sourceId, material);
|
|
380
|
-
}, 2000);
|
|
381
|
-
}
|
|
382
|
-
else {
|
|
383
|
-
NEEDLE_deferred_texture.assignTextureLOD(this.context, this.sourceId, material);
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
if (material.envMapIntensity !== undefined) {
|
|
388
|
-
const factor = this.hasLightmap ? Math.PI : 1;
|
|
389
|
-
material.envMapIntensity = Math.max(0, this.context.rendererData.environmentIntensity / factor);
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
// if (!camera) {
|
|
393
|
-
// let isXRCamera = false;
|
|
394
|
-
// if (this.context.isInXR) {
|
|
395
|
-
// // @ts-ignore
|
|
396
|
-
// const arr = this.context.renderer.xr.getCamera() as ArrayCamera;
|
|
397
|
-
// if (arr.cameras?.length > 0) {
|
|
398
|
-
// camera = arr;
|
|
399
|
-
// isXRCamera = true;
|
|
400
|
-
// }
|
|
401
|
-
// }
|
|
402
|
-
// }
|
|
403
|
-
|
|
404
|
-
// if (this.customShaderHandler) {
|
|
405
|
-
// this.customShaderHandler.onBeforeRender(renderer, scene, camera, geometry, material, group);
|
|
406
|
-
// }
|
|
407
|
-
// else if (this.rawShaderHandler) {
|
|
408
|
-
// for (const h of this.rawShaderHandler) {
|
|
409
|
-
// h.onBeforeRender(this.gameObject, camera);
|
|
410
|
-
// }
|
|
411
|
-
// }
|
|
412
|
-
|
|
413
|
-
if (this._lightmaps) {
|
|
414
|
-
for (const lm of this._lightmaps) {
|
|
415
|
-
lm.onBeforeRenderThree(material);
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
}
|
|
395
|
+
static envmap: THREE.Texture | null = null;
|
|
419
396
|
|
|
420
397
|
onBeforeRender() {
|
|
421
398
|
if (!this.gameObject) {
|
|
422
399
|
return;
|
|
423
400
|
}
|
|
424
401
|
|
|
402
|
+
Renderer.envmap = this.scene.environment;
|
|
403
|
+
|
|
425
404
|
const needsUpdate: boolean = this.gameObject[NEED_UPDATE_INSTANCE_KEY] === true || this.gameObject.matrixWorldNeedsUpdate;
|
|
426
405
|
|
|
427
406
|
if (this.gameObject.type === "Group" && this.gameObject.children?.length > 0) {
|
|
@@ -464,6 +443,73 @@ export class Renderer extends Behaviour implements IRenderer {
|
|
|
464
443
|
handle.object.layers.disableAll();
|
|
465
444
|
}
|
|
466
445
|
}
|
|
446
|
+
|
|
447
|
+
if (this.reflectionProbeUsage !== ReflectionProbeUsage.Off && this._reflectionProbe) {
|
|
448
|
+
this._reflectionProbe.onSet(this);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
onBeforeRenderThree(_renderer, _scene, _camera, _geometry, material, _group) {
|
|
454
|
+
|
|
455
|
+
// progressive load before rendering so we only load textures for visible materials
|
|
456
|
+
if (!suppressProgressiveLoading && material._didRequestTextureLOD === undefined) {
|
|
457
|
+
material._didRequestTextureLOD = 0;
|
|
458
|
+
if (debugProgressiveLoading) {
|
|
459
|
+
console.log("Load material LOD (with delay)", material.name);
|
|
460
|
+
setTimeout(() => {
|
|
461
|
+
NEEDLE_deferred_texture.assignTextureLOD(this.context, this.sourceId, material);
|
|
462
|
+
}, 2000);
|
|
463
|
+
}
|
|
464
|
+
else {
|
|
465
|
+
NEEDLE_deferred_texture.assignTextureLOD(this.context, this.sourceId, material);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
if (material.envMapIntensity !== undefined) {
|
|
470
|
+
const factor = this.hasLightmap ? Math.PI : 1;
|
|
471
|
+
material.envMapIntensity = Math.max(0, this.context.rendererData.environmentIntensity / factor);
|
|
472
|
+
}
|
|
473
|
+
// if (this._reflectionProbe?.texture) {
|
|
474
|
+
// material.envMap = this._reflectionProbe.texture;
|
|
475
|
+
// // this.context.renderer.prop
|
|
476
|
+
// // console.log(material.name);
|
|
477
|
+
// // this.context.renderer.properties.get(material);
|
|
478
|
+
// // this.context.renderer.properties.update(material, "environment", this._reflectionProbe.texture);
|
|
479
|
+
// }
|
|
480
|
+
|
|
481
|
+
// _scene.environment = null;
|
|
482
|
+
// else _scene.environment = Renderer.envmap;
|
|
483
|
+
// if (!material.envmap)
|
|
484
|
+
// material.envMap = Renderer.envmap;
|
|
485
|
+
// material.needsUpdate = true;
|
|
486
|
+
|
|
487
|
+
// if (!camera) {
|
|
488
|
+
// let isXRCamera = false;
|
|
489
|
+
// if (this.context.isInXR) {
|
|
490
|
+
// // @ts-ignore
|
|
491
|
+
// const arr = this.context.renderer.xr.getCamera() as ArrayCamera;
|
|
492
|
+
// if (arr.cameras?.length > 0) {
|
|
493
|
+
// camera = arr;
|
|
494
|
+
// isXRCamera = true;
|
|
495
|
+
// }
|
|
496
|
+
// }
|
|
497
|
+
// }
|
|
498
|
+
|
|
499
|
+
// if (this.customShaderHandler) {
|
|
500
|
+
// this.customShaderHandler.onBeforeRender(renderer, scene, camera, geometry, material, group);
|
|
501
|
+
// }
|
|
502
|
+
// else if (this.rawShaderHandler) {
|
|
503
|
+
// for (const h of this.rawShaderHandler) {
|
|
504
|
+
// h.onBeforeRender(this.gameObject, camera);
|
|
505
|
+
// }
|
|
506
|
+
// }
|
|
507
|
+
|
|
508
|
+
if (this._lightmaps) {
|
|
509
|
+
for (const lm of this._lightmaps) {
|
|
510
|
+
lm.onBeforeRenderThree(material);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
467
513
|
}
|
|
468
514
|
|
|
469
515
|
onAfterRender() {
|
|
@@ -473,6 +519,10 @@ export class Renderer extends Behaviour implements IRenderer {
|
|
|
473
519
|
handle.object.layers.mask = this.prevLayers[i];
|
|
474
520
|
}
|
|
475
521
|
}
|
|
522
|
+
|
|
523
|
+
if (this.reflectionProbeUsage !== ReflectionProbeUsage.Off && this._reflectionProbe) {
|
|
524
|
+
this._reflectionProbe.onUnset(this)
|
|
525
|
+
}
|
|
476
526
|
}
|
|
477
527
|
|
|
478
528
|
private applySettings(go: THREE.Object3D) {
|
|
@@ -483,6 +533,18 @@ export class Renderer extends Behaviour implements IRenderer {
|
|
|
483
533
|
else go.castShadow = false;
|
|
484
534
|
}
|
|
485
535
|
|
|
536
|
+
private _reflectionProbe: ReflectionProbe | null = null;
|
|
537
|
+
private updateReflectionProbe() {
|
|
538
|
+
// handle reflection probe
|
|
539
|
+
this._reflectionProbe = null;
|
|
540
|
+
if (this.reflectionProbeUsage !== ReflectionProbeUsage.Off) {
|
|
541
|
+
// if(this.gameObject.name.includes("Tank_Case_Jewlery") === false) return;
|
|
542
|
+
const obj = this.probeAnchor || this.gameObject;
|
|
543
|
+
const isAnchor = this.probeAnchor ? true : false;
|
|
544
|
+
this._reflectionProbe = ReflectionProbe.get(obj, this.context, isAnchor);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
486
548
|
}
|
|
487
549
|
|
|
488
550
|
export class MeshRenderer extends Renderer {
|
|
@@ -637,7 +699,7 @@ class InstancedMeshRenderer {
|
|
|
637
699
|
this.material = material;
|
|
638
700
|
this.context = context;
|
|
639
701
|
this.maxCount = count;
|
|
640
|
-
if(debugInstancing){
|
|
702
|
+
if (debugInstancing) {
|
|
641
703
|
material = new THREE.MeshBasicMaterial({ color: this.randomColor() });
|
|
642
704
|
}
|
|
643
705
|
this.inst = new THREE.InstancedMesh(geo, material, count);
|
|
@@ -655,7 +717,7 @@ class InstancedMeshRenderer {
|
|
|
655
717
|
// }, 500);
|
|
656
718
|
}
|
|
657
719
|
|
|
658
|
-
private randomColor(){
|
|
720
|
+
private randomColor() {
|
|
659
721
|
return new THREE.Color(Math.random(), Math.random(), Math.random());
|
|
660
722
|
}
|
|
661
723
|
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { Behaviour, GameObject } from "./Component";
|
|
2
|
-
import
|
|
2
|
+
import { XRSession } from 'three'
|
|
3
3
|
import { Matrix4, Object3D, XRPose } from "three";
|
|
4
4
|
import { WebAR, WebXR } from "./WebXR";
|
|
5
5
|
import { InstancingUtil } from "../engine/engine_instancing";
|
|
6
6
|
import { serializeable } from "../engine/engine_serialization_decorator";
|
|
7
7
|
|
|
8
|
-
// https://github.com/takahirox/takahirox.github.io/blob/master/
|
|
8
|
+
// https://github.com/takahirox/takahirox.github.io/blob/master/js.mmdeditor/examples/js/controls/DeviceOrientationControls.js
|
|
9
9
|
|
|
10
10
|
export class WebARSessionRoot extends Behaviour {
|
|
11
11
|
|
|
12
12
|
webAR: WebAR | null = null;
|
|
13
13
|
|
|
14
|
-
get rig():
|
|
14
|
+
get rig(): Object3D | undefined {
|
|
15
15
|
return this.webAR?.webxr.Rig;
|
|
16
16
|
}
|
|
17
17
|
|
|
@@ -28,7 +28,7 @@ export class WebARSessionRoot extends Behaviour {
|
|
|
28
28
|
this.setScale(val);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
private readonly _initalMatrix = new
|
|
31
|
+
private readonly _initalMatrix = new Matrix4();
|
|
32
32
|
private readonly _selectStartFn = this.onSelectStart.bind(this);
|
|
33
33
|
private readonly _selectEndFn = this.onSelectEnd.bind(this);
|
|
34
34
|
|
|
@@ -41,13 +41,13 @@ export class WebARSessionRoot extends Behaviour {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
private _arScale: number = 5;
|
|
44
|
-
private _rig:
|
|
45
|
-
private _startPose:
|
|
46
|
-
private _placementPose:
|
|
44
|
+
private _rig: Object3D | null = null;
|
|
45
|
+
private _startPose: Matrix4 | null = null;
|
|
46
|
+
private _placementPose: Matrix4 | null = null;
|
|
47
47
|
private _isTouching: boolean = false;
|
|
48
|
-
private _rigStartPose:
|
|
48
|
+
private _rigStartPose: Matrix4 | undefined | null = null;
|
|
49
49
|
|
|
50
|
-
onBegin(session:
|
|
50
|
+
onBegin(session: XRSession) {
|
|
51
51
|
this._placementPose = null;
|
|
52
52
|
this.gameObject.visible = false;
|
|
53
53
|
this.gameObject.matrixAutoUpdate = false;
|
|
@@ -69,12 +69,12 @@ export class WebARSessionRoot extends Behaviour {
|
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
onUpdate(rig:
|
|
72
|
+
onUpdate(rig: Object3D | null, _session: XRSession, pose: XRPose | null | undefined): boolean {
|
|
73
73
|
|
|
74
74
|
if (pose && !this._placementPose) {
|
|
75
75
|
if (this._isTouching) {
|
|
76
76
|
if (this.webAR) this.webAR.setReticleActive(false);
|
|
77
|
-
this.placeAt(rig, new
|
|
77
|
+
this.placeAt(rig, new Matrix4().fromArray(pose.transform.matrix).invert());
|
|
78
78
|
return true;
|
|
79
79
|
}
|
|
80
80
|
}
|
|
@@ -90,13 +90,13 @@ export class WebARSessionRoot extends Behaviour {
|
|
|
90
90
|
// }
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
placeAt(rig:
|
|
94
|
-
if (!this._placementPose) this._placementPose = new
|
|
93
|
+
placeAt(rig: Object3D | null, mat: Matrix4) {
|
|
94
|
+
if (!this._placementPose) this._placementPose = new Matrix4();
|
|
95
95
|
this._placementPose.copy(mat);
|
|
96
96
|
if (rig) {
|
|
97
97
|
|
|
98
98
|
if (this.invertForward) {
|
|
99
|
-
const rot = new
|
|
99
|
+
const rot = new Matrix4().makeRotationY(Math.PI);
|
|
100
100
|
this._placementPose.premultiply(rot);
|
|
101
101
|
}
|
|
102
102
|
this._rig = rig;
|
|
@@ -111,7 +111,7 @@ export class WebARSessionRoot extends Behaviour {
|
|
|
111
111
|
this.gameObject.visible = true;
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
onEnd(rig:
|
|
114
|
+
onEnd(rig: Object3D | null, _session: XRSession) {
|
|
115
115
|
this._placementPose = null;
|
|
116
116
|
this.gameObject.visible = false;
|
|
117
117
|
this.gameObject.matrixAutoUpdate = false;
|
|
@@ -151,7 +151,7 @@ export class WebARSessionRoot extends Behaviour {
|
|
|
151
151
|
this._rigStartPose = rig.matrix.clone();
|
|
152
152
|
}
|
|
153
153
|
rig.matrixAutoUpdate = false;
|
|
154
|
-
rig.matrix.multiplyMatrices(new
|
|
154
|
+
rig.matrix.multiplyMatrices(new Matrix4().makeScale(scale, scale, scale), this._placementPose);
|
|
155
155
|
rig.matrix.decompose(rig.position, rig.quaternion, rig.scale);
|
|
156
156
|
rig.updateMatrixWorld();
|
|
157
157
|
console.log("Place", rig.position);
|
|
@@ -1,23 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { ArrayCamera, Color, Euler, EventDispatcher, Group, Matrix4, Mesh, MeshBasicMaterial, Object3D, Quaternion, RingGeometry, Texture, Vector3, XRFrame, XRHitTestSource, XRRigidTransform, XRSession, XRViewerPose } from 'three';
|
|
3
2
|
import { ARButton } from '../include/three/ARButton.js';
|
|
4
3
|
import { VRButton } from '../include/three/VRButton.js';
|
|
5
4
|
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
5
|
+
import { AssetReference } from "../engine/engine_addressables";
|
|
6
|
+
import { serializeable } from "../engine/engine_serialization_decorator";
|
|
7
|
+
import { XRSessionMode } from "../engine/engine_setup";
|
|
8
|
+
import { getWorldPosition, getWorldQuaternion, setWorldPosition, setWorldQuaternion } from "../engine/engine_three_utils";
|
|
9
|
+
import { INeedleEngineComponent } from "../engine/engine_types";
|
|
10
|
+
import { getParam, setOrAddParamsToUrl } from "../engine/engine_utils";
|
|
8
11
|
|
|
9
|
-
import
|
|
12
|
+
import { Behaviour, GameObject } from "./Component";
|
|
10
13
|
import { noVoip } from "./Voip";
|
|
11
|
-
import { XRFlag, XRState, XRStateFlag } from "./XRFlag";
|
|
12
|
-
import { ControllerType, WebXRController } from "./WebXRController";
|
|
13
14
|
import { WebARSessionRoot } from "./WebARSessionRoot";
|
|
14
|
-
import {
|
|
15
|
+
import { ControllerType, WebXRController } from "./WebXRController";
|
|
15
16
|
import { XRRig } from "./WebXRRig";
|
|
16
|
-
import { AssetReference } from "../engine/engine_addressables";
|
|
17
|
-
import { serializeable } from "../engine/engine_serialization_decorator";
|
|
18
17
|
import { WebXRSync } from "./WebXRSync";
|
|
19
|
-
import {
|
|
20
|
-
import { INeedleEngineComponent } from "../engine/engine_types";
|
|
18
|
+
import { XRFlag, XRState, XRStateFlag } from "./XRFlag";
|
|
21
19
|
|
|
22
20
|
|
|
23
21
|
export async function detectARSupport() {
|
|
@@ -38,7 +36,6 @@ let vrSupported = false;
|
|
|
38
36
|
detectARSupport().then(res => arSupported = res);
|
|
39
37
|
detectVRSupport().then(res => vrSupported = res);
|
|
40
38
|
|
|
41
|
-
|
|
42
39
|
// import TeleportVR from "teleportvr";
|
|
43
40
|
|
|
44
41
|
export enum WebXREvent {
|
|
@@ -54,16 +51,23 @@ export declare type CreateButtonOptions = {
|
|
|
54
51
|
|
|
55
52
|
export class WebXR extends Behaviour {
|
|
56
53
|
|
|
54
|
+
@serializeable()
|
|
57
55
|
enableVR = true;
|
|
56
|
+
@serializeable()
|
|
58
57
|
enableAR = true;
|
|
58
|
+
|
|
59
59
|
@serializeable(AssetReference)
|
|
60
60
|
defaultAvatar?: AssetReference;
|
|
61
|
+
@serializeable()
|
|
62
|
+
handModelPath: string = "";
|
|
61
63
|
|
|
64
|
+
@serializeable()
|
|
62
65
|
createVRButton: boolean = true;
|
|
66
|
+
@serializeable()
|
|
63
67
|
createARButton: boolean = true;
|
|
64
68
|
|
|
65
69
|
private static _isInXr: boolean = false;
|
|
66
|
-
private static events:
|
|
70
|
+
private static events: EventDispatcher = new EventDispatcher();
|
|
67
71
|
|
|
68
72
|
public static get IsInWebXR(): boolean { return this._isInXr; }
|
|
69
73
|
public static get XRSupported(): boolean { return 'xr' in navigator && (arSupported || vrSupported); }
|
|
@@ -121,7 +125,7 @@ export class WebXR extends Behaviour {
|
|
|
121
125
|
if (session) session.end();
|
|
122
126
|
}
|
|
123
127
|
|
|
124
|
-
public get Rig():
|
|
128
|
+
public get Rig(): Object3D {
|
|
125
129
|
if(!this.rig) this.ensureRig();
|
|
126
130
|
return this.rig;
|
|
127
131
|
}
|
|
@@ -154,7 +158,7 @@ export class WebXR extends Behaviour {
|
|
|
154
158
|
public get IsInVR() { return this._isInVR; }
|
|
155
159
|
public get IsInAR() { return this._isInAR; }
|
|
156
160
|
|
|
157
|
-
private rig!:
|
|
161
|
+
private rig!: Object3D;
|
|
158
162
|
private isInit: boolean = false;
|
|
159
163
|
|
|
160
164
|
private _requestedAR: boolean = false;
|
|
@@ -221,11 +225,11 @@ export class WebXR extends Behaviour {
|
|
|
221
225
|
}, 1000);
|
|
222
226
|
}
|
|
223
227
|
|
|
224
|
-
private _transformOrientation:
|
|
225
|
-
public get TransformOrientation():
|
|
228
|
+
private _transformOrientation: Quaternion = new Quaternion();
|
|
229
|
+
public get TransformOrientation(): Quaternion { return this._transformOrientation; }
|
|
226
230
|
|
|
227
|
-
private _currentHeadPose:
|
|
228
|
-
public get HeadPose():
|
|
231
|
+
private _currentHeadPose: XRViewerPose | null = null;
|
|
232
|
+
public get HeadPose(): XRViewerPose | null { return this._currentHeadPose; }
|
|
229
233
|
|
|
230
234
|
onBeforeRender(frame) {
|
|
231
235
|
if (!frame) return;
|
|
@@ -237,7 +241,7 @@ export class WebXR extends Behaviour {
|
|
|
237
241
|
const pose = frame.getViewerPose(this.context.renderer.xr.getReferenceSpace());
|
|
238
242
|
this._currentHeadPose = pose;
|
|
239
243
|
if (!pose) return; // e.g. if user is not wearing headset
|
|
240
|
-
const transform:
|
|
244
|
+
const transform: XRRigidTransform = pose?.transform;
|
|
241
245
|
|
|
242
246
|
if (transform) {
|
|
243
247
|
this._transformOrientation.set(transform.orientation.x, transform.orientation.y, transform.orientation.z, transform.orientation.w);
|
|
@@ -312,7 +316,7 @@ export class WebXR extends Behaviour {
|
|
|
312
316
|
// this.rig.quaternion.premultiply(existing.worldQuaternion);
|
|
313
317
|
}
|
|
314
318
|
else {
|
|
315
|
-
this.rig = new
|
|
319
|
+
this.rig = new Group();
|
|
316
320
|
this.rig.rotateY(Math.PI);
|
|
317
321
|
this.rig.name = "XRRig";
|
|
318
322
|
this.context.scene.add(this.rig);
|
|
@@ -321,11 +325,11 @@ export class WebXR extends Behaviour {
|
|
|
321
325
|
}
|
|
322
326
|
|
|
323
327
|
|
|
324
|
-
private _originalCameraParent:
|
|
325
|
-
private _originalCameraPosition:
|
|
326
|
-
private _originalCameraRotation:
|
|
328
|
+
private _originalCameraParent: Object3D | null = null;
|
|
329
|
+
private _originalCameraPosition: Vector3 = new Vector3();
|
|
330
|
+
private _originalCameraRotation: Quaternion = new Quaternion();
|
|
327
331
|
|
|
328
|
-
private onEnterXR(session:
|
|
332
|
+
private onEnterXR(session: XRSession, frame: XRFrame) {
|
|
329
333
|
console.log("[XR] session begin", session);
|
|
330
334
|
WebXR._isInXr = true;
|
|
331
335
|
|
|
@@ -336,8 +340,8 @@ export class WebXR extends Behaviour {
|
|
|
336
340
|
const pose = frame.getViewerPose(space);
|
|
337
341
|
const rot = pose?.transform.orientation;
|
|
338
342
|
if (rot) {
|
|
339
|
-
const quat = new
|
|
340
|
-
const eu = new
|
|
343
|
+
const quat = new Quaternion(rot.x, rot.y, rot.z, rot.w);
|
|
344
|
+
const eu = new Euler().setFromQuaternion(quat);
|
|
341
345
|
this.rig.rotateY(eu.y);
|
|
342
346
|
// this.rig.quaternion.multiply(quat);
|
|
343
347
|
}
|
|
@@ -383,7 +387,7 @@ export class WebXR extends Behaviour {
|
|
|
383
387
|
WebXR.events.dispatchEvent({ type: WebXREvent.XRStarted, session: session });
|
|
384
388
|
}
|
|
385
389
|
|
|
386
|
-
private onExitXR(session:
|
|
390
|
+
private onExitXR(session: XRSession | null) {
|
|
387
391
|
|
|
388
392
|
if (this._isInAR && session) {
|
|
389
393
|
this.webAR?.onEnd(session);
|
|
@@ -413,7 +417,7 @@ export class WebXR extends Behaviour {
|
|
|
413
417
|
WebXR.events.dispatchEvent({ type: WebXREvent.XRStopped, session: session });
|
|
414
418
|
}
|
|
415
419
|
|
|
416
|
-
private onEnterVR(_session:
|
|
420
|
+
private onEnterVR(_session: XRSession) {
|
|
417
421
|
}
|
|
418
422
|
|
|
419
423
|
private destroyControllers() {
|
|
@@ -425,13 +429,13 @@ export class WebXR extends Behaviour {
|
|
|
425
429
|
|
|
426
430
|
private xrMirrorWindow: Window | null = null;
|
|
427
431
|
|
|
428
|
-
private onEnterXR_HandleMirrorWindow(session:
|
|
429
|
-
if (!
|
|
432
|
+
private onEnterXR_HandleMirrorWindow(session: XRSession) {
|
|
433
|
+
if (!getParam("mirror")) return;
|
|
430
434
|
setTimeout(() => {
|
|
431
435
|
if (!WebXR.IsInWebXR) return;
|
|
432
436
|
const url = new URL(window.location.href);
|
|
433
|
-
|
|
434
|
-
|
|
437
|
+
setOrAddParamsToUrl(url.searchParams, noVoip, 1);
|
|
438
|
+
setOrAddParamsToUrl(url.searchParams, "isMirror", 1);
|
|
435
439
|
const str = url.toString();
|
|
436
440
|
this.xrMirrorWindow = window.open(str, "webxr sync", "popup=yes");
|
|
437
441
|
if (this.xrMirrorWindow) {
|
|
@@ -456,20 +460,20 @@ export class WebAR {
|
|
|
456
460
|
|
|
457
461
|
private _webxr: WebXR;
|
|
458
462
|
|
|
459
|
-
private reticle:
|
|
463
|
+
private reticle: Object3D | null = null;
|
|
460
464
|
private hitTestSource: XRHitTestSource | null = null;
|
|
461
465
|
private reticleActive: boolean = true;
|
|
462
466
|
|
|
463
467
|
// scene.background before entering AR
|
|
464
|
-
private previousBackground:
|
|
465
|
-
private previousEnvironment:
|
|
468
|
+
private previousBackground: Color | null | Texture = null;
|
|
469
|
+
private previousEnvironment: Texture | null = null;
|
|
466
470
|
|
|
467
471
|
private sessionRoot: WebARSessionRoot | null = null;
|
|
468
|
-
private _previousParent:
|
|
472
|
+
private _previousParent: Object3D | null = null;
|
|
469
473
|
// we need this in case the session root is on the same object as the webxr component
|
|
470
474
|
// so if we disable the session root we attach the webxr component to this temporary object
|
|
471
475
|
// to still receive updates
|
|
472
|
-
private static tempWebXRObject:
|
|
476
|
+
private static tempWebXRObject: Object3D;
|
|
473
477
|
|
|
474
478
|
private get context() { return this.webxr.context; }
|
|
475
479
|
|
|
@@ -496,13 +500,14 @@ export class WebAR {
|
|
|
496
500
|
this.reticleActive = active;
|
|
497
501
|
}
|
|
498
502
|
|
|
499
|
-
async onBegin(session:
|
|
503
|
+
async onBegin(session: XRSession) {
|
|
500
504
|
const context = this.webxr.context;
|
|
501
505
|
this.reticleActive = true;
|
|
502
506
|
this.didPlaceARSessionRoot = false;
|
|
503
507
|
|
|
504
508
|
const deviceType = navigator.userAgent?.includes("OculusBrowser") ? ControllerType.PhysicalDevice : ControllerType.Touch;
|
|
505
|
-
|
|
509
|
+
const controllerCount = deviceType === ControllerType.Touch ? 4 : 2;
|
|
510
|
+
for (let i = 0; i < controllerCount; i++) {
|
|
506
511
|
WebXRController.Create(this.webxr, i, this.webxr.gameObject as GameObject, deviceType)
|
|
507
512
|
}
|
|
508
513
|
|
|
@@ -523,9 +528,9 @@ export class WebAR {
|
|
|
523
528
|
});
|
|
524
529
|
|
|
525
530
|
if (!this.reticle && this.sessionRoot) {
|
|
526
|
-
this.reticle = new
|
|
527
|
-
new
|
|
528
|
-
new
|
|
531
|
+
this.reticle = new Mesh(
|
|
532
|
+
new RingGeometry(0.07, 0.09, 32).rotateX(- Math.PI / 2),
|
|
533
|
+
new MeshBasicMaterial()
|
|
529
534
|
);
|
|
530
535
|
this.reticle.name = "AR Placement reticle";
|
|
531
536
|
this.reticle.matrixAutoUpdate = false;
|
|
@@ -538,7 +543,7 @@ export class WebAR {
|
|
|
538
543
|
}
|
|
539
544
|
|
|
540
545
|
this._previousParent = this.webxr.gameObject;
|
|
541
|
-
if (!WebAR.tempWebXRObject) WebAR.tempWebXRObject = new
|
|
546
|
+
if (!WebAR.tempWebXRObject) WebAR.tempWebXRObject = new Object3D();
|
|
542
547
|
this.context.scene.add(WebAR.tempWebXRObject);
|
|
543
548
|
GameObject.addComponent(WebAR.tempWebXRObject as GameObject, this.webxr);
|
|
544
549
|
|
|
@@ -556,7 +561,7 @@ export class WebAR {
|
|
|
556
561
|
this.context.mainCameraComponent?.applyClearFlagsIfIsActiveCamera();
|
|
557
562
|
}
|
|
558
563
|
|
|
559
|
-
onEnd(session:
|
|
564
|
+
onEnd(session: XRSession) {
|
|
560
565
|
if (this._previousParent) {
|
|
561
566
|
console.log("ADD", this._previousParent);
|
|
562
567
|
GameObject.addComponent(this._previousParent as GameObject, this.webxr);
|
|
@@ -578,7 +583,7 @@ export class WebAR {
|
|
|
578
583
|
this.context.mainCameraComponent?.applyClearFlagsIfIsActiveCamera();
|
|
579
584
|
}
|
|
580
585
|
|
|
581
|
-
onUpdate(session:
|
|
586
|
+
onUpdate(session: XRSession, frame: XRFrame) {
|
|
582
587
|
|
|
583
588
|
if (this.noHitTestAvailable === true) {
|
|
584
589
|
if (this.reticle)
|
|
@@ -631,4 +636,4 @@ export class WebAR {
|
|
|
631
636
|
}
|
|
632
637
|
}
|
|
633
638
|
|
|
634
|
-
const arPlacementWithoutHitTestMatrix = new
|
|
639
|
+
const arPlacementWithoutHitTestMatrix = new Matrix4().identity().makeTranslation(0, -0.5, 0);
|