@kitware/vtk.js 33.0.0-beta.2 → 33.0.0-beta.4

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.
Files changed (87) hide show
  1. package/Common/Core/DataArray.d.ts +21 -0
  2. package/Common/Core/DataArray.js +39 -0
  3. package/Common/Core/Math/index.js +1 -1
  4. package/Common/Core/Math.js +1 -1
  5. package/Common/Core/URLExtract.js +2 -6
  6. package/Common/DataModel/Line.js +1 -0
  7. package/Common/DataModel/PolyLine.js +4 -0
  8. package/Filters/Core/ThresholdPoints.d.ts +72 -0
  9. package/Filters/Core/ThresholdPoints.js +219 -0
  10. package/Filters/General/ContourTriangulator/helper.js +1 -1
  11. package/IO/Core/DataAccessHelper/JSZipDataAccessHelper.js +1 -1
  12. package/IO/Geometry/DracoReader.d.ts +4 -4
  13. package/IO/Geometry/DracoReader.js +154 -105
  14. package/IO/Geometry/GLTFImporter/Animations.js +239 -0
  15. package/IO/Geometry/GLTFImporter/Constants.js +87 -0
  16. package/IO/Geometry/GLTFImporter/Decoder.js +69 -0
  17. package/IO/Geometry/GLTFImporter/Extensions.js +110 -0
  18. package/IO/Geometry/GLTFImporter/ORMTexture.worker.js +42 -0
  19. package/IO/Geometry/GLTFImporter/Parser.js +359 -0
  20. package/IO/Geometry/GLTFImporter/Reader.js +518 -0
  21. package/IO/Geometry/GLTFImporter/Utils.js +165 -0
  22. package/IO/Geometry/GLTFImporter.d.ts +266 -0
  23. package/IO/Geometry/GLTFImporter.js +245 -0
  24. package/IO/Geometry/IFCImporter.d.ts +163 -0
  25. package/IO/Geometry/IFCImporter.js +270 -0
  26. package/IO/Geometry/STLReader.d.ts +14 -0
  27. package/IO/Geometry/STLReader.js +57 -1
  28. package/IO/Geometry.js +5 -1
  29. package/IO/Image/HDRReader/Utils.js +1 -1
  30. package/IO/Image/HDRReader.js +1 -1
  31. package/IO/Image/TGAReader/Constants.js +28 -0
  32. package/IO/Image/TGAReader.d.ts +121 -0
  33. package/IO/Image/TGAReader.js +418 -0
  34. package/IO/Image/TIFFReader.d.ts +133 -0
  35. package/IO/Image/TIFFReader.js +144 -0
  36. package/IO/Image.js +5 -1
  37. package/IO/XML/XMLPolyDataWriter.js +1 -0
  38. package/Interaction/Manipulators/MouseCameraTrackballRollManipulator.js +1 -1
  39. package/Interaction/Style/InteractorStyleTrackballCamera.js +1 -1
  40. package/Rendering/Core/AbstractImageMapper.d.ts +81 -0
  41. package/Rendering/Core/AbstractImageMapper.js +5 -2
  42. package/Rendering/Core/AbstractPicker.d.ts +13 -13
  43. package/Rendering/Core/AbstractPicker.js +1 -1
  44. package/Rendering/Core/Actor2D.d.ts +22 -0
  45. package/Rendering/Core/Actor2D.js +1 -1
  46. package/Rendering/Core/CellPicker.js +4 -1
  47. package/Rendering/Core/Glyph3DMapper.d.ts +45 -29
  48. package/Rendering/Core/ImageCPRMapper.js +6 -5
  49. package/Rendering/Core/ImageProperty.d.ts +42 -1
  50. package/Rendering/Core/ImageProperty.js +7 -5
  51. package/Rendering/Core/ImageResliceMapper.d.ts +1 -2
  52. package/Rendering/Core/ImageResliceMapper.js +5 -4
  53. package/Rendering/Core/PointPicker.js +10 -1
  54. package/Rendering/Core/Prop3D.js +1 -1
  55. package/Rendering/Core/RenderWindowInteractor.d.ts +1 -1
  56. package/Rendering/Core/RenderWindowInteractor.js +1 -1
  57. package/Rendering/Core/Viewport.js +13 -3
  58. package/Rendering/Core/VolumeMapper.d.ts +70 -0
  59. package/Rendering/Core/VolumeMapper.js +10 -5
  60. package/Rendering/Core/VolumeProperty.d.ts +20 -1
  61. package/Rendering/Core/VolumeProperty.js +7 -5
  62. package/Rendering/Misc/CanvasView.js +4 -2
  63. package/Rendering/Misc/RemoteView.d.ts +9 -3
  64. package/Rendering/Misc/RemoteView.js +7 -3
  65. package/Rendering/Misc/SynchronizableRenderWindow/BehaviorManager/CameraSynchronizer.js +2 -2
  66. package/Rendering/Misc/SynchronizableRenderWindow/ObjectManager.d.ts +1 -1
  67. package/Rendering/OpenGL/ImageCPRMapper.js +18 -2
  68. package/Rendering/OpenGL/ImageMapper.js +42 -11
  69. package/Rendering/OpenGL/ImageResliceMapper.js +20 -4
  70. package/Rendering/OpenGL/Renderer.js +1 -1
  71. package/Rendering/OpenGL/Texture/supportsNorm16Linear.js +97 -0
  72. package/Rendering/OpenGL/Texture.d.ts +29 -8
  73. package/Rendering/OpenGL/Texture.js +172 -34
  74. package/Rendering/OpenGL/VolumeMapper.js +22 -4
  75. package/Rendering/SceneGraph/ViewNode.js +12 -2
  76. package/Rendering/WebXR/RenderWindowHelper.js +9 -0
  77. package/Widgets/Core/WidgetManager.d.ts +12 -1
  78. package/Widgets/Representations/WidgetRepresentation.d.ts +1 -7
  79. package/Widgets/Widgets3D/AngleWidget/behavior.js +2 -0
  80. package/Widgets/Widgets3D/InteractiveOrientationWidget.js +1 -1
  81. package/Widgets/Widgets3D/ResliceCursorWidget/behavior.js +17 -0
  82. package/Widgets/Widgets3D/ResliceCursorWidget/helpers.js +1 -0
  83. package/Widgets/Widgets3D/ResliceCursorWidget.d.ts +1 -8
  84. package/Widgets/Widgets3D/ShapeWidget/behavior.js +3 -0
  85. package/_virtual/rollup-plugin-worker-loader__module_Sources/IO/Geometry/GLTFImporter/ORMTexture.worker.js +296 -0
  86. package/index.d.ts +5 -0
  87. package/package.json +19 -17
@@ -0,0 +1,69 @@
1
+ import BinaryHelper from '../../Core/BinaryHelper.js';
2
+ import { BINARY_HEADER_MAGIC, BINARY_CHUNK_TYPES, BINARY_CHUNK_HEADER_INTS, BINARY_HEADER_LENGTH, BINARY_HEADER_INTS } from './Constants.js';
3
+
4
+ function getChunkInfo(headerStart, data) {
5
+ const header = new Uint32Array(data, headerStart, BINARY_CHUNK_HEADER_INTS);
6
+ const chunkStart = headerStart + BINARY_CHUNK_HEADER_INTS * 4;
7
+ const chunkLength = header[0];
8
+ const chunkType = header[1];
9
+ return {
10
+ start: chunkStart,
11
+ length: chunkLength,
12
+ type: chunkType
13
+ };
14
+ }
15
+ function getAllChunkInfos(data) {
16
+ const infos = [];
17
+ let chunkStart = BINARY_HEADER_INTS * 4;
18
+ while (chunkStart < data.byteLength) {
19
+ const chunkInfo = getChunkInfo(chunkStart, data);
20
+ infos.push(chunkInfo);
21
+ chunkStart += chunkInfo.length + BINARY_CHUNK_HEADER_INTS * 4;
22
+ }
23
+ return infos;
24
+ }
25
+ function getJsonFromChunk(chunkInfo, data) {
26
+ const chunkLength = chunkInfo.length;
27
+ const jsonStart = (BINARY_HEADER_INTS + BINARY_CHUNK_HEADER_INTS) * 4;
28
+ const jsonSlice = new Uint8Array(data, jsonStart, chunkLength);
29
+ const stringBuffer = BinaryHelper.arrayBufferToString(jsonSlice);
30
+ return JSON.parse(stringBuffer);
31
+ }
32
+ function getBufferFromChunk(chunkInfo, data) {
33
+ return data.slice(chunkInfo.start, chunkInfo.start + chunkInfo.length);
34
+ }
35
+ function parseGLB(data) {
36
+ let json;
37
+ const buffers = [];
38
+ const headerView = new DataView(data, 0, BINARY_HEADER_LENGTH);
39
+ const header = {
40
+ magic: BinaryHelper.arrayBufferToString(new Uint8Array(data, 0, 4)),
41
+ version: headerView.getUint32(4, true),
42
+ length: headerView.getUint32(8, true)
43
+ };
44
+ if (header.magic !== BINARY_HEADER_MAGIC) {
45
+ throw new Error('Unsupported glTF-Binary header.');
46
+ } else if (header.version < 2.0) {
47
+ throw new Error('Unsupported legacy binary file detected.');
48
+ }
49
+ const chunkInfos = getAllChunkInfos(data);
50
+ chunkInfos.forEach(chunkInfo => {
51
+ if (chunkInfo.type === BINARY_CHUNK_TYPES.JSON && !json) {
52
+ json = getJsonFromChunk(chunkInfo, data);
53
+ } else if (chunkInfo.type === BINARY_CHUNK_TYPES.BIN) {
54
+ buffers.push(getBufferFromChunk(chunkInfo, data));
55
+ }
56
+ });
57
+ if (!json) {
58
+ throw new Error('glTF-Binary: JSON content not found.');
59
+ }
60
+ if (!buffers) {
61
+ throw new Error('glTF-Binary: Binary chunk not found.');
62
+ }
63
+ return {
64
+ json,
65
+ buffers
66
+ };
67
+ }
68
+
69
+ export { parseGLB as default };
@@ -0,0 +1,110 @@
1
+ import { m as macro } from '../../../macros2.js';
2
+ import { r as radiansFromDegrees } from '../../../Common/Core/Math/index.js';
3
+ import vtkDracoReader from '../DracoReader.js';
4
+ import vtkLight from '../../../Rendering/Core/Light.js';
5
+ import { MIN_LIGHT_ATTENUATION } from './Constants.js';
6
+
7
+ const {
8
+ vtkWarningMacro
9
+ } = macro;
10
+
11
+ /**
12
+ * Handles the KHR_materials_unlit extension.
13
+ *
14
+ * @param {object} extension - The KHR_materials_unlit extension object.
15
+ * @param {vtkProperty} property - The vtkProperty instance to update.
16
+ */
17
+ function handleKHRMaterialsUnlit(extension, property) {
18
+ property.setLighting(true);
19
+ }
20
+
21
+ /**
22
+ * Handles the KHR_materials_ior extension.
23
+ *
24
+ * @param {object} extension - The KHR_materials_unlit extension object.
25
+ * @param {vtkProperty} property - The vtkProperty instance to update.
26
+ */
27
+ function handleKHRMaterialsIor(extension, property) {
28
+ property.setBaseIOR(extension.ior);
29
+ }
30
+
31
+ /**
32
+ * Handles the KHR_materials_specular extension.
33
+ * @param {object} extension - The KHR_materials_specular extension object.
34
+ * @param {vtkProperty} property - The vtkProperty instance to update.
35
+ */
36
+ function handleKHRMaterialsSpecular(extension, property) {
37
+ property.setSpecular(extension.specularFactor);
38
+ property.setSpecularColor(extension.specularColorFactor);
39
+ }
40
+
41
+ /**
42
+ * Handles the KHR_lights_punctual extension.
43
+ *
44
+ * @param {object} extension - The KHR_lights_punctual extension object.
45
+ * @param {vtkRenderer} renderer - The vtkRenderer instance to add the light to.
46
+ */
47
+ function handleKHRLightsPunctual(extension, transformMatrix, model) {
48
+ const {
49
+ light
50
+ } = extension;
51
+ const {
52
+ color,
53
+ intensity,
54
+ range,
55
+ spot,
56
+ type
57
+ } = light;
58
+ const l = vtkLight.newInstance({
59
+ color: color || [1, 1, 1],
60
+ intensity: intensity || 1.0
61
+ });
62
+
63
+ // Apply the global transform to the light
64
+ l.setTransformMatrix(transformMatrix);
65
+
66
+ // Handle range
67
+ if (range > 0) {
68
+ // Set quadratic values to get attenuation(range) ~= MIN_LIGHT_ATTENUATION
69
+ l.setAttenuationValues(1, 0, 1.0 / (range * range * MIN_LIGHT_ATTENUATION));
70
+ }
71
+ switch (type) {
72
+ case 'directional':
73
+ l.setPositional(false);
74
+ break;
75
+ case 'point':
76
+ l.setPositional(true);
77
+ l.setConeAngle(90);
78
+ break;
79
+ case 'spot':
80
+ l.setPositional(true);
81
+ l.setConeAngle(radiansFromDegrees(spot.outerConeAngle));
82
+ break;
83
+ default:
84
+ vtkWarningMacro(`Unsupported light type: ${type}`);
85
+ }
86
+ model.lights.set(light.name, l);
87
+ }
88
+
89
+ /**
90
+ * Handles the KHR_draco_mesh_compression extension.
91
+ *
92
+ * @param {object} extension - The KHR_draco_mesh_compression extension object.
93
+ */
94
+ function handleKHRDracoMeshCompression(extension) {
95
+ const reader = vtkDracoReader.newInstance();
96
+ reader.parse(extension.bufferView);
97
+ return reader.getOutputData();
98
+ }
99
+
100
+ /**
101
+ * Handles the KHR_materials_variants extension.
102
+ *
103
+ * @param {object} extension - The KHR_materials_variants extension object.
104
+ * @param {object} model - The model object to update with variant information.
105
+ */
106
+ function handleKHRMaterialsVariants(extension, model) {
107
+ model.variants = extension.variants.map(v => v.name);
108
+ }
109
+
110
+ export { handleKHRDracoMeshCompression, handleKHRLightsPunctual, handleKHRMaterialsIor, handleKHRMaterialsSpecular, handleKHRMaterialsUnlit, handleKHRMaterialsVariants };
@@ -0,0 +1,42 @@
1
+ import registerWebworker from 'webworker-promise/lib/register';
2
+
3
+ /**
4
+ *
5
+ * @param {ArrayBuffer} imageBuffer
6
+ * @param {string} mimeType
7
+ * @param {string} channel
8
+ * @returns {Promise<ImageData>}
9
+ */
10
+ registerWebworker(async _ref => {
11
+ let {
12
+ imageBuffer,
13
+ mimeType,
14
+ channel
15
+ } = _ref;
16
+ const channelsMap = {
17
+ r: 0,
18
+ g: 1,
19
+ b: 2
20
+ };
21
+ const blob = new Blob([imageBuffer], {
22
+ type: mimeType
23
+ });
24
+ const img = await createImageBitmap(blob);
25
+ const canvas = new OffscreenCanvas(img.width, img.height);
26
+ const ctx = canvas.getContext('2d');
27
+ ctx.drawImage(img, 0, 0, img.width, img.height);
28
+ const bitmap = ctx.getImageData(0, 0, img.width, img.height);
29
+ if (channel) {
30
+ const idx = channelsMap[channel];
31
+ for (let i = 0; i < bitmap.data.length; i += 4) {
32
+ const channelValue = bitmap.data[i + idx];
33
+ bitmap.data[i] = channelValue; // red channel
34
+ bitmap.data[i + 1] = channelValue; // green channel
35
+ bitmap.data[i + 2] = channelValue; // blue channel
36
+ }
37
+ }
38
+
39
+ return {
40
+ bitmap
41
+ };
42
+ });
@@ -0,0 +1,359 @@
1
+ import { m as macro } from '../../../macros2.js';
2
+ import { SEMANTIC_ATTRIBUTE_MAP, MODES, ALPHA_MODE, BYTES, COMPONENTS, DEFAULT_SAMPLER, GL_SAMPLER } from './Constants.js';
3
+ import { getAccessorArrayTypeAndLength, resolveUrl, getGLEnumFromSamplerParameter } from './Utils.js';
4
+
5
+ /* eslint-disable guard-for-in */
6
+ const {
7
+ vtkDebugMacro,
8
+ vtkWarningMacro
9
+ } = macro;
10
+ class GLTFParser {
11
+ constructor(glTF) {
12
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
13
+ const {
14
+ json,
15
+ baseUri = ''
16
+ } = glTF;
17
+ this.glTF = glTF;
18
+ this.options = options;
19
+ this.baseUri = baseUri;
20
+ this.json = json;
21
+ this.extensions = json.extensions || {};
22
+ this.extensionsUsed = json.extensionsUsed || [];
23
+ }
24
+ async parse() {
25
+ const buffers = this.json.buffers || [];
26
+ this.buffers = new Array(buffers.length).fill(null);
27
+ const images = this.json.images || [];
28
+ this.images = new Array(images.length).fill({});
29
+ await this.loadBuffers();
30
+ await this.loadImages();
31
+ this.resolveTree();
32
+ return this.glTF.json;
33
+ }
34
+ resolveTree() {
35
+ this.json.scenes = this.json.scenes?.map((scene, idx) => this.resolveScene(scene, idx));
36
+ this.json.cameras = this.json.cameras?.map((camera, idx) => this.resolveCamera(camera, idx));
37
+ this.json.bufferViews = this.json.bufferViews?.map((bufView, idx) => this.resolveBufferView(bufView, idx));
38
+ this.json.images = this.json.images?.map((image, idx) => this.resolveImage(image, idx));
39
+ this.json.samplers = this.json.samplers?.map((sampler, idx) => this.resolveSampler(sampler, idx));
40
+ this.json.textures = this.json.textures?.map((texture, idx) => this.resolveTexture(texture, idx));
41
+ this.json.accessors = this.json.accessors?.map((accessor, idx) => this.resolveAccessor(accessor, idx));
42
+ this.json.materials = this.json.materials?.map((material, idx) => this.resolveMaterial(material, idx));
43
+ this.json.meshes = this.json.meshes?.map((mesh, idx) => this.resolveMesh(mesh, idx));
44
+ this.json.nodes = this.json.nodes?.map((node, idx) => this.resolveNode(node, idx));
45
+ this.json.skins = this.json.skins?.map((skin, idx) => this.resolveSkin(skin, idx));
46
+ this.json.animations = this.json.animations?.map((animation, idx) => this.resolveAnimation(animation, idx));
47
+ }
48
+ get(array, index) {
49
+ // check if already resolved
50
+ if (typeof index === 'object') {
51
+ return index;
52
+ }
53
+ const object = this.json[array] && this.json[array][index];
54
+ if (!object) {
55
+ vtkWarningMacro(`glTF file error: Could not find ${array}[${index}]`);
56
+ }
57
+ return object;
58
+ }
59
+ resolveScene(scene, index) {
60
+ scene.id = scene.id || `scene-${index}`;
61
+ scene.nodes = (scene.nodes || []).map(node => this.get('nodes', node));
62
+ return scene;
63
+ }
64
+ resolveNode(node, index) {
65
+ node.id = node.id || `node-${index}`;
66
+ if (node.children) {
67
+ node.children = node.children.map(child => this.get('nodes', child));
68
+ }
69
+ if (node.mesh !== undefined) {
70
+ node.mesh = this.get('meshes', node.mesh);
71
+ } else if (node.meshes !== undefined && node.meshes.length) {
72
+ node.mesh = node.meshes.reduce((accum, meshIndex) => {
73
+ const mesh = this.get('meshes', meshIndex);
74
+ accum.id = mesh.id;
75
+ accum.primitives = accum.primitives.concat(mesh.primitives);
76
+ return accum;
77
+ }, {
78
+ primitives: []
79
+ });
80
+ }
81
+ if (node.camera !== undefined) {
82
+ node.camera = this.get('cameras', node.camera);
83
+ }
84
+ if (node.skin !== undefined) {
85
+ node.skin = this.get('skins', node.skin);
86
+ }
87
+
88
+ // Fill punctual lights objects
89
+ if (node.extensions?.KHR_lights_punctual) {
90
+ node.extensions.KHR_lights_punctual.light = this.extensions?.KHR_lights_punctual.lights[node.extensions.KHR_lights_punctual.light];
91
+ }
92
+ return node;
93
+ }
94
+ resolveSkin(skin, index) {
95
+ skin.id = skin.id || `skin-${index}`;
96
+ skin.inverseBindMatrices = this.get('accessors', skin.inverseBindMatrices);
97
+ return skin;
98
+ }
99
+ resolveMesh(mesh, index) {
100
+ mesh.id = mesh.id || `mesh-${index}`;
101
+ if (mesh.primitives) {
102
+ mesh.primitives = mesh.primitives.map((primitive, idx) => {
103
+ const attributes = primitive.attributes;
104
+ primitive.name = `primitive-${idx}`;
105
+ primitive.attributes = {};
106
+ for (const attribute in attributes) {
107
+ const attr = SEMANTIC_ATTRIBUTE_MAP[attribute];
108
+ primitive.attributes[attr] = this.get('accessors', attributes[attribute]);
109
+ }
110
+ if (primitive.indices !== undefined) {
111
+ primitive.indices = this.get('accessors', primitive.indices);
112
+ }
113
+ if (primitive.material !== undefined) {
114
+ primitive.material = this.get('materials', primitive.material);
115
+ }
116
+ if (primitive.mode === undefined) {
117
+ primitive.mode = MODES.GL_TRIANGLES; // Default one
118
+ }
119
+
120
+ if (primitive.extensions?.KHR_draco_mesh_compression) {
121
+ vtkDebugMacro('Using Draco mesh compression');
122
+ const bufferView = this.get('bufferViews', primitive.extensions.KHR_draco_mesh_compression.bufferView);
123
+ primitive.extensions.KHR_draco_mesh_compression.bufferView = bufferView.data;
124
+ }
125
+ return primitive;
126
+ });
127
+ }
128
+ return mesh;
129
+ }
130
+ resolveMaterial(material, index) {
131
+ material.id = material.id || `material-${index}`;
132
+ if (material.alphaMode === undefined) material.alphaMode = ALPHA_MODE.OPAQUE;
133
+ if (material.doubleSided === undefined) material.doubleSided = false;
134
+ if (material.alphaCutoff === undefined) material.alphaCutoff = 0.5;
135
+ if (material.normalTexture) {
136
+ material.normalTexture = {
137
+ ...material.normalTexture
138
+ };
139
+ material.normalTexture.texture = this.get('textures', material.normalTexture.index);
140
+ }
141
+ if (material.occlusionTexture) {
142
+ material.occlusionTexture = {
143
+ ...material.occlusionTexture
144
+ };
145
+ material.occlusionTexture.texture = this.get('textures', material.occlusionTexture.index);
146
+ }
147
+ if (material.emissiveTexture) {
148
+ material.emissiveTexture = {
149
+ ...material.emissiveTexture
150
+ };
151
+ material.emissiveTexture.texture = this.get('textures', material.emissiveTexture.index);
152
+ }
153
+ if (!material.emissiveFactor) {
154
+ material.emissiveFactor = material.emissiveTexture ? 1 : 0;
155
+ } else material.emissiveFactor = material.emissiveFactor[0];
156
+ if (material.pbrMetallicRoughness) {
157
+ material.pbrMetallicRoughness = {
158
+ ...material.pbrMetallicRoughness
159
+ };
160
+ const mr = material.pbrMetallicRoughness;
161
+ if (mr.baseColorTexture) {
162
+ mr.baseColorTexture = {
163
+ ...mr.baseColorTexture
164
+ };
165
+ mr.baseColorTexture.texture = this.get('textures', mr.baseColorTexture.index);
166
+ }
167
+ if (mr.metallicRoughnessTexture) {
168
+ mr.metallicRoughnessTexture = {
169
+ ...mr.metallicRoughnessTexture
170
+ };
171
+ mr.metallicRoughnessTexture.texture = this.get('textures', mr.metallicRoughnessTexture.index);
172
+ }
173
+ } else {
174
+ material.pbrMetallicRoughness = {
175
+ baseColorFactor: [1, 1, 1, 1],
176
+ metallicFactor: 1.0,
177
+ roughnessFactor: 1.0
178
+ };
179
+ }
180
+ return material;
181
+ }
182
+
183
+ /**
184
+ * Take values of particular accessor from interleaved buffer various parts of
185
+ * the buffer
186
+ */
187
+ getValueFromInterleavedBuffer(buffer, byteOffset, byteStride, bytesPerElement, count) {
188
+ const result = new Uint8Array(count * bytesPerElement);
189
+ for (let i = 0; i < count; i++) {
190
+ const elementOffset = byteOffset + i * byteStride;
191
+ result.set(new Uint8Array(buffer.arrayBuffer.slice(elementOffset, elementOffset + bytesPerElement)), i * bytesPerElement);
192
+ }
193
+ return result.buffer;
194
+ }
195
+ resolveAccessor(accessor, index) {
196
+ accessor.id = accessor.id || `accessor-${index}`;
197
+ if (accessor.bufferView !== undefined) {
198
+ // Draco encoded meshes don't have bufferView
199
+ accessor.bufferView = this.get('bufferViews', accessor.bufferView);
200
+ }
201
+
202
+ // Look up enums
203
+ accessor.bytesPerComponent = BYTES[accessor.componentType];
204
+ accessor.components = COMPONENTS[accessor.type];
205
+ accessor.bytesPerElement = accessor.bytesPerComponent * accessor.components;
206
+
207
+ // Create TypedArray for the accessor
208
+ // Note: The canonical way to instantiate is to ignore this array and create
209
+ // WebGLBuffer's using the bufferViews.
210
+ if (accessor.bufferView) {
211
+ const buffer = accessor.bufferView.buffer;
212
+ const {
213
+ ArrayType,
214
+ byteLength
215
+ } = getAccessorArrayTypeAndLength(accessor, accessor.bufferView);
216
+ const byteOffset = (accessor.bufferView.byteOffset || 0) + (accessor.byteOffset || 0) + buffer.byteOffset;
217
+ let slicedBufffer = buffer.arrayBuffer.slice(byteOffset, byteOffset + byteLength);
218
+ if (accessor.bufferView.byteStride) {
219
+ slicedBufffer = this.getValueFromInterleavedBuffer(buffer, byteOffset, accessor.bufferView.byteStride, accessor.bytesPerElement, accessor.count);
220
+ }
221
+ accessor.value = new ArrayType(slicedBufffer);
222
+ }
223
+ return accessor;
224
+ }
225
+ resolveTexture(texture, index) {
226
+ texture.id = texture.id || `texture-${index}`;
227
+ texture.sampler = 'sampler' in texture ? this.get('samplers', texture.sampler) : DEFAULT_SAMPLER;
228
+ texture.source = this.get('images', texture.source);
229
+
230
+ // Handle texture extensions sources
231
+ if (texture.extensions !== undefined) {
232
+ const extensionsNames = Object.keys(texture.extensions);
233
+ extensionsNames.forEach(extensionName => {
234
+ const extension = texture.extensions[extensionName];
235
+ switch (extensionName) {
236
+ case 'KHR_texture_basisu':
237
+ case 'EXT_texture_webp':
238
+ case 'EXT_texture_avif':
239
+ texture.source = this.get('images', extension.source);
240
+ break;
241
+ default:
242
+ vtkWarningMacro(`Unhandled extension: ${extensionName}`);
243
+ }
244
+ });
245
+ }
246
+ return texture;
247
+ }
248
+ resolveSampler(sampler, index) {
249
+ sampler.id = sampler.id || `sampler-${index}`;
250
+ if (!Object.hasOwn(sampler, 'wrapS')) sampler.wrapS = GL_SAMPLER.REPEAT;
251
+ if (!Object.hasOwn(sampler, 'wrapT')) sampler.wrapT = GL_SAMPLER.REPEAT;
252
+ if (!Object.hasOwn(sampler, 'minFilter')) sampler.minFilter = GL_SAMPLER.LINEAR_MIPMAP_LINEAR;
253
+ if (!Object.hasOwn(sampler, 'magFilter')) sampler.magFilter = GL_SAMPLER.NEAREST;
254
+
255
+ // Map textual parameters to GL parameter values
256
+ sampler.parameters = {};
257
+ for (const key in sampler) {
258
+ const glEnum = getGLEnumFromSamplerParameter(key);
259
+ if (glEnum !== undefined) {
260
+ sampler.parameters[glEnum] = sampler[key];
261
+ }
262
+ }
263
+ return sampler;
264
+ }
265
+ resolveImage(image, index) {
266
+ image.id = image.id || `image-${index}`;
267
+ if (image.bufferView !== undefined) {
268
+ image.bufferView = this.get('bufferViews', image.bufferView);
269
+ }
270
+ return image;
271
+ }
272
+ resolveBufferView(bufferView, index) {
273
+ bufferView.id = bufferView.id || `bufferView-${index}`;
274
+ const bufferIndex = bufferView.buffer;
275
+ bufferView.buffer = this.buffers[bufferIndex];
276
+ const arrayBuffer = this.buffers[bufferIndex].arrayBuffer;
277
+ let byteOffset = this.buffers[bufferIndex].byteOffset || 0;
278
+ if ('byteOffset' in bufferView) {
279
+ byteOffset += bufferView.byteOffset;
280
+ }
281
+ bufferView.data = new Uint8Array(arrayBuffer, byteOffset, bufferView.byteLength);
282
+ return bufferView;
283
+ }
284
+ resolveCamera(camera, index) {
285
+ camera.id = camera.id || `camera-${index}`;
286
+ return camera;
287
+ }
288
+ resolveAnimation(animation, index) {
289
+ animation.id = animation.id || `animation-${index}`;
290
+ animation.samplers.map(sampler => {
291
+ sampler.input = this.get('accessors', sampler.input).value;
292
+ sampler.output = this.get('accessors', sampler.output).value;
293
+ return sampler;
294
+ });
295
+ return animation;
296
+ }
297
+ loadBuffers() {
298
+ const promises = this.json.buffers.map((buffer, idx) => this.loadBuffer(buffer, idx).then(() => {
299
+ delete buffer.uri;
300
+ }));
301
+ return Promise.all(promises);
302
+ }
303
+ async loadBuffer(buffer, index) {
304
+ let arrayBuffer = buffer;
305
+ if (buffer.uri) {
306
+ vtkDebugMacro('Loading uri', buffer.uri);
307
+ const uri = resolveUrl(buffer.uri, this.options.baseUri);
308
+ const response = await fetch(uri);
309
+ arrayBuffer = await response.arrayBuffer();
310
+ } else if (this.glTF.glbBuffers) {
311
+ arrayBuffer = this.glTF.glbBuffers[index];
312
+ }
313
+ this.buffers[index] = {
314
+ arrayBuffer,
315
+ byteOffset: 0,
316
+ byteLength: arrayBuffer.byteLength
317
+ };
318
+ }
319
+ loadImages() {
320
+ const images = this.json.images || [];
321
+ const promises = [];
322
+ return new Promise((resolve, reject) => {
323
+ for (let i = 0; i < images.length; ++i) {
324
+ promises.push(Promise.resolve(this.loadImage(images[i], i).then(() => {
325
+ vtkDebugMacro('Texture loaded ', images[i]);
326
+ })));
327
+ }
328
+ Promise.all(promises).then(() => resolve(this.images));
329
+ });
330
+ }
331
+ async loadImage(image, index) {
332
+ let arrayBuffer;
333
+ let buffer;
334
+ if (image.uri) {
335
+ vtkDebugMacro('Loading texture', image.uri);
336
+ const uri = resolveUrl(image.uri, this.options.baseUri);
337
+ const response = await fetch(uri);
338
+ arrayBuffer = await response.arrayBuffer();
339
+ image.uri = uri;
340
+ image.bufferView = {
341
+ data: arrayBuffer
342
+ };
343
+ } else if (image.bufferView) {
344
+ const bufferView = this.get('bufferViews', image.bufferView);
345
+ buffer = this.get('buffers', bufferView.buffer);
346
+
347
+ // GLB buffer
348
+ if (this.glTF.glbBuffers) {
349
+ buffer = this.glTF.glbBuffers[bufferView.buffer];
350
+ arrayBuffer = buffer.slice(bufferView.byteOffset, bufferView.byteOffset + bufferView.byteLength);
351
+ }
352
+ image.bufferView = {
353
+ data: arrayBuffer
354
+ };
355
+ }
356
+ }
357
+ }
358
+
359
+ export { GLTFParser as default };