three-mediapipe-rig 0.1.1 → 0.1.3

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.
Files changed (40) hide show
  1. package/README.md +8 -4
  2. package/dist/face-tracker-utils-xt9__vBF.js +16 -0
  3. package/dist/meshcap/atlas-builder.d.ts +10 -0
  4. package/dist/meshcap/atlas-builder.d.ts.map +1 -0
  5. package/dist/meshcap/audio.d.ts +27 -0
  6. package/dist/meshcap/audio.d.ts.map +1 -0
  7. package/dist/meshcap/constants.d.ts +3 -0
  8. package/dist/meshcap/constants.d.ts.map +1 -0
  9. package/dist/meshcap/material.d.ts +75 -0
  10. package/dist/meshcap/material.d.ts.map +1 -0
  11. package/dist/meshcap/meshcap.d.ts +6 -0
  12. package/dist/meshcap/meshcap.d.ts.map +1 -0
  13. package/dist/meshcap/parse-mcap-file.d.ts +8 -0
  14. package/dist/meshcap/parse-mcap-file.d.ts.map +1 -0
  15. package/dist/meshcap/types.d.ts +88 -0
  16. package/dist/meshcap/types.d.ts.map +1 -0
  17. package/dist/meshcap/write-mcap-file.d.ts +3 -0
  18. package/dist/meshcap/write-mcap-file.d.ts.map +1 -0
  19. package/dist/meshcap.d.ts +2 -0
  20. package/dist/meshcap.js +468 -0
  21. package/dist/module.d.ts +1 -0
  22. package/dist/module.d.ts.map +1 -1
  23. package/dist/rigger.d.ts +2 -0
  24. package/dist/rigger.js +864 -0
  25. package/dist/tracking/BoneMapping.d.ts.map +1 -1
  26. package/dist/tracking/FaceTracker.d.ts +12 -2
  27. package/dist/tracking/FaceTracker.d.ts.map +1 -1
  28. package/dist/tracking/HandTracker.d.ts +3 -3
  29. package/dist/tracking/HandTracker.d.ts.map +1 -1
  30. package/dist/tracking/PoseTracker.d.ts +1 -1
  31. package/dist/tracking/PoseTracker.d.ts.map +1 -1
  32. package/dist/tracking/TrackerManager.d.ts +126 -0
  33. package/dist/tracking/TrackerManager.d.ts.map +1 -0
  34. package/dist/tracking/recoding/recorder.d.ts +10 -8
  35. package/dist/tracking/recoding/recorder.d.ts.map +1 -1
  36. package/dist/tracking/util/face-tracker-utils.d.ts +9 -0
  37. package/dist/tracking/util/face-tracker-utils.d.ts.map +1 -0
  38. package/package.json +16 -10
  39. package/dist/three-mediapipe-rig.js +0 -839
  40. package/dist/three-mediapipe-rig.js.map +0 -1
package/dist/rigger.js ADDED
@@ -0,0 +1,864 @@
1
+ var Pe = Object.defineProperty;
2
+ var Ee = (h, o, e) => o in h ? Pe(h, o, { enumerable: !0, configurable: !0, writable: !0, value: e }) : h[o] = e;
3
+ var R = (h, o, e) => Ee(h, typeof o != "symbol" ? o + "" : o, e);
4
+ import { PoseLandmarker as Le, HandLandmarker as G, FaceLandmarker as j, FilesetResolver as We, DrawingUtils as ge } from "@mediapipe/tasks-vision";
5
+ import * as p from "three/webgpu";
6
+ import { Vector3 as b, Quaternion as ke, VideoTexture as Z, SRGBColorSpace as J, MeshPhysicalNodeMaterial as Fe } from "three/webgpu";
7
+ import * as C from "three";
8
+ import { Bone as Ae } from "three";
9
+ import { uniform as D, attribute as Se, instancedArray as Me, varying as Ve, vec3 as Ne, float as Oe, texture as Te, vec2 as _e } from "three/tsl";
10
+ import { c as Ce, F as De } from "./face-tracker-utils-xt9__vBF.js";
11
+ import { GLTFExporter as ze } from "three/examples/jsm/Addons.js";
12
+ const U = new b(), ee = new b(), Be = new b(1, 0, 0), Ue = new b(-1, 0, 0), Ie = new b(0, 1, 0), He = new b(0, -1, 0), te = new b(0, 0, 1);
13
+ new b(0, 0, -1);
14
+ const oe = new b(), Ge = new b(), je = new b(), se = new ke(), I = new ke();
15
+ function S(h, o, e, t = "+x") {
16
+ h.lookAt(o);
17
+ const s = t == "+x" ? Be : t == "-x" ? Ue : t == "+y" ? Ie : He;
18
+ h.getWorldPosition(ee), h.getWorldQuaternion(I), U.subVectors(e, ee).normalize(), oe.copy(s).applyQuaternion(I);
19
+ const n = oe, d = Ge.copy(te).applyQuaternion(I), i = U.clone().addScaledVector(d, -U.dot(d)).normalize(), r = je.crossVectors(n, i), m = Math.atan2(r.dot(d), n.dot(i));
20
+ se.setFromAxisAngle(te, m), h.quaternion.multiply(se);
21
+ }
22
+ const z = new p.Vector3(), O = new p.Vector3(), H = new p.Vector3();
23
+ new p.Vector3();
24
+ class q {
25
+ constructor(o, e) {
26
+ R(this, "objectGhost");
27
+ R(this, "root");
28
+ /**
29
+ * per landmark index, it points to it's object3D equivalent.
30
+ */
31
+ R(this, "marks", {});
32
+ this.points = o, this.debugConnections = e, this.root = new p.Object3D(), this.objectGhost = /* @__PURE__ */ new Map();
33
+ for (let t in this.points)
34
+ this.marks[t] = new qe(), this.root.add(this.marks[t]);
35
+ }
36
+ updateLandmarks(o, e, t) {
37
+ for (let s in this.points) {
38
+ const n = this.points[s], d = this.marks[s];
39
+ d && (n instanceof Array ? (z.copy(o[n[0]]), d.position.copy(o[n[1]]).sub(z).divideScalar(2).add(o[n[0]]), n.length == 4 && (z.subVectors(
40
+ o[n[3]],
41
+ o[n[2]]
42
+ ).divideScalar(2).add(o[n[2]]).sub(d.position).divideScalar(2), d.position.add(z))) : d.position.copy(o[n]));
43
+ }
44
+ t && e && t.drawConnectors(
45
+ e,
46
+ this.debugConnections,
47
+ {
48
+ lineWidth: 1
49
+ }
50
+ );
51
+ }
52
+ getGhost(o) {
53
+ var e;
54
+ if (!this.objectGhost.has(o)) {
55
+ const t = new $e();
56
+ t.position.copy(o.position), t.quaternion.copy(o.quaternion), (e = o.parent) == null || e.add(t), this.objectGhost.set(o, t);
57
+ }
58
+ return this.objectGhost.get(o);
59
+ }
60
+ predict(o, e) {
61
+ throw new Error("Method 'predict' must be implemented.");
62
+ }
63
+ sync(o, e) {
64
+ throw new Error("Method 'sync' must be implemented.");
65
+ }
66
+ test(o) {
67
+ this.marks[o].position.set(1, 2, 3);
68
+ }
69
+ syncObjects(o, e, t) {
70
+ for (const [s, n, d, i] of o) {
71
+ this.marks[d].getWorldPosition(H), this.marks[n].getWorldPosition(O);
72
+ const r = H.sub(O);
73
+ s.getWorldPosition(O), O.add(r);
74
+ const m = O, l = s.getWorldPosition(H).sub(t), u = this.getGhost(s);
75
+ S(u, m, l, i), u.rotateX(Math.PI / 2), s.position.lerp(u.position, e * 4), s.quaternion.slerp(u.quaternion, e * 4);
76
+ }
77
+ }
78
+ getBone(o, e) {
79
+ return o.getObjectByName(e.replace(/[\.\:]/g, ""));
80
+ }
81
+ }
82
+ class qe extends p.Mesh {
83
+ constructor() {
84
+ super(new p.SphereGeometry(0.01, 3, 3), new p.MeshStandardMaterial({ color: 16711680, wireframe: !0 }));
85
+ R(this, "_worldPosition", new p.Vector3());
86
+ this.add(new p.AxesHelper(1e-3));
87
+ }
88
+ get worldPosition() {
89
+ return this.getWorldPosition(this._worldPosition), this._worldPosition;
90
+ }
91
+ }
92
+ class $e extends p.Object3D {
93
+ lerp(o, e, t = 8) {
94
+ o.position.lerp(this.position, e * t), o.quaternion.slerp(this.quaternion, e * t);
95
+ }
96
+ }
97
+ function A(h, o, e) {
98
+ return e.worldToLocal(o.getWorldPosition(h)), h;
99
+ }
100
+ function Ke(h) {
101
+ return h.replace(/[\.\:]/g, "");
102
+ }
103
+ function P(h, o) {
104
+ let e;
105
+ return o = Ke(o), h.traverse((t) => {
106
+ t.name.indexOf(o) === 0 && t instanceof Ae && (e = t);
107
+ }), e || console.log("Bone not found: ", o, h.name), e;
108
+ }
109
+ async function Xe(h, o) {
110
+ const e = await Le.createFromOptions(h, {
111
+ baseOptions: {
112
+ modelAssetPath: (o == null ? void 0 : o.modelPath) ?? "pose_landmarker_lite.task",
113
+ //modelAssetPath: `https://storage.googleapis.com/mediapipe-models/pose_landmarker/pose_landmarker_lite/float16/1/pose_landmarker_lite.task`,
114
+ //modelAssetPath: "https://storage.googleapis.com/mediapipe-models/pose_landmarker/pose_landmarker_heavy/float16/latest/pose_landmarker_heavy.task",
115
+ delegate: "GPU"
116
+ },
117
+ runningMode: "VIDEO",
118
+ numPoses: 1
119
+ });
120
+ return new tt(e, o);
121
+ }
122
+ const Qe = {
123
+ hips: [24, 23],
124
+ neck: [12, 11],
125
+ leftLeg: 23,
126
+ leftKnee: 25,
127
+ leftFoot: 27,
128
+ leftToes: 31,
129
+ leftArm: 11,
130
+ leftElbow: 13,
131
+ leftWrist: 15,
132
+ rightLeg: 24,
133
+ rightKnee: 26,
134
+ rightFoot: 28,
135
+ rightToes: 32,
136
+ rightArm: 12,
137
+ rightElbow: 14,
138
+ rightWrist: 16,
139
+ head: [8, 7],
140
+ mouth: [10, 9],
141
+ torso: [24, 23, 12, 11],
142
+ leftEar: 7,
143
+ rightEar: 8
144
+ }, Ye = new p.Vector3(), ne = new p.Vector3(), Ze = new p.Vector3(), Je = new p.Vector3(), et = new p.Vector3(), ie = new p.Vector3(), re = new p.Vector3();
145
+ class tt extends q {
146
+ constructor(e, t) {
147
+ super(Qe, Le.POSE_CONNECTIONS);
148
+ R(this, "_leftWristNormalizedPosition");
149
+ R(this, "_rightWristNormalizedPosition");
150
+ this.poseLandmarker = e, this.config = t, this.root.scale.y *= -2, this.root.scale.z *= -2, this.root.scale.x *= 2;
151
+ }
152
+ /**
153
+ * Position of the left wrist in normalized coordinates (0..1)
154
+ */
155
+ get leftWristNormalizedPosition() {
156
+ return this._leftWristNormalizedPosition;
157
+ }
158
+ /**
159
+ * Position of the right wrist in normalized coordinates (0..1)
160
+ */
161
+ get rightWristNormalizedPosition() {
162
+ return this._rightWristNormalizedPosition;
163
+ }
164
+ predict(e, t) {
165
+ this.poseLandmarker.detectForVideo(e, performance.now(), (s) => {
166
+ var n;
167
+ s.landmarks.length != 0 && (this.updateLandmarks(s.worldLandmarks[0], ((n = this.config) == null ? void 0 : n.drawLandmarks) === !1 ? void 0 : s.landmarks[0], t), this._leftWristNormalizedPosition = s.landmarks[0][this.points.leftWrist], this._rightWristNormalizedPosition = s.landmarks[0][this.points.rightWrist]);
168
+ });
169
+ }
170
+ // override sync ( delta:number, objects: BoneBinding[] ) {
171
+ // const hipsPos = this.marks.hips.getWorldPosition(C);
172
+ // this.marks.rightArm.getWorldPosition(A).sub(hipsPos);
173
+ // this.marks.leftArm.getWorldPosition(B).sub(hipsPos);
174
+ // const torsoNormal = C.crossVectors(A,B);
175
+ // this.syncObjects(objects, delta, torsoNormal);
176
+ // }
177
+ bind(e, t) {
178
+ var r;
179
+ const s = {
180
+ hips: P(e, t.hips),
181
+ neck: P(e, t.neck),
182
+ leftArm: P(e, t.armL),
183
+ leftElbow: P(e, t.forearmL),
184
+ leftWrist: P(e, t.handL),
185
+ rightArm: P(e, t.armR),
186
+ rightElbow: P(e, t.forearmR),
187
+ rightWrist: P(e, t.handR),
188
+ head: P(e, t.head),
189
+ torso: P(e, t.torso),
190
+ leftLeg: P(e, t.thighL),
191
+ leftKnee: P(e, t.shinL),
192
+ leftFoot: P(e, t.footL),
193
+ rightLeg: P(e, t.thighR),
194
+ rightKnee: P(e, t.shinR),
195
+ rightFoot: P(e, t.footR)
196
+ };
197
+ (r = this.config) != null && r.ignoreLegs && (delete s.leftLeg, delete s.leftKnee, delete s.leftFoot, delete s.leftToes, delete s.rightLeg, delete s.rightKnee, delete s.rightFoot, delete s.rightToes);
198
+ const n = new p.Vector3(), d = new p.Vector3(), i = (m, l, u, y, x, W) => {
199
+ if (!l) return;
200
+ const a = this.marks[y].getWorldPosition(n).sub(this.marks[u].getWorldPosition(d)).normalize();
201
+ A(ie, l, e).add(a).applyMatrix4(e.matrixWorld), A(re, l, e).add(x).applyMatrix4(e.matrixWorld);
202
+ const c = this.getGhost(l);
203
+ S(c, ie, re, W), c.rotateX(Math.PI / 2), c.lerp(l, m);
204
+ };
205
+ return {
206
+ update: (m) => {
207
+ const l = this.marks.leftLeg.getWorldPosition(Ye).sub(this.marks.rightLeg.getWorldPosition(ne)).normalize(), u = this.marks.leftArm.getWorldPosition(ne).sub(this.marks.rightArm.getWorldPosition(Ze)).normalize(), y = this.marks.leftEar.getWorldPosition(Je).sub(this.marks.rightEar.getWorldPosition(et)).normalize();
208
+ i(m, s.hips, "hips", "torso", l, "+x"), i(m, s.torso, "torso", "neck", u, "+x"), i(m, s.neck, "neck", "head", y, "+x"), i(m, s.head, "neck", "head", y, "+x"), i(m, s.leftArm, "leftArm", "leftElbow", u, "-x"), i(m, s.leftElbow, "leftElbow", "leftWrist", u, "-x"), i(m, s.leftLeg, "leftLeg", "leftKnee", l, "+x"), i(m, s.leftKnee, "leftKnee", "leftFoot", l, "+x"), i(m, s.leftFoot, "leftFoot", "leftToes", l, "+x"), i(m, s.rightArm, "rightArm", "rightElbow", u, "-x"), i(m, s.rightElbow, "rightElbow", "rightWrist", u, "-x"), i(m, s.rightLeg, "rightLeg", "rightKnee", l, "+x"), i(m, s.rightKnee, "rightKnee", "rightFoot", l, "+x"), i(m, s.rightFoot, "rightFoot", "rightToes", l, "+x");
209
+ }
210
+ };
211
+ }
212
+ }
213
+ const ae = new p.Vector2(), de = new p.Vector2();
214
+ async function ot(h, o) {
215
+ const e = await G.createFromOptions(h, {
216
+ baseOptions: {
217
+ modelAssetPath: o.modelPath ?? "hand_landmarker.task",
218
+ //modelAssetPath: `https://storage.googleapis.com/mediapipe-models/hand_landmarker/hand_landmarker/float16/1/hand_landmarker.task`,
219
+ delegate: "GPU"
220
+ },
221
+ runningMode: "VIDEO",
222
+ numHands: 2
223
+ }), t = (s, n, d) => {
224
+ try {
225
+ ae.copy(s()), de.copy(n());
226
+ } catch (i) {
227
+ return console.warn("No pose data... will just be optimitic and say yes to everything.", i), !0;
228
+ }
229
+ return ae.distanceTo(d) < de.distanceTo(d);
230
+ };
231
+ return {
232
+ left: new we(e, "Left", t.bind(null, o.leftWrist, o.rightWrist), o.drawLandmarks),
233
+ right: new we(e, "Right", t.bind(null, o.rightWrist, o.leftWrist), o.drawLandmarks)
234
+ };
235
+ }
236
+ const st = {
237
+ wrist: 0,
238
+ palm: [9, 13],
239
+ thumb1: 1,
240
+ thumb2: 2,
241
+ thumb3: 3,
242
+ thumb4: 4,
243
+ index1: 5,
244
+ index2: 6,
245
+ index3: 7,
246
+ index4: 8,
247
+ middle1: 9,
248
+ middle2: 10,
249
+ middle3: 11,
250
+ middle4: 12,
251
+ ring1: 13,
252
+ ring2: 14,
253
+ ring3: 15,
254
+ ring4: 16,
255
+ pinky1: 17,
256
+ pinky2: 18,
257
+ pinky3: 19,
258
+ pinky4: 20
259
+ }, T = {
260
+ thumb: ["thumb1", "thumb2", "thumb3", "thumb4"],
261
+ index: ["index1", "index2", "index3", "index4"],
262
+ middle: ["middle1", "middle2", "middle3", "middle4"],
263
+ ring: ["ring1", "ring2", "ring3", "ring4"],
264
+ pinky: ["pinky1", "pinky2", "pinky3", "pinky4"]
265
+ }, nt = new p.Vector3(), ce = new p.Vector3(), le = new p.Vector3(), he = new p.Vector3(), me = new p.Vector3(), pe = new p.Vector3();
266
+ new p.Vector3();
267
+ new p.Vector3();
268
+ new p.Vector3();
269
+ const ue = new p.Vector3(), fe = Math.PI / 2, it = new p.Vector3(0, -1, 0);
270
+ class we extends q {
271
+ constructor(e, t, s, n = !0) {
272
+ super(st, G.HAND_CONNECTIONS);
273
+ R(this, "sign");
274
+ R(this, "isLeft");
275
+ /**
276
+ * the axis used to look at the pole
277
+ */
278
+ R(this, "lookAtPoleAxis");
279
+ this.handLandmarker = e, this.side = t, this.isMyWrist = s, this.drawLandmarks = n, this.sign = this.side == "Left" ? -1 : 1, this.isLeft = this.side == "Left", this.lookAtPoleAxis = this.sign < 0 ? "+x" : "-x", this.root.scale.setScalar(7), this.root.scale.y *= -1, this.root.scale.z *= -1;
280
+ }
281
+ predict(e, t) {
282
+ const s = this.handLandmarker.detectForVideo(e, performance.now());
283
+ if (s.landmarks.length)
284
+ for (let n = 0; n < s.landmarks.length; n++) {
285
+ const d = s.landmarks[n], i = d[this.points.wrist];
286
+ if (this.isMyWrist(i)) {
287
+ this.updateLandmarks(s.worldLandmarks[n]), this.drawLandmarks && (t.drawConnectors(d, G.HAND_CONNECTIONS, {
288
+ color: this.side == "Left" ? "#00FF00" : "#0000FF",
289
+ lineWidth: 4
290
+ }), t.drawLandmarks(d, { color: this.side == "Left" ? "#00FF00" : "#0000FF", lineWidth: 3, radius: 1 }));
291
+ break;
292
+ }
293
+ }
294
+ }
295
+ sync(e, t) {
296
+ throw new Error("Not used. Use syncHandBones instead");
297
+ }
298
+ /**
299
+ *
300
+ * @param delta time since last frame
301
+ * @param landmark2bones Array the same size as the umber of hand landmarks, and on each positionthe bone that belongs to that point.
302
+ * @see https://ai.google.dev/edge/mediapipe/solutions/vision/hand_landmarker
303
+ */
304
+ syncHandBones(e, t, s) {
305
+ const n = nt.crossVectors(
306
+ ce.copy(this.marks.index1.worldPosition).sub(this.marks.wrist.worldPosition),
307
+ le.copy(this.marks.pinky1.worldPosition).sub(this.marks.wrist.worldPosition)
308
+ ).normalize(), d = ce.copy(this.marks.palm.worldPosition).sub(this.marks.wrist.worldPosition).normalize(), i = le.copy(this.marks.pinky1.worldPosition).sub(this.marks.index1.worldPosition).normalize();
309
+ if (!(d.dot(it) > 0.8)) {
310
+ if (t.wrist) {
311
+ const r = A(he, t.wrist, s).add(d).applyMatrix4(s.matrixWorld), m = A(me, t.wrist, s).sub(i).applyMatrix4(s.matrixWorld), l = this.getGhost(t.wrist);
312
+ S(l, r, m, "-y"), l.rotateX(fe), l.lerp(t.wrist, e);
313
+ }
314
+ this.syncFinger(e, s, n, d, i, t, T.index, "middle1"), this.syncFinger(e, s, n, d, i, t, T.middle, "ring1"), this.syncFinger(e, s, n, d, i, t, T.ring, "pinky1"), this.syncFinger(e, s, n, d, i, t, T.pinky, "ring1", !0), this.syncFinger(e, s, n, d, i, t, T.thumb, "index1");
315
+ }
316
+ }
317
+ syncFinger(e, t, s, n, d, i, r, m, l = !1) {
318
+ for (let u = 0; u < r.length - 1; u++) {
319
+ const y = i[r[u]];
320
+ if (!y) continue;
321
+ const x = this.getGhost(y), W = he.copy(this.marks[r[u + 1]].worldPosition).sub(this.marks[r[u]].worldPosition).normalize(), a = A(me, y, t);
322
+ if (u == 0) {
323
+ const c = pe.copy(this.marks[m].worldPosition).sub(this.marks[r[0]].worldPosition).normalize();
324
+ l && c.negate(), ue.copy(c), S(
325
+ x,
326
+ W.add(a).applyMatrix4(t.matrixWorld),
327
+ c.add(a).applyMatrix4(t.matrixWorld),
328
+ this.lookAtPoleAxis
329
+ );
330
+ } else
331
+ S(
332
+ x,
333
+ W.add(a).applyMatrix4(t.matrixWorld),
334
+ pe.copy(ue).add(a).applyMatrix4(t.matrixWorld),
335
+ this.lookAtPoleAxis
336
+ );
337
+ x.rotateX(fe), x.lerp(y, e);
338
+ }
339
+ }
340
+ bind(e, t) {
341
+ const s = {}, n = (d, i) => {
342
+ const r = P(e, d);
343
+ if (r)
344
+ return s[i] = r, i;
345
+ };
346
+ return n(this.isLeft ? t.handL : t.handR, "wrist"), n(this.isLeft ? t.index1L : t.index1R, "index1"), n(this.isLeft ? t.index2L : t.index2R, "index2"), n(this.isLeft ? t.index3L : t.index3R, "index3"), n(this.isLeft ? t.middle1L : t.middle1R, "middle1"), n(this.isLeft ? t.middle2L : t.middle2R, "middle2"), n(this.isLeft ? t.middle3L : t.middle3R, "middle3"), n(this.isLeft ? t.ring1L : t.ring1R, "ring1"), n(this.isLeft ? t.ring2L : t.ring2R, "ring2"), n(this.isLeft ? t.ring3L : t.ring3R, "ring3"), n(this.isLeft ? t.pinky1L : t.pinky1R, "pinky1"), n(this.isLeft ? t.pinky2L : t.pinky2R, "pinky2"), n(this.isLeft ? t.pinky3L : t.pinky3R, "pinky3"), n(this.isLeft ? t.thumb1L : t.thumb1R, "thumb1"), n(this.isLeft ? t.thumb2L : t.thumb2R, "thumb2"), n(this.isLeft ? t.thumb3L : t.thumb3R, "thumb3"), {
347
+ update: (d) => {
348
+ this.syncHandBones(d, s, e);
349
+ }
350
+ };
351
+ }
352
+ }
353
+ async function rt(h, o) {
354
+ const e = await j.createFromOptions(h, {
355
+ baseOptions: {
356
+ modelAssetPath: (o == null ? void 0 : o.modelPath) ?? "face_landmarker.task",
357
+ delegate: "GPU"
358
+ },
359
+ outputFaceBlendshapes: !0,
360
+ runningMode: "VIDEO",
361
+ numFaces: 1
362
+ });
363
+ return new mt(e, { ...o });
364
+ }
365
+ const at = {
366
+ eyeL: 473,
367
+ eyeR: 468,
368
+ eyeStartL: 463,
369
+ eyeStartR: 243,
370
+ eyeEndL: 263,
371
+ eyeEndR: 33,
372
+ earL: 454,
373
+ earR: 234,
374
+ noseTip: 4,
375
+ noseBone: 6,
376
+ chin: 152,
377
+ forehead: 10
378
+ }, dt = new b(), ct = new b(), be = new b(), lt = new b(), ht = new b();
379
+ new b();
380
+ class mt extends q {
381
+ constructor(e, t) {
382
+ super(at, j.FACE_LANDMARKS_TESSELATION);
383
+ R(this, "blendshapeCategories");
384
+ R(this, "blendshapeMap", /* @__PURE__ */ new Map());
385
+ R(this, "smoothed", {});
386
+ R(this, "smoothing", 3e-4);
387
+ // lower = smoother but more lag, higher = more responsive
388
+ R(this, "_faceLandmarks", []);
389
+ this.faceLandmarker = e, this.cfg = t, this.root.scale.y *= -1, this.root.scale.z *= -1, this.root.scale.multiplyScalar(3);
390
+ }
391
+ predict(e, t) {
392
+ var n, d, i;
393
+ const s = this.faceLandmarker.detectForVideo(e, performance.now());
394
+ s.faceLandmarks[0] && (this.cfg.drawLandmarks && (t.drawConnectors(s.faceLandmarks[0], j.FACE_LANDMARKS_TESSELATION, { color: "#00fff2ff", lineWidth: 0.1 }), t.drawLandmarks(s.faceLandmarks[0], { color: "#00ff00", lineWidth: 0.1, radius: 0.4 })), this.updateLandmarks(s.faceLandmarks[0], s.faceLandmarks[0])), this._faceLandmarks = s.faceLandmarks[0], this.blendshapeCategories = (d = (n = s.faceBlendshapes) == null ? void 0 : n[0]) == null ? void 0 : d.categories, (i = this.blendshapeCategories) == null || i.forEach((r) => {
395
+ this.blendshapeMap.set(r.categoryName, r.score);
396
+ });
397
+ }
398
+ get lastKnownLandmarks() {
399
+ return this._faceLandmarks;
400
+ }
401
+ bindShapeKeys(e) {
402
+ const t = e.morphTargetDictionary;
403
+ return {
404
+ update: (s) => {
405
+ var n;
406
+ (n = this.blendshapeCategories) == null || n.forEach((d) => {
407
+ const { categoryName: i, score: r } = d;
408
+ if (!(t != null && t.hasOwnProperty(i))) return;
409
+ this.smoothed[i] === void 0 && (this.smoothed[i] = r);
410
+ const m = 1 - Math.pow(this.smoothing, s);
411
+ this.smoothed[i] += (r - this.smoothed[i]) * m, e.morphTargetInfluences[t[i]] = this.smoothed[i];
412
+ });
413
+ }
414
+ };
415
+ }
416
+ bind(e) {
417
+ const t = new ye(e, "L"), s = new ye(e, "R"), n = P(e, "head");
418
+ return {
419
+ update: (d) => {
420
+ if (t.update(d, this.blendshapeMap), s.update(d, this.blendshapeMap), !n) return;
421
+ const i = dt.copy(this.marks.earL.worldPosition), r = ct.copy(this.marks.earR.worldPosition), m = be.subVectors(i, r).multiplyScalar(0.5).add(r), l = lt.subVectors(this.marks.noseTip.worldPosition, m), u = i.sub(r), y = A(ht, n, e), x = u.add(y).applyMatrix4(e.matrixWorld), W = l.add(y).applyMatrix4(e.matrixWorld);
422
+ S(n, W, x, "+x");
423
+ }
424
+ };
425
+ }
426
+ /**
427
+ * The mesh is assumed to be a canonical_face_model because we will be manipulating it's vertices.
428
+ *
429
+ * @see https://github.com/google-ai-edge/mediapipe/tree/master/mediapipe/modules/face_geometry
430
+ * @param mesh basically either the original or a clone of the canonical_face_model
431
+ * @returns an object with a disposeMaterial method that should be called when the mesh is disposed of.
432
+ */
433
+ bindGeometry(e, t) {
434
+ new b(), new b();
435
+ const s = new b();
436
+ new b();
437
+ const d = e.geometry.attributes.position;
438
+ D(new b(0.5, 0.5, 0.5)), Ce(e);
439
+ const i = Se("landmarkIndex", "uint"), r = Me(De, "vec3"), m = Ve(r.element(i)).xy;
440
+ let l;
441
+ const u = 116, y = 346, x = s.subVectors(
442
+ new b(d.getX(u), d.getY(u), d.getZ(u)),
443
+ new b(d.getX(y), d.getY(y), d.getZ(y))
444
+ ).lengthSq();
445
+ console.log("# mesh face reference (live): ", x);
446
+ const W = D(x), a = D(1);
447
+ let c;
448
+ return {
449
+ /**
450
+ * Disposes of the material and removes events listeners on the video element.
451
+ */
452
+ disposeMaterial: () => {
453
+ c == null || c();
454
+ },
455
+ /**
456
+ * asas
457
+ * @param delta asas
458
+ * @returns
459
+ */
460
+ update: (L) => {
461
+ var E, g;
462
+ if (!l) {
463
+ const k = (g = (E = this.cfg) == null ? void 0 : E.videoElementRef) == null ? void 0 : g.call(E);
464
+ if (!k || !k.videoWidth || !k.videoHeight) return;
465
+ l = k;
466
+ const f = new Z(l);
467
+ f.colorSpace = J;
468
+ const F = D(l.videoWidth / l.videoHeight), _ = r.element(y).sub(r.element(u)).lengthSq(), B = W.div(_).sqrt().mul(2), M = r.element(234).xy, $ = r.element(93).xy, Re = r.element(454).xy, K = r.element(323).xy, X = M.sub($).div(2).add($), ve = Re.sub(K).div(2).add(K).sub(X).div(2).add(X), Q = r.element(i).sub(ve).xzy.mul(Ne(1, -1, Oe(1).div(F))).mul(B), V = Te(f, _e(m.x, m.y.oneMinus())), Y = () => {
469
+ const N = new Z(l);
470
+ N.colorSpace = J, V.value = N, V.needsUpdate = !0, F.value = l.videoWidth / l.videoHeight;
471
+ };
472
+ l.addEventListener("loadeddata", Y), t ? t(Q, V) : e.material = new Fe({
473
+ positionNode: Q,
474
+ colorNode: V,
475
+ roughness: 0.93
476
+ }), c = () => {
477
+ var N;
478
+ V.value.dispose(), l == null || l.removeEventListener("loadeddata", Y), (N = e.material) == null || N.dispose();
479
+ };
480
+ }
481
+ const w = this.lastKnownLandmarks;
482
+ if (!(w != null && w.length)) return;
483
+ a.value = s.subVectors(w[y], w[u]).lengthSq(), a.needsUpdate = !0;
484
+ const v = r.value.array;
485
+ for (let k = 0; k < w.length; k++)
486
+ v[k * 3] = w[k].x, v[k * 3 + 1] = w[k].y, v[k * 3 + 2] = w[k].z;
487
+ r.value.needsUpdate = !0;
488
+ }
489
+ };
490
+ }
491
+ }
492
+ class ye {
493
+ constructor(o, e) {
494
+ R(this, "eyeBone");
495
+ R(this, "eyeLookOut");
496
+ R(this, "eyeLookIn");
497
+ R(this, "eyeLookUp");
498
+ R(this, "eyeLookDown");
499
+ R(this, "sign", 1);
500
+ this.rig = o, this.side = e, this.eyeBone = o.getObjectByName(`eye${e}`);
501
+ const t = e == "L" ? "Left" : "Right";
502
+ this.eyeLookOut = `eyeLookOut${t}`, this.eyeLookIn = `eyeLookIn${t}`, this.eyeLookUp = `eyeLookUp${t}`, this.eyeLookDown = `eyeLookDown${t}`, this.sign = e == "L" ? -1 : 1;
503
+ }
504
+ update(o, e) {
505
+ if (!this.eyeBone) return;
506
+ A(be, this.eyeBone, this.rig);
507
+ const t = e.get(this.eyeLookOut) ?? 0, s = e.get(this.eyeLookIn) ?? 0, n = e.get(this.eyeLookUp) ?? 0, d = e.get(this.eyeLookDown) ?? 0, i = s - t, r = d - n;
508
+ this.eyeBone.rotation.y = i * this.sign / 2, this.eyeBone.rotation.x = r / 2;
509
+ }
510
+ }
511
+ const xe = {
512
+ faceMesh: "face",
513
+ head: "head",
514
+ hips: "hips",
515
+ neck: "neck",
516
+ torso: "torso",
517
+ armL: "upper_armL",
518
+ forearmL: "forearmL",
519
+ armR: "upper_armR",
520
+ forearmR: "forearmR",
521
+ thighL: "thighL",
522
+ shinL: "shinL",
523
+ footL: "footL",
524
+ toesL: "toesL",
525
+ thighR: "thighR",
526
+ shinR: "shinR",
527
+ footR: "footR",
528
+ toesR: "toesR",
529
+ handL: "handL",
530
+ index1L: "index1L",
531
+ index2L: "index2L",
532
+ index3L: "index3L",
533
+ middle1L: "middle1L",
534
+ middle2L: "middle2L",
535
+ middle3L: "middle3L",
536
+ ring1L: "ring1L",
537
+ ring2L: "ring2L",
538
+ ring3L: "ring3L",
539
+ pinky1L: "pinky1L",
540
+ pinky2L: "pinky2L",
541
+ pinky3L: "pinky3L",
542
+ thumb1L: "thumb1L",
543
+ thumb2L: "thumb2L",
544
+ thumb3L: "thumb3L",
545
+ handR: "handR",
546
+ index1R: "index1R",
547
+ index2R: "index2R",
548
+ index3R: "index3R",
549
+ middle1R: "middle1R",
550
+ middle2R: "middle2R",
551
+ middle3R: "middle3R",
552
+ ring1R: "ring1R",
553
+ ring2R: "ring2R",
554
+ ring3R: "ring3R",
555
+ pinky1R: "pinky1R",
556
+ pinky2R: "pinky2R",
557
+ pinky3R: "pinky3R",
558
+ thumb1R: "thumb1R",
559
+ thumb2R: "thumb2R",
560
+ thumb3R: "thumb3R"
561
+ }, pt = [
562
+ "eyeBlinkLeft",
563
+ "eyeBlinkRight",
564
+ "eyeLookDownLeft",
565
+ "eyeLookDownRight",
566
+ "eyeLookInLeft",
567
+ "eyeLookInRight",
568
+ "eyeLookOutLeft",
569
+ "eyeLookOutRight",
570
+ "eyeLookUpLeft",
571
+ "eyeLookUpRight",
572
+ "eyeSquintLeft",
573
+ "eyeSquintRight",
574
+ "eyeWideLeft",
575
+ "eyeWideRight",
576
+ "browDownLeft",
577
+ "browDownRight",
578
+ "browInnerUp",
579
+ "browOuterUpLeft",
580
+ "browOuterUpRight",
581
+ "noseSneerLeft",
582
+ "noseSneerRight",
583
+ "cheekPuff",
584
+ "cheekSquintLeft",
585
+ "cheekSquintRight",
586
+ "jawForward",
587
+ "jawLeft",
588
+ "jawOpen",
589
+ "jawRight",
590
+ "mouthClose",
591
+ "mouthDimpleLeft",
592
+ "mouthDimpleRight",
593
+ "mouthFrownLeft",
594
+ "mouthFrownRight",
595
+ "mouthFunnel",
596
+ "mouthLeft",
597
+ "mouthLowerDownLeft",
598
+ "mouthLowerDownRight",
599
+ "mouthPressLeft",
600
+ "mouthPressRight",
601
+ "mouthPucker",
602
+ "mouthRight",
603
+ "mouthRollLower",
604
+ "mouthRollUpper",
605
+ "mouthShrugLower",
606
+ "mouthShrugUpper",
607
+ "mouthSmileLeft",
608
+ "mouthSmileRight",
609
+ "mouthStretchLeft",
610
+ "mouthStretchRight",
611
+ "mouthUpperUpLeft",
612
+ "mouthUpperUpRight",
613
+ "tongueOut"
614
+ ];
615
+ function ut(h, o, e = 30) {
616
+ const t = [], s = h.getObjectByName(
617
+ o.faceMesh
618
+ ), n = /* @__PURE__ */ new Set();
619
+ if (s != null && s.morphTargetDictionary)
620
+ for (const a in s.morphTargetDictionary)
621
+ pt.includes(a) && n.add(a);
622
+ const d = Object.keys(o);
623
+ h.traverse((a) => {
624
+ if (a instanceof C.Bone) {
625
+ const c = d.find((L) => a.name.indexOf(o[L]) === 0);
626
+ c && t.push({
627
+ ref: a,
628
+ name: a.name,
629
+ normalizedName: c
630
+ });
631
+ }
632
+ });
633
+ const i = [], r = /* @__PURE__ */ new Map(), m = /* @__PURE__ */ new Map();
634
+ let l = !1, u = 0;
635
+ function y() {
636
+ r.clear(), m.clear(), i.length = 0, u = performance.now() / 1e3, l = !0;
637
+ }
638
+ function x() {
639
+ if (!l) return;
640
+ const a = performance.now() / 1e3 - u;
641
+ i.push(a);
642
+ for (const c of t) {
643
+ r.has(c.name) || r.set(c.name, []);
644
+ const L = r.get(c.name), w = c.ref.quaternion;
645
+ L.push(w.x, w.y, w.z, w.w);
646
+ }
647
+ for (const c of n) {
648
+ m.has(c) || m.set(c, []);
649
+ const L = m.get(c), w = s.morphTargetDictionary[c], v = s.morphTargetInfluences[w];
650
+ L.push(v);
651
+ }
652
+ }
653
+ function W(a = "RecordedClip") {
654
+ l = !1;
655
+ const c = [];
656
+ for (const [w, v] of r)
657
+ c.push(
658
+ new C.QuaternionKeyframeTrack(
659
+ `${w}.quaternion`,
660
+ i,
661
+ v
662
+ )
663
+ );
664
+ for (const [w, v] of m)
665
+ c.push(
666
+ new C.NumberKeyframeTrack(
667
+ `${xe.faceMesh}.morphTargetInfluences[${w}]`,
668
+ i,
669
+ v
670
+ )
671
+ );
672
+ const L = new C.AnimationClip(a, -1, c);
673
+ return {
674
+ clip: L,
675
+ saveToFile: () => {
676
+ new ze().parse(
677
+ h,
678
+ (v) => {
679
+ const E = new Blob([v], {
680
+ type: "model/gltf-binary"
681
+ }), g = URL.createObjectURL(E), k = document.createElement("a");
682
+ k.href = g, k.download = a + ".glb", k.click();
683
+ },
684
+ (v) => {
685
+ console.error(v);
686
+ },
687
+ {
688
+ binary: !0,
689
+ animations: [L]
690
+ }
691
+ );
692
+ }
693
+ };
694
+ }
695
+ return { start: y, captureFrame: x, stop: W, isRecording: () => l };
696
+ }
697
+ const ft = () => {
698
+ var h;
699
+ return !!((h = navigator.mediaDevices) != null && h.getUserMedia);
700
+ };
701
+ async function Pt(h) {
702
+ const o = {
703
+ debugFrame: void 0,
704
+ displayScale: 1,
705
+ ignoreLegs: !1,
706
+ debugVideo: void 0,
707
+ ignoreFace: !1,
708
+ onlyFace: !1,
709
+ drawLandmarksOverlay: !0,
710
+ modelPaths: {
711
+ vision: "https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@0.10.3/wasm",
712
+ pose: "https://storage.googleapis.com/mediapipe-models/pose_landmarker/pose_landmarker_lite/float16/1/pose_landmarker_lite.task",
713
+ hand: "https://storage.googleapis.com/mediapipe-models/hand_landmarker/hand_landmarker/float16/1/hand_landmarker.task",
714
+ face: "https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/1/face_landmarker.task"
715
+ },
716
+ ...h
717
+ };
718
+ let e;
719
+ const t = await We.forVisionTasks(o.modelPaths.vision ?? "/wasm"), s = o.onlyFace ? void 0 : await Xe(t, {
720
+ ignoreLegs: o.ignoreLegs,
721
+ modelPath: o.modelPaths.pose,
722
+ drawLandmarks: o.drawLandmarksOverlay
723
+ }), n = o.onlyFace ? void 0 : await ot(t, {
724
+ leftWrist: () => s.leftWristNormalizedPosition,
725
+ rightWrist: () => s.rightWristNormalizedPosition,
726
+ modelPath: o.modelPaths.hand,
727
+ drawLandmarks: o.drawLandmarksOverlay,
728
+ ...h == null ? void 0 : h.handsTrackerOptions
729
+ }), d = o.ignoreFace ? void 0 : await rt(t, { modelPath: o.modelPaths.face, videoElementRef: () => e, drawLandmarks: o.drawLandmarksOverlay }), i = document.createElement("div");
730
+ i.style.position = "absolute", i.style.top = "0px", i.style.left = "0px", i.style.zIndex = "21", i.style.maxWidth = "600px", i.style.width = "100%", i.classList.add("three-mediapipe-rig"), document.body.appendChild(i);
731
+ const r = document.createElement("canvas"), m = r.getContext("2d"), l = new ge(m);
732
+ r.style.zIndex = "22", r.style.position = "absolute", r.style.top = "0px", r.style.left = "0px", r.style.pointerEvents = "none", r.style.maxWidth = "100%", i.appendChild(r);
733
+ function u(a) {
734
+ m.save(), m.clearRect(0, 0, r.width, r.height), s == null || s.predict(a, l), n == null || n.left.predict(a, l), n == null || n.right.predict(a, l), d == null || d.predict(a, l), m.restore();
735
+ }
736
+ function y() {
737
+ e = document.createElement("video"), i.appendChild(e);
738
+ let a = -1;
739
+ e.style.zIndex = "21", e.style.position = "absolute", e.style.top = "0px", e.style.left = "0px", e.style.height = "auto", e.style.maxWidth = "100%", e.style.display = "block", e.muted = !1, o.debugVideo && (e.src = o.debugVideo, e.controls = !0, e.loop = !0, e.muted = !0, e.controls = !0, e.play());
740
+ function c() {
741
+ a !== e.currentTime && e.readyState >= 2 && (u(e), a = e.currentTime), window.requestAnimationFrame(c);
742
+ }
743
+ e.addEventListener("loadeddata", () => {
744
+ const L = e.videoWidth, w = e.videoHeight, g = Math.min(600 / L, 600 / w, 1);
745
+ e.width = L * g * (o.displayScale ?? 1), e.height = w * g * (o.displayScale ?? 1), r.width = e.width, r.height = e.height, r.style.height = "auto", r.style.width = e.width + "px", r.style.maxWidth = "100%", window.requestAnimationFrame(c);
746
+ });
747
+ }
748
+ if (o.debugFrame) {
749
+ const a = document.createElement("img");
750
+ a.src = o.debugFrame, a.style.zIndex = "21", a.style.position = "absolute", a.style.top = "0px", a.style.left = "0px", i.appendChild(a), a.addEventListener("load", () => {
751
+ a.width = a.naturalWidth * o.displayScale, a.height = a.naturalHeight * o.displayScale, r.width = a.naturalWidth, r.height = a.naturalWidth, r.style.width = a.width + "px", r.style.height = a.height + "px";
752
+ function c() {
753
+ u(a);
754
+ }
755
+ window.requestAnimationFrame(c);
756
+ });
757
+ } else o.debugVideo && y();
758
+ let x;
759
+ function W(a) {
760
+ e && (e.srcObject ? e.srcObject.getTracks().forEach((L) => L.enabled = a) : a ? e.play() : e.pause());
761
+ }
762
+ return {
763
+ poseTracker: s,
764
+ handsTracker: n,
765
+ faceTracker: d,
766
+ video: e,
767
+ canvas: r,
768
+ domElement: i,
769
+ start: async (a = !1) => {
770
+ let c = !1;
771
+ if (!ft())
772
+ throw new Error("Webcam not supported");
773
+ e || y();
774
+ let L;
775
+ function w(f) {
776
+ c || (console.warn("Camera track ended, attempting recovery..."), v(f), E(f));
777
+ }
778
+ function v(f) {
779
+ L == null || L.getVideoTracks().forEach((F) => F.stop()), L = void 0, f.srcObject = null;
780
+ }
781
+ async function E(f, F = 0) {
782
+ const B = Math.min(1e3 * 2 ** F, 16e3);
783
+ if (F >= 3)
784
+ throw new Error("Camera recovery failed after max attempts");
785
+ if (await new Promise((M) => setTimeout(M, B)), !c)
786
+ try {
787
+ await g(f);
788
+ } catch (M) {
789
+ await k(M, f, F + 1);
790
+ }
791
+ }
792
+ async function g(f) {
793
+ L = await navigator.mediaDevices.getUserMedia({ video: !0, audio: a }), f.srcObject = L, await f.play(), L.getVideoTracks().forEach((F) => {
794
+ F.addEventListener("ended", () => w(f));
795
+ });
796
+ }
797
+ async function k(f, F, _ = 0) {
798
+ if (f instanceof DOMException)
799
+ switch (f.name) {
800
+ case "NotAllowedError":
801
+ throw new Error("Permission denied — prompt user to allow camera");
802
+ case "NotFoundError":
803
+ console.error("No camera found — retry when device is connected"), await E(F, _ + 1);
804
+ break;
805
+ case "NotReadableError":
806
+ throw new Error("Camera in use by another app");
807
+ default:
808
+ throw new Error("Camera error: " + f.message);
809
+ }
810
+ else
811
+ throw new Error("Unknown camera error: " + f);
812
+ }
813
+ return await E(e), x = () => {
814
+ c = !0, v(e), x = void 0;
815
+ }, {
816
+ getStream: () => L,
817
+ stop: x
818
+ };
819
+ },
820
+ pause: () => {
821
+ W(!1);
822
+ },
823
+ resume: () => {
824
+ W(!0);
825
+ },
826
+ bind: (a, c) => {
827
+ if (c = c || xe, !s) throw new Error("Pose tracker not initialized");
828
+ if (!n) throw new Error("Hands tracker not initialized");
829
+ if (!d) throw new Error("Face tracker not initialized");
830
+ const L = s.bind(a, c), w = n.left.bind(a, c), v = n.right.bind(a, c);
831
+ let E;
832
+ const g = d == null ? void 0 : d.bind(a);
833
+ a.traverse((f) => {
834
+ f instanceof p.Mesh && f.name.indexOf(c.faceMesh) === 0 && (f.frustumCulled = !1, E = d == null ? void 0 : d.bindShapeKeys(f));
835
+ });
836
+ const k = ut(a, c);
837
+ return {
838
+ /**
839
+ * Will save the tracked movement of the rig to an animation clip.
840
+ * Only the bones moved by the bone mapping will be recorded.
841
+ */
842
+ startRecording: k.start,
843
+ stopRecording: k.stop,
844
+ isRecording: () => k.isRecording(),
845
+ update: (f) => {
846
+ L.update(f), w.update(f), v.update(f), E == null || E.update(f), g == null || g.update(f), k.isRecording() && k.captureFrame();
847
+ }
848
+ };
849
+ },
850
+ setVideoFromSource: (a) => {
851
+ x == null || x(), e || y(), e.src = a instanceof File ? URL.createObjectURL(a) : a, e.controls = !0, e.loop = !0, e.muted = !0, e.controls = !0, e.play();
852
+ },
853
+ async setVideoFromWebcam(a = !1) {
854
+ if (e || y(), x)
855
+ throw new Error("Webcam already started");
856
+ return await this.start(a);
857
+ }
858
+ };
859
+ }
860
+ export {
861
+ De as FACE_LANDMARKS_COUNT,
862
+ Ce as createFaceLandmarksIndexAttribute,
863
+ Pt as setupTracker
864
+ };