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