@needle-tools/engine 4.11.4 → 4.11.5-next.53316bf
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 +8 -0
- package/components.needle.json +1 -1
- package/dist/generateMeshBVH.worker-mO20N_b8.js +21 -0
- package/dist/{gltf-progressive-GwdQV1Qx.umd.cjs → gltf-progressive-DWcmTMCh.umd.cjs} +1 -1
- package/dist/{gltf-progressive-CftVUJy3.min.js → gltf-progressive-DZrY8VT6.min.js} +2 -2
- package/dist/{gltf-progressive-BvlZQAkt.js → gltf-progressive-DgYz5BYa.js} +19 -19
- package/dist/loader.worker-Dip-PthR.js +23 -0
- package/dist/{needle-engine.bundle-CQdk7IvU.min.js → needle-engine.bundle-BR5nmLCs.min.js} +155 -160
- package/dist/{needle-engine.bundle-BxK1-fWD.umd.cjs → needle-engine.bundle-Cb9jKt1y.umd.cjs} +154 -159
- package/dist/{needle-engine.bundle-DmMrUPFQ.js → needle-engine.bundle-D6G3NMe4.js} +5964 -5815
- package/dist/needle-engine.d.ts +17848 -1
- package/dist/needle-engine.js +336 -335
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- package/dist/{postprocessing-CJC0Npcd.js → postprocessing-BTW9pD_s.js} +1822 -1723
- package/dist/{postprocessing-DrM4PWU3.umd.cjs → postprocessing-CMgoN5t5.umd.cjs} +229 -158
- package/dist/{postprocessing-l7zsdO_Q.min.js → postprocessing-DYDtB188.min.js} +227 -156
- package/dist/rapier-B3oL1ap-.js +5217 -0
- package/dist/rapier-DJ-luMxr.min.js +1 -0
- package/dist/rapier-DQltNJbN.umd.cjs +1 -0
- package/dist/{three-BDW9I486.min.js → three-B7CT31Bt.min.js} +1 -5
- package/dist/{three-MHVqtJYj.js → three-DfMvBzXi.js} +0 -5
- package/dist/{three-examples-CgwGHSgz.umd.cjs → three-examples-CsW4_6LI.umd.cjs} +2 -7
- package/dist/{three-examples-fvEPSC8L.min.js → three-examples-D1P7eEhn.min.js} +2 -7
- package/dist/{three-examples-C5Ht-QFN.js → three-examples-D1SK93ek.js} +1 -7
- package/dist/{three-mesh-ui-BjWTTk1R.js → three-mesh-ui-C_uSB5dD.js} +1 -1
- package/dist/{three-mesh-ui-Bm32sS2a.umd.cjs → three-mesh-ui-DpATDXwU.umd.cjs} +1 -1
- package/dist/{three-mesh-ui-CLdkp21K.min.js → three-mesh-ui-LQ44s0AL.min.js} +1 -1
- package/dist/{three-iFaDq9U3.umd.cjs → three-qj71I7J3.umd.cjs} +2 -6
- package/dist/{vendor-CsyK1CFs.min.js → vendor-BKGa4GE0.min.js} +34 -39
- package/dist/{vendor-petGQl0N.js → vendor-D0zoswDa.js} +1626 -1605
- package/dist/{vendor-6kAXU6fm.umd.cjs → vendor-UCpFAwt1.umd.cjs} +30 -35
- 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/debug/debug_spector.d.ts +16 -0
- package/lib/engine/debug/debug_spector.js +28 -0
- package/lib/engine/debug/debug_spector.js.map +1 -0
- package/lib/engine/engine_addressables.d.ts +74 -11
- package/lib/engine/engine_addressables.js +74 -11
- package/lib/engine/engine_addressables.js.map +1 -1
- package/lib/engine/engine_application.d.ts +7 -0
- package/lib/engine/engine_application.js +8 -1
- package/lib/engine/engine_application.js.map +1 -1
- package/lib/engine/engine_camera.fit.d.ts +48 -3
- package/lib/engine/engine_camera.fit.js +29 -0
- package/lib/engine/engine_camera.fit.js.map +1 -1
- package/lib/engine/engine_context.d.ts +33 -8
- package/lib/engine/engine_context.js +47 -8
- package/lib/engine/engine_context.js.map +1 -1
- package/lib/engine/engine_loaders.d.ts +0 -6
- package/lib/engine/engine_loaders.js +5 -5
- package/lib/engine/engine_loaders.js.map +1 -1
- package/lib/engine/engine_physics.js +6 -2
- package/lib/engine/engine_physics.js.map +1 -1
- package/lib/engine/engine_physics_rapier.d.ts +11 -2
- package/lib/engine/engine_physics_rapier.js +9 -0
- package/lib/engine/engine_physics_rapier.js.map +1 -1
- package/lib/engine/engine_scenelighting.d.ts +12 -1
- package/lib/engine/engine_scenelighting.js +21 -1
- package/lib/engine/engine_scenelighting.js.map +1 -1
- package/lib/engine/engine_texture.d.ts +1 -1
- package/lib/engine/engine_tonemapping.d.ts +1 -1
- package/lib/engine/engine_types.d.ts +16 -0
- package/lib/engine/engine_typestore.d.ts +1 -0
- package/lib/engine/engine_typestore.js +5 -6
- package/lib/engine/engine_typestore.js.map +1 -1
- package/lib/engine/engine_utils_qrcode.js +1 -1
- package/lib/engine/engine_utils_qrcode.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_components.d.ts +4 -4
- package/lib/engine/extensions/NEEDLE_components.js +36 -17
- package/lib/engine/extensions/NEEDLE_components.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_lightmaps.js +2 -2
- package/lib/engine/extensions/NEEDLE_lightmaps.js.map +1 -1
- package/lib/engine/extensions/extensions.d.ts +2 -2
- package/lib/engine/extensions/extensions.js +11 -5
- package/lib/engine/extensions/extensions.js.map +1 -1
- package/lib/engine/webcomponents/buttons.d.ts +3 -1
- package/lib/engine/webcomponents/buttons.js +3 -1
- package/lib/engine/webcomponents/buttons.js.map +1 -1
- package/lib/engine/webcomponents/needle menu/needle-menu.d.ts +39 -2
- package/lib/engine/webcomponents/needle menu/needle-menu.js +39 -2
- package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
- package/lib/engine/webcomponents/needle-engine.attributes.d.ts +1 -0
- package/lib/engine/webcomponents/needle-engine.d.ts +1 -0
- package/lib/engine/webcomponents/needle-engine.js +3 -0
- package/lib/engine/webcomponents/needle-engine.js.map +1 -1
- package/lib/engine/xr/NeedleXRSession.js +2 -1
- package/lib/engine/xr/NeedleXRSession.js.map +1 -1
- package/lib/engine-components/Component.d.ts +5 -0
- package/lib/engine-components/Component.js +7 -0
- package/lib/engine-components/Component.js.map +1 -1
- package/lib/engine-components/ReflectionProbe.js +16 -10
- package/lib/engine-components/ReflectionProbe.js.map +1 -1
- package/lib/engine-components/Renderer.js +16 -42
- package/lib/engine-components/Renderer.js.map +1 -1
- package/lib/engine-components/RendererInstancing.d.ts +5 -3
- package/lib/engine-components/RendererInstancing.js +64 -31
- package/lib/engine-components/RendererInstancing.js.map +1 -1
- package/lib/engine-components/RendererLightmap.d.ts +1 -0
- package/lib/engine-components/RendererLightmap.js +24 -18
- package/lib/engine-components/RendererLightmap.js.map +1 -1
- package/lib/engine-components/Skybox.d.ts +15 -5
- package/lib/engine-components/Skybox.js +37 -25
- package/lib/engine-components/Skybox.js.map +1 -1
- package/lib/engine-components/export/usdz/USDZExporter.d.ts +24 -3
- package/lib/engine-components/export/usdz/USDZExporter.js +36 -2
- package/lib/engine-components/export/usdz/USDZExporter.js.map +1 -1
- package/lib/engine-components/timeline/PlayableDirector.d.ts +2 -1
- package/lib/engine-components/timeline/PlayableDirector.js +16 -9
- package/lib/engine-components/timeline/PlayableDirector.js.map +1 -1
- package/lib/engine-components/web/CursorFollow.d.ts +1 -0
- package/lib/engine-components/web/CursorFollow.js +2 -0
- package/lib/engine-components/web/CursorFollow.js.map +1 -1
- package/lib/engine-components/webxr/WebXR.js +4 -0
- package/lib/engine-components/webxr/WebXR.js.map +1 -1
- package/lib/engine-components/webxr/controllers/XRControllerModel.js +1 -1
- package/lib/engine-components/webxr/controllers/XRControllerModel.js.map +1 -1
- package/lib/needle-engine.js +2 -1
- package/lib/needle-engine.js.map +1 -1
- package/package.json +15 -12
- package/plugins/types/needleConfig.d.ts +1 -1
- package/plugins/types/next.d.ts +1 -1
- package/plugins/types/userconfig.d.ts +1 -1
- package/src/engine/api.ts +1 -1
- package/src/engine/debug/debug_spector.ts +43 -0
- package/src/engine/engine_addressables.ts +75 -11
- package/src/engine/engine_application.ts +16 -1
- package/src/engine/engine_camera.fit.ts +49 -4
- package/src/engine/engine_context.ts +59 -10
- package/src/engine/engine_loaders.ts +6 -6
- package/src/engine/engine_physics.ts +6 -2
- package/src/engine/engine_physics_rapier.ts +11 -2
- package/src/engine/engine_scenelighting.ts +30 -8
- package/src/engine/engine_texture.ts +1 -1
- package/src/engine/engine_tonemapping.ts +1 -1
- package/src/engine/engine_types.ts +17 -0
- package/src/engine/engine_typestore.ts +5 -6
- package/src/engine/engine_utils_qrcode.ts +1 -1
- package/src/engine/extensions/NEEDLE_components.ts +47 -26
- package/src/engine/extensions/NEEDLE_lightmaps.ts +2 -2
- package/src/engine/extensions/extensions.ts +11 -5
- package/src/engine/webcomponents/buttons.ts +3 -1
- package/src/engine/webcomponents/needle menu/needle-menu.ts +40 -3
- package/src/engine/webcomponents/needle-engine.attributes.ts +2 -1
- package/src/engine/webcomponents/needle-engine.ts +4 -0
- package/src/engine/xr/NeedleXRSession.ts +3 -1
- package/src/engine-components/Component.ts +9 -1
- package/src/engine-components/ReflectionProbe.ts +18 -10
- package/src/engine-components/Renderer.ts +16 -44
- package/src/engine-components/RendererInstancing.ts +69 -33
- package/src/engine-components/RendererLightmap.ts +27 -17
- package/src/engine-components/Skybox.ts +47 -36
- package/src/engine-components/export/usdz/USDZExporter.ts +52 -5
- package/src/engine-components/timeline/PlayableDirector.ts +16 -10
- package/src/engine-components/web/CursorFollow.ts +3 -0
- package/src/engine-components/webxr/WebXR.ts +4 -0
- package/src/engine-components/webxr/controllers/XRControllerModel.ts +1 -1
- package/src/needle-engine.ts +4 -2
- package/dist/generateMeshBVH.worker-B9bjdr6J.js +0 -25
- package/dist/loader.worker-CiTwpNPW.js +0 -27
- package/dist/rapier-BqdcSmKY.umd.cjs +0 -1
- package/dist/rapier-Cg3w3nFI.min.js +0 -1
- package/dist/rapier-sU12SWAs.js +0 -5217
|
@@ -9,6 +9,10 @@ const debug = getParam("debuglightmaps");
|
|
|
9
9
|
|
|
10
10
|
declare type MaterialWithLightmap = Material & { lightMap?: Texture | null };
|
|
11
11
|
|
|
12
|
+
let cloningCounter = 0;
|
|
13
|
+
|
|
14
|
+
const $lightmapVersion = Symbol("lightmap-material-version");
|
|
15
|
+
|
|
12
16
|
|
|
13
17
|
/**
|
|
14
18
|
* This component is automatically added by the {@link Renderer} component if the object has lightmap uvs AND we have a lightmap.
|
|
@@ -37,6 +41,8 @@ export class RendererLightmap {
|
|
|
37
41
|
private lightmapScaleOffset: Vector4 = new Vector4(1, 1, 0, 0);
|
|
38
42
|
|
|
39
43
|
private readonly renderer: Renderer;
|
|
44
|
+
private readonly clonedMaterials = new Array<Material>();
|
|
45
|
+
|
|
40
46
|
private get context(): Context { return this.renderer.context; }
|
|
41
47
|
private get gameObject() { return this.renderer.gameObject; }
|
|
42
48
|
private lightmapTexture: Texture | null = null;
|
|
@@ -89,8 +95,7 @@ export class RendererLightmap {
|
|
|
89
95
|
|
|
90
96
|
const mat = this.renderer.sharedMaterials[i];
|
|
91
97
|
if (!mat) continue;
|
|
92
|
-
|
|
93
|
-
const newMat = this.ensureLightmapMaterial(mat);
|
|
98
|
+
const newMat = this.ensureLightmapMaterial(mat, i);
|
|
94
99
|
if (mat !== newMat) {
|
|
95
100
|
this.renderer.sharedMaterials[i] = newMat;
|
|
96
101
|
}
|
|
@@ -118,23 +123,28 @@ export class RendererLightmap {
|
|
|
118
123
|
}
|
|
119
124
|
}
|
|
120
125
|
|
|
121
|
-
private ensureLightmapMaterial(material: Material) {
|
|
126
|
+
private ensureLightmapMaterial(material: Material, index: number) {
|
|
122
127
|
if (!material.userData) material.userData = {};
|
|
123
128
|
// if (material instanceof MeshPhysicalMaterial) {
|
|
124
129
|
// return material;
|
|
125
130
|
// }
|
|
126
131
|
// check if the material version has changed and only then clone the material
|
|
127
|
-
if (
|
|
128
|
-
if (
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
// we need to clone the material
|
|
132
|
+
if (this.clonedMaterials[index] !== material) {
|
|
133
|
+
if (debug) {
|
|
134
|
+
++cloningCounter;
|
|
135
|
+
if (cloningCounter++ < 1000) {
|
|
136
|
+
console.warn(`Cloning material for lightmap ${this.renderer.name}: '${material.name}'`);
|
|
137
|
+
}
|
|
138
|
+
else if (cloningCounter === 1000) {
|
|
139
|
+
console.warn(`Further material cloning for lightmaps suppressed to avoid flooding the console.`);
|
|
140
|
+
}
|
|
137
141
|
}
|
|
142
|
+
const mat: Material = material.clone();
|
|
143
|
+
if (!mat.name?.includes("(lightmap)")) mat.name = material.name + " (lightmap)";
|
|
144
|
+
material = mat;
|
|
145
|
+
material.onBeforeCompile = this.onBeforeCompile;
|
|
146
|
+
this.clonedMaterials[index] = material;
|
|
147
|
+
|
|
138
148
|
}
|
|
139
149
|
return material;
|
|
140
150
|
}
|
|
@@ -144,22 +154,22 @@ export class RendererLightmap {
|
|
|
144
154
|
if (material instanceof MeshPhysicalMaterial && material.transmission > 0) {
|
|
145
155
|
return;
|
|
146
156
|
}
|
|
147
|
-
const hasChanged = material.lightMap !== this.lightmapTexture || material[
|
|
157
|
+
const hasChanged = material.lightMap !== this.lightmapTexture || material[$lightmapVersion] !== material.version;
|
|
148
158
|
if (!hasChanged) {
|
|
149
159
|
return;
|
|
150
160
|
}
|
|
151
161
|
|
|
152
|
-
if (debug) console.log(
|
|
162
|
+
if (debug) console.log(`Assigning lightmap texture ${this.renderer.name}: '${material.name}' (${material.version} ${material[$lightmapVersion]})`);
|
|
153
163
|
|
|
154
164
|
// assign the lightmap
|
|
155
165
|
material.lightMap = this.lightmapTexture;
|
|
156
166
|
material.needsUpdate = true;
|
|
157
167
|
// store the version of the material
|
|
158
|
-
material[
|
|
168
|
+
material[$lightmapVersion] = material.version;
|
|
159
169
|
}
|
|
160
170
|
|
|
161
171
|
private onBeforeCompile = (shader: WebGLProgramParametersWithUniforms, _) => {
|
|
162
|
-
if (debug) console.log("Lightmaps, before compile\n", shader)
|
|
172
|
+
if (debug === "verbose") console.log("Lightmaps, before compile\n", shader)
|
|
163
173
|
this.lightmapScaleOffsetUniform.value = this.lightmapScaleOffset;
|
|
164
174
|
this.lightmapUniform.value = this.lightmapTexture;
|
|
165
175
|
shader.uniforms.lightmapScaleOffset = this.lightmapScaleOffsetUniform;
|
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
import { CompressedCubeTexture,
|
|
2
|
-
import { EXRLoader } from "three/examples/jsm/loaders/EXRLoader.js";
|
|
3
|
-
import { KTX2Loader } from "three/examples/jsm/loaders/KTX2Loader.js";
|
|
4
|
-
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js';
|
|
1
|
+
import { CompressedCubeTexture, CubeTexture, CubeUVReflectionMapping, EquirectangularRefractionMapping, Texture } from "three"
|
|
5
2
|
|
|
3
|
+
import { isDevEnvironment } from "../engine/debug/debug.js";
|
|
6
4
|
import { ContextEvent, ContextRegistry } from "../engine/engine_context_registry.js";
|
|
7
5
|
import { syncField } from "../engine/engine_networking_auto.js";
|
|
8
6
|
import { loadPMREM } from "../engine/engine_pmrem.js";
|
|
9
7
|
import { serializable } from "../engine/engine_serialization_decorator.js";
|
|
10
8
|
import { type IContext } from "../engine/engine_types.js";
|
|
11
|
-
import { addAttributeChangeCallback, getParam,
|
|
9
|
+
import { addAttributeChangeCallback, getParam, removeAttributeChangeCallback, toSourceId } from "../engine/engine_utils.js";
|
|
12
10
|
import { registerObservableAttribute } from "../engine/webcomponents/needle-engine.extras.js";
|
|
13
|
-
import { Camera
|
|
11
|
+
import { Camera } from "./Camera.js";
|
|
14
12
|
import { Behaviour, GameObject } from "./Component.js";
|
|
15
13
|
|
|
16
14
|
const debug = getParam("debugskybox");
|
|
@@ -18,6 +16,29 @@ const debug = getParam("debugskybox");
|
|
|
18
16
|
registerObservableAttribute("background-image");
|
|
19
17
|
registerObservableAttribute("environment-image");
|
|
20
18
|
|
|
19
|
+
|
|
20
|
+
type MagicSkyboxName = "studio" | "blurred-skybox" | "quicklook-ar" | "quicklook";
|
|
21
|
+
const MagicSkyboxNames: Record<MagicSkyboxName, { url: string, url_low: string }> = {
|
|
22
|
+
"studio": {
|
|
23
|
+
url: "https://cdn.needle.tools/static/skybox/modelviewer-Neutral.pmrem4x4.ktx2?pmrem",
|
|
24
|
+
url_low: "https://cdn.needle.tools/static/skybox/modelviewer-Neutral-small.pmrem4x4.ktx2?pmrem"
|
|
25
|
+
},
|
|
26
|
+
"blurred-skybox": {
|
|
27
|
+
url: "https://cdn.needle.tools/static/skybox/blurred-skybox.pmrem4x4.ktx2?pmrem",
|
|
28
|
+
url_low: "https://cdn.needle.tools/static/skybox/blurred-skybox-small.pmrem4x4.ktx2?pmrem"
|
|
29
|
+
},
|
|
30
|
+
"quicklook-ar": {
|
|
31
|
+
url: "https://cdn.needle.tools/static/skybox/QuickLook-ARMode.pmrem4x4.ktx2?pmrem",
|
|
32
|
+
url_low: "https://cdn.needle.tools/static/skybox/QuickLook-ARMode-small.pmrem4x4.ktx2?pmrem"
|
|
33
|
+
},
|
|
34
|
+
"quicklook": {
|
|
35
|
+
url: "https://cdn.needle.tools/static/skybox/QuickLook-ObjectMode.pmrem4x4.ktx2?pmrem",
|
|
36
|
+
url_low: "https://cdn.needle.tools/static/skybox/QuickLook-ObjectMode-small.pmrem4x4.ktx2?pmrem"
|
|
37
|
+
}
|
|
38
|
+
} as const;
|
|
39
|
+
type AnyString = string & { _brand?: never };
|
|
40
|
+
|
|
41
|
+
|
|
21
42
|
function createRemoteSkyboxComponent(context: IContext, url: string, skybox: boolean, environment: boolean, attribute: "background-image" | "environment-image") {
|
|
22
43
|
|
|
23
44
|
// when the user sets the attribute to a color we can not handle it as a skybox url.
|
|
@@ -91,8 +112,9 @@ ContextRegistry.registerCallback(ContextEvent.ContextCreationStart, () => {
|
|
|
91
112
|
});
|
|
92
113
|
|
|
93
114
|
|
|
115
|
+
|
|
94
116
|
/**
|
|
95
|
-
* RemoteSkybox is a component that allows you to set the skybox of a scene from a URL or a
|
|
117
|
+
* RemoteSkybox is a component that allows you to set the skybox or environment texture of a scene from a URL, a local file or a static skybox name.
|
|
96
118
|
* It supports .hdr, .exr, .jpg, .png files.
|
|
97
119
|
*
|
|
98
120
|
* ### Events
|
|
@@ -127,8 +149,13 @@ ContextRegistry.registerCallback(ContextEvent.ContextCreationStart, () => {
|
|
|
127
149
|
export class RemoteSkybox extends Behaviour {
|
|
128
150
|
|
|
129
151
|
/**
|
|
130
|
-
* URL to a remote skybox.
|
|
131
|
-
* To update the skybox/environment map use `setSkybox(url)
|
|
152
|
+
* URL to a remote skybox.
|
|
153
|
+
* To update the skybox/environment map use `setSkybox(url)`.
|
|
154
|
+
*
|
|
155
|
+
* The url can also be set to a magic skybox name.
|
|
156
|
+
* Magic name options are: "quicklook", "quicklook-ar", "studio", "blurred-skybox".
|
|
157
|
+
* These will resolve to built-in skyboxes hosted on the Needle CDN that are static, optimized for the web and will never change.
|
|
158
|
+
*
|
|
132
159
|
* @example
|
|
133
160
|
* ```ts
|
|
134
161
|
* skybox.url = "https://example.com/skybox.hdr";
|
|
@@ -136,7 +163,7 @@ export class RemoteSkybox extends Behaviour {
|
|
|
136
163
|
*/
|
|
137
164
|
@syncField(RemoteSkybox.prototype.urlChangedSyncField)
|
|
138
165
|
@serializable(URL)
|
|
139
|
-
url
|
|
166
|
+
url: MagicSkyboxName | AnyString = "studio";
|
|
140
167
|
|
|
141
168
|
/**
|
|
142
169
|
* When enabled a user can drop a link to a skybox image on the scene to set the skybox.
|
|
@@ -208,7 +235,7 @@ export class RemoteSkybox extends Behaviour {
|
|
|
208
235
|
* @param name Define name of the file with extension if it isn't apart of the url
|
|
209
236
|
* @returns Whether the skybox was successfully set
|
|
210
237
|
*/
|
|
211
|
-
async setSkybox(url:
|
|
238
|
+
async setSkybox(url: MagicSkyboxName | AnyString | undefined | null, name?: string) {
|
|
212
239
|
if (!this.activeAndEnabled) return false;
|
|
213
240
|
|
|
214
241
|
url = tryParseMagicSkyboxName(url, this.environment, this.background);
|
|
@@ -404,38 +431,22 @@ export class RemoteSkybox extends Behaviour {
|
|
|
404
431
|
|
|
405
432
|
|
|
406
433
|
|
|
407
|
-
|
|
408
434
|
function tryParseMagicSkyboxName(str: string | null | undefined, environment: boolean, background: boolean): string | null {
|
|
409
435
|
|
|
410
436
|
if (str === null || str === undefined) return null;
|
|
411
437
|
|
|
412
438
|
const useLowRes = environment && !background;
|
|
413
439
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
return "https://cdn.needle.tools/static/skybox/blurred-skybox-small.pmrem4x4.ktx2?pmrem";
|
|
424
|
-
}
|
|
425
|
-
return "https://cdn.needle.tools/static/skybox/blurred-skybox.pmrem4x4.ktx2?pmrem";
|
|
426
|
-
case "quicklook-ar":
|
|
427
|
-
if (useLowRes) {
|
|
428
|
-
return "https://cdn.needle.tools/static/skybox/QuickLook-ARMode-small.pmrem4x4.ktx2?pmrem";
|
|
429
|
-
}
|
|
430
|
-
return "https://cdn.needle.tools/static/skybox/QuickLook-ARMode.pmrem4x4.ktx2?pmrem";
|
|
431
|
-
case "quicklook":
|
|
432
|
-
if (useLowRes) {
|
|
433
|
-
return "https://cdn.needle.tools/static/skybox/QuickLook-ObjectMode-small.pmrem4x4.ktx2?pmrem";
|
|
434
|
-
}
|
|
435
|
-
return "https://cdn.needle.tools/static/skybox/QuickLook-ObjectMode.pmrem4x4.ktx2?pmrem";
|
|
440
|
+
const value = MagicSkyboxNames[str.toLowerCase() as MagicSkyboxName];
|
|
441
|
+
if (value) {
|
|
442
|
+
return useLowRes ? value.url_low : value.url;
|
|
443
|
+
}
|
|
444
|
+
else if (typeof str === "string" && str?.length && (isDevEnvironment() || debug)) {
|
|
445
|
+
const noUrlOrFile = !str.startsWith("http") && !str.startsWith("file:") && !str.startsWith("blob:") && !str.startsWith("data:");
|
|
446
|
+
if(noUrlOrFile) {
|
|
447
|
+
console.warn(`RemoteSkybox: Unknown magic skybox name "${str}". Valid names are: ${Object.keys(MagicSkyboxNames).map(n => `"${n}"`).join(", ")}`);
|
|
448
|
+
}
|
|
436
449
|
}
|
|
437
|
-
|
|
438
|
-
|
|
439
450
|
|
|
440
451
|
return str;
|
|
441
452
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NEEDLE_progressive } from "@needle-tools/gltf-progressive";
|
|
2
|
-
import { Euler,
|
|
2
|
+
import { Euler, Material, Matrix4, Mesh, Object3D, Quaternion, Vector3 } from "three";
|
|
3
3
|
|
|
4
4
|
import { isDevEnvironment, showBalloonMessage, showBalloonWarning } from "../../../engine/debug/index.js";
|
|
5
5
|
import { hasProLicense } from "../../../engine/engine_license.js";
|
|
@@ -53,6 +53,23 @@ export class CustomBranding {
|
|
|
53
53
|
callToActionURL?: string;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
type BeforeLODExportArguments = {
|
|
57
|
+
readonly exporter: USDZExporter;
|
|
58
|
+
/** The type of LOD being exported, either a texture or a mesh */
|
|
59
|
+
readonly type: "texture" | "mesh";
|
|
60
|
+
/** The Renderer gameobject */
|
|
61
|
+
readonly object: Object3D;
|
|
62
|
+
/** The mesh being exported, if applicable */
|
|
63
|
+
readonly mesh?: Mesh;
|
|
64
|
+
/** The material being exported, if applicable */
|
|
65
|
+
readonly material?: Material;
|
|
66
|
+
/** By default LOD 0 will be exported (highest quality).
|
|
67
|
+
* Set to a different LOD level if needed.
|
|
68
|
+
* Set to -1 to disable LOD export and simply export the current version.
|
|
69
|
+
*/
|
|
70
|
+
overrideLevel?: number;
|
|
71
|
+
}
|
|
72
|
+
|
|
56
73
|
/**
|
|
57
74
|
* Exports the current scene or a specific object as USDZ file and opens it in QuickLook on iOS/iPadOS/visionOS.
|
|
58
75
|
* The USDZ file is generated using the Needle Engine ThreeUSDZExporter.
|
|
@@ -72,8 +89,12 @@ export class CustomBranding {
|
|
|
72
89
|
*/
|
|
73
90
|
export class USDZExporter extends Behaviour {
|
|
74
91
|
|
|
75
|
-
|
|
76
|
-
static readonly
|
|
92
|
+
/** Called before the USDZ file is exported */
|
|
93
|
+
static readonly beforeExport = new EventList<{ readonly exporter: USDZExporter }>();
|
|
94
|
+
/** Called after the USDZ file has been exported */
|
|
95
|
+
static readonly afterExport = new EventList<{ readonly exporter: USDZExporter }>();
|
|
96
|
+
/** Called before LOD level are exported. Can be used to override the LOD export settings */
|
|
97
|
+
static readonly beforeLODExport = new EventList<BeforeLODExportArguments>();
|
|
77
98
|
|
|
78
99
|
/**
|
|
79
100
|
* Assign the object to export as USDZ file. If undefined or null, the whole scene will be exported.
|
|
@@ -329,7 +350,20 @@ export class USDZExporter extends Behaviour {
|
|
|
329
350
|
for (const rend of renderers) {
|
|
330
351
|
for (const mesh of rend.sharedMeshes) {
|
|
331
352
|
if (mesh) {
|
|
332
|
-
|
|
353
|
+
let lodLevel = 0;
|
|
354
|
+
const args: BeforeLODExportArguments = { exporter: this, type: "mesh" as const, object: rend.gameObject, mesh: mesh, };
|
|
355
|
+
USDZExporter.beforeLODExport.invoke(args);
|
|
356
|
+
if (args.overrideLevel !== undefined) {
|
|
357
|
+
if (args.overrideLevel === -1) {
|
|
358
|
+
if (debug) console.warn("Skipping LOD export for mesh due to overrideLevel -1", rend.gameObject, mesh);
|
|
359
|
+
continue; // skip LOD assignment
|
|
360
|
+
}
|
|
361
|
+
else if (args.overrideLevel >= 0) {
|
|
362
|
+
lodLevel = args.overrideLevel;
|
|
363
|
+
if (debug) console.log("Overriding LOD level for mesh export to level " + lodLevel + " " + mesh.name);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
const task = NEEDLE_progressive.assignMeshLOD(mesh, lodLevel);
|
|
333
367
|
if (task instanceof Promise)
|
|
334
368
|
progressiveLoading.push(new Promise<void>((resolve, reject) => {
|
|
335
369
|
task.then(() => {
|
|
@@ -342,7 +376,20 @@ export class USDZExporter extends Behaviour {
|
|
|
342
376
|
}
|
|
343
377
|
for (const mat of rend.sharedMaterials) {
|
|
344
378
|
if (mat) {
|
|
345
|
-
|
|
379
|
+
let lodLevel = 0;
|
|
380
|
+
const args: BeforeLODExportArguments = { exporter: this, type: "texture" as const, object: rend.gameObject, material: mat };
|
|
381
|
+
USDZExporter.beforeLODExport.invoke(args);
|
|
382
|
+
if (args.overrideLevel !== undefined) {
|
|
383
|
+
if (args.overrideLevel === -1) {
|
|
384
|
+
if (debug) console.warn("Skipping LOD assignment due to overrideLevel -1", rend.gameObject, mat);
|
|
385
|
+
continue; // skip LOD assignment
|
|
386
|
+
}
|
|
387
|
+
else if (args.overrideLevel >= 0) {
|
|
388
|
+
lodLevel = args.overrideLevel;
|
|
389
|
+
if (debug) console.log("Overriding LOD level for texture export to level " + lodLevel + " " + mat.name);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
const task = NEEDLE_progressive.assignTextureLOD(mat, lodLevel);
|
|
346
393
|
if (task instanceof Promise)
|
|
347
394
|
progressiveLoading.push(new Promise<void>((resolve, reject) => {
|
|
348
395
|
task.then(() => {
|
|
@@ -114,8 +114,7 @@ export class PlayableDirector extends Behaviour {
|
|
|
114
114
|
|
|
115
115
|
/** @internal */
|
|
116
116
|
awake(): void {
|
|
117
|
-
if (debug)
|
|
118
|
-
console.log(this, this.playableAsset);
|
|
117
|
+
if (debug) console.log(`[Timeline] Awake '${this.name}'`, this);
|
|
119
118
|
|
|
120
119
|
this.rebuildGraph();
|
|
121
120
|
|
|
@@ -134,6 +133,8 @@ export class PlayableDirector extends Behaviour {
|
|
|
134
133
|
|
|
135
134
|
/** @internal */
|
|
136
135
|
onEnable() {
|
|
136
|
+
if (debug) console.log("[Timeline] OnEnable", this.name, this.playOnAwake);
|
|
137
|
+
|
|
137
138
|
for (const track of this._audioTracks) {
|
|
138
139
|
track.onEnable?.();
|
|
139
140
|
}
|
|
@@ -162,6 +163,8 @@ export class PlayableDirector extends Behaviour {
|
|
|
162
163
|
|
|
163
164
|
/** @internal */
|
|
164
165
|
onDisable(): void {
|
|
166
|
+
if (debug) console.log("[Timeline] OnDisable", this.name);
|
|
167
|
+
|
|
165
168
|
this.stop();
|
|
166
169
|
for (const track of this._audioTracks) {
|
|
167
170
|
track.onDisable?.();
|
|
@@ -360,14 +363,17 @@ export class PlayableDirector extends Behaviour {
|
|
|
360
363
|
private readonly _controlTracks: Array<Tracks.ControlTrackHandler> = [];
|
|
361
364
|
private readonly _customTracks: Array<Tracks.TrackHandler> = [];
|
|
362
365
|
|
|
363
|
-
private readonly
|
|
364
|
-
|
|
365
|
-
this.
|
|
366
|
-
this.
|
|
367
|
-
this.
|
|
368
|
-
this.
|
|
369
|
-
this.
|
|
370
|
-
|
|
366
|
+
private readonly _tracksArray: Array<Array<Tracks.TrackHandler>> = [];
|
|
367
|
+
private get _allTracks(): Array<Array<Tracks.TrackHandler>> {
|
|
368
|
+
this._tracksArray.length = 0;
|
|
369
|
+
this._tracksArray.push(this._animationTracks);
|
|
370
|
+
this._tracksArray.push(this._audioTracks);
|
|
371
|
+
this._tracksArray.push(this._signalTracks);
|
|
372
|
+
this._tracksArray.push(this._markerTracks);
|
|
373
|
+
this._tracksArray.push(this._controlTracks);
|
|
374
|
+
this._tracksArray.push(this._customTracks);
|
|
375
|
+
return this._tracksArray;
|
|
376
|
+
}
|
|
371
377
|
|
|
372
378
|
/** should be called after evaluate if the director was playing */
|
|
373
379
|
private invokePauseChangedMethodsOnTracks() {
|
|
@@ -20,6 +20,9 @@ const debug = getParam("debugcursor");
|
|
|
20
20
|
*/
|
|
21
21
|
export class CursorFollow extends Behaviour {
|
|
22
22
|
|
|
23
|
+
// testing this for compilation
|
|
24
|
+
static readonly NAME = "CursorFollow";
|
|
25
|
+
|
|
23
26
|
/**
|
|
24
27
|
* Damping for the movement, set to 0 for instant movement
|
|
25
28
|
* @default 0
|
|
@@ -331,6 +331,10 @@ export class WebXR extends Behaviour {
|
|
|
331
331
|
console.warn(`WebXR: another WebXR component is already active (${WebXR.activeWebXRComponent?.name}). This is ignored: ${this.name}`);
|
|
332
332
|
return;
|
|
333
333
|
}
|
|
334
|
+
if (this.activeAndEnabled === false || this.destroyed) {
|
|
335
|
+
console.debug("[WebXR] onBeforeXR called on disabled or destroyed component");
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
334
338
|
WebXR.activeWebXRComponent = this;
|
|
335
339
|
|
|
336
340
|
if (_mode == "immersive-ar" && this.useDepthSensing) {
|
|
@@ -284,7 +284,7 @@ export class XRControllerModel extends Behaviour {
|
|
|
284
284
|
|
|
285
285
|
const loader = new GLTFLoader();
|
|
286
286
|
addDracoAndKTX2Loaders(loader, context);
|
|
287
|
-
await registerExtensions(loader, context, this.sourceId ?? "");
|
|
287
|
+
await registerExtensions(loader, context, this.sourceId ?? "", this.sourceId ?? "");
|
|
288
288
|
const componentsExtension = registerComponentExtension(loader);
|
|
289
289
|
|
|
290
290
|
let filename = "";
|
package/src/needle-engine.ts
CHANGED
|
@@ -7,7 +7,7 @@ export * from "./engine-components-experimental/api.js";
|
|
|
7
7
|
export * from "./engine-schemes/api.js";
|
|
8
8
|
|
|
9
9
|
// make accessible for external javascript
|
|
10
|
-
import { Context, loadAsset, NeedleXRSession, onAfterRender, onBeforeRender, onClear, onDestroy, onInitialized, onStart, onUpdate, VERSION } from "./engine/api.js";
|
|
10
|
+
import { Context, loadAsset, NeedleXRSession, onAfterRender, onBeforeRender, onClear, onDestroy, onInitialized, onStart, onUpdate, TypeStore, VERSION } from "./engine/api.js";
|
|
11
11
|
const Needle = {
|
|
12
12
|
VERSION: VERSION,
|
|
13
13
|
Context: Context,
|
|
@@ -15,6 +15,7 @@ const Needle = {
|
|
|
15
15
|
assets: {
|
|
16
16
|
loadFromURL: loadAsset,
|
|
17
17
|
},
|
|
18
|
+
types: TypeStore,
|
|
18
19
|
onStart: onStart,
|
|
19
20
|
onUpdate: onUpdate,
|
|
20
21
|
onBeforeRender: onBeforeRender,
|
|
@@ -22,7 +23,8 @@ const Needle = {
|
|
|
22
23
|
onInitializedContext: onInitialized,
|
|
23
24
|
onDestroyContext: onDestroy,
|
|
24
25
|
onClearContext: onClear,
|
|
25
|
-
};
|
|
26
|
+
} as const;
|
|
27
|
+
|
|
26
28
|
if (globalThis["Needle"]?.VERSION !== undefined) {
|
|
27
29
|
console.warn(`Needle Engine is already imported: ${globalThis["Needle"].VERSION}`);
|
|
28
30
|
}
|