@shapediver/viewer.data-engine.geometry-engine 2.10.1-rc.0 → 2.12.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/dist/GeometryEngine.d.ts.map +1 -1
- package/dist/GeometryEngine.js +18 -14
- package/dist/GeometryEngine.js.map +1 -1
- package/dist/gltfv1/GLTFLoader.d.ts.map +1 -1
- package/dist/gltfv1/GLTFLoader.js +53 -49
- package/dist/gltfv1/GLTFLoader.js.map +1 -1
- package/dist/gltfv1/SDGTFLoader.js +98 -94
- package/dist/gltfv1/SDGTFLoader.js.map +1 -1
- package/dist/gltfv2/GLTFLoader.d.ts +2 -2
- package/dist/gltfv2/GLTFLoader.d.ts.map +1 -1
- package/dist/gltfv2/GLTFLoader.js +67 -63
- package/dist/gltfv2/GLTFLoader.js.map +1 -1
- package/dist/gltfv2/loaders/AccessorLoader.js +15 -11
- package/dist/gltfv2/loaders/AccessorLoader.js.map +1 -1
- package/dist/gltfv2/loaders/BufferLoader.d.ts.map +1 -1
- package/dist/gltfv2/loaders/BufferLoader.js +10 -6
- package/dist/gltfv2/loaders/BufferLoader.js.map +1 -1
- package/dist/gltfv2/loaders/BufferViewLoader.js +5 -1
- package/dist/gltfv2/loaders/BufferViewLoader.js.map +1 -1
- package/dist/gltfv2/loaders/GeometryLoader.js +19 -15
- package/dist/gltfv2/loaders/GeometryLoader.js.map +1 -1
- package/dist/gltfv2/loaders/MaterialLoader.d.ts.map +1 -1
- package/dist/gltfv2/loaders/MaterialLoader.js +78 -60
- package/dist/gltfv2/loaders/MaterialLoader.js.map +1 -1
- package/dist/gltfv2/loaders/TextureLoader.d.ts +4 -1
- package/dist/gltfv2/loaders/TextureLoader.d.ts.map +1 -1
- package/dist/gltfv2/loaders/TextureLoader.js +27 -20
- package/dist/gltfv2/loaders/TextureLoader.js.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/package.json +10 -10
- package/src/GeometryEngine.ts +29 -29
- package/src/gltfv1/GLTFLoader.ts +31 -31
- package/src/gltfv2/GLTFLoader.ts +66 -66
- package/src/gltfv2/loaders/BufferLoader.ts +10 -10
- package/src/gltfv2/loaders/MaterialLoader.ts +39 -33
- package/src/gltfv2/loaders/TextureLoader.ts +41 -30
package/src/gltfv2/GLTFLoader.ts
CHANGED
|
@@ -1,39 +1,39 @@
|
|
|
1
|
-
import { ITreeNode, TreeNode } from '@shapediver/viewer.shared.node-tree'
|
|
1
|
+
import { ITreeNode, TreeNode } from '@shapediver/viewer.shared.node-tree';
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
} from '@shapediver/viewer.shared.services'
|
|
12
|
-
import { IGLTF_v2 } from '@shapediver/viewer.data-engine.shared-types'
|
|
13
|
-
import { mat4, vec3, vec4 } from 'gl-matrix'
|
|
3
|
+
EventEngine,
|
|
4
|
+
EVENTTYPE,
|
|
5
|
+
HttpClient,
|
|
6
|
+
HttpResponse,
|
|
7
|
+
Logger,
|
|
8
|
+
PerformanceEvaluator,
|
|
9
|
+
ShapeDiverViewerDataProcessingError,
|
|
10
|
+
UuidGenerator,
|
|
11
|
+
} from '@shapediver/viewer.shared.services';
|
|
12
|
+
import { IGLTF_v2 } from '@shapediver/viewer.data-engine.shared-types';
|
|
13
|
+
import { mat4, vec3, vec4 } from 'gl-matrix';
|
|
14
14
|
import {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
} from '@shapediver/viewer.shared.types'
|
|
23
|
-
import { OrthographicCamera, PerspectiveCamera } from '@shapediver/viewer.rendering-engine.camera-engine'
|
|
15
|
+
AnimationData,
|
|
16
|
+
IAnimationTrack,
|
|
17
|
+
AttributeData,
|
|
18
|
+
BoneData,
|
|
19
|
+
Color,
|
|
20
|
+
ITaskEvent,
|
|
21
|
+
TASK_TYPE
|
|
22
|
+
} from '@shapediver/viewer.shared.types';
|
|
23
|
+
import { OrthographicCamera, PerspectiveCamera } from '@shapediver/viewer.rendering-engine.camera-engine';
|
|
24
24
|
import {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
} from '@shapediver/viewer.rendering-engine.light-engine'
|
|
30
|
-
|
|
31
|
-
import { BufferLoader } from './loaders/BufferLoader'
|
|
32
|
-
import { BufferViewLoader } from './loaders/BufferViewLoader'
|
|
33
|
-
import { AccessorLoader } from './loaders/AccessorLoader'
|
|
34
|
-
import { TextureLoader } from './loaders/TextureLoader'
|
|
35
|
-
import { MaterialLoader } from './loaders/MaterialLoader'
|
|
36
|
-
import { GeometryLoader } from './loaders/GeometryLoader'
|
|
25
|
+
AbstractLight,
|
|
26
|
+
DirectionalLight,
|
|
27
|
+
PointLight,
|
|
28
|
+
SpotLight,
|
|
29
|
+
} from '@shapediver/viewer.rendering-engine.light-engine';
|
|
30
|
+
|
|
31
|
+
import { BufferLoader } from './loaders/BufferLoader';
|
|
32
|
+
import { BufferViewLoader } from './loaders/BufferViewLoader';
|
|
33
|
+
import { AccessorLoader } from './loaders/AccessorLoader';
|
|
34
|
+
import { TextureLoader } from './loaders/TextureLoader';
|
|
35
|
+
import { MaterialLoader } from './loaders/MaterialLoader';
|
|
36
|
+
import { GeometryLoader } from './loaders/GeometryLoader';
|
|
37
37
|
|
|
38
38
|
export enum GLTF_EXTENSIONS {
|
|
39
39
|
KHR_BINARY_GLTF = 'KHR_binary_glTF',
|
|
@@ -53,10 +53,11 @@ export enum GLTF_EXTENSIONS {
|
|
|
53
53
|
SHAPEDIVER_MATERIALS_PRESET = 'SHAPEDIVER_materials_preset'
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
56
57
|
const DRACO = require('./draco/draco_decoder.js');
|
|
57
58
|
|
|
58
59
|
export class GLTFLoader {
|
|
59
|
-
// #region Properties (
|
|
60
|
+
// #region Properties (22)
|
|
60
61
|
|
|
61
62
|
private readonly BINARY_EXTENSION_HEADER_LENGTH = 20;
|
|
62
63
|
private readonly _eventEngine: EventEngine = EventEngine.instance;
|
|
@@ -73,18 +74,18 @@ export class GLTFLoader {
|
|
|
73
74
|
private _bufferLoader!: BufferLoader;
|
|
74
75
|
private _bufferViewLoader!: BufferViewLoader;
|
|
75
76
|
private _content!: IGLTF_v2;
|
|
76
|
-
private _eventId: string =
|
|
77
|
+
private _eventId: string = '';
|
|
77
78
|
private _geometryLoader!: GeometryLoader;
|
|
78
79
|
private _materialLoader!: MaterialLoader;
|
|
79
80
|
private _nodes: {
|
|
80
81
|
[key: number]: ITreeNode
|
|
81
82
|
} = {};
|
|
82
|
-
private _numberOfNodes = 0;
|
|
83
83
|
private _numberOfConvertedNodes = 0;
|
|
84
|
-
private
|
|
84
|
+
private _numberOfNodes = 0;
|
|
85
85
|
private _progressTimer = 0;
|
|
86
|
+
private _textureLoader!: TextureLoader;
|
|
86
87
|
|
|
87
|
-
// #endregion Properties (
|
|
88
|
+
// #endregion Properties (22)
|
|
88
89
|
|
|
89
90
|
// #region Public Methods (2)
|
|
90
91
|
|
|
@@ -92,11 +93,11 @@ export class GLTFLoader {
|
|
|
92
93
|
this._eventId = taskEventId || this._uuidGenerator.create();
|
|
93
94
|
const eventStart: ITaskEvent = { type: TASK_TYPE.GLTF_CONTENT_LOADING, id: this._eventId, progress: 0, status: 'Starting glTF 2.0 loading.' };
|
|
94
95
|
this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_START, eventStart);
|
|
95
|
-
|
|
96
|
+
|
|
96
97
|
this._numberOfConvertedNodes = 0;
|
|
97
98
|
this._numberOfNodes = content.nodes ? content.nodes.length : 0;
|
|
98
99
|
this._progressTimer = performance.now();
|
|
99
|
-
|
|
100
|
+
|
|
100
101
|
this._baseUri = baseUri;
|
|
101
102
|
if (gltfBinary && gltfHeader)
|
|
102
103
|
this._body = gltfBinary.slice(this.BINARY_EXTENSION_HEADER_LENGTH + gltfHeader.contentLength + 8, gltfHeader.length);
|
|
@@ -128,7 +129,7 @@ export class GLTFLoader {
|
|
|
128
129
|
for (let i = 0; i < variants.length; i++)
|
|
129
130
|
this._geometryLoader.materialVariantsData.variants.push(variants[i].name);
|
|
130
131
|
this._geometryLoader.materialVariantsData.variantIndex = 0;
|
|
131
|
-
node.data.push(this._geometryLoader.materialVariantsData)
|
|
132
|
+
node.data.push(this._geometryLoader.materialVariantsData);
|
|
132
133
|
}
|
|
133
134
|
|
|
134
135
|
if (this._content.skins !== undefined && this._content.nodes !== undefined) {
|
|
@@ -142,7 +143,7 @@ export class GLTFLoader {
|
|
|
142
143
|
const boneInverses: mat4[] = [];
|
|
143
144
|
|
|
144
145
|
for (let j = 0; j < skinDef.joints.length; j++) {
|
|
145
|
-
this._nodes[skinDef.joints[j]].data.push(new BoneData())
|
|
146
|
+
this._nodes[skinDef.joints[j]].data.push(new BoneData());
|
|
146
147
|
bones.push(this._nodes[skinDef.joints[j]]);
|
|
147
148
|
|
|
148
149
|
let mat = mat4.create();
|
|
@@ -174,12 +175,11 @@ export class GLTFLoader {
|
|
|
174
175
|
|
|
175
176
|
public async loadWithUrl(url?: string | undefined): Promise<ITreeNode> {
|
|
176
177
|
this._performanceEvaluator.startSection('gltfProcessing.' + url);
|
|
177
|
-
let axiosResponse;
|
|
178
178
|
|
|
179
179
|
this._performanceEvaluator.startSection('loadGltf.' + url);
|
|
180
|
-
axiosResponse = await this._httpClient.get(url!, {
|
|
180
|
+
const axiosResponse = await this._httpClient.get(url!, {
|
|
181
181
|
responseType: 'arraybuffer'
|
|
182
|
-
})
|
|
182
|
+
}) as HttpResponse<ArrayBuffer>;
|
|
183
183
|
this._performanceEvaluator.endSection('loadGltf.' + url);
|
|
184
184
|
|
|
185
185
|
let gltfContent, gltfBinary, gltfBaseUrl, gltfHeader;
|
|
@@ -200,8 +200,8 @@ export class GLTFLoader {
|
|
|
200
200
|
length: headerDataView.getUint32(8, true),
|
|
201
201
|
contentLength: headerDataView.getUint32(12, true),
|
|
202
202
|
contentFormat: headerDataView.getUint32(16, true)
|
|
203
|
-
}
|
|
204
|
-
if (gltfHeader.magic != 'glTF')
|
|
203
|
+
};
|
|
204
|
+
if (gltfHeader.magic != 'glTF')
|
|
205
205
|
throw new ShapeDiverViewerDataProcessingError('GLTFLoader.load: Invalid data: sdgTF magic wrong.');
|
|
206
206
|
|
|
207
207
|
// create content
|
|
@@ -215,11 +215,11 @@ export class GLTFLoader {
|
|
|
215
215
|
gltfContent = JSON.parse(new TextDecoder().decode(axiosResponse.data));
|
|
216
216
|
|
|
217
217
|
const removeLastDirectoryPartOf = (the_url: string): string => {
|
|
218
|
-
const dir_char = the_url.includes(
|
|
218
|
+
const dir_char = the_url.includes('/') ? '/' : '\\';
|
|
219
219
|
const the_arr = the_url.split(dir_char);
|
|
220
220
|
the_arr.pop();
|
|
221
221
|
return the_arr.join(dir_char);
|
|
222
|
-
}
|
|
222
|
+
};
|
|
223
223
|
|
|
224
224
|
gltfBaseUrl = removeLastDirectoryPartOf(url!);
|
|
225
225
|
if (!gltfBaseUrl && window && window.location && window.location.href)
|
|
@@ -239,8 +239,8 @@ export class GLTFLoader {
|
|
|
239
239
|
* @return {Promise<AnimationClip>}
|
|
240
240
|
*/
|
|
241
241
|
private loadAnimation(animationId: number): AnimationData {
|
|
242
|
-
if (!this._content.animations) throw new Error('Animations not available.')
|
|
243
|
-
if (!this._content.animations[animationId]) throw new Error('Animations not available.')
|
|
242
|
+
if (!this._content.animations) throw new Error('Animations not available.');
|
|
243
|
+
if (!this._content.animations[animationId]) throw new Error('Animations not available.');
|
|
244
244
|
const animationDef = this._content.animations[animationId];
|
|
245
245
|
const animationTracks: IAnimationTrack[] = [];
|
|
246
246
|
let min = Infinity, max = -Infinity;
|
|
@@ -260,7 +260,7 @@ export class GLTFLoader {
|
|
|
260
260
|
const output = this._accessorLoader.getAccessor(sampler.output);
|
|
261
261
|
let interpolation = sampler.interpolation;
|
|
262
262
|
if (interpolation === 'CUBICSPLINE') {
|
|
263
|
-
this._logger.warn('Animation with CUBICSPLINE interpolation is currently not supported. Assigning linear interpolation instead.')
|
|
263
|
+
this._logger.warn('Animation with CUBICSPLINE interpolation is currently not supported. Assigning linear interpolation instead.');
|
|
264
264
|
interpolation = 'linear';
|
|
265
265
|
}
|
|
266
266
|
|
|
@@ -277,8 +277,8 @@ export class GLTFLoader {
|
|
|
277
277
|
}
|
|
278
278
|
|
|
279
279
|
private loadCamera(cameraId: number): ITreeNode {
|
|
280
|
-
if (!this._content.cameras) throw new Error('Cameras not available.')
|
|
281
|
-
if (!this._content.cameras[cameraId]) throw new Error('Cameras not available.')
|
|
280
|
+
if (!this._content.cameras) throw new Error('Cameras not available.');
|
|
281
|
+
if (!this._content.cameras[cameraId]) throw new Error('Cameras not available.');
|
|
282
282
|
const cameraDef = this._content.cameras[cameraId];
|
|
283
283
|
const cameraNode = new TreeNode(cameraDef.name || 'camera_' + cameraId);
|
|
284
284
|
|
|
@@ -311,7 +311,7 @@ export class GLTFLoader {
|
|
|
311
311
|
|
|
312
312
|
private loadLights(lightId: number): ITreeNode {
|
|
313
313
|
if (!this._content.extensions || !this._content.extensions[GLTF_EXTENSIONS.KHR_LIGHTS_PUNCTUAL] || !this._content.extensions[GLTF_EXTENSIONS.KHR_LIGHTS_PUNCTUAL].lights) throw new Error(`Extension ${GLTF_EXTENSIONS.KHR_LIGHTS_PUNCTUAL} not available.`);
|
|
314
|
-
if (!this._content.extensions[GLTF_EXTENSIONS.KHR_LIGHTS_PUNCTUAL].lights[lightId]) throw new Error('Light not available.')
|
|
314
|
+
if (!this._content.extensions[GLTF_EXTENSIONS.KHR_LIGHTS_PUNCTUAL].lights[lightId]) throw new Error('Light not available.');
|
|
315
315
|
const lightDef = this._content.extensions[GLTF_EXTENSIONS.KHR_LIGHTS_PUNCTUAL].lights[lightId];
|
|
316
316
|
const lightNode = new TreeNode(lightDef.name || 'light_' + lightId);
|
|
317
317
|
|
|
@@ -366,8 +366,8 @@ export class GLTFLoader {
|
|
|
366
366
|
}
|
|
367
367
|
|
|
368
368
|
private async loadNode(nodeId: number): Promise<ITreeNode> {
|
|
369
|
-
if (!this._content.nodes) throw new Error('Nodes not available.')
|
|
370
|
-
if (!this._content.nodes[nodeId]) throw new Error('Node not available.')
|
|
369
|
+
if (!this._content.nodes) throw new Error('Nodes not available.');
|
|
370
|
+
if (!this._content.nodes[nodeId]) throw new Error('Node not available.');
|
|
371
371
|
const node = this._content.nodes[nodeId];
|
|
372
372
|
const nodeDef = new TreeNode(node.name || 'node_' + nodeId);
|
|
373
373
|
this._nodes[nodeId] = nodeDef;
|
|
@@ -429,7 +429,7 @@ export class GLTFLoader {
|
|
|
429
429
|
}
|
|
430
430
|
|
|
431
431
|
this._numberOfConvertedNodes++;
|
|
432
|
-
if(performance.now() - this._progressTimer > this._progressUpdateLimit) {
|
|
432
|
+
if (performance.now() - this._progressTimer > this._progressUpdateLimit) {
|
|
433
433
|
this._progressTimer = performance.now();
|
|
434
434
|
const eventProgress: ITaskEvent = { type: TASK_TYPE.GLTF_CONTENT_LOADING, id: this._eventId, progress: (this._numberOfConvertedNodes / this._numberOfNodes) / 2 + 0.1, status: `GlTF conversion progress: ${this._numberOfConvertedNodes}/${this._numberOfNodes} nodes.` };
|
|
435
435
|
this._eventEngine.emitEvent(EVENTTYPE.TASK.TASK_PROCESS, eventProgress);
|
|
@@ -440,15 +440,15 @@ export class GLTFLoader {
|
|
|
440
440
|
}
|
|
441
441
|
|
|
442
442
|
private async loadScene(): Promise<ITreeNode> {
|
|
443
|
-
if (!this._content.scenes) throw new Error('Scenes not available.')
|
|
443
|
+
if (!this._content.scenes) throw new Error('Scenes not available.');
|
|
444
444
|
const sceneId = this._content.scene || 0;
|
|
445
|
-
if (!this._content.scenes[sceneId]) throw new Error('Scene not available.')
|
|
445
|
+
if (!this._content.scenes[sceneId]) throw new Error('Scene not available.');
|
|
446
446
|
const scene = this._content.scenes[sceneId];
|
|
447
447
|
const sceneDef = new TreeNode(scene.name || 'scene_' + sceneId + '');
|
|
448
448
|
sceneDef.addTransformation({
|
|
449
449
|
id: this._uuidGenerator.create(),
|
|
450
450
|
matrix: this._globalTransformation
|
|
451
|
-
})
|
|
451
|
+
});
|
|
452
452
|
if (scene.nodes)
|
|
453
453
|
for (let i = 0, len = scene.nodes.length; i < len; i++)
|
|
454
454
|
sceneDef.addChild(await this.loadNode(scene.nodes[i]));
|
|
@@ -459,8 +459,8 @@ export class GLTFLoader {
|
|
|
459
459
|
joints: number[],
|
|
460
460
|
inverseBindMatrices: AttributeData | null
|
|
461
461
|
} {
|
|
462
|
-
if (!this._content.skins) throw new Error('Skins not available.')
|
|
463
|
-
if (!this._content.skins[skinId]) throw new Error('Skin not available.')
|
|
462
|
+
if (!this._content.skins) throw new Error('Skins not available.');
|
|
463
|
+
if (!this._content.skins[skinId]) throw new Error('Skin not available.');
|
|
464
464
|
const skinDef = this._content.skins![skinId];
|
|
465
465
|
|
|
466
466
|
const skinEntry: {
|
|
@@ -475,14 +475,14 @@ export class GLTFLoader {
|
|
|
475
475
|
return skinEntry;
|
|
476
476
|
}
|
|
477
477
|
|
|
478
|
-
skinEntry.inverseBindMatrices = this._accessorLoader.getAccessor(skinDef.inverseBindMatrices)
|
|
478
|
+
skinEntry.inverseBindMatrices = this._accessorLoader.getAccessor(skinDef.inverseBindMatrices);
|
|
479
479
|
return skinEntry;
|
|
480
480
|
}
|
|
481
481
|
|
|
482
482
|
private validateVersionAndExtensions(): void {
|
|
483
|
-
if (!this._content.asset) throw new Error('Asset not available.')
|
|
483
|
+
if (!this._content.asset) throw new Error('Asset not available.');
|
|
484
484
|
const asset = this._content.asset;
|
|
485
|
-
if (!asset.version) throw new Error('Asset does not have a version.')
|
|
485
|
+
if (!asset.version) throw new Error('Asset does not have a version.');
|
|
486
486
|
const version: string = asset.minVersion ? asset.minVersion : asset.version;
|
|
487
487
|
if (!version.startsWith('2')) throw new Error('Version of the glTF not supported.');
|
|
488
488
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { IGLTF_v2 } from '@shapediver/viewer.data-engine.shared-types'
|
|
2
|
-
import { HttpClient } from '@shapediver/viewer.shared.services'
|
|
1
|
+
import { IGLTF_v2 } from '@shapediver/viewer.data-engine.shared-types';
|
|
2
|
+
import { HttpClient, HttpResponse } from '@shapediver/viewer.shared.services';
|
|
3
3
|
|
|
4
4
|
export class BufferLoader {
|
|
5
5
|
// #region Properties (2)
|
|
@@ -21,16 +21,16 @@ export class BufferLoader {
|
|
|
21
21
|
// #region Public Methods (2)
|
|
22
22
|
|
|
23
23
|
public getBuffer(bufferId: number): ArrayBuffer {
|
|
24
|
-
if (!this._content.buffers) throw new Error('BufferLoader.getBuffer: Buffers not available.')
|
|
25
|
-
if (!this._content.buffers[bufferId]) throw new Error('BufferLoader.getBuffer: Buffer not available.')
|
|
26
|
-
if (!this._loaded[bufferId]) throw new Error('BufferLoader.getBuffer: Buffer not loaded.')
|
|
24
|
+
if (!this._content.buffers) throw new Error('BufferLoader.getBuffer: Buffers not available.');
|
|
25
|
+
if (!this._content.buffers[bufferId]) throw new Error('BufferLoader.getBuffer: Buffer not available.');
|
|
26
|
+
if (!this._loaded[bufferId]) throw new Error('BufferLoader.getBuffer: Buffer not loaded.');
|
|
27
27
|
return this._loaded[bufferId];
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
public async load(): Promise<void> {
|
|
31
31
|
if (!this._content.buffers) return;
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
const promises: Promise<void>[] = [];
|
|
34
34
|
|
|
35
35
|
for (let i = 0; i < this._content.buffers.length; i++) {
|
|
36
36
|
const bufferId = i;
|
|
@@ -42,7 +42,7 @@ export class BufferLoader {
|
|
|
42
42
|
|
|
43
43
|
// If present, GLB container is required to be the first buffer.
|
|
44
44
|
if (buffer.uri === undefined && bufferId === 0) {
|
|
45
|
-
if (!this._body) throw new Error(
|
|
45
|
+
if (!this._body) throw new Error('BufferLoader.load: Buffer not available.');
|
|
46
46
|
this._loaded[bufferId] = this._body;
|
|
47
47
|
return;
|
|
48
48
|
}
|
|
@@ -63,10 +63,10 @@ export class BufferLoader {
|
|
|
63
63
|
}
|
|
64
64
|
this._loaded[bufferId] = view.buffer;
|
|
65
65
|
} else {
|
|
66
|
-
|
|
66
|
+
const httpResultPromise = (this._httpClient.get(this._baseUri + '/' + buffer.uri!, {
|
|
67
67
|
responseType: 'arraybuffer'
|
|
68
|
-
}).then(response => { this._loaded[bufferId] = response.data; });
|
|
69
|
-
promises.push(httpResultPromise)
|
|
68
|
+
}) as Promise<HttpResponse<ArrayBuffer>>).then(response => { this._loaded[bufferId] = response.data; });
|
|
69
|
+
promises.push(httpResultPromise);
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
await Promise.all(promises);
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { Converter, HttpClient } from '@shapediver/viewer.shared.services'
|
|
1
|
+
import { Converter, HttpClient } from '@shapediver/viewer.shared.services';
|
|
2
2
|
import {
|
|
3
3
|
IGLTF_v2,
|
|
4
4
|
IGLTF_v2_Material,
|
|
5
5
|
IGLTF_v2_Material_KHR_materials_pbrSpecularGlossiness,
|
|
6
6
|
ISHAPEDIVER_materials_preset,
|
|
7
|
-
} from '@shapediver/viewer.data-engine.shared-types'
|
|
8
|
-
import { vec2 } from 'gl-matrix'
|
|
7
|
+
} from '@shapediver/viewer.data-engine.shared-types';
|
|
8
|
+
import { vec2 } from 'gl-matrix';
|
|
9
9
|
import {
|
|
10
10
|
MATERIAL_ALPHA,
|
|
11
11
|
MATERIAL_SIDE,
|
|
@@ -19,11 +19,13 @@ import {
|
|
|
19
19
|
IMaterialUnlitDataProperties,
|
|
20
20
|
MapData,
|
|
21
21
|
IMapData,
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
TEXTURE_WRAPPING,
|
|
23
|
+
TEXTURE_FILTERING,
|
|
24
|
+
} from '@shapediver/viewer.shared.types';
|
|
25
|
+
import { MaterialEngine } from '@shapediver/viewer.data-engine.material-engine';
|
|
24
26
|
|
|
25
|
-
import { GLTF_EXTENSIONS } from '../GLTFLoader'
|
|
26
|
-
import { TextureLoader } from './TextureLoader'
|
|
27
|
+
import { GLTF_EXTENSIONS } from '../GLTFLoader';
|
|
28
|
+
import { TextureLoader } from './TextureLoader';
|
|
27
29
|
|
|
28
30
|
export class MaterialLoader {
|
|
29
31
|
// #region Properties (4)
|
|
@@ -44,9 +46,9 @@ export class MaterialLoader {
|
|
|
44
46
|
// #region Public Methods (2)
|
|
45
47
|
|
|
46
48
|
public getMaterial(materialId: number): IMaterialAbstractData {
|
|
47
|
-
if (!this._content.materials) throw new Error('MaterialLoader.getMaterial: Materials not available.')
|
|
48
|
-
if (!this._content.materials[materialId]) throw new Error('MaterialLoader.getMaterial: Material not available.')
|
|
49
|
-
if (!this._loaded[materialId]) throw new Error('MaterialLoader.getMaterial: Material not loaded.')
|
|
49
|
+
if (!this._content.materials) throw new Error('MaterialLoader.getMaterial: Materials not available.');
|
|
50
|
+
if (!this._content.materials[materialId]) throw new Error('MaterialLoader.getMaterial: Material not available.');
|
|
51
|
+
if (!this._loaded[materialId]) throw new Error('MaterialLoader.getMaterial: Material not loaded.');
|
|
50
52
|
return this._loaded[materialId];
|
|
51
53
|
}
|
|
52
54
|
|
|
@@ -54,7 +56,7 @@ export class MaterialLoader {
|
|
|
54
56
|
this._loaded = {};
|
|
55
57
|
if (!this._content.materials) return;
|
|
56
58
|
|
|
57
|
-
|
|
59
|
+
const promises: Promise<void>[] = [];
|
|
58
60
|
for (let i = 0; i < this._content.materials.length; i++) {
|
|
59
61
|
const materialId = i;
|
|
60
62
|
const material: IGLTF_v2_Material = this._content.materials[materialId];
|
|
@@ -66,18 +68,21 @@ export class MaterialLoader {
|
|
|
66
68
|
if (materialExtensions[GLTF_EXTENSIONS.SHAPEDIVER_MATERIALS_PRESET]) {
|
|
67
69
|
const materialPreset: ISHAPEDIVER_materials_preset = materialExtensions[GLTF_EXTENSIONS.SHAPEDIVER_MATERIALS_PRESET];
|
|
68
70
|
promises.push(
|
|
69
|
-
new Promise<void>(
|
|
71
|
+
new Promise<void>((resolve, reject) => {
|
|
70
72
|
try {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
this._materialEngine.loadPresetMaterial(materialPreset.materialpreset)
|
|
74
|
+
.then(materialData => {
|
|
75
|
+
materialData.name = material.name;
|
|
76
|
+
materialData.color = materialPreset.color;
|
|
77
|
+
this._loaded[materialId] = materialData;
|
|
78
|
+
resolve();
|
|
79
|
+
})
|
|
80
|
+
.catch(reject);
|
|
76
81
|
} catch (e) {
|
|
77
82
|
reject(e);
|
|
78
83
|
}
|
|
79
84
|
})
|
|
80
|
-
)
|
|
85
|
+
);
|
|
81
86
|
continue;
|
|
82
87
|
}
|
|
83
88
|
|
|
@@ -345,25 +350,26 @@ export class MaterialLoader {
|
|
|
345
350
|
// #region Private Methods (1)
|
|
346
351
|
|
|
347
352
|
private loadMap(textureId: number, properties?: { offset?: number[], scale?: number[], rotation?: number, texCoord?: number }): IMapData {
|
|
348
|
-
if (!this._content.textures) throw new Error('Textures not available.')
|
|
353
|
+
if (!this._content.textures) throw new Error('Textures not available.');
|
|
349
354
|
const texture = this._content.textures[textureId];
|
|
350
|
-
if (!this._content.images) throw new Error('Images not available.')
|
|
355
|
+
if (!this._content.images) throw new Error('Images not available.');
|
|
351
356
|
const sampler = this._content.samplers && texture.sampler && this._content.samplers[texture.sampler] ? this._content.samplers[texture.sampler] : {};
|
|
352
|
-
const
|
|
357
|
+
const loadedTexture = this._textureLoader.getTexture(textureId);
|
|
353
358
|
|
|
354
359
|
return new MapData(
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
360
|
+
loadedTexture.image,
|
|
361
|
+
{
|
|
362
|
+
blob: loadedTexture.blob,
|
|
363
|
+
wrapS: sampler.wrapS as TEXTURE_WRAPPING,
|
|
364
|
+
wrapT: sampler.wrapT as TEXTURE_WRAPPING,
|
|
365
|
+
minFilter: sampler.minFilter as TEXTURE_FILTERING,
|
|
366
|
+
magFilter: sampler.magFilter as TEXTURE_FILTERING,
|
|
367
|
+
offset: properties && properties.offset ? vec2.fromValues(properties.offset[0], properties.offset[1]) : vec2.create(),
|
|
368
|
+
repeat: properties && properties.scale ? vec2.fromValues(properties.scale[0], properties.scale[1]) : vec2.fromValues(1, 1),
|
|
369
|
+
rotation: properties && properties.rotation !== undefined ? properties.rotation : 0,
|
|
370
|
+
texCoord: properties?.texCoord,
|
|
371
|
+
flipY: false
|
|
372
|
+
}
|
|
367
373
|
);
|
|
368
374
|
}
|
|
369
375
|
|
|
@@ -1,19 +1,22 @@
|
|
|
1
|
-
import { IGLTF_v2 } from '@shapediver/viewer.data-engine.shared-types'
|
|
2
|
-
import { Converter, HttpClient } from '@shapediver/viewer.shared.services'
|
|
1
|
+
import { IGLTF_v2 } from '@shapediver/viewer.data-engine.shared-types';
|
|
2
|
+
import { Converter, HttpClient } from '@shapediver/viewer.shared.services';
|
|
3
3
|
|
|
4
|
-
import { BufferViewLoader } from './BufferViewLoader'
|
|
4
|
+
import { BufferViewLoader } from './BufferViewLoader';
|
|
5
5
|
|
|
6
6
|
export class TextureLoader {
|
|
7
|
-
// #region Properties (
|
|
7
|
+
// #region Properties (3)
|
|
8
8
|
|
|
9
9
|
private readonly _converter: Converter = Converter.instance;
|
|
10
10
|
private readonly _httpClient: HttpClient = HttpClient.instance;
|
|
11
11
|
|
|
12
12
|
private _loaded: {
|
|
13
|
-
[key: string]:
|
|
13
|
+
[key: string]: {
|
|
14
|
+
image: HTMLImageElement,
|
|
15
|
+
blob: Blob
|
|
16
|
+
}
|
|
14
17
|
} = {};
|
|
15
18
|
|
|
16
|
-
// #endregion Properties (
|
|
19
|
+
// #endregion Properties (3)
|
|
17
20
|
|
|
18
21
|
// #region Constructors (1)
|
|
19
22
|
|
|
@@ -23,59 +26,67 @@ export class TextureLoader {
|
|
|
23
26
|
|
|
24
27
|
// #region Public Methods (2)
|
|
25
28
|
|
|
26
|
-
public getTexture(textureId: number):
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
public getTexture(textureId: number): {
|
|
30
|
+
image: HTMLImageElement,
|
|
31
|
+
blob: Blob
|
|
32
|
+
} {
|
|
33
|
+
if (!this._content.textures) throw new Error('TextureLoader.getTexture: Textures not available.');
|
|
34
|
+
if (!this._content.textures[textureId]) throw new Error('TextureLoader.getTexture: Texture not available.');
|
|
35
|
+
if (!this._loaded[textureId]) throw new Error('TextureLoader.getTexture: Texture not loaded.');
|
|
30
36
|
return this._loaded[textureId];
|
|
31
37
|
}
|
|
32
38
|
|
|
33
39
|
public async load(): Promise<void> {
|
|
34
40
|
if (!this._content.textures) return;
|
|
35
41
|
|
|
36
|
-
|
|
37
|
-
for(let i = 0; i < this._content.textures.length; i++) {
|
|
42
|
+
const promises: Promise<void>[] = [];
|
|
43
|
+
for (let i = 0; i < this._content.textures.length; i++) {
|
|
38
44
|
const textureId = i;
|
|
39
45
|
const texture = this._content.textures[textureId];
|
|
40
|
-
if (!this._content.images) throw new Error('TextureLoader.load: Images not available.')
|
|
46
|
+
if (!this._content.images) throw new Error('TextureLoader.load: Images not available.');
|
|
41
47
|
const image = this._content.images[texture.source];
|
|
42
|
-
|
|
48
|
+
|
|
43
49
|
const DATA_URI_REGEX = /^data:(.*?)(;base64)?,(.*)$/;
|
|
44
50
|
const HTTPS_URI_REGEX = /^https:\/\//;
|
|
45
|
-
|
|
51
|
+
|
|
46
52
|
if (image.bufferView !== undefined) {
|
|
47
53
|
const bufferView = this._bufferViewLoader.getBufferView(image.bufferView);
|
|
48
54
|
const dataView = new DataView(bufferView);
|
|
49
55
|
const array: Array<number> = [];
|
|
50
56
|
for (let i = 0; i < dataView.byteLength; i += 1)
|
|
51
57
|
array[i] = dataView.getUint8(i);
|
|
52
|
-
|
|
58
|
+
|
|
53
59
|
const blob = new Blob([new Uint8Array(array)], { type: image.mimeType });
|
|
54
60
|
const dataUri = URL.createObjectURL(blob);
|
|
55
|
-
|
|
61
|
+
|
|
62
|
+
const img = new Image();
|
|
63
|
+
|
|
56
64
|
promises.push(
|
|
57
65
|
new Promise<void>((resolve, reject) => {
|
|
58
|
-
|
|
59
|
-
.
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
+
img.onload = () => {
|
|
67
|
+
this._loaded[textureId] = {
|
|
68
|
+
image: img,
|
|
69
|
+
blob
|
|
70
|
+
};
|
|
71
|
+
URL.revokeObjectURL(dataUri);
|
|
72
|
+
resolve();
|
|
73
|
+
};
|
|
74
|
+
img.onerror = reject;
|
|
66
75
|
})
|
|
67
76
|
);
|
|
77
|
+
|
|
78
|
+
img.crossOrigin = 'anonymous';
|
|
79
|
+
img.src = dataUri;
|
|
68
80
|
} else {
|
|
69
81
|
const url = DATA_URI_REGEX.test(image.uri!) || HTTPS_URI_REGEX.test(image.uri!) ? image.uri : `${this._baseUri}/${image.uri}`;
|
|
70
82
|
promises.push(
|
|
71
83
|
new Promise<void>((resolve, reject) => {
|
|
72
84
|
this._httpClient.loadTexture(url!)
|
|
73
85
|
.then(response => {
|
|
74
|
-
this.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}).catch(e => reject(e));
|
|
86
|
+
this._loaded[textureId] = response.data;
|
|
87
|
+
resolve();
|
|
88
|
+
})
|
|
89
|
+
.catch(e => reject(e));
|
|
79
90
|
})
|
|
80
91
|
);
|
|
81
92
|
}
|