@needle-tools/engine 4.5.0-alpha.2 → 4.5.0-alpha.4
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 +23 -2
- package/dist/{needle-engine.bundle-a52706c5.umd.cjs → needle-engine.bundle-1ea82d1b.umd.cjs} +74 -73
- package/dist/{needle-engine.bundle-f3c8cffc.light.umd.cjs → needle-engine.bundle-5799046c.light.umd.cjs} +74 -73
- package/dist/{needle-engine.bundle-53f80c62.js → needle-engine.bundle-613ac05e.js} +757 -750
- package/dist/{needle-engine.bundle-1526f05b.light.js → needle-engine.bundle-82027067.light.js} +944 -937
- package/dist/{needle-engine.bundle-15b19b2c.light.min.js → needle-engine.bundle-cb8d3ee9.light.min.js} +74 -73
- package/dist/{needle-engine.bundle-2024e2b3.min.js → needle-engine.bundle-e8936122.min.js} +74 -73
- package/dist/needle-engine.js +24 -24
- package/dist/needle-engine.light.js +24 -24
- package/dist/needle-engine.light.min.js +1 -1
- package/dist/needle-engine.light.umd.cjs +1 -1
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- package/lib/engine/engine_components.js +6 -14
- package/lib/engine/engine_components.js.map +1 -1
- package/lib/engine/engine_context_registry.d.ts +2 -2
- package/lib/engine/engine_context_registry.js +2 -2
- package/lib/engine/engine_context_registry.js.map +1 -1
- package/lib/engine/engine_loaders.callbacks.d.ts +43 -9
- package/lib/engine/engine_loaders.callbacks.js +42 -12
- package/lib/engine/engine_loaders.callbacks.js.map +1 -1
- package/lib/engine/engine_loaders.js +18 -15
- package/lib/engine/engine_loaders.js.map +1 -1
- package/lib/engine/engine_utils_format.d.ts +5 -5
- package/lib/engine/engine_utils_format.js +31 -31
- package/lib/engine/engine_utils_format.js.map +1 -1
- package/lib/engine-components/ContactShadows.d.ts +12 -0
- package/lib/engine-components/ContactShadows.js +23 -0
- package/lib/engine-components/ContactShadows.js.map +1 -1
- package/lib/engine-components/webxr/controllers/XRControllerModel.js.map +1 -1
- package/package.json +1 -1
- package/plugins/vite/dependencies.js +1 -1
- package/src/engine/engine_components.ts +4 -12
- package/src/engine/engine_context_registry.ts +2 -2
- package/src/engine/engine_loaders.callbacks.ts +63 -17
- package/src/engine/engine_loaders.ts +17 -15
- package/src/engine/engine_utils_format.ts +45 -34
- package/src/engine-components/ContactShadows.ts +24 -0
- package/src/engine-components/webxr/controllers/XRControllerModel.ts +0 -2
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { BufferGeometry, Object3D } from "three";
|
|
2
2
|
import { Context } from "./engine_setup.js";
|
|
3
3
|
import { CustomModel } from "./engine_types.js";
|
|
4
|
-
import { type
|
|
4
|
+
import { type NeedleMimetype } from "./engine_utils_format.js";
|
|
5
5
|
|
|
6
6
|
export type ValidLoaderReturnType = CustomModel | Object3D | BufferGeometry;
|
|
7
7
|
|
|
8
8
|
|
|
9
|
+
|
|
9
10
|
/** @internal */
|
|
10
11
|
export type CustomLoader = {
|
|
11
12
|
/** The name of the loader. This is used for debugging purposes. */
|
|
@@ -16,12 +17,12 @@ export type CustomLoader = {
|
|
|
16
17
|
parse: (buffer: ArrayBuffer | string, path: string) => ValidLoaderReturnType,
|
|
17
18
|
};
|
|
18
19
|
|
|
19
|
-
type CustomLoaderCallback = (args: { context: Context, url: string,
|
|
20
|
+
type CustomLoaderCallback = (args: { context: Context, url: string, mimetype: NeedleMimetype }) => CustomLoader | Promise<CustomLoader> | null | undefined | void;
|
|
20
21
|
/** @internal */
|
|
21
|
-
export const registeredModelLoaderCallbacks: Array<CustomLoaderCallback> = [];
|
|
22
|
+
export const registeredModelLoaderCallbacks: Array<{ name?: string, priority: number, callback: CustomLoaderCallback }> = [];
|
|
22
23
|
|
|
23
24
|
|
|
24
|
-
type
|
|
25
|
+
type MimetypeCallback = (args: {
|
|
25
26
|
/** The URL of the file to load */
|
|
26
27
|
url: string,
|
|
27
28
|
/** The response of the range request with the first few bytes of the file (bytes are available in the 'args.bytes' property of this callback) */
|
|
@@ -30,22 +31,58 @@ type FileTypeCallback = (args: {
|
|
|
30
31
|
contentType: string | null,
|
|
31
32
|
/** The first few bytes of the file as a Uint8Array */
|
|
32
33
|
bytes: Uint8Array
|
|
33
|
-
}) =>
|
|
34
|
+
}) => NeedleMimetype | null;
|
|
34
35
|
/** @internal */
|
|
35
|
-
export const
|
|
36
|
+
export const registeredMimetypeCallbacks: Array<MimetypeCallback> = [];
|
|
36
37
|
|
|
37
38
|
|
|
38
39
|
/**
|
|
39
40
|
* NeedleEngineModelLoader is a namespace that provides functions to register custom model loaders and mimetype callbacks.
|
|
40
41
|
* It allows you to create custom loaders for specific file types and determine the mimetype of files based on their content.
|
|
42
|
+
* @example
|
|
43
|
+
* ```ts
|
|
44
|
+
* import { NeedleEngineModelLoader } from "@needle-tools/engine";
|
|
45
|
+
* import { STLLoader } from "three/examples/jsm/loaders/STLLoader";
|
|
46
|
+
*
|
|
47
|
+
* NeedleEngineModelLoader.onCreateCustomModelLoader(args => {
|
|
48
|
+
* if (args.mimetype === "model/stl") {
|
|
49
|
+
* return new STLLoader();
|
|
50
|
+
* }
|
|
51
|
+
* });
|
|
52
|
+
*
|
|
53
|
+
* NeedleEngineModelLoader.onDetermineModelMimetype((args) => {
|
|
54
|
+
* // detect stl mimetype
|
|
55
|
+
* const bytes = args.bytes;
|
|
56
|
+
* if (bytes[0] === 0x73 && bytes[1] === 0x74 && bytes[2] === 0x6c) {
|
|
57
|
+
* return "model/stl";
|
|
58
|
+
* }
|
|
59
|
+
* return null;
|
|
60
|
+
* });
|
|
61
|
+
* ```
|
|
41
62
|
*/
|
|
42
63
|
export namespace NeedleEngineModelLoader {
|
|
43
64
|
|
|
44
|
-
// export type
|
|
45
|
-
// name: string
|
|
46
|
-
// canLoad: (
|
|
65
|
+
// export type Plugin = {
|
|
66
|
+
// readonly name: string;
|
|
67
|
+
// canLoad: (mimetype: string, url: string) => boolean,
|
|
68
|
+
// createLoader: (url: string, mimetype: string) => Promise<CustomLoader>,
|
|
69
|
+
// }
|
|
70
|
+
|
|
71
|
+
// export function registerLoaderPlugin(plugin: Plugin) {
|
|
47
72
|
// }
|
|
48
|
-
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
type CustomLoaderOptions = {
|
|
77
|
+
/** The name of the loader. This is used for debugging purposes. */
|
|
78
|
+
name?: string,
|
|
79
|
+
/**
|
|
80
|
+
* The priority of the loader. Higher priority loaders will be called first.
|
|
81
|
+
* @default 0
|
|
82
|
+
*/
|
|
83
|
+
priority?: number,
|
|
84
|
+
}
|
|
85
|
+
|
|
49
86
|
/**
|
|
50
87
|
* Register a custom loader callback. For every file that is requested this callback is called with the url and mimetype. It should return a custom loader or null if it does not want to handle the file.
|
|
51
88
|
* @param callback The callback to register
|
|
@@ -60,10 +97,19 @@ export namespace NeedleEngineModelLoader {
|
|
|
60
97
|
* return null;
|
|
61
98
|
* });
|
|
62
99
|
*/
|
|
63
|
-
export function onCreateCustomModelLoader(callback: CustomLoaderCallback) {
|
|
64
|
-
|
|
100
|
+
export function onCreateCustomModelLoader(callback: CustomLoaderCallback, opts?: CustomLoaderOptions) {
|
|
101
|
+
const entry = { name: opts?.name, priority: opts?.priority ?? 0, callback };
|
|
102
|
+
registeredModelLoaderCallbacks.push(entry);
|
|
103
|
+
|
|
104
|
+
// sort plugins by priority. Higher priority first
|
|
105
|
+
registeredModelLoaderCallbacks.sort((a, b) => {
|
|
106
|
+
if (a.priority === b.priority) return 0;
|
|
107
|
+
if (a.priority > b.priority) return -1;
|
|
108
|
+
return 1;
|
|
109
|
+
});
|
|
110
|
+
|
|
65
111
|
return () => {
|
|
66
|
-
const index = registeredModelLoaderCallbacks.indexOf(
|
|
112
|
+
const index = registeredModelLoaderCallbacks.indexOf(entry);
|
|
67
113
|
if (index >= 0) {
|
|
68
114
|
registeredModelLoaderCallbacks.splice(index, 1);
|
|
69
115
|
}
|
|
@@ -76,12 +122,12 @@ export namespace NeedleEngineModelLoader {
|
|
|
76
122
|
* @returns A function to unregister the callback
|
|
77
123
|
*
|
|
78
124
|
*/
|
|
79
|
-
export function
|
|
80
|
-
|
|
125
|
+
export function onDetermineModelMimetype(callback: MimetypeCallback): (() => void) {
|
|
126
|
+
registeredMimetypeCallbacks.push(callback);
|
|
81
127
|
return () => {
|
|
82
|
-
const index =
|
|
128
|
+
const index = registeredMimetypeCallbacks.indexOf(callback);
|
|
83
129
|
if (index >= 0) {
|
|
84
|
-
|
|
130
|
+
registeredMimetypeCallbacks.splice(index, 1);
|
|
85
131
|
}
|
|
86
132
|
}
|
|
87
133
|
}
|
|
@@ -15,7 +15,7 @@ import { Context } from "./engine_setup.js"
|
|
|
15
15
|
import { postprocessFBXMaterials } from "./engine_three_utils.js";
|
|
16
16
|
import { CustomModel, isGLTFModel, Model, type UIDProvider } from "./engine_types.js";
|
|
17
17
|
import * as utils from "./engine_utils.js";
|
|
18
|
-
import {
|
|
18
|
+
import { tryDetermineMimetypeFromURL } from "./engine_utils_format.js"
|
|
19
19
|
import { invokeLoadedImportPluginHooks, registerComponentExtension, registerExtensions } from "./extensions/extensions.js";
|
|
20
20
|
import { NEEDLE_components } from "./extensions/NEEDLE_components.js";
|
|
21
21
|
|
|
@@ -45,42 +45,44 @@ const debugFileTypes = utils.getParam("debugfileformat");
|
|
|
45
45
|
|
|
46
46
|
export async function onCreateLoader(url: string, context: Context): Promise<CustomLoader | GLTFLoader | FBXLoader | USDZLoader | OBJLoader | null> {
|
|
47
47
|
|
|
48
|
-
const type = await
|
|
48
|
+
const type = await tryDetermineMimetypeFromURL(url, { useExtension: true }) || "unknown";
|
|
49
49
|
if (debugFileTypes) console.debug(`Determined file type: '${type}' for url '${url}'`);
|
|
50
50
|
|
|
51
|
-
for (const
|
|
52
|
-
const
|
|
51
|
+
for (const entry of registeredModelLoaderCallbacks) {
|
|
52
|
+
const { callback } = entry;
|
|
53
|
+
let loader = callback({ context, url, mimetype: type });
|
|
54
|
+
if (loader instanceof Promise) await loader;
|
|
53
55
|
if (loader) {
|
|
54
|
-
console.debug(
|
|
56
|
+
console.debug(`Using custom loader (${entry.name}) for url '${url}'`);
|
|
55
57
|
return loader;
|
|
56
58
|
}
|
|
57
59
|
}
|
|
58
60
|
|
|
59
61
|
switch (type) {
|
|
60
62
|
default:
|
|
61
|
-
console.warn(`Unknown file type: ${type}`);
|
|
62
63
|
case "unknown":
|
|
63
64
|
{
|
|
64
|
-
console.warn(
|
|
65
|
+
console.warn(`Unknown file type (${type}). Needle Engine will fallback to the GLTFLoader - To support more model formats please create a Needle loader plugin.\nUse import { NeedleEngineModelLoader } from \"@needle-tools/engine\" namespace to register your loader.`, url);
|
|
65
66
|
const loader = new GLTFLoader();
|
|
66
67
|
await registerExtensions(loader, context, url);
|
|
67
68
|
return loader;
|
|
68
69
|
}
|
|
69
|
-
case "fbx":
|
|
70
|
+
case "model/fbx":
|
|
71
|
+
case "model/vnd.autodesk.fbx":
|
|
70
72
|
return new FBXLoader();
|
|
71
|
-
case "obj":
|
|
73
|
+
case "model/obj":
|
|
72
74
|
return new OBJLoader();
|
|
73
|
-
case "
|
|
74
|
-
case "
|
|
75
|
-
case "
|
|
75
|
+
case "model/vnd.usdz+zip":
|
|
76
|
+
case "model/vnd.usd+zip":
|
|
77
|
+
case "model/vnd.usda+zip":
|
|
76
78
|
{
|
|
77
79
|
console.warn(type.toUpperCase() + " files are not supported.");
|
|
78
80
|
// return new USDZLoader();
|
|
79
81
|
return null;
|
|
80
82
|
}
|
|
81
|
-
case "gltf":
|
|
82
|
-
case "
|
|
83
|
-
case "vrm":
|
|
83
|
+
case "model/gltf+json":
|
|
84
|
+
case "model/gltf-binary":
|
|
85
|
+
case "model/vrm":
|
|
84
86
|
{
|
|
85
87
|
const loader = new GLTFLoader();
|
|
86
88
|
await registerExtensions(loader, context, url);
|
|
@@ -1,13 +1,24 @@
|
|
|
1
1
|
import { isDevEnvironment } from "./debug/index.js";
|
|
2
|
-
import {
|
|
2
|
+
import { registeredMimetypeCallbacks } from "./engine_loaders.callbacks.js";
|
|
3
3
|
import { getParam } from "./engine_utils.js";
|
|
4
4
|
|
|
5
5
|
const debug = getParam("debugfileformat");
|
|
6
|
-
|
|
7
6
|
/**
|
|
8
|
-
* The supported file types that can be determined by the engine. Used in {@link
|
|
7
|
+
* The supported file types that can be determined by the engine. Used in {@link tryDetermineMimetypeFromURL} and {@link tryDetermineMimetypeFromBinary}
|
|
9
8
|
*/
|
|
10
|
-
export
|
|
9
|
+
export type NeedleMimetype = "unknown" |
|
|
10
|
+
"model/gltf+json" |
|
|
11
|
+
"model/gltf-binary" |
|
|
12
|
+
"model/vrm" |
|
|
13
|
+
"model/vnd.usdz+zip" |
|
|
14
|
+
"model/vnd.usd+zip" |
|
|
15
|
+
"model/vnd.usda+zip" |
|
|
16
|
+
"model/fbx" |
|
|
17
|
+
"model/vnd.autodesk.fbx" |
|
|
18
|
+
"model/obj" |
|
|
19
|
+
`model/${string}`
|
|
20
|
+
| (string & {})
|
|
21
|
+
|
|
11
22
|
|
|
12
23
|
/**
|
|
13
24
|
* Tries to determine the file type of a file from its URL
|
|
@@ -21,7 +32,7 @@ export declare type FileType = "gltf" | "glb" | "vrm" | "fbx" | "obj" | "usdz" |
|
|
|
21
32
|
* const fileType = await tryDetermineFileTypeFromURL(url);
|
|
22
33
|
* console.log(fileType); // "glb"
|
|
23
34
|
*/
|
|
24
|
-
export async function
|
|
35
|
+
export async function tryDetermineMimetypeFromURL(url: string, opts: { useExtension: boolean }): Promise<NeedleMimetype> {
|
|
25
36
|
|
|
26
37
|
const { useExtension = true } = opts;
|
|
27
38
|
|
|
@@ -44,21 +55,21 @@ export async function tryDetermineFileTypeFromURL(url: string, opts: { useExtens
|
|
|
44
55
|
if (debug) console.debug("Use file extension to determine type: " + ext);
|
|
45
56
|
switch (ext) {
|
|
46
57
|
case "GLTF":
|
|
47
|
-
return "gltf"
|
|
58
|
+
return "model/gltf+json"
|
|
48
59
|
case "VRM":
|
|
49
|
-
return "vrm";
|
|
60
|
+
return "model/vrm";
|
|
50
61
|
case "GLB":
|
|
51
|
-
return "
|
|
62
|
+
return "model/gltf-binary";
|
|
52
63
|
case "FBX":
|
|
53
|
-
return "fbx";
|
|
64
|
+
return "model/fbx";
|
|
54
65
|
case "USD":
|
|
55
|
-
return "usd";
|
|
66
|
+
return "model/vnd.usd+zip";
|
|
56
67
|
case "USDA":
|
|
57
|
-
return "usda";
|
|
68
|
+
return "model/vnd.usda+zip";
|
|
58
69
|
case "USDZ":
|
|
59
|
-
return "usdz";
|
|
70
|
+
return "model/vnd.usdz+zip";
|
|
60
71
|
case "OBJ":
|
|
61
|
-
return "obj";
|
|
72
|
+
return "model/obj";
|
|
62
73
|
}
|
|
63
74
|
}
|
|
64
75
|
|
|
@@ -88,7 +99,7 @@ export async function tryDetermineFileTypeFromURL(url: string, opts: { useExtens
|
|
|
88
99
|
|
|
89
100
|
if (header?.ok) {
|
|
90
101
|
const data = await header.arrayBuffer();
|
|
91
|
-
const res =
|
|
102
|
+
const res = tryDetermineMimetypeFromBinary(originalUrl, data, header);
|
|
92
103
|
if (debug) console.log("Determined file type from header: " + res);
|
|
93
104
|
return res;
|
|
94
105
|
}
|
|
@@ -100,7 +111,7 @@ export async function tryDetermineFileTypeFromURL(url: string, opts: { useExtens
|
|
|
100
111
|
/** Attempts to determine the file type of a binary file by looking at the first few bytes of the file.
|
|
101
112
|
* @hidden
|
|
102
113
|
*/
|
|
103
|
-
export function
|
|
114
|
+
export function tryDetermineMimetypeFromBinary(url: string, data: ArrayBuffer, response: Response): NeedleMimetype {
|
|
104
115
|
|
|
105
116
|
if (data.byteLength < 4) {
|
|
106
117
|
return "unknown";
|
|
@@ -112,67 +123,67 @@ export function tryDetermineFileTypeFromBinary(url: string, data: ArrayBuffer, r
|
|
|
112
123
|
console.warn("Trying to determine file type from binary data\n", "\"" + new TextDecoder().decode(data) + "\"\n", bytes);
|
|
113
124
|
}
|
|
114
125
|
|
|
115
|
-
// GLTF
|
|
116
|
-
if (bytes[0] == 103 && bytes[1] == 108 && bytes[2] == 84 && bytes[3] == 70) {
|
|
126
|
+
// GLTF
|
|
127
|
+
if (bytes[0] == 103 && bytes[1] == 108 && bytes[2] == 84 && bytes[3] == 70 && bytes[4] == 10) {
|
|
128
|
+
// GLTF
|
|
117
129
|
console.debug("GLTF detected");
|
|
118
|
-
return "
|
|
130
|
+
return "model/gltf+json";
|
|
131
|
+
}
|
|
132
|
+
// GLB
|
|
133
|
+
else if (bytes[0] == 103 && bytes[1] == 108 && bytes[2] == 84 && bytes[3] == 70 && bytes[4] == 98) {
|
|
134
|
+
// GLB
|
|
135
|
+
console.debug("GLB detected");
|
|
136
|
+
return "model/gltf-binary";
|
|
119
137
|
}
|
|
120
138
|
// USDZ
|
|
121
139
|
if (bytes[0] == 80 && bytes[1] == 75 && bytes[2] == 3 && bytes[3] == 4) {
|
|
122
140
|
console.debug("USDZ detected");
|
|
123
|
-
return "usdz";
|
|
141
|
+
return "model/vnd.usdz+zip";
|
|
124
142
|
}
|
|
125
143
|
// USD
|
|
126
144
|
if (bytes[0] == 80 && bytes[1] == 88 && bytes[2] == 82 && bytes[3] == 45 && bytes[4] == 85 && bytes[5] == 83 && bytes[6] == 68 && bytes[7] == 67) {
|
|
127
145
|
console.debug("Binary USD detected");
|
|
128
|
-
return "usd";
|
|
146
|
+
return "model/vnd.usd+zip";
|
|
129
147
|
}
|
|
130
148
|
// USDA: check if the file starts with #usda
|
|
131
149
|
else if (bytes[0] == 35 && bytes[1] == 117 && bytes[2] == 115 && bytes[3] == 100 && bytes[4] == 97) {
|
|
132
150
|
console.debug("ASCII USD detected");
|
|
133
|
-
return "usda";
|
|
151
|
+
return "model/vnd.usda+zip";
|
|
134
152
|
}
|
|
135
153
|
// FBX
|
|
136
154
|
if (bytes[0] == 75 && bytes[1] == 97 && bytes[2] == 121 && bytes[3] == 100 && bytes[4] == 97 && bytes[5] == 114 && bytes[6] == 97 && bytes[7] == 32) {
|
|
137
155
|
console.debug("Binary FBX detected");
|
|
138
|
-
return "fbx";
|
|
156
|
+
return "model/fbx";
|
|
139
157
|
}
|
|
140
158
|
// ASCII FBX
|
|
141
159
|
else if (bytes[0] == 59 && bytes[1] == 32 && bytes[2] == 70 && bytes[3] == 66 && bytes[4] == 88 && bytes[5] == 32) {
|
|
142
160
|
console.debug("ASCII FBX detected");
|
|
143
|
-
return "fbx";
|
|
161
|
+
return "model/fbx";
|
|
144
162
|
}
|
|
145
163
|
// OBJ - in this case exported from blender it starts with "# Blender" - we only check the first 10 bytes, technically it could still be a different file so we should do this check at the end
|
|
146
164
|
else if (bytes[0] == 35 && bytes[1] == 32 && bytes[2] == 66 && bytes[3] == 108 && bytes[4] == 101 && bytes[5] == 110 && bytes[6] == 100 && bytes[7] == 101 && bytes[8] == 114 && bytes[9] == 32) {
|
|
147
165
|
console.debug("OBJ detected");
|
|
148
|
-
return "obj";
|
|
166
|
+
return "model/obj";
|
|
149
167
|
}
|
|
150
168
|
// Check if it starts "# Alias OBJ"
|
|
151
169
|
else if (bytes[0] == 35 && bytes[1] == 32 && bytes[2] == 65 && bytes[3] == 108 && bytes[4] == 105 && bytes[5] == 97 && bytes[6] == 115 && bytes[7] == 32 && bytes[8] == 79 && bytes[9] == 66 && bytes[10] == 74) {
|
|
152
170
|
console.debug("OBJ detected");
|
|
153
|
-
return "obj";
|
|
171
|
+
return "model/obj";
|
|
154
172
|
}
|
|
155
173
|
else if (response.headers.has("content-type")) {
|
|
156
174
|
const content_type = response.headers.get("content-type");
|
|
157
175
|
console.debug("Content-Type: " + content_type);
|
|
158
176
|
switch (content_type) {
|
|
159
177
|
case "model/gltf+json":
|
|
160
|
-
return "gltf";
|
|
161
178
|
case "model/gltf-binary":
|
|
162
|
-
return "glb";
|
|
163
179
|
case "model/vrm":
|
|
164
|
-
return "vrm";
|
|
165
180
|
case "model/vnd.usdz+zip":
|
|
166
|
-
return "usdz";
|
|
167
181
|
case "model/vnd.usd+zip":
|
|
168
|
-
return "usd";
|
|
169
182
|
case "model/vnd.usda+zip":
|
|
170
|
-
return "usda";
|
|
171
183
|
case "model/fbx":
|
|
172
184
|
case "model/vnd.autodesk.fbx":
|
|
173
|
-
return "fbx";
|
|
174
185
|
case "model/obj":
|
|
175
|
-
return
|
|
186
|
+
return content_type;
|
|
176
187
|
// case "model/stl":
|
|
177
188
|
// return "stl";
|
|
178
189
|
case "text/plain":
|
|
@@ -205,7 +216,7 @@ export function tryDetermineFileTypeFromBinary(url: string, data: ArrayBuffer, r
|
|
|
205
216
|
// return "gltf";
|
|
206
217
|
// }
|
|
207
218
|
|
|
208
|
-
for (const callback of
|
|
219
|
+
for (const callback of registeredMimetypeCallbacks) {
|
|
209
220
|
const mimetype = callback({
|
|
210
221
|
url: url,
|
|
211
222
|
response: response,
|
|
@@ -110,6 +110,21 @@ export class ContactShadows extends Behaviour {
|
|
|
110
110
|
*/
|
|
111
111
|
minSize?: Partial<Vec3>;
|
|
112
112
|
|
|
113
|
+
/**
|
|
114
|
+
* When enabled the shadows will not be updated automatically. Use `needsUpdate()` to update the shadows manually.
|
|
115
|
+
* This is useful when you want to update the shadows only when the scene changes.
|
|
116
|
+
*/
|
|
117
|
+
manualUpdate: boolean = false;
|
|
118
|
+
/**
|
|
119
|
+
* Call this method to update the shadows manually. The update will be done in the next frame.
|
|
120
|
+
*/
|
|
121
|
+
set needsUpdate(val: boolean) {
|
|
122
|
+
this._needsUpdate = val;
|
|
123
|
+
}
|
|
124
|
+
get needsUpdate(): boolean {
|
|
125
|
+
return this._needsUpdate;
|
|
126
|
+
}
|
|
127
|
+
private _needsUpdate: boolean = false;
|
|
113
128
|
|
|
114
129
|
/** All shadow objects are parented to this object.
|
|
115
130
|
* The gameObject itself should not be transformed because we want the ContactShadows object e.g. also have a GroundProjectedEnv component
|
|
@@ -288,6 +303,10 @@ export class ContactShadows extends Behaviour {
|
|
|
288
303
|
else this.applyMinSize();
|
|
289
304
|
}
|
|
290
305
|
|
|
306
|
+
onEnable(): void {
|
|
307
|
+
this._needsUpdate = true;
|
|
308
|
+
}
|
|
309
|
+
|
|
291
310
|
/** @internal */
|
|
292
311
|
onDestroy(): void {
|
|
293
312
|
const instance = ContactShadows._instances.get(this.context);
|
|
@@ -313,6 +332,11 @@ export class ContactShadows extends Behaviour {
|
|
|
313
332
|
/** @internal */
|
|
314
333
|
onBeforeRender(_frame: XRFrame | null): void {
|
|
315
334
|
|
|
335
|
+
if (this.manualUpdate) {
|
|
336
|
+
if (!this._needsUpdate) return;
|
|
337
|
+
}
|
|
338
|
+
this._needsUpdate = false;
|
|
339
|
+
|
|
316
340
|
if (!this.renderTarget || !this.renderTargetBlur ||
|
|
317
341
|
!this.depthMaterial || !this.shadowCamera ||
|
|
318
342
|
!this.blurPlane || !this.shadowGroup || !this.plane ||
|
|
@@ -3,12 +3,10 @@ import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
|
3
3
|
import { XRControllerModelFactory } from "three/examples/jsm/webxr/XRControllerModelFactory.js";
|
|
4
4
|
import { XRHandMeshModel } from "three/examples/jsm/webxr/XRHandMeshModel.js";
|
|
5
5
|
|
|
6
|
-
import { showBalloonWarning } from "../../../engine/debug/index.js";
|
|
7
6
|
import { AssetReference } from "../../../engine/engine_addressables.js";
|
|
8
7
|
import { setDontDestroy } from "../../../engine/engine_gameobject.js";
|
|
9
8
|
import { Gizmos } from "../../../engine/engine_gizmos.js";
|
|
10
9
|
import { getLoader } from "../../../engine/engine_gltf.js";
|
|
11
|
-
import { createBuiltinComponents } from "../../../engine/engine_gltf_builtin_components.js";
|
|
12
10
|
import { addDracoAndKTX2Loaders } from "../../../engine/engine_loaders.gltf.js";
|
|
13
11
|
import { serializable } from "../../../engine/engine_serialization_decorator.js";
|
|
14
12
|
import type { IGameObject, SourceIdentifier } from "../../../engine/engine_types.js";
|