three-mediapipe-rig 0.0.1 → 0.0.2

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 CHANGED
@@ -3,10 +3,14 @@
3
3
 
4
4
  # three-mediapipe-rig
5
5
 
6
- Integrate [Google MediaPipe](https://ai.google.dev/edge/mediapipe/solutions/guide) motion tracking with [Three.js](https://threejs.org/) skeletal rigs. Load a GLTF/GLB character, bind it, and drive its body, hands, and face from a webcam or video — in just a few lines of code.
6
+ Integrate [Google MediaPipe](https://ai.google.dev/edge/mediapipe/solutions/guide)'s **webcam motion tracking** with [Three.js](https://threejs.org/) skeletal rigs. Load a GLTF/GLB character, bind it, and drive its body, hands, and face from a webcam or video — in just a few lines of code.
7
+
8
+ Use your webcam ( or a video ) to drive a skeleton.
7
9
 
8
10
  This will run 3 models: face, body, hands. So expect a FPS drop.
9
11
 
12
+ LIVE EXAMPLE: https://bandinopla.github.io/three-mediapipe-rig/
13
+
10
14
  ## Features
11
15
 
12
16
  - **Full-body pose tracking** — shoulders, arms, hips, legs, and head
@@ -2,21 +2,21 @@ var nt = Object.defineProperty;
2
2
  var rt = (l, o, t) => o in l ? nt(l, o, { enumerable: !0, configurable: !0, writable: !0, value: t }) : l[o] = t;
3
3
  var y = (l, o, t) => rt(l, typeof o != "symbol" ? o + "" : o, t);
4
4
  import { PoseLandmarker as tt, HandLandmarker as S, FaceLandmarker as C, FilesetResolver as at, DrawingUtils as dt } from "@mediapipe/tasks-vision";
5
- import * as c from "three/webgpu";
6
- import { Vector3 as w, Quaternion as et } from "three/webgpu";
5
+ import * as h from "three/webgpu";
6
+ import { Vector3 as L, Quaternion as et } from "three/webgpu";
7
7
  import { Bone as lt } from "three";
8
- const F = new w(), D = new w(), ct = new w(1, 0, 0), ht = new w(-1, 0, 0), pt = new w(0, 1, 0), mt = new w(0, -1, 0), B = new w(0, 0, 1);
9
- new w(0, 0, -1);
10
- const G = new w(), ut = new w(), ft = new w(), g = new et(), O = new et();
8
+ const N = new L(), D = new L(), ht = new L(1, 0, 0), ct = new L(-1, 0, 0), pt = new L(0, 1, 0), mt = new L(0, -1, 0), T = new L(0, 0, 1);
9
+ new L(0, 0, -1);
10
+ const g = new L(), ut = new L(), ft = new L(), B = new et(), O = new et();
11
11
  function A(l, o, t, e = "+x") {
12
12
  l.lookAt(o);
13
- const s = e == "+x" ? ct : e == "-x" ? ht : e == "+y" ? pt : mt;
14
- l.getWorldPosition(D), l.getWorldQuaternion(O), F.subVectors(t, D).normalize(), G.copy(s).applyQuaternion(O);
15
- const i = G, n = ut.copy(B).applyQuaternion(O), r = F.clone().addScaledVector(n, -F.dot(n)).normalize(), a = ft.crossVectors(i, r), p = Math.atan2(a.dot(n), i.dot(r));
16
- g.setFromAxisAngle(B, p), l.quaternion.multiply(g);
13
+ const s = e == "+x" ? ht : e == "-x" ? ct : e == "+y" ? pt : mt;
14
+ l.getWorldPosition(D), l.getWorldQuaternion(O), N.subVectors(t, D).normalize(), g.copy(s).applyQuaternion(O);
15
+ const i = g, r = ut.copy(T).applyQuaternion(O), n = N.clone().addScaledVector(r, -N.dot(r)).normalize(), a = ft.crossVectors(i, n), c = Math.atan2(a.dot(r), i.dot(n));
16
+ B.setFromAxisAngle(T, c), l.quaternion.multiply(B);
17
17
  }
18
- const N = new c.Vector3(), v = new c.Vector3(), _ = new c.Vector3();
19
- new c.Vector3();
18
+ const V = new h.Vector3(), F = new h.Vector3(), _ = new h.Vector3();
19
+ new h.Vector3();
20
20
  class z {
21
21
  constructor(o, t) {
22
22
  y(this, "objectGhost");
@@ -25,17 +25,17 @@ class z {
25
25
  * per landmark index, it points to it's object3D equivalent.
26
26
  */
27
27
  y(this, "marks", {});
28
- this.points = o, this.debugConnections = t, this.root = new c.Object3D(), this.objectGhost = /* @__PURE__ */ new Map();
28
+ this.points = o, this.debugConnections = t, this.root = new h.Object3D(), this.objectGhost = /* @__PURE__ */ new Map();
29
29
  for (let e in this.points)
30
30
  this.marks[e] = new yt(), this.root.add(this.marks[e]);
31
31
  }
32
32
  updateLandmarks(o, t, e) {
33
33
  for (let s in this.points) {
34
- const i = this.points[s], n = this.marks[s];
35
- n && (i instanceof Array ? (N.copy(o[i[0]]), n.position.copy(o[i[1]]).sub(N).divideScalar(2).add(o[i[0]]), i.length == 4 && (N.subVectors(
34
+ const i = this.points[s], r = this.marks[s];
35
+ r && (i instanceof Array ? (V.copy(o[i[0]]), r.position.copy(o[i[1]]).sub(V).divideScalar(2).add(o[i[0]]), i.length == 4 && (V.subVectors(
36
36
  o[i[3]],
37
37
  o[i[2]]
38
- ).divideScalar(2).add(o[i[2]]).sub(n.position).divideScalar(2), n.position.add(N))) : n.position.copy(o[i]));
38
+ ).divideScalar(2).add(o[i[2]]).sub(r.position).divideScalar(2), r.position.add(V))) : r.position.copy(o[i]));
39
39
  }
40
40
  e && t && e.drawConnectors(
41
41
  t,
@@ -63,29 +63,29 @@ class z {
63
63
  this.marks[o].position.set(1, 2, 3);
64
64
  }
65
65
  syncObjects(o, t, e) {
66
- for (const [s, i, n, r] of o) {
67
- this.marks[n].getWorldPosition(_), this.marks[i].getWorldPosition(v);
68
- const a = _.sub(v);
69
- s.getWorldPosition(v), v.add(a);
70
- const p = v, u = s.getWorldPosition(_).sub(e), f = this.getGhost(s);
71
- A(f, p, u, r), f.rotateX(Math.PI / 2), s.position.lerp(f.position, t * 4), s.quaternion.slerp(f.quaternion, t * 4);
66
+ for (const [s, i, r, n] of o) {
67
+ this.marks[r].getWorldPosition(_), this.marks[i].getWorldPosition(F);
68
+ const a = _.sub(F);
69
+ s.getWorldPosition(F), F.add(a);
70
+ const c = F, m = s.getWorldPosition(_).sub(e), f = this.getGhost(s);
71
+ A(f, c, m, n), f.rotateX(Math.PI / 2), s.position.lerp(f.position, t * 4), s.quaternion.slerp(f.quaternion, t * 4);
72
72
  }
73
73
  }
74
74
  getBone(o, t) {
75
75
  return o.getObjectByName(t.replace(/[\.\:]/g, ""));
76
76
  }
77
77
  }
78
- class yt extends c.Mesh {
78
+ class yt extends h.Mesh {
79
79
  constructor() {
80
- super(new c.SphereGeometry(0.01, 3, 3), new c.MeshStandardMaterial({ color: 16711680, wireframe: !0 }));
81
- y(this, "_worldPosition", new c.Vector3());
82
- this.add(new c.AxesHelper(1e-3));
80
+ super(new h.SphereGeometry(0.01, 3, 3), new h.MeshStandardMaterial({ color: 16711680, wireframe: !0 }));
81
+ y(this, "_worldPosition", new h.Vector3());
82
+ this.add(new h.AxesHelper(1e-3));
83
83
  }
84
84
  get worldPosition() {
85
85
  return this.getWorldPosition(this._worldPosition), this._worldPosition;
86
86
  }
87
87
  }
88
- class wt extends c.Object3D {
88
+ class wt extends h.Object3D {
89
89
  lerp(o, t, e = 8) {
90
90
  o.position.lerp(this.position, t * e), o.quaternion.slerp(this.quaternion, t * e);
91
91
  }
@@ -96,7 +96,7 @@ function E(l, o, t) {
96
96
  function Lt(l) {
97
97
  return l.replace(/[\.\:]/g, "");
98
98
  }
99
- function L(l, o) {
99
+ function w(l, o) {
100
100
  let t;
101
101
  return o = Lt(o), l.traverse((e) => {
102
102
  e.name.indexOf(o) === 0 && e instanceof lt && (t = e);
@@ -115,16 +115,20 @@ async function kt(l, o) {
115
115
  });
116
116
  return new Et(t, o);
117
117
  }
118
- const bt = {
118
+ const xt = {
119
119
  hips: [24, 23],
120
120
  neck: [12, 11],
121
121
  leftLeg: 23,
122
122
  leftKnee: 25,
123
+ leftFoot: 27,
124
+ leftToes: 31,
123
125
  leftArm: 11,
124
126
  leftElbow: 13,
125
127
  leftWrist: 15,
126
128
  rightLeg: 24,
127
129
  rightKnee: 26,
130
+ rightFoot: 28,
131
+ rightToes: 32,
128
132
  rightArm: 12,
129
133
  rightElbow: 14,
130
134
  rightWrist: 16,
@@ -133,10 +137,10 @@ const bt = {
133
137
  torso: [24, 23, 12, 11],
134
138
  leftEar: 7,
135
139
  rightEar: 8
136
- }, xt = new c.Vector3(), I = new c.Vector3(), Pt = new c.Vector3(), Rt = new c.Vector3(), Wt = new c.Vector3(), T = new c.Vector3(), H = new c.Vector3();
140
+ }, bt = new h.Vector3(), G = new h.Vector3(), Pt = new h.Vector3(), Rt = new h.Vector3(), Wt = new h.Vector3(), I = new h.Vector3(), H = new h.Vector3();
137
141
  class Et extends z {
138
142
  constructor(t, e) {
139
- super(bt, tt.POSE_CONNECTIONS);
143
+ super(xt, tt.POSE_CONNECTIONS);
140
144
  y(this, "_leftWristNormalizedPosition");
141
145
  y(this, "_rightWristNormalizedPosition");
142
146
  this.poseLandmarker = t, this.config = e, this.root.scale.y *= -2, this.root.scale.z *= -2, this.root.scale.x *= 2;
@@ -168,38 +172,40 @@ class Et extends z {
168
172
  bind(t, e) {
169
173
  var a;
170
174
  const s = {
171
- hips: L(t, e.hips),
172
- neck: L(t, e.neck),
173
- leftArm: L(t, e.armL),
174
- leftElbow: L(t, e.forearmL),
175
- leftWrist: L(t, e.handL),
176
- rightArm: L(t, e.armR),
177
- rightElbow: L(t, e.forearmR),
178
- rightWrist: L(t, e.handR),
179
- head: L(t, e.head),
180
- torso: L(t, e.torso),
181
- leftLeg: L(t, e.thighL),
182
- leftKnee: L(t, e.shinL),
183
- rightLeg: L(t, e.thighR),
184
- rightKnee: L(t, e.shinR)
175
+ hips: w(t, e.hips),
176
+ neck: w(t, e.neck),
177
+ leftArm: w(t, e.armL),
178
+ leftElbow: w(t, e.forearmL),
179
+ leftWrist: w(t, e.handL),
180
+ rightArm: w(t, e.armR),
181
+ rightElbow: w(t, e.forearmR),
182
+ rightWrist: w(t, e.handR),
183
+ head: w(t, e.head),
184
+ torso: w(t, e.torso),
185
+ leftLeg: w(t, e.thighL),
186
+ leftKnee: w(t, e.shinL),
187
+ leftFoot: w(t, e.footL),
188
+ rightLeg: w(t, e.thighR),
189
+ rightKnee: w(t, e.shinR),
190
+ rightFoot: w(t, e.footR)
185
191
  };
186
- (a = this.config) != null && a.ignoreLegs && (delete s.leftLeg, delete s.leftKnee, delete s.rightLeg, delete s.rightKnee);
187
- const i = new c.Vector3(), n = new c.Vector3(), r = (p, u, f, k, d, h) => {
188
- if (!u) return;
189
- const P = this.marks[k].getWorldPosition(i).sub(this.marks[f].getWorldPosition(n)).normalize();
190
- E(T, u, t).add(P).applyMatrix4(t.matrixWorld), E(H, u, t).add(d).applyMatrix4(t.matrixWorld);
191
- const b = this.getGhost(u);
192
- A(b, T, H, h), b.rotateX(Math.PI / 2), b.lerp(u, p);
192
+ (a = this.config) != null && a.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);
193
+ const i = new h.Vector3(), r = new h.Vector3(), n = (c, m, f, k, d, p) => {
194
+ if (!m) return;
195
+ const P = this.marks[k].getWorldPosition(i).sub(this.marks[f].getWorldPosition(r)).normalize();
196
+ E(I, m, t).add(P).applyMatrix4(t.matrixWorld), E(H, m, t).add(d).applyMatrix4(t.matrixWorld);
197
+ const x = this.getGhost(m);
198
+ A(x, I, H, p), x.rotateX(Math.PI / 2), x.lerp(m, c);
193
199
  };
194
200
  return {
195
- update: (p) => {
196
- const u = this.marks.leftLeg.getWorldPosition(xt).sub(this.marks.rightLeg.getWorldPosition(I)).normalize(), f = this.marks.leftArm.getWorldPosition(I).sub(this.marks.rightArm.getWorldPosition(Pt)).normalize(), k = this.marks.leftEar.getWorldPosition(Rt).sub(this.marks.rightEar.getWorldPosition(Wt)).normalize();
197
- r(p, s.hips, "hips", "torso", u, "+x"), r(p, s.torso, "torso", "neck", f, "+x"), r(p, s.neck, "neck", "head", k, "+x"), r(p, s.head, "neck", "head", k, "+x"), r(p, s.leftArm, "leftArm", "leftElbow", f, "-x"), r(p, s.leftElbow, "leftElbow", "leftWrist", f, "-x"), r(p, s.leftLeg, "leftLeg", "leftKnee", u, "-x"), r(p, s.rightArm, "rightArm", "rightElbow", f, "-x"), r(p, s.rightElbow, "rightElbow", "rightWrist", f, "-x"), r(p, s.rightLeg, "rightLeg", "rightKnee", u, "-x");
201
+ update: (c) => {
202
+ const m = this.marks.leftLeg.getWorldPosition(bt).sub(this.marks.rightLeg.getWorldPosition(G)).normalize(), f = this.marks.leftArm.getWorldPosition(G).sub(this.marks.rightArm.getWorldPosition(Pt)).normalize(), k = this.marks.leftEar.getWorldPosition(Rt).sub(this.marks.rightEar.getWorldPosition(Wt)).normalize();
203
+ n(c, s.hips, "hips", "torso", m, "+x"), n(c, s.torso, "torso", "neck", f, "+x"), n(c, s.neck, "neck", "head", k, "+x"), n(c, s.head, "neck", "head", k, "+x"), n(c, s.leftArm, "leftArm", "leftElbow", f, "-x"), n(c, s.leftElbow, "leftElbow", "leftWrist", f, "-x"), n(c, s.leftLeg, "leftLeg", "leftKnee", m, "+x"), n(c, s.leftKnee, "leftKnee", "leftFoot", m, "+x"), n(c, s.leftFoot, "leftFoot", "leftToes", m, "+x"), n(c, s.rightArm, "rightArm", "rightElbow", f, "-x"), n(c, s.rightElbow, "rightElbow", "rightWrist", f, "-x"), n(c, s.rightLeg, "rightLeg", "rightKnee", m, "+x"), n(c, s.rightKnee, "rightKnee", "rightFoot", m, "+x"), n(c, s.rightFoot, "rightFoot", "rightToes", m, "+x");
198
204
  }
199
205
  };
200
206
  }
201
207
  }
202
- const $ = new c.Vector2(), U = new c.Vector2();
208
+ const $ = new h.Vector2(), U = new h.Vector2();
203
209
  async function At(l, o) {
204
210
  const t = await S.createFromOptions(l, {
205
211
  baseOptions: {
@@ -209,7 +215,7 @@ async function At(l, o) {
209
215
  },
210
216
  runningMode: "VIDEO",
211
217
  numHands: 2
212
- }), e = (s, i, n) => ($.copy(s()), U.copy(i()), $.distanceTo(n) < U.distanceTo(n));
218
+ }), e = (s, i, r) => ($.copy(s()), U.copy(i()), $.distanceTo(r) < U.distanceTo(r));
213
219
  return {
214
220
  left: new Z(t, "Left", e.bind(null, o.leftWrist, o.rightWrist)),
215
221
  right: new Z(t, "Right", e.bind(null, o.rightWrist, o.leftWrist))
@@ -238,16 +244,16 @@ const Mt = {
238
244
  pinky2: 18,
239
245
  pinky3: 19,
240
246
  pinky4: 20
241
- }, V = {
247
+ }, v = {
242
248
  thumb: ["thumb1", "thumb2", "thumb3", "thumb4"],
243
249
  index: ["index1", "index2", "index3", "index4"],
244
250
  middle: ["middle1", "middle2", "middle3", "middle4"],
245
251
  ring: ["ring1", "ring2", "ring3", "ring4"],
246
252
  pinky: ["pinky1", "pinky2", "pinky3", "pinky4"]
247
- }, vt = new c.Vector3(), j = new c.Vector3(), q = new c.Vector3(), K = new c.Vector3(), X = new c.Vector3(), Vt = new c.Vector3();
248
- new c.Vector3();
249
- new c.Vector3();
250
- const Q = new c.Vector3(), Y = Math.PI / 2, Nt = new c.Vector3(0, -1, 0);
253
+ }, Ft = new h.Vector3(), K = new h.Vector3(), j = new h.Vector3(), q = new h.Vector3(), X = new h.Vector3(), vt = new h.Vector3();
254
+ new h.Vector3();
255
+ new h.Vector3();
256
+ const Q = new h.Vector3(), Y = Math.PI / 2, Vt = new h.Vector3(0, -1, 0);
251
257
  class Z extends z {
252
258
  constructor(t, e, s) {
253
259
  super(Mt, S.HAND_CONNECTIONS);
@@ -263,12 +269,12 @@ class Z extends z {
263
269
  const s = this.handLandmarker.detectForVideo(t, performance.now());
264
270
  if (s.landmarks.length)
265
271
  for (let i = 0; i < s.landmarks.length; i++) {
266
- const n = s.landmarks[i], r = n[this.points.wrist];
267
- if (this.isMyWrist(r)) {
268
- this.updateLandmarks(s.worldLandmarks[i]), e.drawConnectors(n, S.HAND_CONNECTIONS, {
272
+ const r = s.landmarks[i], n = r[this.points.wrist];
273
+ if (this.isMyWrist(n)) {
274
+ this.updateLandmarks(s.worldLandmarks[i]), e.drawConnectors(r, S.HAND_CONNECTIONS, {
269
275
  color: this.side == "Left" ? "#00FF00" : "#0000FF",
270
276
  lineWidth: 4
271
- }), e.drawLandmarks(n, { color: this.side == "Left" ? "#00FF00" : "#0000FF", lineWidth: 3, radius: 1 });
277
+ }), e.drawLandmarks(r, { color: this.side == "Left" ? "#00FF00" : "#0000FF", lineWidth: 3, radius: 1 });
272
278
  break;
273
279
  }
274
280
  }
@@ -283,51 +289,51 @@ class Z extends z {
283
289
  * @see https://ai.google.dev/edge/mediapipe/solutions/vision/hand_landmarker
284
290
  */
285
291
  syncHandBones(t, e, s) {
286
- const i = vt.crossVectors(
287
- j.copy(this.marks.index1.worldPosition).sub(this.marks.wrist.worldPosition),
288
- q.copy(this.marks.pinky1.worldPosition).sub(this.marks.wrist.worldPosition)
289
- ).normalize(), n = j.copy(this.marks.palm.worldPosition).sub(this.marks.wrist.worldPosition).normalize(), r = q.copy(this.marks.pinky1.worldPosition).sub(this.marks.index1.worldPosition).normalize();
290
- if (!(n.dot(Nt) > 0.8)) {
292
+ const i = Ft.crossVectors(
293
+ K.copy(this.marks.index1.worldPosition).sub(this.marks.wrist.worldPosition),
294
+ j.copy(this.marks.pinky1.worldPosition).sub(this.marks.wrist.worldPosition)
295
+ ).normalize(), r = K.copy(this.marks.palm.worldPosition).sub(this.marks.wrist.worldPosition).normalize(), n = j.copy(this.marks.pinky1.worldPosition).sub(this.marks.index1.worldPosition).normalize();
296
+ if (!(r.dot(Vt) > 0.8)) {
291
297
  if (e.wrist) {
292
- const a = E(K, e.wrist, s).add(n).applyMatrix4(s.matrixWorld), p = E(X, e.wrist, s).sub(r).applyMatrix4(s.matrixWorld), u = this.getGhost(e.wrist);
293
- A(u, a, p, "-y"), u.rotateX(Y), u.lerp(e.wrist, t);
298
+ const a = E(q, e.wrist, s).add(r).applyMatrix4(s.matrixWorld), c = E(X, e.wrist, s).sub(n).applyMatrix4(s.matrixWorld), m = this.getGhost(e.wrist);
299
+ A(m, a, c, "-y"), m.rotateX(Y), m.lerp(e.wrist, t);
294
300
  }
295
- this.syncFinger(t, s, i, n, r, e, V.index, "middle1"), this.syncFinger(t, s, i, n, r, e, V.middle, "ring1"), this.syncFinger(t, s, i, n, r, e, V.ring, "pinky1"), this.syncFinger(t, s, i, n, r, e, V.pinky, "ring1", !0), this.syncFinger(t, s, i, n, r, e, V.thumb, "index1");
301
+ this.syncFinger(t, s, i, r, n, e, v.index, "middle1"), this.syncFinger(t, s, i, r, n, e, v.middle, "ring1"), this.syncFinger(t, s, i, r, n, e, v.ring, "pinky1"), this.syncFinger(t, s, i, r, n, e, v.pinky, "ring1", !0), this.syncFinger(t, s, i, r, n, e, v.thumb, "index1");
296
302
  }
297
303
  }
298
- syncFinger(t, e, s, i, n, r, a, p, u = !1) {
304
+ syncFinger(t, e, s, i, r, n, a, c, m = !1) {
299
305
  for (let f = 0; f < a.length - 1; f++) {
300
- const k = r[a[f]];
306
+ const k = n[a[f]];
301
307
  if (!k) continue;
302
- const d = K.copy(this.marks[a[f + 1]].worldPosition).sub(this.marks[a[f]].worldPosition).normalize(), h = E(X, k, e), P = Vt.copy(h).add(n);
303
- u && P.negate();
304
- const b = this.getGhost(k);
308
+ const d = q.copy(this.marks[a[f + 1]].worldPosition).sub(this.marks[a[f]].worldPosition).normalize(), p = E(X, k, e), P = vt.copy(p).add(r);
309
+ m && P.negate();
310
+ const x = this.getGhost(k);
305
311
  f == 0 ? (Q.copy(P), A(
306
- b,
307
- d.add(h).applyMatrix4(e.matrixWorld),
308
- P.add(h).applyMatrix4(e.matrixWorld),
312
+ x,
313
+ d.add(p).applyMatrix4(e.matrixWorld),
314
+ P.add(p).applyMatrix4(e.matrixWorld),
309
315
  this.lookAtPoleAxis
310
316
  )) : (P.copy(Q), A(
311
- b,
312
- d.add(h).applyMatrix4(e.matrixWorld),
313
- P.add(h).applyMatrix4(e.matrixWorld),
317
+ x,
318
+ d.add(p).applyMatrix4(e.matrixWorld),
319
+ P.add(p).applyMatrix4(e.matrixWorld),
314
320
  this.lookAtPoleAxis
315
- )), b.rotateX(Y), b.lerp(k, t);
321
+ )), x.rotateX(Y), x.lerp(k, t);
316
322
  }
317
323
  }
318
324
  bind(t, e) {
319
- const s = {}, i = (n, r) => {
320
- const a = L(t, n);
321
- a && (s[r] = a);
325
+ const s = {}, i = (r, n) => {
326
+ const a = w(t, r);
327
+ a && (s[n] = a);
322
328
  };
323
329
  return i(this.isLeft ? e.handL : e.handR, "wrist"), i(this.isLeft ? e.index1L : e.index1R, "index1"), i(this.isLeft ? e.index2L : e.index2R, "index2"), i(this.isLeft ? e.index3L : e.index3R, "index3"), i(this.isLeft ? e.middle1L : e.middle1R, "middle1"), i(this.isLeft ? e.middle2L : e.middle2R, "middle2"), i(this.isLeft ? e.middle3L : e.middle3R, "middle3"), i(this.isLeft ? e.ring1L : e.ring1R, "ring1"), i(this.isLeft ? e.ring2L : e.ring2R, "ring2"), i(this.isLeft ? e.ring3L : e.ring3R, "ring3"), i(this.isLeft ? e.pinky1L : e.pinky1R, "pinky1"), i(this.isLeft ? e.pinky2L : e.pinky2R, "pinky2"), i(this.isLeft ? e.pinky3L : e.pinky3R, "pinky3"), i(this.isLeft ? e.thumb1L : e.thumb1R, "thumb1"), i(this.isLeft ? e.thumb2L : e.thumb2R, "thumb2"), i(this.isLeft ? e.thumb3L : e.thumb3R, "thumb3"), {
324
- update: (n) => {
325
- this.syncHandBones(n, s, t);
330
+ update: (r) => {
331
+ this.syncHandBones(r, s, t);
326
332
  }
327
333
  };
328
334
  }
329
335
  }
330
- async function Ft(l, o) {
336
+ async function Nt(l, o) {
331
337
  const t = await C.createFromOptions(l, {
332
338
  baseOptions: {
333
339
  modelAssetPath: (o == null ? void 0 : o.modelPath) ?? "face_landmarker.task",
@@ -352,8 +358,8 @@ const Ot = {
352
358
  noseBone: 6,
353
359
  chin: 152,
354
360
  forehead: 10
355
- }, _t = new w(), St = new w(), ot = new w(), Ct = new w(), zt = new w();
356
- new w();
361
+ }, _t = new L(), St = new L(), ot = new L(), Ct = new L(), zt = new L();
362
+ new L();
357
363
  class Dt extends z {
358
364
  // lower = smoother but more lag, higher = more responsive
359
365
  constructor(t) {
@@ -365,9 +371,9 @@ class Dt extends z {
365
371
  this.faceLandmarker = t, this.root.scale.y *= -1, this.root.scale.z *= -1, this.root.scale.multiplyScalar(3);
366
372
  }
367
373
  predict(t, e) {
368
- var i, n, r;
374
+ var i, r, n;
369
375
  const s = this.faceLandmarker.detectForVideo(t, performance.now());
370
- s.faceLandmarks[0] && (e.drawConnectors(s.faceLandmarks[0], C.FACE_LANDMARKS_TESSELATION, { color: "#00fff2ff", lineWidth: 0.1 }), e.drawLandmarks(s.faceLandmarks[0], { color: "#00ff00", lineWidth: 0.1, radius: 0.4 }), this.updateLandmarks(s.faceLandmarks[0], s.faceLandmarks[0])), this.blendshapeCategories = (n = (i = s.faceBlendshapes) == null ? void 0 : i[0]) == null ? void 0 : n.categories, (r = this.blendshapeCategories) == null || r.forEach((a) => {
376
+ s.faceLandmarks[0] && (e.drawConnectors(s.faceLandmarks[0], C.FACE_LANDMARKS_TESSELATION, { color: "#00fff2ff", lineWidth: 0.1 }), e.drawLandmarks(s.faceLandmarks[0], { color: "#00ff00", lineWidth: 0.1, radius: 0.4 }), this.updateLandmarks(s.faceLandmarks[0], s.faceLandmarks[0])), this.blendshapeCategories = (r = (i = s.faceBlendshapes) == null ? void 0 : i[0]) == null ? void 0 : r.categories, (n = this.blendshapeCategories) == null || n.forEach((a) => {
371
377
  this.blendshapeMap.set(a.categoryName, a.score);
372
378
  });
373
379
  }
@@ -376,23 +382,23 @@ class Dt extends z {
376
382
  return {
377
383
  update: (s) => {
378
384
  var i;
379
- (i = this.blendshapeCategories) == null || i.forEach((n) => {
380
- const { categoryName: r, score: a } = n;
381
- if (!(e != null && e.hasOwnProperty(r))) return;
382
- this.smoothed[r] === void 0 && (this.smoothed[r] = a);
383
- const p = 1 - Math.pow(this.smoothing, s);
384
- this.smoothed[r] += (a - this.smoothed[r]) * p, t.morphTargetInfluences[e[r]] = this.smoothed[r];
385
+ (i = this.blendshapeCategories) == null || i.forEach((r) => {
386
+ const { categoryName: n, score: a } = r;
387
+ if (!(e != null && e.hasOwnProperty(n))) return;
388
+ this.smoothed[n] === void 0 && (this.smoothed[n] = a);
389
+ const c = 1 - Math.pow(this.smoothing, s);
390
+ this.smoothed[n] += (a - this.smoothed[n]) * c, t.morphTargetInfluences[e[n]] = this.smoothed[n];
385
391
  });
386
392
  }
387
393
  };
388
394
  }
389
395
  bind(t) {
390
- const e = new J(t, "L"), s = new J(t, "R"), i = L(t, "head");
396
+ const e = new J(t, "L"), s = new J(t, "R"), i = w(t, "head");
391
397
  return {
392
- update: (n) => {
393
- if (e.update(n, this.blendshapeMap), s.update(n, this.blendshapeMap), !i) return;
394
- const r = _t.copy(this.marks.earL.worldPosition), a = St.copy(this.marks.earR.worldPosition), p = ot.subVectors(r, a).multiplyScalar(0.5).add(a), u = Ct.subVectors(this.marks.noseTip.worldPosition, p), f = r.sub(a), k = E(zt, i, t), d = f.add(k).applyMatrix4(t.matrixWorld), h = u.add(k).applyMatrix4(t.matrixWorld);
395
- A(i, h, d, "+x");
398
+ update: (r) => {
399
+ if (e.update(r, this.blendshapeMap), s.update(r, this.blendshapeMap), !i) return;
400
+ const n = _t.copy(this.marks.earL.worldPosition), a = St.copy(this.marks.earR.worldPosition), c = ot.subVectors(n, a).multiplyScalar(0.5).add(a), m = Ct.subVectors(this.marks.noseTip.worldPosition, c), f = n.sub(a), k = E(zt, i, t), d = f.add(k).applyMatrix4(t.matrixWorld), p = m.add(k).applyMatrix4(t.matrixWorld);
401
+ A(i, p, d, "+x");
396
402
  }
397
403
  };
398
404
  }
@@ -412,11 +418,11 @@ class J {
412
418
  update(o, t) {
413
419
  if (!this.eyeBone) return;
414
420
  E(ot, this.eyeBone, this.rig);
415
- const e = t.get(this.eyeLookOut) ?? 0, s = t.get(this.eyeLookIn) ?? 0, i = t.get(this.eyeLookUp) ?? 0, n = t.get(this.eyeLookDown) ?? 0, r = s - e, a = n - i;
416
- console.log("EYE: ", r, a), this.eyeBone.rotation.y = r * this.sign / 2, this.eyeBone.rotation.x = a / 2;
421
+ const e = t.get(this.eyeLookOut) ?? 0, s = t.get(this.eyeLookIn) ?? 0, i = t.get(this.eyeLookUp) ?? 0, r = t.get(this.eyeLookDown) ?? 0, n = s - e, a = r - i;
422
+ console.log("EYE: ", n, a), this.eyeBone.rotation.y = n * this.sign / 2, this.eyeBone.rotation.x = a / 2;
417
423
  }
418
424
  }
419
- const Bt = {
425
+ const Tt = {
420
426
  faceMesh: "face",
421
427
  head: "head",
422
428
  hips: "hips",
@@ -464,7 +470,7 @@ const Bt = {
464
470
  thumb1R: "thumb1R",
465
471
  thumb2R: "thumb2R",
466
472
  thumb3R: "thumb3R"
467
- }, Gt = () => {
473
+ }, gt = () => {
468
474
  var l;
469
475
  return !!((l = navigator.mediaDevices) != null && l.getUserMedia);
470
476
  };
@@ -492,96 +498,96 @@ async function Ut(l) {
492
498
  rightWrist: () => s.rightWristNormalizedPosition,
493
499
  modelPath: o.modelPaths.hand,
494
500
  ...l == null ? void 0 : l.handsTrackerOptions
495
- }), n = o.ignoreFace ? void 0 : await Ft(e, { modelPath: o.modelPaths.face }), r = document.createElement("div");
496
- r.style.position = "absolute", r.style.top = "0px", r.style.left = "0px", r.style.zIndex = "21", r.classList.add("three-mediapipe-rig"), document.body.appendChild(r);
497
- const a = document.createElement("canvas"), p = a.getContext("2d"), u = new dt(p);
498
- a.style.zIndex = "22", a.style.position = "absolute", a.style.top = "0px", a.style.left = "0px", a.style.pointerEvents = "none", r.appendChild(a);
501
+ }), r = o.ignoreFace ? void 0 : await Nt(e, { modelPath: o.modelPaths.face }), n = document.createElement("div");
502
+ n.style.position = "absolute", n.style.top = "0px", n.style.left = "0px", n.style.zIndex = "21", n.classList.add("three-mediapipe-rig"), document.body.appendChild(n);
503
+ const a = document.createElement("canvas"), c = a.getContext("2d"), m = new dt(c);
504
+ a.style.zIndex = "22", a.style.position = "absolute", a.style.top = "0px", a.style.left = "0px", a.style.pointerEvents = "none", n.appendChild(a);
499
505
  function f(d) {
500
- p.save(), p.clearRect(0, 0, a.width, a.height), s == null || s.predict(d, u), i == null || i.left.predict(d, u), i == null || i.right.predict(d, u), n == null || n.predict(d, u), p.restore();
506
+ c.save(), c.clearRect(0, 0, a.width, a.height), s == null || s.predict(d, m), i == null || i.left.predict(d, m), i == null || i.right.predict(d, m), r == null || r.predict(d, m), c.restore();
501
507
  }
502
508
  function k() {
503
- t = document.createElement("video"), r.appendChild(t);
509
+ t = document.createElement("video"), n.appendChild(t);
504
510
  let d = -1;
505
511
  t.style.zIndex = "21", t.style.position = "absolute", t.style.top = "0px", t.style.left = "0px", o.debugVideo && (t.src = o.debugVideo, t.controls = !0, t.loop = !0, t.muted = !0, t.controls = !0, t.play());
506
- function h() {
507
- d !== t.currentTime && (f(t), d = t.currentTime), window.requestAnimationFrame(h);
512
+ function p() {
513
+ d !== t.currentTime && (f(t), d = t.currentTime), window.requestAnimationFrame(p);
508
514
  }
509
515
  t.addEventListener("loadeddata", () => {
510
- t.width = t.videoWidth * o.displayScale, t.height = t.videoHeight * o.displayScale, a.width = t.videoWidth, a.height = t.videoHeight, a.style.height = t.height + "px", a.style.width = t.width + "px", window.requestAnimationFrame(h);
516
+ t.width = t.videoWidth * o.displayScale, t.height = t.videoHeight * o.displayScale, a.width = t.videoWidth, a.height = t.videoHeight, a.style.height = t.height + "px", a.style.width = t.width + "px", window.requestAnimationFrame(p);
511
517
  });
512
518
  }
513
519
  if (o.debugFrame) {
514
520
  const d = document.createElement("img");
515
521
  d.src = o.debugFrame, d.style.zIndex = "21", d.style.position = "absolute", d.style.top = "0px", d.style.left = "0px", document.body.appendChild(d), d.addEventListener("load", () => {
516
522
  d.width = d.naturalWidth * o.displayScale, d.height = d.naturalHeight * o.displayScale, a.width = d.naturalWidth, a.height = d.naturalWidth, a.style.width = d.width + "px", a.style.height = d.height + "px";
517
- function h() {
523
+ function p() {
518
524
  f(d);
519
525
  }
520
- window.requestAnimationFrame(h);
526
+ window.requestAnimationFrame(p);
521
527
  });
522
528
  } else o.debugVideo && k();
523
529
  return {
524
530
  poseTracker: s,
525
531
  handsTracker: i,
526
- faceTracker: n,
532
+ faceTracker: r,
527
533
  video: t,
528
534
  /**
529
535
  * A div that contains the video and canvas used to display the landmarks stacked on top of each other.
530
536
  */
531
- domElement: r,
537
+ domElement: n,
532
538
  /**
533
539
  * Start the webcam feed. This must be initiated by a user triggered event ( a click on a button ) due to security reasons.
534
540
  */
535
541
  start: async () => {
536
542
  let d = !1;
537
- if (!Gt())
543
+ if (!gt())
538
544
  throw new Error("Webcam not supported");
539
545
  t || k();
540
- let h;
541
- function P(m) {
542
- console.warn("Camera track ended, attempting recovery..."), b(m), R(m);
546
+ let p;
547
+ function P(u) {
548
+ console.warn("Camera track ended, attempting recovery..."), x(u), R(u);
543
549
  }
544
- function b(m) {
545
- h == null || h.getTracks().forEach((x) => x.stop()), h = void 0, m.srcObject = null;
550
+ function x(u) {
551
+ p == null || p.getTracks().forEach((b) => b.stop()), p = void 0, u.srcObject = null;
546
552
  }
547
- async function R(m, x = 0) {
548
- const st = Math.min(1e3 * 2 ** x, 16e3);
549
- if (x >= 5)
553
+ async function R(u, b = 0) {
554
+ const st = Math.min(1e3 * 2 ** b, 16e3);
555
+ if (b >= 5)
550
556
  throw new Error("Camera recovery failed after max attempts");
551
557
  if (await new Promise((it) => setTimeout(it, st)), !d)
552
558
  try {
553
- await W(m), console.log("Camera recovered successfully");
559
+ await W(u), console.log("Camera recovered successfully");
554
560
  } catch {
555
- R(m, x + 1);
561
+ R(u, b + 1);
556
562
  }
557
563
  }
558
- async function W(m) {
564
+ async function W(u) {
559
565
  try {
560
- h = await navigator.mediaDevices.getUserMedia({ video: !0 }), m.srcObject = h, await m.play(), h.getVideoTracks().forEach((x) => {
561
- x.addEventListener("ended", () => P(m));
566
+ p = await navigator.mediaDevices.getUserMedia({ video: !0 }), u.srcObject = p, await u.play(), p.getVideoTracks().forEach((b) => {
567
+ b.addEventListener("ended", () => P(u));
562
568
  });
563
- } catch (x) {
564
- M(x, m);
569
+ } catch (b) {
570
+ M(b, u);
565
571
  }
566
572
  }
567
- function M(m, x) {
568
- if (m instanceof DOMException)
569
- switch (m.name) {
573
+ function M(u, b) {
574
+ if (u instanceof DOMException)
575
+ switch (u.name) {
570
576
  case "NotAllowedError":
571
577
  throw new Error("Permission denied — prompt user to allow camera");
572
578
  case "NotFoundError":
573
- console.error("No camera found — retry when device is connected"), R(x);
579
+ console.error("No camera found — retry when device is connected"), R(b);
574
580
  break;
575
581
  case "NotReadableError":
576
- console.error("Camera in use by another app"), R(x);
582
+ console.error("Camera in use by another app"), R(b);
577
583
  break;
578
584
  default:
579
- console.error("Camera error:", m.message), R(x);
585
+ console.error("Camera error:", u.message), R(b);
580
586
  }
581
587
  }
582
588
  return await W(t), {
583
589
  stop: () => {
584
- d = !0, b(t);
590
+ d = !0, x(t);
585
591
  }
586
592
  };
587
593
  },
@@ -590,16 +596,16 @@ async function Ut(l) {
590
596
  * @param rig The rig that contains all the bones and skinned meshes of your character.
591
597
  * @param magging The bone mapping to use for the rig.
592
598
  */
593
- bind: (d, h) => {
594
- h = h || Bt;
595
- const P = s.bind(d, h), b = i.left.bind(d, h), R = i.right.bind(d, h);
599
+ bind: (d, p) => {
600
+ p = p || Tt;
601
+ const P = s.bind(d, p), x = i.left.bind(d, p), R = i.right.bind(d, p);
596
602
  let W;
597
- const M = n == null ? void 0 : n.bind(d);
598
- return d.traverse((m) => {
599
- m instanceof c.Mesh && m.name.indexOf(h.faceMesh) === 0 && (m.frustumCulled = !1, W = n == null ? void 0 : n.bindShapeKeys(m));
603
+ const M = r == null ? void 0 : r.bind(d);
604
+ return d.traverse((u) => {
605
+ u instanceof h.Mesh && u.name.indexOf(p.faceMesh) === 0 && (u.frustumCulled = !1, W = r == null ? void 0 : r.bindShapeKeys(u));
600
606
  }), {
601
- update: (m) => {
602
- P.update(m), b.update(m), R.update(m), W == null || W.update(m), M == null || M.update(m);
607
+ update: (u) => {
608
+ P.update(u), x.update(u), R.update(u), W == null || W.update(u), M == null || M.update(u);
603
609
  }
604
610
  };
605
611
  }
@@ -1 +1 @@
1
- {"version":3,"file":"three-mediapipe-rig.js","sources":["../src/tracking/util/lookAt.ts","../src/tracking/Tracker.ts","../src/tracking/util/getRootPosition.ts","../src/tracking/util/cleanBoneName.ts","../src/tracking/util/getBoneByName.ts","../src/tracking/PoseTracker.ts","../src/tracking/HandTracker.ts","../src/tracking/FaceTracker.ts","../src/tracking/BoneMapping.ts","../src/tracking/TrackerManager.ts"],"sourcesContent":["import { Object3D, Quaternion, Vector3 } from \"three/webgpu\";\n\nconst poleDir = new Vector3();\nconst objectPosition = new Vector3();\n\nconst XAxis = new Vector3(1,0,0);\nconst XAxisNeg = new Vector3(-1,0,0);\nconst YAxis = new Vector3(0,1,0); \nconst YAxisNeg = new Vector3(0,-1,0); \nconst ZAxis = new Vector3(0,0,1); \nconst ZAxisNeg = new Vector3(0,0,-1); \n\nconst pole = new Vector3();\nconst lookDir = new Vector3();\n\nconst v = new Vector3();\nconst correction = new Quaternion();\nconst worldQuat = new Quaternion();\n\nexport type LookAtPoleAxis = \"+x\"|\"+y\"|\"-x\"|\"-y\"\n\n/**\n * Will point the Z axis of object at target and the X or Y axis in the general direction of the pole target\n * @param object The object to rotate\n * @param target The point to look at ( in world coord )\n * @param poleTarget The goal of the pole axis ( in world coord )\n * @param poleAxis The axis to use as the pole axis ( z is the one pointing at the target )\n */\nexport function lookAt( object:Object3D, target:Vector3, poleTarget:Vector3, poleAxis:LookAtPoleAxis = \"+x\" )\n{ \n\t//\n\t// look at target (handles parent transforms internally)\n\t// \n\tobject.lookAt(target);\n\n\tconst axis = poleAxis==\"+x\"?XAxis: poleAxis==\"-x\"?XAxisNeg: poleAxis==\"+y\"?YAxis: YAxisNeg;\n\n\tobject.getWorldPosition(objectPosition);\n\tobject.getWorldQuaternion(worldQuat);\n\n\tpoleDir.subVectors(poleTarget, objectPosition).normalize();\n\n\t// direction in which the pole axis is currently pointing (in world space)\n\tpole.copy(axis).applyQuaternion(worldQuat);\n\n\tconst currentPole = pole;\n\n\t// look direction in world space\n\tconst lookAxisDir = lookDir.copy( ZAxis ).applyQuaternion(worldQuat);\n\n\t// project desired pole direction onto the plane perpendicular to the look axis\n\tconst desiredPoleDir = poleDir.clone().addScaledVector(lookAxisDir, -poleDir.dot(lookAxisDir)).normalize();\n\n\t// signed angle between current pole and desired pole around the look axis\n\tconst cross = v.crossVectors(currentPole, desiredPoleDir);\n\tconst angle = Math.atan2(cross.dot(lookAxisDir), currentPole.dot(desiredPoleDir));\n\n\t// The correction is a spin around the look axis (local Z after lookAt).\n\t// Since lookAt aligned local Z to the target, we can apply around the local Z axis directly.\n\tcorrection.setFromAxisAngle(ZAxis, angle);\n\tobject.quaternion.multiply(correction);\n}","import * as THREE from \"three/webgpu\";\nimport {\n Landmark,\n NormalizedLandmark,\n\tDrawingUtils, \n} from \"@mediapipe/tasks-vision\"; \nimport { lookAt, LookAtPoleAxis } from \"./util/lookAt\";\n\n \n\nconst v = new THREE.Vector3();\nconst A = new THREE.Vector3();\nconst B = new THREE.Vector3();\nconst C = new THREE.Vector3();\n\nexport class Tracker<T extends Record<string, number|number[]> > {\n\tprivate objectGhost : Map<THREE.Object3D, Ghost> ;\n\treadonly root:THREE.Object3D;\n\n\t/**\n\t * per landmark index, it points to it's object3D equivalent.\n\t */\n\tprotected marks: { [name in keyof T]: Mark } = {} as { [name in keyof T]: Mark };\n\n\tconstructor( protected readonly points:T, private readonly debugConnections?:{start:number,end:number}[] ){\n\t\tthis.root = new THREE.Object3D();\n\t\tthis.objectGhost = new Map();\n\n\t\t// por each key in points\n\t\tfor( let key in this.points ){\n\t\t\tthis.marks[key] = new Mark();\n \n\t\t\tthis.root.add(this.marks[key]);\n\t\t}\n\t}\n\n\tprotected updateLandmarks( landmarks:Landmark[], debugLandmarks?:NormalizedLandmark[], debugDrawer?:DrawingUtils ) {\n\t\tfor( let key in this.points ){\n\t\t\tconst point = this.points[key];\n\t\t\tconst mark = this.marks[key];\n\t\t\tif( mark ){\n\t\t\t\tif( point instanceof Array )\n\t\t\t\t{\n\t\t\t\t\t\n\t\t\t\t\tv.copy( landmarks[ point[0] ] ) \n\t\t\t\t\tmark.position.copy( landmarks[ point[1] ] ).sub( v ).divideScalar(2).add(landmarks[ point[0] ]);\n\t\t\t\t\t\n\t\t\t\t\tif( point.length==4 )\n\t\t\t\t\t{\n\t\t\t\t\t\tv.subVectors(\n\t\t\t\t\t\t\tlandmarks[ point[3] ],\n\t\t\t\t\t\t\tlandmarks[ point[2] ]\n\t\t\t\t\t\t).divideScalar(2).add(landmarks[ point[2] ]) \n\n\t\t\t\t\t\t.sub( mark.position )\n\t\t\t\t\t\t.divideScalar(2) \n\n\t\t\t\t\t\tmark.position.add( v );\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\telse \n\t\t\t\t{\n\t\t\t\t\tmark.position.copy( landmarks[ point as number ] )\n\t\t\t\t}\n \n\t\t\t}\n\t\t}\n\n\t\tif( debugDrawer && debugLandmarks )\n\t\t{ \n\t\t\t// debugDrawer.drawLandmarks(debugLandmarks, {\n\t\t\t// \tradius: (data) =>\n\t\t\t// \t\tDrawingUtils.lerp(data.from!.z, -0.15, 0.1, 5, 1),\n\t\t\t// \tlineWidth:1\n\t\t\t// });\n\t\t\tdebugDrawer.drawConnectors(\n\t\t\t\tdebugLandmarks,\n\t\t\t\tthis.debugConnections,\n\t\t\t\t{\n\t\t\t\t\tlineWidth:1\n\t\t\t\t}\n\t\t\t); \n\t\t}\n\t}\n\n\tprotected getGhost( object:THREE.Object3D ){\n\t\tif( !this.objectGhost.has(object)) \n\t\t{\n\t\t\tconst o = new Ghost()\n\n\t\t\to.position.copy(object.position)\n\t\t\to.quaternion.copy(object.quaternion)\n\t\t\tobject.parent?.add(o);\n\n\t\t\tthis.objectGhost.set(object, o)\n\t\t} \n\t\treturn this.objectGhost.get(object)!;\n\t}\n\n\tpredict( source:TexImageSource, drawingUtils:DrawingUtils ){\n\t\tthrow new Error(\"Method 'predict' must be implemented.\");\n\t}\n\n\tsync ( delta:number, objects: [THREE.Object3D, keyof T, keyof T, LookAtPoleAxis][] ) {\n\t\tthrow new Error(\"Method 'sync' must be implemented.\"); \n\t}\n\n\ttest( key:keyof T ){\n\t\tthis.marks[key]!.position.set(1,2,3)\n\t}\n\n\tprotected syncObjects(objects: [THREE.Object3D, keyof T, keyof T,LookAtPoleAxis][], delta:number, normal:THREE.Vector3 ){\n\t\tfor( const [object, root, target, poleAxis] of objects ){\n\n\t\t\t//\n\t\t\t// position A and B where the landmarks are\n\t\t\t//\n\t\t\tthis.marks[target].getWorldPosition(B)\n\t\t\tthis.marks[root].getWorldPosition(A)\n\n\t\t\t//\n\t\t\t// calcuate the offset\n\t\t\t//\n\t\t\tconst offset = B.sub(A); // offset from root to taget in world units\n\n\t\t\t//\n\t\t\t// now position A in object position\n\t\t\t//\n\t\t\tobject.getWorldPosition(A)\n\n\t\t\t//\n\t\t\t// and displace it by the offset ( this will be the look at target )\n\t\t\t//\n\t\t\tA.add(offset);\n\n\t\t\t \n\t\t\tconst objectLookAtGoal = A;\n\t\t\tconst polePosition = object.getWorldPosition(B).sub( normal )\n\n\t\t\tconst ghost = this.getGhost(object);\n \n\n\t\t\t \n\t\t\t\tlookAt( ghost, objectLookAtGoal, polePosition, poleAxis);\n\n\t\t\t\tghost.rotateX( Math.PI/2) \n\t\t\t\n\t\t\t//ghost.rotateY( Math.PI/2)\n\n\t\t\tobject.position.lerp(ghost.position, delta * 4)\n\t\t\tobject.quaternion.slerp(ghost.quaternion, delta * 4) \n\t\t}\n\t}\n\n\tprotected getBone( rig:THREE.Object3D, name:string ){\n\t\treturn rig.getObjectByName(name.replace(/[\\.\\:]/g,\"\")) ;\n\t}\n}\n\n// const t = {\n// \tpepe:[1,2]\n// }\n// const d = new Tracker(t)\n// d.test(\"pepe\")\n\nclass Mark extends THREE.Mesh {\n\tprivate _worldPosition = new THREE.Vector3();\n\tconstructor() {\n\t\tsuper(new THREE.SphereGeometry(0.01,3,3), new THREE.MeshStandardMaterial({ color: 0xff0000, wireframe:true }));\n\t\tthis.add( new THREE.AxesHelper(0.001))\n\t}\n\n\tget worldPosition(){\n\t\tthis.getWorldPosition(this._worldPosition);\n\t\treturn this._worldPosition;\n\t}\n}\n\nclass Ghost extends THREE.Object3D { \n\tlerp( target:THREE.Object3D, delta:number, speed = 8 )\n\t{\n\t\ttarget.position.lerp(this.position, delta * speed)\n\t\ttarget.quaternion.slerp(this.quaternion, delta * speed) \n\t}\n}","import { Object3D, Vector3 } from \"three/webgpu\";\n\n\n/**\n * Gets the position of `object` relative to `root`.\n * @param out \n * @param object \n * @param root \n * @returns \n */\nexport function rootPosition( out:Vector3, object:Object3D, root:Object3D ) {\n\n\troot.worldToLocal( object.getWorldPosition(out) )\n\n\treturn out;\n}","export function cleanBoneName(name:string) {\n\treturn name.replace(/[\\.\\:]/g,\"\")\n}","import { Bone, Object3D } from \"three\";\nimport { cleanBoneName } from \"./cleanBoneName\";\n\nexport function getBoneByName(rig:Object3D, name:string) {\n\tlet bone:Bone|undefined;\n\tname = cleanBoneName(name); \n\t\n\trig.traverse( (o:Object3D) => {\n\t\tif( o.name.indexOf(name)===0 && o instanceof Bone ) bone = o as Bone;\n\t})\n\n\tif( !bone ) console.log(\"Bone not found: \", name, rig.name)\n\n\treturn bone;\n}","import {\n DrawingUtils,\n NormalizedLandmark,\n PoseLandmarker,\n} from \"@mediapipe/tasks-vision\"; \nimport * as THREE from \"three/webgpu\";\nimport { lookAt, LookAtPoleAxis } from \"./util/lookAt\";\nimport { Tracker } from \"./Tracker\";\nimport { rootPosition } from \"./util/getRootPosition\";\nimport { getBoneByName } from \"./util/getBoneByName\";\nimport { BoneMap } from \"./BoneMapping\";\n\nexport async function loadPoseTracker(vision: any, config?:Partial<PoseTrackerConfig>) {\n\tconst poseLandmarker = await PoseLandmarker.createFromOptions(vision, {\n baseOptions: { \n\t\t\tmodelAssetPath: config?.modelPath ?? \"pose_landmarker_lite.task\",\n //modelAssetPath: `https://storage.googleapis.com/mediapipe-models/pose_landmarker/pose_landmarker_lite/float16/1/pose_landmarker_lite.task`,\n //modelAssetPath: \"https://storage.googleapis.com/mediapipe-models/pose_landmarker/pose_landmarker_heavy/float16/latest/pose_landmarker_heavy.task\",\n delegate: \"GPU\",\n },\n runningMode: \"VIDEO\",\n numPoses: 1,\n });\n\n\treturn new PoseTracker(poseLandmarker, config);\n} \n\n/**\n * Points derived from https://ai.google.dev/static/mediapipe/images/solutions/pose_landmarks_index.png\n * If the array has 2 elements, the point is between those 2 landmarks.\n * If it has 4, the point is at the center of those 4 landmarks.\n */\nconst poseMarks = {\n\t\t\thips: [24,23],\n\t\t\tneck: [12,11],\n\t\t\tleftLeg: 23,\n\t\t\tleftKnee:25,\n\t\t\tleftArm: 11,\n\t\t\tleftElbow: 13,\n\t\t\tleftWrist: 15,\n\t\t\trightLeg: 24,\n\t\t\trightKnee: 26,\n\t\t\trightArm: 12,\n\t\t\trightElbow: 14,\n\t\t\trightWrist: 16, \n\t\t\thead: [8,7] //between the ears\n\t\t\t, mouth:[10,9]\n\t\t\t, torso: [24,23, 12,11] //at the center of the torso\n\t\t\t, leftEar: 7\n\t\t\t, rightEar: 8\n\t\t} ;\n\ntype MarkKey = keyof typeof poseMarks;\n\ntype BoneBinding = [THREE.Object3D, MarkKey, MarkKey,LookAtPoleAxis]\n\nconst A = new THREE.Vector3();\nconst B = new THREE.Vector3();\nconst C = new THREE.Vector3();\nconst D = new THREE.Vector3();\nconst E = new THREE.Vector3();\nconst lookGoal = new THREE.Vector3();\nconst poleGoal = new THREE.Vector3();\n\ntype PoseTrackerConfig = {\n\tignoreLegs:boolean\n\tmodelPath:string\n}\n\n/**\n * @see https://ai.google.dev/edge/mediapipe/solutions/vision/pose_landmarker\n */\nclass PoseTracker extends Tracker<typeof poseMarks> {\n\tprivate _leftWristNormalizedPosition!:NormalizedLandmark;\n\tprivate _rightWristNormalizedPosition!:NormalizedLandmark;\n\n\t/**\n\t * Position of the left wrist in normalized coordinates (0..1)\n\t */\n\tget leftWristNormalizedPosition() { return this._leftWristNormalizedPosition; }\n\n\t/**\n\t * Position of the right wrist in normalized coordinates (0..1)\n\t */\n\tget rightWristNormalizedPosition() { return this._rightWristNormalizedPosition; }\n\n\tconstructor(private readonly poseLandmarker:PoseLandmarker, private readonly config?:Partial<PoseTrackerConfig>){ \n\n\t\tsuper(poseMarks, PoseLandmarker.POSE_CONNECTIONS)\n\t\t\n\t\tthis.root.scale.y *= -2\n\t\tthis.root.scale.z *= -2\n\t\tthis.root.scale.x *= 2 \n\t}\n\n\toverride predict( source:TexImageSource, drawingUtils:DrawingUtils ){\n\t\tthis.poseLandmarker.detectForVideo( source, performance.now(), (result) => {\n\n\t\t\tif( result.landmarks.length==0 )\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n \n\t\t\tthis.updateLandmarks( result.worldLandmarks[0], result.landmarks[0], drawingUtils );\n\n\t\t\t\n\t\t\tthis._leftWristNormalizedPosition = result.landmarks[0][ this.points.leftWrist ];\n\t\t\tthis._rightWristNormalizedPosition = result.landmarks[0][ this.points.rightWrist ];\n\t\t} );\n\t}\n\n\t// override sync ( delta:number, objects: BoneBinding[] ) {\n\n\t// \tconst hipsPos = this.marks.hips.getWorldPosition(C); \n\n\t// \tthis.marks.rightArm.getWorldPosition(A).sub(hipsPos);\n\t// \tthis.marks.leftArm.getWorldPosition(B).sub(hipsPos); \n\n\t// \tconst torsoNormal = C.crossVectors(A,B);\n\n\t// \tthis.syncObjects(objects, delta, torsoNormal); \n\n\t// }\n\t\n\n\tbind( rig:THREE.Object3D, magging:BoneMap )\n\t{ \n\t\t \n\t\tconst map : { [key in MarkKey]?:THREE.Object3D } = {\n\t\t\t\"hips\": getBoneByName(rig, magging.hips),\n\t\t\t\"neck\": getBoneByName(rig, magging.neck),\n\t\t\t\"leftArm\": getBoneByName(rig, magging.armL),\n\t\t\t\"leftElbow\": getBoneByName(rig, magging.forearmL),\n\t\t\t\"leftWrist\": getBoneByName(rig, magging.handL),\n\t\t\t\"rightArm\": getBoneByName(rig, magging.armR),\n\t\t\t\"rightElbow\": getBoneByName(rig, magging.forearmR),\n\t\t\t\"rightWrist\": getBoneByName(rig, magging.handR),\n\t\t\t\"head\": getBoneByName(rig, magging.head), \n\t\t\t\"torso\": getBoneByName(rig, magging.torso),\n\t\t\t\"leftLeg\": getBoneByName(rig, magging.thighL),\n\t\t\t\"leftKnee\": getBoneByName(rig, magging.shinL),\n\t\t\t\"rightLeg\": getBoneByName(rig, magging.thighR),\n\t\t\t\"rightKnee\": getBoneByName(rig, magging.shinR),\n\t\t} \n\n\t\tif( this.config?.ignoreLegs ){\n\t\t\tdelete map.leftLeg\n\t\t\tdelete map.leftKnee\n\t\t\tdelete map.rightLeg\n\t\t\tdelete map.rightKnee\n\t\t}\n\n\t\tconst v = new THREE.Vector3();\n\t\tconst v2 = new THREE.Vector3();\n\n\t\tconst syncBone = ( delta:number, bone:THREE.Object3D|undefined, from:MarkKey, to:MarkKey, sideAxis:THREE.Vector3, poleAxis:LookAtPoleAxis ) => {\n\t\t\tif( !bone ) return;\n\n\t\t\tconst hipsDir = this.marks[to].getWorldPosition(v).sub(this.marks[from].getWorldPosition(v2)).normalize(); \n\n\t\t \n\t\t\trootPosition(lookGoal, bone, rig).add( hipsDir ).applyMatrix4(rig.matrixWorld) ;\n\t\t\trootPosition(poleGoal, bone, rig).add( sideAxis ).applyMatrix4(rig.matrixWorld) ; \n\n\t\t\tconst ghost = this.getGhost(bone)\n\n\t\t\tlookAt(ghost, lookGoal, poleGoal, poleAxis)\n\t\t\tghost.rotateX(Math.PI/2)\n\t\t\t \n\n\t\t\tghost.lerp(bone, delta)\n\t\t}\n\n\t\treturn {\n\t\t\tupdate: (delta:number)=>{\n \n\t\t\t\tconst sideHips = this.marks.leftLeg.getWorldPosition(A).sub(this.marks.rightLeg.getWorldPosition(B)).normalize();\n\t\t\t\tconst sideShoulders = this.marks.leftArm.getWorldPosition(B).sub(this.marks.rightArm.getWorldPosition(C)).normalize();\n\t\t\t\tconst sideHead = this.marks.leftEar.getWorldPosition(D).sub(this.marks.rightEar.getWorldPosition(E)).normalize();\n\n\t\t\t\tsyncBone(delta, map.hips, \"hips\", \"torso\", sideHips, \"+x\")\n\t\t\t\tsyncBone(delta, map.torso, \"torso\", \"neck\", sideShoulders, \"+x\")\n\t\t\t\tsyncBone(delta, map.neck, \"neck\", \"head\", sideHead, \"+x\")\n\t\t\t\tsyncBone(delta, map.head, \"neck\", \"head\", sideHead, \"+x\")\n\n\t\t\t\tsyncBone(delta, map.leftArm, \"leftArm\", \"leftElbow\", sideShoulders, \"-x\")\n\t\t\t\tsyncBone(delta, map.leftElbow, \"leftElbow\", \"leftWrist\", sideShoulders, \"-x\")\n\t\t\t\tsyncBone(delta, map.leftLeg, \"leftLeg\", \"leftKnee\", sideHips, \"-x\") \n\n\t\t\t\tsyncBone(delta, map.rightArm, \"rightArm\", \"rightElbow\", sideShoulders, \"-x\")\n\t\t\t\tsyncBone(delta, map.rightElbow, \"rightElbow\", \"rightWrist\", sideShoulders, \"-x\")\n\t\t\t\tsyncBone(delta, map.rightLeg, \"rightLeg\", \"rightKnee\", sideHips, \"-x\") \n\t\t\t\t\n\t\t\t}\n\t\t}\n\t}\n}\n ","import {\n\tDrawingUtils,\n HandLandmarker,\n\tHandLandmarkerOptions,\n\tNormalizedLandmark,\n} from \"@mediapipe/tasks-vision\";\nimport * as THREE from \"three/webgpu\";\nimport { lookAt, LookAtPoleAxis } from \"./util/lookAt\";\nimport { Tracker } from \"./Tracker\";\nimport { rootPosition } from \"./util/getRootPosition\";\nimport { getBoneByName } from \"./util/getBoneByName\";\nimport { BoneMap } from \"./BoneMapping\";\n\nexport type HandsTrackerConfig = {\n\tleftWrist: ()=>NormalizedLandmark;\n\trightWrist: ()=>NormalizedLandmark;\n\tmodelPath?:string\n} & Partial<HandLandmarkerOptions>;\n\nconst A = new THREE.Vector2();\nconst B = new THREE.Vector2();\n\nexport async function loadHandTracker(vision: any, config:HandsTrackerConfig ) {\n const landmarker = await HandLandmarker.createFromOptions(vision, {\n baseOptions: {\n modelAssetPath: config.modelPath ?? \"hand_landmarker.task\",\n //modelAssetPath: `https://storage.googleapis.com/mediapipe-models/hand_landmarker/hand_landmarker/float16/1/hand_landmarker.task`,\n delegate: \"GPU\",\n },\n runningMode: \"VIDEO\",\n numHands: 2,\n });\n\n\tconst isMyWrist = ( myWrist:()=>NormalizedLandmark, otherWrist:()=>NormalizedLandmark, handWrist:NormalizedLandmark ) => {\n\t\tA.copy(myWrist());\n\t\tB.copy(otherWrist());\n\t\treturn A.distanceTo(handWrist) < B.distanceTo(handWrist);\n\t}\n\n return {\n\t\tleft:new HandsTracker(landmarker, \"Left\", isMyWrist.bind(null, config.leftWrist, config.rightWrist) ),\n\t\tright:new HandsTracker(landmarker, \"Right\", isMyWrist.bind(null, config.rightWrist, config.leftWrist) )\n\t};\n}\n\nconst handMarks = {\n wrist: 0,\n\tpalm: [9,13],\n\n thumb1: 1,\n thumb2: 2,\n thumb3: 3,\n thumb4: 4,\n\n index1: 5,\n index2: 6,\n index3: 7,\n index4: 8,\n\n middle1: 9,\n middle2: 10,\n middle3: 11,\n middle4: 12,\n\n ring1: 13,\n ring2: 14,\n ring3: 15,\n ring4: 16,\n\n pinky1: 17,\n pinky2: 18,\n pinky3: 19,\n pinky4: 20,\n};\n\nexport type HandMarkName = keyof typeof handMarks;\n\nconst fingerKeys = {\n\tthumb: [\"thumb1\",\"thumb2\",\"thumb3\",\"thumb4\"],\n\tindex: [\"index1\",\"index2\",\"index3\",\"index4\"],\n\tmiddle: [\"middle1\",\"middle2\",\"middle3\",\"middle4\"],\n\tring: [\"ring1\",\"ring2\",\"ring3\",\"ring4\"],\n\tpinky: [\"pinky1\",\"pinky2\",\"pinky3\",\"pinky4\"]\n} as { [key:string]: HandMarkName[]} ;\n\n\ntype HandSide = \"Left\" | \"Right\"\nexport type Mark2Bone = Partial<{ [key in HandMarkName]: THREE.Object3D }>;\n\nconst v1 = new THREE.Vector3();\nconst v2 = new THREE.Vector3();\nconst v3 = new THREE.Vector3();\nconst v4 = new THREE.Vector3();\nconst v5 = new THREE.Vector3();\nconst v6 = new THREE.Vector3();\n\nconst currNormal = new THREE.Vector3();\nconst currForward = new THREE.Vector3();\nconst currSide = new THREE.Vector3();\nconst HALF_PI = Math.PI/2\nconst DOWN = new THREE.Vector3(0,-1,0);\n\nclass HandsTracker extends Tracker<typeof handMarks> {\n\tprivate readonly sign:number;\n\tprivate readonly isLeft:boolean;\n\t/**\n\t * the axis used to look at the pole\n\t */\n\tprivate readonly lookAtPoleAxis:LookAtPoleAxis;\n\n\tconstructor(private readonly handLandmarker:HandLandmarker, private readonly side:HandSide, private readonly isMyWrist:( handWrist:NormalizedLandmark )=>boolean ){\n\t\tsuper(handMarks, HandLandmarker.HAND_CONNECTIONS)\n\n\t\tthis.sign = this.side==\"Left\" ? -1 : 1;\n\t\tthis.isLeft = this.side==\"Left\";\n\t\tthis.lookAtPoleAxis = this.sign<0? \"+x\" : \"-x\";\n\t\tthis.root.scale.setScalar(2)\n\t\tthis.root.scale.y *= -1\n\t\tthis.root.scale.z *= -1\n\t}\n\n\toverride predict( source:TexImageSource, drawingUtils:DrawingUtils ){\n\t\tconst result = this.handLandmarker.detectForVideo(source, performance.now());\n\n\t\tif( result.landmarks.length )\n\t\t{\n\t\t\t//console.log(`DETECTED ${result.landmarks.length} hands`, result.handedness)\n\n\n\t\t\tfor(let i=0; i<result.landmarks.length; i++){\n\t\t\t\tconst hand = result.landmarks[i];\n\t\t\t\tconst wrist = hand[this.points.wrist];\n\t\t\t\tconst isMyWrist = this.isMyWrist(wrist);\n\t\t\t\tif( isMyWrist ){\n\t\t\t\t\tthis.updateLandmarks( result.worldLandmarks[i] );\n\n\t\t\t\t\tdrawingUtils.drawConnectors(hand, HandLandmarker.HAND_CONNECTIONS, {\n\t\t\t\t\t\tcolor: this.side==\"Left\" ? \"#00FF00\" : \"#0000FF\",\n\t\t\t\t\t\tlineWidth: 4\n\t\t\t\t\t});\n\t\t\t\t\tdrawingUtils.drawLandmarks(hand, { color: this.side==\"Left\" ? \"#00FF00\" : \"#0000FF\", lineWidth: 3, radius: 1 }); \n\n\t\t\t\t\t\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} \n \n \n\t\t} \n\t}\n\n\toverride sync ( delta:number, objects: [THREE.Object3D, HandMarkName, HandMarkName, LookAtPoleAxis][] ) {\n\n\t\tthrow new Error(\"Not used. Use syncHandBones instead\");\n\t}\n\t\t\n\t/**\n\t * \n\t * @param delta time since last frame\n\t * @param landmark2bones Array the same size as the umber of hand landmarks, and on each positionthe bone that belongs to that point.\n\t * @see https://ai.google.dev/edge/mediapipe/solutions/vision/hand_landmarker\n\t */\n\tsyncHandBones( delta:number, markToBone:Mark2Bone, rig:THREE.Object3D )\n\t{ \n\t\tconst palmNormal = v1.crossVectors(\n\t\t\tv2.copy(this.marks.index1.worldPosition).sub(this.marks.wrist.worldPosition),\n\t\t\tv3.copy(this.marks.pinky1.worldPosition).sub(this.marks.wrist.worldPosition)\n\t\t).normalize();\n\n\t\tconst parlmDir = v2.copy(this.marks.palm.worldPosition).sub(this.marks.wrist.worldPosition).normalize();\n\t\tconst palmSide = v3.copy(this.marks.pinky1.worldPosition).sub(this.marks.index1.worldPosition).normalize();\n\t\t \n\t\tif( parlmDir.dot(DOWN)>0.8 )\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tif( markToBone.wrist )\n\t\t{\n\t\t\tconst palmLookAt = rootPosition(v4, markToBone.wrist, rig ).add( parlmDir ).applyMatrix4(rig.matrixWorld) //markToBone.wrist.getWorldPosition(v4).add( parlmDir );\n\t\t\tconst polPosition = rootPosition(v5, markToBone.wrist, rig ).sub( palmSide ).applyMatrix4(rig.matrixWorld) //markToBone.wrist.getWorldPosition(v5).sub( palmSide );\n\n\t\t\tconst palmGhost = this.getGhost(markToBone.wrist)\n\n\t\t\tlookAt( palmGhost, palmLookAt, polPosition, \"-y\" );\n\t\t\tpalmGhost.rotateX( HALF_PI ) ; \n\n\t\t\tpalmGhost.lerp(markToBone.wrist, delta)\n\t\t}\n\t\t\n\n\t\t// palmLookAtOffset.normalize();\n\n\t\t \n\t\t// const palmSide = v3.crossVectors(palmNormal, palmLookAtOffset).normalize();\n \n\t\tthis.syncFinger( delta, rig, palmNormal, parlmDir, palmSide, markToBone, fingerKeys.index, \"middle1\" )\n\t\tthis.syncFinger( delta, rig, palmNormal, parlmDir, palmSide, markToBone, fingerKeys.middle, \"ring1\" )\n\t\tthis.syncFinger( delta, rig, palmNormal, parlmDir, palmSide, markToBone, fingerKeys.ring, \"pinky1\" )\n\t\tthis.syncFinger( delta, rig, palmNormal, parlmDir, palmSide, markToBone, fingerKeys.pinky, \"ring1\", true )\n\n\t\t// //thumb...\n\t\tthis.syncFinger( delta, rig, palmNormal, parlmDir, palmSide, markToBone, fingerKeys.thumb, \"index1\" )\n\n\t\t\n\t}\n\n\tprivate syncFinger( delta:number, rig:THREE.Object3D, palmNormal:THREE.Vector3, palmForward:THREE.Vector3, palmSide:THREE.Vector3, markToBone:Mark2Bone, fingerKeys:HandMarkName[], sideGoal:HandMarkName, negateSideGoal:boolean=false ){\n\t \n\t\tlet signMult = 1;\n\n\t\tfor(let i=0; i<fingerKeys.length-1;i++) { \n\t\t\t\n\t\t\tconst bone = markToBone[fingerKeys[i]];\n\t\t\t//const bonePole = markToBone[sideGoal];\n\n\t\t\tif(!bone ) continue;\n\n\t\t\tconst myDir = v4.copy( this.marks[fingerKeys[i+1]].worldPosition ).sub( this.marks[fingerKeys[i]].worldPosition).normalize(); \n\t\t\t\n\t\t\tconst bonePos = rootPosition(v5, bone, rig) //bone.getWorldPosition(v5);\n\t\t\tconst poleOffset = v6.copy(bonePos).add(palmSide) //rootPosition(v6, bonePole, rig).sub( bonePos );//bonePole.getWorldPosition(v6).sub( bonePos );\n\n\t\t\tif( negateSideGoal ) poleOffset.negate();\n\n\t\t\tconst fingerGhost = this.getGhost(bone)\n\n\n\t\t\tif( i==0 )\n\t\t\t{ \n\n\t\t\t\tcurrSide.copy(poleOffset);\n\n\t\t\t\t\n\t\t\t\tlookAt( fingerGhost, \n\t\t\t\t\tmyDir.add( bonePos ).applyMatrix4(rig.matrixWorld), \n\t\t\t\t\tpoleOffset.add(bonePos).applyMatrix4(rig.matrixWorld), \n\t\t\t\t\tthis.lookAtPoleAxis );\n\n\t\t\t\t\n\t\t\t}\n\t\t\telse \n\t\t\t{ \n\t\t\t\tpoleOffset.copy( currSide );\n\t\t\t\tlookAt( fingerGhost, \n\t\t\t\t\tmyDir.add( bonePos ).applyMatrix4(rig.matrixWorld), \n\t\t\t\t\tpoleOffset.add(bonePos).applyMatrix4(rig.matrixWorld), \n\t\t\t\t\tthis.lookAtPoleAxis );\n\t\t\t} \n\n\t\t\tfingerGhost.rotateX( HALF_PI ); \n\n\t\t\tfingerGhost.lerp(bone, delta)\n\n\t\t}\n\n \n\t}\n \n\tbind( rig:THREE.Object3D, magging:BoneMap ){\n\n\t\tconst map:Mark2Bone = {\n\t\t\t\n\t\t}\t \n\n\t\tconst addBind = ( boneName:string, markName:HandMarkName ) => {\n\t\t\t//const bone = rig.getObjectByName( cleanBoneName( boneName.replace(\"X\", this.sign<0 ? \"L\" : \"R\") ));\n\n\t\t\tconst bone = getBoneByName(rig, boneName );\n\n\t\t\tif( bone ){\n\t\t\t\tmap[markName] = bone;\n\t\t\t}\n\t\t}\n\n\t\taddBind( this.isLeft ? magging.handL : magging.handR, \"wrist\" )\n\t\taddBind( this.isLeft ? magging.index1L : magging.index1R, \"index1\" )\n\t\taddBind( this.isLeft ? magging.index2L : magging.index2R, \"index2\" )\n\t\taddBind( this.isLeft ? magging.index3L : magging.index3R, \"index3\" ) \n\n\t\taddBind( this.isLeft ? magging.middle1L : magging.middle1R, \"middle1\" )\n\t\taddBind( this.isLeft ? magging.middle2L : magging.middle2R, \"middle2\" )\n\t\taddBind( this.isLeft ? magging.middle3L : magging.middle3R, \"middle3\" ) \n\n\t\taddBind( this.isLeft ? magging.ring1L : magging.ring1R, \"ring1\" )\n\t\taddBind( this.isLeft ? magging.ring2L : magging.ring2R, \"ring2\" )\n\t\taddBind( this.isLeft ? magging.ring3L : magging.ring3R, \"ring3\" ) \n\n\t\taddBind( this.isLeft ? magging.pinky1L : magging.pinky1R, \"pinky1\" )\n\t\taddBind( this.isLeft ? magging.pinky2L : magging.pinky2R, \"pinky2\" )\n\t\taddBind( this.isLeft ? magging.pinky3L : magging.pinky3R, \"pinky3\" ) \n\n\t\taddBind( this.isLeft ? magging.thumb1L : magging.thumb1R, \"thumb1\" )\n\t\taddBind( this.isLeft ? magging.thumb2L : magging.thumb2R, \"thumb2\" )\n\t\taddBind( this.isLeft ? magging.thumb3L : magging.thumb3R, \"thumb3\" ) \n\n\t\treturn {\n\t\t\tupdate: ( delta:number )=> { \n\t\t\t\tthis.syncHandBones(delta, map, rig);\n\t\t\t}\n\t\t}\t\n\t}\n}\n","import {\n Category,\n DrawingUtils,\n FaceLandmarker\n} from \"@mediapipe/tasks-vision\";\nimport { Mesh, Object3D, Vector3 } from \"three/webgpu\";\nimport { Tracker } from \"./Tracker\";\nimport { rootPosition } from \"./util/getRootPosition\";\nimport { getBoneByName } from \"./util/getBoneByName\";\nimport { lookAt } from \"./util/lookAt\";\n\nexport async function loadFaceTracker(vision: any, cfg?: { modelPath?: string }) {\n const faceLandmarker = await FaceLandmarker.createFromOptions(vision, {\n baseOptions: {\n modelAssetPath: cfg?.modelPath ?? \"face_landmarker.task\",\n\t\t\tdelegate: \"GPU\", \n },\n\t\toutputFaceBlendshapes: true,\n runningMode: \"VIDEO\",\n\t\tnumFaces: 1,\n });\n\n\treturn new FaceTracker(faceLandmarker);\n}\n\n/**\n * @see https://storage.googleapis.com/mediapipe-assets/documentation/mediapipe_face_landmark_fullsize.png\n */\nconst faceMarks = {\n\teyeL: 473,\n\teyeR: 468,\n\teyeStartL: 463,\n\teyeStartR: 243,\n\teyeEndL: 263,\n\teyeEndR: 33, \n\n\tearL: 454,\n\tearR: 234,\n\tnoseTip: 4,\n\tnoseBone:6,\n\tchin:152,\n\tforehead: 10\n\n}\n\ntype MarkKey = keyof typeof faceMarks;\nconst v = new Vector3();\nconst v2 = new Vector3();\nconst v3 = new Vector3();\nconst v4 = new Vector3();\nconst v5 = new Vector3();\nconst v6 = new Vector3();\n\nclass FaceTracker extends Tracker<typeof faceMarks> {\n\tprivate blendshapeCategories: Category[] | undefined;\n\tprivate blendshapeMap: Map<string, number> = new Map();\n\tprivate smoothed: Record<string, number> = {};\n\tprivate smoothing =.0003; // lower = smoother but more lag, higher = more responsive\n\n\tconstructor(private faceLandmarker: FaceLandmarker) {\n\t\tsuper(faceMarks, FaceLandmarker.FACE_LANDMARKS_TESSELATION)\n\n\t\tthis.root.scale.y*=-1\n\t\tthis.root.scale.z*=-1\n\t\tthis.root.scale.multiplyScalar(3)\n\t}\n\n\toverride predict(frame: TexImageSource, drawingUtils: DrawingUtils) {\n\t\tconst result = this.faceLandmarker.detectForVideo(frame, performance.now());\n\t\tif (result.faceLandmarks[0]) {\n\t\t\tdrawingUtils.drawConnectors(result.faceLandmarks[0], FaceLandmarker.FACE_LANDMARKS_TESSELATION, { color: \"#00fff2ff\", lineWidth: .1 });\n\t\t\tdrawingUtils.drawLandmarks(result.faceLandmarks[0], { color: \"#00ff00\", lineWidth: .1, radius: .4 });\t\n\n\t\t\tthis.updateLandmarks(result.faceLandmarks[0], result.faceLandmarks[0] );\n\t\t}\n\n\t\tthis.blendshapeCategories = result.faceBlendshapes?.[0]?.categories; \n\n\t\tthis.blendshapeCategories?.forEach((category) => {\n\t\t\tthis.blendshapeMap.set(category.categoryName, category.score);\n\t\t});\n\t\t\n\t}\n\n\tbindShapeKeys(mesh: Mesh) {\n\t\tconst meshKeys = mesh.morphTargetDictionary; \n\n\t\treturn {\n\t\t\tupdate: (delta: number) => {\n\t\t\t\tthis.blendshapeCategories?.forEach((category) => {\n\t\t\t\t\tconst { categoryName, score } = category;\n\n\t\t\t\t\tif (!meshKeys?.hasOwnProperty(categoryName)) return;\n\n\t\t\t\t\t// Initialize if first time seeing this key\n\t\t\t\t\tif (this.smoothed[categoryName] === undefined)\n\t\t\t\t\t\tthis.smoothed[categoryName] = score;\n\n\t\t\t\t\t// Lerp toward target score\n\t\t\t\t\tconst factor = 1 - Math.pow(this.smoothing, delta);\n\t\t\t\t\tthis.smoothed[categoryName] += (score - this.smoothed[categoryName]) * factor;\n\n\t\t\t\t\tmesh.morphTargetInfluences![meshKeys[categoryName]] = this.smoothed[categoryName];\n\t\t\t\t});\n\n\t\t\t\t//eyes\n\t\t\t}\n\t\t}\n\t}\n\n\tbind( rig:Object3D ) {\n\n\t\tconst eyeL = new EyeRig(rig, \"L\");\n\t\tconst eyeR = new EyeRig(rig, \"R\");\n\t\tconst headBone = getBoneByName(rig, \"head\") ;\n \n\t\treturn {\n\t\t\tupdate: ( delta:number )=> {\n\t\t\t\t \n\t\t\t\teyeL.update(delta, this.blendshapeMap);\n\t\t\t\teyeR.update(delta, this.blendshapeMap); \n\t\t\t\t\n\t\t\t\tif(!headBone) return;\n\n\t\t\t\t//\n\t\t\t\tconst markEarL = v.copy( this.marks.earL.worldPosition );\n\t\t\t\tconst markEarR = v2.copy( this.marks.earR.worldPosition );\n\t\t\t\tconst headcenter = v3.subVectors(markEarL, markEarR).multiplyScalar(.5).add(markEarR);\n\t\t\t\tconst headForward = v4.subVectors(this.marks.noseTip.worldPosition, headcenter) ;\n\t\t\t\tconst headSideNormal = markEarL.sub(markEarR) ;\n\n\t\t\t\t\n\t\t\t\tconst headPosition = rootPosition( v5, headBone, rig); \n\n\t\t\t\tconst poleLookAt = headSideNormal.add( headPosition ).applyMatrix4(rig.matrixWorld);\n\t\t\t\tconst faceLookAt = headForward.add( headPosition ).applyMatrix4(rig.matrixWorld);\n\n\t\t\t\tlookAt( headBone, faceLookAt, poleLookAt,\"+x\" );\n\t\t\t\t \n\n\t\t\t\t// headLookAtPos.applyMatrix4(rig.matrixWorld);\n\t\t\t\t//headBone.lookAt( headLookAtPos );\n\t\t\t\t// \n\t\t\t}\n\t\t}\n\t\t\n\t}\n}\n\nclass EyeRig {\n\tprivate eyeBone:Object3D|undefined; \n\n\tprivate eyeLookOut:string;\n\tprivate eyeLookIn:string;\n\tprivate eyeLookUp:string;\n\tprivate eyeLookDown:string;\n\tprivate sign = 1;\n\t\n\tconstructor( readonly rig:Object3D, readonly side:\"L\"|\"R\" ) {\n\t\tthis.eyeBone = rig.getObjectByName(`eye${side}`) as Object3D; \n\n\t\tconst sideName = side == \"L\" ? \"Left\" : \"Right\";\n\t\tthis.eyeLookOut = `eyeLookOut${sideName}`;\n\t\tthis.eyeLookIn = `eyeLookIn${sideName}`;\n\t\tthis.eyeLookUp = `eyeLookUp${sideName}`;\n\t\tthis.eyeLookDown = `eyeLookDown${sideName}`;\n\n\t\tthis.sign = side == \"L\" ? -1 : 1;\n\t}\n\n\tupdate( delta:number, blendshapes: Map<string, number> ) {\n\t\tif( !this.eyeBone ) return; \n \n\t\tconst eye = rootPosition(v3, this.eyeBone, this.rig); \n\n\t\t\n\t\t\n\t\t// From MediaPipe blendshapes\n\t\tconst lookLeft = blendshapes.get(this.eyeLookOut) ?? 0; // or eyeLookInRight\n\t\tconst lookRight = blendshapes.get(this.eyeLookIn) ?? 0; // or eyeLookOutRight\n\t\tconst lookUp = blendshapes.get(this.eyeLookUp) ?? 0;\n\t\tconst lookDown = blendshapes.get(this.eyeLookDown) ?? 0;\n\n\t\t\n\t\t// Map to a -1..1 range\n\t\tconst sideMovement = lookRight - lookLeft // horizontal\n\t\tconst verticalMovement = lookDown - lookUp // vertical\n\n\t\tconsole.log(\"EYE: \", sideMovement, verticalMovement)\n\n\t\tthis.eyeBone.rotation.y =( sideMovement * this.sign) / 2; \n\t\tthis.eyeBone.rotation.x = verticalMovement / 2; \n\t\t// // Then drive your rig bone with a target offset\n\t\t// const lookAtPos = eyeCenter\n\t\t// .add(eyeHorizontalDir ) // -sideMovement * eyeRange)\n\t\t// //.addScaledVector(eyeVerticalDir, verticalMovement * eyeRange/3)\n\t\t// .applyMatrix4(this.rig.matrixWorld);\n\n\t\t// this.eyeBone.lookAt(lookAtPos);\n\t\t// this.eyeBone.rotateX(Math.PI/2)\n\t}\n}","/**\n * The bone mapping to use for the rig.\n */\nexport type BoneMap = {\n\tfaceMesh:string\n\thead: string;\n\thips:string\n\tneck:string\n\ttorso:string\n\tarmL:string\n\tforearmL:string\n\n\tarmR:string\n\tforearmR:string\n\n\tthighL:string\n\tshinL:string\n\tfootL:string\n\n\tthighR:string\n\tshinR:string\n\tfootR:string\n\t \n\t\n\thandL:string\n\tindex1L:string\n\tindex2L:string\n\tindex3L:string\n\n\tmiddle1L:string\n\tmiddle2L:string\n\tmiddle3L:string\n\n\tring1L:string\n\tring2L:string\n\tring3L:string\n\n\tpinky1L:string\n\tpinky2L:string\n\tpinky3L:string\n\n\tthumb1L:string\n\tthumb2L:string\n\tthumb3L:string\n\n\thandR:string\n\tindex1R:string\n\tindex2R:string\n\tindex3R:string\n\n\tmiddle1R:string\n\tmiddle2R:string\n\tmiddle3R:string\n\n\tring1R:string\n\tring2R:string\n\tring3R:string\n\n\tpinky1R:string\n\tpinky2R:string\n\tpinky3R:string\n\n\tthumb1R:string\n\tthumb2R:string\n\tthumb3R:string\n \n}\n\nexport const defaultBoneMap:BoneMap = {\n\tfaceMesh:\"face\",\n\t\n\thead: \"head\",\n\thips:\"hips\",\n\tneck:\"neck\",\n\ttorso:\"torso\",\n\n\tarmL:\"upper_armL\",\n\tforearmL:\"forearmL\",\n\n\tarmR:\"upper_armR\",\n\tforearmR:\"forearmR\",\n\n\tthighL:\"thighL\",\n\tshinL:\"shinL\",\n\tfootL:\"footL\",\n\n\tthighR:\"thighR\",\n\tshinR:\"shinR\",\n\tfootR:\"footR\",\n\t \n\t\n\thandL:\"handL\",\n\tindex1L:\"index1L\",\n\tindex2L:\"index2L\",\n\tindex3L:\"index3L\",\n\n\tmiddle1L:\"middle1L\",\n\tmiddle2L:\"middle2L\",\n\tmiddle3L:\"middle3L\",\n\n\tring1L:\"ring1L\",\n\tring2L:\"ring2L\",\n\tring3L:\"ring3L\",\n\n\tpinky1L:\"pinky1L\",\n\tpinky2L:\"pinky2L\",\n\tpinky3L:\"pinky3L\",\n\n\tthumb1L:\"thumb1L\",\n\tthumb2L:\"thumb2L\",\n\tthumb3L:\"thumb3L\",\n\n\thandR:\"handR\",\n\tindex1R:\"index1R\",\n\tindex2R:\"index2R\",\n\tindex3R:\"index3R\",\n\n\tmiddle1R:\"middle1R\",\n\tmiddle2R:\"middle2R\",\n\tmiddle3R:\"middle3R\",\n\n\tring1R:\"ring1R\",\n\tring2R:\"ring2R\",\n\tring3R:\"ring3R\",\n\n\tpinky1R:\"pinky1R\",\n\tpinky2R:\"pinky2R\",\n\tpinky3R:\"pinky3R\",\n\n\tthumb1R:\"thumb1R\",\n\tthumb2R:\"thumb2R\",\n\tthumb3R:\"thumb3R\",\n \n}","import {\n DrawingUtils,\n FilesetResolver,\n HandLandmarkerOptions,\n PoseLandmarker,\n} from \"@mediapipe/tasks-vision\";\nimport * as THREE from \"three/webgpu\";\nimport { loadPoseTracker } from \"./PoseTracker\";\nimport { loadHandTracker } from \"./HandTracker\"; \nimport { loadFaceTracker } from \"./FaceTracker\";\nimport { BoneMap, defaultBoneMap } from \"./BoneMapping\";\n\nexport type TrackerConfig = {\n /**\n * Use an image file. Useful to test a particular pose.\n */\n debugFrame?: string;\n\n /**\n * Scale of the video display\n */\n displayScale: number;\n\n /**\n * If the body pose should ignore the legs\n */\n ignoreLegs: boolean;\n\n /**\n * Use a video file instead of the webcam\n */\n debugVideo?: string;\n\n /**\n * Don't track the face\n */\n ignoreFace: boolean;\n\n /**\n * @see https://ai.google.dev/edge/mediapipe/solutions/vision/hand_landmarker/web_js#configuration_options\n */\n handsTrackerOptions: HandLandmarkerOptions | undefined;\n\n\tmodelPaths?: {\n\t\tvision?:string;\n\t\tpose?: string;\n\t\thand?: string;\n\t\tface?: string;\n\t}\n};\n\nexport interface BindingHandler {\n update: (delta: number) => void;\n}\n\n// Check if webcam access is supported.\nconst hasGetUserMedia = () => !!navigator.mediaDevices?.getUserMedia;\n\nexport async function setupTracker(config?: Partial<TrackerConfig>) {\n const $cfg = {\n debugFrame: undefined,\n displayScale: 1,\n ignoreLegs: false,\n debugVideo: undefined,\n ignoreFace: false,\n\t\tmodelPaths: {\n\t\t\tvision: \"https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@0.10.3/wasm\",\n\t\t\tpose: \"https://storage.googleapis.com/mediapipe-models/pose_landmarker/pose_landmarker_lite/float16/1/pose_landmarker_lite.task\",\n\t\t\thand: \"https://storage.googleapis.com/mediapipe-models/hand_landmarker/hand_landmarker/float16/1/hand_landmarker.task\",\n\t\t\tface: \"https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/1/face_landmarker.task\",\n\t\t},\n ...config,\n };\n let video: HTMLVideoElement | undefined;\n const vision = await FilesetResolver.forVisionTasks( $cfg.modelPaths.vision ?? \"/wasm\" );\n const poseTracker = await loadPoseTracker(vision, {\n ignoreLegs: $cfg.ignoreLegs,\n\t\tmodelPath: $cfg.modelPaths.pose!,\n });\n const handsTracker = await loadHandTracker(vision, {\n leftWrist: () => poseTracker.leftWristNormalizedPosition,\n rightWrist: () => poseTracker.rightWristNormalizedPosition,\n\t\tmodelPath: $cfg.modelPaths.hand!,\n ...config?.handsTrackerOptions,\n });\n const faceTracker = $cfg.ignoreFace\n ? undefined\n : await loadFaceTracker(vision, { modelPath: $cfg.modelPaths.face! });\n\n //#region setup Camera and Canvas...\n\tconst viewport = document.createElement(\"div\");\n\tviewport.style.position = \"absolute\";\n\tviewport.style.top = \"0px\";\n\tviewport.style.left = \"0px\"; \n\tviewport.style.zIndex = \"21\";\n\tviewport.classList.add(\"three-mediapipe-rig\")\n\tdocument.body.appendChild(viewport);\n\n const canvasElement = document.createElement(\"canvas\");\n const canvasCtx = canvasElement.getContext(\"2d\")!;\n const drawingUtils = new DrawingUtils(canvasCtx);\n\n canvasElement.style.zIndex = \"22\";\n canvasElement.style.position = \"absolute\";\n canvasElement.style.top = \"0px\";\n canvasElement.style.left = \"0px\";\n canvasElement.style.pointerEvents = \"none\";\n viewport.appendChild(canvasElement);\n\n function predict(source: TexImageSource) {\n canvasCtx.save();\n canvasCtx.clearRect(0, 0, canvasElement.width, canvasElement.height);\n poseTracker?.predict(source, drawingUtils);\n handsTracker?.left.predict(source, drawingUtils);\n handsTracker?.right.predict(source, drawingUtils);\n faceTracker?.predict(source, drawingUtils);\n canvasCtx.restore();\n }\n\n function initializeVideo() {\n video = document.createElement(\"video\");\n viewport.appendChild(video);\n\n let lastVideoTime = -1;\n\n video.style.zIndex = \"21\";\n video.style.position = \"absolute\";\n video.style.top = \"0px\";\n video.style.left = \"0px\";\n\n if ($cfg.debugVideo) {\n video.src = $cfg.debugVideo;\n video.controls = true;\n video.loop = true;\n video.muted = true;\n video.controls = true;\n video.play();\n }\n\n function predictWebcam() {\n if (lastVideoTime !== video!.currentTime) {\n predict(video!);\n lastVideoTime = video!.currentTime;\n }\n window.requestAnimationFrame(predictWebcam);\n }\n\n video.addEventListener(\"loadeddata\", () => {\n video!.width = video!.videoWidth * $cfg.displayScale;\n video!.height = video!.videoHeight * $cfg.displayScale;\n canvasElement.width = video!.videoWidth;\n canvasElement.height = video!.videoHeight;\n canvasElement.style.height = video!.height + \"px\";\n canvasElement.style.width = video!.width + \"px\";\n\n window.requestAnimationFrame(predictWebcam);\n });\n }\n\n if ($cfg.debugFrame) {\n //#region Debug Frame mode — use a static image\n const img = document.createElement(\"img\");\n img.src = $cfg.debugFrame;\n img.style.zIndex = \"21\";\n img.style.position = \"absolute\";\n img.style.top = \"0px\";\n img.style.left = \"0px\";\n document.body.appendChild(img);\n\n img.addEventListener(\"load\", () => {\n img.width = img.naturalWidth * $cfg.displayScale;\n img.height = img.naturalHeight * $cfg.displayScale;\n canvasElement.width = img.naturalWidth;\n canvasElement.height = img.naturalWidth;\n canvasElement.style.width = img.width + \"px\";\n canvasElement.style.height = img.height + \"px\";\n\n function predictFrame() {\n predict(img);\n }\n\n window.requestAnimationFrame(predictFrame);\n });\n //#endregion\n } else if( $cfg.debugVideo ) {\n //#region Video mode\n initializeVideo();\n //#endregion\n } \n\n return {\n poseTracker,\n handsTracker,\n faceTracker,\n video,\n\n\t\t/**\n\t\t * A div that contains the video and canvas used to display the landmarks stacked on top of each other.\n\t\t */\n\t\tdomElement: viewport,\n\n\t\t/**\n\t\t * Start the webcam feed. This must be initiated by a user triggered event ( a click on a button ) due to security reasons. \n\t\t */\n start: async () => {\n\t\t\tlet stopped = false;\n\n if (!hasGetUserMedia()) {\n throw new Error(\"Webcam not supported\");\n }\n\n if (!video) {\n initializeVideo();\n }\n\n let stream: Awaited<MediaStream> | undefined;\n\n\t\t\tfunction onTrackEnded(video: HTMLVideoElement): void {\n\t\t\t\tconsole.warn('Camera track ended, attempting recovery...');\n\t\t\t\tstopCamera(video);\n\t\t\t\tretryWithBackoff(video);\n\t\t\t}\n\n\t\t\tfunction stopCamera(video: HTMLVideoElement): void {\n\t\t\t\tstream?.getTracks().forEach(t => t.stop());\n\t\t\t\tstream = undefined;\n\t\t\t\tvideo.srcObject = null;\n\t\t\t}\n\n\t\t\tasync function retryWithBackoff(video: HTMLVideoElement, attempt = 0): Promise<void> {\n\t\t\t const MAX_ATTEMPTS = 5;\n\t\t\t const delay = Math.min(1000 * 2 ** attempt, 16000); // 1s, 2s, 4s, 8s, 16s\n\n\t\t\t if (attempt >= MAX_ATTEMPTS) { \n\t\t\t throw new Error('Camera recovery failed after max attempts');\n\t\t\t }\n\n\t\t\t await new Promise(res => setTimeout(res, delay)); \n\n\t\t\t if(stopped) return;\n\n\t\t\t try {\n\t\t\t await startCamera(video);\n\t\t\t console.log('Camera recovered successfully');\n\t\t\t } catch {\n\t\t\t retryWithBackoff(video, attempt + 1);\n\t\t\t }\n\t\t\t}\n\n\t\t\tasync function startCamera(video: HTMLVideoElement): Promise<void> {\n\t\t\t try {\n\t\t\t stream = await navigator.mediaDevices.getUserMedia({ video: true });\n\t\t\t video.srcObject = stream;\n\t\t\t await video.play();\n\n\t\t\t // Listen for track ending (camera disconnected / permission revoked)\n\t\t\t stream.getVideoTracks().forEach(track => {\n\t\t\t track.addEventListener('ended', () => onTrackEnded(video));\n\t\t\t });\n\n\t\t\t } catch (err) {\n\t\t\t handleCameraError(err, video);\n\t\t\t }\n\t\t\t}\n\n\t\t\tfunction handleCameraError(err: unknown, video: HTMLVideoElement): void {\n\t\t\t if (err instanceof DOMException) {\n\t\t\t switch (err.name) {\n\t\t\t case 'NotAllowedError':\n\t\t\t throw new Error('Permission denied — prompt user to allow camera');\n\t\t\t break;\n\t\t\t case 'NotFoundError':\n\t\t\t console.error('No camera found — retry when device is connected');\n\t\t\t retryWithBackoff(video); // device might be plugged in later\n\t\t\t break;\n\t\t\t case 'NotReadableError':\n\t\t\t console.error('Camera in use by another app');\n\t\t\t retryWithBackoff(video);\n\t\t\t break;\n\t\t\t default:\n\t\t\t console.error('Camera error:', err.message);\n\t\t\t retryWithBackoff(video);\n\t\t\t }\n\t\t\t }\n\t\t\t} \n\n await startCamera(video!);\n\n\t\t\treturn {\n\t\t\t\tstop:()=>{\n\t\t\t\t\tstopped = true;\n\t\t\t\t\tstopCamera(video!);\n\t\t\t\t}\n\t\t\t}\n },\n\n /**\n * Binds the bones of the rig to the landmarks provided by media pipe.\n * @param rig The rig that contains all the bones and skinned meshes of your character.\n\t\t * @param magging The bone mapping to use for the rig.\n */\n bind: ( rig: THREE.Object3D, magging?:BoneMap ) => {\n\n\t\t\tmagging = magging || defaultBoneMap;\n\n const bodyBindin = poseTracker.bind(rig, magging);\n const leftHandBinding = handsTracker.left.bind(rig, magging);\n const rightHandBinding = handsTracker.right.bind(rig, magging);\n let faceKeys: BindingHandler | undefined;\n const faceRig = faceTracker?.bind(rig);\n\n rig.traverse((child) => {\n if (\n child instanceof THREE.Mesh &&\n child.name.indexOf( magging.faceMesh ) === 0\n ) {\n child.frustumCulled = false;\n faceKeys = faceTracker?.bindShapeKeys(child);\n }\n });\n\n return {\n update: (delta: number) => {\n bodyBindin.update(delta);\n leftHandBinding.update(delta);\n rightHandBinding.update(delta);\n faceKeys?.update(delta);\n faceRig?.update(delta);\n },\n } as BindingHandler;\n },\n };\n}\n"],"names":["poleDir","Vector3","objectPosition","XAxis","XAxisNeg","YAxis","YAxisNeg","ZAxis","pole","lookDir","v","correction","Quaternion","worldQuat","lookAt","object","target","poleTarget","poleAxis","axis","currentPole","lookAxisDir","desiredPoleDir","cross","angle","THREE","A","B","Tracker","points","debugConnections","__publicField","key","Mark","landmarks","debugLandmarks","debugDrawer","point","mark","o","Ghost","_a","source","drawingUtils","delta","objects","normal","root","offset","objectLookAtGoal","polePosition","ghost","rig","name","speed","rootPosition","out","cleanBoneName","getBoneByName","bone","Bone","loadPoseTracker","vision","config","poseLandmarker","PoseLandmarker","PoseTracker","poseMarks","C","D","E","lookGoal","poleGoal","result","magging","map","v2","syncBone","from","to","sideAxis","hipsDir","sideHips","sideShoulders","sideHead","loadHandTracker","landmarker","HandLandmarker","isMyWrist","myWrist","otherWrist","handWrist","HandsTracker","handMarks","fingerKeys","v1","v3","v4","v5","v6","currSide","HALF_PI","DOWN","handLandmarker","side","hand","wrist","markToBone","palmNormal","parlmDir","palmSide","palmLookAt","polPosition","palmGhost","palmForward","sideGoal","negateSideGoal","i","myDir","bonePos","poleOffset","fingerGhost","addBind","boneName","markName","loadFaceTracker","cfg","faceLandmarker","FaceLandmarker","FaceTracker","faceMarks","frame","_b","_c","category","mesh","meshKeys","categoryName","score","factor","eyeL","EyeRig","eyeR","headBone","markEarL","markEarR","headcenter","headForward","headSideNormal","headPosition","poleLookAt","faceLookAt","sideName","blendshapes","lookLeft","lookRight","lookUp","lookDown","sideMovement","verticalMovement","defaultBoneMap","hasGetUserMedia","setupTracker","$cfg","video","FilesetResolver","poseTracker","handsTracker","faceTracker","viewport","canvasElement","canvasCtx","DrawingUtils","predict","initializeVideo","lastVideoTime","predictWebcam","img","predictFrame","stopped","stream","onTrackEnded","stopCamera","retryWithBackoff","t","attempt","delay","res","startCamera","track","err","handleCameraError","bodyBindin","leftHandBinding","rightHandBinding","faceKeys","faceRig","child"],"mappings":"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"}
1
+ {"version":3,"file":"three-mediapipe-rig.js","sources":["../src/tracking/util/lookAt.ts","../src/tracking/Tracker.ts","../src/tracking/util/getRootPosition.ts","../src/tracking/util/cleanBoneName.ts","../src/tracking/util/getBoneByName.ts","../src/tracking/PoseTracker.ts","../src/tracking/HandTracker.ts","../src/tracking/FaceTracker.ts","../src/tracking/BoneMapping.ts","../src/tracking/TrackerManager.ts"],"sourcesContent":["import { Object3D, Quaternion, Vector3 } from \"three/webgpu\";\n\nconst poleDir = new Vector3();\nconst objectPosition = new Vector3();\n\nconst XAxis = new Vector3(1,0,0);\nconst XAxisNeg = new Vector3(-1,0,0);\nconst YAxis = new Vector3(0,1,0); \nconst YAxisNeg = new Vector3(0,-1,0); \nconst ZAxis = new Vector3(0,0,1); \nconst ZAxisNeg = new Vector3(0,0,-1); \n\nconst pole = new Vector3();\nconst lookDir = new Vector3();\n\nconst v = new Vector3();\nconst correction = new Quaternion();\nconst worldQuat = new Quaternion();\n\nexport type LookAtPoleAxis = \"+x\"|\"+y\"|\"-x\"|\"-y\"\n\n/**\n * Will point the Z axis of object at target and the X or Y axis in the general direction of the pole target\n * @param object The object to rotate\n * @param target The point to look at ( in world coord )\n * @param poleTarget The goal of the pole axis ( in world coord )\n * @param poleAxis The axis to use as the pole axis ( z is the one pointing at the target )\n */\nexport function lookAt( object:Object3D, target:Vector3, poleTarget:Vector3, poleAxis:LookAtPoleAxis = \"+x\" )\n{ \n\t//\n\t// look at target (handles parent transforms internally)\n\t// \n\tobject.lookAt(target);\n\n\tconst axis = poleAxis==\"+x\"?XAxis: poleAxis==\"-x\"?XAxisNeg: poleAxis==\"+y\"?YAxis: YAxisNeg;\n\n\tobject.getWorldPosition(objectPosition);\n\tobject.getWorldQuaternion(worldQuat);\n\n\tpoleDir.subVectors(poleTarget, objectPosition).normalize();\n\n\t// direction in which the pole axis is currently pointing (in world space)\n\tpole.copy(axis).applyQuaternion(worldQuat);\n\n\tconst currentPole = pole;\n\n\t// look direction in world space\n\tconst lookAxisDir = lookDir.copy( ZAxis ).applyQuaternion(worldQuat);\n\n\t// project desired pole direction onto the plane perpendicular to the look axis\n\tconst desiredPoleDir = poleDir.clone().addScaledVector(lookAxisDir, -poleDir.dot(lookAxisDir)).normalize();\n\n\t// signed angle between current pole and desired pole around the look axis\n\tconst cross = v.crossVectors(currentPole, desiredPoleDir);\n\tconst angle = Math.atan2(cross.dot(lookAxisDir), currentPole.dot(desiredPoleDir));\n\n\t// The correction is a spin around the look axis (local Z after lookAt).\n\t// Since lookAt aligned local Z to the target, we can apply around the local Z axis directly.\n\tcorrection.setFromAxisAngle(ZAxis, angle);\n\tobject.quaternion.multiply(correction);\n}","import * as THREE from \"three/webgpu\";\nimport {\n Landmark,\n NormalizedLandmark,\n\tDrawingUtils, \n} from \"@mediapipe/tasks-vision\"; \nimport { lookAt, LookAtPoleAxis } from \"./util/lookAt\";\n\n \n\nconst v = new THREE.Vector3();\nconst A = new THREE.Vector3();\nconst B = new THREE.Vector3();\nconst C = new THREE.Vector3();\n\nexport class Tracker<T extends Record<string, number|number[]> > {\n\tprivate objectGhost : Map<THREE.Object3D, Ghost> ;\n\treadonly root:THREE.Object3D;\n\n\t/**\n\t * per landmark index, it points to it's object3D equivalent.\n\t */\n\tprotected marks: { [name in keyof T]: Mark } = {} as { [name in keyof T]: Mark };\n\n\tconstructor( protected readonly points:T, private readonly debugConnections?:{start:number,end:number}[] ){\n\t\tthis.root = new THREE.Object3D();\n\t\tthis.objectGhost = new Map();\n\n\t\t// por each key in points\n\t\tfor( let key in this.points ){\n\t\t\tthis.marks[key] = new Mark();\n \n\t\t\tthis.root.add(this.marks[key]);\n\t\t}\n\t}\n\n\tprotected updateLandmarks( landmarks:Landmark[], debugLandmarks?:NormalizedLandmark[], debugDrawer?:DrawingUtils ) {\n\t\tfor( let key in this.points ){\n\t\t\tconst point = this.points[key];\n\t\t\tconst mark = this.marks[key];\n\t\t\tif( mark ){\n\t\t\t\tif( point instanceof Array )\n\t\t\t\t{\n\t\t\t\t\t\n\t\t\t\t\tv.copy( landmarks[ point[0] ] ) \n\t\t\t\t\tmark.position.copy( landmarks[ point[1] ] ).sub( v ).divideScalar(2).add(landmarks[ point[0] ]);\n\t\t\t\t\t\n\t\t\t\t\tif( point.length==4 )\n\t\t\t\t\t{\n\t\t\t\t\t\tv.subVectors(\n\t\t\t\t\t\t\tlandmarks[ point[3] ],\n\t\t\t\t\t\t\tlandmarks[ point[2] ]\n\t\t\t\t\t\t).divideScalar(2).add(landmarks[ point[2] ]) \n\n\t\t\t\t\t\t.sub( mark.position )\n\t\t\t\t\t\t.divideScalar(2) \n\n\t\t\t\t\t\tmark.position.add( v );\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\telse \n\t\t\t\t{\n\t\t\t\t\tmark.position.copy( landmarks[ point as number ] )\n\t\t\t\t}\n \n\t\t\t}\n\t\t}\n\n\t\tif( debugDrawer && debugLandmarks )\n\t\t{ \n\t\t\t// debugDrawer.drawLandmarks(debugLandmarks, {\n\t\t\t// \tradius: (data) =>\n\t\t\t// \t\tDrawingUtils.lerp(data.from!.z, -0.15, 0.1, 5, 1),\n\t\t\t// \tlineWidth:1\n\t\t\t// });\n\t\t\tdebugDrawer.drawConnectors(\n\t\t\t\tdebugLandmarks,\n\t\t\t\tthis.debugConnections,\n\t\t\t\t{\n\t\t\t\t\tlineWidth:1\n\t\t\t\t}\n\t\t\t); \n\t\t}\n\t}\n\n\tprotected getGhost( object:THREE.Object3D ){\n\t\tif( !this.objectGhost.has(object)) \n\t\t{\n\t\t\tconst o = new Ghost()\n\n\t\t\to.position.copy(object.position)\n\t\t\to.quaternion.copy(object.quaternion)\n\t\t\tobject.parent?.add(o);\n\n\t\t\tthis.objectGhost.set(object, o)\n\t\t} \n\t\treturn this.objectGhost.get(object)!;\n\t}\n\n\tpredict( source:TexImageSource, drawingUtils:DrawingUtils ){\n\t\tthrow new Error(\"Method 'predict' must be implemented.\");\n\t}\n\n\tsync ( delta:number, objects: [THREE.Object3D, keyof T, keyof T, LookAtPoleAxis][] ) {\n\t\tthrow new Error(\"Method 'sync' must be implemented.\"); \n\t}\n\n\ttest( key:keyof T ){\n\t\tthis.marks[key]!.position.set(1,2,3)\n\t}\n\n\tprotected syncObjects(objects: [THREE.Object3D, keyof T, keyof T,LookAtPoleAxis][], delta:number, normal:THREE.Vector3 ){\n\t\tfor( const [object, root, target, poleAxis] of objects ){\n\n\t\t\t//\n\t\t\t// position A and B where the landmarks are\n\t\t\t//\n\t\t\tthis.marks[target].getWorldPosition(B)\n\t\t\tthis.marks[root].getWorldPosition(A)\n\n\t\t\t//\n\t\t\t// calcuate the offset\n\t\t\t//\n\t\t\tconst offset = B.sub(A); // offset from root to taget in world units\n\n\t\t\t//\n\t\t\t// now position A in object position\n\t\t\t//\n\t\t\tobject.getWorldPosition(A)\n\n\t\t\t//\n\t\t\t// and displace it by the offset ( this will be the look at target )\n\t\t\t//\n\t\t\tA.add(offset);\n\n\t\t\t \n\t\t\tconst objectLookAtGoal = A;\n\t\t\tconst polePosition = object.getWorldPosition(B).sub( normal )\n\n\t\t\tconst ghost = this.getGhost(object);\n \n\n\t\t\t \n\t\t\t\tlookAt( ghost, objectLookAtGoal, polePosition, poleAxis);\n\n\t\t\t\tghost.rotateX( Math.PI/2) \n\t\t\t\n\t\t\t//ghost.rotateY( Math.PI/2)\n\n\t\t\tobject.position.lerp(ghost.position, delta * 4)\n\t\t\tobject.quaternion.slerp(ghost.quaternion, delta * 4) \n\t\t}\n\t}\n\n\tprotected getBone( rig:THREE.Object3D, name:string ){\n\t\treturn rig.getObjectByName(name.replace(/[\\.\\:]/g,\"\")) ;\n\t}\n}\n\n// const t = {\n// \tpepe:[1,2]\n// }\n// const d = new Tracker(t)\n// d.test(\"pepe\")\n\nclass Mark extends THREE.Mesh {\n\tprivate _worldPosition = new THREE.Vector3();\n\tconstructor() {\n\t\tsuper(new THREE.SphereGeometry(0.01,3,3), new THREE.MeshStandardMaterial({ color: 0xff0000, wireframe:true }));\n\t\tthis.add( new THREE.AxesHelper(0.001))\n\t}\n\n\tget worldPosition(){\n\t\tthis.getWorldPosition(this._worldPosition);\n\t\treturn this._worldPosition;\n\t}\n}\n\nclass Ghost extends THREE.Object3D { \n\tlerp( target:THREE.Object3D, delta:number, speed = 8 )\n\t{\n\t\ttarget.position.lerp(this.position, delta * speed)\n\t\ttarget.quaternion.slerp(this.quaternion, delta * speed) \n\t}\n}","import { Object3D, Vector3 } from \"three/webgpu\";\n\n\n/**\n * Gets the position of `object` relative to `root`.\n * @param out \n * @param object \n * @param root \n * @returns \n */\nexport function rootPosition( out:Vector3, object:Object3D, root:Object3D ) {\n\n\troot.worldToLocal( object.getWorldPosition(out) )\n\n\treturn out;\n}","export function cleanBoneName(name:string) {\n\treturn name.replace(/[\\.\\:]/g,\"\")\n}","import { Bone, Object3D } from \"three\";\nimport { cleanBoneName } from \"./cleanBoneName\";\n\nexport function getBoneByName(rig:Object3D, name:string) {\n\tlet bone:Bone|undefined;\n\tname = cleanBoneName(name); \n\t\n\trig.traverse( (o:Object3D) => {\n\t\tif( o.name.indexOf(name)===0 && o instanceof Bone ) bone = o as Bone;\n\t})\n\n\tif( !bone ) console.log(\"Bone not found: \", name, rig.name)\n\n\treturn bone;\n}","import {\n DrawingUtils,\n NormalizedLandmark,\n PoseLandmarker,\n} from \"@mediapipe/tasks-vision\"; \nimport * as THREE from \"three/webgpu\";\nimport { lookAt, LookAtPoleAxis } from \"./util/lookAt\";\nimport { Tracker } from \"./Tracker\";\nimport { rootPosition } from \"./util/getRootPosition\";\nimport { getBoneByName } from \"./util/getBoneByName\";\nimport { BoneMap } from \"./BoneMapping\";\n\nexport async function loadPoseTracker(vision: any, config?:Partial<PoseTrackerConfig>) {\n\tconst poseLandmarker = await PoseLandmarker.createFromOptions(vision, {\n baseOptions: { \n\t\t\tmodelAssetPath: config?.modelPath ?? \"pose_landmarker_lite.task\",\n //modelAssetPath: `https://storage.googleapis.com/mediapipe-models/pose_landmarker/pose_landmarker_lite/float16/1/pose_landmarker_lite.task`,\n //modelAssetPath: \"https://storage.googleapis.com/mediapipe-models/pose_landmarker/pose_landmarker_heavy/float16/latest/pose_landmarker_heavy.task\",\n delegate: \"GPU\",\n },\n runningMode: \"VIDEO\",\n numPoses: 1,\n });\n\n\treturn new PoseTracker(poseLandmarker, config);\n} \n\n/**\n * Points derived from https://ai.google.dev/static/mediapipe/images/solutions/pose_landmarks_index.png\n * If the array has 2 elements, the point is between those 2 landmarks.\n * If it has 4, the point is at the center of those 4 landmarks.\n */\nconst poseMarks = {\n\t\t\thips: [24,23],\n\t\t\tneck: [12,11],\n\t\t\tleftLeg: 23,\n\t\t\tleftKnee:25,\n\t\t\tleftFoot: 27,\n\t\t\tleftToes: 31,\n\t\t\tleftArm: 11,\n\t\t\tleftElbow: 13,\n\t\t\tleftWrist: 15,\n\t\t\trightLeg: 24,\n\t\t\trightKnee: 26,\n\t\t\trightFoot: 28,\n\t\t\trightToes: 32,\n\t\t\trightArm: 12,\n\t\t\trightElbow: 14,\n\t\t\trightWrist: 16, \n\t\t\thead: [8,7] //between the ears\n\t\t\t, mouth:[10,9]\n\t\t\t, torso: [24,23, 12,11] //at the center of the torso\n\t\t\t, leftEar: 7\n\t\t\t, rightEar: 8\n\t\t} ;\n\ntype MarkKey = keyof typeof poseMarks;\n\ntype BoneBinding = [THREE.Object3D, MarkKey, MarkKey,LookAtPoleAxis]\n\nconst A = new THREE.Vector3();\nconst B = new THREE.Vector3();\nconst C = new THREE.Vector3();\nconst D = new THREE.Vector3();\nconst E = new THREE.Vector3();\nconst lookGoal = new THREE.Vector3();\nconst poleGoal = new THREE.Vector3();\n\ntype PoseTrackerConfig = {\n\tignoreLegs:boolean\n\tmodelPath:string\n}\n\n/**\n * @see https://ai.google.dev/edge/mediapipe/solutions/vision/pose_landmarker\n */\nclass PoseTracker extends Tracker<typeof poseMarks> {\n\tprivate _leftWristNormalizedPosition!:NormalizedLandmark;\n\tprivate _rightWristNormalizedPosition!:NormalizedLandmark;\n\n\t/**\n\t * Position of the left wrist in normalized coordinates (0..1)\n\t */\n\tget leftWristNormalizedPosition() { return this._leftWristNormalizedPosition; }\n\n\t/**\n\t * Position of the right wrist in normalized coordinates (0..1)\n\t */\n\tget rightWristNormalizedPosition() { return this._rightWristNormalizedPosition; }\n\n\tconstructor(private readonly poseLandmarker:PoseLandmarker, private readonly config?:Partial<PoseTrackerConfig>){ \n\n\t\tsuper(poseMarks, PoseLandmarker.POSE_CONNECTIONS)\n\t\t\n\t\tthis.root.scale.y *= -2\n\t\tthis.root.scale.z *= -2\n\t\tthis.root.scale.x *= 2 \n\t}\n\n\toverride predict( source:TexImageSource, drawingUtils:DrawingUtils ){\n\t\tthis.poseLandmarker.detectForVideo( source, performance.now(), (result) => {\n\n\t\t\tif( result.landmarks.length==0 )\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n \n\t\t\tthis.updateLandmarks( result.worldLandmarks[0], result.landmarks[0], drawingUtils );\n\n\t\t\t\n\t\t\tthis._leftWristNormalizedPosition = result.landmarks[0][ this.points.leftWrist ];\n\t\t\tthis._rightWristNormalizedPosition = result.landmarks[0][ this.points.rightWrist ];\n\t\t} );\n\t}\n\n\t// override sync ( delta:number, objects: BoneBinding[] ) {\n\n\t// \tconst hipsPos = this.marks.hips.getWorldPosition(C); \n\n\t// \tthis.marks.rightArm.getWorldPosition(A).sub(hipsPos);\n\t// \tthis.marks.leftArm.getWorldPosition(B).sub(hipsPos); \n\n\t// \tconst torsoNormal = C.crossVectors(A,B);\n\n\t// \tthis.syncObjects(objects, delta, torsoNormal); \n\n\t// }\n\t\n\n\tbind( rig:THREE.Object3D, magging:BoneMap )\n\t{ \n\t\t \n\t\tconst map : { [key in MarkKey]?:THREE.Object3D } = {\n\t\t\t\"hips\": getBoneByName(rig, magging.hips),\n\t\t\t\"neck\": getBoneByName(rig, magging.neck),\n\t\t\t\"leftArm\": getBoneByName(rig, magging.armL),\n\t\t\t\"leftElbow\": getBoneByName(rig, magging.forearmL),\n\t\t\t\"leftWrist\": getBoneByName(rig, magging.handL),\n\t\t\t\"rightArm\": getBoneByName(rig, magging.armR),\n\t\t\t\"rightElbow\": getBoneByName(rig, magging.forearmR),\n\t\t\t\"rightWrist\": getBoneByName(rig, magging.handR),\n\t\t\t\"head\": getBoneByName(rig, magging.head), \n\t\t\t\"torso\": getBoneByName(rig, magging.torso),\n\t\t\t\"leftLeg\": getBoneByName(rig, magging.thighL),\n\t\t\t\"leftKnee\": getBoneByName(rig, magging.shinL),\n\t\t\t\"leftFoot\": getBoneByName(rig, magging.footL),\n\t\t\t\"rightLeg\": getBoneByName(rig, magging.thighR),\n\t\t\t\"rightKnee\": getBoneByName(rig, magging.shinR),\n\t\t\t\"rightFoot\": getBoneByName(rig, magging.footR),\n\t\t} \n\n\t\tif( this.config?.ignoreLegs ){\n\t\t\tdelete map.leftLeg\n\t\t\tdelete map.leftKnee\n\t\t\tdelete map.leftFoot\n\t\t\tdelete map.leftToes\n\t\t\tdelete map.rightLeg\n\t\t\tdelete map.rightKnee\n\t\t\tdelete map.rightFoot\n\t\t\tdelete map.rightToes\n\t\t}\n\n\t\tconst v = new THREE.Vector3();\n\t\tconst v2 = new THREE.Vector3();\n\n\t\tconst syncBone = ( delta:number, bone:THREE.Object3D|undefined, from:MarkKey, to:MarkKey, sideAxis:THREE.Vector3, poleAxis:LookAtPoleAxis ) => {\n\t\t\tif( !bone ) return;\n\n\t\t\tconst hipsDir = this.marks[to].getWorldPosition(v).sub(this.marks[from].getWorldPosition(v2)).normalize(); \n\n\t\t \n\t\t\trootPosition(lookGoal, bone, rig).add( hipsDir ).applyMatrix4(rig.matrixWorld) ;\n\t\t\trootPosition(poleGoal, bone, rig).add( sideAxis ).applyMatrix4(rig.matrixWorld) ; \n\n\t\t\tconst ghost = this.getGhost(bone)\n\n\t\t\tlookAt(ghost, lookGoal, poleGoal, poleAxis)\n\t\t\tghost.rotateX(Math.PI/2)\n\t\t\t \n\n\t\t\tghost.lerp(bone, delta)\n\t\t}\n\n\t\treturn {\n\t\t\tupdate: (delta:number)=>{\n \n\t\t\t\tconst sideHips = this.marks.leftLeg.getWorldPosition(A).sub(this.marks.rightLeg.getWorldPosition(B)).normalize();\n\t\t\t\tconst sideShoulders = this.marks.leftArm.getWorldPosition(B).sub(this.marks.rightArm.getWorldPosition(C)).normalize();\n\t\t\t\tconst sideHead = this.marks.leftEar.getWorldPosition(D).sub(this.marks.rightEar.getWorldPosition(E)).normalize();\n\n\t\t\t\tsyncBone(delta, map.hips, \"hips\", \"torso\", sideHips, \"+x\")\n\t\t\t\tsyncBone(delta, map.torso, \"torso\", \"neck\", sideShoulders, \"+x\")\n\t\t\t\tsyncBone(delta, map.neck, \"neck\", \"head\", sideHead, \"+x\")\n\t\t\t\tsyncBone(delta, map.head, \"neck\", \"head\", sideHead, \"+x\")\n\n\t\t\t\tsyncBone(delta, map.leftArm, \"leftArm\", \"leftElbow\", sideShoulders, \"-x\")\n\t\t\t\tsyncBone(delta, map.leftElbow, \"leftElbow\", \"leftWrist\", sideShoulders, \"-x\")\n\t\t\t\tsyncBone(delta, map.leftLeg, \"leftLeg\", \"leftKnee\", sideHips, \"+x\") \n\t\t\t\tsyncBone(delta, map.leftKnee, \"leftKnee\", \"leftFoot\", sideHips, \"+x\") \n\t\t\t\tsyncBone(delta, map.leftFoot, \"leftFoot\", \"leftToes\", sideHips, \"+x\") \n\n\t\t\t\tsyncBone(delta, map.rightArm, \"rightArm\", \"rightElbow\", sideShoulders, \"-x\")\n\t\t\t\tsyncBone(delta, map.rightElbow, \"rightElbow\", \"rightWrist\", sideShoulders, \"-x\")\n\t\t\t\tsyncBone(delta, map.rightLeg, \"rightLeg\", \"rightKnee\", sideHips, \"+x\") \n\t\t\t\tsyncBone(delta, map.rightKnee, \"rightKnee\", \"rightFoot\", sideHips, \"+x\") \n\t\t\t\tsyncBone(delta, map.rightFoot, \"rightFoot\", \"rightToes\", sideHips, \"+x\") \n\t\t\t\t\n\t\t\t}\n\t\t}\n\t}\n}\n ","import {\n\tDrawingUtils,\n HandLandmarker,\n\tHandLandmarkerOptions,\n\tNormalizedLandmark,\n} from \"@mediapipe/tasks-vision\";\nimport * as THREE from \"three/webgpu\";\nimport { lookAt, LookAtPoleAxis } from \"./util/lookAt\";\nimport { Tracker } from \"./Tracker\";\nimport { rootPosition } from \"./util/getRootPosition\";\nimport { getBoneByName } from \"./util/getBoneByName\";\nimport { BoneMap } from \"./BoneMapping\";\n\nexport type HandsTrackerConfig = {\n\tleftWrist: ()=>NormalizedLandmark;\n\trightWrist: ()=>NormalizedLandmark;\n\tmodelPath?:string\n} & Partial<HandLandmarkerOptions>;\n\nconst A = new THREE.Vector2();\nconst B = new THREE.Vector2();\n\nexport async function loadHandTracker(vision: any, config:HandsTrackerConfig ) {\n const landmarker = await HandLandmarker.createFromOptions(vision, {\n baseOptions: {\n modelAssetPath: config.modelPath ?? \"hand_landmarker.task\",\n //modelAssetPath: `https://storage.googleapis.com/mediapipe-models/hand_landmarker/hand_landmarker/float16/1/hand_landmarker.task`,\n delegate: \"GPU\",\n },\n runningMode: \"VIDEO\",\n numHands: 2,\n });\n\n\tconst isMyWrist = ( myWrist:()=>NormalizedLandmark, otherWrist:()=>NormalizedLandmark, handWrist:NormalizedLandmark ) => {\n\t\tA.copy(myWrist());\n\t\tB.copy(otherWrist());\n\t\treturn A.distanceTo(handWrist) < B.distanceTo(handWrist);\n\t}\n\n return {\n\t\tleft:new HandsTracker(landmarker, \"Left\", isMyWrist.bind(null, config.leftWrist, config.rightWrist) ),\n\t\tright:new HandsTracker(landmarker, \"Right\", isMyWrist.bind(null, config.rightWrist, config.leftWrist) )\n\t};\n}\n\nconst handMarks = {\n wrist: 0,\n\tpalm: [9,13],\n\n thumb1: 1,\n thumb2: 2,\n thumb3: 3,\n thumb4: 4,\n\n index1: 5,\n index2: 6,\n index3: 7,\n index4: 8,\n\n middle1: 9,\n middle2: 10,\n middle3: 11,\n middle4: 12,\n\n ring1: 13,\n ring2: 14,\n ring3: 15,\n ring4: 16,\n\n pinky1: 17,\n pinky2: 18,\n pinky3: 19,\n pinky4: 20,\n};\n\nexport type HandMarkName = keyof typeof handMarks;\n\nconst fingerKeys = {\n\tthumb: [\"thumb1\",\"thumb2\",\"thumb3\",\"thumb4\"],\n\tindex: [\"index1\",\"index2\",\"index3\",\"index4\"],\n\tmiddle: [\"middle1\",\"middle2\",\"middle3\",\"middle4\"],\n\tring: [\"ring1\",\"ring2\",\"ring3\",\"ring4\"],\n\tpinky: [\"pinky1\",\"pinky2\",\"pinky3\",\"pinky4\"]\n} as { [key:string]: HandMarkName[]} ;\n\n\ntype HandSide = \"Left\" | \"Right\"\nexport type Mark2Bone = Partial<{ [key in HandMarkName]: THREE.Object3D }>;\n\nconst v1 = new THREE.Vector3();\nconst v2 = new THREE.Vector3();\nconst v3 = new THREE.Vector3();\nconst v4 = new THREE.Vector3();\nconst v5 = new THREE.Vector3();\nconst v6 = new THREE.Vector3();\n\nconst currNormal = new THREE.Vector3();\nconst currForward = new THREE.Vector3();\nconst currSide = new THREE.Vector3();\nconst HALF_PI = Math.PI/2\nconst DOWN = new THREE.Vector3(0,-1,0);\n\nclass HandsTracker extends Tracker<typeof handMarks> {\n\tprivate readonly sign:number;\n\tprivate readonly isLeft:boolean;\n\t/**\n\t * the axis used to look at the pole\n\t */\n\tprivate readonly lookAtPoleAxis:LookAtPoleAxis;\n\n\tconstructor(private readonly handLandmarker:HandLandmarker, private readonly side:HandSide, private readonly isMyWrist:( handWrist:NormalizedLandmark )=>boolean ){\n\t\tsuper(handMarks, HandLandmarker.HAND_CONNECTIONS)\n\n\t\tthis.sign = this.side==\"Left\" ? -1 : 1;\n\t\tthis.isLeft = this.side==\"Left\";\n\t\tthis.lookAtPoleAxis = this.sign<0? \"+x\" : \"-x\";\n\t\tthis.root.scale.setScalar(2)\n\t\tthis.root.scale.y *= -1\n\t\tthis.root.scale.z *= -1\n\t}\n\n\toverride predict( source:TexImageSource, drawingUtils:DrawingUtils ){\n\t\tconst result = this.handLandmarker.detectForVideo(source, performance.now());\n\n\t\tif( result.landmarks.length )\n\t\t{\n\t\t\t//console.log(`DETECTED ${result.landmarks.length} hands`, result.handedness)\n\n\n\t\t\tfor(let i=0; i<result.landmarks.length; i++){\n\t\t\t\tconst hand = result.landmarks[i];\n\t\t\t\tconst wrist = hand[this.points.wrist];\n\t\t\t\tconst isMyWrist = this.isMyWrist(wrist);\n\t\t\t\tif( isMyWrist ){\n\t\t\t\t\tthis.updateLandmarks( result.worldLandmarks[i] );\n\n\t\t\t\t\tdrawingUtils.drawConnectors(hand, HandLandmarker.HAND_CONNECTIONS, {\n\t\t\t\t\t\tcolor: this.side==\"Left\" ? \"#00FF00\" : \"#0000FF\",\n\t\t\t\t\t\tlineWidth: 4\n\t\t\t\t\t});\n\t\t\t\t\tdrawingUtils.drawLandmarks(hand, { color: this.side==\"Left\" ? \"#00FF00\" : \"#0000FF\", lineWidth: 3, radius: 1 }); \n\n\t\t\t\t\t\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} \n \n \n\t\t} \n\t}\n\n\toverride sync ( delta:number, objects: [THREE.Object3D, HandMarkName, HandMarkName, LookAtPoleAxis][] ) {\n\n\t\tthrow new Error(\"Not used. Use syncHandBones instead\");\n\t}\n\t\t\n\t/**\n\t * \n\t * @param delta time since last frame\n\t * @param landmark2bones Array the same size as the umber of hand landmarks, and on each positionthe bone that belongs to that point.\n\t * @see https://ai.google.dev/edge/mediapipe/solutions/vision/hand_landmarker\n\t */\n\tsyncHandBones( delta:number, markToBone:Mark2Bone, rig:THREE.Object3D )\n\t{ \n\t\tconst palmNormal = v1.crossVectors(\n\t\t\tv2.copy(this.marks.index1.worldPosition).sub(this.marks.wrist.worldPosition),\n\t\t\tv3.copy(this.marks.pinky1.worldPosition).sub(this.marks.wrist.worldPosition)\n\t\t).normalize();\n\n\t\tconst parlmDir = v2.copy(this.marks.palm.worldPosition).sub(this.marks.wrist.worldPosition).normalize();\n\t\tconst palmSide = v3.copy(this.marks.pinky1.worldPosition).sub(this.marks.index1.worldPosition).normalize();\n\t\t \n\t\tif( parlmDir.dot(DOWN)>0.8 )\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tif( markToBone.wrist )\n\t\t{\n\t\t\tconst palmLookAt = rootPosition(v4, markToBone.wrist, rig ).add( parlmDir ).applyMatrix4(rig.matrixWorld) //markToBone.wrist.getWorldPosition(v4).add( parlmDir );\n\t\t\tconst polPosition = rootPosition(v5, markToBone.wrist, rig ).sub( palmSide ).applyMatrix4(rig.matrixWorld) //markToBone.wrist.getWorldPosition(v5).sub( palmSide );\n\n\t\t\tconst palmGhost = this.getGhost(markToBone.wrist)\n\n\t\t\tlookAt( palmGhost, palmLookAt, polPosition, \"-y\" );\n\t\t\tpalmGhost.rotateX( HALF_PI ) ; \n\n\t\t\tpalmGhost.lerp(markToBone.wrist, delta)\n\t\t}\n\t\t\n\n\t\t// palmLookAtOffset.normalize();\n\n\t\t \n\t\t// const palmSide = v3.crossVectors(palmNormal, palmLookAtOffset).normalize();\n \n\t\tthis.syncFinger( delta, rig, palmNormal, parlmDir, palmSide, markToBone, fingerKeys.index, \"middle1\" )\n\t\tthis.syncFinger( delta, rig, palmNormal, parlmDir, palmSide, markToBone, fingerKeys.middle, \"ring1\" )\n\t\tthis.syncFinger( delta, rig, palmNormal, parlmDir, palmSide, markToBone, fingerKeys.ring, \"pinky1\" )\n\t\tthis.syncFinger( delta, rig, palmNormal, parlmDir, palmSide, markToBone, fingerKeys.pinky, \"ring1\", true )\n\n\t\t// //thumb...\n\t\tthis.syncFinger( delta, rig, palmNormal, parlmDir, palmSide, markToBone, fingerKeys.thumb, \"index1\" )\n\n\t\t\n\t}\n\n\tprivate syncFinger( delta:number, rig:THREE.Object3D, palmNormal:THREE.Vector3, palmForward:THREE.Vector3, palmSide:THREE.Vector3, markToBone:Mark2Bone, fingerKeys:HandMarkName[], sideGoal:HandMarkName, negateSideGoal:boolean=false ){\n\t \n\t\tlet signMult = 1;\n\n\t\tfor(let i=0; i<fingerKeys.length-1;i++) { \n\t\t\t\n\t\t\tconst bone = markToBone[fingerKeys[i]];\n\t\t\t//const bonePole = markToBone[sideGoal];\n\n\t\t\tif(!bone ) continue;\n\n\t\t\tconst myDir = v4.copy( this.marks[fingerKeys[i+1]].worldPosition ).sub( this.marks[fingerKeys[i]].worldPosition).normalize(); \n\t\t\t\n\t\t\tconst bonePos = rootPosition(v5, bone, rig) //bone.getWorldPosition(v5);\n\t\t\tconst poleOffset = v6.copy(bonePos).add(palmSide) //rootPosition(v6, bonePole, rig).sub( bonePos );//bonePole.getWorldPosition(v6).sub( bonePos );\n\n\t\t\tif( negateSideGoal ) poleOffset.negate();\n\n\t\t\tconst fingerGhost = this.getGhost(bone)\n\n\n\t\t\tif( i==0 )\n\t\t\t{ \n\n\t\t\t\tcurrSide.copy(poleOffset);\n\n\t\t\t\t\n\t\t\t\tlookAt( fingerGhost, \n\t\t\t\t\tmyDir.add( bonePos ).applyMatrix4(rig.matrixWorld), \n\t\t\t\t\tpoleOffset.add(bonePos).applyMatrix4(rig.matrixWorld), \n\t\t\t\t\tthis.lookAtPoleAxis );\n\n\t\t\t\t\n\t\t\t}\n\t\t\telse \n\t\t\t{ \n\t\t\t\tpoleOffset.copy( currSide );\n\t\t\t\tlookAt( fingerGhost, \n\t\t\t\t\tmyDir.add( bonePos ).applyMatrix4(rig.matrixWorld), \n\t\t\t\t\tpoleOffset.add(bonePos).applyMatrix4(rig.matrixWorld), \n\t\t\t\t\tthis.lookAtPoleAxis );\n\t\t\t} \n\n\t\t\tfingerGhost.rotateX( HALF_PI ); \n\n\t\t\tfingerGhost.lerp(bone, delta)\n\n\t\t}\n\n \n\t}\n \n\tbind( rig:THREE.Object3D, magging:BoneMap ){\n\n\t\tconst map:Mark2Bone = {\n\t\t\t\n\t\t}\t \n\n\t\tconst addBind = ( boneName:string, markName:HandMarkName ) => {\n\t\t\t//const bone = rig.getObjectByName( cleanBoneName( boneName.replace(\"X\", this.sign<0 ? \"L\" : \"R\") ));\n\n\t\t\tconst bone = getBoneByName(rig, boneName );\n\n\t\t\tif( bone ){\n\t\t\t\tmap[markName] = bone;\n\t\t\t}\n\t\t}\n\n\t\taddBind( this.isLeft ? magging.handL : magging.handR, \"wrist\" )\n\t\taddBind( this.isLeft ? magging.index1L : magging.index1R, \"index1\" )\n\t\taddBind( this.isLeft ? magging.index2L : magging.index2R, \"index2\" )\n\t\taddBind( this.isLeft ? magging.index3L : magging.index3R, \"index3\" ) \n\n\t\taddBind( this.isLeft ? magging.middle1L : magging.middle1R, \"middle1\" )\n\t\taddBind( this.isLeft ? magging.middle2L : magging.middle2R, \"middle2\" )\n\t\taddBind( this.isLeft ? magging.middle3L : magging.middle3R, \"middle3\" ) \n\n\t\taddBind( this.isLeft ? magging.ring1L : magging.ring1R, \"ring1\" )\n\t\taddBind( this.isLeft ? magging.ring2L : magging.ring2R, \"ring2\" )\n\t\taddBind( this.isLeft ? magging.ring3L : magging.ring3R, \"ring3\" ) \n\n\t\taddBind( this.isLeft ? magging.pinky1L : magging.pinky1R, \"pinky1\" )\n\t\taddBind( this.isLeft ? magging.pinky2L : magging.pinky2R, \"pinky2\" )\n\t\taddBind( this.isLeft ? magging.pinky3L : magging.pinky3R, \"pinky3\" ) \n\n\t\taddBind( this.isLeft ? magging.thumb1L : magging.thumb1R, \"thumb1\" )\n\t\taddBind( this.isLeft ? magging.thumb2L : magging.thumb2R, \"thumb2\" )\n\t\taddBind( this.isLeft ? magging.thumb3L : magging.thumb3R, \"thumb3\" ) \n\n\t\treturn {\n\t\t\tupdate: ( delta:number )=> { \n\t\t\t\tthis.syncHandBones(delta, map, rig);\n\t\t\t}\n\t\t}\t\n\t}\n}\n","import {\n Category,\n DrawingUtils,\n FaceLandmarker\n} from \"@mediapipe/tasks-vision\";\nimport { Mesh, Object3D, Vector3 } from \"three/webgpu\";\nimport { Tracker } from \"./Tracker\";\nimport { rootPosition } from \"./util/getRootPosition\";\nimport { getBoneByName } from \"./util/getBoneByName\";\nimport { lookAt } from \"./util/lookAt\";\n\nexport async function loadFaceTracker(vision: any, cfg?: { modelPath?: string }) {\n const faceLandmarker = await FaceLandmarker.createFromOptions(vision, {\n baseOptions: {\n modelAssetPath: cfg?.modelPath ?? \"face_landmarker.task\",\n\t\t\tdelegate: \"GPU\", \n },\n\t\toutputFaceBlendshapes: true,\n runningMode: \"VIDEO\",\n\t\tnumFaces: 1,\n });\n\n\treturn new FaceTracker(faceLandmarker);\n}\n\n/**\n * @see https://storage.googleapis.com/mediapipe-assets/documentation/mediapipe_face_landmark_fullsize.png\n */\nconst faceMarks = {\n\teyeL: 473,\n\teyeR: 468,\n\teyeStartL: 463,\n\teyeStartR: 243,\n\teyeEndL: 263,\n\teyeEndR: 33, \n\n\tearL: 454,\n\tearR: 234,\n\tnoseTip: 4,\n\tnoseBone:6,\n\tchin:152,\n\tforehead: 10\n\n}\n\ntype MarkKey = keyof typeof faceMarks;\nconst v = new Vector3();\nconst v2 = new Vector3();\nconst v3 = new Vector3();\nconst v4 = new Vector3();\nconst v5 = new Vector3();\nconst v6 = new Vector3();\n\nclass FaceTracker extends Tracker<typeof faceMarks> {\n\tprivate blendshapeCategories: Category[] | undefined;\n\tprivate blendshapeMap: Map<string, number> = new Map();\n\tprivate smoothed: Record<string, number> = {};\n\tprivate smoothing =.0003; // lower = smoother but more lag, higher = more responsive\n\n\tconstructor(private faceLandmarker: FaceLandmarker) {\n\t\tsuper(faceMarks, FaceLandmarker.FACE_LANDMARKS_TESSELATION)\n\n\t\tthis.root.scale.y*=-1\n\t\tthis.root.scale.z*=-1\n\t\tthis.root.scale.multiplyScalar(3)\n\t}\n\n\toverride predict(frame: TexImageSource, drawingUtils: DrawingUtils) {\n\t\tconst result = this.faceLandmarker.detectForVideo(frame, performance.now());\n\t\tif (result.faceLandmarks[0]) {\n\t\t\tdrawingUtils.drawConnectors(result.faceLandmarks[0], FaceLandmarker.FACE_LANDMARKS_TESSELATION, { color: \"#00fff2ff\", lineWidth: .1 });\n\t\t\tdrawingUtils.drawLandmarks(result.faceLandmarks[0], { color: \"#00ff00\", lineWidth: .1, radius: .4 });\t\n\n\t\t\tthis.updateLandmarks(result.faceLandmarks[0], result.faceLandmarks[0] );\n\t\t}\n\n\t\tthis.blendshapeCategories = result.faceBlendshapes?.[0]?.categories; \n\n\t\tthis.blendshapeCategories?.forEach((category) => {\n\t\t\tthis.blendshapeMap.set(category.categoryName, category.score);\n\t\t});\n\t\t\n\t}\n\n\tbindShapeKeys(mesh: Mesh) {\n\t\tconst meshKeys = mesh.morphTargetDictionary; \n\n\t\treturn {\n\t\t\tupdate: (delta: number) => {\n\t\t\t\tthis.blendshapeCategories?.forEach((category) => {\n\t\t\t\t\tconst { categoryName, score } = category;\n\n\t\t\t\t\tif (!meshKeys?.hasOwnProperty(categoryName)) return;\n\n\t\t\t\t\t// Initialize if first time seeing this key\n\t\t\t\t\tif (this.smoothed[categoryName] === undefined)\n\t\t\t\t\t\tthis.smoothed[categoryName] = score;\n\n\t\t\t\t\t// Lerp toward target score\n\t\t\t\t\tconst factor = 1 - Math.pow(this.smoothing, delta);\n\t\t\t\t\tthis.smoothed[categoryName] += (score - this.smoothed[categoryName]) * factor;\n\n\t\t\t\t\tmesh.morphTargetInfluences![meshKeys[categoryName]] = this.smoothed[categoryName];\n\t\t\t\t});\n\n\t\t\t\t//eyes\n\t\t\t}\n\t\t}\n\t}\n\n\tbind( rig:Object3D ) {\n\n\t\tconst eyeL = new EyeRig(rig, \"L\");\n\t\tconst eyeR = new EyeRig(rig, \"R\");\n\t\tconst headBone = getBoneByName(rig, \"head\") ;\n \n\t\treturn {\n\t\t\tupdate: ( delta:number )=> {\n\t\t\t\t \n\t\t\t\teyeL.update(delta, this.blendshapeMap);\n\t\t\t\teyeR.update(delta, this.blendshapeMap); \n\t\t\t\t\n\t\t\t\tif(!headBone) return;\n\n\t\t\t\t//\n\t\t\t\tconst markEarL = v.copy( this.marks.earL.worldPosition );\n\t\t\t\tconst markEarR = v2.copy( this.marks.earR.worldPosition );\n\t\t\t\tconst headcenter = v3.subVectors(markEarL, markEarR).multiplyScalar(.5).add(markEarR);\n\t\t\t\tconst headForward = v4.subVectors(this.marks.noseTip.worldPosition, headcenter) ;\n\t\t\t\tconst headSideNormal = markEarL.sub(markEarR) ;\n\n\t\t\t\t\n\t\t\t\tconst headPosition = rootPosition( v5, headBone, rig); \n\n\t\t\t\tconst poleLookAt = headSideNormal.add( headPosition ).applyMatrix4(rig.matrixWorld);\n\t\t\t\tconst faceLookAt = headForward.add( headPosition ).applyMatrix4(rig.matrixWorld);\n\n\t\t\t\tlookAt( headBone, faceLookAt, poleLookAt,\"+x\" );\n\t\t\t\t \n\n\t\t\t\t// headLookAtPos.applyMatrix4(rig.matrixWorld);\n\t\t\t\t//headBone.lookAt( headLookAtPos );\n\t\t\t\t// \n\t\t\t}\n\t\t}\n\t\t\n\t}\n}\n\nclass EyeRig {\n\tprivate eyeBone:Object3D|undefined; \n\n\tprivate eyeLookOut:string;\n\tprivate eyeLookIn:string;\n\tprivate eyeLookUp:string;\n\tprivate eyeLookDown:string;\n\tprivate sign = 1;\n\t\n\tconstructor( readonly rig:Object3D, readonly side:\"L\"|\"R\" ) {\n\t\tthis.eyeBone = rig.getObjectByName(`eye${side}`) as Object3D; \n\n\t\tconst sideName = side == \"L\" ? \"Left\" : \"Right\";\n\t\tthis.eyeLookOut = `eyeLookOut${sideName}`;\n\t\tthis.eyeLookIn = `eyeLookIn${sideName}`;\n\t\tthis.eyeLookUp = `eyeLookUp${sideName}`;\n\t\tthis.eyeLookDown = `eyeLookDown${sideName}`;\n\n\t\tthis.sign = side == \"L\" ? -1 : 1;\n\t}\n\n\tupdate( delta:number, blendshapes: Map<string, number> ) {\n\t\tif( !this.eyeBone ) return; \n \n\t\tconst eye = rootPosition(v3, this.eyeBone, this.rig); \n\n\t\t\n\t\t\n\t\t// From MediaPipe blendshapes\n\t\tconst lookLeft = blendshapes.get(this.eyeLookOut) ?? 0; // or eyeLookInRight\n\t\tconst lookRight = blendshapes.get(this.eyeLookIn) ?? 0; // or eyeLookOutRight\n\t\tconst lookUp = blendshapes.get(this.eyeLookUp) ?? 0;\n\t\tconst lookDown = blendshapes.get(this.eyeLookDown) ?? 0;\n\n\t\t\n\t\t// Map to a -1..1 range\n\t\tconst sideMovement = lookRight - lookLeft // horizontal\n\t\tconst verticalMovement = lookDown - lookUp // vertical\n\n\t\tconsole.log(\"EYE: \", sideMovement, verticalMovement)\n\n\t\tthis.eyeBone.rotation.y =( sideMovement * this.sign) / 2; \n\t\tthis.eyeBone.rotation.x = verticalMovement / 2; \n\t\t// // Then drive your rig bone with a target offset\n\t\t// const lookAtPos = eyeCenter\n\t\t// .add(eyeHorizontalDir ) // -sideMovement * eyeRange)\n\t\t// //.addScaledVector(eyeVerticalDir, verticalMovement * eyeRange/3)\n\t\t// .applyMatrix4(this.rig.matrixWorld);\n\n\t\t// this.eyeBone.lookAt(lookAtPos);\n\t\t// this.eyeBone.rotateX(Math.PI/2)\n\t}\n}","/**\n * The bone mapping to use for the rig.\n */\nexport type BoneMap = {\n\tfaceMesh:string\n\thead: string;\n\thips:string\n\tneck:string\n\ttorso:string\n\tarmL:string\n\tforearmL:string\n\n\tarmR:string\n\tforearmR:string\n\n\tthighL:string\n\tshinL:string\n\tfootL:string\n\ttoesL:string\n\n\tthighR:string\n\tshinR:string\n\tfootR:string\n\ttoesR:string\n\t \n\t\n\thandL:string\n\tindex1L:string\n\tindex2L:string\n\tindex3L:string\n\n\tmiddle1L:string\n\tmiddle2L:string\n\tmiddle3L:string\n\n\tring1L:string\n\tring2L:string\n\tring3L:string\n\n\tpinky1L:string\n\tpinky2L:string\n\tpinky3L:string\n\n\tthumb1L:string\n\tthumb2L:string\n\tthumb3L:string\n\n\thandR:string\n\tindex1R:string\n\tindex2R:string\n\tindex3R:string\n\n\tmiddle1R:string\n\tmiddle2R:string\n\tmiddle3R:string\n\n\tring1R:string\n\tring2R:string\n\tring3R:string\n\n\tpinky1R:string\n\tpinky2R:string\n\tpinky3R:string\n\n\tthumb1R:string\n\tthumb2R:string\n\tthumb3R:string\n \n}\n\nexport const defaultBoneMap:BoneMap = {\n\tfaceMesh:\"face\",\n\t\n\thead: \"head\",\n\thips:\"hips\",\n\tneck:\"neck\",\n\ttorso:\"torso\",\n\n\tarmL:\"upper_armL\",\n\tforearmL:\"forearmL\",\n\n\tarmR:\"upper_armR\",\n\tforearmR:\"forearmR\",\n\n\tthighL:\"thighL\",\n\tshinL:\"shinL\",\n\tfootL:\"footL\",\n\n\tthighR:\"thighR\",\n\tshinR:\"shinR\",\n\tfootR:\"footR\",\n\t \n\t\n\thandL:\"handL\",\n\tindex1L:\"index1L\",\n\tindex2L:\"index2L\",\n\tindex3L:\"index3L\",\n\n\tmiddle1L:\"middle1L\",\n\tmiddle2L:\"middle2L\",\n\tmiddle3L:\"middle3L\",\n\n\tring1L:\"ring1L\",\n\tring2L:\"ring2L\",\n\tring3L:\"ring3L\",\n\n\tpinky1L:\"pinky1L\",\n\tpinky2L:\"pinky2L\",\n\tpinky3L:\"pinky3L\",\n\n\tthumb1L:\"thumb1L\",\n\tthumb2L:\"thumb2L\",\n\tthumb3L:\"thumb3L\",\n\n\thandR:\"handR\",\n\tindex1R:\"index1R\",\n\tindex2R:\"index2R\",\n\tindex3R:\"index3R\",\n\n\tmiddle1R:\"middle1R\",\n\tmiddle2R:\"middle2R\",\n\tmiddle3R:\"middle3R\",\n\n\tring1R:\"ring1R\",\n\tring2R:\"ring2R\",\n\tring3R:\"ring3R\",\n\n\tpinky1R:\"pinky1R\",\n\tpinky2R:\"pinky2R\",\n\tpinky3R:\"pinky3R\",\n\n\tthumb1R:\"thumb1R\",\n\tthumb2R:\"thumb2R\",\n\tthumb3R:\"thumb3R\",\n \n}","import {\n DrawingUtils,\n FilesetResolver,\n HandLandmarkerOptions,\n PoseLandmarker,\n} from \"@mediapipe/tasks-vision\";\nimport * as THREE from \"three/webgpu\";\nimport { loadPoseTracker } from \"./PoseTracker\";\nimport { loadHandTracker } from \"./HandTracker\"; \nimport { loadFaceTracker } from \"./FaceTracker\";\nimport { BoneMap, defaultBoneMap } from \"./BoneMapping\";\n\nexport type TrackerConfig = {\n /**\n * Use an image file. Useful to test a particular pose.\n */\n debugFrame?: string;\n\n /**\n * Scale of the video display\n */\n displayScale: number;\n\n /**\n * If the body pose should ignore the legs\n */\n ignoreLegs: boolean;\n\n /**\n * Use a video file instead of the webcam\n */\n debugVideo?: string;\n\n /**\n * Don't track the face\n */\n ignoreFace: boolean;\n\n /**\n * @see https://ai.google.dev/edge/mediapipe/solutions/vision/hand_landmarker/web_js#configuration_options\n */\n handsTrackerOptions: HandLandmarkerOptions | undefined;\n\n\tmodelPaths?: {\n\t\tvision?:string;\n\t\tpose?: string;\n\t\thand?: string;\n\t\tface?: string;\n\t}\n};\n\nexport interface BindingHandler {\n update: (delta: number) => void;\n}\n\n// Check if webcam access is supported.\nconst hasGetUserMedia = () => !!navigator.mediaDevices?.getUserMedia;\n\nexport async function setupTracker(config?: Partial<TrackerConfig>) {\n const $cfg = {\n debugFrame: undefined,\n displayScale: 1,\n ignoreLegs: false,\n debugVideo: undefined,\n ignoreFace: false,\n\t\tmodelPaths: {\n\t\t\tvision: \"https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@0.10.3/wasm\",\n\t\t\tpose: \"https://storage.googleapis.com/mediapipe-models/pose_landmarker/pose_landmarker_lite/float16/1/pose_landmarker_lite.task\",\n\t\t\thand: \"https://storage.googleapis.com/mediapipe-models/hand_landmarker/hand_landmarker/float16/1/hand_landmarker.task\",\n\t\t\tface: \"https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/1/face_landmarker.task\",\n\t\t},\n ...config,\n };\n let video: HTMLVideoElement | undefined;\n const vision = await FilesetResolver.forVisionTasks( $cfg.modelPaths.vision ?? \"/wasm\" );\n const poseTracker = await loadPoseTracker(vision, {\n ignoreLegs: $cfg.ignoreLegs,\n\t\tmodelPath: $cfg.modelPaths.pose!,\n });\n const handsTracker = await loadHandTracker(vision, {\n leftWrist: () => poseTracker.leftWristNormalizedPosition,\n rightWrist: () => poseTracker.rightWristNormalizedPosition,\n\t\tmodelPath: $cfg.modelPaths.hand!,\n ...config?.handsTrackerOptions,\n });\n const faceTracker = $cfg.ignoreFace\n ? undefined\n : await loadFaceTracker(vision, { modelPath: $cfg.modelPaths.face! });\n\n //#region setup Camera and Canvas...\n\tconst viewport = document.createElement(\"div\");\n\tviewport.style.position = \"absolute\";\n\tviewport.style.top = \"0px\";\n\tviewport.style.left = \"0px\"; \n\tviewport.style.zIndex = \"21\";\n\tviewport.classList.add(\"three-mediapipe-rig\")\n\tdocument.body.appendChild(viewport);\n\n const canvasElement = document.createElement(\"canvas\");\n const canvasCtx = canvasElement.getContext(\"2d\")!;\n const drawingUtils = new DrawingUtils(canvasCtx);\n\n canvasElement.style.zIndex = \"22\";\n canvasElement.style.position = \"absolute\";\n canvasElement.style.top = \"0px\";\n canvasElement.style.left = \"0px\";\n canvasElement.style.pointerEvents = \"none\";\n viewport.appendChild(canvasElement);\n\n function predict(source: TexImageSource) {\n canvasCtx.save();\n canvasCtx.clearRect(0, 0, canvasElement.width, canvasElement.height);\n poseTracker?.predict(source, drawingUtils);\n handsTracker?.left.predict(source, drawingUtils);\n handsTracker?.right.predict(source, drawingUtils);\n faceTracker?.predict(source, drawingUtils);\n canvasCtx.restore();\n }\n\n function initializeVideo() {\n video = document.createElement(\"video\");\n viewport.appendChild(video);\n\n let lastVideoTime = -1;\n\n video.style.zIndex = \"21\";\n video.style.position = \"absolute\";\n video.style.top = \"0px\";\n video.style.left = \"0px\";\n\n if ($cfg.debugVideo) {\n video.src = $cfg.debugVideo;\n video.controls = true;\n video.loop = true;\n video.muted = true;\n video.controls = true;\n video.play();\n }\n\n function predictWebcam() {\n if (lastVideoTime !== video!.currentTime) {\n predict(video!);\n lastVideoTime = video!.currentTime;\n }\n window.requestAnimationFrame(predictWebcam);\n }\n\n video.addEventListener(\"loadeddata\", () => {\n video!.width = video!.videoWidth * $cfg.displayScale;\n video!.height = video!.videoHeight * $cfg.displayScale;\n canvasElement.width = video!.videoWidth;\n canvasElement.height = video!.videoHeight;\n canvasElement.style.height = video!.height + \"px\";\n canvasElement.style.width = video!.width + \"px\";\n\n window.requestAnimationFrame(predictWebcam);\n });\n }\n\n if ($cfg.debugFrame) {\n //#region Debug Frame mode — use a static image\n const img = document.createElement(\"img\");\n img.src = $cfg.debugFrame;\n img.style.zIndex = \"21\";\n img.style.position = \"absolute\";\n img.style.top = \"0px\";\n img.style.left = \"0px\";\n document.body.appendChild(img);\n\n img.addEventListener(\"load\", () => {\n img.width = img.naturalWidth * $cfg.displayScale;\n img.height = img.naturalHeight * $cfg.displayScale;\n canvasElement.width = img.naturalWidth;\n canvasElement.height = img.naturalWidth;\n canvasElement.style.width = img.width + \"px\";\n canvasElement.style.height = img.height + \"px\";\n\n function predictFrame() {\n predict(img);\n }\n\n window.requestAnimationFrame(predictFrame);\n });\n //#endregion\n } else if( $cfg.debugVideo ) {\n //#region Video mode\n initializeVideo();\n //#endregion\n } \n\n return {\n poseTracker,\n handsTracker,\n faceTracker,\n video,\n\n\t\t/**\n\t\t * A div that contains the video and canvas used to display the landmarks stacked on top of each other.\n\t\t */\n\t\tdomElement: viewport,\n\n\t\t/**\n\t\t * Start the webcam feed. This must be initiated by a user triggered event ( a click on a button ) due to security reasons. \n\t\t */\n start: async () => {\n\t\t\tlet stopped = false;\n\n if (!hasGetUserMedia()) {\n throw new Error(\"Webcam not supported\");\n }\n\n if (!video) {\n initializeVideo();\n }\n\n let stream: Awaited<MediaStream> | undefined;\n\n\t\t\tfunction onTrackEnded(video: HTMLVideoElement): void {\n\t\t\t\tconsole.warn('Camera track ended, attempting recovery...');\n\t\t\t\tstopCamera(video);\n\t\t\t\tretryWithBackoff(video);\n\t\t\t}\n\n\t\t\tfunction stopCamera(video: HTMLVideoElement): void {\n\t\t\t\tstream?.getTracks().forEach(t => t.stop());\n\t\t\t\tstream = undefined;\n\t\t\t\tvideo.srcObject = null;\n\t\t\t}\n\n\t\t\tasync function retryWithBackoff(video: HTMLVideoElement, attempt = 0): Promise<void> {\n\t\t\t const MAX_ATTEMPTS = 5;\n\t\t\t const delay = Math.min(1000 * 2 ** attempt, 16000); // 1s, 2s, 4s, 8s, 16s\n\n\t\t\t if (attempt >= MAX_ATTEMPTS) { \n\t\t\t throw new Error('Camera recovery failed after max attempts');\n\t\t\t }\n\n\t\t\t await new Promise(res => setTimeout(res, delay)); \n\n\t\t\t if(stopped) return;\n\n\t\t\t try {\n\t\t\t await startCamera(video);\n\t\t\t console.log('Camera recovered successfully');\n\t\t\t } catch {\n\t\t\t retryWithBackoff(video, attempt + 1);\n\t\t\t }\n\t\t\t}\n\n\t\t\tasync function startCamera(video: HTMLVideoElement): Promise<void> {\n\t\t\t try {\n\t\t\t stream = await navigator.mediaDevices.getUserMedia({ video: true });\n\t\t\t video.srcObject = stream;\n\t\t\t await video.play();\n\n\t\t\t // Listen for track ending (camera disconnected / permission revoked)\n\t\t\t stream.getVideoTracks().forEach(track => {\n\t\t\t track.addEventListener('ended', () => onTrackEnded(video));\n\t\t\t });\n\n\t\t\t } catch (err) {\n\t\t\t handleCameraError(err, video);\n\t\t\t }\n\t\t\t}\n\n\t\t\tfunction handleCameraError(err: unknown, video: HTMLVideoElement): void {\n\t\t\t if (err instanceof DOMException) {\n\t\t\t switch (err.name) {\n\t\t\t case 'NotAllowedError':\n\t\t\t throw new Error('Permission denied — prompt user to allow camera');\n\t\t\t break;\n\t\t\t case 'NotFoundError':\n\t\t\t console.error('No camera found — retry when device is connected');\n\t\t\t retryWithBackoff(video); // device might be plugged in later\n\t\t\t break;\n\t\t\t case 'NotReadableError':\n\t\t\t console.error('Camera in use by another app');\n\t\t\t retryWithBackoff(video);\n\t\t\t break;\n\t\t\t default:\n\t\t\t console.error('Camera error:', err.message);\n\t\t\t retryWithBackoff(video);\n\t\t\t }\n\t\t\t }\n\t\t\t} \n\n await startCamera(video!);\n\n\t\t\treturn {\n\t\t\t\tstop:()=>{\n\t\t\t\t\tstopped = true;\n\t\t\t\t\tstopCamera(video!);\n\t\t\t\t}\n\t\t\t}\n },\n\n /**\n * Binds the bones of the rig to the landmarks provided by media pipe.\n * @param rig The rig that contains all the bones and skinned meshes of your character.\n\t\t * @param magging The bone mapping to use for the rig.\n */\n bind: ( rig: THREE.Object3D, magging?:BoneMap ) => {\n\n\t\t\tmagging = magging || defaultBoneMap;\n\n const bodyBindin = poseTracker.bind(rig, magging);\n const leftHandBinding = handsTracker.left.bind(rig, magging);\n const rightHandBinding = handsTracker.right.bind(rig, magging);\n let faceKeys: BindingHandler | undefined;\n const faceRig = faceTracker?.bind(rig);\n\n rig.traverse((child) => {\n if (\n child instanceof THREE.Mesh &&\n child.name.indexOf( magging.faceMesh ) === 0\n ) {\n child.frustumCulled = false;\n faceKeys = faceTracker?.bindShapeKeys(child);\n }\n });\n\n return {\n update: (delta: number) => {\n bodyBindin.update(delta);\n leftHandBinding.update(delta);\n rightHandBinding.update(delta);\n faceKeys?.update(delta);\n faceRig?.update(delta);\n },\n } as BindingHandler;\n },\n };\n}\n"],"names":["poleDir","Vector3","objectPosition","XAxis","XAxisNeg","YAxis","YAxisNeg","ZAxis","pole","lookDir","v","correction","Quaternion","worldQuat","lookAt","object","target","poleTarget","poleAxis","axis","currentPole","lookAxisDir","desiredPoleDir","cross","angle","THREE","A","B","Tracker","points","debugConnections","__publicField","key","Mark","landmarks","debugLandmarks","debugDrawer","point","mark","o","Ghost","_a","source","drawingUtils","delta","objects","normal","root","offset","objectLookAtGoal","polePosition","ghost","rig","name","speed","rootPosition","out","cleanBoneName","getBoneByName","bone","Bone","loadPoseTracker","vision","config","poseLandmarker","PoseLandmarker","PoseTracker","poseMarks","C","D","E","lookGoal","poleGoal","result","magging","map","v2","syncBone","from","to","sideAxis","hipsDir","sideHips","sideShoulders","sideHead","loadHandTracker","landmarker","HandLandmarker","isMyWrist","myWrist","otherWrist","handWrist","HandsTracker","handMarks","fingerKeys","v1","v3","v4","v5","v6","currSide","HALF_PI","DOWN","handLandmarker","side","hand","wrist","markToBone","palmNormal","parlmDir","palmSide","palmLookAt","polPosition","palmGhost","palmForward","sideGoal","negateSideGoal","i","myDir","bonePos","poleOffset","fingerGhost","addBind","boneName","markName","loadFaceTracker","cfg","faceLandmarker","FaceLandmarker","FaceTracker","faceMarks","frame","_b","_c","category","mesh","meshKeys","categoryName","score","factor","eyeL","EyeRig","eyeR","headBone","markEarL","markEarR","headcenter","headForward","headSideNormal","headPosition","poleLookAt","faceLookAt","sideName","blendshapes","lookLeft","lookRight","lookUp","lookDown","sideMovement","verticalMovement","defaultBoneMap","hasGetUserMedia","setupTracker","$cfg","video","FilesetResolver","poseTracker","handsTracker","faceTracker","viewport","canvasElement","canvasCtx","DrawingUtils","predict","initializeVideo","lastVideoTime","predictWebcam","img","predictFrame","stopped","stream","onTrackEnded","stopCamera","retryWithBackoff","t","attempt","delay","res","startCamera","track","err","handleCameraError","bodyBindin","leftHandBinding","rightHandBinding","faceKeys","faceRig","child"],"mappings":"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"}
@@ -14,9 +14,11 @@ export type BoneMap = {
14
14
  thighL: string;
15
15
  shinL: string;
16
16
  footL: string;
17
+ toesL: string;
17
18
  thighR: string;
18
19
  shinR: string;
19
20
  footR: string;
21
+ toesR: string;
20
22
  handL: string;
21
23
  index1L: string;
22
24
  index2L: string;
@@ -1 +1 @@
1
- {"version":3,"file":"BoneMapping.d.ts","sourceRoot":"","sources":["../../src/tracking/BoneMapping.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,OAAO,GAAG;IACrB,QAAQ,EAAC,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAC,MAAM,CAAA;IACX,IAAI,EAAC,MAAM,CAAA;IACX,KAAK,EAAC,MAAM,CAAA;IACZ,IAAI,EAAC,MAAM,CAAA;IACX,QAAQ,EAAC,MAAM,CAAA;IAEf,IAAI,EAAC,MAAM,CAAA;IACX,QAAQ,EAAC,MAAM,CAAA;IAEf,MAAM,EAAC,MAAM,CAAA;IACb,KAAK,EAAC,MAAM,CAAA;IACZ,KAAK,EAAC,MAAM,CAAA;IAEZ,MAAM,EAAC,MAAM,CAAA;IACb,KAAK,EAAC,MAAM,CAAA;IACZ,KAAK,EAAC,MAAM,CAAA;IAGZ,KAAK,EAAC,MAAM,CAAA;IACZ,OAAO,EAAC,MAAM,CAAA;IACd,OAAO,EAAC,MAAM,CAAA;IACd,OAAO,EAAC,MAAM,CAAA;IAEd,QAAQ,EAAC,MAAM,CAAA;IACf,QAAQ,EAAC,MAAM,CAAA;IACf,QAAQ,EAAC,MAAM,CAAA;IAEf,MAAM,EAAC,MAAM,CAAA;IACb,MAAM,EAAC,MAAM,CAAA;IACb,MAAM,EAAC,MAAM,CAAA;IAEb,OAAO,EAAC,MAAM,CAAA;IACd,OAAO,EAAC,MAAM,CAAA;IACd,OAAO,EAAC,MAAM,CAAA;IAEd,OAAO,EAAC,MAAM,CAAA;IACd,OAAO,EAAC,MAAM,CAAA;IACd,OAAO,EAAC,MAAM,CAAA;IAEd,KAAK,EAAC,MAAM,CAAA;IACZ,OAAO,EAAC,MAAM,CAAA;IACd,OAAO,EAAC,MAAM,CAAA;IACd,OAAO,EAAC,MAAM,CAAA;IAEd,QAAQ,EAAC,MAAM,CAAA;IACf,QAAQ,EAAC,MAAM,CAAA;IACf,QAAQ,EAAC,MAAM,CAAA;IAEf,MAAM,EAAC,MAAM,CAAA;IACb,MAAM,EAAC,MAAM,CAAA;IACb,MAAM,EAAC,MAAM,CAAA;IAEb,OAAO,EAAC,MAAM,CAAA;IACd,OAAO,EAAC,MAAM,CAAA;IACd,OAAO,EAAC,MAAM,CAAA;IAEd,OAAO,EAAC,MAAM,CAAA;IACd,OAAO,EAAC,MAAM,CAAA;IACd,OAAO,EAAC,MAAM,CAAA;CAEd,CAAA;AAED,eAAO,MAAM,cAAc,EAAC,OAiE3B,CAAA"}
1
+ {"version":3,"file":"BoneMapping.d.ts","sourceRoot":"","sources":["../../src/tracking/BoneMapping.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,OAAO,GAAG;IACrB,QAAQ,EAAC,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAC,MAAM,CAAA;IACX,IAAI,EAAC,MAAM,CAAA;IACX,KAAK,EAAC,MAAM,CAAA;IACZ,IAAI,EAAC,MAAM,CAAA;IACX,QAAQ,EAAC,MAAM,CAAA;IAEf,IAAI,EAAC,MAAM,CAAA;IACX,QAAQ,EAAC,MAAM,CAAA;IAEf,MAAM,EAAC,MAAM,CAAA;IACb,KAAK,EAAC,MAAM,CAAA;IACZ,KAAK,EAAC,MAAM,CAAA;IACZ,KAAK,EAAC,MAAM,CAAA;IAEZ,MAAM,EAAC,MAAM,CAAA;IACb,KAAK,EAAC,MAAM,CAAA;IACZ,KAAK,EAAC,MAAM,CAAA;IACZ,KAAK,EAAC,MAAM,CAAA;IAGZ,KAAK,EAAC,MAAM,CAAA;IACZ,OAAO,EAAC,MAAM,CAAA;IACd,OAAO,EAAC,MAAM,CAAA;IACd,OAAO,EAAC,MAAM,CAAA;IAEd,QAAQ,EAAC,MAAM,CAAA;IACf,QAAQ,EAAC,MAAM,CAAA;IACf,QAAQ,EAAC,MAAM,CAAA;IAEf,MAAM,EAAC,MAAM,CAAA;IACb,MAAM,EAAC,MAAM,CAAA;IACb,MAAM,EAAC,MAAM,CAAA;IAEb,OAAO,EAAC,MAAM,CAAA;IACd,OAAO,EAAC,MAAM,CAAA;IACd,OAAO,EAAC,MAAM,CAAA;IAEd,OAAO,EAAC,MAAM,CAAA;IACd,OAAO,EAAC,MAAM,CAAA;IACd,OAAO,EAAC,MAAM,CAAA;IAEd,KAAK,EAAC,MAAM,CAAA;IACZ,OAAO,EAAC,MAAM,CAAA;IACd,OAAO,EAAC,MAAM,CAAA;IACd,OAAO,EAAC,MAAM,CAAA;IAEd,QAAQ,EAAC,MAAM,CAAA;IACf,QAAQ,EAAC,MAAM,CAAA;IACf,QAAQ,EAAC,MAAM,CAAA;IAEf,MAAM,EAAC,MAAM,CAAA;IACb,MAAM,EAAC,MAAM,CAAA;IACb,MAAM,EAAC,MAAM,CAAA;IAEb,OAAO,EAAC,MAAM,CAAA;IACd,OAAO,EAAC,MAAM,CAAA;IACd,OAAO,EAAC,MAAM,CAAA;IAEd,OAAO,EAAC,MAAM,CAAA;IACd,OAAO,EAAC,MAAM,CAAA;IACd,OAAO,EAAC,MAAM,CAAA;CAEd,CAAA;AAED,eAAO,MAAM,cAAc,EAAC,OAiE3B,CAAA"}
@@ -13,11 +13,15 @@ declare const poseMarks: {
13
13
  neck: number[];
14
14
  leftLeg: number;
15
15
  leftKnee: number;
16
+ leftFoot: number;
17
+ leftToes: number;
16
18
  leftArm: number;
17
19
  leftElbow: number;
18
20
  leftWrist: number;
19
21
  rightLeg: number;
20
22
  rightKnee: number;
23
+ rightFoot: number;
24
+ rightToes: number;
21
25
  rightArm: number;
22
26
  rightElbow: number;
23
27
  rightWrist: number;
@@ -1 +1 @@
1
- {"version":3,"file":"PoseTracker.d.ts","sourceRoot":"","sources":["../../src/tracking/PoseTracker.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACjB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAEtC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAExC,wBAAsB,eAAe,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,EAAC,OAAO,CAAC,iBAAiB,CAAC,wBAapF;AAED;;;;GAIG;AACH,QAAA,MAAM,SAAS;;;;;;;;;;;;;;;;;;CAkBZ,CAAE;AAcL,KAAK,iBAAiB,GAAG;IACxB,UAAU,EAAC,OAAO,CAAA;IAClB,SAAS,EAAC,MAAM,CAAA;CAChB,CAAA;AAED;;GAEG;AACH,cAAM,WAAY,SAAQ,OAAO,CAAC,OAAO,SAAS,CAAC;IActC,OAAO,CAAC,QAAQ,CAAC,cAAc;IAAiB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;IAbpF,OAAO,CAAC,4BAA4B,CAAqB;IACzD,OAAO,CAAC,6BAA6B,CAAqB;IAE1D;;OAEG;IACH,IAAI,2BAA2B,uBAAgD;IAE/E;;OAEG;IACH,IAAI,4BAA4B,uBAAiD;gBAEpD,cAAc,EAAC,cAAc,EAAmB,MAAM,CAAC,EAAC,OAAO,CAAC,iBAAiB,CAAC,YAAA;IAStG,OAAO,CAAE,MAAM,EAAC,cAAc,EAAE,YAAY,EAAC,YAAY;IA8BlE,IAAI,CAAE,GAAG,EAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAC,OAAO;wBAiDxB,MAAM;;CAsBvB"}
1
+ {"version":3,"file":"PoseTracker.d.ts","sourceRoot":"","sources":["../../src/tracking/PoseTracker.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACjB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAEtC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAExC,wBAAsB,eAAe,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,EAAC,OAAO,CAAC,iBAAiB,CAAC,wBAapF;AAED;;;;GAIG;AACH,QAAA,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;CAsBZ,CAAE;AAcL,KAAK,iBAAiB,GAAG;IACxB,UAAU,EAAC,OAAO,CAAA;IAClB,SAAS,EAAC,MAAM,CAAA;CAChB,CAAA;AAED;;GAEG;AACH,cAAM,WAAY,SAAQ,OAAO,CAAC,OAAO,SAAS,CAAC;IActC,OAAO,CAAC,QAAQ,CAAC,cAAc;IAAiB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;IAbpF,OAAO,CAAC,4BAA4B,CAAqB;IACzD,OAAO,CAAC,6BAA6B,CAAqB;IAE1D;;OAEG;IACH,IAAI,2BAA2B,uBAAgD;IAE/E;;OAEG;IACH,IAAI,4BAA4B,uBAAiD;gBAEpD,cAAc,EAAC,cAAc,EAAmB,MAAM,CAAC,EAAC,OAAO,CAAC,iBAAiB,CAAC,YAAA;IAStG,OAAO,CAAE,MAAM,EAAC,cAAc,EAAE,YAAY,EAAC,YAAY;IA8BlE,IAAI,CAAE,GAAG,EAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAC,OAAO;wBAuDxB,MAAM;;CA0BvB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "three-mediapipe-rig",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "type": "module",
5
5
  "description": "Easy setup of a skeletal rig that responds to the motion tracker provided by google's mediapipe webwam feed.",
6
6
  "repository": {