@zephyr3d/scene 0.9.4 → 0.9.5

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 (102) hide show
  1. package/dist/animation/animationmask.js +224 -0
  2. package/dist/animation/animationmask.js.map +1 -0
  3. package/dist/animation/animationset.js +268 -67
  4. package/dist/animation/animationset.js.map +1 -1
  5. package/dist/animation/animationtrack.js.map +1 -1
  6. package/dist/animation/eulerrotationtrack.js +3 -0
  7. package/dist/animation/eulerrotationtrack.js.map +1 -1
  8. package/dist/animation/fixed_geometry_cache_track.js +7 -0
  9. package/dist/animation/fixed_geometry_cache_track.js.map +1 -1
  10. package/dist/animation/ik_modifier.js.map +1 -1
  11. package/dist/animation/joint_dynamics/collision.js +6 -4
  12. package/dist/animation/joint_dynamics/collision.js.map +1 -1
  13. package/dist/animation/joint_dynamics/controller.js +390 -43
  14. package/dist/animation/joint_dynamics/controller.js.map +1 -1
  15. package/dist/animation/joint_dynamics/joint_dynamics_system.js +62 -3
  16. package/dist/animation/joint_dynamics/joint_dynamics_system.js.map +1 -1
  17. package/dist/animation/joint_dynamics/solver.js +4 -3
  18. package/dist/animation/joint_dynamics/solver.js.map +1 -1
  19. package/dist/animation/joint_dynamics/types.js.map +1 -1
  20. package/dist/animation/joint_dynamics_modifier.js +2 -0
  21. package/dist/animation/joint_dynamics_modifier.js.map +1 -1
  22. package/dist/animation/morphtarget.js +3 -72
  23. package/dist/animation/morphtarget.js.map +1 -1
  24. package/dist/animation/morphtrack.js +3 -0
  25. package/dist/animation/morphtrack.js.map +1 -1
  26. package/dist/animation/pca_geometry_cache_track.js +3 -0
  27. package/dist/animation/pca_geometry_cache_track.js.map +1 -1
  28. package/dist/animation/proptrack.js +3 -0
  29. package/dist/animation/proptrack.js.map +1 -1
  30. package/dist/animation/rotationtrack.js +3 -0
  31. package/dist/animation/rotationtrack.js.map +1 -1
  32. package/dist/animation/scaletrack.js +3 -0
  33. package/dist/animation/scaletrack.js.map +1 -1
  34. package/dist/animation/skeleton.js +254 -79
  35. package/dist/animation/skeleton.js.map +1 -1
  36. package/dist/animation/skeleton_modifier.js.map +1 -1
  37. package/dist/animation/spring_modifier.js.map +1 -1
  38. package/dist/animation/translationtrack.js +3 -0
  39. package/dist/animation/translationtrack.js.map +1 -1
  40. package/dist/app/engine.js +171 -107
  41. package/dist/app/engine.js.map +1 -1
  42. package/dist/app/scriptregistry.js +251 -80
  43. package/dist/app/scriptregistry.js.map +1 -1
  44. package/dist/asset/assetmanager.js +344 -365
  45. package/dist/asset/assetmanager.js.map +1 -1
  46. package/dist/asset/loaders/gltf/gltf_loader.js +17 -14
  47. package/dist/asset/loaders/gltf/gltf_loader.js.map +1 -1
  48. package/dist/asset/loaders/loader.js +1 -6
  49. package/dist/asset/loaders/loader.js.map +1 -1
  50. package/dist/asset/loaders/zabc/zabc_loader.js.map +1 -1
  51. package/dist/asset/model.js +1000 -131
  52. package/dist/asset/model.js.map +1 -1
  53. package/dist/avatar/wardrobe.js +474 -0
  54. package/dist/avatar/wardrobe.js.map +1 -0
  55. package/dist/index.d.ts +1125 -199
  56. package/dist/index.js +3 -2
  57. package/dist/index.js.map +1 -1
  58. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js +6 -3
  59. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js.map +1 -1
  60. package/dist/material/mixins/pbr/common.js +72 -15
  61. package/dist/material/mixins/pbr/common.js.map +1 -1
  62. package/dist/material/msdf_text_sprite.js +4 -4
  63. package/dist/material/msdf_text_sprite.js.map +1 -1
  64. package/dist/material/pbrblueprint.js +102 -102
  65. package/dist/material/pbrblueprint.js.map +1 -1
  66. package/dist/render/envlight.js +54 -1
  67. package/dist/render/envlight.js.map +1 -1
  68. package/dist/render/sky.js +9 -0
  69. package/dist/render/sky.js.map +1 -1
  70. package/dist/scene/batchgroup.js +11 -13
  71. package/dist/scene/batchgroup.js.map +1 -1
  72. package/dist/scene/environment.js +15 -2
  73. package/dist/scene/environment.js.map +1 -1
  74. package/dist/scene/mesh.js +79 -16
  75. package/dist/scene/mesh.js.map +1 -1
  76. package/dist/scene/scene.js +1 -0
  77. package/dist/scene/scene.js.map +1 -1
  78. package/dist/scene/scene_node.js +203 -2
  79. package/dist/scene/scene_node.js.map +1 -1
  80. package/dist/text/font/font_asset.js.map +1 -1
  81. package/dist/text/msdf/generator.js.map +1 -1
  82. package/dist/text/msdf/shape.js +4 -1
  83. package/dist/text/msdf/shape.js.map +1 -1
  84. package/dist/text/runtime/msdf_text_atlas_manager.js +4 -1
  85. package/dist/text/runtime/msdf_text_atlas_manager.js.map +1 -1
  86. package/dist/utility/blueprint/material/inputs.js +1157 -1154
  87. package/dist/utility/blueprint/material/inputs.js.map +1 -1
  88. package/dist/utility/bounding_volume.js.map +1 -1
  89. package/dist/utility/pmrem.js +34 -8
  90. package/dist/utility/pmrem.js.map +1 -1
  91. package/dist/utility/serialization/manager.js +22 -9
  92. package/dist/utility/serialization/manager.js.map +1 -1
  93. package/dist/utility/serialization/scene/animation.js +700 -7
  94. package/dist/utility/serialization/scene/animation.js.map +1 -1
  95. package/dist/utility/serialization/scene/mesh.js +64 -4
  96. package/dist/utility/serialization/scene/mesh.js.map +1 -1
  97. package/dist/utility/serialization/scene/node.js +187 -8
  98. package/dist/utility/serialization/scene/node.js.map +1 -1
  99. package/dist/utility/serialization/types.js.map +1 -1
  100. package/dist/utility/textures/sheenlut.js +138 -0
  101. package/dist/utility/textures/sheenlut.js.map +1 -0
  102. package/package.json +2 -2
@@ -1,4 +1,4 @@
1
- import { Vector3, Disposable, randomUUID, DRef, Quaternion, DWeakRef, Matrix4x4, nextPowerOf2 } from '@zephyr3d/base';
1
+ import { Vector3, Disposable, randomUUID, Quaternion, DWeakRef, DRef, Matrix4x4, nextPowerOf2 } from '@zephyr3d/base';
2
2
  import { BoundingBox } from '../utility/bounding_volume.js';
3
3
  import { getDevice } from '../app/api.js';
4
4
 
@@ -61,6 +61,183 @@ const tmpV0 = new Vector3();
61
61
  const tmpV1 = new Vector3();
62
62
  const tmpV2 = new Vector3();
63
63
  const tmpV3 = new Vector3();
64
+ /**
65
+ * Shared joint rig for skeletal animation.
66
+ *
67
+ * A rig owns the animated joint nodes, bind pose, humanoid mapping and procedural
68
+ * modifiers. Multiple skin bindings may reference the same rig with different
69
+ * inverse bind matrices.
70
+ *
71
+ * @public
72
+ */ class SkeletonRig extends Disposable {
73
+ static _registry = new Map();
74
+ _id;
75
+ _joints;
76
+ _bindPoseByJoint;
77
+ _bindPose;
78
+ _rootJoint;
79
+ _rootBindPose;
80
+ _playing;
81
+ _modifiers;
82
+ _humanoidJointMapping;
83
+ _humanoidRootRotation;
84
+ constructor(joints, bindPose, options){
85
+ super();
86
+ this._id = randomUUID();
87
+ this._joints = joints;
88
+ this._bindPose = bindPose;
89
+ this._bindPoseByJoint = new Map();
90
+ for(let i = 0; i < joints.length; i++){
91
+ this._bindPoseByJoint.set(joints[i], bindPose[i]);
92
+ }
93
+ const skeletonRoot = this.findRootJoint(this._joints);
94
+ this._rootJoint = options?.rootJoint ?? skeletonRoot;
95
+ this._rootBindPose = options?.rootBindPose ?? this.getNodeBindPose(this._rootJoint);
96
+ this._playing = false;
97
+ this._modifiers = [];
98
+ this.computeBindPose();
99
+ if (skeletonRoot) {
100
+ this._humanoidJointMapping = Skeleton.tryExtractHumanoidJoints(skeletonRoot);
101
+ this._humanoidRootRotation = Quaternion.identity();
102
+ } else {
103
+ this._humanoidJointMapping = null;
104
+ this._humanoidRootRotation = Quaternion.identity();
105
+ }
106
+ if (this._humanoidJointMapping) {
107
+ let p = this._humanoidJointMapping.body["Hips"];
108
+ while(this._joints.includes(p.parent)){
109
+ Quaternion.multiply(p.parent.rotation, this._humanoidRootRotation, this._humanoidRootRotation);
110
+ p = p.parent;
111
+ }
112
+ }
113
+ SkeletonRig._registry.set(this._id, new DWeakRef(this));
114
+ }
115
+ static getRigKey(joints, rootJoint) {
116
+ return [
117
+ rootJoint?.persistentId ?? '',
118
+ ...joints.map((joint)=>joint.persistentId).sort()
119
+ ].join('|');
120
+ }
121
+ static findRigById(id) {
122
+ const m = this._registry.get(id);
123
+ if (m && !m.get()) {
124
+ this._registry.delete(id);
125
+ return null;
126
+ }
127
+ return m ? m.get() : null;
128
+ }
129
+ get persistentId() {
130
+ return this._id;
131
+ }
132
+ set persistentId(val) {
133
+ if (val !== this._id) {
134
+ const m = SkeletonRig._registry.get(this._id);
135
+ if (!m || m.get() !== this) {
136
+ throw new Error('Registry skeleton rig mismatch');
137
+ }
138
+ SkeletonRig._registry.delete(this._id);
139
+ this._id = val;
140
+ SkeletonRig._registry.set(this._id, m);
141
+ }
142
+ }
143
+ get joints() {
144
+ return this._joints;
145
+ }
146
+ get bindPose() {
147
+ return this._bindPose;
148
+ }
149
+ get rootJoint() {
150
+ return this._rootJoint;
151
+ }
152
+ set rootJoint(joint) {
153
+ this._rootJoint = joint;
154
+ this._rootBindPose = this.getNodeBindPose(joint);
155
+ }
156
+ get rootBindPose() {
157
+ return this._rootBindPose;
158
+ }
159
+ getBindPoseForJoint(joint) {
160
+ return this._bindPoseByJoint.get(joint) ?? null;
161
+ }
162
+ get humanoidJointMapping() {
163
+ return this._humanoidJointMapping;
164
+ }
165
+ get humanoidRootRotation() {
166
+ return this._humanoidRootRotation;
167
+ }
168
+ get modifiers() {
169
+ return this._modifiers;
170
+ }
171
+ get playing() {
172
+ return this._playing;
173
+ }
174
+ set playing(b) {
175
+ this._playing = b;
176
+ }
177
+ getJointIndex(joint) {
178
+ return this._joints.indexOf(joint);
179
+ }
180
+ getJointIndexByName(jointName) {
181
+ return this._joints.findIndex((joint)=>joint.name === jointName);
182
+ }
183
+ computeBindPose() {
184
+ for(let i = 0; i < this._joints.length; i++){
185
+ const joint = this._joints[i];
186
+ const bindpose = this._bindPose[i];
187
+ joint.position.set(bindpose.position);
188
+ joint.rotation.set(bindpose.rotation);
189
+ joint.scale.set(bindpose.scale);
190
+ }
191
+ if (this._rootJoint && !this._bindPoseByJoint.has(this._rootJoint)) {
192
+ this._rootJoint.position.set(this._rootBindPose.position);
193
+ this._rootJoint.rotation.set(this._rootBindPose.rotation);
194
+ this._rootJoint.scale.set(this._rootBindPose.scale);
195
+ }
196
+ }
197
+ apply(deltaTime) {
198
+ for (const modifier of this._modifiers){
199
+ modifier.apply(this, deltaTime);
200
+ }
201
+ }
202
+ reset() {
203
+ this._playing = false;
204
+ }
205
+ onDispose() {
206
+ super.onDispose();
207
+ const m = SkeletonRig._registry.get(this._id);
208
+ if (m?.get() === this) {
209
+ SkeletonRig._registry.delete(this._id);
210
+ m.dispose();
211
+ }
212
+ }
213
+ findRootJoint(joints) {
214
+ let root = null;
215
+ for (const joint of joints){
216
+ if (!root) {
217
+ root = joint;
218
+ }
219
+ while(!root.isParentOf(joint)){
220
+ root = root.parent;
221
+ }
222
+ if (!root) {
223
+ break;
224
+ }
225
+ }
226
+ return root;
227
+ }
228
+ getNodeBindPose(node) {
229
+ const bindPose = node ? this._bindPoseByJoint.get(node) : null;
230
+ return bindPose ? {
231
+ position: bindPose.position.clone(),
232
+ rotation: bindPose.rotation.clone(),
233
+ scale: bindPose.scale.clone()
234
+ } : {
235
+ position: node?.position.clone() ?? Vector3.zero(),
236
+ rotation: node?.rotation.clone() ?? Quaternion.identity(),
237
+ scale: node?.scale.clone() ?? Vector3.one()
238
+ };
239
+ }
240
+ }
64
241
  function jointPattern(all, none, any) {
65
242
  return {
66
243
  all,
@@ -90,10 +267,11 @@ function sideJointPatterns(side, patterns) {
90
267
  })));
91
268
  }
92
269
  /**
93
- * Skeleton for skinned animation.
270
+ * Skin binding for skinned animation.
94
271
  *
95
272
  * Responsibilities:
96
- * - Maintains joint transforms: inverse bind, bind pose, and current skinning matrices.
273
+ * - References a shared SkeletonRig.
274
+ * - Maintains inverse bind and current skinning matrices for one skin.
97
275
  * - Provides a texture containing joint matrices for GPU skinning.
98
276
  * - Applies skinning state to associated meshes each frame.
99
277
  * - Computes animated axis-aligned bounding boxes using representative skinned vertices.
@@ -105,58 +283,49 @@ function sideJointPatterns(side, patterns) {
105
283
  * and `_jointOffsets[1]` (previous).
106
284
  *
107
285
  * Usage:
108
- * - Construct with joints, bind data, meshes and submesh bounding info.
286
+ * - Construct with a rig, bind data, meshes and submesh bounding info.
109
287
  * - Call `apply()` each frame to update joint texture, bind to meshes, and update bounds.
110
288
  * - Call `reset()` to clear skinning on meshes.
111
289
  *
112
290
  * @public
113
- */ class Skeleton extends Disposable {
291
+ */ class SkinBinding extends Disposable {
114
292
  /** @internal Global weak registry keyed by persistentId for serialization/lookup. */ static _registry = new Map();
115
293
  /** @internal */ _id;
294
+ /** @internal */ _rig;
116
295
  /** @internal */ _joints;
117
296
  /** @internal */ _inverseBindMatrices;
118
- /** @internal */ _bindPose;
119
297
  /** @internal */ _jointMatrices;
120
298
  /** @internal */ _jointOffsets;
121
299
  /** @internal */ _jointMatrixArray;
122
300
  /** @internal */ _jointTexture;
123
301
  /** @internal */ _playing;
124
- /** @internal */ _modifiers;
125
302
  /** @internal */ _lastUpdateTime;
126
- /** @internal */ _humanoidJointMapping;
127
- /** @internal */ _humanoidRootRotation;
128
303
  /**
129
- * Create a skeleton instance.
304
+ * Create a skin binding instance.
130
305
  *
306
+ * @param rig - Shared skeleton rig that owns animated joint transforms.
131
307
  * @param joints - Joint scene nodes (one per joint), ordered to match skin data.
132
308
  * @param inverseBindMatrices - Inverse bind matrices for each joint.
133
309
  * @param bindPoseMatrices - Bind pose matrices for each joint (model-space).
134
- */ constructor(joints, inverseBindMatrices, bindPose){
310
+ */ constructor(rig, inverseBindMatrices, joints, bindPose){
135
311
  super();
136
312
  this._id = randomUUID();
137
- this._joints = joints;
313
+ this._rig = rig;
314
+ this._joints = joints ?? rig.joints;
138
315
  this._inverseBindMatrices = inverseBindMatrices;
139
- this._bindPose = bindPose;
140
316
  this._jointTexture = new DRef();
141
317
  this._playing = false;
142
- this._modifiers = [];
143
318
  this._lastUpdateTime = 0;
144
- this.computeBindPose();
145
- this.updateJointMatrices(0);
146
- let skeletonRoot = this.findRootJoint(this._joints);
147
- if (!skeletonRoot || !this._joints.includes(skeletonRoot)) {
148
- throw new Error('Skeleton root must be included in the joint list');
149
- }
150
- this._humanoidJointMapping = Skeleton.tryExtractHumanoidJoints(skeletonRoot);
151
- this._humanoidRootRotation = Quaternion.identity();
152
- if (this._humanoidJointMapping) {
153
- let p = this._humanoidJointMapping.body["Hips"];
154
- while(this._joints.includes(p.parent)){
155
- Quaternion.multiply(p.parent.rotation, this._humanoidRootRotation, this._humanoidRootRotation);
156
- p = p.parent;
157
- }
319
+ if (bindPose && bindPose !== rig.bindPose) {
320
+ // Legacy callers used Skeleton as both rig and binding. Keep the old bind
321
+ // pose visible by replacing the rig pose only when explicitly supplied.
322
+ this._rig = new SkeletonRig(rig.joints, bindPose, {
323
+ rootJoint: rig.rootJoint,
324
+ rootBindPose: rig.rootBindPose
325
+ });
158
326
  }
159
- Skeleton._registry.set(this._id, new DWeakRef(this));
327
+ this.updateJointMatrices();
328
+ SkinBinding._registry.set(this._id, new DWeakRef(this));
160
329
  }
161
330
  /**
162
331
  * Lookup a skeleton from the global registry by persistent id.
@@ -164,7 +333,7 @@ function sideJointPatterns(side, patterns) {
164
333
  * @param id - The persistent UUID to search for.
165
334
  * @returns The skeleton if alive, otherwise `null`.
166
335
  * @internal
167
- */ static findSkeletonById(id) {
336
+ */ static findSkinBindingById(id) {
168
337
  const m = this._registry.get(id);
169
338
  if (m && !m.get()) {
170
339
  this._registry.delete(id);
@@ -172,20 +341,26 @@ function sideJointPatterns(side, patterns) {
172
341
  }
173
342
  return m ? m.get() : null;
174
343
  }
344
+ static findSkeletonById(id) {
345
+ return this.findSkinBindingById(id);
346
+ }
347
+ get rig() {
348
+ return this._rig;
349
+ }
175
350
  /** Gets joint nodes */ get joints() {
176
351
  return this._joints;
177
352
  }
178
353
  /** Gets the humanoid joint mapping */ get humanoidJointMapping() {
179
- return this._humanoidJointMapping;
354
+ return this._rig.humanoidJointMapping;
180
355
  }
181
356
  /** Root rotation of humanoid hips bone */ get humanoidRootRotation() {
182
- return this._humanoidRootRotation;
357
+ return this._rig.humanoidRootRotation;
183
358
  }
184
359
  /** @internal */ get inverseBindMatrices() {
185
360
  return this._inverseBindMatrices;
186
361
  }
187
362
  /** @internal */ get bindPose() {
188
- return this._bindPose;
363
+ return this._joints.map((joint)=>this._rig.getBindPoseForJoint(joint));
189
364
  }
190
365
  get playing() {
191
366
  return this._playing;
@@ -198,13 +373,13 @@ function sideJointPatterns(side, patterns) {
198
373
  }
199
374
  set persistentId(val) {
200
375
  if (val !== this._id) {
201
- const m = Skeleton._registry.get(this._id);
376
+ const m = SkinBinding._registry.get(this._id);
202
377
  if (!m || m.get() !== this) {
203
- throw new Error('Registry skeleton mismatch');
378
+ throw new Error('Registry skin binding mismatch');
204
379
  }
205
- Skeleton._registry.delete(this._id);
380
+ SkinBinding._registry.delete(this._id);
206
381
  this._id = val;
207
- Skeleton._registry.set(this._id, m);
382
+ SkinBinding._registry.set(this._id, m);
208
383
  }
209
384
  }
210
385
  /**
@@ -243,8 +418,7 @@ function sideJointPatterns(side, patterns) {
243
418
  * @param jointTransforms - Optional per-joint transforms to use instead of node world matrices.
244
419
  * @param worldMatrix - Optional world-to-model transform applied before inverse bind.
245
420
  * @internal
246
- */ updateJointMatrices(deltaTime) {
247
- this.applyModifiers(deltaTime);
421
+ */ updateJointMatrices() {
248
422
  if (!this._jointTexture.get()) {
249
423
  this._createJointTexture();
250
424
  }
@@ -253,10 +427,10 @@ function sideJointPatterns(side, patterns) {
253
427
  this._jointOffsets[1] = 1;
254
428
  } else {
255
429
  this._jointOffsets[1] = this._jointOffsets[0];
256
- this._jointOffsets[0] = this._joints.length - this._jointOffsets[0] + 2;
430
+ this._jointOffsets[0] = this.joints.length - this._jointOffsets[0] + 2;
257
431
  }
258
- for(let i = 0; i < this._joints.length; i++){
259
- Matrix4x4.multiply(this._joints[i].worldMatrix, this._inverseBindMatrices[i], this._jointMatrices[i + this._jointOffsets[0] - 1]);
432
+ for(let i = 0; i < this.joints.length; i++){
433
+ Matrix4x4.multiply(this.joints[i].worldMatrix, this._inverseBindMatrices[i], this._jointMatrices[i + this._jointOffsets[0] - 1]);
260
434
  }
261
435
  }
262
436
  /**
@@ -264,22 +438,16 @@ function sideJointPatterns(side, patterns) {
264
438
  *
265
439
  * @internal
266
440
  */ computeBindPose() {
267
- for(let i = 0; i < this._joints.length; i++){
268
- const joint = this._joints[i];
269
- const bindpose = this._bindPose[i];
270
- joint.position.set(bindpose.position);
271
- joint.rotation.set(bindpose.rotation);
272
- //joint.rotation.identity();
273
- joint.scale.set(bindpose.scale);
274
- }
441
+ this._rig.computeBindPose();
275
442
  }
276
443
  /**
277
444
  * Compute current joint matrices from the nodes and upload them to the joint texture.
278
445
  *
279
446
  * @internal
280
- */ apply(deltaTime) {
281
- this.updateJointMatrices(deltaTime);
447
+ */ apply() {
448
+ this.updateJointMatrices();
282
449
  const tex = this.jointTexture;
450
+ this._syncJointMatrixArray();
283
451
  tex.update(this._jointMatrixArray, 0, 0, tex.width, tex.height);
284
452
  }
285
453
  /**
@@ -291,16 +459,14 @@ function sideJointPatterns(side, patterns) {
291
459
  * @param deltaTime - Time elapsed since last frame (in seconds)
292
460
  * @internal
293
461
  */ applyModifiers(deltaTime) {
294
- for (const modifier of this._modifiers){
295
- modifier.apply(this, deltaTime);
296
- }
462
+ this._rig.apply(deltaTime);
297
463
  }
298
464
  /**
299
465
  * Get all modifiers attached to this skeleton.
300
466
  *
301
467
  * @public
302
468
  */ get modifiers() {
303
- return this._modifiers;
469
+ return this._rig.modifiers;
304
470
  }
305
471
  /**
306
472
  * Reset all meshes to an unskinned state and clear animated bounds.
@@ -341,9 +507,9 @@ function sideJointPatterns(side, patterns) {
341
507
  */ onDispose() {
342
508
  super.onDispose();
343
509
  this._jointTexture.dispose();
344
- const m = Skeleton._registry.get(this._id);
510
+ const m = SkinBinding._registry.get(this._id);
345
511
  if (m?.get() === this) {
346
- Skeleton._registry.delete(this._id);
512
+ SkinBinding._registry.delete(this._id);
347
513
  m.dispose();
348
514
  }
349
515
  }
@@ -359,7 +525,7 @@ function sideJointPatterns(side, patterns) {
359
525
  *
360
526
  * @internal
361
527
  */ _createJointTexture() {
362
- const textureWidth = nextPowerOf2(Math.max(4, Math.ceil(Math.sqrt((this._joints.length * 2 + 1) * 4))));
528
+ const textureWidth = nextPowerOf2(Math.max(4, Math.ceil(Math.sqrt((this.joints.length * 2 + 1) * 4))));
363
529
  const device = getDevice();
364
530
  this._jointTexture.set(device.createTexture2D('rgba32f', textureWidth, textureWidth, {
365
531
  mipmapping: false,
@@ -369,13 +535,17 @@ function sideJointPatterns(side, patterns) {
369
535
  }
370
536
  }));
371
537
  this._jointMatrixArray = new Float32Array(textureWidth * textureWidth * 4);
372
- const buffer = this._jointMatrixArray.buffer;
373
- this._jointOffsets = new Float32Array(buffer);
538
+ this._jointOffsets = this._jointMatrixArray.subarray(0, 2);
374
539
  this._jointOffsets[0] = 0;
375
540
  this._jointOffsets[1] = 0;
376
541
  this._jointMatrices = Array.from({
377
- length: this._joints.length * 2
378
- }).map((val, index)=>new Matrix4x4(buffer, (index + 1) * 16 * Float32Array.BYTES_PER_ELEMENT));
542
+ length: this.joints.length * 2
543
+ }).map(()=>new Matrix4x4());
544
+ }
545
+ _syncJointMatrixArray() {
546
+ for(let i = 0; i < this._jointMatrices.length; i++){
547
+ this._jointMatrixArray.set(this._jointMatrices[i], (i + 1) * 16);
548
+ }
379
549
  }
380
550
  /**
381
551
  * Build representative skinned bounding data for a submesh.
@@ -509,21 +679,6 @@ function sideJointPatterns(side, patterns) {
509
679
  }
510
680
  return result;
511
681
  }
512
- findRootJoint(joints) {
513
- let root = null;
514
- for (const joint of joints){
515
- if (!root) {
516
- root = joint;
517
- }
518
- while(!root.isParentOf(joint)){
519
- root = root.parent;
520
- }
521
- if (!root) {
522
- break;
523
- }
524
- }
525
- return root;
526
- }
527
682
  static normalizeHumanoidJointName(name) {
528
683
  return name.replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2').replace(/([a-z0-9])([A-Z])/g, '$1 $2').replace(/([a-zA-Z])(\d+)/g, '$1 $2').replace(/(\d+)([a-zA-Z])/g, '$1 $2').replace(/[_:\/\\.-]+/g, ' ').replace(/[^a-zA-Z0-9]+/g, ' ').toLowerCase().replace(/\bforearm\b/g, 'fore arm').replace(/\bupperarm\b/g, 'upper arm').replace(/\blowerarm\b/g, 'lower arm').replace(/\bupleg\b/g, 'up leg').replace(/\bupperleg\b/g, 'upper leg').replace(/\blowerleg\b/g, 'lower leg').replace(/\btoebase\b/g, 'toe base').replace(/\bupperchest\b/g, 'upper chest').replace(/\btoes\b/g, 'toe').replace(/\blittle\b/g, 'pinky').replace(/\bcollar\b/g, 'clavicle').replace(/\s+/g, ' ').trim();
529
684
  }
@@ -2258,6 +2413,26 @@ function sideJointPatterns(side, patterns) {
2258
2413
  return this.tryExtractHumanoidJointsByBodyProfile(root, this.createBipedHumanoidBodyProfile());
2259
2414
  }
2260
2415
  }
2416
+ /**
2417
+ * Legacy compatibility name for a skin binding.
2418
+ *
2419
+ * New code should use {@link SkeletonRig} for the shared animated rig and
2420
+ * {@link SkinBinding} for per-skin inverse bind matrices.
2421
+ *
2422
+ * @public
2423
+ */ class Skeleton extends SkinBinding {
2424
+ constructor(joints, inverseBindMatrices, bindPose){
2425
+ super(new SkeletonRig(joints, bindPose), inverseBindMatrices, joints);
2426
+ }
2427
+ static tryExtractHumanoidJoints = SkinBinding.tryExtractHumanoidJoints;
2428
+ static tryExtractHumanoidJointsMixamo = SkinBinding.tryExtractHumanoidJointsMixamo;
2429
+ static tryExtractHumanoidJointsVRM = SkinBinding.tryExtractHumanoidJointsVRM;
2430
+ static tryExtractHumanoidJointsUnityHumanoid = SkinBinding.tryExtractHumanoidJointsUnityHumanoid;
2431
+ static tryExtractHumanoidJointsBiped = SkinBinding.tryExtractHumanoidJointsBiped;
2432
+ static findSkeletonById(id) {
2433
+ return SkinBinding.findSkinBindingById(id);
2434
+ }
2435
+ }
2261
2436
 
2262
- export { HumanoidBodyRig, HumanoidHandRig, Skeleton };
2437
+ export { HumanoidBodyRig, HumanoidHandRig, Skeleton, SkeletonRig, SkinBinding };
2263
2438
  //# sourceMappingURL=skeleton.js.map