redhotmagma-visualization 1.44.10 → 1.45.0
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/Constants.js +1 -0
- package/DevApp.js +14 -0
- package/Three/Three2D.js +25 -4
- package/Three/Three3D.js +121 -83
- package/Three/Three3DScene.js +132 -58
- package/Utils/createBakedShadow.js +1 -2
- package/Utils/initTextureCanvas.js +3 -1
- package/Utils/optimizeTextureImage.js +1 -1
- package/Utils/rememberCameraViewOffset.js +12 -7
- package/Utils/restrictCameraMovement.js +2 -2
- package/package.json +3 -3
- package/public/libs/draco/README.md +2 -2
- package/public/libs/draco/draco_decoder.js +17 -35
- package/public/libs/draco/draco_decoder.wasm +0 -0
- package/public/libs/draco/draco_wasm_wrapper.js +117 -104
- package/public/libs/draco/gltf/draco_decoder.js +16 -31
- package/public/libs/draco/gltf/draco_decoder.wasm +0 -0
- package/public/libs/draco/gltf/draco_wasm_wrapper.js +116 -104
- package/src/Constants.js +1 -0
- package/src/DevApp.js +12 -0
- package/src/Three/Three2D.js +4 -3
- package/src/Three/Three3D.js +15 -8
- package/src/Three/Three3DScene.js +85 -29
- package/src/Three/__tests__/Three3D.test.js +0 -33
- package/src/Utils/createBakedShadow.js +2 -4
- package/src/Utils/initTextureCanvas.js +2 -1
- package/src/Utils/optimizeTextureImage.js +1 -1
- package/src/Utils/rememberCameraViewOffset.js +5 -3
- package/src/Utils/restrictCameraMovement.js +1 -1
- package/Three/Controls/OrbitControls.js +0 -724
- package/Three/Loaders/ColladaLoader.js +0 -2568
- package/Three/Loaders/MTLLoader.js +0 -418
- package/Three/Loaders/OBJLoader.js +0 -516
- package/src/Three/Controls/OrbitControls.js +0 -934
- package/src/Three/Loaders/ColladaLoader.js +0 -3245
- package/src/Three/Loaders/MTLLoader.js +0 -512
- package/src/Three/Loaders/OBJLoader.js +0 -640
package/src/Constants.js
CHANGED
|
@@ -8,6 +8,7 @@ export const EventTypes = {
|
|
|
8
8
|
LoadStart: "Visualization/LoadStart",
|
|
9
9
|
LoadFinished: "Visualization/LoadFinished",
|
|
10
10
|
LoadError: "Visualization/LoadError",
|
|
11
|
+
EmptySceneError: "Visualization/EmptySceneError",
|
|
11
12
|
Zoomed: "Visualization/Zoomed",
|
|
12
13
|
HoverIn: "Visualization/HoverIn",
|
|
13
14
|
HoverOut: "Visualization/HoverOut",
|
package/src/DevApp.js
CHANGED
|
@@ -332,6 +332,18 @@ const modelData = {
|
|
|
332
332
|
},
|
|
333
333
|
},
|
|
334
334
|
},
|
|
335
|
+
BrokenModel: {
|
|
336
|
+
designAreaList: [],
|
|
337
|
+
configuration: {
|
|
338
|
+
visualizationData: {
|
|
339
|
+
sceneData: [
|
|
340
|
+
{ model: "models/3d/BrokenModel/MissingBuffer.gltf" },
|
|
341
|
+
{ model: "models/3d/BrokenModel/MissingImages.gltf" },
|
|
342
|
+
{ model: "models/3d/BrokenModel/WorkingPart.gltf" },
|
|
343
|
+
],
|
|
344
|
+
},
|
|
345
|
+
},
|
|
346
|
+
},
|
|
335
347
|
},
|
|
336
348
|
};
|
|
337
349
|
|
package/src/Three/Three2D.js
CHANGED
|
@@ -16,8 +16,8 @@ import {
|
|
|
16
16
|
WebGLRenderer,
|
|
17
17
|
BufferGeometry,
|
|
18
18
|
Float32BufferAttribute,
|
|
19
|
-
DoubleSide,
|
|
20
|
-
} from
|
|
19
|
+
DoubleSide, LinearSRGBColorSpace,
|
|
20
|
+
} from 'three';
|
|
21
21
|
import TWEEN from "@tweenjs/tween.js";
|
|
22
22
|
import get from "lodash/get";
|
|
23
23
|
import first from "lodash/first";
|
|
@@ -118,6 +118,7 @@ export class Three2D extends ThreeBase {
|
|
|
118
118
|
depth: true, // needed only for the admin area, consider to make it configurable
|
|
119
119
|
});
|
|
120
120
|
renderer.setPixelRatio(window.devicePixelRatio ? window.devicePixelRatio : 1);
|
|
121
|
+
renderer.outputColorSpace = LinearSRGBColorSpace;
|
|
121
122
|
return renderer;
|
|
122
123
|
}
|
|
123
124
|
|
|
@@ -856,7 +857,7 @@ export class Three2D extends ThreeBase {
|
|
|
856
857
|
};
|
|
857
858
|
}
|
|
858
859
|
|
|
859
|
-
async getScreenshots(callback, { designViewList, areaList, variantList, size }) {
|
|
860
|
+
async getScreenshots(callback, { designViewList, areaList, variantList, size } = {}) {
|
|
860
861
|
if (!this.renderer) {
|
|
861
862
|
return callback({});
|
|
862
863
|
}
|
package/src/Three/Three3D.js
CHANGED
|
@@ -15,9 +15,6 @@ import first from "lodash/first";
|
|
|
15
15
|
import findIndex from "lodash/findIndex";
|
|
16
16
|
|
|
17
17
|
import { ThreeBase, onProgress } from "./ThreeBase";
|
|
18
|
-
import MTLLoader from "./Loaders/MTLLoader";
|
|
19
|
-
import OBJLoader from "./Loaders/OBJLoader";
|
|
20
|
-
import ColladaLoader from "./Loaders/ColladaLoader";
|
|
21
18
|
|
|
22
19
|
import { initTextureCanvas } from "../Utils/initTextureCanvas";
|
|
23
20
|
import { createWorkingCanvas } from "../Utils/createCanvas";
|
|
@@ -28,9 +25,12 @@ import { disposeMaterial } from "../Utils/disposeMaterial";
|
|
|
28
25
|
import { rememberCameraViewOffset } from "../Utils/rememberCameraViewOffset";
|
|
29
26
|
import { restrictOrbitControls } from "../Utils/restrictCameraMovement";
|
|
30
27
|
import { isMobileDevice } from "../Utils/isMobileDevice";
|
|
31
|
-
import OrbitControls from "./Controls/OrbitControls";
|
|
32
28
|
import { createZoomHandler } from "../CommonUtils/pointerEvent";
|
|
33
29
|
import { createTextureBuilder } from "../Utils/TextureBuilder/createTextureBuilder";
|
|
30
|
+
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
|
|
31
|
+
import { ColladaLoader } from "three/examples/jsm/loaders/ColladaLoader";
|
|
32
|
+
import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader";
|
|
33
|
+
import { MTLLoader } from "three/examples/jsm/loaders/MTLLoader";
|
|
34
34
|
|
|
35
35
|
export const MAX_DISTANCE_MULTIPLIER = 1.1;
|
|
36
36
|
export const MIN_DISTANCE_MULTIPLIER = 0.1;
|
|
@@ -580,10 +580,13 @@ export class Three3D extends ThreeBase {
|
|
|
580
580
|
return () => {};
|
|
581
581
|
}
|
|
582
582
|
|
|
583
|
-
async getScreenshots(callback, { viewList, variantList, size }) {
|
|
583
|
+
async getScreenshots(callback, { viewList, variantList, size } = {}) {
|
|
584
584
|
if (!this.renderer) {
|
|
585
585
|
return callback({});
|
|
586
586
|
}
|
|
587
|
+
if (!variantList) {
|
|
588
|
+
variantList = ["default"];
|
|
589
|
+
}
|
|
587
590
|
this._screenshottingInProgress = true;
|
|
588
591
|
this.endAnimation();
|
|
589
592
|
await this.animationRunning();
|
|
@@ -619,10 +622,12 @@ export class Three3D extends ThreeBase {
|
|
|
619
622
|
const height = size?.height || 768;
|
|
620
623
|
|
|
621
624
|
const screenshots = {};
|
|
622
|
-
const views = this.
|
|
625
|
+
const views = { ...this.cameraViews, ...this.screenshotViews };
|
|
623
626
|
// if the viewList option is provided, use it as keys instead of the list of all views
|
|
624
627
|
const viewKeyList =
|
|
625
|
-
viewList instanceof Array && viewList.length > 0
|
|
628
|
+
viewList instanceof Array && viewList.length > 0
|
|
629
|
+
? viewList.filter(viewKey => views[viewKey])
|
|
630
|
+
: Object.keys(views);
|
|
626
631
|
|
|
627
632
|
for (let variant of variantList) {
|
|
628
633
|
if (this._abortScreenshotting) {
|
|
@@ -701,9 +706,11 @@ export class Three3D extends ThreeBase {
|
|
|
701
706
|
? this.findMaterialByName(materialName)
|
|
702
707
|
: first(this._customizableMaterials);
|
|
703
708
|
if (!material || !material.map || !material.map.image) {
|
|
704
|
-
|
|
709
|
+
// eslint-disable-next-line no-console
|
|
710
|
+
console.error(
|
|
705
711
|
`Cannot get drawing context for material: ${materialName}! Is it prepared already?`
|
|
706
712
|
);
|
|
713
|
+
return;
|
|
707
714
|
}
|
|
708
715
|
|
|
709
716
|
const { ctx, canvas, originalImage, texture } = this.getCanvasContextForTexture(material.map);
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
Clock,
|
|
7
7
|
Color,
|
|
8
8
|
DirectionalLight,
|
|
9
|
+
DoubleSide,
|
|
9
10
|
Group,
|
|
10
11
|
ImageLoader,
|
|
11
12
|
LoadingManager,
|
|
@@ -14,16 +15,13 @@ import {
|
|
|
14
15
|
Object3D,
|
|
15
16
|
PCFSoftShadowMap,
|
|
16
17
|
PerspectiveCamera,
|
|
17
|
-
|
|
18
|
+
PlaneGeometry,
|
|
18
19
|
PMREMGenerator,
|
|
19
|
-
Quaternion,
|
|
20
20
|
Scene,
|
|
21
21
|
ShadowMaterial,
|
|
22
22
|
Sphere,
|
|
23
23
|
SphereGeometry,
|
|
24
|
-
sRGBEncoding,
|
|
25
24
|
Texture,
|
|
26
|
-
UnsignedByteType,
|
|
27
25
|
Vector3,
|
|
28
26
|
WebGLRenderer,
|
|
29
27
|
} from "three";
|
|
@@ -41,6 +39,9 @@ import findIndex from "lodash/findIndex";
|
|
|
41
39
|
import merge from "lodash/merge";
|
|
42
40
|
import createBakedShadow from "../Utils/createBakedShadow";
|
|
43
41
|
import setLightShadow from "../Utils/setLightShadow";
|
|
42
|
+
import { EventTypes } from "../Constants";
|
|
43
|
+
import { createImageRepository } from "../Utils/createImageRepository";
|
|
44
|
+
import { createCache } from "../Utils/createCache";
|
|
44
45
|
|
|
45
46
|
const UNSET = Symbol("unset");
|
|
46
47
|
|
|
@@ -126,8 +127,9 @@ function findImageBySrc(tree, src) {
|
|
|
126
127
|
tree.traverse(({ material }) => {
|
|
127
128
|
if (!result && material) {
|
|
128
129
|
for (const value of Object.values(material)) {
|
|
129
|
-
if (value && value.isTexture && value.image
|
|
130
|
-
result = value.
|
|
130
|
+
if (value && value.isTexture && (value.image?.src === src || value.userData?.src === src)) {
|
|
131
|
+
result = value.source;
|
|
132
|
+
return result;
|
|
131
133
|
}
|
|
132
134
|
}
|
|
133
135
|
}
|
|
@@ -263,7 +265,7 @@ export class Three3DScene extends Three3D {
|
|
|
263
265
|
dirLightPosition = new Vector3(1, 1, 1).normalize();
|
|
264
266
|
|
|
265
267
|
defaultCameraPosition = new Vector3(0, 1, 2).normalize();
|
|
266
|
-
defaultScreenshotPosition = new Vector3(0,
|
|
268
|
+
defaultScreenshotPosition = new Vector3(0, 1, 2).normalize();
|
|
267
269
|
|
|
268
270
|
relativeCameraViews = {};
|
|
269
271
|
relativeScreenshotViews = {};
|
|
@@ -284,6 +286,7 @@ export class Three3DScene extends Three3D {
|
|
|
284
286
|
blurRadius: 6,
|
|
285
287
|
shadowOpacity: 0.8,
|
|
286
288
|
},
|
|
289
|
+
textureImageCacheSize: 20,
|
|
287
290
|
};
|
|
288
291
|
|
|
289
292
|
constructor(cfg = {}) {
|
|
@@ -315,14 +318,40 @@ export class Three3DScene extends Three3D {
|
|
|
315
318
|
createLoader(options = {}) {
|
|
316
319
|
const loadingManager = this.createLoadingManager(options);
|
|
317
320
|
|
|
318
|
-
|
|
319
|
-
|
|
321
|
+
if (!this.dracoLoader) {
|
|
322
|
+
const dracoLoader = new (class PatchedDRACOLoader extends DRACOLoader {
|
|
323
|
+
decodeGeometry(buffer, taskConfig) {
|
|
324
|
+
return super.decodeGeometry(buffer, taskConfig).catch(e => {
|
|
325
|
+
// eslint-disable-next-line no-console
|
|
326
|
+
console.error(e.message || e.error);
|
|
327
|
+
// make sure an empty geometry is returned to not break the app
|
|
328
|
+
return { attributes: {} };
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
})();
|
|
332
|
+
dracoLoader.setDecoderPath("libs/draco/gltf/");
|
|
333
|
+
this.dracoLoader = dracoLoader;
|
|
334
|
+
}
|
|
320
335
|
|
|
321
336
|
const loader = new GLTFLoader(loadingManager);
|
|
322
|
-
loader.setDRACOLoader(dracoLoader);
|
|
337
|
+
loader.setDRACOLoader(this.dracoLoader);
|
|
323
338
|
return loader;
|
|
324
339
|
}
|
|
325
340
|
|
|
341
|
+
getImageCache() {
|
|
342
|
+
if (!this._imageCache) {
|
|
343
|
+
this._imageCache = createCache(this.config.textureImageCacheSize);
|
|
344
|
+
}
|
|
345
|
+
return this._imageCache;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
useImageRepository(imageLoader) {
|
|
349
|
+
return createImageRepository(
|
|
350
|
+
this.getImageCache(),
|
|
351
|
+
src => new Promise((resolve, reject) => imageLoader.load(src, resolve, undefined, reject))
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
|
|
326
355
|
createImageLoader(options = {}) {
|
|
327
356
|
const loadingManager = this.createLoadingManager(options);
|
|
328
357
|
const imageLoader = new ImageLoader(loadingManager);
|
|
@@ -334,7 +363,6 @@ export class Three3DScene extends Three3D {
|
|
|
334
363
|
alpha: true,
|
|
335
364
|
antialias: true,
|
|
336
365
|
});
|
|
337
|
-
renderer.outputEncoding = sRGBEncoding;
|
|
338
366
|
renderer.shadowMap.enabled = true;
|
|
339
367
|
renderer.shadowMap.type = PCFSoftShadowMap;
|
|
340
368
|
renderer.toneMapping = ACESFilmicToneMapping;
|
|
@@ -362,7 +390,7 @@ export class Three3DScene extends Three3D {
|
|
|
362
390
|
pmremGenerator.compileEquirectangularShader();
|
|
363
391
|
|
|
364
392
|
this.envMapPromise = new Promise((resolve, reject) => {
|
|
365
|
-
new RGBELoader().
|
|
393
|
+
new RGBELoader().load(
|
|
366
394
|
envMapURL,
|
|
367
395
|
texture => {
|
|
368
396
|
this.envMap = pmremGenerator.fromEquirectangular(texture).texture;
|
|
@@ -415,7 +443,7 @@ export class Three3DScene extends Three3D {
|
|
|
415
443
|
shadowMaterial = new ShadowMaterial({ color: 0x202020 });
|
|
416
444
|
}
|
|
417
445
|
|
|
418
|
-
const mesh = new Mesh(new
|
|
446
|
+
const mesh = new Mesh(new PlaneGeometry(1, 1), shadowMaterial);
|
|
419
447
|
mesh.name = "ground";
|
|
420
448
|
mesh.rotation.x = -Math.PI / 2;
|
|
421
449
|
mesh.receiveShadow = true;
|
|
@@ -477,6 +505,7 @@ export class Three3DScene extends Three3D {
|
|
|
477
505
|
}
|
|
478
506
|
|
|
479
507
|
async applyMaterialParams(model, materialOptions, imageLoader) {
|
|
508
|
+
const imageRepository = this.useImageRepository(imageLoader);
|
|
480
509
|
if (materialOptions) {
|
|
481
510
|
const { params } = materialOptions;
|
|
482
511
|
params &&
|
|
@@ -514,13 +543,16 @@ export class Three3DScene extends Three3D {
|
|
|
514
543
|
case "specularColorMap":
|
|
515
544
|
case "thicknessMap":
|
|
516
545
|
case "transmissionMap": {
|
|
517
|
-
const texture =
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
546
|
+
const texture = material[p]?.clone() || new Texture();
|
|
547
|
+
texture.flipY = material.map?.flipY || false;
|
|
548
|
+
const src = imageLoader.manager.resolveURL(params[p]);
|
|
549
|
+
const textureSource = findImageBySrc(this.sceneContainer, src);
|
|
550
|
+
if (textureSource) {
|
|
551
|
+
texture.source = textureSource;
|
|
552
|
+
} else {
|
|
553
|
+
texture.image = await imageRepository.loadImage(params[p]);
|
|
554
|
+
}
|
|
555
|
+
texture.userData.src = src;
|
|
524
556
|
texture.needsUpdate = true;
|
|
525
557
|
material[p] = texture;
|
|
526
558
|
break;
|
|
@@ -560,7 +592,10 @@ export class Three3DScene extends Three3D {
|
|
|
560
592
|
}
|
|
561
593
|
})
|
|
562
594
|
);
|
|
563
|
-
|
|
595
|
+
if (material.alphaMap) {
|
|
596
|
+
material.transparent = true;
|
|
597
|
+
material.side = DoubleSide;
|
|
598
|
+
}
|
|
564
599
|
material.needsUpdate = true;
|
|
565
600
|
})
|
|
566
601
|
));
|
|
@@ -614,7 +649,7 @@ export class Three3DScene extends Three3D {
|
|
|
614
649
|
if (!mat.original) {
|
|
615
650
|
mat.original = mat.clone();
|
|
616
651
|
Object.values(mat)
|
|
617
|
-
.filter(value => value && value.
|
|
652
|
+
.filter(value => value && value.clone)
|
|
618
653
|
.forEach(texture => {
|
|
619
654
|
if (!texture.original) {
|
|
620
655
|
texture.original = texture.clone();
|
|
@@ -624,7 +659,7 @@ export class Three3DScene extends Three3D {
|
|
|
624
659
|
mat.copy(mat.original);
|
|
625
660
|
Object.keys(mat).forEach(key => {
|
|
626
661
|
const value = mat[key];
|
|
627
|
-
if (value && value.original) {
|
|
662
|
+
if (typeof value === "object" && value?.copy && value.original) {
|
|
628
663
|
value.copy(value.original);
|
|
629
664
|
}
|
|
630
665
|
});
|
|
@@ -723,6 +758,18 @@ export class Three3DScene extends Three3D {
|
|
|
723
758
|
};
|
|
724
759
|
}
|
|
725
760
|
|
|
761
|
+
onLoadError = url => {
|
|
762
|
+
const errorMessage = `Could not load file: ${url}`;
|
|
763
|
+
// eslint-disable-next-line no-console
|
|
764
|
+
console.error(errorMessage);
|
|
765
|
+
};
|
|
766
|
+
|
|
767
|
+
checkEmptyScene() {
|
|
768
|
+
if (!this.sceneContainer.children.length) {
|
|
769
|
+
this.observable.dispatch(EventTypes.EmptySceneError);
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
|
|
726
773
|
async loadSceneSync(resourceList) {
|
|
727
774
|
// fix LoadFinished event by trapping the loadScene calls to finish the current one before starting the next one
|
|
728
775
|
try {
|
|
@@ -787,9 +834,19 @@ export class Three3DScene extends Three3D {
|
|
|
787
834
|
|
|
788
835
|
triggerLoadEvent && this.onLoadStart();
|
|
789
836
|
|
|
790
|
-
const sceneParts = await Promise.
|
|
837
|
+
const sceneParts = await Promise.allSettled(
|
|
838
|
+
toBeAdded.map(item => this.loadSceneContainer(item))
|
|
839
|
+
);
|
|
840
|
+
|
|
841
|
+
sceneParts.forEach(({ value, reason }, index) => {
|
|
842
|
+
if (reason) {
|
|
843
|
+
// eslint-disable-next-line no-console
|
|
844
|
+
console.error(`Failed to load 3D model: ${toBeAdded[index].model}`);
|
|
845
|
+
return;
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
const { scene, animations } = value;
|
|
791
849
|
|
|
792
|
-
sceneParts.forEach(({ scene, animations }) => {
|
|
793
850
|
sceneContainer.add(scene);
|
|
794
851
|
|
|
795
852
|
// collect animations
|
|
@@ -802,6 +859,8 @@ export class Three3DScene extends Three3D {
|
|
|
802
859
|
}
|
|
803
860
|
});
|
|
804
861
|
|
|
862
|
+
this.checkEmptyScene();
|
|
863
|
+
|
|
805
864
|
sceneContainer.updateWorldMatrix(true, true);
|
|
806
865
|
|
|
807
866
|
await Promise.all(
|
|
@@ -896,10 +955,7 @@ export class Three3DScene extends Three3D {
|
|
|
896
955
|
const distance = position.distanceTo(center);
|
|
897
956
|
const lookat = dir.multiplyScalar(distance).add(position);
|
|
898
957
|
|
|
899
|
-
const
|
|
900
|
-
camera.getWorldQuaternion(rotation);
|
|
901
|
-
const orientation = Object3D.DefaultUp.clone();
|
|
902
|
-
|
|
958
|
+
const orientation = Object3D.DEFAULT_UP;
|
|
903
959
|
const fov = camera.fov || 45;
|
|
904
960
|
|
|
905
961
|
const cameraView = {
|
|
@@ -31,19 +31,6 @@ describe("Visualization/Three/Three3D", () => {
|
|
|
31
31
|
});
|
|
32
32
|
});
|
|
33
33
|
|
|
34
|
-
// FIXME this test fails since CI-423
|
|
35
|
-
test.skip("the loadModel function calls the loadMaterial and loadObject methods with the correct path", async () => {
|
|
36
|
-
three.loadMaterial = jest.fn(() => Promise.resolve(false));
|
|
37
|
-
three.loadObject = jest.fn(() => Promise.resolve(false));
|
|
38
|
-
await three.loadModel();
|
|
39
|
-
expect(three.loadMaterial.mock.calls[0][0]).toEqual(
|
|
40
|
-
"/path/to/3D/content/path_for_item_id/materials/path_for_variant_id/material.mtl"
|
|
41
|
-
);
|
|
42
|
-
expect(three.loadObject.mock.calls[0][0]).toEqual(
|
|
43
|
-
"/path/to/3D/content/path_for_item_id/model.obj"
|
|
44
|
-
);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
34
|
test("setCustomizableMaterialName and findCustomizableMaterials", () => {
|
|
48
35
|
const matObj = {
|
|
49
36
|
myMaterial: {
|
|
@@ -61,24 +48,4 @@ describe("Visualization/Three/Three3D", () => {
|
|
|
61
48
|
]);
|
|
62
49
|
expect(three.prepareCustomCanvasForMaterial).toHaveBeenCalledWith(matObj.myMaterial);
|
|
63
50
|
});
|
|
64
|
-
|
|
65
|
-
test("loads the camera views correctly", async () => {
|
|
66
|
-
// read the test obj file (cameraviews.obj) as a data url
|
|
67
|
-
const cameraViewsDataUrl =
|
|
68
|
-
"data:text/plain;base64," +
|
|
69
|
-
btoa(fs.readFileSync(path.resolve(__dirname, "cameraviews.obj"), "utf8"));
|
|
70
|
-
const three = new Three3D();
|
|
71
|
-
|
|
72
|
-
three.controls = { update: () => true };
|
|
73
|
-
|
|
74
|
-
const views = await three.loadCameraViews(cameraViewsDataUrl, false);
|
|
75
|
-
|
|
76
|
-
expect(views).toEqual({
|
|
77
|
-
default: {
|
|
78
|
-
lookat: { x: 0, y: 0, z: 0 },
|
|
79
|
-
position: { x: 3, y: 5, z: -12 },
|
|
80
|
-
},
|
|
81
|
-
sleeve: { lookat: { x: 0, y: 0, z: 0 } },
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
51
|
});
|
|
@@ -2,13 +2,12 @@ import {
|
|
|
2
2
|
Box3,
|
|
3
3
|
DoubleSide,
|
|
4
4
|
Sphere,
|
|
5
|
-
|
|
5
|
+
PlaneGeometry,
|
|
6
6
|
Mesh,
|
|
7
7
|
ShadowMaterial,
|
|
8
8
|
DirectionalLight,
|
|
9
9
|
WebGLRenderTarget,
|
|
10
10
|
WebGLRenderer,
|
|
11
|
-
sRGBEncoding,
|
|
12
11
|
PCFSoftShadowMap,
|
|
13
12
|
MeshStandardMaterial,
|
|
14
13
|
CanvasTexture,
|
|
@@ -52,7 +51,7 @@ export default function createBakedShadow(scene, options) {
|
|
|
52
51
|
const sphere = box.getBoundingSphere(new Sphere());
|
|
53
52
|
const { radius } = sphere;
|
|
54
53
|
|
|
55
|
-
const shadowGeometry = new
|
|
54
|
+
const shadowGeometry = new PlaneGeometry(1, 1);
|
|
56
55
|
shadowGeometry.rotateX(-Math.PI * 0.5);
|
|
57
56
|
shadowGeometry.rotateY(Math.PI);
|
|
58
57
|
const shadowGround = new Mesh(
|
|
@@ -97,7 +96,6 @@ export default function createBakedShadow(scene, options) {
|
|
|
97
96
|
alpha: true,
|
|
98
97
|
antialias: true,
|
|
99
98
|
});
|
|
100
|
-
renderer.outputEncoding = sRGBEncoding;
|
|
101
99
|
renderer.shadowMap.enabled = true;
|
|
102
100
|
renderer.shadowMap.type = PCFSoftShadowMap;
|
|
103
101
|
renderer.setRenderTarget(renderTarget);
|
|
@@ -14,7 +14,8 @@ export function initTextureCanvas(texture) {
|
|
|
14
14
|
if (!texture.originalImage || texture.image.nodeName !== "CANVAS") {
|
|
15
15
|
const originalImage = optimizeTextureImage(texture.image);
|
|
16
16
|
// eslint-disable-next-line no-console
|
|
17
|
-
|
|
17
|
+
texture.userData.src = texture.image?.src || texture.userData?.src;
|
|
18
|
+
console.log(`Creating canvas from texture: ${texture.userData.src}`);
|
|
18
19
|
texture.image = createCanvasFromImage(originalImage);
|
|
19
20
|
texture.originalImage = originalImage;
|
|
20
21
|
} else {
|
|
@@ -9,7 +9,7 @@ import { createWorkingCanvas } from "./createCanvas";
|
|
|
9
9
|
* @param {number} minTextureSize
|
|
10
10
|
* @return {HTMLImageElement|HTMLCanvasElement}
|
|
11
11
|
*/
|
|
12
|
-
export const optimizeTextureImage = (image, maxTextureSize =
|
|
12
|
+
export const optimizeTextureImage = (image, maxTextureSize = 4096, minTextureSize = 2048) => {
|
|
13
13
|
let textureSize = Math.max(image.width, image.height);
|
|
14
14
|
if (textureSize <= maxTextureSize && textureSize >= minTextureSize) {
|
|
15
15
|
return image;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export const rememberCameraViewOffset = camera => {
|
|
2
|
-
const {
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
const { view } = camera;
|
|
3
|
+
if (!view) {
|
|
4
|
+
return () => null;
|
|
5
|
+
}
|
|
6
|
+
const { fullWidth, fullHeight, offsetX, offsetY, width, height } = view;
|
|
5
7
|
return () => camera.setViewOffset(fullWidth, fullHeight, offsetX, offsetY, width, height);
|
|
6
8
|
};
|