@threlte/gltf 3.0.6 → 3.0.7

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @threlte/gltf
2
2
 
3
+ ## 3.0.7
4
+
5
+ ### Patch Changes
6
+
7
+ - e854fb5: Add multiple SkinnedMesh support
8
+
3
9
  ## 3.0.6
4
10
 
5
11
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@threlte/gltf",
3
- "version": "3.0.6",
3
+ "version": "3.0.7",
4
4
  "description": "GLTF to Threlte converter",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -21,6 +21,9 @@ export function parse(fileName, gltf, options = {}) {
21
21
  const objects = []
22
22
  gltf.scene.traverse((child) => objects.push(child))
23
23
 
24
+ // Detect skinned meshes — these need per-instance cloning
25
+ const hasSkinnedMeshes = objects.some((o) => o.isSkinnedMesh)
26
+
24
27
  // Browse for duplicates
25
28
  const duplicates = {
26
29
  names: {},
@@ -184,14 +187,15 @@ export function parse(fileName, gltf, options = {}) {
184
187
  else result += `material={gltf.${node}.material} `
185
188
  }
186
189
 
187
- if (obj.skeleton) result += `skeleton={gltf.${node}.skeleton} `
190
+ if (obj.skeleton)
191
+ result += `skeleton={${hasSkinnedMeshes ? `clonedNodes${sanitizeName(obj.name)}` : `gltf.${node}`}.skeleton} `
188
192
  if (obj.visible === false) result += `visible={false} `
189
193
  if (obj.castShadow === true) result += `castShadow `
190
194
  if (obj.receiveShadow === true) result += `receiveShadow `
191
195
  if (obj.morphTargetDictionary)
192
- result += `morphTargetDictionary={gltf.${node}.morphTargetDictionary} `
196
+ result += `morphTargetDictionary={${hasSkinnedMeshes ? `clonedNodes${sanitizeName(obj.name)}` : `gltf.${node}`}.morphTargetDictionary} `
193
197
  if (obj.morphTargetInfluences)
194
- result += `morphTargetInfluences={gltf.${node}.morphTargetInfluences} `
198
+ result += `morphTargetInfluences={${hasSkinnedMeshes ? `clonedNodes${sanitizeName(obj.name)}` : `gltf.${node}`}.morphTargetInfluences} `
195
199
  if (obj.intensity && rNbr(obj.intensity)) result += `intensity={${rNbr(obj.intensity)}} `
196
200
  //if (obj.power && obj.power !== 4 * Math.PI) result += `power={${rNbr(obj.power)}} `
197
201
  if (obj.angle && obj.angle !== Math.PI / 3) result += `angle={${rDeg(obj.angle)}} `
@@ -402,7 +406,7 @@ export function parse(fileName, gltf, options = {}) {
402
406
 
403
407
  // Bail out on lights and bones
404
408
  if (type === 'bone') {
405
- return `<T is={gltf.${node}} />\n`
409
+ return `<T is={${hasSkinnedMeshes ? `clonedNodes${sanitizeName(obj.name)}` : `gltf.${node}`}} />\n`
406
410
  }
407
411
 
408
412
  // Collect children
@@ -495,6 +499,7 @@ export function parse(fileName, gltf, options = {}) {
495
499
  const imports = `
496
500
  ${options.types ? `\nimport type * as THREE from 'three'` : ''}
497
501
  ${hasAnimations ? `import { Group } from 'three'` : ''}
502
+ ${hasSkinnedMeshes ? `import { clone as cloneSkeleton } from 'three/examples/jsm/utils/SkeletonUtils.js'` : ''}
498
503
  ${options.types ? `import type { Snippet } from 'svelte'` : ''}
499
504
  import { ${['T', options.types && !options.isolated ? 'type Props' : '']
500
505
  .filter(Boolean)
@@ -575,6 +580,19 @@ ${
575
580
 
576
581
  ${!options.preload ? `const gltf = ${useGltf}` : 'const gltf = load()'}
577
582
 
583
+ ${
584
+ hasSkinnedMeshes
585
+ ? `function cloneScene(scene${options.types ? ': THREE.Group' : ''}) {
586
+ const clone = cloneSkeleton(scene)
587
+ const nodes${options.types ? ': Record<string, THREE.Object3D>' : ''} = {}
588
+ clone.traverse((child) => {
589
+ if (child.name) nodes[child.name] = child
590
+ })
591
+ return nodes${options.types ? ' as unknown as GLTFResult["nodes"]' : ''}
592
+ }`
593
+ : ''
594
+ }
595
+
578
596
  ${
579
597
  hasAnimations
580
598
  ? `export const { actions, mixer } = useGltfAnimations${
@@ -588,6 +606,7 @@ ${
588
606
  {#await gltf}
589
607
  {@render fallback?.()}
590
608
  {:then gltf}
609
+ ${hasSkinnedMeshes ? '{@const clonedNodes = cloneScene(gltf.scene)}' : ''}
591
610
  ${scene}
592
611
  {:catch err}
593
612
  {@render error?.({ error: err })}