@@ -210,8 +210,8 @@
|
|
210
210
|
return this.internalOnPlay(act, options);
|
211
211
|
}
|
212
212
|
}
|
213
|
-
if (!
|
214
|
-
console.warn("Clip is no AnimationClip", clip
|
213
|
+
if (!clip.tracks) {
|
214
|
+
console.warn("Clip is no AnimationClip", clip)
|
215
215
|
return;
|
216
216
|
}
|
217
217
|
const act = this.mixer.clipAction(clip);
|
@@ -2,6 +2,7 @@
|
|
2
2
|
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js'
|
3
3
|
import { type GLTF, GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
|
4
4
|
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js';
|
5
|
+
import { USDZLoader } from 'three/examples/jsm/loaders/USDZLoader.js';
|
5
6
|
|
6
7
|
import { showBalloonMessage } from "./debug/index.js";
|
7
8
|
import { getLoader, type INeedleGltfLoader, registerLoader } from "./engine_gltf.js";
|
@@ -111,7 +112,7 @@
|
|
111
112
|
return await tryDetermineFileTypeFromURL(url) || "unknown";
|
112
113
|
}
|
113
114
|
|
114
|
-
export async function createLoader(url: string, context: Context): Promise<GLTFLoader | FBXLoader | OBJLoader | null> {
|
115
|
+
export async function createLoader(url: string, context: Context): Promise<GLTFLoader | FBXLoader | USDZLoader | OBJLoader | null> {
|
115
116
|
|
116
117
|
const type = await determineFileTypeFromURL(url);
|
117
118
|
|
@@ -123,10 +124,16 @@
|
|
123
124
|
return new FBXLoader();
|
124
125
|
case "obj":
|
125
126
|
return new OBJLoader();
|
127
|
+
case "usd":
|
128
|
+
console.warn("USD files are not supported.")
|
129
|
+
return null;
|
130
|
+
break;
|
126
131
|
case "usdz":
|
127
|
-
console.warn("USDZ
|
132
|
+
console.warn("USDZ files are not supported.")
|
128
133
|
return null;
|
134
|
+
// return new USDZLoader();
|
129
135
|
default:
|
136
|
+
console.warn("Unknown file type:", type);
|
130
137
|
case "gltf":
|
131
138
|
case "glb":
|
132
139
|
const loader = new GLTFLoader();
|
@@ -321,20 +328,22 @@
|
|
321
328
|
|
322
329
|
function postprocessLoadedFile(loader: Loader, result: Object3D | GLTF) {
|
323
330
|
|
324
|
-
if (result
|
325
|
-
|
331
|
+
if ((result as Object3D)?.isObject3D) {
|
332
|
+
const obj = result as Object3D;
|
333
|
+
|
326
334
|
if (loader instanceof FBXLoader) {
|
327
|
-
|
335
|
+
obj.traverse((child) => {
|
336
|
+
const mesh = child as Mesh;
|
328
337
|
|
329
338
|
// See https://github.com/needle-tools/three.js/blob/b8df3843ff123ac9dc0ed0d3ccc5b568f840c804/examples/webgl_loader_multiple.html#L377
|
330
|
-
if (
|
331
|
-
postprocessFBXMaterials(
|
339
|
+
if (mesh?.isMesh) {
|
340
|
+
postprocessFBXMaterials(mesh, mesh.material as Material);
|
332
341
|
}
|
333
342
|
});
|
334
343
|
}
|
335
344
|
else if (loader instanceof OBJLoader) {
|
336
345
|
|
337
|
-
|
346
|
+
obj.traverse(_child => {
|
338
347
|
|
339
348
|
// TODO: Needs testing
|
340
349
|
|
@@ -5,7 +5,7 @@
|
|
5
5
|
/**
|
6
6
|
* The supported file types that can be determined by the engine. Used in {@link tryDetermineFileTypeFromURL} and {@link tryDetermineFileTypeFromBinary}
|
7
7
|
*/
|
8
|
-
export declare type FileType = "gltf" | "glb" | "fbx" | "obj" | "usdz" | "unknown";
|
8
|
+
export declare type FileType = "gltf" | "glb" | "fbx" | "obj" | "usdz" | "usd" | "unknown";
|
9
9
|
|
10
10
|
/**
|
11
11
|
* Tries to determine the file type of a file from its URL
|
@@ -27,7 +27,7 @@
|
|
27
27
|
if (header?.ok) {
|
28
28
|
const data = await header.arrayBuffer();
|
29
29
|
const res = tryDetermineFileTypeFromBinary(data);
|
30
|
-
if (debug) console.log("Determined file type from header"
|
30
|
+
if (debug) console.log("Determined file type from header: " + res);
|
31
31
|
return res;
|
32
32
|
}
|
33
33
|
|
@@ -50,18 +50,22 @@
|
|
50
50
|
console.warn("Trying to determine file type from binary data\n", "\"" + new TextDecoder().decode(data) + "\"\n", bytes);
|
51
51
|
}
|
52
52
|
|
53
|
+
// GLTF or GLB
|
54
|
+
if (bytes[0] == 103 && bytes[1] == 108 && bytes[2] == 84 && bytes[3] == 70) {
|
55
|
+
return "glb";
|
56
|
+
}
|
53
57
|
// USDZ
|
54
58
|
if (bytes[0] == 80 && bytes[1] == 75 && bytes[2] == 3 && bytes[3] == 4) {
|
55
59
|
return "usdz";
|
56
60
|
}
|
61
|
+
// USD
|
62
|
+
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) {
|
63
|
+
return "usd";
|
64
|
+
}
|
57
65
|
// FBX
|
58
66
|
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) {
|
59
67
|
return "fbx";
|
60
68
|
}
|
61
|
-
// GLTF or GLB
|
62
|
-
else if (bytes[0] == 103 && bytes[1] == 108 && bytes[2] == 84 && bytes[3] == 70) {
|
63
|
-
return "glb";
|
64
|
-
}
|
65
69
|
// 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
|
66
70
|
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) {
|
67
71
|
// const text = new TextDecoder().decode(data.slice(0, 9));
|
@@ -8,30 +8,30 @@
|
|
8
8
|
export type userSettings = {
|
9
9
|
|
10
10
|
/** disable needle asap plugin */
|
11
|
-
noAsap
|
11
|
+
noAsap?: boolean;
|
12
12
|
|
13
13
|
/** disable vite.alias modification */
|
14
|
-
noAlias
|
14
|
+
noAlias?: boolean;
|
15
15
|
/** disable automatic copying of files to include and output directory (dist) */
|
16
|
-
noCopy
|
16
|
+
noCopy?: boolean;
|
17
17
|
/** set to false to tree-shake rapier physics engine to the reduce bundle size */
|
18
|
-
useRapier
|
19
|
-
noDependencyWatcher
|
18
|
+
useRapier?: boolean;
|
19
|
+
noDependencyWatcher?: boolean;
|
20
20
|
/** set to false to suppress editor-sync package installation and connection */
|
21
|
-
dontInstallEditor
|
21
|
+
dontInstallEditor?: boolean;
|
22
22
|
/** set to false to prevent meta.html modifications (vite only) */
|
23
|
-
allowMetaPlugin
|
23
|
+
allowMetaPlugin?: boolean;
|
24
24
|
/** set to true to prevent injecting peerjs `parcelRequire` global variable declaration */
|
25
|
-
noPeer
|
25
|
+
noPeer?: boolean;
|
26
26
|
/** set to true to disable reload plugin */
|
27
|
-
noReload
|
27
|
+
noReload?: boolean;
|
28
28
|
/** Set to false to disable hot reload for the needle plugin. */
|
29
|
-
allowHotReload
|
29
|
+
allowHotReload?: boolean;
|
30
30
|
|
31
|
-
noCodegenTransform
|
32
|
-
noFacebookInstantGames
|
31
|
+
noCodegenTransform?: boolean;
|
32
|
+
noFacebookInstantGames?: boolean;
|
33
33
|
/** Set to true to create an imports.log file that shows all module imports. The file is generated when stopping the server. */
|
34
|
-
logModuleImportChains
|
34
|
+
logModuleImportChains?: boolean;
|
35
35
|
|
36
36
|
/** Set to true to disable generating the buildinfo.json file in your output directory */
|
37
37
|
noBuildInfo?: boolean;
|
@@ -45,7 +45,7 @@
|
|
45
45
|
buildPipelineVersion?: string;
|
46
46
|
|
47
47
|
/** required for @serializable https://github.com/vitejs/vite/issues/13736 */
|
48
|
-
vite44Hack
|
48
|
+
vite44Hack?: boolean;
|
49
49
|
|
50
50
|
/** set to true to disable poster generation */
|
51
51
|
noPoster?: boolean;
|
@@ -61,7 +61,7 @@
|
|
61
61
|
pwa?: undefined;
|
62
62
|
|
63
63
|
/** used by nextjs config to forward the webpack module */
|
64
|
-
modules
|
64
|
+
modules?: needleModules;
|
65
65
|
|
66
66
|
/**
|
67
67
|
* Use to activate a needle engine license
|