@shapediver/viewer.data-engine.geometry-engine 2.10.0 → 2.11.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.js +55 -51
- package/dist/gltfv2/loaders/MaterialLoader.js.map +1 -1
- package/dist/gltfv2/loaders/TextureLoader.d.ts.map +1 -1
- package/dist/gltfv2/loaders/TextureLoader.js +20 -18
- 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/TextureLoader.ts +24 -25
package/src/GeometryEngine.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { ITreeNode } from '@shapediver/viewer.shared.node-tree'
|
|
2
|
-
import { HttpClient, Logger, PerformanceEvaluator, ShapeDiverViewerDataProcessingError } from '@shapediver/viewer.shared.services'
|
|
1
|
+
import { ITreeNode } from '@shapediver/viewer.shared.node-tree';
|
|
2
|
+
import { HttpClient, HttpResponse, Logger, PerformanceEvaluator, ShapeDiverViewerDataProcessingError } from '@shapediver/viewer.shared.services';
|
|
3
3
|
|
|
4
|
-
import { GLTFLoader as GLTF_v1Loader } from './gltfv1/GLTFLoader'
|
|
5
|
-
import { GLTFLoader as GLTF_v2Loader } from './gltfv2/GLTFLoader'
|
|
6
|
-
import { ShapeDiverResponseOutputContent } from '@shapediver/sdk.geometry-api-sdk-v2'
|
|
4
|
+
import { GLTFLoader as GLTF_v1Loader } from './gltfv1/GLTFLoader';
|
|
5
|
+
import { GLTFLoader as GLTF_v2Loader } from './gltfv2/GLTFLoader';
|
|
6
|
+
import { ShapeDiverResponseOutputContent } from '@shapediver/sdk.geometry-api-sdk-v2';
|
|
7
7
|
|
|
8
8
|
export class GeometryEngine {
|
|
9
9
|
// #region Properties (7)
|
|
@@ -52,7 +52,7 @@ export class GeometryEngine {
|
|
|
52
52
|
if (!content || (content && !content.href))
|
|
53
53
|
throw new ShapeDiverViewerDataProcessingError('GeometryEngine cannot load content.');
|
|
54
54
|
|
|
55
|
-
while(this._loadingQueueLength <= this._loadingQueue.length)
|
|
55
|
+
while (this._loadingQueueLength <= this._loadingQueue.length)
|
|
56
56
|
await new Promise(resolve => setTimeout(resolve, 10));
|
|
57
57
|
|
|
58
58
|
const url = content.href!;
|
|
@@ -60,19 +60,19 @@ export class GeometryEngine {
|
|
|
60
60
|
const loadingPromise = new Promise<ITreeNode>(async (resolve, reject) => {
|
|
61
61
|
let gltfContent, gltfBinary, gltfBaseUrl, gltfHeader;
|
|
62
62
|
let version = '2.0';
|
|
63
|
-
|
|
63
|
+
|
|
64
64
|
if (content.format === 'glb' || content.format === 'gltf') {
|
|
65
65
|
this._performanceEvaluator.startSection('gltfProcessing.' + url);
|
|
66
|
-
|
|
66
|
+
|
|
67
67
|
this._performanceEvaluator.startSection('loadGltf.' + url);
|
|
68
68
|
const axiosResponse = await this._httpClient.get(url!, {
|
|
69
69
|
responseType: 'arraybuffer'
|
|
70
|
-
})
|
|
70
|
+
}) as HttpResponse<ArrayBuffer>;
|
|
71
71
|
this._performanceEvaluator.endSection('loadGltf.' + url);
|
|
72
|
-
|
|
72
|
+
|
|
73
73
|
const magic = new TextDecoder().decode(new Uint8Array(axiosResponse.data, 0, 4));
|
|
74
74
|
const isBinary = magic === 'glTF';
|
|
75
|
-
|
|
75
|
+
|
|
76
76
|
if (isBinary) {
|
|
77
77
|
gltfBinary = axiosResponse.data;
|
|
78
78
|
// create header data
|
|
@@ -83,18 +83,18 @@ export class GeometryEngine {
|
|
|
83
83
|
length: headerDataView.getUint32(8, true),
|
|
84
84
|
contentLength: headerDataView.getUint32(12, true),
|
|
85
85
|
contentFormat: headerDataView.getUint32(16, true)
|
|
86
|
-
}
|
|
87
|
-
if (gltfHeader.magic != 'glTF')
|
|
86
|
+
};
|
|
87
|
+
if (gltfHeader.magic != 'glTF')
|
|
88
88
|
throw new ShapeDiverViewerDataProcessingError('Invalid data: glTF magic wrong.');
|
|
89
|
-
|
|
89
|
+
|
|
90
90
|
// create content
|
|
91
91
|
const contentDataView = new DataView(gltfBinary, this.BINARY_EXTENSION_HEADER_LENGTH, gltfHeader.contentLength);
|
|
92
92
|
const contentDecoded = new TextDecoder().decode(contentDataView);
|
|
93
93
|
gltfContent = JSON.parse(contentDecoded);
|
|
94
|
-
|
|
95
|
-
if(gltfContent && gltfContent.asset && gltfContent.asset.version) {
|
|
94
|
+
|
|
95
|
+
if (gltfContent && gltfContent.asset && gltfContent.asset.version) {
|
|
96
96
|
const assetVersion = (gltfContent.asset.version + '').endsWith('.0') ? gltfContent.asset.version : gltfContent.asset.version + '.0';
|
|
97
|
-
if(gltfHeader.version + '.0' === assetVersion) {
|
|
97
|
+
if (gltfHeader.version + '.0' === assetVersion) {
|
|
98
98
|
version = gltfHeader.version + '.0';
|
|
99
99
|
} else {
|
|
100
100
|
throw new ShapeDiverViewerDataProcessingError('GeometryEngine.loadContent: glTF header version (' + gltfHeader.version + ') is not the same as asset version (' + assetVersion + ').');
|
|
@@ -104,42 +104,42 @@ export class GeometryEngine {
|
|
|
104
104
|
}
|
|
105
105
|
} else {
|
|
106
106
|
gltfContent = JSON.parse(new TextDecoder().decode(axiosResponse.data));
|
|
107
|
-
|
|
108
|
-
if(gltfContent && gltfContent.asset && gltfContent.asset.version) {
|
|
109
|
-
if(gltfContent.asset.version !== '2.0')
|
|
107
|
+
|
|
108
|
+
if (gltfContent && gltfContent.asset && gltfContent.asset.version) {
|
|
109
|
+
if (gltfContent.asset.version !== '2.0')
|
|
110
110
|
throw new ShapeDiverViewerDataProcessingError('GeometryEngine.loadContent: Only gltf v2 is supported in a non-binary format.');
|
|
111
111
|
} else {
|
|
112
112
|
this._logger.warn('GeometryEngine.loadContent: No version specified in asset, trying to load as v2.');
|
|
113
113
|
version = '2.0';
|
|
114
114
|
}
|
|
115
|
-
|
|
115
|
+
|
|
116
116
|
const removeLastDirectoryPartOf = (the_url: string): string => {
|
|
117
|
-
const dir_char = the_url.includes(
|
|
117
|
+
const dir_char = the_url.includes('/') ? '/' : '\\';
|
|
118
118
|
const the_arr = the_url.split(dir_char);
|
|
119
119
|
the_arr.pop();
|
|
120
120
|
return the_arr.join(dir_char);
|
|
121
|
-
}
|
|
122
|
-
|
|
121
|
+
};
|
|
122
|
+
|
|
123
123
|
gltfBaseUrl = removeLastDirectoryPartOf(url!);
|
|
124
124
|
if (!gltfBaseUrl && window && window.location && window.location.href)
|
|
125
125
|
gltfBaseUrl = removeLastDirectoryPartOf(window.location.href);
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
|
-
|
|
128
|
+
|
|
129
129
|
let promise: Promise<ITreeNode>;
|
|
130
130
|
if (version === '1.0') {
|
|
131
|
-
promise = new GLTF_v1Loader().load(gltfContent, gltfBinary, gltfHeader, gltfBaseUrl, taskEventId)
|
|
131
|
+
promise = new GLTF_v1Loader().load(gltfContent, gltfBinary, gltfHeader, gltfBaseUrl, taskEventId);
|
|
132
132
|
} else {
|
|
133
133
|
promise = new GLTF_v2Loader().load(gltfContent, gltfBinary, gltfHeader, gltfBaseUrl, taskEventId);
|
|
134
134
|
}
|
|
135
|
-
promise.catch(e => { reject(e) })
|
|
135
|
+
promise.catch(e => { reject(e); });
|
|
136
136
|
resolve(promise);
|
|
137
|
-
})
|
|
137
|
+
});
|
|
138
138
|
|
|
139
139
|
this._loadingQueue.push(loadingPromise);
|
|
140
140
|
const node = await loadingPromise;
|
|
141
141
|
this._loadingQueue.splice(this._loadingQueue.indexOf(loadingPromise), 1);
|
|
142
|
-
|
|
142
|
+
|
|
143
143
|
this._performanceEvaluator.endSection('gltfProcessing.' + url);
|
|
144
144
|
|
|
145
145
|
return node;
|
package/src/gltfv1/GLTFLoader.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
1
|
+
/* eslint-disable no-prototype-builtins */
|
|
2
|
+
import { ITreeNode, TreeNode } from '@shapediver/viewer.shared.node-tree';
|
|
3
|
+
import { HttpClient, PerformanceEvaluator, UuidGenerator, Logger, ShapeDiverViewerDataProcessingError, EventEngine, EVENTTYPE, HttpResponse } from '@shapediver/viewer.shared.services';
|
|
3
4
|
import {
|
|
4
5
|
ACCESSORCOMPONENTTYPE_V1 as ACCESSOR_COMPONENTTYPE,
|
|
5
6
|
ACCESSORTYPE_V1 as ACCESSORTYPE,
|
|
6
7
|
IGLTF_v1,
|
|
7
8
|
IGLTF_v1_Material,
|
|
8
|
-
} from '@shapediver/viewer.data-engine.shared-types'
|
|
9
|
-
import { mat4, vec3, vec4 } from 'gl-matrix'
|
|
9
|
+
} from '@shapediver/viewer.data-engine.shared-types';
|
|
10
|
+
import { mat4, vec3, vec4 } from 'gl-matrix';
|
|
10
11
|
import {
|
|
11
12
|
AttributeData,
|
|
12
13
|
GeometryData,
|
|
@@ -16,9 +17,9 @@ import {
|
|
|
16
17
|
ITaskEvent,
|
|
17
18
|
TASK_TYPE,
|
|
18
19
|
PRIMITIVE_MODE,
|
|
19
|
-
} from '@shapediver/viewer.shared.types'
|
|
20
|
+
} from '@shapediver/viewer.shared.types';
|
|
20
21
|
|
|
21
|
-
import { SDGTFLoader } from './SDGTFLoader'
|
|
22
|
+
import { SDGTFLoader } from './SDGTFLoader';
|
|
22
23
|
|
|
23
24
|
export class GLTFLoader {
|
|
24
25
|
// #region Properties (5)
|
|
@@ -36,7 +37,7 @@ export class GLTFLoader {
|
|
|
36
37
|
private _baseUri: string | undefined;
|
|
37
38
|
private _body: ArrayBuffer | undefined;
|
|
38
39
|
private _content!: IGLTF_v1;
|
|
39
|
-
private _eventId: string =
|
|
40
|
+
private _eventId: string = '';
|
|
40
41
|
private _numberOfNodes = 0;
|
|
41
42
|
private _numberOfConvertedNodes = 0;
|
|
42
43
|
private _progressTimer = 0;
|
|
@@ -80,12 +81,11 @@ export class GLTFLoader {
|
|
|
80
81
|
|
|
81
82
|
public async loadWithUrl(url?: string | undefined): Promise<ITreeNode> {
|
|
82
83
|
this._performanceEvaluator.startSection('gltfProcessing.' + url);
|
|
83
|
-
let binaryGeometry: ArrayBuffer;
|
|
84
84
|
|
|
85
85
|
this._performanceEvaluator.startSection('loadGltf.' + url);
|
|
86
|
-
binaryGeometry = (await this._httpClient.get(url!, {
|
|
86
|
+
const binaryGeometry = (await this._httpClient.get(url!, {
|
|
87
87
|
responseType: 'arraybuffer'
|
|
88
|
-
})).data;
|
|
88
|
+
}) as HttpResponse<ArrayBuffer>).data;
|
|
89
89
|
this._performanceEvaluator.endSection('loadGltf.' + url);
|
|
90
90
|
|
|
91
91
|
// create header data
|
|
@@ -96,7 +96,7 @@ export class GLTFLoader {
|
|
|
96
96
|
length: headerDataView.getUint32(8, true),
|
|
97
97
|
contentLength: headerDataView.getUint32(12, true),
|
|
98
98
|
contentFormat: headerDataView.getUint32(16, true)
|
|
99
|
-
}
|
|
99
|
+
};
|
|
100
100
|
if (header.magic != 'glTF')
|
|
101
101
|
throw new ShapeDiverViewerDataProcessingError('GLTFLoader.load: Invalid data: glTF magic wrong.');
|
|
102
102
|
|
|
@@ -140,7 +140,7 @@ export class GLTFLoader {
|
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
private async loadAccessor(accessorName: string): Promise<AttributeData> {
|
|
143
|
-
if (!this._content.accessors![accessorName]) throw new Error('Accessor not available.')
|
|
143
|
+
if (!this._content.accessors![accessorName]) throw new Error('Accessor not available.');
|
|
144
144
|
const accessor = this._content.accessors![accessorName];
|
|
145
145
|
const bufferView = await this.loadBufferView(accessor.bufferView!);
|
|
146
146
|
|
|
@@ -155,15 +155,15 @@ export class GLTFLoader {
|
|
|
155
155
|
const normalized = false;
|
|
156
156
|
const target = this._content.bufferViews![accessor.bufferView] ? this._content.bufferViews![accessor.bufferView].target : undefined;
|
|
157
157
|
|
|
158
|
-
const min = this._content.asset && this._content.asset?.generator ===
|
|
159
|
-
const max = this._content.asset && this._content.asset?.generator ===
|
|
158
|
+
const min = this._content.asset && this._content.asset?.generator === 'ShapeDiverGltfV1Writer' ? accessor.min || [] : [];
|
|
159
|
+
const max = this._content.asset && this._content.asset?.generator === 'ShapeDiverGltfV1Writer' ? accessor.max || [] : [];
|
|
160
160
|
|
|
161
161
|
// The buffer is not interleaved if the stride is the item size in bytes.
|
|
162
162
|
return new AttributeData(new ArrayType(bufferView), itemSize, itemBytes, byteOffset, elementBytes, normalized, accessor.count, min, max, byteStride, target);
|
|
163
163
|
}
|
|
164
164
|
|
|
165
165
|
private async loadBuffer(bufferName: string): Promise<ArrayBuffer> {
|
|
166
|
-
if (!this._content.buffers![bufferName]) throw new Error('Buffer not available.')
|
|
166
|
+
if (!this._content.buffers![bufferName]) throw new Error('Buffer not available.');
|
|
167
167
|
const buffer = this._content.buffers![bufferName];
|
|
168
168
|
|
|
169
169
|
if (bufferName === 'binary_glTF')
|
|
@@ -172,7 +172,7 @@ export class GLTFLoader {
|
|
|
172
172
|
if (buffer.type === 'arraybuffer') {
|
|
173
173
|
const binaryGeometry: ArrayBuffer = (await this._httpClient.get(buffer.uri!, {
|
|
174
174
|
responseType: 'arraybuffer'
|
|
175
|
-
})).data;
|
|
175
|
+
}) as HttpResponse<ArrayBuffer>).data;
|
|
176
176
|
return binaryGeometry;
|
|
177
177
|
}
|
|
178
178
|
if(!this._body) throw new Error('Buffer not available.');
|
|
@@ -180,7 +180,7 @@ export class GLTFLoader {
|
|
|
180
180
|
}
|
|
181
181
|
|
|
182
182
|
private async loadBufferView(bufferViewName: string): Promise<ArrayBuffer> {
|
|
183
|
-
if (!this._content.bufferViews![bufferViewName]) throw new Error('Buffer View not available.')
|
|
183
|
+
if (!this._content.bufferViews![bufferViewName]) throw new Error('Buffer View not available.');
|
|
184
184
|
const bufferView = this._content.bufferViews![bufferViewName];
|
|
185
185
|
const buffer: ArrayBuffer = await this.loadBuffer(bufferView.buffer!);
|
|
186
186
|
const byteLength = bufferView.byteLength !== undefined ? bufferView.byteLength : 0;
|
|
@@ -190,14 +190,14 @@ export class GLTFLoader {
|
|
|
190
190
|
|
|
191
191
|
|
|
192
192
|
private async loadMaterial(materialName: string): Promise<MaterialStandardData> {
|
|
193
|
-
if(!this._content.materials![materialName]) throw new Error('Material not available.')
|
|
193
|
+
if(!this._content.materials![materialName]) throw new Error('Material not available.');
|
|
194
194
|
const material: IGLTF_v1_Material = this._content.materials![materialName];
|
|
195
195
|
const materialData = new MaterialStandardData();
|
|
196
196
|
if(material.name !== undefined) materialData.name = material.name;
|
|
197
197
|
|
|
198
198
|
if(material.extensions && material.extensions.KHR_materials_common) {
|
|
199
199
|
const technique = material.extensions.KHR_materials_common.technique;
|
|
200
|
-
if(technique && technique !== 'BLINN') this._logger.warn('The technique ' + technique + ' is not supported. Trying to load the material either way.')
|
|
200
|
+
if(technique && technique !== 'BLINN') this._logger.warn('The technique ' + technique + ' is not supported. Trying to load the material either way.');
|
|
201
201
|
const values = material.extensions.KHR_materials_common.values;
|
|
202
202
|
|
|
203
203
|
if (values.hasOwnProperty('doubleSided'))
|
|
@@ -209,7 +209,7 @@ export class GLTFLoader {
|
|
|
209
209
|
materialData.color = diffuseScaled;
|
|
210
210
|
materialData.opacity = Math.max(0.0, Math.min(values.diffuse[3], 1.0));
|
|
211
211
|
} else if(values.hasOwnProperty('diffuse')) {
|
|
212
|
-
this._logger.warn('GLTFLoader.loadMaterial: The value diffuse was set for a material, but is not supported in that type.')
|
|
212
|
+
this._logger.warn('GLTFLoader.loadMaterial: The value diffuse was set for a material, but is not supported in that type.');
|
|
213
213
|
}
|
|
214
214
|
|
|
215
215
|
if (!values.hasOwnProperty('diffuse') && values.hasOwnProperty('ambient')) {
|
|
@@ -220,7 +220,7 @@ export class GLTFLoader {
|
|
|
220
220
|
if (values.hasOwnProperty('emission') && Array.isArray(values.emission)) {
|
|
221
221
|
materialData.emissiveness = values.emission;
|
|
222
222
|
} else if (values.hasOwnProperty('emission')) {
|
|
223
|
-
this._logger.warn('GLTFLoader.loadMaterial: The value emission was set for a material, but is not supported in that type.')
|
|
223
|
+
this._logger.warn('GLTFLoader.loadMaterial: The value emission was set for a material, but is not supported in that type.');
|
|
224
224
|
}
|
|
225
225
|
|
|
226
226
|
if (values.hasOwnProperty('shininess')) {
|
|
@@ -244,7 +244,7 @@ export class GLTFLoader {
|
|
|
244
244
|
}
|
|
245
245
|
|
|
246
246
|
private async loadMesh(meshName: string): Promise<ITreeNode> {
|
|
247
|
-
if (!this._content.meshes![meshName]) throw new Error('Mesh not available.')
|
|
247
|
+
if (!this._content.meshes![meshName]) throw new Error('Mesh not available.');
|
|
248
248
|
const mesh = this._content.meshes![meshName];
|
|
249
249
|
const meshNode = new TreeNode(meshName);
|
|
250
250
|
|
|
@@ -253,16 +253,16 @@ export class GLTFLoader {
|
|
|
253
253
|
const primitiveNode = new TreeNode('primitive_' + i);
|
|
254
254
|
meshNode.addChild(primitiveNode);
|
|
255
255
|
|
|
256
|
-
|
|
256
|
+
const primitive = mesh.primitives![i];
|
|
257
257
|
const attributes: {
|
|
258
258
|
[key: string]: AttributeData
|
|
259
259
|
} = {};
|
|
260
260
|
|
|
261
|
-
for (
|
|
261
|
+
for (const attribute in primitive.attributes) {
|
|
262
262
|
// attribute name conversion to be consistent witg gltf
|
|
263
263
|
let attributeName = attribute;
|
|
264
264
|
if(/\d/.test(attributeName) && !attributeName.includes('_')) {
|
|
265
|
-
const index = attributeName.search(/\d/)
|
|
265
|
+
const index = attributeName.search(/\d/);
|
|
266
266
|
attributeName = attributeName.substring(0, index) + '_' + attributeName.substring(index, attributeName.length);
|
|
267
267
|
} else if(attributeName === 'TEXCOORD' || attributeName === 'COLOR' || attributeName === 'JOINTS' || attributeName === 'WEIGHTS') {
|
|
268
268
|
attributeName += '_0';
|
|
@@ -272,7 +272,7 @@ export class GLTFLoader {
|
|
|
272
272
|
|
|
273
273
|
attributes[attributeName] = await this.loadAccessor(primitive.attributes[attribute]);
|
|
274
274
|
if(attributeName.startsWith('COLOR'))
|
|
275
|
-
attributes[attributeName] = new AttributeData(attributes[attributeName].array, attributes[attributeName].itemSize, attributes[attributeName].itemBytes, attributes[attributeName].byteOffset, attributes[attributeName].elementBytes, true, attributes[attributeName].count, [], [], attributes[attributeName].byteStride, attributes[attributeName].target)
|
|
275
|
+
attributes[attributeName] = new AttributeData(attributes[attributeName].array, attributes[attributeName].itemSize, attributes[attributeName].itemBytes, attributes[attributeName].byteOffset, attributes[attributeName].elementBytes, true, attributes[attributeName].count, [], [], attributes[attributeName].byteStride, attributes[attributeName].target);
|
|
276
276
|
}
|
|
277
277
|
|
|
278
278
|
let material: MaterialStandardData | undefined;
|
|
@@ -286,7 +286,7 @@ export class GLTFLoader {
|
|
|
286
286
|
}
|
|
287
287
|
|
|
288
288
|
private async loadNode(nodeName: string): Promise<ITreeNode> {
|
|
289
|
-
if (!this._content.nodes![nodeName]) throw new Error('Node not available.')
|
|
289
|
+
if (!this._content.nodes![nodeName]) throw new Error('Node not available.');
|
|
290
290
|
const node = this._content.nodes![nodeName];
|
|
291
291
|
const nodeDef = new TreeNode(nodeName);
|
|
292
292
|
|
|
@@ -337,15 +337,15 @@ export class GLTFLoader {
|
|
|
337
337
|
}
|
|
338
338
|
|
|
339
339
|
private async loadScene(): Promise<ITreeNode> {
|
|
340
|
-
if (!this._content.scene) throw new Error('No scene.')
|
|
341
|
-
if (!this._content.scenes![this._content.scene!]) throw new Error('Scene not available.')
|
|
340
|
+
if (!this._content.scene) throw new Error('No scene.');
|
|
341
|
+
if (!this._content.scenes![this._content.scene!]) throw new Error('Scene not available.');
|
|
342
342
|
const scene = this._content.scenes![this._content.scene!];
|
|
343
343
|
const sceneDef = new TreeNode(this._content.scene!);
|
|
344
|
-
if(this._content.asset && this._content.asset?.generator !==
|
|
344
|
+
if(this._content.asset && this._content.asset?.generator !== 'ShapeDiverGltfWriter' && this._content.asset?.generator !== 'ShapeDiverGltfV1Writer') {
|
|
345
345
|
sceneDef.addTransformation({
|
|
346
346
|
id: this._uuidGenerator.create(),
|
|
347
347
|
matrix: this._globalTransformation
|
|
348
|
-
})
|
|
348
|
+
});
|
|
349
349
|
}
|
|
350
350
|
if(scene.nodes)
|
|
351
351
|
for (let i = 0, len = scene.nodes!.length; i < len; i++)
|
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
|
|