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 +5 -1
- package/dist/three-mediapipe-rig.js +160 -154
- package/dist/three-mediapipe-rig.js.map +1 -1
- package/dist/tracking/BoneMapping.d.ts +2 -0
- package/dist/tracking/BoneMapping.d.ts.map +1 -1
- package/dist/tracking/PoseTracker.d.ts +4 -0
- package/dist/tracking/PoseTracker.d.ts.map +1 -1
- package/package.json +1 -1
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
|
|
6
|
-
import { Vector3 as
|
|
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
|
|
9
|
-
new
|
|
10
|
-
const
|
|
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" ?
|
|
14
|
-
l.getWorldPosition(D), l.getWorldQuaternion(O),
|
|
15
|
-
const i =
|
|
16
|
-
|
|
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
|
|
19
|
-
new
|
|
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
|
|
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],
|
|
35
|
-
|
|
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(
|
|
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,
|
|
67
|
-
this.marks[
|
|
68
|
-
const a = _.sub(
|
|
69
|
-
s.getWorldPosition(
|
|
70
|
-
const
|
|
71
|
-
A(f,
|
|
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
|
|
78
|
+
class yt extends h.Mesh {
|
|
79
79
|
constructor() {
|
|
80
|
-
super(new
|
|
81
|
-
y(this, "_worldPosition", new
|
|
82
|
-
this.add(new
|
|
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
|
|
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
|
|
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
|
|
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
|
-
},
|
|
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(
|
|
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:
|
|
172
|
-
neck:
|
|
173
|
-
leftArm:
|
|
174
|
-
leftElbow:
|
|
175
|
-
leftWrist:
|
|
176
|
-
rightArm:
|
|
177
|
-
rightElbow:
|
|
178
|
-
rightWrist:
|
|
179
|
-
head:
|
|
180
|
-
torso:
|
|
181
|
-
leftLeg:
|
|
182
|
-
leftKnee:
|
|
183
|
-
|
|
184
|
-
|
|
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
|
|
188
|
-
if (!
|
|
189
|
-
const P = this.marks[k].getWorldPosition(i).sub(this.marks[f].getWorldPosition(
|
|
190
|
-
E(
|
|
191
|
-
const
|
|
192
|
-
A(
|
|
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: (
|
|
196
|
-
const
|
|
197
|
-
|
|
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
|
|
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,
|
|
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
|
-
},
|
|
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
|
-
},
|
|
248
|
-
new
|
|
249
|
-
new
|
|
250
|
-
const Q = new
|
|
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
|
|
267
|
-
if (this.isMyWrist(
|
|
268
|
-
this.updateLandmarks(s.worldLandmarks[i]), e.drawConnectors(
|
|
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(
|
|
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 =
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
).normalize(),
|
|
290
|
-
if (!(
|
|
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(
|
|
293
|
-
A(
|
|
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,
|
|
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,
|
|
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 =
|
|
306
|
+
const k = n[a[f]];
|
|
301
307
|
if (!k) continue;
|
|
302
|
-
const d =
|
|
303
|
-
|
|
304
|
-
const
|
|
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
|
-
|
|
307
|
-
d.add(
|
|
308
|
-
P.add(
|
|
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
|
-
|
|
312
|
-
d.add(
|
|
313
|
-
P.add(
|
|
317
|
+
x,
|
|
318
|
+
d.add(p).applyMatrix4(e.matrixWorld),
|
|
319
|
+
P.add(p).applyMatrix4(e.matrixWorld),
|
|
314
320
|
this.lookAtPoleAxis
|
|
315
|
-
)),
|
|
321
|
+
)), x.rotateX(Y), x.lerp(k, t);
|
|
316
322
|
}
|
|
317
323
|
}
|
|
318
324
|
bind(t, e) {
|
|
319
|
-
const s = {}, i = (
|
|
320
|
-
const a =
|
|
321
|
-
a && (s[
|
|
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: (
|
|
325
|
-
this.syncHandBones(
|
|
330
|
+
update: (r) => {
|
|
331
|
+
this.syncHandBones(r, s, t);
|
|
326
332
|
}
|
|
327
333
|
};
|
|
328
334
|
}
|
|
329
335
|
}
|
|
330
|
-
async function
|
|
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
|
|
356
|
-
new
|
|
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,
|
|
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 = (
|
|
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((
|
|
380
|
-
const { categoryName:
|
|
381
|
-
if (!(e != null && e.hasOwnProperty(
|
|
382
|
-
this.smoothed[
|
|
383
|
-
const
|
|
384
|
-
this.smoothed[
|
|
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 =
|
|
396
|
+
const e = new J(t, "L"), s = new J(t, "R"), i = w(t, "head");
|
|
391
397
|
return {
|
|
392
|
-
update: (
|
|
393
|
-
if (e.update(
|
|
394
|
-
const
|
|
395
|
-
A(i,
|
|
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,
|
|
416
|
-
console.log("EYE: ",
|
|
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
|
|
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
|
-
},
|
|
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
|
-
}),
|
|
496
|
-
|
|
497
|
-
const a = document.createElement("canvas"),
|
|
498
|
-
a.style.zIndex = "22", a.style.position = "absolute", a.style.top = "0px", a.style.left = "0px", a.style.pointerEvents = "none",
|
|
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
|
-
|
|
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"),
|
|
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
|
|
507
|
-
d !== t.currentTime && (f(t), d = t.currentTime), window.requestAnimationFrame(
|
|
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(
|
|
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
|
|
523
|
+
function p() {
|
|
518
524
|
f(d);
|
|
519
525
|
}
|
|
520
|
-
window.requestAnimationFrame(
|
|
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:
|
|
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:
|
|
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 (!
|
|
543
|
+
if (!gt())
|
|
538
544
|
throw new Error("Webcam not supported");
|
|
539
545
|
t || k();
|
|
540
|
-
let
|
|
541
|
-
function P(
|
|
542
|
-
console.warn("Camera track ended, attempting recovery..."),
|
|
546
|
+
let p;
|
|
547
|
+
function P(u) {
|
|
548
|
+
console.warn("Camera track ended, attempting recovery..."), x(u), R(u);
|
|
543
549
|
}
|
|
544
|
-
function
|
|
545
|
-
|
|
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(
|
|
548
|
-
const st = Math.min(1e3 * 2 **
|
|
549
|
-
if (
|
|
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(
|
|
559
|
+
await W(u), console.log("Camera recovered successfully");
|
|
554
560
|
} catch {
|
|
555
|
-
R(
|
|
561
|
+
R(u, b + 1);
|
|
556
562
|
}
|
|
557
563
|
}
|
|
558
|
-
async function W(
|
|
564
|
+
async function W(u) {
|
|
559
565
|
try {
|
|
560
|
-
|
|
561
|
-
|
|
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 (
|
|
564
|
-
M(
|
|
569
|
+
} catch (b) {
|
|
570
|
+
M(b, u);
|
|
565
571
|
}
|
|
566
572
|
}
|
|
567
|
-
function M(
|
|
568
|
-
if (
|
|
569
|
-
switch (
|
|
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(
|
|
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(
|
|
582
|
+
console.error("Camera in use by another app"), R(b);
|
|
577
583
|
break;
|
|
578
584
|
default:
|
|
579
|
-
console.error("Camera error:",
|
|
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,
|
|
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,
|
|
594
|
-
|
|
595
|
-
const P = s.bind(d,
|
|
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 =
|
|
598
|
-
return d.traverse((
|
|
599
|
-
|
|
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: (
|
|
602
|
-
P.update(
|
|
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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"}
|
|
@@ -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
|
|
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