@@ -976,13 +976,6 @@
|
|
976
976
|
break;
|
977
977
|
}
|
978
978
|
const file = files[i];
|
979
|
-
if (!file.includes(".glb") && !file.includes(".gltf")) {
|
980
|
-
// TODO this may not be true if the URL just forwards to a proper GLB file resource
|
981
|
-
const warning = `Needle Engine: found suspicious src "${file}"`;
|
982
|
-
console.warn(warning);
|
983
|
-
if (isLocalNetwork()) showBalloonWarning(warning);
|
984
|
-
}
|
985
|
-
|
986
979
|
args?.onLoadingStart?.call(this, i, file);
|
987
980
|
if (debug) console.log("Context Load " + file);
|
988
981
|
const res = await loader.loadSync(this, file, file, loadingHash, prog => {
|
@@ -66,7 +66,8 @@
|
|
66
66
|
private _isInvoking: boolean = false;
|
67
67
|
|
68
68
|
// TODO: can we make functions serializable?
|
69
|
-
private methods: CallInfo[] = [];
|
69
|
+
private readonly methods: CallInfo[] = [];
|
70
|
+
private readonly _methodsCopy: CallInfo[] = [];
|
70
71
|
|
71
72
|
constructor(evts?: CallInfo[]) {
|
72
73
|
this.methods = evts ?? [];
|
@@ -84,8 +85,12 @@
|
|
84
85
|
this._isInvoking = true;
|
85
86
|
try {
|
86
87
|
|
88
|
+
// make a copy of the methods array to avoid issues when removing listeners during invocation
|
89
|
+
this._methodsCopy.length = 0;
|
90
|
+
this._methodsCopy.push(...this.methods);
|
91
|
+
|
87
92
|
// first invoke all the methods that were subscribed to this eventlist
|
88
|
-
for (const m of this.
|
93
|
+
for (const m of this._methodsCopy) {
|
89
94
|
m.invoke(...args);
|
90
95
|
}
|
91
96
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { Box3, DoubleSide, Group, Mesh, MeshBasicMaterial, ShapeGeometry, Vector3 } from "three";
|
2
|
-
import { SVGLoader } from "three/examples/jsm/loaders/SVGLoader";
|
2
|
+
import { SVGLoader } from "three/examples/jsm/loaders/SVGLoader.js";
|
3
3
|
|
4
4
|
|
5
5
|
const logoSvgString = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 160 187.74"><defs><linearGradient id="a" x1="89.64" y1="184.81" x2="90.48" y2="21.85" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#62d399"/><stop offset=".51" stop-color="#acd842"/><stop offset=".9" stop-color="#d7db0a"/></linearGradient><linearGradient id="b" x1="69.68" y1="178.9" x2="68.08" y2="16.77" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#0ba398"/><stop offset=".5" stop-color="#4ca352"/><stop offset="1" stop-color="#76a30a"/></linearGradient><linearGradient id="c" x1="36.6" y1="152.17" x2="34.7" y2="84.19" gradientUnits="userSpaceOnUse"><stop offset=".19" stop-color="#36a382"/><stop offset=".54" stop-color="#49a459"/><stop offset="1" stop-color="#76a30b"/></linearGradient><linearGradient id="d" x1="15.82" y1="153.24" x2="18" y2="90.86" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#267880"/><stop offset=".51" stop-color="#457a5c"/><stop offset="1" stop-color="#717516"/></linearGradient><linearGradient id="e" x1="135.08" y1="135.43" x2="148.93" y2="63.47" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#b0d939"/><stop offset="1" stop-color="#eadb04"/></linearGradient><linearGradient id="f" x1="-4163.25" y1="2285.12" x2="-4160.81" y2="2215.34" gradientTransform="rotate(20 4088.49 13316.712)" gradientUnits="userSpaceOnUse"><stop offset=".17" stop-color="#74af52"/><stop offset=".48" stop-color="#99be32"/><stop offset="1" stop-color="#c0c40a"/></linearGradient><symbol id="g" viewBox="0 0 160 187.74"><path style="fill:url(#a)" d="M79.32 36.98v150.76L95 174.54l6.59-156.31-22.27 18.75z"/><path style="fill:url(#b)" d="M79.32 36.98 57.05 18.23l6.59 156.31 15.68 13.2V36.98z"/><path style="fill:url(#c)" d="m25.19 104.83 8.63 49.04 12.5-14.95-2.46-56.42-18.67 22.33z"/><path style="fill:url(#d)" d="M25.19 104.83 0 90.24l16.97 53.86 16.85 9.77-8.63-49.04z"/><path style="fill:#9c3" d="M43.86 82.5 18.69 67.98 0 90.24l25.18 14.59L43.86 82.5z"/><path style="fill:url(#e)" d="m134.82 78.69-9.97 56.5 15.58-9.04L160 64.1l-25.18 14.59z"/><path style="fill:url(#f)" d="m134.82 78.69-18.68-22.33-2.86 65 11.57 13.83 9.97-56.5z"/><path style="fill:#ffe113" d="m160 64.1-18.69-22.26-25.17 14.52 18.67 22.33L160 64.1z"/><path style="fill:#f3e600" d="M101.59 18.23 79.32 0 57.05 18.23l22.27 18.75 22.27-18.75z"/></symbol></defs><use width="160" height="187.74" xlink:href="#g"/></svg>`;
|
@@ -240,7 +240,7 @@
|
|
240
240
|
}
|
241
241
|
this.onProgressiveLoadEnd(info);
|
242
242
|
return geo;
|
243
|
-
|
243
|
+
|
244
244
|
}).catch(err => {
|
245
245
|
this.onProgressiveLoadEnd(info);
|
246
246
|
console.error("Error loading mesh LOD", mesh, err);
|
@@ -353,8 +353,8 @@
|
|
353
353
|
this.onProgressiveLoadEnd(info);
|
354
354
|
return tex;
|
355
355
|
}
|
356
|
-
else if (debug) {
|
357
|
-
console.warn("No LOD found for",
|
356
|
+
else if (debug == "verbose") {
|
357
|
+
console.warn("No LOD found for", current, level);
|
358
358
|
}
|
359
359
|
|
360
360
|
this.onProgressiveLoadEnd(info);
|
@@ -388,59 +388,30 @@
|
|
388
388
|
if (textureInfo?.extensions) {
|
389
389
|
const ext: NEEDLE_progressive_texture_model = textureInfo?.extensions[EXTENSION_NAME];
|
390
390
|
if (ext) {
|
391
|
-
const
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
console.error(`Error loading progressive texture ${index}\n`, err);
|
407
|
-
});
|
408
|
-
}
|
409
|
-
}
|
410
|
-
});
|
411
|
-
|
412
|
-
this.parser.json.meshes?.forEach((meshInfo, index) => {
|
413
|
-
if (meshInfo?.extensions) {
|
414
|
-
const ext = meshInfo?.extensions[EXTENSION_NAME] as NEEDLE_progressive_mesh_model;
|
415
|
-
if (ext && ext.lods) {
|
416
|
-
const prom = this.parser.getDependency("mesh", index);
|
417
|
-
prom.then((obj: Mesh | Group) => {
|
418
|
-
if (debug) console.log("> Progressive: register mesh", index, obj.name, ext, obj.uuid, obj);
|
419
|
-
const LODKEY = obj.uuid;
|
420
|
-
const LODLEVEL = ext.lods.length;
|
421
|
-
if (obj instanceof Mesh) {
|
422
|
-
applyMeshLOD(LODKEY, obj, LODLEVEL, undefined, ext);
|
423
|
-
NEEDLE_progressive.lowresCache.set(LODKEY, obj.geometry);
|
424
|
-
}
|
425
|
-
else {
|
426
|
-
const geometries = new Array<BufferGeometry>();
|
427
|
-
for (let i = 0; i < obj.children.length; i++) {
|
428
|
-
const child = obj.children[i];
|
429
|
-
if (child instanceof Mesh) {
|
430
|
-
geometries.push(child.geometry as BufferGeometry);
|
431
|
-
applyMeshLOD(LODKEY, child, LODLEVEL, i, ext);
|
432
|
-
}
|
391
|
+
for (const key of this.parser.associations.keys()) {
|
392
|
+
if (key instanceof Texture) {
|
393
|
+
const val = this.parser.associations.get(key) as { textures: number };
|
394
|
+
if (val.textures === index) {
|
395
|
+
const tex = key;
|
396
|
+
if (debug)
|
397
|
+
console.log("> Progressive: register texture", index, tex.name, tex.uuid, tex, ext);
|
398
|
+
// Put the extension info into the source (seems like tiled textures are cloned and the userdata etc is not properly copied BUT the source of course is not cloned)
|
399
|
+
// see https://github.com/needle-tools/needle-engine-support/issues/133
|
400
|
+
if (tex.source)
|
401
|
+
tex.source[$progressiveTextureExtension] = ext;
|
402
|
+
const LODKEY = tex.uuid;
|
403
|
+
NEEDLE_progressive.assignLODInformation(tex, LODKEY, 0, 0, undefined);
|
404
|
+
NEEDLE_progressive.lodInfos.set(LODKEY, ext);
|
405
|
+
NEEDLE_progressive.lowresCache.set(LODKEY, tex);
|
433
406
|
}
|
434
|
-
NEEDLE_progressive.lowresCache.set(LODKEY, geometries);
|
435
407
|
}
|
436
|
-
|
437
|
-
}
|
438
|
-
console.error(`Error loading progressive mesh ${index}\n`, err);
|
439
|
-
});
|
408
|
+
|
409
|
+
}
|
440
410
|
}
|
441
411
|
}
|
442
412
|
});
|
443
413
|
|
414
|
+
|
444
415
|
const applyMeshLOD = (key: string, mesh: Mesh, level: number, index: number | undefined, ext: NEEDLE_progressive_mesh_model) => {
|
445
416
|
const geometry = mesh.geometry as BufferGeometry;
|
446
417
|
geometry["needle:raycast-mesh"] = true;
|
@@ -458,7 +429,41 @@
|
|
458
429
|
NEEDLE_progressive.assignLODInformation(geometry, key, level, index, ext.density);
|
459
430
|
NEEDLE_progressive.lodInfos.set(key, ext);
|
460
431
|
};
|
432
|
+
this.parser.json.meshes?.forEach((meshInfo, index: number) => {
|
433
|
+
if (meshInfo?.extensions) {
|
434
|
+
const ext = meshInfo?.extensions[EXTENSION_NAME] as NEEDLE_progressive_mesh_model;
|
435
|
+
if (ext && ext.lods) {
|
436
|
+
for (const key of this.parser.associations.keys()) {
|
437
|
+
if (key instanceof Mesh || key instanceof Group) {
|
438
|
+
const val = this.parser.associations.get(key) as { meshes: number };
|
439
|
+
if (val.meshes === index) {
|
440
|
+
const obj = key;
|
441
|
+
if (debug) console.log("> Progressive: register mesh", index, obj.name, ext, obj.uuid, obj);
|
442
|
+
const LODKEY = obj.uuid;
|
443
|
+
const LODLEVEL = ext.lods.length;
|
444
|
+
if (obj instanceof Mesh) {
|
445
|
+
applyMeshLOD(LODKEY, obj, LODLEVEL, undefined, ext);
|
446
|
+
NEEDLE_progressive.lowresCache.set(LODKEY, obj.geometry);
|
447
|
+
}
|
448
|
+
else {
|
449
|
+
const geometries = new Array<BufferGeometry>();
|
450
|
+
for (let i = 0; i < obj.children.length; i++) {
|
451
|
+
const child = obj.children[i];
|
452
|
+
if (child instanceof Mesh) {
|
453
|
+
geometries.push(child.geometry as BufferGeometry);
|
454
|
+
applyMeshLOD(LODKEY, child, LODLEVEL, i, ext);
|
455
|
+
}
|
456
|
+
}
|
457
|
+
NEEDLE_progressive.lowresCache.set(LODKEY, geometries);
|
458
|
+
}
|
459
|
+
}
|
460
|
+
}
|
461
|
+
}
|
461
462
|
|
463
|
+
}
|
464
|
+
}
|
465
|
+
});
|
466
|
+
|
462
467
|
return null;
|
463
468
|
}
|
464
469
|
|
@@ -709,19 +714,24 @@
|
|
709
714
|
return res?.userData?.LODS || null;
|
710
715
|
}
|
711
716
|
|
717
|
+
private static readonly _copiedTextures: WeakMap<Texture, Texture> = new Map();
|
718
|
+
|
712
719
|
private static copySettings(source: Texture, target: Texture): Texture {
|
720
|
+
// don't copy again if the texture was processed before
|
721
|
+
const existingClone = this._copiedTextures.get(source);
|
722
|
+
if (existingClone) {
|
723
|
+
return existingClone;
|
724
|
+
}
|
713
725
|
// We need to clone e.g. when the same texture is used multiple times (but with e.g. different wrap settings)
|
714
726
|
// This is relatively cheap since it only stores settings
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
res.copy(source);
|
719
|
-
res.source = src;
|
720
|
-
res.mipmaps = mips;
|
727
|
+
// This should only happen once ever for every texture
|
728
|
+
target = target.clone();
|
729
|
+
this._copiedTextures.set(source, target);
|
721
730
|
// we re-use the offset and repeat settings because it might be animated
|
722
|
-
|
723
|
-
|
724
|
-
|
731
|
+
target.offset = source.offset;
|
732
|
+
target.repeat = source.repeat;
|
733
|
+
target.colorSpace = source.colorSpace;
|
734
|
+
return target;
|
725
735
|
|
726
736
|
}
|
727
737
|
|
@@ -830,6 +830,8 @@
|
|
830
830
|
}
|
831
831
|
|
832
832
|
private _lastLodLevel = -1;
|
833
|
+
private _lastScreenCoverage = 0;
|
834
|
+
private _lastScreenspaceVolume = 0;
|
833
835
|
private _nextLodTestTime = 0;
|
834
836
|
private _randomLodLevelCheckFrameOffset = Math.floor(Math.random() * 100);
|
835
837
|
private readonly _sphere = new Sphere();
|
@@ -842,12 +844,15 @@
|
|
842
844
|
// if (this.isInstancingActive) return 0;
|
843
845
|
|
844
846
|
const interval = 3;
|
845
|
-
if (!force && (this.context.time.frame + this._randomLodLevelCheckFrameOffset) % interval != 0) {
|
846
|
-
return this._lastLodLevel;
|
847
|
-
}
|
848
847
|
|
849
|
-
if (
|
850
|
-
|
848
|
+
if (!debugProgressiveLoading) {
|
849
|
+
if (!force && (this.context.time.frame + this._randomLodLevelCheckFrameOffset) % interval != 0) {
|
850
|
+
return this._lastLodLevel;
|
851
|
+
}
|
852
|
+
|
853
|
+
if (this.context.time.realtimeSinceStartup < this._nextLodTestTime) {
|
854
|
+
return this._lastLodLevel;
|
855
|
+
}
|
851
856
|
}
|
852
857
|
|
853
858
|
const maxLevel = 10;
|
@@ -875,6 +880,9 @@
|
|
875
880
|
if (lodsInfo?.lods && lodsInfo?.lods.length > 0)
|
876
881
|
meshDensity = (Math.log2(lodsInfo.lods[0].density || 0) / 2) - 8;
|
877
882
|
else if(debugProgressiveLoading) console.warn("No LOD information found...", mesh.name);
|
883
|
+
if (debugProgressiveLoading) {
|
884
|
+
// ^console.log("Looking at LOD levels", lodsInfo)
|
885
|
+
}
|
878
886
|
|
879
887
|
// TODO: we can skip all this if we dont have any LOD information - we can ask the progressive extension for that
|
880
888
|
const frustum = this.context.mainCameraComponent?.getFrustum();
|
@@ -907,14 +915,47 @@
|
|
907
915
|
// calculate size on screen
|
908
916
|
this._box.copy(box);
|
909
917
|
this._box.applyMatrix4(mesh.matrixWorld);
|
910
|
-
this.
|
918
|
+
const mat = this.context.mainCameraComponent!.getProjectionScreenMatrix(Renderer.tempMatrix);
|
919
|
+
this._box.applyMatrix4(mat);
|
911
920
|
// Gizmos.DrawWireBox(this._box.getCenter(getTempVector()), this._box.getSize(getTempVector()), 0x00ff00, .02);
|
912
921
|
const boxSize = this._box.getSize(getTempVector());
|
913
922
|
// const verticalFov = this.context.mainCamera.fov;
|
914
923
|
let screenSize = boxSize.y / 2;// / (2 * Math.atan(Math.PI * verticalFov / 360));
|
915
924
|
// if (mesh.name.startsWith("Statue_")) console.log(mesh.name, "ScreenSize", screenSize, "Density", meshDensity, mesh.geometry.index!.count / 3);
|
916
925
|
screenSize /= Math.pow(2, meshDensity - .5);
|
926
|
+
this._lastScreenCoverage = Math.max(boxSize.x, boxSize.y, boxSize.z) / 2;
|
927
|
+
this._lastScreenspaceVolume = boxSize.x * boxSize.y * boxSize.z / 8;
|
917
928
|
|
929
|
+
// draw screen size box
|
930
|
+
if (debugProgressiveLoading) {
|
931
|
+
mat.invert();
|
932
|
+
|
933
|
+
// get box corners, transform with camera space, and draw as quad lines
|
934
|
+
const corner0 = getTempVector();
|
935
|
+
corner0.copy(this._box.min);
|
936
|
+
const corner1 = getTempVector();
|
937
|
+
corner1.copy(this._box.max);
|
938
|
+
corner1.x = corner0.x;
|
939
|
+
const corner2 = getTempVector();
|
940
|
+
corner2.copy(this._box.max);
|
941
|
+
corner2.y = corner0.y;
|
942
|
+
const corner3 = getTempVector();
|
943
|
+
corner3.copy(this._box.max);
|
944
|
+
const z = (corner0.z + corner3.z) * 0.5;
|
945
|
+
|
946
|
+
corner0.z = corner1.z = corner2.z = corner3.z = z;
|
947
|
+
|
948
|
+
corner0.applyMatrix4(mat);
|
949
|
+
corner1.applyMatrix4(mat);
|
950
|
+
corner2.applyMatrix4(mat);
|
951
|
+
corner3.applyMatrix4(mat);
|
952
|
+
|
953
|
+
Gizmos.DrawLine(corner0, corner1, 0x0000ff);
|
954
|
+
Gizmos.DrawLine(corner0, corner2, 0x0000ff);
|
955
|
+
Gizmos.DrawLine(corner1, corner3, 0x0000ff);
|
956
|
+
Gizmos.DrawLine(corner2, corner3, 0x0000ff);
|
957
|
+
}
|
958
|
+
|
918
959
|
// screenSize *= .2;
|
919
960
|
|
920
961
|
let expectedLevel = 999;
|
@@ -929,8 +970,9 @@
|
|
929
970
|
// expectedLevel -= meshDensity - 5;
|
930
971
|
// expectedLevel += meshDensity;
|
931
972
|
const isLowerLod = expectedLevel < level;
|
932
|
-
if (isLowerLod)
|
973
|
+
if (isLowerLod) {
|
933
974
|
level = expectedLevel;
|
975
|
+
}
|
934
976
|
}
|
935
977
|
}
|
936
978
|
}
|
@@ -950,7 +992,8 @@
|
|
950
992
|
}
|
951
993
|
|
952
994
|
private drawGizmoLodLevel(changed: boolean) {
|
953
|
-
|
995
|
+
// Will be (maxLod + 1) (11) if no lod level is found
|
996
|
+
const _level = this._lastLodLevel;
|
954
997
|
const camForward = (this.context.mainCamera as any as IGameObject).worldForward;
|
955
998
|
const camWorld = (this.context.mainCamera as any as IGameObject).worldPosition;
|
956
999
|
for (const mesh of this.sharedMeshes) {
|
@@ -964,11 +1007,49 @@
|
|
964
1007
|
const colors = ["#76c43e", "#bcc43e", "#c4ac3e", "#c4673e", "#ff3e3e"];
|
965
1008
|
// if the lod has changed we just want to draw the gizmo for the changed mesh
|
966
1009
|
if (changed) {
|
967
|
-
Gizmos.DrawWireSphere(boundsCenter, radius, colors[
|
1010
|
+
Gizmos.DrawWireSphere(boundsCenter, radius, colors[_level], .1);
|
968
1011
|
}
|
969
1012
|
else {
|
970
|
-
//
|
971
|
-
|
1013
|
+
// Mesh Density is calculated as: triangle count per square meter of surface area, normalized to the bounding box size of the model.
|
1014
|
+
// Our goal for automatic switching of LODs is that the resulting triangle count per screen area is constant.
|
1015
|
+
// We assume a uniform distribution of triangles over the surface area; which means that
|
1016
|
+
// we can express a ratio of "screen area to surface area".
|
1017
|
+
const triangleCount = mesh.geometry.index!.count / 3;
|
1018
|
+
const lods = NEEDLE_progressive.getMeshLODInformation(mesh.geometry)?.lods;
|
1019
|
+
const level = lods ? Math.min(lods?.length - 1, _level) : 0;
|
1020
|
+
let allLods = "";
|
1021
|
+
if (lods) {
|
1022
|
+
for (let i = 0; i < lods.length; i++) {
|
1023
|
+
allLods += lods[i].density.toFixed(0) + ",";
|
1024
|
+
}
|
1025
|
+
}
|
1026
|
+
const density = lods ? lods[level]?.density : -1;
|
1027
|
+
const box = mesh.geometry.boundingBox;
|
1028
|
+
const boxSize = box ? box.getSize(getTempVector()) : new Vector3();
|
1029
|
+
const maxBoxSize = Math.max(boxSize.x, boxSize.y, boxSize.z);
|
1030
|
+
|
1031
|
+
// Surface area is in local space of the model;
|
1032
|
+
// we need to scale it by the model's world scale and the model's geometry bounding box size.
|
1033
|
+
const ws = mesh.getWorldScale(getTempVector());
|
1034
|
+
const wsMedian = (ws.x + ws.y + ws.z) / 3;
|
1035
|
+
// Area is squared, so both maxBoxSize and wsMedian are squared here
|
1036
|
+
// Here, we're basically reverting the calculations that have happened in the pipeline for debugging.
|
1037
|
+
const surfaceArea = 1 / density * triangleCount * (maxBoxSize * maxBoxSize) * (wsMedian * wsMedian);
|
1038
|
+
const idealDensity = this._lastScreenCoverage;
|
1039
|
+
let text = "LOD " + level;
|
1040
|
+
if(debugProgressiveLoading == "density"){
|
1041
|
+
text += "\n" +
|
1042
|
+
triangleCount + " tris\n" +
|
1043
|
+
(density / this._lastScreenCoverage * 0.01).toFixed(0) + " dens\n" +
|
1044
|
+
(this._lastScreenCoverage * 100).toFixed(1) + "% cov" + "\n" +
|
1045
|
+
(this._lastScreenspaceVolume * 100).toFixed(2) + " m3" + "\n" +
|
1046
|
+
(surfaceArea).toFixed(2) + " m2" + "\n" +
|
1047
|
+
(ws.x).toFixed(2) + "x" + " " + maxBoxSize.toFixed(2) + "b" + "\n" +
|
1048
|
+
allLods + "\n" +
|
1049
|
+
"----" + "\n" +
|
1050
|
+
"1000" + " ideal dens";
|
1051
|
+
}
|
1052
|
+
|
972
1053
|
// if (helper) {
|
973
1054
|
// helper?.setText(text);
|
974
1055
|
// continue;
|
@@ -978,8 +1059,8 @@
|
|
978
1059
|
const vertexCount = mesh.geometry.index!.count / 3;
|
979
1060
|
// const vertexCountFactor = Math.min(1, vertexCount / 1000);
|
980
1061
|
const col = colors[Math.min(colors.length - 1, level)] + "88";
|
981
|
-
const size = Math.min(10, radius);
|
982
|
-
Gizmos.DrawLabel(pos, text, distance * .
|
1062
|
+
// const size = Math.min(10, radius);
|
1063
|
+
Gizmos.DrawLabel(pos, text, distance * .01, undefined, 0xffffff, col);
|
983
1064
|
// mesh["LOD_level_label"] = helper;
|
984
1065
|
}
|
985
1066
|
|
@@ -90,8 +90,10 @@
|
|
90
90
|
if (!existingUSDZExporter) {
|
91
91
|
// if no USDZ Exporter is found we add one and assign the scene to be exported
|
92
92
|
if (debug) console.log("WebXR: Adding USDZExporter");
|
93
|
-
this._usdzExporter = GameObject.
|
93
|
+
this._usdzExporter = GameObject.addComponent(this.gameObject, USDZExporter);
|
94
94
|
this._usdzExporter.objectToExport = this.context.scene;
|
95
|
+
this._usdzExporter.autoExportAnimations = true;
|
96
|
+
this._usdzExporter.autoExportAudioSources = true;
|
95
97
|
}
|
96
98
|
}
|