@kitware/vtk.js 32.7.1 → 32.7.2

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.
@@ -133,7 +133,7 @@ function createAnimationSampler(glTFSampler) {
133
133
  result = cubicSplineInterpolate(path, t0, t1, i0, i1, time);
134
134
  break;
135
135
  default:
136
- throw new Error(`Unknown interpolation method: ${glTFSampler.interpolation}`);
136
+ vtkWarningMacro(`Unknown interpolation method: ${glTFSampler.interpolation}`);
137
137
  }
138
138
  return result;
139
139
  }
@@ -101,7 +101,7 @@ class GLTFParser {
101
101
  if (mesh.primitives) {
102
102
  mesh.primitives = mesh.primitives.map((primitive, idx) => {
103
103
  const attributes = primitive.attributes;
104
- primitive.name = `submesh-${idx}`;
104
+ primitive.name = `primitive-${idx}`;
105
105
  primitive.attributes = {};
106
106
  for (const attribute in attributes) {
107
107
  const attr = SEMANTIC_ATTRIBUTE_MAP[attribute];
@@ -30,18 +30,15 @@ async function parseGLTF(gltf, options) {
30
30
  }
31
31
 
32
32
  /**
33
- * Creates VTK polydata from a GLTF mesh
34
- * @param {GLTFMesh} mesh - The GLTF mesh
33
+ * Creates VTK polydata from a GLTF mesh primitive
34
+ * @param {GLTFPrimitive} primitive - The GLTF mesh primitive
35
35
  * @returns {vtkPolyData} The created VTK polydata
36
36
  */
37
- async function createPolyDataFromGLTFMesh(mesh) {
38
- const primitive = mesh.primitives[0]; // For simplicity, we'll just use the first primitive
39
-
37
+ async function createPolyDataFromGLTFMesh(primitive) {
40
38
  if (!primitive || !primitive.attributes) {
41
- vtkWarningMacro('Mesh has no position data, skipping');
39
+ vtkWarningMacro('Primitive has no position data, skipping');
42
40
  return null;
43
41
  }
44
- const mode = primitive.mode;
45
42
  if (primitive.extensions?.KHR_draco_mesh_compression) {
46
43
  return handleKHRDracoMeshCompression(primitive.extensions.KHR_draco_mesh_compression);
47
44
  }
@@ -118,10 +115,10 @@ async function createPolyDataFromGLTFMesh(mesh) {
118
115
  });
119
116
 
120
117
  // Handle indices if available
121
- if (primitive.indices !== undefined) {
118
+ if (primitive.indices != null) {
122
119
  const indices = primitive.indices.value;
123
120
  const nCells = indices.length - 2;
124
- switch (mode) {
121
+ switch (primitive.mode) {
125
122
  case MODES.GL_LINE_STRIP:
126
123
  case MODES.GL_TRIANGLE_STRIP:
127
124
  case MODES.GL_LINE_LOOP:
@@ -135,7 +132,7 @@ async function createPolyDataFromGLTFMesh(mesh) {
135
132
  }
136
133
  }
137
134
  }
138
- switch (mode) {
135
+ switch (primitive.mode) {
139
136
  case MODES.GL_TRIANGLES:
140
137
  case MODES.GL_TRIANGLE_FAN:
141
138
  polyData.setPolys(cells);
@@ -159,7 +156,7 @@ async function createPolyDataFromGLTFMesh(mesh) {
159
156
 
160
157
  /**
161
158
  * Creates a VTK property from a GLTF material
162
- * @param {*} model - The vtk model object
159
+ * @param {object} model - The vtk model object
163
160
  * @param {GLTFMaterial} material - The GLTF material
164
161
  * @param {vtkActor} actor - The VTK actor
165
162
  */
@@ -169,15 +166,15 @@ async function createPropertyFromGLTFMaterial(model, material, actor) {
169
166
  const emissiveFactor = material.emissiveFactor;
170
167
  const property = actor.getProperty();
171
168
  const pbr = material.pbrMetallicRoughness;
172
- if (pbr !== undefined) {
169
+ if (pbr != null) {
173
170
  if (!pbr?.metallicFactor || pbr?.metallicFactor <= 0 || pbr?.metallicFactor >= 1) {
174
- vtkWarningMacro('Invalid material.pbrMetallicRoughness.metallicFactor value. Using default value instead.');
171
+ vtkDebugMacro('Invalid material.pbrMetallicRoughness.metallicFactor value. Using default value instead.');
175
172
  } else metallicFactor = pbr.metallicFactor;
176
173
  if (!pbr?.roughnessFactor || pbr?.roughnessFactor <= 0 || pbr?.roughnessFactor >= 1) {
177
- vtkWarningMacro('Invalid material.pbrMetallicRoughness.roughnessFactor value. Using default value instead.');
174
+ vtkDebugMacro('Invalid material.pbrMetallicRoughness.roughnessFactor value. Using default value instead.');
178
175
  } else roughnessFactor = pbr.roughnessFactor;
179
176
  const color = pbr.baseColorFactor;
180
- if (color !== undefined) {
177
+ if (color != null) {
181
178
  property.setDiffuseColor(color[0], color[1], color[2]);
182
179
  property.setOpacity(color[3]);
183
180
  }
@@ -187,7 +184,7 @@ async function createPropertyFromGLTFMaterial(model, material, actor) {
187
184
  if (pbr.baseColorTexture) {
188
185
  pbr.baseColorTexture.extensions;
189
186
  const tex = pbr.baseColorTexture.texture;
190
- if (tex.extensions !== undefined) {
187
+ if (tex.extensions != null) {
191
188
  const extensionsNames = Object.keys(tex.extensions);
192
189
  extensionsNames.forEach(extensionName => {
193
190
  // TODO: Handle KHR_texture_basisu extension
@@ -243,7 +240,7 @@ async function createPropertyFromGLTFMaterial(model, material, actor) {
243
240
  property.setEmissionTexture(emissiveTex);
244
241
 
245
242
  // Handle mutiple Uvs
246
- if (material.emissiveTexture.texCoord !== undefined) {
243
+ if (material.emissiveTexture.texCoord != null) {
247
244
  const pd = actor.getMapper().getInputData().getPointData();
248
245
  pd.setActiveTCoords(`TEXCOORD_${material.emissiveTexture.texCoord}`);
249
246
  }
@@ -257,14 +254,14 @@ async function createPropertyFromGLTFMaterial(model, material, actor) {
257
254
  const normalImage = await loadImage(tex.source);
258
255
  const normalTex = createVTKTextureFromGLTFTexture(normalImage, sampler);
259
256
  property.setNormalTexture(normalTex);
260
- if (material.normalTexture.scale !== undefined) {
257
+ if (material.normalTexture.scale != null) {
261
258
  property.setNormalStrength(material.normalTexture.scale);
262
259
  }
263
260
  }
264
261
  }
265
262
 
266
263
  // Material extensions
267
- if (material.extensions !== undefined) {
264
+ if (material.extensions != null) {
268
265
  const extensionsNames = Object.keys(material.extensions);
269
266
  extensionsNames.forEach(extensionName => {
270
267
  const extension = material.extensions[extensionName];
@@ -291,17 +288,17 @@ async function createPropertyFromGLTFMaterial(model, material, actor) {
291
288
 
292
289
  /**
293
290
  * Handles primitive extensions
291
+ * @param {string} nodeId The GLTF node id
294
292
  * @param {*} extensions The extensions object
295
293
  * @param {*} model The vtk model object
296
- * @param {GLTFNode} node The GLTF node
297
294
  */
298
- function handlePrimitiveExtensions(extensions, model, node) {
295
+ function handlePrimitiveExtensions(nodeId, extensions, model) {
299
296
  const extensionsNames = Object.keys(extensions);
300
297
  extensionsNames.forEach(extensionName => {
301
298
  const extension = extensions[extensionName];
302
299
  switch (extensionName) {
303
300
  case 'KHR_materials_variants':
304
- model.variantMappings.set(node.id, extension.mappings);
301
+ model.variantMappings.set(nodeId, extension.mappings);
305
302
  break;
306
303
  default:
307
304
  vtkWarningMacro(`Unhandled extension: ${extensionName}`);
@@ -314,33 +311,43 @@ function handlePrimitiveExtensions(extensions, model, node) {
314
311
  * @param {GLTFMesh} mesh - The GLTF mesh
315
312
  * @returns {vtkActor} The created VTK actor
316
313
  */
317
- async function createActorFromGTLFNode(model, node, worldMatrix) {
314
+ async function createActorFromGTLFNode(worldMatrix) {
318
315
  const actor = vtkActor.newInstance();
319
316
  const mapper = vtkMapper.newInstance();
320
317
  mapper.setColorModeToDirectScalars();
321
318
  actor.setMapper(mapper);
322
319
  actor.setUserMatrix(worldMatrix);
323
- if (node.mesh !== undefined) {
324
- const polyData = await createPolyDataFromGLTFMesh(node.mesh);
325
- mapper.setInputData(polyData);
326
- const primitive = node.mesh.primitives[0]; // the first one for now
320
+ const polydata = vtkPolyData.newInstance();
321
+ mapper.setInputData(polydata);
322
+ return actor;
323
+ }
327
324
 
328
- // Support for materials
329
- if (primitive.material !== undefined) {
330
- await createPropertyFromGLTFMaterial(model, primitive.material, actor);
331
- }
332
- if (primitive.extensions !== undefined) {
333
- handlePrimitiveExtensions(primitive.extensions, model, node);
334
- }
335
- } else {
336
- const polyData = vtkPolyData.newInstance();
337
- mapper.setInputData(polyData);
325
+ /**
326
+ * Creates a VTK actor from a GLTF mesh
327
+ * @param {GLTFMesh} mesh - The GLTF mesh
328
+ * @returns {vtkActor} The created VTK actor
329
+ */
330
+ async function createActorFromGTLFPrimitive(model, primitive, worldMatrix) {
331
+ const actor = vtkActor.newInstance();
332
+ const mapper = vtkMapper.newInstance();
333
+ mapper.setColorModeToDirectScalars();
334
+ actor.setMapper(mapper);
335
+ actor.setUserMatrix(worldMatrix);
336
+ const polydata = await createPolyDataFromGLTFMesh(primitive);
337
+ mapper.setInputData(polydata);
338
+
339
+ // Support for materials
340
+ if (primitive.material != null) {
341
+ await createPropertyFromGLTFMaterial(model, primitive.material, actor);
342
+ }
343
+ if (primitive.extensions != null) {
344
+ handlePrimitiveExtensions(`${primitive.name}`, primitive.extensions, model);
338
345
  }
339
346
  return actor;
340
347
  }
341
348
 
342
349
  /**
343
- *
350
+ * Creates a GLTF animation object
344
351
  * @param {GLTFAnimation} animation
345
352
  * @returns
346
353
  */
@@ -366,7 +373,7 @@ function getTransformationMatrix(node) {
366
373
  const translation = node.translation ?? vec3.create();
367
374
  const rotation = node.rotation ?? quat.create();
368
375
  const scale = node.scale ?? vec3.fromValues(1.0, 1.0, 1.0);
369
- const matrix = node.matrix !== undefined ? mat4.clone(node.matrix) : mat4.fromRotationTranslationScale(mat4.create(), rotation, translation, scale);
376
+ const matrix = node.matrix != null ? mat4.clone(node.matrix) : mat4.fromRotationTranslationScale(mat4.create(), rotation, translation, scale);
370
377
  return matrix;
371
378
  }
372
379
 
@@ -384,13 +391,17 @@ async function processNode(node, model) {
384
391
  const worldMatrix = mat4.multiply(mat4.create(), parentMatrix, node.transform);
385
392
 
386
393
  // Create actor for the current node
387
- const actor = await createActorFromGTLFNode(model, node, worldMatrix);
388
- if (actor) {
389
- actor.setUserMatrix(worldMatrix);
394
+ if (node.mesh != null) {
395
+ const nodeActor = await createActorFromGTLFNode(worldMatrix);
390
396
  if (parentActor) {
391
- actor.setParentProp(parentActor);
397
+ nodeActor.setParentProp(parentActor);
392
398
  }
393
- model.actors.set(node.id, actor);
399
+ model.actors.set(`${node.id}`, nodeActor);
400
+ await Promise.all(node.mesh.primitives.map(async (primitive, i) => {
401
+ const actor = await createActorFromGTLFPrimitive(model, primitive, worldMatrix);
402
+ actor.setParentProp(nodeActor);
403
+ model.actors.set(`${node.id}_${primitive.name}`, actor);
404
+ }));
394
405
  }
395
406
 
396
407
  // Handle KHRLightsPunctual extension
@@ -153,7 +153,7 @@ function createVTKTextureFromGLTFTexture(image, sampler, extensions) {
153
153
  texture.setInterpolate(true);
154
154
  }
155
155
  } else {
156
- texture.MipmapOn();
156
+ texture.setMipLevel(8);
157
157
  texture.setInterpolate(true);
158
158
  texture.setEdgeClamp(true);
159
159
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kitware/vtk.js",
3
- "version": "32.7.1",
3
+ "version": "32.7.2",
4
4
  "description": "Visualization Toolkit for the Web",
5
5
  "keywords": [
6
6
  "3d",