@zephyr3d/scene 0.8.1 → 0.8.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.
@@ -1,4 +1,4 @@
1
- import { Disposable, weightedAverage, Quaternion, Interpolator } from '@zephyr3d/base';
1
+ import { Disposable, weightedAverage, Interpolator } from '@zephyr3d/base';
2
2
  import { AnimationClip } from './animation.js';
3
3
  import { NodeRotationTrack } from './rotationtrack.js';
4
4
  import { NodeEulerRotationTrack } from './eulerrotationtrack.js';
@@ -355,45 +355,72 @@ import { Skeleton } from './skeleton.js';
355
355
  console.error(`copyAnimationFrom: animation '${destName}' already exists in target set`);
356
356
  return null;
357
357
  }
358
+ if (sourceClip.skeletons.size !== 1) {
359
+ console.error(`copyAnimationFrom: source animation clip must be affected by exactly one skeleton`);
360
+ return null;
361
+ }
362
+ const srcSkeletonId = [
363
+ ...sourceClip.skeletons
364
+ ][0];
365
+ const srcSkeleton = Skeleton.findSkeletonById(srcSkeletonId);
366
+ if (!srcSkeleton) {
367
+ console.error(`copyAnimationFrom: source skeleton '${srcSkeletonId}' not found`);
368
+ return null;
369
+ }
358
370
  const nodeMap = new Map();
359
371
  const jointRemapBySrcNode = new Map();
360
- for (const srcSkeletonId of sourceClip.skeletons){
361
- const srcSkeleton = Skeleton.findSkeletonById(srcSkeletonId);
362
- if (!srcSkeleton) {
363
- console.error(`copyAnimationFrom: source skeleton '${srcSkeletonId}' not found`);
364
- return null;
372
+ const jointsFiltered = srcSkeleton.joints.filter((j)=>!excludeJoint?.(j.name));
373
+ const srcRootNode = findRootJoint(jointsFiltered);
374
+ if (!srcRootNode) {
375
+ console.error(`copyAnimationFrom: cannot determine the root joint for source skeleton`);
376
+ return null;
377
+ }
378
+ // Build filtered joint lists for matching (exclude joints rejected by filterJoint)
379
+ const srcJointsFiltered = sortJoints(srcRootNode, jointsFiltered);
380
+ if (!srcJointsFiltered) {
381
+ console.error(`copyAnimationFrom: invalid source skeleton structure`);
382
+ return null;
383
+ }
384
+ let dstJointsFiltered = [];
385
+ const dstSkeleton = this._skeletons.map((ref)=>ref.get()).find((sk)=>{
386
+ if (!sk) {
387
+ return false;
365
388
  }
366
- // Build filtered joint lists for matching (exclude joints rejected by filterJoint)
367
- const srcJointsFiltered = srcSkeleton.joints.filter((j)=>!excludeJoint?.(j.name));
368
- const dstSkeleton = this._skeletons.map((ref)=>ref.get()).find((sk)=>{
369
- if (!sk) {
370
- return false;
371
- }
372
- const dstJointsFiltered = sk.joints.filter((j)=>!excludeJoint?.(j.name));
373
- return dstJointsFiltered.length === srcJointsFiltered.length && srcJointsFiltered.every((j, i)=>j.name === dstJointsFiltered[i].name);
374
- });
375
- if (!dstSkeleton) {
376
- console.error(`copyAnimationFrom: no matching skeleton in target set for '${srcSkeletonId}'`);
377
- return null;
389
+ const jointsFiltered = sk.joints.filter((j)=>!excludeJoint?.(j.name));
390
+ if (jointsFiltered.length !== srcJointsFiltered.length) {
391
+ return false;
378
392
  }
379
- // Build remap only for joints that pass the filter
380
- const dstJointsFiltered = dstSkeleton.joints.filter((j)=>!excludeJoint?.(j.name));
381
- for(let fi = 0; fi < srcJointsFiltered.length; fi++){
382
- const srcJoint = srcJointsFiltered[fi];
383
- const dstJoint = dstJointsFiltered[fi];
384
- const si = srcSkeleton.joints.indexOf(srcJoint);
385
- const di = dstSkeleton.joints.indexOf(dstJoint);
386
- const srcLen = srcSkeleton.bindPose[si].position.magnitude;
387
- const dstLen = dstSkeleton.bindPose[di].position.magnitude;
388
- const translationScale = srcLen > 1e-6 ? dstLen / srcLen : 1;
389
- nodeMap.set(srcJoint, dstJoint);
390
- jointRemapBySrcNode.set(srcJoint, {
391
- dstNode: dstJoint,
392
- srcBindRot: srcSkeleton.bindPose[si].rotation,
393
- dstBindRot: dstSkeleton.bindPose[di].rotation,
394
- translationScale
395
- });
393
+ const rootNode = findRootJoint(jointsFiltered);
394
+ if (!rootNode) {
395
+ return false;
396
396
  }
397
+ const sortedJointsFiltered = sortJoints(rootNode, jointsFiltered);
398
+ if (sortedJointsFiltered && srcJointsFiltered.every((j, i)=>j.name === sortedJointsFiltered[i].name)) {
399
+ dstJointsFiltered = sortedJointsFiltered;
400
+ return true;
401
+ }
402
+ return false;
403
+ });
404
+ if (!dstJointsFiltered || !dstSkeleton) {
405
+ console.error(`copyAnimationFrom: no matching skeleton in target set for '${srcSkeletonId}'`);
406
+ return null;
407
+ }
408
+ // Build remap only for joints that pass the filter
409
+ for(let fi = 0; fi < srcJointsFiltered.length; fi++){
410
+ const srcJoint = srcJointsFiltered[fi];
411
+ const dstJoint = dstJointsFiltered[fi];
412
+ const si = srcSkeleton.joints.indexOf(srcJoint);
413
+ const di = dstSkeleton.joints.indexOf(dstJoint);
414
+ const srcLen = srcSkeleton.bindPose[si].position.magnitude;
415
+ const dstLen = dstSkeleton.bindPose[di].position.magnitude;
416
+ const translationScale = srcLen > 1e-6 ? dstLen / srcLen : 1;
417
+ nodeMap.set(srcJoint, dstJoint);
418
+ jointRemapBySrcNode.set(srcJoint, {
419
+ dstNode: dstJoint,
420
+ srcBindRot: srcSkeleton.bindPose[si].rotation,
421
+ dstBindRot: dstSkeleton.bindPose[di].rotation,
422
+ translationScale
423
+ });
397
424
  }
398
425
  const dstClip = this.createAnimation(destName);
399
426
  if (!dstClip) {
@@ -402,30 +429,22 @@ import { Skeleton } from './skeleton.js';
402
429
  dstClip.timeDuration = sourceClip.timeDuration;
403
430
  dstClip.weight = sourceClip.weight;
404
431
  dstClip.autoPlay = sourceClip.autoPlay;
405
- // Register destination skeleton ids
406
- for (const srcSkeletonId of sourceClip.skeletons){
407
- const srcSkeleton = Skeleton.findSkeletonById(srcSkeletonId);
408
- const firstSrcJoint = srcSkeleton.joints[0];
409
- const firstDstJoint = nodeMap.get(firstSrcJoint);
410
- const dstSkeleton = this._skeletons.map((r)=>r.get()).find((sk)=>sk && sk.joints[0] === firstDstJoint);
411
- if (dstSkeleton) {
412
- dstClip.addSkeleton(dstSkeleton.persistentId);
432
+ // Register destination skeleton
433
+ dstClip.addSkeleton(dstSkeleton.persistentId);
434
+ for (const srcNode of srcJointsFiltered){
435
+ const srcTracks = sourceClip.tracks.get(srcNode);
436
+ if (!srcTracks) {
437
+ console.error(`copyAnimationFrom: no track for joint: ${srcNode.name}`);
438
+ return null;
413
439
  }
414
- }
415
- const tmpSrcBind = new Quaternion();
416
- const tmpDstBindInv = new Quaternion();
417
- for (const [srcNode, srcTracks] of sourceClip.tracks){
418
440
  const dstNode = nodeMap.get(srcNode);
419
- if (!dstNode) {
420
- continue;
421
- }
422
441
  const remap = jointRemapBySrcNode.get(srcNode) ?? null;
423
442
  for (const srcTrack of srcTracks){
424
443
  let dstTrack;
425
444
  if (srcTrack instanceof NodeRotationTrack) {
426
- dstTrack = retargetRotationTrack(srcTrack, remap);
445
+ dstTrack = retargetRotationTrack(srcTrack);
427
446
  } else if (srcTrack instanceof NodeEulerRotationTrack) {
428
- dstTrack = retargetEulerToRotationTrack(srcTrack, remap);
447
+ dstTrack = retargetEulerToRotationTrack(srcTrack);
429
448
  } else if (srcTrack instanceof NodeTranslationTrack) {
430
449
  dstTrack = retargetTranslationTrack(srcTrack, remap);
431
450
  } else if (srcTrack instanceof NodeScaleTrack) {
@@ -441,6 +460,48 @@ import { Skeleton } from './skeleton.js';
441
460
  }
442
461
  }
443
462
  return dstClip;
463
+ function findRootJoint(joints) {
464
+ let root = null;
465
+ for (const joint of joints){
466
+ if (!root) {
467
+ root = joint;
468
+ }
469
+ while(!root.isParentOf(joint)){
470
+ root = root.parent;
471
+ }
472
+ if (!root) {
473
+ break;
474
+ }
475
+ }
476
+ if (!root || !joints.includes(root)) {
477
+ return null;
478
+ }
479
+ return root;
480
+ }
481
+ function sortJoints(root, joints) {
482
+ const ordered = [];
483
+ const visited = new Set();
484
+ function visit(joint) {
485
+ if (visited.has(joint)) {
486
+ return true;
487
+ }
488
+ if (!joints.includes(joint)) {
489
+ return false;
490
+ }
491
+ if (joint !== root) {
492
+ visit(joint.parent);
493
+ }
494
+ visited.add(joint);
495
+ ordered.push(joint);
496
+ return true;
497
+ }
498
+ for (const joint of joints){
499
+ if (!visit(joint)) {
500
+ return null;
501
+ }
502
+ }
503
+ return ordered;
504
+ }
444
505
  function retargetTranslationTrack(src, remap) {
445
506
  if (!remap || Math.abs(remap.translationScale - 1) < 1e-6) {
446
507
  return new NodeTranslationTrack(cloneInterpolator(src.interpolator));
@@ -460,65 +521,26 @@ import { Skeleton } from './skeleton.js';
460
521
  ...src.outputs
461
522
  ]);
462
523
  }
463
- function retargetRotationTrack(src, remap) {
464
- if (!remap) {
465
- return new NodeRotationTrack(cloneInterpolator(src.interpolator));
466
- }
467
- tmpSrcBind.set(remap.srcBindRot);
468
- Quaternion.conjugate(remap.dstBindRot, tmpDstBindInv);
524
+ function retargetRotationTrack(src) {
469
525
  const isCubic = src.interpolator.mode === 'cubicspline';
470
526
  const frameStride = isCubic ? 12 : 4;
471
527
  const numFrames = src.interpolator.inputs.length;
472
528
  const srcOutputs = src.interpolator.outputs;
473
529
  const newOutputs = new Float32Array(srcOutputs.length);
474
- const q = new Quaternion();
475
530
  for(let f = 0; f < numFrames; f++){
476
531
  const base = f * frameStride;
477
- if (isCubic) {
478
- // layout per frame: [inTangent×4, value×4, outTangent×4] — only retarget value
479
- newOutputs.set(srcOutputs.subarray(base, base + 4), base);
480
- q.set(srcOutputs.subarray(base + 4, base + 8));
481
- Quaternion.multiply(tmpSrcBind, q, q);
482
- Quaternion.multiply(tmpDstBindInv, q, q);
483
- newOutputs[base + 4] = q.x;
484
- newOutputs[base + 5] = q.y;
485
- newOutputs[base + 6] = q.z;
486
- newOutputs[base + 7] = q.w;
487
- newOutputs.set(srcOutputs.subarray(base + 8, base + 12), base + 8);
488
- } else {
489
- q.set(srcOutputs.subarray(base, base + 4));
490
- Quaternion.multiply(tmpSrcBind, q, q);
491
- Quaternion.multiply(tmpDstBindInv, q, q);
492
- newOutputs[base] = q.x;
493
- newOutputs[base + 1] = q.y;
494
- newOutputs[base + 2] = q.z;
495
- newOutputs[base + 3] = q.w;
496
- }
532
+ newOutputs.set(srcOutputs.subarray(base, base + (isCubic ? 12 : 4)), base);
497
533
  }
498
534
  return new NodeRotationTrack(new Interpolator(src.interpolator.mode, 'quat', new Float32Array(src.interpolator.inputs), newOutputs));
499
535
  }
500
- function retargetEulerToRotationTrack(src, remap) {
536
+ function retargetEulerToRotationTrack(src) {
501
537
  const srcInputs = src.interpolator.inputs;
502
538
  const srcOutputs = src.interpolator.outputs;
503
539
  const numFrames = srcInputs.length;
504
- const newOutputs = new Float32Array(numFrames * 4);
505
- const q = new Quaternion();
506
- if (remap) {
507
- tmpSrcBind.set(remap.srcBindRot);
508
- Quaternion.conjugate(remap.dstBindRot, tmpDstBindInv);
509
- }
540
+ const newOutputs = new Float32Array(numFrames * 3);
510
541
  for(let f = 0; f < numFrames; f++){
511
- const b3 = f * 3;
512
- const b4 = f * 4;
513
- q.fromEulerAngle(srcOutputs[b3], srcOutputs[b3 + 1], srcOutputs[b3 + 2]);
514
- if (remap) {
515
- Quaternion.multiply(tmpSrcBind, q, q);
516
- Quaternion.multiply(tmpDstBindInv, q, q);
517
- }
518
- newOutputs[b4] = q.x;
519
- newOutputs[b4 + 1] = q.y;
520
- newOutputs[b4 + 2] = q.z;
521
- newOutputs[b4 + 3] = q.w;
542
+ const base = f * 3;
543
+ newOutputs.set(srcOutputs.subarray(base, base + 3), base);
522
544
  }
523
545
  return new NodeRotationTrack(new Interpolator('linear', 'quat', new Float32Array(srcInputs), newOutputs));
524
546
  }
@@ -1 +1 @@
1
- {"version":3,"file":"animationset.js","sources":["../../src/animation/animationset.ts"],"sourcesContent":["import { weightedAverage, Disposable, Interpolator, Quaternion } from '@zephyr3d/base';\r\nimport type { DRef, IDisposable } from '@zephyr3d/base';\r\nimport type { SceneNode } from '../scene';\r\nimport { AnimationClip } from './animation';\r\nimport type { AnimationTrack } from './animationtrack';\r\nimport { NodeRotationTrack } from './rotationtrack';\r\nimport { NodeEulerRotationTrack } from './eulerrotationtrack';\r\nimport { NodeTranslationTrack } from './translationtrack';\r\nimport { NodeScaleTrack } from './scaletrack';\r\nimport { Skeleton } from './skeleton';\r\n\r\n/**\r\n * Options for playing an animation.\r\n *\r\n * Controls looping, playback speed (including reverse), and fade-in blending.\r\n * @public\r\n **/\r\nexport type PlayAnimationOptions = {\r\n /**\r\n * Number of loops to play.\r\n *\r\n * - 0: infinite looping (default).\r\n * - n \\> 0: play exactly n loops (each loop is one full duration of the clip).\r\n */\r\n repeat?: number;\r\n /**\r\n * Playback speed multiplier.\r\n *\r\n * - 1: normal speed (default).\r\n * - \\>1: faster; \\<1: slower.\r\n * - Negative values play the clip in reverse. The initial `currentTime` will be set to the end.\r\n */\r\n speedRatio?: number;\r\n /**\r\n * Fade-in duration in seconds.\r\n *\r\n * Interpolates the animation weight from 0 to the clip's configured weight over this time.\r\n * Use together with `stopAnimation(..., { fadeOut })` for smooth cross-fading.\r\n * Default is 0 (no fade-in).\r\n */\r\n fadeIn?: number;\r\n /**\r\n * Weight of the animation clip.\r\n *\r\n * Used during blending when multiple animations affect the same property.\r\n * Default is the clip's configured weight.\r\n */\r\n weight?: number;\r\n};\r\n\r\n/**\r\n * Options for stopping an animation.\r\n *\r\n * Allows a graceful fade-out instead of abrupt stop.\r\n * @public\r\n */\r\nexport type StopAnimationOptions = {\r\n /**\r\n * Fade-out duration in seconds.\r\n *\r\n * Interpolates the current animation weight down to 0 over this time.\r\n * Default is 0 (immediate stop).\r\n */\r\n fadeOut?: number;\r\n};\r\n\r\n/**\r\n * Animation set\r\n *\r\n * Manages a collection of named animation clips for a model and orchestrates:\r\n * - Playback state (time, loops, speed, weights, fade-in/out).\r\n * - Blending across multiple tracks targeting the same property via weighted averages.\r\n * - Skeleton usage and application for clips that drive skeletal animation.\r\n * - Active track registration and cleanup as clips start/stop.\r\n *\r\n * Usage:\r\n * - Create or retrieve `AnimationClip`s by name.\r\n * - Start playback with `playAnimation(name, options)`.\r\n * - Advance animation with `update(deltaSeconds)`.\r\n * - Optionally adjust weight while playing with `setAnimationWeight(name, weight)`.\r\n *\r\n * Lifetime:\r\n * - Disposing the set releases references to the model, clips, and clears active state.\r\n *\r\n * @public\r\n */\r\nexport class AnimationSet extends Disposable implements IDisposable {\r\n /** @internal */\r\n private _model: SceneNode;\r\n /** @internal */\r\n private _animations: Partial<Record<string, AnimationClip>>;\r\n /** @internal */\r\n private _skeletons: DRef<Skeleton>[];\r\n /** @internal */\r\n private readonly _activeTracks: Map<object, Map<unknown, AnimationTrack[]>>;\r\n /** @internal */\r\n private readonly _activeSkeletons: Map<Skeleton, number>;\r\n /** @internal */\r\n private readonly _activeAnimations: Map<\r\n AnimationClip,\r\n {\r\n currentTime: number;\r\n repeat: number;\r\n repeatCounter: number;\r\n weight: number;\r\n speedRatio: number;\r\n firstFrame: boolean;\r\n fadeIn: number;\r\n fadeOut: number;\r\n fadeOutStart: number;\r\n animateTime: number;\r\n }\r\n >;\r\n /**\r\n * Create an AnimationSet controlling the provided model.\r\n *\r\n * @param model - The SceneNode (model root) controlled by this animation set.\r\n */\r\n constructor(model: SceneNode) {\r\n super();\r\n this._model = model;\r\n this._animations = {};\r\n this._activeTracks = new Map();\r\n this._activeSkeletons = new Map();\r\n this._activeAnimations = new Map();\r\n this._skeletons = [];\r\n }\r\n /**\r\n * The model (SceneNode) controlled by this animation set.\r\n */\r\n get model() {\r\n return this._model;\r\n }\r\n /**\r\n * Number of animation clips registered in this set.\r\n */\r\n get numAnimations() {\r\n return Object.getOwnPropertyNames(this._animations).length;\r\n }\r\n /**\r\n * The skeletons used by animations in this set.\r\n */\r\n get skeletons() {\r\n return this._skeletons;\r\n }\r\n /**\r\n * Retrieve an animation clip by name.\r\n *\r\n * @param name - Name of the animation.\r\n * @returns The clip if present; otherwise null.\r\n */\r\n get(name: string) {\r\n return this._animations[name] ?? null;\r\n }\r\n /**\r\n * Create and register a new animation clip.\r\n *\r\n * @param name - Unique name for the animation clip.\r\n * @param embedded - Whether the clip is embedded/owned (implementation-specific). Default false.\r\n * @returns The created clip, or null if the name is empty or not unique.\r\n */\r\n createAnimation(name: string, embedded = false) {\r\n if (!name || this._animations[name]) {\r\n console.error('Animation must have unique name');\r\n return null;\r\n } else {\r\n const animation = new AnimationClip(name, this, embedded);\r\n this._animations[name] = animation;\r\n this._model.scene?.queueUpdateNode(this._model);\r\n return animation;\r\n }\r\n }\r\n /**\r\n * Delete and dispose an animation clip by name.\r\n *\r\n * - If the animation is currently playing, it is first stopped (immediately).\r\n *\r\n * @param name - Name of the animation to remove.\r\n */\r\n deleteAnimation(name: string) {\r\n const animation = this._animations[name];\r\n if (animation) {\r\n this.stopAnimation(name);\r\n delete this._animations[name];\r\n animation.dispose();\r\n }\r\n }\r\n /**\r\n * Get the list of all registered animation names.\r\n *\r\n * @returns An array of clip names.\r\n */\r\n getAnimationNames() {\r\n return Object.keys(this._animations);\r\n }\r\n /**\r\n * Advance and apply active animations.\r\n *\r\n * Responsibilities per call:\r\n * - Update time cursor for each active clip (respecting speedRatio and looping).\r\n * - Enforce repeat limits and apply fade-out termination if configured.\r\n * - For each animated target, blend active tracks (weighted by clip weight × fade-in × fade-out)\r\n * and apply the resulting state to the target.\r\n * - Apply all active skeletons to update skinning transforms.\r\n *\r\n * @param deltaInSeconds - Time step in seconds since last update.\r\n */\r\n update(deltaInSeconds: number) {\r\n this._activeAnimations.forEach((v, k) => {\r\n if (v.fadeOut > 0 && v.fadeOutStart < 0) {\r\n v.fadeOutStart = v.animateTime;\r\n }\r\n // Update animation time\r\n if (v.firstFrame) {\r\n v.firstFrame = false;\r\n } else {\r\n const timeAdvance = deltaInSeconds * v.speedRatio;\r\n v.currentTime += timeAdvance;\r\n v.animateTime += timeAdvance;\r\n if (v.currentTime > k.timeDuration) {\r\n v.repeatCounter++;\r\n v.currentTime = 0;\r\n } else if (v.currentTime < 0) {\r\n v.repeatCounter++;\r\n v.currentTime = k.timeDuration;\r\n }\r\n if (v.repeat !== 0 && v.repeatCounter >= v.repeat) {\r\n this.stopAnimation(k.name);\r\n } else if (v.fadeOut > 0) {\r\n if (v.animateTime - v.fadeOutStart >= v.fadeOut) {\r\n this.stopAnimation(k.name);\r\n }\r\n }\r\n }\r\n });\r\n // Update tracks\r\n this._activeTracks.forEach((v, k) => {\r\n v.forEach((alltracks) => {\r\n // Only deal with tracks which have not been removed\r\n const tracks = alltracks.filter(\r\n (track) => track.animation && this.isPlayingAnimation(track.animation.name)\r\n );\r\n if (tracks.length > 0) {\r\n const weights = tracks.map((track) => {\r\n const info = this._activeAnimations.get(track.animation!)!;\r\n const weight = info.weight;\r\n const fadeIn = info.fadeIn === 0 ? 1 : Math.min(1, info.animateTime / info.fadeIn);\r\n let fadeOut = 1;\r\n if (info.fadeOut !== 0) {\r\n fadeOut = 1 - (info.animateTime - info.fadeOutStart) / info.fadeOut;\r\n }\r\n return weight * fadeIn * fadeOut;\r\n });\r\n const states = tracks.map((track) => {\r\n const info = this._activeAnimations.get(track.animation!)!;\r\n const t = (info.currentTime / track.animation!.timeDuration) * track.getDuration();\r\n return track.calculateState(k, t);\r\n });\r\n const state = weightedAverage(weights, states, (a, b, t) => {\r\n return tracks[0].mixState(a, b, t);\r\n });\r\n tracks[0].applyState(k, state);\r\n }\r\n });\r\n });\r\n // Update skeletons\r\n this._skeletons.forEach((v) => {\r\n v.get()?.apply(deltaInSeconds);\r\n });\r\n }\r\n /**\r\n * Check whether an animation is currently playing.\r\n *\r\n * @param name - Optional animation name. If omitted, returns true if any animation is playing.\r\n * @returns True if playing; otherwise false.\r\n */\r\n isPlayingAnimation(name?: string) {\r\n if (name) {\r\n const animation = this._animations[name];\r\n return !!animation && this._activeAnimations.has(animation);\r\n }\r\n return this._activeAnimations.size > 0;\r\n }\r\n /**\r\n * Get an animation clip by name.\r\n *\r\n * Alias of `get(name)` returning a nullable type.\r\n *\r\n * @param name - Name of the animation.\r\n * @returns The clip if present; otherwise null.\r\n */\r\n getAnimationClip(name: string) {\r\n return this._animations[name] ?? null;\r\n }\r\n /**\r\n * Set the runtime blend weight for a currently playing animation.\r\n *\r\n * Has no effect if the clip is not active.\r\n *\r\n * @param name - Name of the playing animation.\r\n * @param weight - New weight value used during blending.\r\n */\r\n setAnimationWeight(name: string, weight: number) {\r\n const ani = this._animations[name];\r\n if (!ani) {\r\n console.error(`Animation ${name} not exists`);\r\n return;\r\n }\r\n const info = this._activeAnimations.get(ani);\r\n if (info) {\r\n info.weight = weight;\r\n }\r\n }\r\n /**\r\n * Start (or update) playback of an animation clip.\r\n *\r\n * Behavior:\r\n * - If the clip is already playing, updates its fade-in (resets fade-out).\r\n * - Otherwise initializes playback state (repeat counter, speed, weight, initial time).\r\n * - Registers clip tracks and skeletons into the active sets for blending and application.\r\n *\r\n * @param name - Name of the animation to play.\r\n * @param options - Playback options (repeat, speedRatio, fadeIn).\r\n */\r\n playAnimation(name: string, options?: PlayAnimationOptions) {\r\n const ani = this._animations[name];\r\n if (!ani) {\r\n console.error(`Animation ${name} not exists`);\r\n return;\r\n }\r\n const fadeIn = Math.max(options?.fadeIn ?? 0, 0);\r\n const info = this._activeAnimations.get(ani);\r\n if (info) {\r\n info.fadeOut = 0;\r\n info.fadeIn = fadeIn;\r\n } else {\r\n const repeat = options?.repeat ?? 0;\r\n const speedRatio = options?.speedRatio ?? 1;\r\n const weight = options?.weight ?? ani.weight ?? 1;\r\n this._activeAnimations.set(ani, {\r\n repeat,\r\n weight,\r\n speedRatio,\r\n fadeIn,\r\n fadeOut: 0,\r\n repeatCounter: 0,\r\n currentTime: speedRatio < 0 ? ani.timeDuration : 0,\r\n animateTime: 0,\r\n fadeOutStart: 0,\r\n firstFrame: true\r\n });\r\n ani.tracks?.forEach((v, k) => {\r\n let nodeTracks = this._activeTracks.get(k);\r\n if (!nodeTracks) {\r\n nodeTracks = new Map();\r\n this._activeTracks.set(k, nodeTracks);\r\n }\r\n for (const track of v) {\r\n const blendId = track.getBlendId();\r\n let blendedTracks = nodeTracks.get(blendId);\r\n if (!blendedTracks) {\r\n blendedTracks = [];\r\n nodeTracks.set(blendId, blendedTracks);\r\n }\r\n blendedTracks.push(track);\r\n }\r\n });\r\n ani.skeletons?.forEach((v, k) => {\r\n const skeleton = this.model.findSkeletonById(k);\r\n if (skeleton) {\r\n const refcount = this._activeSkeletons.get(skeleton);\r\n if (refcount) {\r\n this._activeSkeletons.set(skeleton, refcount + 1);\r\n } else {\r\n this._activeSkeletons.set(skeleton, 1);\r\n }\r\n skeleton.playing = true;\r\n }\r\n });\r\n }\r\n }\r\n /**\r\n * Stop playback of an animation clip.\r\n *\r\n * Behavior:\r\n * - If `options.fadeOut > 0`, marks the clip for fade-out; actual removal occurs after fade completes.\r\n * - If `fadeOut` is 0 or omitted, immediately:\r\n * - Removes the clip from active animations.\r\n * - Unregisters its tracks from active track maps.\r\n * - Decrements skeleton reference counts; resets and removes skeletons when refcount reaches 0.\r\n *\r\n * @param name - Name of the animation to stop.\r\n * @param options - Optional fade-out configuration.\r\n */\r\n stopAnimation(name: string, options?: StopAnimationOptions) {\r\n const ani = this._animations[name];\r\n if (!ani) {\r\n console.error(`Animation ${name} not exists`);\r\n return;\r\n }\r\n const info = this._activeAnimations.get(ani);\r\n if (info) {\r\n const fadeOut = Math.max(options?.fadeOut ?? 0, 0);\r\n if (fadeOut !== 0) {\r\n info.fadeOut = fadeOut;\r\n info.fadeOutStart = -1;\r\n } else {\r\n this._activeAnimations.delete(ani);\r\n this._activeTracks.forEach((v) => {\r\n v.forEach((tracks, id) => {\r\n v.set(\r\n id,\r\n tracks.filter((track) => track.animation !== ani)\r\n );\r\n });\r\n });\r\n ani.skeletons?.forEach((v, k) => {\r\n const skeleton = this.model.findSkeletonById(k);\r\n if (skeleton) {\r\n const refcount = this._activeSkeletons.get(skeleton)!;\r\n if (refcount === 1) {\r\n skeleton.reset();\r\n this._activeSkeletons.delete(skeleton);\r\n } else {\r\n this._activeSkeletons.set(skeleton, refcount - 1);\r\n }\r\n }\r\n });\r\n }\r\n }\r\n }\r\n /**\r\n * Copy an animation clip from another AnimationSet into this one.\r\n *\r\n * Prerequisites:\r\n * - Both sets must reference skeletons with identical joint names and counts.\r\n * - The source clip must exist in `sourceSet`.\r\n *\r\n * @param sourceSet - The AnimationSet to copy from.\r\n * @param animationName - Name of the clip to copy.\r\n * @param targetName - Name for the new clip in this set. Defaults to `animationName`.\r\n * @param excludeJoint - Optional predicate; joints whose name returns true are excluded from\r\n * skeleton structure matching.\r\n * @returns The newly created AnimationClip, or null on failure.\r\n */\r\n copyAnimationFrom(\r\n sourceSet: AnimationSet,\r\n animationName: string,\r\n targetName?: string,\r\n excludeJoint?: (jointName: string) => boolean\r\n ): AnimationClip | null {\r\n const destName = targetName ?? animationName;\r\n const sourceClip = sourceSet.get(animationName);\r\n if (!sourceClip) {\r\n console.error(`copyAnimationFrom: animation '${animationName}' not found in source set`);\r\n return null;\r\n }\r\n if (this._animations[destName]) {\r\n console.error(`copyAnimationFrom: animation '${destName}' already exists in target set`);\r\n return null;\r\n }\r\n\r\n // Per-joint retargeting info indexed by source joint node\r\n type JointRemap = {\r\n dstNode: SceneNode;\r\n srcBindRot: Quaternion;\r\n dstBindRot: Quaternion;\r\n translationScale: number;\r\n };\r\n const nodeMap = new Map<object, SceneNode>();\r\n const jointRemapBySrcNode = new Map<object, JointRemap>();\r\n\r\n for (const srcSkeletonId of sourceClip.skeletons) {\r\n const srcSkeleton = Skeleton.findSkeletonById(srcSkeletonId);\r\n if (!srcSkeleton) {\r\n console.error(`copyAnimationFrom: source skeleton '${srcSkeletonId}' not found`);\r\n return null;\r\n }\r\n // Build filtered joint lists for matching (exclude joints rejected by filterJoint)\r\n const srcJointsFiltered = srcSkeleton.joints.filter((j) => !excludeJoint?.(j.name));\r\n const dstSkeleton = this._skeletons\r\n .map((ref) => ref.get())\r\n .find((sk) => {\r\n if (!sk) {\r\n return false;\r\n }\r\n const dstJointsFiltered = sk.joints.filter((j) => !excludeJoint?.(j.name));\r\n return (\r\n dstJointsFiltered.length === srcJointsFiltered.length &&\r\n srcJointsFiltered.every((j, i) => j.name === dstJointsFiltered[i].name)\r\n );\r\n });\r\n if (!dstSkeleton) {\r\n console.error(`copyAnimationFrom: no matching skeleton in target set for '${srcSkeletonId}'`);\r\n return null;\r\n }\r\n // Build remap only for joints that pass the filter\r\n const dstJointsFiltered = dstSkeleton.joints.filter((j) => !excludeJoint?.(j.name));\r\n for (let fi = 0; fi < srcJointsFiltered.length; fi++) {\r\n const srcJoint = srcJointsFiltered[fi];\r\n const dstJoint = dstJointsFiltered[fi];\r\n const si = srcSkeleton.joints.indexOf(srcJoint);\r\n const di = dstSkeleton.joints.indexOf(dstJoint);\r\n const srcLen = srcSkeleton.bindPose[si].position.magnitude;\r\n const dstLen = dstSkeleton.bindPose[di].position.magnitude;\r\n const translationScale = srcLen > 1e-6 ? dstLen / srcLen : 1;\r\n nodeMap.set(srcJoint, dstJoint);\r\n jointRemapBySrcNode.set(srcJoint, {\r\n dstNode: dstJoint,\r\n srcBindRot: srcSkeleton.bindPose[si].rotation,\r\n dstBindRot: dstSkeleton.bindPose[di].rotation,\r\n translationScale\r\n });\r\n }\r\n }\r\n\r\n const dstClip = this.createAnimation(destName);\r\n if (!dstClip) {\r\n return null;\r\n }\r\n dstClip.timeDuration = sourceClip.timeDuration;\r\n dstClip.weight = sourceClip.weight;\r\n dstClip.autoPlay = sourceClip.autoPlay;\r\n\r\n // Register destination skeleton ids\r\n for (const srcSkeletonId of sourceClip.skeletons) {\r\n const srcSkeleton = Skeleton.findSkeletonById(srcSkeletonId)!;\r\n const firstSrcJoint = srcSkeleton.joints[0];\r\n const firstDstJoint = nodeMap.get(firstSrcJoint);\r\n const dstSkeleton = this._skeletons\r\n .map((r) => r.get())\r\n .find((sk) => sk && sk.joints[0] === firstDstJoint);\r\n if (dstSkeleton) {\r\n dstClip.addSkeleton(dstSkeleton.persistentId);\r\n }\r\n }\r\n\r\n const tmpSrcBind = new Quaternion();\r\n const tmpDstBindInv = new Quaternion();\r\n\r\n for (const [srcNode, srcTracks] of sourceClip.tracks) {\r\n const dstNode = nodeMap.get(srcNode);\r\n if (!dstNode) {\r\n continue;\r\n }\r\n const remap = jointRemapBySrcNode.get(srcNode) ?? null;\r\n\r\n for (const srcTrack of srcTracks) {\r\n let dstTrack: AnimationTrack;\r\n\r\n if (srcTrack instanceof NodeRotationTrack) {\r\n dstTrack = retargetRotationTrack(srcTrack, remap);\r\n } else if (srcTrack instanceof NodeEulerRotationTrack) {\r\n dstTrack = retargetEulerToRotationTrack(srcTrack, remap);\r\n } else if (srcTrack instanceof NodeTranslationTrack) {\r\n dstTrack = retargetTranslationTrack(srcTrack, remap);\r\n } else if (srcTrack instanceof NodeScaleTrack) {\r\n dstTrack = new NodeScaleTrack(cloneInterpolator(srcTrack.interpolator));\r\n } else {\r\n console.warn(`copyAnimationFrom: unsupported track type '${srcTrack.constructor.name}', skipping`);\r\n continue;\r\n }\r\n\r\n dstTrack.name = srcTrack.name;\r\n dstTrack.target = srcTrack.target;\r\n dstTrack.jointIndex = srcTrack.jointIndex;\r\n dstClip.addTrack(dstNode, dstTrack);\r\n }\r\n }\r\n\r\n return dstClip;\r\n\r\n function retargetTranslationTrack(\r\n src: NodeTranslationTrack,\r\n remap: JointRemap | null\r\n ): NodeTranslationTrack {\r\n if (!remap || Math.abs(remap.translationScale - 1) < 1e-6) {\r\n return new NodeTranslationTrack(cloneInterpolator(src.interpolator));\r\n }\r\n const scale = remap.translationScale;\r\n const srcOutputs = src.interpolator.outputs as Float32Array;\r\n const newOutputs = new Float32Array(srcOutputs.length);\r\n for (let i = 0; i < newOutputs.length; i++) {\r\n newOutputs[i] = srcOutputs[i] * scale;\r\n }\r\n return new NodeTranslationTrack(\r\n new Interpolator(\r\n src.interpolator.mode,\r\n 'vec3',\r\n new Float32Array(src.interpolator.inputs as Float32Array),\r\n newOutputs\r\n )\r\n );\r\n }\r\n\r\n function cloneInterpolator(src: Interpolator): Interpolator {\r\n return new Interpolator(\r\n src.mode,\r\n src.target,\r\n src.inputs instanceof Float32Array ? new Float32Array(src.inputs) : [...src.inputs],\r\n src.outputs instanceof Float32Array ? new Float32Array(src.outputs) : [...src.outputs]\r\n );\r\n }\r\n\r\n function retargetRotationTrack(src: NodeRotationTrack, remap: JointRemap | null): NodeRotationTrack {\r\n if (!remap) {\r\n return new NodeRotationTrack(cloneInterpolator(src.interpolator));\r\n }\r\n tmpSrcBind.set(remap.srcBindRot);\r\n Quaternion.conjugate(remap.dstBindRot, tmpDstBindInv);\r\n const isCubic = src.interpolator.mode === 'cubicspline';\r\n const frameStride = isCubic ? 12 : 4;\r\n const numFrames = (src.interpolator.inputs as Float32Array).length;\r\n const srcOutputs = src.interpolator.outputs as Float32Array;\r\n const newOutputs = new Float32Array(srcOutputs.length);\r\n const q = new Quaternion();\r\n for (let f = 0; f < numFrames; f++) {\r\n const base = f * frameStride;\r\n if (isCubic) {\r\n // layout per frame: [inTangent×4, value×4, outTangent×4] — only retarget value\r\n newOutputs.set(srcOutputs.subarray(base, base + 4), base);\r\n q.set(srcOutputs.subarray(base + 4, base + 8));\r\n Quaternion.multiply(tmpSrcBind, q, q);\r\n Quaternion.multiply(tmpDstBindInv, q, q);\r\n newOutputs[base + 4] = q.x;\r\n newOutputs[base + 5] = q.y;\r\n newOutputs[base + 6] = q.z;\r\n newOutputs[base + 7] = q.w;\r\n newOutputs.set(srcOutputs.subarray(base + 8, base + 12), base + 8);\r\n } else {\r\n q.set(srcOutputs.subarray(base, base + 4));\r\n Quaternion.multiply(tmpSrcBind, q, q);\r\n Quaternion.multiply(tmpDstBindInv, q, q);\r\n newOutputs[base] = q.x;\r\n newOutputs[base + 1] = q.y;\r\n newOutputs[base + 2] = q.z;\r\n newOutputs[base + 3] = q.w;\r\n }\r\n }\r\n return new NodeRotationTrack(\r\n new Interpolator(\r\n src.interpolator.mode,\r\n 'quat',\r\n new Float32Array(src.interpolator.inputs as Float32Array),\r\n newOutputs\r\n )\r\n );\r\n }\r\n\r\n function retargetEulerToRotationTrack(\r\n src: NodeEulerRotationTrack,\r\n remap: JointRemap | null\r\n ): NodeRotationTrack {\r\n const srcInputs = src.interpolator.inputs as Float32Array;\r\n const srcOutputs = src.interpolator.outputs as Float32Array;\r\n const numFrames = srcInputs.length;\r\n const newOutputs = new Float32Array(numFrames * 4);\r\n const q = new Quaternion();\r\n if (remap) {\r\n tmpSrcBind.set(remap.srcBindRot);\r\n Quaternion.conjugate(remap.dstBindRot, tmpDstBindInv);\r\n }\r\n for (let f = 0; f < numFrames; f++) {\r\n const b3 = f * 3;\r\n const b4 = f * 4;\r\n q.fromEulerAngle(srcOutputs[b3], srcOutputs[b3 + 1], srcOutputs[b3 + 2]);\r\n if (remap) {\r\n Quaternion.multiply(tmpSrcBind, q, q);\r\n Quaternion.multiply(tmpDstBindInv, q, q);\r\n }\r\n newOutputs[b4] = q.x;\r\n newOutputs[b4 + 1] = q.y;\r\n newOutputs[b4 + 2] = q.z;\r\n newOutputs[b4 + 3] = q.w;\r\n }\r\n return new NodeRotationTrack(\r\n new Interpolator('linear', 'quat', new Float32Array(srcInputs), newOutputs)\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Dispose the animation set and release owned resources.\r\n *\r\n * - Disposes the weak reference to the model.\r\n * - Disposes all registered animation clips.\r\n * - Clears active animations, tracks, and skeleton references.\r\n */\r\n protected onDispose() {\r\n super.onDispose();\r\n for (const k in this._animations) {\r\n this._animations[k]!.dispose();\r\n }\r\n this._animations = {};\r\n this._activeAnimations.clear();\r\n this._activeSkeletons.clear();\r\n this._activeTracks.clear();\r\n }\r\n}\r\n"],"names":["AnimationSet","Disposable","model","_model","_animations","_activeTracks","Map","_activeSkeletons","_activeAnimations","_skeletons","numAnimations","Object","getOwnPropertyNames","length","skeletons","get","name","createAnimation","embedded","console","error","animation","AnimationClip","scene","queueUpdateNode","deleteAnimation","stopAnimation","dispose","getAnimationNames","keys","update","deltaInSeconds","forEach","v","k","fadeOut","fadeOutStart","animateTime","firstFrame","timeAdvance","speedRatio","currentTime","timeDuration","repeatCounter","repeat","alltracks","tracks","filter","track","isPlayingAnimation","weights","map","info","weight","fadeIn","Math","min","states","t","getDuration","calculateState","state","weightedAverage","a","b","mixState","applyState","apply","has","size","getAnimationClip","setAnimationWeight","ani","playAnimation","options","max","set","nodeTracks","blendId","getBlendId","blendedTracks","push","skeleton","findSkeletonById","refcount","playing","delete","id","reset","copyAnimationFrom","sourceSet","animationName","targetName","excludeJoint","destName","sourceClip","nodeMap","jointRemapBySrcNode","srcSkeletonId","srcSkeleton","Skeleton","srcJointsFiltered","joints","j","dstSkeleton","ref","find","sk","dstJointsFiltered","every","i","fi","srcJoint","dstJoint","si","indexOf","di","srcLen","bindPose","position","magnitude","dstLen","translationScale","dstNode","srcBindRot","rotation","dstBindRot","dstClip","autoPlay","firstSrcJoint","firstDstJoint","r","addSkeleton","persistentId","tmpSrcBind","Quaternion","tmpDstBindInv","srcNode","srcTracks","remap","srcTrack","dstTrack","NodeRotationTrack","retargetRotationTrack","NodeEulerRotationTrack","retargetEulerToRotationTrack","NodeTranslationTrack","retargetTranslationTrack","NodeScaleTrack","cloneInterpolator","interpolator","warn","target","jointIndex","addTrack","src","abs","scale","srcOutputs","outputs","newOutputs","Float32Array","Interpolator","mode","inputs","conjugate","isCubic","frameStride","numFrames","q","f","base","subarray","multiply","x","y","z","w","srcInputs","b3","b4","fromEulerAngle","onDispose","clear"],"mappings":"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"}
1
+ {"version":3,"file":"animationset.js","sources":["../../src/animation/animationset.ts"],"sourcesContent":["import { weightedAverage, Disposable, Interpolator } from '@zephyr3d/base';\r\nimport type { DRef, IDisposable, Nullable, Quaternion } from '@zephyr3d/base';\r\nimport type { SceneNode } from '../scene';\r\nimport { AnimationClip } from './animation';\r\nimport type { AnimationTrack } from './animationtrack';\r\nimport { NodeRotationTrack } from './rotationtrack';\r\nimport { NodeEulerRotationTrack } from './eulerrotationtrack';\r\nimport { NodeTranslationTrack } from './translationtrack';\r\nimport { NodeScaleTrack } from './scaletrack';\r\nimport { Skeleton } from './skeleton';\r\n\r\n/**\r\n * Options for playing an animation.\r\n *\r\n * Controls looping, playback speed (including reverse), and fade-in blending.\r\n * @public\r\n **/\r\nexport type PlayAnimationOptions = {\r\n /**\r\n * Number of loops to play.\r\n *\r\n * - 0: infinite looping (default).\r\n * - n \\> 0: play exactly n loops (each loop is one full duration of the clip).\r\n */\r\n repeat?: number;\r\n /**\r\n * Playback speed multiplier.\r\n *\r\n * - 1: normal speed (default).\r\n * - \\>1: faster; \\<1: slower.\r\n * - Negative values play the clip in reverse. The initial `currentTime` will be set to the end.\r\n */\r\n speedRatio?: number;\r\n /**\r\n * Fade-in duration in seconds.\r\n *\r\n * Interpolates the animation weight from 0 to the clip's configured weight over this time.\r\n * Use together with `stopAnimation(..., { fadeOut })` for smooth cross-fading.\r\n * Default is 0 (no fade-in).\r\n */\r\n fadeIn?: number;\r\n /**\r\n * Weight of the animation clip.\r\n *\r\n * Used during blending when multiple animations affect the same property.\r\n * Default is the clip's configured weight.\r\n */\r\n weight?: number;\r\n};\r\n\r\n/**\r\n * Options for stopping an animation.\r\n *\r\n * Allows a graceful fade-out instead of abrupt stop.\r\n * @public\r\n */\r\nexport type StopAnimationOptions = {\r\n /**\r\n * Fade-out duration in seconds.\r\n *\r\n * Interpolates the current animation weight down to 0 over this time.\r\n * Default is 0 (immediate stop).\r\n */\r\n fadeOut?: number;\r\n};\r\n\r\n/**\r\n * Animation set\r\n *\r\n * Manages a collection of named animation clips for a model and orchestrates:\r\n * - Playback state (time, loops, speed, weights, fade-in/out).\r\n * - Blending across multiple tracks targeting the same property via weighted averages.\r\n * - Skeleton usage and application for clips that drive skeletal animation.\r\n * - Active track registration and cleanup as clips start/stop.\r\n *\r\n * Usage:\r\n * - Create or retrieve `AnimationClip`s by name.\r\n * - Start playback with `playAnimation(name, options)`.\r\n * - Advance animation with `update(deltaSeconds)`.\r\n * - Optionally adjust weight while playing with `setAnimationWeight(name, weight)`.\r\n *\r\n * Lifetime:\r\n * - Disposing the set releases references to the model, clips, and clears active state.\r\n *\r\n * @public\r\n */\r\nexport class AnimationSet extends Disposable implements IDisposable {\r\n /** @internal */\r\n private _model: SceneNode;\r\n /** @internal */\r\n private _animations: Partial<Record<string, AnimationClip>>;\r\n /** @internal */\r\n private _skeletons: DRef<Skeleton>[];\r\n /** @internal */\r\n private readonly _activeTracks: Map<object, Map<unknown, AnimationTrack[]>>;\r\n /** @internal */\r\n private readonly _activeSkeletons: Map<Skeleton, number>;\r\n /** @internal */\r\n private readonly _activeAnimations: Map<\r\n AnimationClip,\r\n {\r\n currentTime: number;\r\n repeat: number;\r\n repeatCounter: number;\r\n weight: number;\r\n speedRatio: number;\r\n firstFrame: boolean;\r\n fadeIn: number;\r\n fadeOut: number;\r\n fadeOutStart: number;\r\n animateTime: number;\r\n }\r\n >;\r\n /**\r\n * Create an AnimationSet controlling the provided model.\r\n *\r\n * @param model - The SceneNode (model root) controlled by this animation set.\r\n */\r\n constructor(model: SceneNode) {\r\n super();\r\n this._model = model;\r\n this._animations = {};\r\n this._activeTracks = new Map();\r\n this._activeSkeletons = new Map();\r\n this._activeAnimations = new Map();\r\n this._skeletons = [];\r\n }\r\n /**\r\n * The model (SceneNode) controlled by this animation set.\r\n */\r\n get model() {\r\n return this._model;\r\n }\r\n /**\r\n * Number of animation clips registered in this set.\r\n */\r\n get numAnimations() {\r\n return Object.getOwnPropertyNames(this._animations).length;\r\n }\r\n /**\r\n * The skeletons used by animations in this set.\r\n */\r\n get skeletons() {\r\n return this._skeletons;\r\n }\r\n /**\r\n * Retrieve an animation clip by name.\r\n *\r\n * @param name - Name of the animation.\r\n * @returns The clip if present; otherwise null.\r\n */\r\n get(name: string) {\r\n return this._animations[name] ?? null;\r\n }\r\n /**\r\n * Create and register a new animation clip.\r\n *\r\n * @param name - Unique name for the animation clip.\r\n * @param embedded - Whether the clip is embedded/owned (implementation-specific). Default false.\r\n * @returns The created clip, or null if the name is empty or not unique.\r\n */\r\n createAnimation(name: string, embedded = false) {\r\n if (!name || this._animations[name]) {\r\n console.error('Animation must have unique name');\r\n return null;\r\n } else {\r\n const animation = new AnimationClip(name, this, embedded);\r\n this._animations[name] = animation;\r\n this._model.scene?.queueUpdateNode(this._model);\r\n return animation;\r\n }\r\n }\r\n /**\r\n * Delete and dispose an animation clip by name.\r\n *\r\n * - If the animation is currently playing, it is first stopped (immediately).\r\n *\r\n * @param name - Name of the animation to remove.\r\n */\r\n deleteAnimation(name: string) {\r\n const animation = this._animations[name];\r\n if (animation) {\r\n this.stopAnimation(name);\r\n delete this._animations[name];\r\n animation.dispose();\r\n }\r\n }\r\n /**\r\n * Get the list of all registered animation names.\r\n *\r\n * @returns An array of clip names.\r\n */\r\n getAnimationNames() {\r\n return Object.keys(this._animations);\r\n }\r\n /**\r\n * Advance and apply active animations.\r\n *\r\n * Responsibilities per call:\r\n * - Update time cursor for each active clip (respecting speedRatio and looping).\r\n * - Enforce repeat limits and apply fade-out termination if configured.\r\n * - For each animated target, blend active tracks (weighted by clip weight × fade-in × fade-out)\r\n * and apply the resulting state to the target.\r\n * - Apply all active skeletons to update skinning transforms.\r\n *\r\n * @param deltaInSeconds - Time step in seconds since last update.\r\n */\r\n update(deltaInSeconds: number) {\r\n this._activeAnimations.forEach((v, k) => {\r\n if (v.fadeOut > 0 && v.fadeOutStart < 0) {\r\n v.fadeOutStart = v.animateTime;\r\n }\r\n // Update animation time\r\n if (v.firstFrame) {\r\n v.firstFrame = false;\r\n } else {\r\n const timeAdvance = deltaInSeconds * v.speedRatio;\r\n v.currentTime += timeAdvance;\r\n v.animateTime += timeAdvance;\r\n if (v.currentTime > k.timeDuration) {\r\n v.repeatCounter++;\r\n v.currentTime = 0;\r\n } else if (v.currentTime < 0) {\r\n v.repeatCounter++;\r\n v.currentTime = k.timeDuration;\r\n }\r\n if (v.repeat !== 0 && v.repeatCounter >= v.repeat) {\r\n this.stopAnimation(k.name);\r\n } else if (v.fadeOut > 0) {\r\n if (v.animateTime - v.fadeOutStart >= v.fadeOut) {\r\n this.stopAnimation(k.name);\r\n }\r\n }\r\n }\r\n });\r\n // Update tracks\r\n this._activeTracks.forEach((v, k) => {\r\n v.forEach((alltracks) => {\r\n // Only deal with tracks which have not been removed\r\n const tracks = alltracks.filter(\r\n (track) => track.animation && this.isPlayingAnimation(track.animation.name)\r\n );\r\n if (tracks.length > 0) {\r\n const weights = tracks.map((track) => {\r\n const info = this._activeAnimations.get(track.animation!)!;\r\n const weight = info.weight;\r\n const fadeIn = info.fadeIn === 0 ? 1 : Math.min(1, info.animateTime / info.fadeIn);\r\n let fadeOut = 1;\r\n if (info.fadeOut !== 0) {\r\n fadeOut = 1 - (info.animateTime - info.fadeOutStart) / info.fadeOut;\r\n }\r\n return weight * fadeIn * fadeOut;\r\n });\r\n const states = tracks.map((track) => {\r\n const info = this._activeAnimations.get(track.animation!)!;\r\n const t = (info.currentTime / track.animation!.timeDuration) * track.getDuration();\r\n return track.calculateState(k, t);\r\n });\r\n const state = weightedAverage(weights, states, (a, b, t) => {\r\n return tracks[0].mixState(a, b, t);\r\n });\r\n tracks[0].applyState(k, state);\r\n }\r\n });\r\n });\r\n // Update skeletons\r\n this._skeletons.forEach((v) => {\r\n v.get()?.apply(deltaInSeconds);\r\n });\r\n }\r\n /**\r\n * Check whether an animation is currently playing.\r\n *\r\n * @param name - Optional animation name. If omitted, returns true if any animation is playing.\r\n * @returns True if playing; otherwise false.\r\n */\r\n isPlayingAnimation(name?: string) {\r\n if (name) {\r\n const animation = this._animations[name];\r\n return !!animation && this._activeAnimations.has(animation);\r\n }\r\n return this._activeAnimations.size > 0;\r\n }\r\n /**\r\n * Get an animation clip by name.\r\n *\r\n * Alias of `get(name)` returning a nullable type.\r\n *\r\n * @param name - Name of the animation.\r\n * @returns The clip if present; otherwise null.\r\n */\r\n getAnimationClip(name: string) {\r\n return this._animations[name] ?? null;\r\n }\r\n /**\r\n * Set the runtime blend weight for a currently playing animation.\r\n *\r\n * Has no effect if the clip is not active.\r\n *\r\n * @param name - Name of the playing animation.\r\n * @param weight - New weight value used during blending.\r\n */\r\n setAnimationWeight(name: string, weight: number) {\r\n const ani = this._animations[name];\r\n if (!ani) {\r\n console.error(`Animation ${name} not exists`);\r\n return;\r\n }\r\n const info = this._activeAnimations.get(ani);\r\n if (info) {\r\n info.weight = weight;\r\n }\r\n }\r\n /**\r\n * Start (or update) playback of an animation clip.\r\n *\r\n * Behavior:\r\n * - If the clip is already playing, updates its fade-in (resets fade-out).\r\n * - Otherwise initializes playback state (repeat counter, speed, weight, initial time).\r\n * - Registers clip tracks and skeletons into the active sets for blending and application.\r\n *\r\n * @param name - Name of the animation to play.\r\n * @param options - Playback options (repeat, speedRatio, fadeIn).\r\n */\r\n playAnimation(name: string, options?: PlayAnimationOptions) {\r\n const ani = this._animations[name];\r\n if (!ani) {\r\n console.error(`Animation ${name} not exists`);\r\n return;\r\n }\r\n const fadeIn = Math.max(options?.fadeIn ?? 0, 0);\r\n const info = this._activeAnimations.get(ani);\r\n if (info) {\r\n info.fadeOut = 0;\r\n info.fadeIn = fadeIn;\r\n } else {\r\n const repeat = options?.repeat ?? 0;\r\n const speedRatio = options?.speedRatio ?? 1;\r\n const weight = options?.weight ?? ani.weight ?? 1;\r\n this._activeAnimations.set(ani, {\r\n repeat,\r\n weight,\r\n speedRatio,\r\n fadeIn,\r\n fadeOut: 0,\r\n repeatCounter: 0,\r\n currentTime: speedRatio < 0 ? ani.timeDuration : 0,\r\n animateTime: 0,\r\n fadeOutStart: 0,\r\n firstFrame: true\r\n });\r\n ani.tracks?.forEach((v, k) => {\r\n let nodeTracks = this._activeTracks.get(k);\r\n if (!nodeTracks) {\r\n nodeTracks = new Map();\r\n this._activeTracks.set(k, nodeTracks);\r\n }\r\n for (const track of v) {\r\n const blendId = track.getBlendId();\r\n let blendedTracks = nodeTracks.get(blendId);\r\n if (!blendedTracks) {\r\n blendedTracks = [];\r\n nodeTracks.set(blendId, blendedTracks);\r\n }\r\n blendedTracks.push(track);\r\n }\r\n });\r\n ani.skeletons?.forEach((v, k) => {\r\n const skeleton = this.model.findSkeletonById(k);\r\n if (skeleton) {\r\n const refcount = this._activeSkeletons.get(skeleton);\r\n if (refcount) {\r\n this._activeSkeletons.set(skeleton, refcount + 1);\r\n } else {\r\n this._activeSkeletons.set(skeleton, 1);\r\n }\r\n skeleton.playing = true;\r\n }\r\n });\r\n }\r\n }\r\n /**\r\n * Stop playback of an animation clip.\r\n *\r\n * Behavior:\r\n * - If `options.fadeOut > 0`, marks the clip for fade-out; actual removal occurs after fade completes.\r\n * - If `fadeOut` is 0 or omitted, immediately:\r\n * - Removes the clip from active animations.\r\n * - Unregisters its tracks from active track maps.\r\n * - Decrements skeleton reference counts; resets and removes skeletons when refcount reaches 0.\r\n *\r\n * @param name - Name of the animation to stop.\r\n * @param options - Optional fade-out configuration.\r\n */\r\n stopAnimation(name: string, options?: StopAnimationOptions) {\r\n const ani = this._animations[name];\r\n if (!ani) {\r\n console.error(`Animation ${name} not exists`);\r\n return;\r\n }\r\n const info = this._activeAnimations.get(ani);\r\n if (info) {\r\n const fadeOut = Math.max(options?.fadeOut ?? 0, 0);\r\n if (fadeOut !== 0) {\r\n info.fadeOut = fadeOut;\r\n info.fadeOutStart = -1;\r\n } else {\r\n this._activeAnimations.delete(ani);\r\n this._activeTracks.forEach((v) => {\r\n v.forEach((tracks, id) => {\r\n v.set(\r\n id,\r\n tracks.filter((track) => track.animation !== ani)\r\n );\r\n });\r\n });\r\n ani.skeletons?.forEach((v, k) => {\r\n const skeleton = this.model.findSkeletonById(k);\r\n if (skeleton) {\r\n const refcount = this._activeSkeletons.get(skeleton)!;\r\n if (refcount === 1) {\r\n skeleton.reset();\r\n this._activeSkeletons.delete(skeleton);\r\n } else {\r\n this._activeSkeletons.set(skeleton, refcount - 1);\r\n }\r\n }\r\n });\r\n }\r\n }\r\n }\r\n /**\r\n * Copy an animation clip from another AnimationSet into this one.\r\n *\r\n * Prerequisites:\r\n * - Both sets must reference skeletons with identical joint names and counts.\r\n * - The source clip must exist in `sourceSet`.\r\n *\r\n * @param sourceSet - The AnimationSet to copy from.\r\n * @param animationName - Name of the clip to copy.\r\n * @param targetName - Name for the new clip in this set. Defaults to `animationName`.\r\n * @param excludeJoint - Optional predicate; joints whose name returns true are excluded from\r\n * skeleton structure matching.\r\n * @returns The newly created AnimationClip, or null on failure.\r\n */\r\n copyAnimationFrom(\r\n sourceSet: AnimationSet,\r\n animationName: string,\r\n targetName?: string,\r\n excludeJoint?: (jointName: string) => boolean\r\n ): AnimationClip | null {\r\n const destName = targetName ?? animationName;\r\n const sourceClip = sourceSet.get(animationName);\r\n if (!sourceClip) {\r\n console.error(`copyAnimationFrom: animation '${animationName}' not found in source set`);\r\n return null;\r\n }\r\n if (this._animations[destName]) {\r\n console.error(`copyAnimationFrom: animation '${destName}' already exists in target set`);\r\n return null;\r\n }\r\n\r\n // Per-joint retargeting info indexed by source joint node\r\n type JointRemap = {\r\n dstNode: SceneNode;\r\n srcBindRot: Quaternion;\r\n dstBindRot: Quaternion;\r\n translationScale: number;\r\n };\r\n if (sourceClip.skeletons.size !== 1) {\r\n console.error(`copyAnimationFrom: source animation clip must be affected by exactly one skeleton`);\r\n return null;\r\n }\r\n const srcSkeletonId = [...sourceClip.skeletons][0];\r\n const srcSkeleton = Skeleton.findSkeletonById(srcSkeletonId);\r\n if (!srcSkeleton) {\r\n console.error(`copyAnimationFrom: source skeleton '${srcSkeletonId}' not found`);\r\n return null;\r\n }\r\n const nodeMap = new Map<object, SceneNode>();\r\n const jointRemapBySrcNode = new Map<object, JointRemap>();\r\n\r\n const jointsFiltered = srcSkeleton.joints.filter((j) => !excludeJoint?.(j.name));\r\n const srcRootNode = findRootJoint(jointsFiltered);\r\n if (!srcRootNode) {\r\n console.error(`copyAnimationFrom: cannot determine the root joint for source skeleton`);\r\n return null;\r\n }\r\n // Build filtered joint lists for matching (exclude joints rejected by filterJoint)\r\n const srcJointsFiltered = sortJoints(srcRootNode, jointsFiltered);\r\n if (!srcJointsFiltered) {\r\n console.error(`copyAnimationFrom: invalid source skeleton structure`);\r\n return null;\r\n }\r\n let dstJointsFiltered: SceneNode[] = [];\r\n const dstSkeleton = this._skeletons\r\n .map((ref) => ref.get())\r\n .find((sk) => {\r\n if (!sk) {\r\n return false;\r\n }\r\n const jointsFiltered = sk.joints.filter((j) => !excludeJoint?.(j.name));\r\n if (jointsFiltered.length !== srcJointsFiltered.length) {\r\n return false;\r\n }\r\n const rootNode = findRootJoint(jointsFiltered);\r\n if (!rootNode) {\r\n return false;\r\n }\r\n const sortedJointsFiltered = sortJoints(rootNode, jointsFiltered);\r\n if (\r\n sortedJointsFiltered &&\r\n srcJointsFiltered.every((j, i) => j.name === sortedJointsFiltered[i].name)\r\n ) {\r\n dstJointsFiltered = sortedJointsFiltered;\r\n return true;\r\n }\r\n return false;\r\n });\r\n if (!dstJointsFiltered || !dstSkeleton) {\r\n console.error(`copyAnimationFrom: no matching skeleton in target set for '${srcSkeletonId}'`);\r\n return null;\r\n }\r\n // Build remap only for joints that pass the filter\r\n for (let fi = 0; fi < srcJointsFiltered.length; fi++) {\r\n const srcJoint = srcJointsFiltered[fi];\r\n const dstJoint = dstJointsFiltered[fi];\r\n const si = srcSkeleton.joints.indexOf(srcJoint);\r\n const di = dstSkeleton.joints.indexOf(dstJoint);\r\n const srcLen = srcSkeleton.bindPose[si].position.magnitude;\r\n const dstLen = dstSkeleton.bindPose[di].position.magnitude;\r\n const translationScale = srcLen > 1e-6 ? dstLen / srcLen : 1;\r\n nodeMap.set(srcJoint, dstJoint);\r\n jointRemapBySrcNode.set(srcJoint, {\r\n dstNode: dstJoint,\r\n srcBindRot: srcSkeleton.bindPose[si].rotation,\r\n dstBindRot: dstSkeleton.bindPose[di].rotation,\r\n translationScale\r\n });\r\n }\r\n\r\n const dstClip = this.createAnimation(destName);\r\n if (!dstClip) {\r\n return null;\r\n }\r\n dstClip.timeDuration = sourceClip.timeDuration;\r\n dstClip.weight = sourceClip.weight;\r\n dstClip.autoPlay = sourceClip.autoPlay;\r\n\r\n // Register destination skeleton\r\n dstClip.addSkeleton(dstSkeleton.persistentId);\r\n\r\n for (const srcNode of srcJointsFiltered) {\r\n const srcTracks = sourceClip.tracks.get(srcNode);\r\n if (!srcTracks) {\r\n console.error(`copyAnimationFrom: no track for joint: ${srcNode.name}`);\r\n return null;\r\n }\r\n const dstNode = nodeMap.get(srcNode)!;\r\n const remap = jointRemapBySrcNode.get(srcNode) ?? null;\r\n\r\n for (const srcTrack of srcTracks) {\r\n let dstTrack: AnimationTrack;\r\n if (srcTrack instanceof NodeRotationTrack) {\r\n dstTrack = retargetRotationTrack(srcTrack);\r\n } else if (srcTrack instanceof NodeEulerRotationTrack) {\r\n dstTrack = retargetEulerToRotationTrack(srcTrack);\r\n } else if (srcTrack instanceof NodeTranslationTrack) {\r\n dstTrack = retargetTranslationTrack(srcTrack, remap);\r\n } else if (srcTrack instanceof NodeScaleTrack) {\r\n dstTrack = new NodeScaleTrack(cloneInterpolator(srcTrack.interpolator));\r\n } else {\r\n console.warn(`copyAnimationFrom: unsupported track type '${srcTrack.constructor.name}', skipping`);\r\n continue;\r\n }\r\n\r\n dstTrack.name = srcTrack.name;\r\n dstTrack.target = srcTrack.target;\r\n dstTrack.jointIndex = srcTrack.jointIndex;\r\n dstClip.addTrack(dstNode, dstTrack);\r\n }\r\n }\r\n\r\n return dstClip;\r\n\r\n function findRootJoint(joints: SceneNode[]) {\r\n let root: Nullable<SceneNode> = null;\r\n for (const joint of joints) {\r\n if (!root) {\r\n root = joint;\r\n }\r\n while (!root!.isParentOf(joint)) {\r\n root = root!.parent;\r\n }\r\n if (!root) {\r\n break;\r\n }\r\n }\r\n if (!root || !joints.includes(root)) {\r\n return null;\r\n }\r\n return root;\r\n }\r\n\r\n function sortJoints(root: SceneNode, joints: SceneNode[]): Nullable<SceneNode[]> {\r\n const ordered: SceneNode[] = [];\r\n const visited = new Set<SceneNode>();\r\n function visit(joint: SceneNode) {\r\n if (visited.has(joint)) {\r\n return true;\r\n }\r\n if (!joints.includes(joint)) {\r\n return false;\r\n }\r\n if (joint !== root) {\r\n visit(joint.parent!);\r\n }\r\n visited.add(joint);\r\n ordered.push(joint);\r\n return true;\r\n }\r\n for (const joint of joints) {\r\n if (!visit(joint)) {\r\n return null;\r\n }\r\n }\r\n return ordered;\r\n }\r\n function retargetTranslationTrack(\r\n src: NodeTranslationTrack,\r\n remap: JointRemap | null\r\n ): NodeTranslationTrack {\r\n if (!remap || Math.abs(remap.translationScale - 1) < 1e-6) {\r\n return new NodeTranslationTrack(cloneInterpolator(src.interpolator));\r\n }\r\n const scale = remap.translationScale;\r\n const srcOutputs = src.interpolator.outputs as Float32Array;\r\n const newOutputs = new Float32Array(srcOutputs.length);\r\n for (let i = 0; i < newOutputs.length; i++) {\r\n newOutputs[i] = srcOutputs[i] * scale;\r\n }\r\n return new NodeTranslationTrack(\r\n new Interpolator(\r\n src.interpolator.mode,\r\n 'vec3',\r\n new Float32Array(src.interpolator.inputs as Float32Array),\r\n newOutputs\r\n )\r\n );\r\n }\r\n\r\n function cloneInterpolator(src: Interpolator): Interpolator {\r\n return new Interpolator(\r\n src.mode,\r\n src.target,\r\n src.inputs instanceof Float32Array ? new Float32Array(src.inputs) : [...src.inputs],\r\n src.outputs instanceof Float32Array ? new Float32Array(src.outputs) : [...src.outputs]\r\n );\r\n }\r\n\r\n function retargetRotationTrack(src: NodeRotationTrack): NodeRotationTrack {\r\n const isCubic = src.interpolator.mode === 'cubicspline';\r\n const frameStride = isCubic ? 12 : 4;\r\n const numFrames = (src.interpolator.inputs as Float32Array).length;\r\n const srcOutputs = src.interpolator.outputs as Float32Array;\r\n const newOutputs = new Float32Array(srcOutputs.length);\r\n for (let f = 0; f < numFrames; f++) {\r\n const base = f * frameStride;\r\n newOutputs.set(srcOutputs.subarray(base, base + (isCubic ? 12 : 4)), base);\r\n }\r\n return new NodeRotationTrack(\r\n new Interpolator(\r\n src.interpolator.mode,\r\n 'quat',\r\n new Float32Array(src.interpolator.inputs as Float32Array),\r\n newOutputs\r\n )\r\n );\r\n }\r\n\r\n function retargetEulerToRotationTrack(src: NodeEulerRotationTrack): NodeRotationTrack {\r\n const srcInputs = src.interpolator.inputs as Float32Array;\r\n const srcOutputs = src.interpolator.outputs as Float32Array;\r\n const numFrames = srcInputs.length;\r\n const newOutputs = new Float32Array(numFrames * 3);\r\n for (let f = 0; f < numFrames; f++) {\r\n const base = f * 3;\r\n newOutputs.set(srcOutputs.subarray(base, base + 3), base);\r\n }\r\n return new NodeRotationTrack(\r\n new Interpolator('linear', 'quat', new Float32Array(srcInputs), newOutputs)\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Dispose the animation set and release owned resources.\r\n *\r\n * - Disposes the weak reference to the model.\r\n * - Disposes all registered animation clips.\r\n * - Clears active animations, tracks, and skeleton references.\r\n */\r\n protected onDispose() {\r\n super.onDispose();\r\n for (const k in this._animations) {\r\n this._animations[k]!.dispose();\r\n }\r\n this._animations = {};\r\n this._activeAnimations.clear();\r\n this._activeSkeletons.clear();\r\n this._activeTracks.clear();\r\n }\r\n}\r\n"],"names":["AnimationSet","Disposable","model","_model","_animations","_activeTracks","Map","_activeSkeletons","_activeAnimations","_skeletons","numAnimations","Object","getOwnPropertyNames","length","skeletons","get","name","createAnimation","embedded","console","error","animation","AnimationClip","scene","queueUpdateNode","deleteAnimation","stopAnimation","dispose","getAnimationNames","keys","update","deltaInSeconds","forEach","v","k","fadeOut","fadeOutStart","animateTime","firstFrame","timeAdvance","speedRatio","currentTime","timeDuration","repeatCounter","repeat","alltracks","tracks","filter","track","isPlayingAnimation","weights","map","info","weight","fadeIn","Math","min","states","t","getDuration","calculateState","state","weightedAverage","a","b","mixState","applyState","apply","has","size","getAnimationClip","setAnimationWeight","ani","playAnimation","options","max","set","nodeTracks","blendId","getBlendId","blendedTracks","push","skeleton","findSkeletonById","refcount","playing","delete","id","reset","copyAnimationFrom","sourceSet","animationName","targetName","excludeJoint","destName","sourceClip","srcSkeletonId","srcSkeleton","Skeleton","nodeMap","jointRemapBySrcNode","jointsFiltered","joints","j","srcRootNode","findRootJoint","srcJointsFiltered","sortJoints","dstJointsFiltered","dstSkeleton","ref","find","sk","rootNode","sortedJointsFiltered","every","i","fi","srcJoint","dstJoint","si","indexOf","di","srcLen","bindPose","position","magnitude","dstLen","translationScale","dstNode","srcBindRot","rotation","dstBindRot","dstClip","autoPlay","addSkeleton","persistentId","srcNode","srcTracks","remap","srcTrack","dstTrack","NodeRotationTrack","retargetRotationTrack","NodeEulerRotationTrack","retargetEulerToRotationTrack","NodeTranslationTrack","retargetTranslationTrack","NodeScaleTrack","cloneInterpolator","interpolator","warn","target","jointIndex","addTrack","root","joint","isParentOf","parent","includes","ordered","visited","Set","visit","add","src","abs","scale","srcOutputs","outputs","newOutputs","Float32Array","Interpolator","mode","inputs","isCubic","frameStride","numFrames","f","base","subarray","srcInputs","onDispose","clear"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { Vector3, Disposable, randomUUID, DRef, DWeakRef, Matrix4x4, nextPowerOf2 } from '@zephyr3d/base';
1
+ import { Vector3, Disposable, randomUUID, DRef, Matrix4x4, DWeakRef, nextPowerOf2 } from '@zephyr3d/base';
2
2
  import { BoundingBox } from '../utility/bounding_volume.js';
3
3
  import { getDevice } from '../app/api.js';
4
4
 
@@ -6,32 +6,33 @@ const tmpV0 = new Vector3();
6
6
  const tmpV1 = new Vector3();
7
7
  const tmpV2 = new Vector3();
8
8
  const tmpV3 = new Vector3();
9
- /**
10
- * Skeleton for skinned animation.
11
- *
12
- * Responsibilities:
13
- * - Maintains joint transforms: inverse bind, bind pose, and current skinning matrices.
14
- * - Provides a texture containing joint matrices for GPU skinning.
15
- * - Applies skinning state to associated meshes each frame.
16
- * - Computes animated axis-aligned bounding boxes using representative skinned vertices.
17
- *
18
- * Joint matrix texture layout:
19
- * - Texture format: `rgba32f`.
20
- * - Stored as a 2-layered ring buffer: current and previous joint transforms to support
21
- * temporal addressing if needed. Offsets are tracked in `_jointOffsets[0]` (current)
22
- * and `_jointOffsets[1]` (previous).
23
- *
24
- * Usage:
25
- * - Construct with joints, bind data, meshes and submesh bounding info.
26
- * - Call `apply()` each frame to update joint texture, bind to meshes, and update bounds.
27
- * - Call `reset()` to clear skinning on meshes.
28
- *
29
- * @public
9
+ /**
10
+ * Skeleton for skinned animation.
11
+ *
12
+ * Responsibilities:
13
+ * - Maintains joint transforms: inverse bind, bind pose, and current skinning matrices.
14
+ * - Provides a texture containing joint matrices for GPU skinning.
15
+ * - Applies skinning state to associated meshes each frame.
16
+ * - Computes animated axis-aligned bounding boxes using representative skinned vertices.
17
+ *
18
+ * Joint matrix texture layout:
19
+ * - Texture format: `rgba32f`.
20
+ * - Stored as a 2-layered ring buffer: current and previous joint transforms to support
21
+ * temporal addressing if needed. Offsets are tracked in `_jointOffsets[0]` (current)
22
+ * and `_jointOffsets[1]` (previous).
23
+ *
24
+ * Usage:
25
+ * - Construct with joints, bind data, meshes and submesh bounding info.
26
+ * - Call `apply()` each frame to update joint texture, bind to meshes, and update bounds.
27
+ * - Call `reset()` to clear skinning on meshes.
28
+ *
29
+ * @public
30
30
  */ class Skeleton extends Disposable {
31
31
  /** @internal Global weak registry keyed by persistentId for serialization/lookup. */ static _registry = new Map();
32
32
  /** @internal */ _id;
33
33
  /** @internal */ _joints;
34
34
  /** @internal */ _inverseBindMatrices;
35
+ /** @internal */ _bindPoseModelSpace;
35
36
  /** @internal */ _bindPose;
36
37
  /** @internal */ _jointMatrices;
37
38
  /** @internal */ _jointOffsets;
@@ -40,12 +41,12 @@ const tmpV3 = new Vector3();
40
41
  /** @internal */ _playing;
41
42
  /** @internal */ _modifiers;
42
43
  /** @internal */ _lastUpdateTime;
43
- /**
44
- * Create a skeleton instance.
45
- *
46
- * @param joints - Joint scene nodes (one per joint), ordered to match skin data.
47
- * @param inverseBindMatrices - Inverse bind matrices for each joint.
48
- * @param bindPoseMatrices - Bind pose matrices for each joint (model-space).
44
+ /**
45
+ * Create a skeleton instance.
46
+ *
47
+ * @param joints - Joint scene nodes (one per joint), ordered to match skin data.
48
+ * @param inverseBindMatrices - Inverse bind matrices for each joint.
49
+ * @param bindPoseMatrices - Bind pose matrices for each joint (model-space).
49
50
  */ constructor(joints, inverseBindMatrices, bindPose){
50
51
  super();
51
52
  this._id = randomUUID();
@@ -56,16 +57,29 @@ const tmpV3 = new Vector3();
56
57
  this._playing = false;
57
58
  this._modifiers = [];
58
59
  this._lastUpdateTime = 0;
60
+ this._bindPoseModelSpace = [];
59
61
  this.computeBindPose();
60
62
  this.updateJointMatrices(0);
63
+ let skeletonRoot = this.findRootJoint(this._joints);
64
+ if (!skeletonRoot || !this._joints.includes(skeletonRoot)) {
65
+ throw new Error('Skeleton root must be included in the joint list');
66
+ }
67
+ while(skeletonRoot.parent && this._joints.includes(skeletonRoot.parent)){
68
+ skeletonRoot = skeletonRoot.parent;
69
+ }
70
+ const im = skeletonRoot.parent.invWorldMatrix;
71
+ for (const joint of this._joints){
72
+ const m = Matrix4x4.multiplyAffine(im, joint.worldMatrix);
73
+ this._bindPoseModelSpace.push(m);
74
+ }
61
75
  Skeleton._registry.set(this._id, new DWeakRef(this));
62
76
  }
63
- /**
64
- * Lookup a skeleton from the global registry by persistent id.
65
- *
66
- * @param id - The persistent UUID to search for.
67
- * @returns The skeleton if alive, otherwise `null`.
68
- * @internal
77
+ /**
78
+ * Lookup a skeleton from the global registry by persistent id.
79
+ *
80
+ * @param id - The persistent UUID to search for.
81
+ * @returns The skeleton if alive, otherwise `null`.
82
+ * @internal
69
83
  */ static findSkeletonById(id) {
70
84
  const m = this._registry.get(id);
71
85
  if (m && !m.get()) {
@@ -83,6 +97,9 @@ const tmpV3 = new Vector3();
83
97
  /** @internal */ get bindPose() {
84
98
  return this._bindPose;
85
99
  }
100
+ get bindPoseModelSpace() {
101
+ return this._bindPoseModelSpace;
102
+ }
86
103
  /** @internal */ get playing() {
87
104
  return this._playing;
88
105
  }
@@ -103,42 +120,42 @@ const tmpV3 = new Vector3();
103
120
  Skeleton._registry.set(this._id, m);
104
121
  }
105
122
  }
106
- /**
107
- * Texture containing joint matrices for GPU skinning.
108
- *
109
- * Each matrix is stored in 4 texels (one row per texel, RGBA = 4 floats).
123
+ /**
124
+ * Texture containing joint matrices for GPU skinning.
125
+ *
126
+ * Each matrix is stored in 4 texels (one row per texel, RGBA = 4 floats).
110
127
  */ get jointTexture() {
111
128
  return this._jointTexture.get();
112
129
  }
113
- /**
114
- * Get joint index by joint node
115
- * @param joint - joint node
116
- * @returns The index of the joint
130
+ /**
131
+ * Get joint index by joint node
132
+ * @param joint - joint node
133
+ * @returns The index of the joint
117
134
  */ getJointIndex(joint) {
118
135
  return this._joints.indexOf(joint);
119
136
  }
120
- /**
121
- * Get joint index by joint name
122
- * @param jointName - joint name
123
- * @returns The index of the joint
137
+ /**
138
+ * Get joint index by joint name
139
+ * @param jointName - joint name
140
+ * @returns The index of the joint
124
141
  */ getJointIndexByName(jointName) {
125
142
  return this._joints.findIndex((joint)=>joint.name === jointName);
126
143
  }
127
- /**
128
- * Update joint matrices from either provided transforms or the joints' world matrices.
129
- *
130
- * - Lazily creates the joint texture and its backing arrays on first call.
131
- * - Advances the ring buffer offset in `_jointOffsets` to write a new "current" set.
132
- * - For each joint:
133
- * - Optionally premultiplies by `worldMatrix` (to transform into model space).
134
- * - Computes skinning matrix: ( M_\{skin\} = M_\{joint\} \\times M_\{inverseBind\} ).
135
- *
136
- * Note: This method only writes into the CPU-side array; callers like `computeJoints()`
137
- * update the GPU texture.
138
- *
139
- * @param jointTransforms - Optional per-joint transforms to use instead of node world matrices.
140
- * @param worldMatrix - Optional world-to-model transform applied before inverse bind.
141
- * @internal
144
+ /**
145
+ * Update joint matrices from either provided transforms or the joints' world matrices.
146
+ *
147
+ * - Lazily creates the joint texture and its backing arrays on first call.
148
+ * - Advances the ring buffer offset in `_jointOffsets` to write a new "current" set.
149
+ * - For each joint:
150
+ * - Optionally premultiplies by `worldMatrix` (to transform into model space).
151
+ * - Computes skinning matrix: ( M_\{skin\} = M_\{joint\} \\times M_\{inverseBind\} ).
152
+ *
153
+ * Note: This method only writes into the CPU-side array; callers like `computeJoints()`
154
+ * update the GPU texture.
155
+ *
156
+ * @param jointTransforms - Optional per-joint transforms to use instead of node world matrices.
157
+ * @param worldMatrix - Optional world-to-model transform applied before inverse bind.
158
+ * @internal
142
159
  */ updateJointMatrices(deltaTime) {
143
160
  this.applyModifiers(deltaTime);
144
161
  if (!this._jointTexture.get()) {
@@ -155,10 +172,10 @@ const tmpV3 = new Vector3();
155
172
  Matrix4x4.multiply(this._joints[i].worldMatrix, this._inverseBindMatrices[i], this._jointMatrices[i + this._jointOffsets[0] - 1]);
156
173
  }
157
174
  }
158
- /**
159
- * Reset skeleton to bind pose
160
- *
161
- * @internal
175
+ /**
176
+ * Reset skeleton to bind pose
177
+ *
178
+ * @internal
162
179
  */ computeBindPose() {
163
180
  for(let i = 0; i < this._joints.length; i++){
164
181
  const joint = this._joints[i];
@@ -168,54 +185,54 @@ const tmpV3 = new Vector3();
168
185
  joint.scale.set(bindpose.scale);
169
186
  }
170
187
  }
171
- /**
172
- * Compute current joint matrices from the nodes and upload them to the joint texture.
173
- *
174
- * @internal
188
+ /**
189
+ * Compute current joint matrices from the nodes and upload them to the joint texture.
190
+ *
191
+ * @internal
175
192
  */ apply(deltaTime) {
176
193
  this.updateJointMatrices(deltaTime);
177
194
  const tex = this.jointTexture;
178
195
  tex.update(this._jointMatrixArray, 0, 0, tex.width, tex.height);
179
196
  }
180
- /**
181
- * Apply all enabled modifiers.
182
- *
183
- * Modifiers are applied after the base animation/bind pose layer,
184
- * allowing procedural modifications like IK, spring physics, or manual overrides.
185
- *
186
- * @param deltaTime - Time elapsed since last frame (in seconds)
187
- * @internal
197
+ /**
198
+ * Apply all enabled modifiers.
199
+ *
200
+ * Modifiers are applied after the base animation/bind pose layer,
201
+ * allowing procedural modifications like IK, spring physics, or manual overrides.
202
+ *
203
+ * @param deltaTime - Time elapsed since last frame (in seconds)
204
+ * @internal
188
205
  */ applyModifiers(deltaTime) {
189
206
  for (const modifier of this._modifiers){
190
207
  modifier.apply(this, deltaTime);
191
208
  }
192
209
  }
193
- /**
194
- * Get all modifiers attached to this skeleton.
195
- *
196
- * @public
210
+ /**
211
+ * Get all modifiers attached to this skeleton.
212
+ *
213
+ * @public
197
214
  */ get modifiers() {
198
215
  return this._modifiers;
199
216
  }
200
- /**
201
- * Reset all meshes to an unskinned state and clear animated bounds.
202
- *
203
- * @internal
217
+ /**
218
+ * Reset all meshes to an unskinned state and clear animated bounds.
219
+ *
220
+ * @internal
204
221
  */ reset() {
205
222
  //this.updateJointMatrices(this._bindPoseMatrices);
206
223
  this._playing = false;
207
224
  }
208
- /**
209
- * Compute the animated bounding box for a single mesh using its representative vertices.
210
- *
211
- * For each representative vertex:
212
- * - Blends the vertex by up to 4 joint matrices using provided weights.
213
- * - Transforms to the mesh's local space using `invWorldMatrix`.
214
- * - Expands the bounding box.
215
- *
216
- * @param info - Precomputed bounding data (representative vertices, indices, weights).
217
- * @param invWorldMatrix - Mesh inverse world matrix to convert to model/local space.
218
- * @internal
225
+ /**
226
+ * Compute the animated bounding box for a single mesh using its representative vertices.
227
+ *
228
+ * For each representative vertex:
229
+ * - Blends the vertex by up to 4 joint matrices using provided weights.
230
+ * - Transforms to the mesh's local space using `invWorldMatrix`.
231
+ * - Expands the bounding box.
232
+ *
233
+ * @param info - Precomputed bounding data (representative vertices, indices, weights).
234
+ * @param invWorldMatrix - Mesh inverse world matrix to convert to model/local space.
235
+ * @internal
219
236
  */ computeBoundingBox(info, invWorldMatrix) {
220
237
  info.boundingBox.beginExtend();
221
238
  for(let i = 0; i < info.boundingVertices.length; i++){
@@ -228,11 +245,11 @@ const tmpV3 = new Vector3();
228
245
  info.boundingBox.extend(tmpV0);
229
246
  }
230
247
  }
231
- /**
232
- * Dispose GPU resources and references held by the skeleton.
233
- *
234
- * - Disposes the joint texture.
235
- * - Clears matrix arrays and joint references.
248
+ /**
249
+ * Dispose GPU resources and references held by the skeleton.
250
+ *
251
+ * - Disposes the joint texture.
252
+ * - Clears matrix arrays and joint references.
236
253
  */ onDispose() {
237
254
  super.onDispose();
238
255
  this._jointTexture.dispose();
@@ -242,17 +259,17 @@ const tmpV3 = new Vector3();
242
259
  m.dispose();
243
260
  }
244
261
  }
245
- /**
246
- * Initialize joint texture and CPU-side matrix storage.
247
- *
248
- * Layout details:
249
- * - Texture size is the next power-of-two able to contain all matrices plus two offset texels.
250
- * - `_jointMatrixArray` holds:
251
- * - First 2 vec4s: ring buffer offsets `[current, previous, 0, 0]`.
252
- * - Followed by 2×N matrices (current and previous), each as 16 floats.
253
- * - `_jointMatrices` is a view into `_jointMatrixArray` providing Matrix4x4 objects per slot.
254
- *
255
- * @internal
262
+ /**
263
+ * Initialize joint texture and CPU-side matrix storage.
264
+ *
265
+ * Layout details:
266
+ * - Texture size is the next power-of-two able to contain all matrices plus two offset texels.
267
+ * - `_jointMatrixArray` holds:
268
+ * - First 2 vec4s: ring buffer offsets `[current, previous, 0, 0]`.
269
+ * - Followed by 2×N matrices (current and previous), each as 16 floats.
270
+ * - `_jointMatrices` is a view into `_jointMatrixArray` providing Matrix4x4 objects per slot.
271
+ *
272
+ * @internal
256
273
  */ _createJointTexture() {
257
274
  const textureWidth = nextPowerOf2(Math.max(4, Math.ceil(Math.sqrt((this._joints.length * 2 + 1) * 4))));
258
275
  const device = getDevice();
@@ -272,19 +289,19 @@ const tmpV3 = new Vector3();
272
289
  length: this._joints.length * 2
273
290
  }).map((val, index)=>new Matrix4x4(buffer, (index + 1) * 16 * Float32Array.BYTES_PER_ELEMENT));
274
291
  }
275
- /**
276
- * Build representative skinned bounding data for a submesh.
277
- *
278
- * Strategy:
279
- * - For all vertices, compute their skinned position (using current ring buffer slot).
280
- * - Track the indices of the min/max extents along x, y, z (6 indices total).
281
- * - Store:
282
- * - The 6 representative positions in object space.
283
- * - Their 4 joint indices and weights (flattened).
284
- * - An empty BoundingBox to be filled during animation.
285
- *
286
- * @param meshData - Raw submesh attributes (positions, blend indices, weights).
287
- * @returns Skinned bounding box info used during per-frame updates.
292
+ /**
293
+ * Build representative skinned bounding data for a submesh.
294
+ *
295
+ * Strategy:
296
+ * - For all vertices, compute their skinned position (using current ring buffer slot).
297
+ * - Track the indices of the min/max extents along x, y, z (6 indices total).
298
+ * - Store:
299
+ * - The 6 representative positions in object space.
300
+ * - Their 4 joint indices and weights (flattened).
301
+ * - An empty BoundingBox to be filled during animation.
302
+ *
303
+ * @param meshData - Raw submesh attributes (positions, blend indices, weights).
304
+ * @returns Skinned bounding box info used during per-frame updates.
288
305
  */ getBoundingInfo(data) {
289
306
  const indices = [
290
307
  0,
@@ -353,6 +370,21 @@ const tmpV3 = new Vector3();
353
370
  };
354
371
  return info;
355
372
  }
373
+ findRootJoint(joints) {
374
+ let root = null;
375
+ for (const joint of joints){
376
+ if (!root) {
377
+ root = joint;
378
+ }
379
+ while(!root.isParentOf(joint)){
380
+ root = root.parent;
381
+ }
382
+ if (!root) {
383
+ break;
384
+ }
385
+ }
386
+ return root;
387
+ }
356
388
  }
357
389
 
358
390
  export { Skeleton };
@@ -1 +1 @@
1
- {"version":3,"file":"skeleton.js","sources":["../../src/animation/skeleton.ts"],"sourcesContent":["import { DRef, randomUUID, DWeakRef } from '@zephyr3d/base';\r\nimport type { Quaternion, TypedArray } from '@zephyr3d/base';\r\nimport { Disposable, Matrix4x4, Vector3, nextPowerOf2 } from '@zephyr3d/base';\r\nimport type { Texture2D } from '@zephyr3d/device';\r\nimport type { SceneNode } from '../scene/scene_node';\r\nimport { BoundingBox } from '../utility/bounding_volume';\r\nimport { getDevice } from '../app/api';\r\nimport type { SkeletonModifier } from './skeleton_modifier';\r\n\r\n/**\r\n * Skinned bounding box information for a submesh.\r\n *\r\n * Used to compute animated AABB for skinned meshes.\r\n *\r\n * @public\r\n */\r\nexport interface SkinnedBoundingBox {\r\n /**\r\n * Representative vertices used to bound a skinned mesh (extreme points along axes).\r\n */\r\n boundingVertices: Vector3[];\r\n /**\r\n * Joint indices (up to 4 per vertex) for each representative vertex, flattened.\r\n * Layout: [i0_0, i0_1, i0_2, i0_3, i1_0, ...] for 6 vertices.\r\n */\r\n boundingVertexBlendIndices: Float32Array;\r\n /**\r\n * Corresponding joint weights (up to 4 per vertex) for each representative vertex, flattened.\r\n * Layout matches `boundingVertexBlendIndices`.\r\n */\r\n boundingVertexJointWeights: Float32Array;\r\n /**\r\n * Computed axis-aligned bounding box in model space for the current pose.\r\n */\r\n boundingBox: BoundingBox;\r\n}\r\n\r\nconst tmpV0 = new Vector3();\r\nconst tmpV1 = new Vector3();\r\nconst tmpV2 = new Vector3();\r\nconst tmpV3 = new Vector3();\r\n\r\n/**\r\n * Skeleton for skinned animation.\r\n *\r\n * Responsibilities:\r\n * - Maintains joint transforms: inverse bind, bind pose, and current skinning matrices.\r\n * - Provides a texture containing joint matrices for GPU skinning.\r\n * - Applies skinning state to associated meshes each frame.\r\n * - Computes animated axis-aligned bounding boxes using representative skinned vertices.\r\n *\r\n * Joint matrix texture layout:\r\n * - Texture format: `rgba32f`.\r\n * - Stored as a 2-layered ring buffer: current and previous joint transforms to support\r\n * temporal addressing if needed. Offsets are tracked in `_jointOffsets[0]` (current)\r\n * and `_jointOffsets[1]` (previous).\r\n *\r\n * Usage:\r\n * - Construct with joints, bind data, meshes and submesh bounding info.\r\n * - Call `apply()` each frame to update joint texture, bind to meshes, and update bounds.\r\n * - Call `reset()` to clear skinning on meshes.\r\n *\r\n * @public\r\n */\r\nexport class Skeleton extends Disposable {\r\n /** @internal Global weak registry keyed by persistentId for serialization/lookup. */\r\n private static readonly _registry: Map<string, DWeakRef<Skeleton>> = new Map();\r\n /** @internal */\r\n protected _id: string;\r\n /** @internal */\r\n protected _joints: SceneNode[];\r\n /** @internal */\r\n protected _inverseBindMatrices: Matrix4x4[];\r\n /** @internal */\r\n protected _bindPose: { rotation: Quaternion; scale: Vector3; position: Vector3 }[];\r\n /** @internal */\r\n protected _jointMatrices!: Matrix4x4[];\r\n /** @internal */\r\n protected _jointOffsets!: Float32Array<ArrayBuffer>;\r\n /** @internal */\r\n protected _jointMatrixArray!: Float32Array<ArrayBuffer>;\r\n /** @internal */\r\n protected _jointTexture: DRef<Texture2D>;\r\n /** @internal */\r\n protected _playing: boolean;\r\n /** @internal */\r\n protected _modifiers: SkeletonModifier[];\r\n /** @internal */\r\n protected _lastUpdateTime: number;\r\n /**\r\n * Create a skeleton instance.\r\n *\r\n * @param joints - Joint scene nodes (one per joint), ordered to match skin data.\r\n * @param inverseBindMatrices - Inverse bind matrices for each joint.\r\n * @param bindPoseMatrices - Bind pose matrices for each joint (model-space).\r\n */\r\n constructor(\r\n joints: SceneNode[],\r\n inverseBindMatrices: Matrix4x4[],\r\n bindPose: { rotation: Quaternion; scale: Vector3; position: Vector3 }[]\r\n ) {\r\n super();\r\n this._id = randomUUID();\r\n this._joints = joints;\r\n this._inverseBindMatrices = inverseBindMatrices;\r\n this._bindPose = bindPose;\r\n this._jointTexture = new DRef();\r\n this._playing = false;\r\n this._modifiers = [];\r\n this._lastUpdateTime = 0;\r\n this.computeBindPose();\r\n this.updateJointMatrices(0);\r\n Skeleton._registry.set(this._id, new DWeakRef(this));\r\n }\r\n /**\r\n * Lookup a skeleton from the global registry by persistent id.\r\n *\r\n * @param id - The persistent UUID to search for.\r\n * @returns The skeleton if alive, otherwise `null`.\r\n * @internal\r\n */\r\n static findSkeletonById(id: string) {\r\n const m = this._registry.get(id);\r\n if (m && !m.get()) {\r\n this._registry.delete(id);\r\n return null;\r\n }\r\n return m ? m.get() : null;\r\n }\r\n /** @internal */\r\n get joints() {\r\n return this._joints;\r\n }\r\n /** @internal */\r\n get inverseBindMatrices() {\r\n return this._inverseBindMatrices;\r\n }\r\n /** @internal */\r\n get bindPose() {\r\n return this._bindPose;\r\n }\r\n /** @internal */\r\n get playing() {\r\n return this._playing;\r\n }\r\n set playing(b: boolean) {\r\n this._playing = b;\r\n }\r\n /** @internal */\r\n get persistentId() {\r\n return this._id;\r\n }\r\n set persistentId(val) {\r\n if (val !== this._id) {\r\n const m = Skeleton._registry.get(this._id);\r\n if (!m || m.get() !== this) {\r\n throw new Error('Registry skeleton mismatch');\r\n }\r\n Skeleton._registry.delete(this._id);\r\n this._id = val;\r\n Skeleton._registry.set(this._id, m);\r\n }\r\n }\r\n /**\r\n * Texture containing joint matrices for GPU skinning.\r\n *\r\n * Each matrix is stored in 4 texels (one row per texel, RGBA = 4 floats).\r\n */\r\n get jointTexture() {\r\n return this._jointTexture.get()!;\r\n }\r\n /**\r\n * Get joint index by joint node\r\n * @param joint - joint node\r\n * @returns The index of the joint\r\n */\r\n getJointIndex(joint: SceneNode) {\r\n return this._joints.indexOf(joint);\r\n }\r\n /**\r\n * Get joint index by joint name\r\n * @param jointName - joint name\r\n * @returns The index of the joint\r\n */\r\n getJointIndexByName(jointName: string) {\r\n return this._joints.findIndex((joint) => joint.name === jointName);\r\n }\r\n /**\r\n * Update joint matrices from either provided transforms or the joints' world matrices.\r\n *\r\n * - Lazily creates the joint texture and its backing arrays on first call.\r\n * - Advances the ring buffer offset in `_jointOffsets` to write a new \"current\" set.\r\n * - For each joint:\r\n * - Optionally premultiplies by `worldMatrix` (to transform into model space).\r\n * - Computes skinning matrix: ( M_\\{skin\\} = M_\\{joint\\} \\\\times M_\\{inverseBind\\} ).\r\n *\r\n * Note: This method only writes into the CPU-side array; callers like `computeJoints()`\r\n * update the GPU texture.\r\n *\r\n * @param jointTransforms - Optional per-joint transforms to use instead of node world matrices.\r\n * @param worldMatrix - Optional world-to-model transform applied before inverse bind.\r\n * @internal\r\n */\r\n updateJointMatrices(deltaTime: number) {\r\n this.applyModifiers(deltaTime);\r\n if (!this._jointTexture.get()) {\r\n this._createJointTexture();\r\n }\r\n if (this._jointOffsets[0] === 0) {\r\n this._jointOffsets[0] = 1;\r\n this._jointOffsets[1] = 1;\r\n } else {\r\n this._jointOffsets[1] = this._jointOffsets[0];\r\n this._jointOffsets[0] = this._joints.length - this._jointOffsets[0] + 2;\r\n }\r\n for (let i = 0; i < this._joints.length; i++) {\r\n Matrix4x4.multiply(\r\n this._joints[i].worldMatrix,\r\n this._inverseBindMatrices[i],\r\n this._jointMatrices[i + this._jointOffsets[0] - 1]\r\n );\r\n }\r\n }\r\n /**\r\n * Reset skeleton to bind pose\r\n *\r\n * @internal\r\n */\r\n computeBindPose() {\r\n for (let i = 0; i < this._joints.length; i++) {\r\n const joint = this._joints[i];\r\n const bindpose = this._bindPose[i];\r\n joint.position.set(bindpose.position);\r\n joint.rotation.set(bindpose.rotation);\r\n joint.scale.set(bindpose.scale);\r\n }\r\n }\r\n /**\r\n * Compute current joint matrices from the nodes and upload them to the joint texture.\r\n *\r\n * @internal\r\n */\r\n apply(deltaTime: number) {\r\n this.updateJointMatrices(deltaTime);\r\n const tex = this.jointTexture;\r\n tex.update(this._jointMatrixArray, 0, 0, tex.width, tex.height);\r\n }\r\n /**\r\n * Apply all enabled modifiers.\r\n *\r\n * Modifiers are applied after the base animation/bind pose layer,\r\n * allowing procedural modifications like IK, spring physics, or manual overrides.\r\n *\r\n * @param deltaTime - Time elapsed since last frame (in seconds)\r\n * @internal\r\n */\r\n protected applyModifiers(deltaTime: number): void {\r\n for (const modifier of this._modifiers) {\r\n modifier.apply(this, deltaTime);\r\n }\r\n }\r\n /**\r\n * Get all modifiers attached to this skeleton.\r\n *\r\n * @public\r\n */\r\n get modifiers(): SkeletonModifier[] {\r\n return this._modifiers;\r\n }\r\n /**\r\n * Reset all meshes to an unskinned state and clear animated bounds.\r\n *\r\n * @internal\r\n */\r\n reset() {\r\n //this.updateJointMatrices(this._bindPoseMatrices);\r\n this._playing = false;\r\n }\r\n /**\r\n * Compute the animated bounding box for a single mesh using its representative vertices.\r\n *\r\n * For each representative vertex:\r\n * - Blends the vertex by up to 4 joint matrices using provided weights.\r\n * - Transforms to the mesh's local space using `invWorldMatrix`.\r\n * - Expands the bounding box.\r\n *\r\n * @param info - Precomputed bounding data (representative vertices, indices, weights).\r\n * @param invWorldMatrix - Mesh inverse world matrix to convert to model/local space.\r\n * @internal\r\n */\r\n computeBoundingBox(info: SkinnedBoundingBox, invWorldMatrix: Matrix4x4) {\r\n info.boundingBox.beginExtend();\r\n for (let i = 0; i < info.boundingVertices.length; i++) {\r\n this._jointMatrices[info.boundingVertexBlendIndices[i * 4 + 0] + this._jointOffsets[0] - 1]\r\n .transformPointAffine(info.boundingVertices[i], tmpV0)\r\n .scaleBy(info.boundingVertexJointWeights[i * 4 + 0]);\r\n this._jointMatrices[info.boundingVertexBlendIndices[i * 4 + 1] + this._jointOffsets[0] - 1]\r\n .transformPointAffine(info.boundingVertices[i], tmpV1)\r\n .scaleBy(info.boundingVertexJointWeights[i * 4 + 1]);\r\n this._jointMatrices[info.boundingVertexBlendIndices[i * 4 + 2] + this._jointOffsets[0] - 1]\r\n .transformPointAffine(info.boundingVertices[i], tmpV2)\r\n .scaleBy(info.boundingVertexJointWeights[i * 4 + 2]);\r\n this._jointMatrices[info.boundingVertexBlendIndices[i * 4 + 3] + this._jointOffsets[0] - 1]\r\n .transformPointAffine(info.boundingVertices[i], tmpV3)\r\n .scaleBy(info.boundingVertexJointWeights[i * 4 + 3]);\r\n tmpV0.addBy(tmpV1).addBy(tmpV2).addBy(tmpV3);\r\n invWorldMatrix.transformPointAffine(tmpV0, tmpV0);\r\n info.boundingBox.extend(tmpV0);\r\n }\r\n }\r\n /**\r\n * Dispose GPU resources and references held by the skeleton.\r\n *\r\n * - Disposes the joint texture.\r\n * - Clears matrix arrays and joint references.\r\n */\r\n protected onDispose() {\r\n super.onDispose();\r\n this._jointTexture.dispose();\r\n const m = Skeleton._registry.get(this._id);\r\n if (m?.get() === this) {\r\n Skeleton._registry.delete(this._id);\r\n m.dispose();\r\n }\r\n }\r\n /**\r\n * Initialize joint texture and CPU-side matrix storage.\r\n *\r\n * Layout details:\r\n * - Texture size is the next power-of-two able to contain all matrices plus two offset texels.\r\n * - `_jointMatrixArray` holds:\r\n * - First 2 vec4s: ring buffer offsets `[current, previous, 0, 0]`.\r\n * - Followed by 2×N matrices (current and previous), each as 16 floats.\r\n * - `_jointMatrices` is a view into `_jointMatrixArray` providing Matrix4x4 objects per slot.\r\n *\r\n * @internal\r\n */\r\n private _createJointTexture() {\r\n const textureWidth = nextPowerOf2(Math.max(4, Math.ceil(Math.sqrt((this._joints.length * 2 + 1) * 4))));\r\n const device = getDevice();\r\n this._jointTexture.set(\r\n device.createTexture2D('rgba32f', textureWidth, textureWidth, {\r\n mipmapping: false,\r\n samplerOptions: {\r\n magFilter: 'nearest',\r\n minFilter: 'nearest'\r\n }\r\n })\r\n );\r\n this._jointMatrixArray = new Float32Array(textureWidth * textureWidth * 4);\r\n const buffer = this._jointMatrixArray.buffer;\r\n this._jointOffsets = new Float32Array(buffer);\r\n this._jointOffsets[0] = 0;\r\n this._jointOffsets[1] = 0;\r\n this._jointMatrices = Array.from({ length: this._joints.length * 2 }).map(\r\n (val, index) => new Matrix4x4(buffer, (index + 1) * 16 * Float32Array.BYTES_PER_ELEMENT)\r\n );\r\n }\r\n /**\r\n * Build representative skinned bounding data for a submesh.\r\n *\r\n * Strategy:\r\n * - For all vertices, compute their skinned position (using current ring buffer slot).\r\n * - Track the indices of the min/max extents along x, y, z (6 indices total).\r\n * - Store:\r\n * - The 6 representative positions in object space.\r\n * - Their 4 joint indices and weights (flattened).\r\n * - An empty BoundingBox to be filled during animation.\r\n *\r\n * @param meshData - Raw submesh attributes (positions, blend indices, weights).\r\n * @returns Skinned bounding box info used during per-frame updates.\r\n */\r\n getBoundingInfo(data: { positions: Float32Array; blendIndices: TypedArray; weights: TypedArray }) {\r\n const indices = [0, 0, 0, 0, 0, 0];\r\n let minx = Number.MAX_VALUE;\r\n let maxx = -Number.MAX_VALUE;\r\n let miny = Number.MAX_VALUE;\r\n let maxy = -Number.MAX_VALUE;\r\n let minz = Number.MAX_VALUE;\r\n let maxz = -Number.MAX_VALUE;\r\n const v = data.positions;\r\n const vert = new Vector3();\r\n const tmpV0 = new Vector3();\r\n const tmpV1 = new Vector3();\r\n const tmpV2 = new Vector3();\r\n const tmpV3 = new Vector3();\r\n const numVertices = Math.floor(v.length / 3);\r\n for (let i = 0; i < numVertices; i++) {\r\n vert.setXYZ(v[i * 3], v[i * 3 + 1], v[i * 3 + 2]);\r\n this._jointMatrices[data.blendIndices[i * 4 + 0] + this._jointOffsets[0] - 1]\r\n .transformPointAffine(vert, tmpV0)\r\n .scaleBy(data.weights[i * 4 + 0]);\r\n this._jointMatrices[data.blendIndices[i * 4 + 1] + this._jointOffsets[0] - 1]\r\n .transformPointAffine(vert, tmpV1)\r\n .scaleBy(data.weights[i * 4 + 1]);\r\n this._jointMatrices[data.blendIndices[i * 4 + 2] + this._jointOffsets[0] - 1]\r\n .transformPointAffine(vert, tmpV2)\r\n .scaleBy(data.weights[i * 4 + 2]);\r\n this._jointMatrices[data.blendIndices[i * 4 + 3] + this._jointOffsets[0] - 1]\r\n .transformPointAffine(vert, tmpV3)\r\n .scaleBy(data.weights[i * 4 + 3]);\r\n tmpV0.addBy(tmpV1).addBy(tmpV2).addBy(tmpV3);\r\n if (tmpV0.x < minx) {\r\n minx = tmpV0.x;\r\n indices[0] = i;\r\n }\r\n if (tmpV0.x > maxx) {\r\n maxx = tmpV0.x;\r\n indices[1] = i;\r\n }\r\n if (tmpV0.y < miny) {\r\n miny = tmpV0.y;\r\n indices[2] = i;\r\n }\r\n if (tmpV0.y > maxy) {\r\n maxy = tmpV0.y;\r\n indices[3] = i;\r\n }\r\n if (tmpV0.z < minz) {\r\n minz = tmpV0.z;\r\n indices[4] = i;\r\n }\r\n if (tmpV0.z > maxz) {\r\n maxz = tmpV0.z;\r\n indices[5] = i;\r\n }\r\n }\r\n const info: SkinnedBoundingBox = {\r\n boundingVertexBlendIndices: new Float32Array(\r\n Array.from({ length: 6 * 4 }).map(\r\n (val, index) => data.blendIndices[indices[index >> 2] * 4 + (index % 4)]\r\n )\r\n ),\r\n boundingVertexJointWeights: new Float32Array(\r\n Array.from({ length: 6 * 4 }).map((val, index) => data.weights[indices[index >> 2] * 4 + (index % 4)])\r\n ),\r\n boundingVertices: Array.from({ length: 6 }).map(\r\n (val, index) =>\r\n new Vector3(\r\n data.positions[indices[index] * 3],\r\n data.positions[indices[index] * 3 + 1],\r\n data.positions[indices[index] * 3 + 2]\r\n )\r\n ),\r\n boundingBox: new BoundingBox()\r\n };\r\n return info;\r\n }\r\n}\r\n"],"names":["tmpV0","Vector3","tmpV1","tmpV2","tmpV3","Skeleton","Disposable","_registry","Map","joints","inverseBindMatrices","bindPose","_id","randomUUID","_joints","_inverseBindMatrices","_bindPose","_jointTexture","DRef","_playing","_modifiers","_lastUpdateTime","computeBindPose","updateJointMatrices","set","DWeakRef","findSkeletonById","id","m","get","delete","playing","b","persistentId","val","Error","jointTexture","getJointIndex","joint","indexOf","getJointIndexByName","jointName","findIndex","name","deltaTime","applyModifiers","_createJointTexture","_jointOffsets","length","i","Matrix4x4","multiply","worldMatrix","_jointMatrices","bindpose","position","rotation","scale","apply","tex","update","_jointMatrixArray","width","height","modifier","modifiers","reset","computeBoundingBox","info","invWorldMatrix","boundingBox","beginExtend","boundingVertices","boundingVertexBlendIndices","transformPointAffine","scaleBy","boundingVertexJointWeights","addBy","extend","onDispose","dispose","textureWidth","nextPowerOf2","Math","max","ceil","sqrt","device","getDevice","createTexture2D","mipmapping","samplerOptions","magFilter","minFilter","Float32Array","buffer","Array","from","map","index","BYTES_PER_ELEMENT","getBoundingInfo","data","indices","minx","Number","MAX_VALUE","maxx","miny","maxy","minz","maxz","v","positions","vert","numVertices","floor","setXYZ","blendIndices","weights","x","y","z","BoundingBox"],"mappings":"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"}
1
+ {"version":3,"file":"skeleton.js","sources":["../../src/animation/skeleton.ts"],"sourcesContent":["import { DRef, randomUUID, DWeakRef } from '@zephyr3d/base';\nimport type { Nullable, Quaternion, TypedArray } from '@zephyr3d/base';\nimport { Disposable, Matrix4x4, Vector3, nextPowerOf2 } from '@zephyr3d/base';\nimport type { Texture2D } from '@zephyr3d/device';\nimport type { SceneNode } from '../scene/scene_node';\nimport { BoundingBox } from '../utility/bounding_volume';\nimport { getDevice } from '../app/api';\nimport type { SkeletonModifier } from './skeleton_modifier';\n\n/**\n * Skinned bounding box information for a submesh.\n *\n * Used to compute animated AABB for skinned meshes.\n *\n * @public\n */\nexport interface SkinnedBoundingBox {\n /**\n * Representative vertices used to bound a skinned mesh (extreme points along axes).\n */\n boundingVertices: Vector3[];\n /**\n * Joint indices (up to 4 per vertex) for each representative vertex, flattened.\n * Layout: [i0_0, i0_1, i0_2, i0_3, i1_0, ...] for 6 vertices.\n */\n boundingVertexBlendIndices: Float32Array;\n /**\n * Corresponding joint weights (up to 4 per vertex) for each representative vertex, flattened.\n * Layout matches `boundingVertexBlendIndices`.\n */\n boundingVertexJointWeights: Float32Array;\n /**\n * Computed axis-aligned bounding box in model space for the current pose.\n */\n boundingBox: BoundingBox;\n}\n\nconst tmpV0 = new Vector3();\nconst tmpV1 = new Vector3();\nconst tmpV2 = new Vector3();\nconst tmpV3 = new Vector3();\n\n/**\n * Skeleton for skinned animation.\n *\n * Responsibilities:\n * - Maintains joint transforms: inverse bind, bind pose, and current skinning matrices.\n * - Provides a texture containing joint matrices for GPU skinning.\n * - Applies skinning state to associated meshes each frame.\n * - Computes animated axis-aligned bounding boxes using representative skinned vertices.\n *\n * Joint matrix texture layout:\n * - Texture format: `rgba32f`.\n * - Stored as a 2-layered ring buffer: current and previous joint transforms to support\n * temporal addressing if needed. Offsets are tracked in `_jointOffsets[0]` (current)\n * and `_jointOffsets[1]` (previous).\n *\n * Usage:\n * - Construct with joints, bind data, meshes and submesh bounding info.\n * - Call `apply()` each frame to update joint texture, bind to meshes, and update bounds.\n * - Call `reset()` to clear skinning on meshes.\n *\n * @public\n */\nexport class Skeleton extends Disposable {\n /** @internal Global weak registry keyed by persistentId for serialization/lookup. */\n private static readonly _registry: Map<string, DWeakRef<Skeleton>> = new Map();\n /** @internal */\n protected _id: string;\n /** @internal */\n protected _joints: SceneNode[];\n /** @internal */\n protected _inverseBindMatrices: Matrix4x4[];\n /** @internal */\n protected _bindPoseModelSpace: Matrix4x4[];\n /** @internal */\n protected _bindPose: { rotation: Quaternion; scale: Vector3; position: Vector3 }[];\n /** @internal */\n protected _jointMatrices!: Matrix4x4[];\n /** @internal */\n protected _jointOffsets!: Float32Array<ArrayBuffer>;\n /** @internal */\n protected _jointMatrixArray!: Float32Array<ArrayBuffer>;\n /** @internal */\n protected _jointTexture: DRef<Texture2D>;\n /** @internal */\n protected _playing: boolean;\n /** @internal */\n protected _modifiers: SkeletonModifier[];\n /** @internal */\n protected _lastUpdateTime: number;\n /**\n * Create a skeleton instance.\n *\n * @param joints - Joint scene nodes (one per joint), ordered to match skin data.\n * @param inverseBindMatrices - Inverse bind matrices for each joint.\n * @param bindPoseMatrices - Bind pose matrices for each joint (model-space).\n */\n constructor(\n joints: SceneNode[],\n inverseBindMatrices: Matrix4x4[],\n bindPose: { rotation: Quaternion; scale: Vector3; position: Vector3 }[]\n ) {\n super();\n this._id = randomUUID();\n this._joints = joints;\n this._inverseBindMatrices = inverseBindMatrices;\n this._bindPose = bindPose;\n this._jointTexture = new DRef();\n this._playing = false;\n this._modifiers = [];\n this._lastUpdateTime = 0;\n this._bindPoseModelSpace = [];\n this.computeBindPose();\n this.updateJointMatrices(0);\n let skeletonRoot = this.findRootJoint(this._joints);\n if (!skeletonRoot || !this._joints.includes(skeletonRoot)) {\n throw new Error('Skeleton root must be included in the joint list');\n }\n while (skeletonRoot.parent && this._joints.includes(skeletonRoot.parent)) {\n skeletonRoot = skeletonRoot.parent;\n }\n const im = skeletonRoot.parent!.invWorldMatrix;\n for (const joint of this._joints) {\n const m = Matrix4x4.multiplyAffine(im, joint.worldMatrix);\n this._bindPoseModelSpace.push(m);\n }\n Skeleton._registry.set(this._id, new DWeakRef(this));\n }\n /**\n * Lookup a skeleton from the global registry by persistent id.\n *\n * @param id - The persistent UUID to search for.\n * @returns The skeleton if alive, otherwise `null`.\n * @internal\n */\n static findSkeletonById(id: string) {\n const m = this._registry.get(id);\n if (m && !m.get()) {\n this._registry.delete(id);\n return null;\n }\n return m ? m.get() : null;\n }\n /** @internal */\n get joints() {\n return this._joints;\n }\n /** @internal */\n get inverseBindMatrices() {\n return this._inverseBindMatrices;\n }\n /** @internal */\n get bindPose() {\n return this._bindPose;\n }\n get bindPoseModelSpace() {\n return this._bindPoseModelSpace;\n }\n /** @internal */\n get playing() {\n return this._playing;\n }\n set playing(b: boolean) {\n this._playing = b;\n }\n /** @internal */\n get persistentId() {\n return this._id;\n }\n set persistentId(val) {\n if (val !== this._id) {\n const m = Skeleton._registry.get(this._id);\n if (!m || m.get() !== this) {\n throw new Error('Registry skeleton mismatch');\n }\n Skeleton._registry.delete(this._id);\n this._id = val;\n Skeleton._registry.set(this._id, m);\n }\n }\n /**\n * Texture containing joint matrices for GPU skinning.\n *\n * Each matrix is stored in 4 texels (one row per texel, RGBA = 4 floats).\n */\n get jointTexture() {\n return this._jointTexture.get()!;\n }\n /**\n * Get joint index by joint node\n * @param joint - joint node\n * @returns The index of the joint\n */\n getJointIndex(joint: SceneNode) {\n return this._joints.indexOf(joint);\n }\n /**\n * Get joint index by joint name\n * @param jointName - joint name\n * @returns The index of the joint\n */\n getJointIndexByName(jointName: string) {\n return this._joints.findIndex((joint) => joint.name === jointName);\n }\n /**\n * Update joint matrices from either provided transforms or the joints' world matrices.\n *\n * - Lazily creates the joint texture and its backing arrays on first call.\n * - Advances the ring buffer offset in `_jointOffsets` to write a new \"current\" set.\n * - For each joint:\n * - Optionally premultiplies by `worldMatrix` (to transform into model space).\n * - Computes skinning matrix: ( M_\\{skin\\} = M_\\{joint\\} \\\\times M_\\{inverseBind\\} ).\n *\n * Note: This method only writes into the CPU-side array; callers like `computeJoints()`\n * update the GPU texture.\n *\n * @param jointTransforms - Optional per-joint transforms to use instead of node world matrices.\n * @param worldMatrix - Optional world-to-model transform applied before inverse bind.\n * @internal\n */\n updateJointMatrices(deltaTime: number) {\n this.applyModifiers(deltaTime);\n if (!this._jointTexture.get()) {\n this._createJointTexture();\n }\n if (this._jointOffsets[0] === 0) {\n this._jointOffsets[0] = 1;\n this._jointOffsets[1] = 1;\n } else {\n this._jointOffsets[1] = this._jointOffsets[0];\n this._jointOffsets[0] = this._joints.length - this._jointOffsets[0] + 2;\n }\n for (let i = 0; i < this._joints.length; i++) {\n Matrix4x4.multiply(\n this._joints[i].worldMatrix,\n this._inverseBindMatrices[i],\n this._jointMatrices[i + this._jointOffsets[0] - 1]\n );\n }\n }\n /**\n * Reset skeleton to bind pose\n *\n * @internal\n */\n computeBindPose() {\n for (let i = 0; i < this._joints.length; i++) {\n const joint = this._joints[i];\n const bindpose = this._bindPose[i];\n joint.position.set(bindpose.position);\n joint.rotation.set(bindpose.rotation);\n joint.scale.set(bindpose.scale);\n }\n }\n /**\n * Compute current joint matrices from the nodes and upload them to the joint texture.\n *\n * @internal\n */\n apply(deltaTime: number) {\n this.updateJointMatrices(deltaTime);\n const tex = this.jointTexture;\n tex.update(this._jointMatrixArray, 0, 0, tex.width, tex.height);\n }\n /**\n * Apply all enabled modifiers.\n *\n * Modifiers are applied after the base animation/bind pose layer,\n * allowing procedural modifications like IK, spring physics, or manual overrides.\n *\n * @param deltaTime - Time elapsed since last frame (in seconds)\n * @internal\n */\n protected applyModifiers(deltaTime: number): void {\n for (const modifier of this._modifiers) {\n modifier.apply(this, deltaTime);\n }\n }\n /**\n * Get all modifiers attached to this skeleton.\n *\n * @public\n */\n get modifiers(): SkeletonModifier[] {\n return this._modifiers;\n }\n /**\n * Reset all meshes to an unskinned state and clear animated bounds.\n *\n * @internal\n */\n reset() {\n //this.updateJointMatrices(this._bindPoseMatrices);\n this._playing = false;\n }\n /**\n * Compute the animated bounding box for a single mesh using its representative vertices.\n *\n * For each representative vertex:\n * - Blends the vertex by up to 4 joint matrices using provided weights.\n * - Transforms to the mesh's local space using `invWorldMatrix`.\n * - Expands the bounding box.\n *\n * @param info - Precomputed bounding data (representative vertices, indices, weights).\n * @param invWorldMatrix - Mesh inverse world matrix to convert to model/local space.\n * @internal\n */\n computeBoundingBox(info: SkinnedBoundingBox, invWorldMatrix: Matrix4x4) {\n info.boundingBox.beginExtend();\n for (let i = 0; i < info.boundingVertices.length; i++) {\n this._jointMatrices[info.boundingVertexBlendIndices[i * 4 + 0] + this._jointOffsets[0] - 1]\n .transformPointAffine(info.boundingVertices[i], tmpV0)\n .scaleBy(info.boundingVertexJointWeights[i * 4 + 0]);\n this._jointMatrices[info.boundingVertexBlendIndices[i * 4 + 1] + this._jointOffsets[0] - 1]\n .transformPointAffine(info.boundingVertices[i], tmpV1)\n .scaleBy(info.boundingVertexJointWeights[i * 4 + 1]);\n this._jointMatrices[info.boundingVertexBlendIndices[i * 4 + 2] + this._jointOffsets[0] - 1]\n .transformPointAffine(info.boundingVertices[i], tmpV2)\n .scaleBy(info.boundingVertexJointWeights[i * 4 + 2]);\n this._jointMatrices[info.boundingVertexBlendIndices[i * 4 + 3] + this._jointOffsets[0] - 1]\n .transformPointAffine(info.boundingVertices[i], tmpV3)\n .scaleBy(info.boundingVertexJointWeights[i * 4 + 3]);\n tmpV0.addBy(tmpV1).addBy(tmpV2).addBy(tmpV3);\n invWorldMatrix.transformPointAffine(tmpV0, tmpV0);\n info.boundingBox.extend(tmpV0);\n }\n }\n /**\n * Dispose GPU resources and references held by the skeleton.\n *\n * - Disposes the joint texture.\n * - Clears matrix arrays and joint references.\n */\n protected onDispose() {\n super.onDispose();\n this._jointTexture.dispose();\n const m = Skeleton._registry.get(this._id);\n if (m?.get() === this) {\n Skeleton._registry.delete(this._id);\n m.dispose();\n }\n }\n /**\n * Initialize joint texture and CPU-side matrix storage.\n *\n * Layout details:\n * - Texture size is the next power-of-two able to contain all matrices plus two offset texels.\n * - `_jointMatrixArray` holds:\n * - First 2 vec4s: ring buffer offsets `[current, previous, 0, 0]`.\n * - Followed by 2×N matrices (current and previous), each as 16 floats.\n * - `_jointMatrices` is a view into `_jointMatrixArray` providing Matrix4x4 objects per slot.\n *\n * @internal\n */\n private _createJointTexture() {\n const textureWidth = nextPowerOf2(Math.max(4, Math.ceil(Math.sqrt((this._joints.length * 2 + 1) * 4))));\n const device = getDevice();\n this._jointTexture.set(\n device.createTexture2D('rgba32f', textureWidth, textureWidth, {\n mipmapping: false,\n samplerOptions: {\n magFilter: 'nearest',\n minFilter: 'nearest'\n }\n })\n );\n this._jointMatrixArray = new Float32Array(textureWidth * textureWidth * 4);\n const buffer = this._jointMatrixArray.buffer;\n this._jointOffsets = new Float32Array(buffer);\n this._jointOffsets[0] = 0;\n this._jointOffsets[1] = 0;\n this._jointMatrices = Array.from({ length: this._joints.length * 2 }).map(\n (val, index) => new Matrix4x4(buffer, (index + 1) * 16 * Float32Array.BYTES_PER_ELEMENT)\n );\n }\n /**\n * Build representative skinned bounding data for a submesh.\n *\n * Strategy:\n * - For all vertices, compute their skinned position (using current ring buffer slot).\n * - Track the indices of the min/max extents along x, y, z (6 indices total).\n * - Store:\n * - The 6 representative positions in object space.\n * - Their 4 joint indices and weights (flattened).\n * - An empty BoundingBox to be filled during animation.\n *\n * @param meshData - Raw submesh attributes (positions, blend indices, weights).\n * @returns Skinned bounding box info used during per-frame updates.\n */\n getBoundingInfo(data: { positions: Float32Array; blendIndices: TypedArray; weights: TypedArray }) {\n const indices = [0, 0, 0, 0, 0, 0];\n let minx = Number.MAX_VALUE;\n let maxx = -Number.MAX_VALUE;\n let miny = Number.MAX_VALUE;\n let maxy = -Number.MAX_VALUE;\n let minz = Number.MAX_VALUE;\n let maxz = -Number.MAX_VALUE;\n const v = data.positions;\n const vert = new Vector3();\n const tmpV0 = new Vector3();\n const tmpV1 = new Vector3();\n const tmpV2 = new Vector3();\n const tmpV3 = new Vector3();\n const numVertices = Math.floor(v.length / 3);\n for (let i = 0; i < numVertices; i++) {\n vert.setXYZ(v[i * 3], v[i * 3 + 1], v[i * 3 + 2]);\n this._jointMatrices[data.blendIndices[i * 4 + 0] + this._jointOffsets[0] - 1]\n .transformPointAffine(vert, tmpV0)\n .scaleBy(data.weights[i * 4 + 0]);\n this._jointMatrices[data.blendIndices[i * 4 + 1] + this._jointOffsets[0] - 1]\n .transformPointAffine(vert, tmpV1)\n .scaleBy(data.weights[i * 4 + 1]);\n this._jointMatrices[data.blendIndices[i * 4 + 2] + this._jointOffsets[0] - 1]\n .transformPointAffine(vert, tmpV2)\n .scaleBy(data.weights[i * 4 + 2]);\n this._jointMatrices[data.blendIndices[i * 4 + 3] + this._jointOffsets[0] - 1]\n .transformPointAffine(vert, tmpV3)\n .scaleBy(data.weights[i * 4 + 3]);\n tmpV0.addBy(tmpV1).addBy(tmpV2).addBy(tmpV3);\n if (tmpV0.x < minx) {\n minx = tmpV0.x;\n indices[0] = i;\n }\n if (tmpV0.x > maxx) {\n maxx = tmpV0.x;\n indices[1] = i;\n }\n if (tmpV0.y < miny) {\n miny = tmpV0.y;\n indices[2] = i;\n }\n if (tmpV0.y > maxy) {\n maxy = tmpV0.y;\n indices[3] = i;\n }\n if (tmpV0.z < minz) {\n minz = tmpV0.z;\n indices[4] = i;\n }\n if (tmpV0.z > maxz) {\n maxz = tmpV0.z;\n indices[5] = i;\n }\n }\n const info: SkinnedBoundingBox = {\n boundingVertexBlendIndices: new Float32Array(\n Array.from({ length: 6 * 4 }).map(\n (val, index) => data.blendIndices[indices[index >> 2] * 4 + (index % 4)]\n )\n ),\n boundingVertexJointWeights: new Float32Array(\n Array.from({ length: 6 * 4 }).map((val, index) => data.weights[indices[index >> 2] * 4 + (index % 4)])\n ),\n boundingVertices: Array.from({ length: 6 }).map(\n (val, index) =>\n new Vector3(\n data.positions[indices[index] * 3],\n data.positions[indices[index] * 3 + 1],\n data.positions[indices[index] * 3 + 2]\n )\n ),\n boundingBox: new BoundingBox()\n };\n return info;\n }\n private findRootJoint(joints: SceneNode[]) {\n let root: Nullable<SceneNode> = null;\n for (const joint of joints) {\n if (!root) {\n root = joint;\n }\n while (!root!.isParentOf(joint)) {\n root = root!.parent;\n }\n if (!root) {\n break;\n }\n }\n return root;\n }\n}\n"],"names":["tmpV0","Vector3","tmpV1","tmpV2","tmpV3","Skeleton","Disposable","_registry","Map","joints","inverseBindMatrices","bindPose","_id","randomUUID","_joints","_inverseBindMatrices","_bindPose","_jointTexture","DRef","_playing","_modifiers","_lastUpdateTime","_bindPoseModelSpace","computeBindPose","updateJointMatrices","skeletonRoot","findRootJoint","includes","Error","parent","im","invWorldMatrix","joint","m","Matrix4x4","multiplyAffine","worldMatrix","push","set","DWeakRef","findSkeletonById","id","get","delete","bindPoseModelSpace","playing","b","persistentId","val","jointTexture","getJointIndex","indexOf","getJointIndexByName","jointName","findIndex","name","deltaTime","applyModifiers","_createJointTexture","_jointOffsets","length","i","multiply","_jointMatrices","bindpose","position","rotation","scale","apply","tex","update","_jointMatrixArray","width","height","modifier","modifiers","reset","computeBoundingBox","info","boundingBox","beginExtend","boundingVertices","boundingVertexBlendIndices","transformPointAffine","scaleBy","boundingVertexJointWeights","addBy","extend","onDispose","dispose","textureWidth","nextPowerOf2","Math","max","ceil","sqrt","device","getDevice","createTexture2D","mipmapping","samplerOptions","magFilter","minFilter","Float32Array","buffer","Array","from","map","index","BYTES_PER_ELEMENT","getBoundingInfo","data","indices","minx","Number","MAX_VALUE","maxx","miny","maxy","minz","maxz","v","positions","vert","numVertices","floor","setXYZ","blendIndices","weights","x","y","z","BoundingBox","root","isParentOf"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -12210,6 +12210,7 @@ declare class Skeleton extends Disposable {
12210
12210
  scale: Vector3;
12211
12211
  position: Vector3;
12212
12212
  }[]);
12213
+ get bindPoseModelSpace(): Matrix4x4[];
12213
12214
  set playing(b: boolean);
12214
12215
  set persistentId(val: string);
12215
12216
  /**
@@ -12262,6 +12263,7 @@ declare class Skeleton extends Disposable {
12262
12263
  blendIndices: TypedArray;
12263
12264
  weights: TypedArray;
12264
12265
  }): SkinnedBoundingBox;
12266
+ private findRootJoint;
12265
12267
  }
12266
12268
 
12267
12269
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zephyr3d/scene",
3
- "version": "0.8.1",
3
+ "version": "0.8.2",
4
4
  "description": "Scene API for zephyr3d",
5
5
  "homepage": "https://github.com/gavinyork/zephyr3d#readme",
6
6
  "type": "module",