three-vat 2.0.0 → 2.1.0
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/README.md +5 -0
- package/dist/{carrier-BFCPmcQK.d.ts → carrier-BXaLAPRO.d.ts} +61 -18
- package/dist/{chunk-2PGZ44TP.js → chunk-3PWAY6MD.js} +10 -1
- package/dist/{chunk-W2ZAFMPB.js → chunk-I4STYOD5.js} +1 -1
- package/dist/index.d.ts +39 -4
- package/dist/index.js +499 -35
- package/dist/tsl.d.ts +50 -27
- package/dist/tsl.js +95 -15
- package/dist/webgl.d.ts +1 -1
- package/dist/webgl.js +179 -21
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -81,6 +81,11 @@ Two things worth knowing the first time:
|
|
|
81
81
|
- **Materials are never merged.** A 500-robot crowd with 3 materials is 3 draw
|
|
82
82
|
calls — not 1, and not 500. VAT collapses instance count, not material count.
|
|
83
83
|
|
|
84
|
+
**A skinned character?** There is a second encoding: `{ encoding: 'rig' }` bakes
|
|
85
|
+
the posed rig instead of the posed vertices — two orders of magnitude less
|
|
86
|
+
texture, a bake in milliseconds, and faster on a phone, for an asset a rig can
|
|
87
|
+
express. [The rig encoding](./docs/usage.md#the-rig-encoding-encoding-rig).
|
|
88
|
+
|
|
84
89
|
<details>
|
|
85
90
|
<summary><b>Does it work with my model?</b></summary>
|
|
86
91
|
|
|
@@ -374,7 +374,9 @@ interface VATClip extends VATClipDefaults {
|
|
|
374
374
|
/** Source clip duration in seconds. */
|
|
375
375
|
duration: number;
|
|
376
376
|
/**
|
|
377
|
-
* Largest
|
|
377
|
+
* Largest displacement (metres) of any vertex from the rest pose across the
|
|
378
|
+
* clip — the same number under either encoding, because the rig bake skins
|
|
379
|
+
* every vertex on the CPU for the bounds anyway and measures it there.
|
|
378
380
|
* Near-zero means the clip baked as a frozen pose — the diagnostic for a
|
|
379
381
|
* mis-targeted or genuinely static clip.
|
|
380
382
|
*/
|
|
@@ -396,22 +398,14 @@ interface VATClip extends VATClipDefaults {
|
|
|
396
398
|
* change it in a minor release. Move the buffer, hand it to {@link makeVATTexture};
|
|
397
399
|
* do not read numbers out of it.
|
|
398
400
|
*/
|
|
399
|
-
interface
|
|
400
|
-
/** RGBA float texture of per-vertex position deltas (`x = vertex`, `y = frame`). */
|
|
401
|
-
positionTexture: DataTexture;
|
|
402
|
-
/**
|
|
403
|
-
* RGBA float texture of per-vertex absolute normals (`x = vertex`, `y = frame`),
|
|
404
|
-
* or `null` when the bake was told to skip it (`bakeNormals: false`) — halving
|
|
405
|
-
* the VAT for a crowd that never reads a normal. Neither decode path samples
|
|
406
|
-
* it when it is absent; a smooth-shaded lit material paired with such a VAT is
|
|
407
|
-
* refused rather than lit by its rest pose.
|
|
408
|
-
*/
|
|
409
|
-
normalTexture: DataTexture | null;
|
|
401
|
+
interface VATBase {
|
|
410
402
|
/**
|
|
411
|
-
* Merged
|
|
412
|
-
*
|
|
413
|
-
*
|
|
414
|
-
*
|
|
403
|
+
* Merged rest-pose geometry, in whichever space the encoding stores it: root
|
|
404
|
+
* space under the vertex encoding, where its `position` is the delta
|
|
405
|
+
* reference; each part's own local space under the rig encoding, where the
|
|
406
|
+
* slot carries the placement and also keeps `skinIndex` and `skinWeight`.
|
|
407
|
+
* Carries `normal` always, and `uv`, `color` and `tangent` when every source
|
|
408
|
+
* mesh carried them.
|
|
415
409
|
*/
|
|
416
410
|
geometry: BufferGeometry;
|
|
417
411
|
/** Source materials, indexed by `geometry.groups[].materialIndex`. */
|
|
@@ -424,9 +418,58 @@ interface VAT {
|
|
|
424
418
|
vertexCount: number;
|
|
425
419
|
/** Total frame rows across all clips (texture height). */
|
|
426
420
|
totalFrames: number;
|
|
427
|
-
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* A VAT under the **vertex encoding**: a row holds where every vertex ended up,
|
|
424
|
+
* as a position delta and, unless the bake was told to skip it, a normal. The
|
|
425
|
+
* source-agnostic encoding (ADR-0008) and the default; the member every bake
|
|
426
|
+
* produced before there was a second one (ADR-0018).
|
|
427
|
+
*/
|
|
428
|
+
interface DeltaVAT extends VATBase {
|
|
429
|
+
/** Which encoding a row holds — the discriminant of {@link VAT}. */
|
|
428
430
|
encoding: 'delta';
|
|
431
|
+
/** RGBA float texture of per-vertex position deltas (`x = vertex`, `y = frame`). */
|
|
432
|
+
positionTexture: DataTexture;
|
|
433
|
+
/**
|
|
434
|
+
* RGBA float texture of per-vertex absolute normals (`x = vertex`, `y = frame`),
|
|
435
|
+
* or `null` when the bake was told to skip it (`bakeNormals: false`) — halving
|
|
436
|
+
* the VAT for a crowd that never reads a normal. Neither decode path samples
|
|
437
|
+
* it when it is absent; a smooth-shaded lit material paired with such a VAT is
|
|
438
|
+
* refused rather than lit by its rest pose.
|
|
439
|
+
*/
|
|
440
|
+
normalTexture: DataTexture | null;
|
|
429
441
|
}
|
|
442
|
+
/**
|
|
443
|
+
* A VAT under the **rig encoding** (ADR-0018): a row holds the posed rig — one
|
|
444
|
+
* **slot** per bone, as a rotation, a translation and a uniform scale — and the
|
|
445
|
+
* vertex shader skins the rest-pose geometry from it. Two orders of magnitude
|
|
446
|
+
* smaller than the vertex encoding and bake-cheap, at the price of source
|
|
447
|
+
* agnosticism: what a rig cannot express is refused at the bake.
|
|
448
|
+
*
|
|
449
|
+
* No normal texture, and none missing: normals and tangents come out of the
|
|
450
|
+
* skin matrix, as in three's own skinning.
|
|
451
|
+
*/
|
|
452
|
+
interface RigVAT extends VATBase {
|
|
453
|
+
/** Which encoding a row holds — the discriminant of {@link VAT}. */
|
|
454
|
+
encoding: 'rig';
|
|
455
|
+
/**
|
|
456
|
+
* RGBA float **rig texture**: two texels per slot — `(qx, qy, qz, qw)` then
|
|
457
|
+
* `(tx, ty, tz, s)` — laid out as `x = slot × 2 + texel`, `y = frame`, clips
|
|
458
|
+
* stacked as bands exactly as in the position texture. Consecutive rows of
|
|
459
|
+
* one slot sit on one quaternion hemisphere; the decode still flips the
|
|
460
|
+
* second row onto the first's side, because a looping clip blends a band's
|
|
461
|
+
* last row into its first and those are not neighbours.
|
|
462
|
+
*/
|
|
463
|
+
rigTexture: DataTexture;
|
|
464
|
+
/** Slots in the rig — the texture is `slotCount × 2` texels wide. */
|
|
465
|
+
slotCount: number;
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* A baked VAT, discriminated on `encoding`. A decode that samples a texture
|
|
469
|
+
* narrows on `encoding` first, so an encoding it does not decode is refused by
|
|
470
|
+
* name rather than sampled as a texture the VAT does not have (ADR-0018).
|
|
471
|
+
*/
|
|
472
|
+
type VAT = DeltaVAT | RigVAT;
|
|
430
473
|
/**
|
|
431
474
|
* The shared playback clock: one `{ value }` in seconds, read by every material
|
|
432
475
|
* of every VAT mesh driven by it. Set it once per frame. Deliberately the
|
|
@@ -469,4 +512,4 @@ interface VATCrowd {
|
|
|
469
512
|
*/
|
|
470
513
|
type VATCarrier = InstancedMesh | BatchedMesh;
|
|
471
514
|
|
|
472
|
-
export { EndMode as E, INFINITE_REPETITIONS as I, LoopMode as L, MAX_FADE_DURATION as M, type VAT as V, type
|
|
515
|
+
export { type DeltaVAT as D, EndMode as E, INFINITE_REPETITIONS as I, LoopMode as L, MAX_FADE_DURATION as M, type RigVAT as R, type VAT as V, type VATBase as a, type VATCarrier as b, type VATClip as c, type VATClipDefaults as d, type VATClock as e, type VATCrowd as f, type VATFadeFrom as g, type VATFrame as h, type VATInstance as i, type VATPlaybackTexture as j, createVATPlaybackTexture as k, endsAt as l, resolveVATFrame as r, setVATInstance as s };
|
|
@@ -199,4 +199,13 @@ function endsAt(instance) {
|
|
|
199
199
|
return instance.startTime + duration * repetitions / speed;
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
-
|
|
202
|
+
// src/rig-texture.ts
|
|
203
|
+
var RIG_TEXELS = {
|
|
204
|
+
/** `(qx, qy, qz, qw)` — the slot's rotation, on one hemisphere with its neighbouring rows. */
|
|
205
|
+
rotation: 0,
|
|
206
|
+
/** `(tx, ty, tz, s)` — where the slot puts the origin, and its uniform scale in the spare component. */
|
|
207
|
+
placement: 1
|
|
208
|
+
};
|
|
209
|
+
var RIG_TEXELS_PER_SLOT = 2;
|
|
210
|
+
|
|
211
|
+
export { EndMode, FORWARD_ONLY_REASON, INFINITE_REPETITIONS, LIBRARY_PLAYBACK_DEFAULTS, LoopMode, MAX_FADE_DURATION, MAX_TEXTURE_SIZE, PACK_TEXELS, RIG_TEXELS, RIG_TEXELS_PER_SLOT, createVATPlaybackTexture, endsAt, makeVATTexture, resolveVATFrame, setVATInstance };
|
|
@@ -13,7 +13,7 @@ function needsBakedNormal(material) {
|
|
|
13
13
|
return NORMAL_READING_FLAGS.some((flag) => flags[flag] === true);
|
|
14
14
|
}
|
|
15
15
|
function assertBakedNormal(vat, material) {
|
|
16
|
-
if (vat.normalTexture !== null || !needsBakedNormal(material)) return;
|
|
16
|
+
if (vat.encoding !== "delta" || vat.normalTexture !== null || !needsBakedNormal(material)) return;
|
|
17
17
|
throw new Error(
|
|
18
18
|
`three-vat: material "${material.name || "(unnamed)"}" (${material.type}) shades from a normal, but this VAT was baked with \`bakeNormals: false\` and carries none \u2014 the crowd would be lit by its rest pose. Set \`flatShading: true\` on the material (three then derives the normal from the deformed position, per fragment, which is the right normal for a posed mesh), or use an unlit material such as MeshBasicMaterial, or bake with \`bakeNormals: true\`.`
|
|
19
19
|
);
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AnimationClip, AnimationAction, Object3D, TypedArray, TextureDataType, DataTexture } from 'three';
|
|
2
|
-
import { V as VAT } from './carrier-
|
|
3
|
-
export { E as EndMode, I as INFINITE_REPETITIONS, L as LoopMode, M as MAX_FADE_DURATION, a as
|
|
2
|
+
import { D as DeltaVAT, R as RigVAT, V as VAT } from './carrier-BXaLAPRO.js';
|
|
3
|
+
export { E as EndMode, I as INFINITE_REPETITIONS, L as LoopMode, M as MAX_FADE_DURATION, a as VATBase, b as VATCarrier, c as VATClip, d as VATClipDefaults, e as VATClock, f as VATCrowd, g as VATFadeFrom, h as VATFrame, i as VATInstance, j as VATPlaybackTexture, k as createVATPlaybackTexture, l as endsAt, r as resolveVATFrame, s as setVATInstance } from './carrier-BXaLAPRO.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* What {@link bakeVAT} takes for each animation: the clip itself, or an
|
|
@@ -37,8 +37,29 @@ interface BakeOptions {
|
|
|
37
37
|
* Anything else that shades — a smooth-shaded lit material — would light the
|
|
38
38
|
* crowd by its rest-pose normals, which is visibly wrong (ADR-0002). Both
|
|
39
39
|
* decode paths refuse that pairing loudly rather than render it.
|
|
40
|
+
*
|
|
41
|
+
* Accepted and ignored under the rig encoding, which has no normal texture to
|
|
42
|
+
* drop: normals come out of the skin matrix there. Refusing a no-op would
|
|
43
|
+
* punish the caller who switched encodings and left their options alone.
|
|
40
44
|
*/
|
|
41
45
|
bakeNormals?: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* What a frame row holds (ADR-0018). Default `'delta'`.
|
|
48
|
+
*
|
|
49
|
+
* - **`'delta'`** — the vertex encoding: where every vertex ended up, as a
|
|
50
|
+
* position delta and a normal. Source-agnostic — skinning, morph targets
|
|
51
|
+
* and node animation alike — and the default.
|
|
52
|
+
* - **`'rig'`** — the rig encoding: the posed rig, one **slot** per bone as a
|
|
53
|
+
* rotation, a translation and a uniform scale, skinned in the vertex shader
|
|
54
|
+
* from the rest-pose geometry. Two orders of magnitude smaller, no vertex
|
|
55
|
+
* ceiling, and unable to store what a rig cannot express — refused at the
|
|
56
|
+
* bake by name, before a frame is sampled: a morph target whose influence a
|
|
57
|
+
* baked clip animates, or a bone (or rigid part) scaled unevenly. A morph
|
|
58
|
+
* influence no clip animates is folded into the rest pose; a rigid,
|
|
59
|
+
* node-animated part is one slot of weight one; parts reading the same
|
|
60
|
+
* bones through the same bind matrix share slots.
|
|
61
|
+
*/
|
|
62
|
+
encoding?: 'delta' | 'rig';
|
|
42
63
|
}
|
|
43
64
|
/**
|
|
44
65
|
* Bake animations into a VAT by sampling the posed subtree frame by frame on
|
|
@@ -89,8 +110,22 @@ interface BakeOptions {
|
|
|
89
110
|
* approximation becomes visible, so the bake warns once, naming the bone.
|
|
90
111
|
* Renderer-agnostic — touches no WebGL/WebGPU context — so it runs identically
|
|
91
112
|
* at runtime, in a Web Worker, and in Node.
|
|
113
|
+
*
|
|
114
|
+
* All of that is the **vertex encoding**, the default. `encoding: 'rig'`
|
|
115
|
+
* stores the posed rig instead — one slot per bone, two texels, skinned in the
|
|
116
|
+
* vertex shader from the rest-pose geometry (ADR-0018) — under the same clip
|
|
117
|
+
* table and the same playback contract, at a fraction of the memory; see
|
|
118
|
+
* {@link BakeOptions.encoding} for what it refuses. Overloaded on the option's
|
|
119
|
+
* literal, so a call that names no encoding, or the vertex encoding, still
|
|
120
|
+
* holds the narrow {@link DeltaVAT} it always did.
|
|
92
121
|
*/
|
|
93
|
-
declare function bakeVAT(root: Object3D, animations: BakeInput[],
|
|
122
|
+
declare function bakeVAT(root: Object3D, animations: BakeInput[], options?: BakeOptions & {
|
|
123
|
+
encoding?: 'delta';
|
|
124
|
+
}): DeltaVAT;
|
|
125
|
+
declare function bakeVAT(root: Object3D, animations: BakeInput[], options: BakeOptions & {
|
|
126
|
+
encoding: 'rig';
|
|
127
|
+
}): RigVAT;
|
|
128
|
+
declare function bakeVAT(root: Object3D, animations: BakeInput[], options?: BakeOptions): VAT;
|
|
94
129
|
|
|
95
130
|
/**
|
|
96
131
|
* The WebGL2 *spec floor for high-end desktop*, which two things lean on.
|
|
@@ -117,4 +152,4 @@ declare const MAX_TEXTURE_SIZE = 16384;
|
|
|
117
152
|
*/
|
|
118
153
|
declare function makeVATTexture(data: TypedArray, width: number, height: number, type?: TextureDataType): DataTexture;
|
|
119
154
|
|
|
120
|
-
export { type BakeInput, type BakeOptions, MAX_TEXTURE_SIZE, VAT, bakeVAT, makeVATTexture };
|
|
155
|
+
export { type BakeInput, type BakeOptions, DeltaVAT, MAX_TEXTURE_SIZE, RigVAT, VAT, bakeVAT, makeVATTexture };
|