@viggle/splat-engine-three 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +450 -2
- package/dist/chunks/chunk-WN5WBKM4.js +8606 -0
- package/dist/chunks/chunk-WN5WBKM4.js.map +7 -0
- package/dist/index.js +56 -0
- package/dist/index.js.map +7 -0
- package/dist/types/anim/animation-conversion.d.ts +25 -0
- package/dist/types/anim/bind-pose.d.ts +15 -0
- package/dist/types/anim/keyframe-splines.d.ts +59 -0
- package/dist/types/anim/rest-relative.d.ts +32 -0
- package/dist/types/anim/spline.d.ts +14 -0
- package/dist/types/animation.d.ts +216 -0
- package/dist/types/armature.d.ts +524 -0
- package/dist/types/character.d.ts +582 -0
- package/dist/types/engine.d.ts +166 -0
- package/dist/types/environment.d.ts +53 -0
- package/dist/types/index.d.ts +40 -0
- package/dist/types/lighting/color.d.ts +13 -0
- package/dist/types/lighting/point-light.d.ts +33 -0
- package/dist/types/lighting/sky-light.d.ts +22 -0
- package/dist/types/lighting/sun-light.d.ts +34 -0
- package/dist/types/loader/animation/animation-glb.d.ts +117 -0
- package/dist/types/loader/character/index.d.ts +33 -0
- package/dist/types/loader/character/legacy/index.d.ts +34 -0
- package/dist/types/loader/character/legacy/interleaved-splat.d.ts +101 -0
- package/dist/types/loader/character/legacy/planar-splat.d.ts +139 -0
- package/dist/types/loader/character/load.d.ts +33 -0
- package/dist/types/loader/character/types.d.ts +129 -0
- package/dist/types/loader/character/v1/decode.d.ts +32 -0
- package/dist/types/loader/environment/ply.d.ts +16 -0
- package/dist/types/loader/shared/bin-cache.d.ts +19 -0
- package/dist/types/loader/skeleton/index.d.ts +19 -0
- package/dist/types/loader/skeleton/skeleton-data-441.d.ts +5 -0
- package/dist/types/loader/skeleton/skeleton-data.d.ts +6 -0
- package/dist/types/math.d.ts +82 -0
- package/dist/types/skeletal/animation-player.d.ts +185 -0
- package/dist/types/skeletal/bone-mask.d.ts +27 -0
- package/dist/types/skeletal/bone-stretch.d.ts +65 -0
- package/dist/types/skeletal/pose.d.ts +27 -0
- package/dist/types/skeletal/skeleton.d.ts +57 -0
- package/dist/types/skeletal/splat-skinning.d.ts +69 -0
- package/dist/types/splat/backend.d.ts +57 -0
- package/dist/types/splat/bone-binding.d.ts +38 -0
- package/dist/types/splat/depth-sort.d.ts +76 -0
- package/dist/types/splat/importance.d.ts +60 -0
- package/dist/types/splat/packed-splats.d.ts +36 -0
- package/dist/types/splat/prune.d.ts +60 -0
- package/dist/types/splat/quality.d.ts +175 -0
- package/dist/types/splat/splat-mesh.d.ts +71 -0
- package/dist/types/splat/splat.d.ts +252 -0
- package/dist/types/splat/transform-palette.d.ts +42 -0
- package/dist/types/splat/webgl/backend.d.ts +17 -0
- package/dist/types/splat/webgl/shaders.d.ts +2 -0
- package/dist/types/splat/webgl/splat-mesh.d.ts +54 -0
- package/dist/types/splat/webgpu/backend.d.ts +25 -0
- package/dist/types/splat/webgpu/lighting.d.ts +34 -0
- package/dist/types/splat/webgpu/radix-sort.d.ts +46 -0
- package/dist/types/splat/webgpu/splat-mesh.d.ts +73 -0
- package/dist/types/three/loaders.d.ts +77 -0
- package/dist/types/three/splat-character.d.ts +220 -0
- package/dist/types/types.d.ts +30 -0
- package/dist/types/webgpu.d.ts +5 -0
- package/dist/webgpu.js +843 -0
- package/dist/webgpu.js.map +7 -0
- package/package.json +46 -4
package/dist/index.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Animation,
|
|
3
|
+
Armature,
|
|
4
|
+
Character,
|
|
5
|
+
CharacterBundleError,
|
|
6
|
+
EngineDisposedError,
|
|
7
|
+
Environment,
|
|
8
|
+
PointLight,
|
|
9
|
+
SkyLight,
|
|
10
|
+
Splat,
|
|
11
|
+
SplatCharacter,
|
|
12
|
+
SplatClipLoader,
|
|
13
|
+
SplatEngine,
|
|
14
|
+
SplatMesh,
|
|
15
|
+
SplatPLYLoader,
|
|
16
|
+
SplatQuality,
|
|
17
|
+
SunLight,
|
|
18
|
+
VSplatLoader,
|
|
19
|
+
WebGLSplatBackend,
|
|
20
|
+
decodeCharacterBundle,
|
|
21
|
+
loadCharacterBundle,
|
|
22
|
+
loadCharacterBundleFromBytes,
|
|
23
|
+
makeRegionMask,
|
|
24
|
+
packSplats,
|
|
25
|
+
parseGaussianPly,
|
|
26
|
+
pruneSplats
|
|
27
|
+
} from "./chunks/chunk-WN5WBKM4.js";
|
|
28
|
+
export {
|
|
29
|
+
Animation,
|
|
30
|
+
Armature,
|
|
31
|
+
Character,
|
|
32
|
+
CharacterBundleError,
|
|
33
|
+
EngineDisposedError,
|
|
34
|
+
Environment,
|
|
35
|
+
PointLight,
|
|
36
|
+
SkyLight,
|
|
37
|
+
Splat,
|
|
38
|
+
SplatCharacter,
|
|
39
|
+
Animation as SplatClip,
|
|
40
|
+
SplatClipLoader,
|
|
41
|
+
SplatEngine,
|
|
42
|
+
SplatMesh,
|
|
43
|
+
SplatPLYLoader,
|
|
44
|
+
SplatQuality,
|
|
45
|
+
SunLight,
|
|
46
|
+
VSplatLoader,
|
|
47
|
+
WebGLSplatBackend,
|
|
48
|
+
decodeCharacterBundle,
|
|
49
|
+
loadCharacterBundle,
|
|
50
|
+
loadCharacterBundleFromBytes,
|
|
51
|
+
makeRegionMask,
|
|
52
|
+
packSplats,
|
|
53
|
+
parseGaussianPly,
|
|
54
|
+
pruneSplats
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Animation } from '../animation';
|
|
2
|
+
import type { SkeletonLibrary } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Walk the raw 4×4 bone matrices stored in `animationData.data` and produce
|
|
5
|
+
* the per-bone keyframe + spline cache used at playback time.
|
|
6
|
+
*
|
|
7
|
+
* Idempotent - subsequent calls on the same `Animation` are no-ops (guarded
|
|
8
|
+
* by `Animation.skeletalConverted`). {@link Animation.register} calls this
|
|
9
|
+
* for you.
|
|
10
|
+
*
|
|
11
|
+
* Side effect: clears `animationData.data` once converted, since the raw
|
|
12
|
+
* matrices are no longer needed and would otherwise hold ~16 floats per bone
|
|
13
|
+
* per frame in memory for the lifetime of the animation.
|
|
14
|
+
*/
|
|
15
|
+
export declare function convertSkeletalAnimation(animationData: Animation, _skeletonLibrary: SkeletonLibrary): void;
|
|
16
|
+
/**
|
|
17
|
+
* Return a view of `animationData` remapped to the target armature's bone
|
|
18
|
+
* count, handling rig mismatches (e.g. a 1185-bone source animation played on
|
|
19
|
+
* an 86-bone body rig). Target bones with no matching source bone stay at
|
|
20
|
+
* rest pose during playback.
|
|
21
|
+
*
|
|
22
|
+
* Result is cached on the input via `Animation.filteredForBones`, so repeated
|
|
23
|
+
* calls for the same target bone count reuse the filtered copy.
|
|
24
|
+
*/
|
|
25
|
+
export declare function filterAnimationForArmature(animationData: Animation, targetBoneCount: number, skeletonLibrary: SkeletonLibrary): Animation;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Mat4 } from '../math';
|
|
2
|
+
/**
|
|
3
|
+
* Walk the rig's rest pose to produce world-space bind-pose matrices, one per
|
|
4
|
+
* bone. Parents are expected to come before their children in index order (the
|
|
5
|
+
* skeleton library's bone arrays satisfy this).
|
|
6
|
+
*
|
|
7
|
+
* Returns `null` if any of the three arrays is missing - the armature's
|
|
8
|
+
* `armatureData` carries them as optional fields.
|
|
9
|
+
*/
|
|
10
|
+
export declare function computeBindPoseTransforms(numBones: number, restTranslations: Float32Array, restRotations: Float32Array, parents: Int32Array): Mat4[];
|
|
11
|
+
/**
|
|
12
|
+
* Compute the inverse of each matrix in `bindPose`. Returns a new array; the
|
|
13
|
+
* input is left untouched.
|
|
14
|
+
*/
|
|
15
|
+
export declare function invertBindPose(bindPose: Mat4[]): Mat4[];
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Quat, Vec3 } from '../math';
|
|
2
|
+
import type { RestPose } from './rest-relative';
|
|
3
|
+
import { CubicSpline } from './spline';
|
|
4
|
+
/** One sample on a per-bone animation curve. */
|
|
5
|
+
export interface Pose {
|
|
6
|
+
frame: number;
|
|
7
|
+
position: Vec3;
|
|
8
|
+
rotation: Quat;
|
|
9
|
+
scale: Vec3;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Per-bone keyframe entry: a list of poses sorted by frame plus the cached
|
|
13
|
+
* cubic spline that interpolates them. `spline` is null when there are fewer
|
|
14
|
+
* than two poses (a constant-pose bone - the consumer samples `poses[0]`).
|
|
15
|
+
*/
|
|
16
|
+
export interface KeyframeEntryData {
|
|
17
|
+
poses: Pose[];
|
|
18
|
+
spline: CubicSpline | null;
|
|
19
|
+
}
|
|
20
|
+
interface RebuildOptions {
|
|
21
|
+
/** Include poses where `frame === duration`. Default `false`. */
|
|
22
|
+
includeEnd?: boolean;
|
|
23
|
+
/** Build a looping spline that wraps at `duration`. Default `false`. */
|
|
24
|
+
looping?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Filter `poses` against `[0, duration)` (or `[0, duration]` when
|
|
28
|
+
* `options.includeEnd`), sort by frame, and build the cubic spline that
|
|
29
|
+
* interpolates them.
|
|
30
|
+
*
|
|
31
|
+
* Returns `{ poses, spline }`: a fresh sorted poses array (callers should
|
|
32
|
+
* replace their original) and the spline, or `null` if fewer than two poses
|
|
33
|
+
* survive the filter.
|
|
34
|
+
*
|
|
35
|
+
* Quaternion sign is normalized along the timeline so neighboring keys take
|
|
36
|
+
* the short arc - without this the spline would interpolate the long way
|
|
37
|
+
* around whenever a sample flips hemisphere.
|
|
38
|
+
*/
|
|
39
|
+
export declare function rebuildKeyframeSpline(poses: Pose[], duration: number, options?: RebuildOptions): {
|
|
40
|
+
poses: Pose[];
|
|
41
|
+
spline: CubicSpline | null;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Build the per-bone keyframe array an armature samples from at playback time.
|
|
45
|
+
*
|
|
46
|
+
* For each bone in `libraryKeyframes` whose index is below `numBones`:
|
|
47
|
+
* 1. convert every pose into the bone's rest-relative space (so playback can
|
|
48
|
+
* blend a delta on top of the rest pose), and
|
|
49
|
+
* 2. rebuild the cubic spline, filtered+sorted by frame and wrapped for
|
|
50
|
+
* looping if requested.
|
|
51
|
+
*
|
|
52
|
+
* Result is a sparse array of length `numBones`; bones not referenced by the
|
|
53
|
+
* source map stay `null` and fall back to rest pose at evaluation time.
|
|
54
|
+
*
|
|
55
|
+
* If `restPose.positions` is empty (rig has no rest data), poses are emitted
|
|
56
|
+
* unchanged - the rest-relative conversion no-ops.
|
|
57
|
+
*/
|
|
58
|
+
export declare function buildArmatureKeyframes(libraryKeyframes: Map<number, KeyframeEntryData>, numFrames: number, numBones: number, restPose: RestPose, looping: boolean, translationMask?: Uint8Array): Array<KeyframeEntryData | null>;
|
|
59
|
+
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Quat } from '../math';
|
|
2
|
+
import type { Vec3 } from '../math';
|
|
3
|
+
/**
|
|
4
|
+
* Rest pose for a rig, stored as parallel arrays indexed by bone. An empty
|
|
5
|
+
* `positions` array marks an uninitialized rest pose - the rest-relative
|
|
6
|
+
* conversion functions pass poses through unchanged in that case.
|
|
7
|
+
*/
|
|
8
|
+
export interface RestPose {
|
|
9
|
+
positions: Vec3[];
|
|
10
|
+
rotations: Quat[];
|
|
11
|
+
scales: Vec3[];
|
|
12
|
+
}
|
|
13
|
+
/** A bone-space transform: position, rotation (as quaternion), and scale. */
|
|
14
|
+
export interface BonePose {
|
|
15
|
+
position: Vec3;
|
|
16
|
+
rotation: Quat;
|
|
17
|
+
scale: Vec3;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Express `pose` relative to the bone's rest transform. Writes the result
|
|
21
|
+
* into `out`. Safe to call with `out === pose` (in-place).
|
|
22
|
+
*
|
|
23
|
+
* If `boneIndex` is out of range or `rest` is uninitialized, `pose` is copied
|
|
24
|
+
* to `out` unchanged.
|
|
25
|
+
*/
|
|
26
|
+
export declare function toRestRelative(boneIndex: number, pose: BonePose, rest: RestPose, out: BonePose): void;
|
|
27
|
+
/**
|
|
28
|
+
* Inverse of {@link toRestRelative}: compose a rest-relative `delta` back into
|
|
29
|
+
* an absolute bone pose. Writes the result into `out`. Safe to call with
|
|
30
|
+
* `out === delta` (in-place).
|
|
31
|
+
*/
|
|
32
|
+
export declare function fromRestRelative(boneIndex: number, delta: BonePose, rest: RestPose, out: BonePose): void;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
declare class CubicSpline {
|
|
2
|
+
times: number[];
|
|
3
|
+
knots: number[];
|
|
4
|
+
dim: number;
|
|
5
|
+
readonly keyframeOffset: number;
|
|
6
|
+
constructor(times: number[], knots: number[], keyframeOffset?: number);
|
|
7
|
+
evaluate(time: number, result: number[]): void;
|
|
8
|
+
getKnot(index: number, result: number[]): void;
|
|
9
|
+
evaluateSegment(segment: number, t: number, result: number[]): void;
|
|
10
|
+
static calcKnots(times: number[], points: number[], smoothness: number): number[];
|
|
11
|
+
static fromPoints(times: number[], points: number[], smoothness?: number): CubicSpline;
|
|
12
|
+
static fromPointsLooping(length: number, times: number[], points: number[], smoothness?: number): CubicSpline;
|
|
13
|
+
}
|
|
14
|
+
export { CubicSpline };
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import type { Quat, Vec3 } from './math';
|
|
2
|
+
import type { CubicSpline } from './anim/spline';
|
|
3
|
+
import type { SplatEngine } from './engine';
|
|
4
|
+
/**
|
|
5
|
+
* A frame-aligned event attached to an {@link Animation}. Events are fired by
|
|
6
|
+
* {@link AnimationPlayer} as `animTime` crosses each `frame`, dispatched
|
|
7
|
+
* through {@link Armature.onAnimEvent} / {@link Character.onAnimEvent}.
|
|
8
|
+
*
|
|
9
|
+
* The engine treats `name` and `payload` as opaque - games define their own
|
|
10
|
+
* vocabulary (e.g. `'footstep'`, `'hit-impact'`, `'screen-shake'`) and route
|
|
11
|
+
* via the listener.
|
|
12
|
+
*
|
|
13
|
+
* @group Characters & Animation
|
|
14
|
+
*/
|
|
15
|
+
export interface AnimationEvent {
|
|
16
|
+
/** Frame index (integer, `0 .. numFrames-1`). */
|
|
17
|
+
frame: number;
|
|
18
|
+
/** Game-defined event name. */
|
|
19
|
+
name: string;
|
|
20
|
+
/** Optional game-defined payload, opaque to the engine. */
|
|
21
|
+
payload?: unknown;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Per-bone keyframe entry inside a {@link SkeletalStore}.
|
|
25
|
+
* @internal
|
|
26
|
+
*/
|
|
27
|
+
export interface SkeletalKeyframeEntry {
|
|
28
|
+
poses: Array<{
|
|
29
|
+
frame: number;
|
|
30
|
+
position: Vec3;
|
|
31
|
+
rotation: Quat;
|
|
32
|
+
scale: Vec3;
|
|
33
|
+
}>;
|
|
34
|
+
spline: CubicSpline | null;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Engine-private cache attached to an {@link Animation} after
|
|
38
|
+
* {@link convertSkeletalAnimation} processes the raw matrices into
|
|
39
|
+
* per-bone keyframes + splines. Subsequent registrations and playback reads
|
|
40
|
+
* go through this store rather than re-walking the raw `Float32Array`.
|
|
41
|
+
*
|
|
42
|
+
* @internal
|
|
43
|
+
*/
|
|
44
|
+
export interface SkeletalStore {
|
|
45
|
+
keyframes: Map<number, SkeletalKeyframeEntry>;
|
|
46
|
+
manualBones: Set<number>;
|
|
47
|
+
source: string;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Parsed skeletal animation data.
|
|
51
|
+
*
|
|
52
|
+
* An `Animation` is the deserialized form of one clip, whatever it was
|
|
53
|
+
* authored as. It holds a flat `Float32Array` of per-bone 4×4 matrices indexed
|
|
54
|
+
* by frame and bone. Once registered on an engine under a name, characters can play
|
|
55
|
+
* it via {@link Character.playAnimation} / {@link Character.crossfadeTo}.
|
|
56
|
+
*
|
|
57
|
+
* The primary entry point is {@link Animation.loadGlb}, which fetches a
|
|
58
|
+
* MetaHuman GLB, parses and registers it in one call. For custom fetch
|
|
59
|
+
* pipelines, use {@link Animation.fromGlb} on an already-fetched
|
|
60
|
+
* `ArrayBuffer`, then {@link Animation#register} to attach it to the engine.
|
|
61
|
+
* The `.anim` container is still read, by {@link Animation.load} and
|
|
62
|
+
* {@link Animation.parse}.
|
|
63
|
+
*
|
|
64
|
+
* @group Characters & Animation
|
|
65
|
+
*/
|
|
66
|
+
export declare class Animation {
|
|
67
|
+
/** Column-major bone matrices (translation at `[12..14]`, the layout
|
|
68
|
+
* `THREE.Matrix4.elements` uses), length `numFrames * numBones * 16`. */
|
|
69
|
+
data: Float32Array;
|
|
70
|
+
/** Number of animation frames. */
|
|
71
|
+
numFrames: number;
|
|
72
|
+
/** Number of bones per frame. */
|
|
73
|
+
numBones: number;
|
|
74
|
+
/** Optional sparse keyframe indices. If present, frames between keyframes are interpolated. */
|
|
75
|
+
keyframeFrames?: number[];
|
|
76
|
+
/**
|
|
77
|
+
* Per bone: `1` if this clip drives the bone's translation, `0` if the bone
|
|
78
|
+
* must keep the armature's own rest translation.
|
|
79
|
+
*
|
|
80
|
+
* A constant translation track is not motion - it is the source rig's bone
|
|
81
|
+
* length. Applied to a character whose skeleton differs, it silently replaces
|
|
82
|
+
* that character's bone lengths mid-clip while the bind pose keeps the
|
|
83
|
+
* originals, which compresses the skin. Both readers are built with that in
|
|
84
|
+
* mind and set a `0` for every bone whose translation holds still, judged from
|
|
85
|
+
* the decoded data: {@link Animation.fromGlb} per channel, {@link Animation.parse}
|
|
86
|
+
* across the per-frame matrices. `undefined` means every bone genuinely
|
|
87
|
+
* translates, and every bone drives its own translation.
|
|
88
|
+
*
|
|
89
|
+
* Set once, at parse time, and never mutated afterwards. Playback caches
|
|
90
|
+
* keyframes per `Animation` object, so a mask that could change would go stale
|
|
91
|
+
* inside them. `filterAnimationForArmature` remaps rather than edits, onto a
|
|
92
|
+
* new `Animation` that is its own cache key.
|
|
93
|
+
*
|
|
94
|
+
* Consumed by `buildArmatureKeyframes`, which zeroes the position delta for
|
|
95
|
+
* masked bones so `fromRestRelative` yields `pose.position = restPosition`.
|
|
96
|
+
*/
|
|
97
|
+
translationMask?: Uint8Array;
|
|
98
|
+
/**
|
|
99
|
+
* Frame-aligned events fired as `animTime` advances. Set by
|
|
100
|
+
* {@link Animation.parse} from the `.anim` header's optional `events` array,
|
|
101
|
+
* or assigned directly by game code before {@link Animation.register}.
|
|
102
|
+
*/
|
|
103
|
+
events?: AnimationEvent[];
|
|
104
|
+
/** @internal Set by convertSkeletalAnimation on first registration. */
|
|
105
|
+
/** The clip's own name, where its file gave one. Not the name it is registered under. */
|
|
106
|
+
name: string;
|
|
107
|
+
/** Frames per second the clip was authored at. `30` unless the file says otherwise. */
|
|
108
|
+
frameRate: number;
|
|
109
|
+
/** The name of the most recent {@link Animation.register}, if any. */
|
|
110
|
+
registeredName?: string;
|
|
111
|
+
private _registeredIn;
|
|
112
|
+
/** Length in seconds at the authored frame rate. */
|
|
113
|
+
get duration(): number;
|
|
114
|
+
skeletalConverted: boolean;
|
|
115
|
+
/** @internal Per-bone keyframe cache produced by convertSkeletalAnimation. */
|
|
116
|
+
skeletalStore?: SkeletalStore;
|
|
117
|
+
/** @internal Per-target-bone-count cache of `filterAnimationForArmature` outputs. */
|
|
118
|
+
filteredForBones?: Map<number, Animation>;
|
|
119
|
+
constructor(data: Float32Array, numFrames: number, numBones: number, keyframeFrames?: number[]);
|
|
120
|
+
/**
|
|
121
|
+
* Parse an in-memory `.anim` buffer.
|
|
122
|
+
*
|
|
123
|
+
* Accepts both v2 (float32) and v3 (float16) data encodings. Use this when
|
|
124
|
+
* fetching through a custom pipeline; pair with {@link Animation#register}
|
|
125
|
+
* to make the result playable. Otherwise prefer {@link Animation.load}, the
|
|
126
|
+
* fetching wrapper around this one. For a MetaHuman GLB, the current
|
|
127
|
+
* container, the pair is {@link Animation.fromGlb} / {@link Animation.loadGlb}.
|
|
128
|
+
*
|
|
129
|
+
* Also derives {@link Animation#translationMask} from the decoded matrices, so
|
|
130
|
+
* bones whose translation never moves keep the *target* character's bone
|
|
131
|
+
* lengths instead of the source rig's.
|
|
132
|
+
*
|
|
133
|
+
* @throws If the header is missing, malformed, or not of type `skeletal_animation`.
|
|
134
|
+
*/
|
|
135
|
+
static parse(buffer: ArrayBuffer): Animation;
|
|
136
|
+
/**
|
|
137
|
+
* Parse an in-memory *MetaHuman GLB* - a glTF 2.0 binary holding a bone
|
|
138
|
+
* hierarchy and one animation clip, carrying no real geometry (as produced
|
|
139
|
+
* by the offline MetaHuman GLB exporter).
|
|
140
|
+
*
|
|
141
|
+
* The result is indistinguishable from {@link Animation.parse} output: the
|
|
142
|
+
* clip's absolute parent-local TRS is packed into the same flat 4x4 bone
|
|
143
|
+
* matrices, so every downstream stage - `convertSkeletalAnimation`,
|
|
144
|
+
* `filterAnimationForArmature`, `AnimationPlayer` - behaves exactly as it
|
|
145
|
+
* does for a `.anim`.
|
|
146
|
+
*
|
|
147
|
+
* `animationName` selects a clip by name when the GLB holds more than one;
|
|
148
|
+
* omitted, the first clip is used. Pair with {@link Animation#register} to
|
|
149
|
+
* make the result playable, or use {@link Animation.loadGlb}.
|
|
150
|
+
*
|
|
151
|
+
* @throws If the container is not GLB 2.0, or the clip does not supply a
|
|
152
|
+
* translation and a rotation channel for every bone on one shared timeline.
|
|
153
|
+
*/
|
|
154
|
+
static fromGlb(buffer: ArrayBuffer, animationName?: string): Animation;
|
|
155
|
+
/**
|
|
156
|
+
* {@link Animation.fromGlb} without the frame-rate warning: the clip's own
|
|
157
|
+
* rate is recorded on {@link Animation.frameRate} for a caller that applies it.
|
|
158
|
+
* @internal
|
|
159
|
+
*/
|
|
160
|
+
static parseGlb(buffer: ArrayBuffer, animationName?: string): Animation;
|
|
161
|
+
/**
|
|
162
|
+
* Fetch, parse, and register a `.anim` file on the engine under `name`.
|
|
163
|
+
*
|
|
164
|
+
* After this resolves, characters can play it via
|
|
165
|
+
* `character.playAnimation(name)` / `character.crossfadeTo(name)`.
|
|
166
|
+
*
|
|
167
|
+
* @throws If the network request fails or the file is not a valid animation.
|
|
168
|
+
* @example
|
|
169
|
+
* ```ts
|
|
170
|
+
* await Animation.load(engine, '/assets/idle.anim', 'idle');
|
|
171
|
+
* character.playAnimation('idle', { loop: true });
|
|
172
|
+
* ```
|
|
173
|
+
*/
|
|
174
|
+
static load(engine: SplatEngine, url: string, name: string): Promise<Animation>;
|
|
175
|
+
/**
|
|
176
|
+
* Fetch, parse, and register a MetaHuman GLB on the engine under `name`.
|
|
177
|
+
* The GLB counterpart of {@link Animation.load}.
|
|
178
|
+
*
|
|
179
|
+
* `animationName` selects a clip inside the GLB by name; omitted, the first
|
|
180
|
+
* clip is used. After this resolves, characters can play it via
|
|
181
|
+
* `character.playAnimation(name)` / `character.crossfadeTo(name)` - the
|
|
182
|
+
* source format is invisible from that point on.
|
|
183
|
+
*
|
|
184
|
+
* @throws If the network request fails or the GLB is not a valid armature clip.
|
|
185
|
+
* @example
|
|
186
|
+
* ```ts
|
|
187
|
+
* await Animation.loadGlb(engine, '/assets/metahuman_full.glb', 'walk');
|
|
188
|
+
* character.playAnimation('walk', { loop: true });
|
|
189
|
+
* ```
|
|
190
|
+
*/
|
|
191
|
+
static loadGlb(engine: SplatEngine, url: string, name: string, animationName?: string): Promise<Animation>;
|
|
192
|
+
/**
|
|
193
|
+
* Process-wide ArrayBuffer cache for .anim URLs. Each `SplatEngine` still
|
|
194
|
+
* gets its own parsed `Animation` (storage arrays are mutated by the
|
|
195
|
+
* skeletal converter so they're not safely shareable across scenes),
|
|
196
|
+
* but the network bytes are shared. Avoids re-downloading the same
|
|
197
|
+
* idle/walk clips every time the app swaps one engine for another.
|
|
198
|
+
*/
|
|
199
|
+
private static _bufferCache;
|
|
200
|
+
private static _bufferLoading;
|
|
201
|
+
private static _fetchBuffer;
|
|
202
|
+
/**
|
|
203
|
+
* Convert the animation data against the engine's skeleton library and
|
|
204
|
+
* register it under `name` so characters can play it.
|
|
205
|
+
*
|
|
206
|
+
* Must be called before {@link Character.playAnimation} / {@link Character.crossfadeTo}
|
|
207
|
+
* reference this animation.
|
|
208
|
+
*/
|
|
209
|
+
register(engine: SplatEngine, name: string): void;
|
|
210
|
+
/**
|
|
211
|
+
* Remove the clip from the engine it is registered with, so it can be
|
|
212
|
+
* garbage-collected once nothing is playing it. A character already playing
|
|
213
|
+
* the clip keeps playing; starting it again registers it afresh.
|
|
214
|
+
*/
|
|
215
|
+
dispose(): void;
|
|
216
|
+
}
|