@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/head.js
DELETED
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Hold-and-move: how a head spends a conversation.
|
|
3
|
-
*
|
|
4
|
-
* Watch a person on a video call with the sound off and the head is almost
|
|
5
|
-
* never *moving*. It is held, and every second or two it goes somewhere else
|
|
6
|
-
* — a quick, decided move of a few degrees, a short settle, and then still
|
|
7
|
-
* again. Speech adds strokes on top: a nod on a stressed word, down and back,
|
|
8
|
-
* over in a third of a second. What it never does is glide, and gliding is
|
|
9
|
-
* the one thing a stack of smoothed envelopes can do. That stack is what this
|
|
10
|
-
* replaced: beats, a phrase drift and a lead-in, each a linear keyframe curve,
|
|
11
|
-
* summed and then low-passed at the head's 160 ms, drew a head in continuous
|
|
12
|
-
* motion from the first word to the last. A video reviewer called it a
|
|
13
|
-
* screensaver (a recorded call, reviewed 2026-09-12), and that is
|
|
14
|
-
* the right word: every part was a movement the literature measured, and the
|
|
15
|
-
* sum was a movement nobody makes.
|
|
16
|
-
*
|
|
17
|
-
* So this keeps the *events* the research found — a head that moves before the
|
|
18
|
-
* voice, beats on stressed vowels, the settle as a phrase ends — and changes
|
|
19
|
-
* what an event is:
|
|
20
|
-
*
|
|
21
|
-
* - A **move** takes the held pose somewhere new along a minimum-jerk path,
|
|
22
|
-
* the profile a practised human reach follows (Flash & Hogan 1985): it
|
|
23
|
-
* starts and stops at zero velocity and acceleration, and nearly all of its
|
|
24
|
-
* travel is in the middle. It arrives, and then the pose is exactly still.
|
|
25
|
-
* - A **stroke** is a pulse on top of the held pose: out fast, back a little
|
|
26
|
-
* slower, and nothing left over when it is done.
|
|
27
|
-
*
|
|
28
|
-
* Between those the output does not change at all, and that stillness is the
|
|
29
|
-
* point: it is what makes the moves read as decisions.
|
|
30
|
-
*
|
|
31
|
-
* Times are ms on whatever clock the owner keeps; this only needs it to be
|
|
32
|
-
* monotonic.
|
|
33
|
-
*/
|
|
34
|
-
|
|
35
|
-
/** Minimum-jerk position for a normalised time in [0, 1]. */
|
|
36
|
-
export const minJerk = (x) => (x <= 0 ? 0 : x >= 1 ? 1 : x * x * x * (10 + x * (-15 + 6 * x)));
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Fold `x` into ±`limit` without a corner: identity up to `KNEE` of the way
|
|
40
|
-
* there, then an exponential approach that reaches the limit only in the
|
|
41
|
-
* limit. It is memoryless — the same input gives the same output whenever it
|
|
42
|
-
* arrives — so nothing it touches is re-timed, which is what lets it sit in a
|
|
43
|
-
* chain whose curves are all authored against a known smoothing.
|
|
44
|
-
*
|
|
45
|
-
* A hard clamp was the obvious thing and is wrong here: what wants limiting is
|
|
46
|
-
* a sum of layers that each stay small and occasionally point the same way, so
|
|
47
|
-
* a clamp would be invisible for a minute and then hold the head perfectly
|
|
48
|
-
* still at the stop for half a second — the one thing a held pose must not do,
|
|
49
|
-
* because stillness is how this file says "decided". The knee sits at 0.7
|
|
50
|
-
* because below it the pose passes through untouched, and a recorded minute of
|
|
51
|
-
* either conversational state spends its median there.
|
|
52
|
-
*/
|
|
53
|
-
const KNEE = 0.7;
|
|
54
|
-
export const soften = (x, limit) => {
|
|
55
|
-
const a = KNEE * limit;
|
|
56
|
-
const m = Math.abs(x);
|
|
57
|
-
if (!(limit > 0) || m <= a) return x;
|
|
58
|
-
return Math.sign(x) * (a + (limit - a) * (1 - Math.exp(-(m - a) / (limit - a))));
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
export const HEAD_AXES = ['headYaw', 'headPitch', 'headRoll'];
|
|
62
|
-
const ZERO = Object.freeze({ headYaw: 0, headPitch: 0, headRoll: 0 });
|
|
63
|
-
|
|
64
|
-
export class HeadPose {
|
|
65
|
-
constructor() {
|
|
66
|
-
// The held pose as a list of moves, each starting where the one before it
|
|
67
|
-
// had got to. A move may be booked ahead of time (a head moves before the
|
|
68
|
-
// voice it anticipates), so the next one can be waiting while this one
|
|
69
|
-
// plays.
|
|
70
|
-
this._moves = [{ at: -Infinity, dur: 0, from: ZERO, to: ZERO }];
|
|
71
|
-
this._strokes = [];
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/** The pose the head will hold once every booked move has landed. */
|
|
75
|
-
get aim() {
|
|
76
|
-
return this._moves[this._moves.length - 1].to;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Go to `pose` (missing axes keep where they are), starting at `at` and
|
|
81
|
-
* arriving `dur` ms later. A move booked to start before one already
|
|
82
|
-
* booked replaces it: the later plan wins, from wherever the head will be.
|
|
83
|
-
*/
|
|
84
|
-
moveTo(pose, at, dur) {
|
|
85
|
-
while (this._moves.length > 1 && this._moves[this._moves.length - 1].at > at) this._moves.pop();
|
|
86
|
-
const from = this._held(at);
|
|
87
|
-
this._moves.push({ at, dur: Math.max(1, dur), from, to: { ...from, ...pose } });
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/** A pulse of `add` (per axis) that peaks `attack` ms after `at` and is gone `release` ms later. */
|
|
91
|
-
stroke(add, at, attack, release) {
|
|
92
|
-
this._strokes.push({ add, at, attack, release });
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/** Drop every stroke that has not begun by `now`; the ones under way finish. */
|
|
96
|
-
cancelStrokes(now) {
|
|
97
|
-
this._strokes = this._strokes.filter((s) => s.at <= now);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/** True when nothing is booked or playing after `now`: the head is holding. */
|
|
101
|
-
still(now) {
|
|
102
|
-
const m = this._moves[this._moves.length - 1];
|
|
103
|
-
return now >= m.at + m.dur && this._strokes.every((s) => now >= s.at + s.attack + s.release);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/** The head's offset at `now`, per axis. */
|
|
107
|
-
sample(now) {
|
|
108
|
-
// A move whose successor has started can no longer be seen.
|
|
109
|
-
while (this._moves.length > 1 && this._moves[1].at <= now) this._moves.shift();
|
|
110
|
-
this._strokes = this._strokes.filter((s) => now < s.at + s.attack + s.release);
|
|
111
|
-
const out = this._held(now);
|
|
112
|
-
for (const s of this._strokes) {
|
|
113
|
-
const t = now - s.at;
|
|
114
|
-
if (t <= 0) continue;
|
|
115
|
-
const e = t < s.attack ? minJerk(t / s.attack) : 1 - minJerk((t - s.attack) / s.release);
|
|
116
|
-
for (const k in s.add) out[k] += e * s.add[k];
|
|
117
|
-
}
|
|
118
|
-
return out;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/** The held pose at `t`, strokes left out: where the head *is*, not what it is doing. */
|
|
122
|
-
held(t) {
|
|
123
|
-
return this._held(t);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
_held(t) {
|
|
127
|
-
let m = this._moves[0];
|
|
128
|
-
for (const n of this._moves) if (n.at <= t) m = n;
|
|
129
|
-
const k = minJerk((t - m.at) / m.dur);
|
|
130
|
-
const out = {};
|
|
131
|
-
for (const c of HEAD_AXES) out[c] = m.from[c] + (m.to[c] - m.from[c]) * k;
|
|
132
|
-
return out;
|
|
133
|
-
}
|
|
134
|
-
}
|