@voqalize/avatar 0.4.4 → 0.5.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/README.md +65 -154
- package/dist/index.d.ts +37 -26
- package/dist/index.js +48 -25
- package/dist/pin.d.ts +2 -0
- package/dist/pin.js +3 -0
- package/dist/react.d.ts +21 -6
- package/dist/react.js +24 -6
- package/package.json +8 -67
- package/LICENSE-APACHE-2.0 +0 -201
- package/LICENSE-CC-BY-4.0 +0 -396
- package/assets/README.md +0 -60
- package/assets/tanvi.glb +0 -0
- package/assets/tanya.glb +0 -0
- package/assets/tara.glb +0 -0
- package/assets/tess.glb +0 -0
- package/assets/tushar.glb +0 -0
- package/client/Avatar.tsx +0 -57
- package/client/AvatarClient.ts +0 -818
- package/client/createAvatar.ts +0 -177
- package/client/index.ts +0 -44
- package/client/internal.ts +0 -132
- package/client/playout.ts +0 -95
- package/client/react.ts +0 -13
- package/client/supports.ts +0 -27
- package/client/three/assets.ts +0 -26
- package/client/three/budgets.ts +0 -27
- package/client/three/character-rig.ts +0 -1746
- package/client/three/createCharacter.ts +0 -109
- package/client/three/holds.ts +0 -69
- package/client/three/internal.ts +0 -55
- package/client/three/motion-limits.json +0 -124
- package/client/three/sequences.ts +0 -281
- package/client/three/tanvi-asset.ts +0 -6
- package/client/three/tanvi.ts +0 -30
- package/client/three/tanya-asset.ts +0 -6
- package/client/three/tanya.ts +0 -29
- package/client/three/tara-asset.ts +0 -25
- package/client/three/tara.ts +0 -36
- package/client/three/tess-asset.ts +0 -6
- package/client/three/tess.ts +0 -30
- package/client/three/tushar-asset.ts +0 -6
- package/client/three/tushar.ts +0 -28
- package/client/types.ts +0 -235
- package/client/useAvatar.ts +0 -74
- package/dist/Avatar.d.ts +0 -44
- package/dist/Avatar.d.ts.map +0 -1
- package/dist/Avatar.js +0 -7
- package/dist/Avatar.js.map +0 -1
- package/dist/AvatarClient.d.ts +0 -274
- package/dist/AvatarClient.d.ts.map +0 -1
- package/dist/AvatarClient.js +0 -712
- package/dist/AvatarClient.js.map +0 -1
- package/dist/createAvatar.d.ts +0 -135
- package/dist/createAvatar.d.ts.map +0 -1
- package/dist/createAvatar.js +0 -75
- package/dist/createAvatar.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/internal.d.ts +0 -34
- package/dist/internal.d.ts.map +0 -1
- package/dist/internal.js +0 -56
- package/dist/internal.js.map +0 -1
- package/dist/playout.d.ts +0 -42
- package/dist/playout.d.ts.map +0 -1
- package/dist/playout.js +0 -85
- package/dist/playout.js.map +0 -1
- package/dist/react.d.ts.map +0 -1
- package/dist/react.js.map +0 -1
- package/dist/supports.d.ts +0 -19
- package/dist/supports.d.ts.map +0 -1
- package/dist/supports.js +0 -25
- package/dist/supports.js.map +0 -1
- package/dist/three/assets.d.ts +0 -10
- package/dist/three/assets.d.ts.map +0 -1
- package/dist/three/assets.js +0 -23
- package/dist/three/assets.js.map +0 -1
- package/dist/three/budgets.d.ts +0 -17
- package/dist/three/budgets.d.ts.map +0 -1
- package/dist/three/budgets.js +0 -21
- package/dist/three/budgets.js.map +0 -1
- package/dist/three/character-rig.d.ts +0 -366
- package/dist/three/character-rig.d.ts.map +0 -1
- package/dist/three/character-rig.js +0 -1644
- package/dist/three/character-rig.js.map +0 -1
- package/dist/three/createCharacter.d.ts +0 -60
- package/dist/three/createCharacter.d.ts.map +0 -1
- package/dist/three/createCharacter.js +0 -84
- package/dist/three/createCharacter.js.map +0 -1
- package/dist/three/holds.d.ts +0 -38
- package/dist/three/holds.d.ts.map +0 -1
- package/dist/three/holds.js +0 -61
- package/dist/three/holds.js.map +0 -1
- package/dist/three/internal.d.ts +0 -52
- package/dist/three/internal.d.ts.map +0 -1
- package/dist/three/internal.js +0 -49
- package/dist/three/internal.js.map +0 -1
- package/dist/three/motion-limits.json +0 -124
- package/dist/three/sequences.d.ts +0 -71
- package/dist/three/sequences.d.ts.map +0 -1
- package/dist/three/sequences.js +0 -262
- package/dist/three/sequences.js.map +0 -1
- package/dist/three/tanvi-asset.d.ts +0 -7
- package/dist/three/tanvi-asset.d.ts.map +0 -1
- package/dist/three/tanvi-asset.js +0 -7
- package/dist/three/tanvi-asset.js.map +0 -1
- package/dist/three/tanvi.d.ts +0 -24
- package/dist/three/tanvi.d.ts.map +0 -1
- package/dist/three/tanvi.js +0 -24
- package/dist/three/tanvi.js.map +0 -1
- package/dist/three/tanya-asset.d.ts +0 -7
- package/dist/three/tanya-asset.d.ts.map +0 -1
- package/dist/three/tanya-asset.js +0 -7
- package/dist/three/tanya-asset.js.map +0 -1
- package/dist/three/tanya.d.ts +0 -23
- package/dist/three/tanya.d.ts.map +0 -1
- package/dist/three/tanya.js +0 -23
- package/dist/three/tanya.js.map +0 -1
- package/dist/three/tara-asset.d.ts +0 -26
- package/dist/three/tara-asset.d.ts.map +0 -1
- package/dist/three/tara-asset.js +0 -26
- package/dist/three/tara-asset.js.map +0 -1
- package/dist/three/tara.d.ts +0 -30
- package/dist/three/tara.d.ts.map +0 -1
- package/dist/three/tara.js +0 -30
- package/dist/three/tara.js.map +0 -1
- package/dist/three/tess-asset.d.ts +0 -7
- package/dist/three/tess-asset.d.ts.map +0 -1
- package/dist/three/tess-asset.js +0 -7
- package/dist/three/tess-asset.js.map +0 -1
- package/dist/three/tess.d.ts +0 -24
- package/dist/three/tess.d.ts.map +0 -1
- package/dist/three/tess.js +0 -24
- package/dist/three/tess.js.map +0 -1
- package/dist/three/tushar-asset.d.ts +0 -7
- package/dist/three/tushar-asset.d.ts.map +0 -1
- package/dist/three/tushar-asset.js +0 -7
- package/dist/three/tushar-asset.js.map +0 -1
- package/dist/three/tushar.d.ts +0 -22
- package/dist/three/tushar.d.ts.map +0 -1
- package/dist/three/tushar.js +0 -22
- package/dist/three/tushar.js.map +0 -1
- package/dist/types.d.ts +0 -149
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -140
- package/dist/types.js.map +0 -1
- package/dist/useAvatar.d.ts +0 -39
- package/dist/useAvatar.d.ts.map +0 -1
- package/dist/useAvatar.js +0 -35
- package/dist/useAvatar.js.map +0 -1
- package/src/avatar.d.ts +0 -436
- package/src/avatar.js +0 -1378
- package/src/behavior.d.ts +0 -42
- package/src/behavior.js +0 -114
- package/src/camera.js +0 -29
- package/src/clips.js +0 -155
- package/src/conformance.js +0 -119
- package/src/emotions.js +0 -58
- package/src/face-core.js +0 -180
- package/src/face-myna.d.ts +0 -7
- package/src/face-myna.js +0 -786
- package/src/face-peep-control-plane.js +0 -167
- package/src/face-peep.d.ts +0 -7
- package/src/face-peep.js +0 -925
- package/src/face-wren.d.ts +0 -7
- package/src/face-wren.js +0 -468
- package/src/faces.d.ts +0 -12
- package/src/faces.js +0 -53
- package/src/gaze.js +0 -504
- package/src/hand.js +0 -709
- package/src/head.js +0 -134
- package/src/idle.js +0 -668
- package/src/interjections.js +0 -747
- package/src/line-art.js +0 -137
- package/src/params.js +0 -180
- package/src/perform.js +0 -107
- package/src/prosody.js +0 -741
- package/src/rig.d.ts +0 -31
- package/src/rig.js +0 -32
- package/src/speech-timing.js +0 -51
- package/src/visemes.js +0 -410
package/src/face-core.js
DELETED
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
// ---------------------------------------------------------------------------
|
|
2
|
-
// face-core — the part of a face module that is not the face.
|
|
3
|
-
//
|
|
4
|
-
// Three avatars were built independently before this module existed, and their
|
|
5
|
-
// renderers converged on the same shape: an element table, a memoized attribute
|
|
6
|
-
// writer, and an apply() that runs torso lean → shoulders → parallax → eyes →
|
|
7
|
-
// brows → mouth → teeth → tongue. The geometry differs per character; the
|
|
8
|
-
// plumbing and the pose mechanics do not. This module absorbs the proven-
|
|
9
|
-
// identical parts, so a face module supplies art and feature geometry and gets
|
|
10
|
-
// the body mechanics for free.
|
|
11
|
-
//
|
|
12
|
-
// What lives here is exactly what those faces shared line-for-line, or differed
|
|
13
|
-
// in only by a named scalar. Anything a character has an opinion about — what
|
|
14
|
-
// an eye is, how a mouth is drawn — stays in the face module. Two of the three
|
|
15
|
-
// have since been retired; what they proved about the seam is why this file
|
|
16
|
-
// looks the way it does, and helpers only they used went with them.
|
|
17
|
-
// ---------------------------------------------------------------------------
|
|
18
|
-
|
|
19
|
-
import { clamp } from './params.js';
|
|
20
|
-
|
|
21
|
-
/** Attribute-value number formatter: 2 decimal places, no trailing zeros. */
|
|
22
|
-
export const f = (n) => (Math.round(n * 100) / 100).toString();
|
|
23
|
-
|
|
24
|
-
// Constants every rig agreed on. Named here so a new avatar inherits the
|
|
25
|
-
// agreement instead of re-deriving it.
|
|
26
|
-
export const LEAN_SCALE = 0.055; // scale gain at torsoLean = 1
|
|
27
|
-
export const ROLL_TORSO = 1.5; // degrees of roll the torso follows…
|
|
28
|
-
export const ROLL_HEAD = 5.5; // …versus what the head itself takes.
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Mount the static markup and return the per-instance tools: the svg root, an
|
|
32
|
-
* id-scoped selector for building the element table, and the memoized `set`.
|
|
33
|
-
* SVG attribute setting is the hot path; `set` skips redundant DOM writes.
|
|
34
|
-
*/
|
|
35
|
-
export function createFaceShell(mount, id, markupHtml) {
|
|
36
|
-
mount.innerHTML = markupHtml;
|
|
37
|
-
const svg = mount.querySelector(`#${id}`);
|
|
38
|
-
const $ = (n) => svg.querySelector(`#${id}-${n}`);
|
|
39
|
-
const prev = new Map();
|
|
40
|
-
const set = (node, attr, val) => {
|
|
41
|
-
const k = node.id + attr;
|
|
42
|
-
if (prev.get(k) === val) return;
|
|
43
|
-
prev.set(k, val);
|
|
44
|
-
node.setAttribute(attr, val);
|
|
45
|
-
};
|
|
46
|
-
return { svg, $, set };
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/** The one return shape every face honours: { svg, apply, theme, destroy }. */
|
|
50
|
-
export function faceApi(mount, svg, apply, theme) {
|
|
51
|
-
return { svg, apply, theme, destroy: () => { mount.innerHTML = ''; } };
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Blocks A–C of every apply(): torso lean, shoulders, and the layer parallax
|
|
56
|
-
* loop. `spec` is a module-level constant in the face module:
|
|
57
|
-
*
|
|
58
|
-
* leanTravel px of downward travel at torsoLean = 1
|
|
59
|
-
* leanPivot {x, y} the scale pivot — behind the head, not the frame base:
|
|
60
|
-
* scaling about the bottom makes the head rise as it grows,
|
|
61
|
-
* which reads as standing up instead of leaning in
|
|
62
|
-
* shrugLift px of shoulder lift at shrug = 1
|
|
63
|
-
* shrugTiltDeg degrees of one-sided-shrug rotation at tilt = 1 — a per-rig
|
|
64
|
-
* judgement about how much the collar can cover, not taste
|
|
65
|
-
* shrugPivot {x, y} the sternum
|
|
66
|
-
* yawPx px of head travel at headYaw = 1
|
|
67
|
-
* pitchPx px at headPitch = 1
|
|
68
|
-
* pitch optional corrective-pose contract for rigs that can nod:
|
|
69
|
-
* `{ headLayers, neckLayer, hinge, headTravel, neckTravel,
|
|
70
|
-
* foreshorten, neckCompress, neckBase }`.
|
|
71
|
-
* `headLayers` must be separate SVG groups for the skull and
|
|
72
|
-
* its attached surface layers; `neckLayer` must be behind it.
|
|
73
|
-
* This is intentionally a small group-level contract, not a
|
|
74
|
-
* second set of authored paths per expression.
|
|
75
|
-
* pivot {x, y} roll pivot — the base of the neck, not the chin:
|
|
76
|
-
* rotating about the chin swings the whole cranium sideways
|
|
77
|
-
* and reads as a puppet on a stick
|
|
78
|
-
* breathSwell fractional scale of the torso layers at breath = 1, about
|
|
79
|
-
* `swellPivot`. Required. It replaced a rigid vertical bob of
|
|
80
|
-
* the whole shirt, which moved the hem — and the hem is the one
|
|
81
|
-
* part of a seated torso that does not move, so the result read
|
|
82
|
-
* as the figure being nudged up and down rather than as breath.
|
|
83
|
-
* A scale about the hem raises the shoulder line and widens the
|
|
84
|
-
* chest, which is what an inbreath does and is the only breath
|
|
85
|
-
* cue a head-and-shoulders crop can actually show.
|
|
86
|
-
* swellPivot {x, y} the hem — bottom of the frame, on the midline
|
|
87
|
-
* turnPx px of lateral trunk travel at torsoTurn = 1 (0 if the rig
|
|
88
|
-
* does not declare it)
|
|
89
|
-
* layers draw-order list of layer names in the element table
|
|
90
|
-
* parallax {layer: multiplier} — follows the art, not a standard
|
|
91
|
-
* torsoLayers the subset of `layers` that moves at torso speed
|
|
92
|
-
* units the rig's linear scale factor relative to the numbers above
|
|
93
|
-
* (1 where travels are already in the rig's own units). Kept as
|
|
94
|
-
* a separate factor, applied last, so a rig built by scaling
|
|
95
|
-
* another's numbers states that lineage — and so evaluation
|
|
96
|
-
* order matches code that wrote `travel * 9 * S` longhand.
|
|
97
|
-
* Degrees never take it: degrees are degrees at any scale.
|
|
98
|
-
*
|
|
99
|
-
* In a webcam frame a lean is read almost entirely as a change of scale, so
|
|
100
|
-
* that is how it is drawn.
|
|
101
|
-
*/
|
|
102
|
-
export function poseTransforms(p, set, el, spec) {
|
|
103
|
-
const u = spec.units;
|
|
104
|
-
const lean = p.torsoLean;
|
|
105
|
-
const leanT = lean
|
|
106
|
-
? `translate(0 ${f(lean * spec.leanTravel * u)}) `
|
|
107
|
-
+ `translate(${f(spec.leanPivot.x)} ${f(spec.leanPivot.y)}) `
|
|
108
|
-
+ `scale(${f(1 + lean * LEAN_SCALE)}) `
|
|
109
|
-
+ `translate(${f(-spec.leanPivot.x)} ${f(-spec.leanPivot.y)}) `
|
|
110
|
-
: '';
|
|
111
|
-
|
|
112
|
-
// One shoulder cannot rise without the other when the shirt is a single
|
|
113
|
-
// path. A small rotation about the sternum is what a one-sided shrug looks
|
|
114
|
-
// like anyway, and it needs no new geometry.
|
|
115
|
-
const shrug = (p.shoulderL + p.shoulderR) * 0.5;
|
|
116
|
-
const tilt = (p.shoulderR - p.shoulderL) * 0.5;
|
|
117
|
-
|
|
118
|
-
// Breath as chest expansion. The swell scales the torso layers about the
|
|
119
|
-
// hem, so the shoulder line rises and the chest widens while the bottom of
|
|
120
|
-
// the shirt stays put. The head then has to ride whatever the shoulders did
|
|
121
|
-
// or the neck telescopes — and that lift is not a tuned constant, it is
|
|
122
|
-
// arithmetic: the swell's vertical displacement at the neck pivot. One
|
|
123
|
-
// number to author, and the two layers cannot drift out of agreement.
|
|
124
|
-
const swell = spec.breathSwell ? p.breath * spec.breathSwell : 0;
|
|
125
|
-
const neckLift = swell ? swell * (spec.swellPivot.y - spec.pivot.y) : 0;
|
|
126
|
-
const swellT = swell
|
|
127
|
-
? `translate(${f(spec.swellPivot.x)} ${f(spec.swellPivot.y)}) `
|
|
128
|
-
+ `scale(${f(1 + swell)}) `
|
|
129
|
-
+ `translate(${f(-spec.swellPivot.x)} ${f(-spec.swellPivot.y)}) `
|
|
130
|
-
: '';
|
|
131
|
-
|
|
132
|
-
const torsoT = `translate(${f(p.torsoTurn * (spec.turnPx || 0) * u)} ${f(-shrug * spec.shrugLift * u)}) `
|
|
133
|
-
+ `rotate(${f(-tilt * spec.shrugTiltDeg)} ${f(spec.shrugPivot.x)} ${f(spec.shrugPivot.y)}) `
|
|
134
|
-
+ swellT;
|
|
135
|
-
|
|
136
|
-
const yx = p.headYaw * spec.yawPx;
|
|
137
|
-
const py = p.headPitch * spec.pitchPx;
|
|
138
|
-
const pitch = spec.pitch;
|
|
139
|
-
for (const key of spec.layers) {
|
|
140
|
-
const k = spec.parallax[key];
|
|
141
|
-
const torso = spec.torsoLayers.includes(key);
|
|
142
|
-
const roll = torso ? p.headRoll * ROLL_TORSO : p.headRoll * ROLL_HEAD;
|
|
143
|
-
const isPitchHead = !!pitch && pitch.headLayers.includes(key);
|
|
144
|
-
const isPitchNeck = !!pitch && pitch.neckLayer === key;
|
|
145
|
-
// A pitch-capable rig makes its skull, features and hair move together:
|
|
146
|
-
// their old parallax values still apply to yaw, but not to the vertical
|
|
147
|
-
// nod. That coherence is the point of separating them from the neck.
|
|
148
|
-
const pitchTravel = isPitchHead ? pitch.headTravel
|
|
149
|
-
: isPitchNeck ? pitch.neckTravel : k;
|
|
150
|
-
const pitchScale = isPitchHead
|
|
151
|
-
? 1 - Math.max(0, p.headPitch) * pitch.foreshorten : 1;
|
|
152
|
-
const neckScale = isPitchNeck
|
|
153
|
-
? 1 - Math.max(0, p.headPitch) * pitch.neckCompress : 1;
|
|
154
|
-
const pitchT = pitchScale !== 1
|
|
155
|
-
? `translate(${f(pitch.hinge.x)} ${f(pitch.hinge.y)}) scale(1 ${f(pitchScale)}) translate(${f(-pitch.hinge.x)} ${f(-pitch.hinge.y)}) `
|
|
156
|
-
: '';
|
|
157
|
-
const neckT = neckScale !== 1
|
|
158
|
-
? `translate(${f(pitch.neckBase.x)} ${f(pitch.neckBase.y)}) scale(1 ${f(neckScale)}) translate(${f(-pitch.neckBase.x)} ${f(-pitch.neckBase.y)}) `
|
|
159
|
-
: '';
|
|
160
|
-
// Torso layers get their breath from the swell inside torsoT; head layers
|
|
161
|
-
// get the matching lift, which is derived from the swell rather than tuned
|
|
162
|
-
// separately — the neck rides on the chest it sits on.
|
|
163
|
-
const bob = torso ? 0 : -neckLift;
|
|
164
|
-
set(el[key], 'transform',
|
|
165
|
-
leanT + (torso ? torsoT : '')
|
|
166
|
-
+ pitchT + neckT
|
|
167
|
-
+ `translate(${f(yx * k)} ${f(py * pitchTravel + bob)}) rotate(${f(roll)} ${f(spec.pivot.x)} ${f(spec.pivot.y)})`);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Upper-and-lower teeth pair (peep, wren). Lower teeth appear only once
|
|
173
|
-
* the mouth is genuinely open: below that the lower lip is over them and
|
|
174
|
-
* drawing them turns every mid-open viseme into a grin; above it, their
|
|
175
|
-
* absence is what made viseme D read as a cave.
|
|
176
|
-
*/
|
|
177
|
-
export function pairedTeeth(p, set, el, teethPath, m) {
|
|
178
|
-
set(el.teeth, 'd', teethPath(m, clamp(p.teethUpper), false));
|
|
179
|
-
set(el.teethLo, 'd', teethPath(m, clamp(p.teethUpper) * clamp((m.open - 0.45) / 0.4), true));
|
|
180
|
-
}
|
package/src/face-myna.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { AvatarMeta, Face, FaceFactory } from "./avatar.js";
|
|
2
|
-
|
|
3
|
-
export const createFace: FaceFactory;
|
|
4
|
-
export const META: AvatarMeta;
|
|
5
|
-
/** Default palette. Passed as `createAvatar({ theme })`; see authoring-a-face.md. */
|
|
6
|
-
export const THEME: Readonly<Record<string, string>>;
|
|
7
|
-
export const myna: Face;
|