three-mediapipe-rig 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
import { PoseLandmarker as
|
|
5
|
-
import * as
|
|
6
|
-
import { Vector3 as
|
|
7
|
-
import * as
|
|
8
|
-
import { Bone as
|
|
9
|
-
import { uniform as
|
|
10
|
-
import { GLTFExporter as
|
|
11
|
-
const
|
|
12
|
-
new
|
|
13
|
-
const
|
|
1
|
+
var Re = Object.defineProperty;
|
|
2
|
+
var Pe = (c, s, e) => s in c ? Re(c, s, { enumerable: !0, configurable: !0, writable: !0, value: e }) : c[s] = e;
|
|
3
|
+
var P = (c, s, e) => Pe(c, typeof s != "symbol" ? s + "" : s, e);
|
|
4
|
+
import { PoseLandmarker as fe, HandLandmarker as U, FaceLandmarker as G, FilesetResolver as ve, DrawingUtils as ge } from "@mediapipe/tasks-vision";
|
|
5
|
+
import * as u from "three/webgpu";
|
|
6
|
+
import { Vector3 as b, Quaternion as we, BufferAttribute as Ee, VideoTexture as We, SRGBColorSpace as Fe, MeshPhysicalNodeMaterial as Ae } from "three/webgpu";
|
|
7
|
+
import * as T from "three";
|
|
8
|
+
import { Bone as Se } from "three";
|
|
9
|
+
import { uniform as _, attribute as Me, instancedArray as Ve, varying as Ne, vec3 as Oe, texture as Te, vec2 as _e } from "three/tsl";
|
|
10
|
+
import { GLTFExporter as Ce } from "three/examples/jsm/Addons.js";
|
|
11
|
+
const z = new b(), Y = new b(), De = new b(1, 0, 0), ze = new b(-1, 0, 0), Be = new b(0, 1, 0), Ie = new b(0, -1, 0), Z = new b(0, 0, 1);
|
|
12
|
+
new b(0, 0, -1);
|
|
13
|
+
const J = new b(), Ue = new b(), Ge = new b(), ee = new we(), B = new we();
|
|
14
14
|
function M(c, s, e, t = "+x") {
|
|
15
15
|
c.lookAt(s);
|
|
16
|
-
const o = t == "+x" ?
|
|
17
|
-
c.getWorldPosition(
|
|
18
|
-
const n =
|
|
19
|
-
|
|
16
|
+
const o = t == "+x" ? De : t == "-x" ? ze : t == "+y" ? Be : Ie;
|
|
17
|
+
c.getWorldPosition(Y), c.getWorldQuaternion(B), z.subVectors(e, Y).normalize(), J.copy(o).applyQuaternion(B);
|
|
18
|
+
const n = J, a = Ue.copy(Z).applyQuaternion(B), i = z.clone().addScaledVector(a, -z.dot(a)).normalize(), r = Ge.crossVectors(n, i), l = Math.atan2(r.dot(a), n.dot(i));
|
|
19
|
+
ee.setFromAxisAngle(Z, l), c.quaternion.multiply(ee);
|
|
20
20
|
}
|
|
21
|
-
const
|
|
22
|
-
new
|
|
23
|
-
class
|
|
21
|
+
const C = new u.Vector3(), V = new u.Vector3(), I = new u.Vector3();
|
|
22
|
+
new u.Vector3();
|
|
23
|
+
class H {
|
|
24
24
|
constructor(s, e) {
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
P(this, "objectGhost");
|
|
26
|
+
P(this, "root");
|
|
27
27
|
/**
|
|
28
28
|
* per landmark index, it points to it's object3D equivalent.
|
|
29
29
|
*/
|
|
30
|
-
|
|
31
|
-
this.points = s, this.debugConnections = e, this.root = new
|
|
30
|
+
P(this, "marks", {});
|
|
31
|
+
this.points = s, this.debugConnections = e, this.root = new u.Object3D(), this.objectGhost = /* @__PURE__ */ new Map();
|
|
32
32
|
for (let t in this.points)
|
|
33
|
-
this.marks[t] = new
|
|
33
|
+
this.marks[t] = new He(), this.root.add(this.marks[t]);
|
|
34
34
|
}
|
|
35
35
|
updateLandmarks(s, e, t) {
|
|
36
36
|
for (let o in this.points) {
|
|
37
|
-
const n = this.points[o],
|
|
38
|
-
|
|
37
|
+
const n = this.points[o], a = this.marks[o];
|
|
38
|
+
a && (n instanceof Array ? (C.copy(s[n[0]]), a.position.copy(s[n[1]]).sub(C).divideScalar(2).add(s[n[0]]), n.length == 4 && (C.subVectors(
|
|
39
39
|
s[n[3]],
|
|
40
40
|
s[n[2]]
|
|
41
|
-
).divideScalar(2).add(s[n[2]]).sub(
|
|
41
|
+
).divideScalar(2).add(s[n[2]]).sub(a.position).divideScalar(2), a.position.add(C))) : a.position.copy(s[n]));
|
|
42
42
|
}
|
|
43
43
|
t && e && t.drawConnectors(
|
|
44
44
|
e,
|
|
@@ -51,7 +51,7 @@ class I {
|
|
|
51
51
|
getGhost(s) {
|
|
52
52
|
var e;
|
|
53
53
|
if (!this.objectGhost.has(s)) {
|
|
54
|
-
const t = new
|
|
54
|
+
const t = new $e();
|
|
55
55
|
t.position.copy(s.position), t.quaternion.copy(s.quaternion), (e = s.parent) == null || e.add(t), this.objectGhost.set(s, t);
|
|
56
56
|
}
|
|
57
57
|
return this.objectGhost.get(s);
|
|
@@ -66,47 +66,47 @@ class I {
|
|
|
66
66
|
this.marks[s].position.set(1, 2, 3);
|
|
67
67
|
}
|
|
68
68
|
syncObjects(s, e, t) {
|
|
69
|
-
for (const [o, n,
|
|
70
|
-
this.marks[
|
|
71
|
-
const
|
|
72
|
-
o.getWorldPosition(
|
|
73
|
-
const l =
|
|
74
|
-
M(f, l,
|
|
69
|
+
for (const [o, n, a, i] of s) {
|
|
70
|
+
this.marks[a].getWorldPosition(I), this.marks[n].getWorldPosition(V);
|
|
71
|
+
const r = I.sub(V);
|
|
72
|
+
o.getWorldPosition(V), V.add(r);
|
|
73
|
+
const l = V, h = o.getWorldPosition(I).sub(t), f = this.getGhost(o);
|
|
74
|
+
M(f, l, h, i), f.rotateX(Math.PI / 2), o.position.lerp(f.position, e * 4), o.quaternion.slerp(f.quaternion, e * 4);
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
getBone(s, e) {
|
|
78
78
|
return s.getObjectByName(e.replace(/[\.\:]/g, ""));
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
|
-
class
|
|
81
|
+
class He extends u.Mesh {
|
|
82
82
|
constructor() {
|
|
83
|
-
super(new
|
|
84
|
-
|
|
85
|
-
this.add(new
|
|
83
|
+
super(new u.SphereGeometry(0.01, 3, 3), new u.MeshStandardMaterial({ color: 16711680, wireframe: !0 }));
|
|
84
|
+
P(this, "_worldPosition", new u.Vector3());
|
|
85
|
+
this.add(new u.AxesHelper(1e-3));
|
|
86
86
|
}
|
|
87
87
|
get worldPosition() {
|
|
88
88
|
return this.getWorldPosition(this._worldPosition), this._worldPosition;
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
|
-
class
|
|
91
|
+
class $e extends u.Object3D {
|
|
92
92
|
lerp(s, e, t = 8) {
|
|
93
93
|
s.position.lerp(this.position, e * t), s.quaternion.slerp(this.quaternion, e * t);
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
|
-
function
|
|
96
|
+
function S(c, s, e) {
|
|
97
97
|
return e.worldToLocal(s.getWorldPosition(c)), c;
|
|
98
98
|
}
|
|
99
|
-
function
|
|
99
|
+
function qe(c) {
|
|
100
100
|
return c.replace(/[\.\:]/g, "");
|
|
101
101
|
}
|
|
102
|
-
function
|
|
102
|
+
function g(c, s) {
|
|
103
103
|
let e;
|
|
104
|
-
return s =
|
|
105
|
-
t.name.indexOf(s) === 0 && t instanceof
|
|
104
|
+
return s = qe(s), c.traverse((t) => {
|
|
105
|
+
t.name.indexOf(s) === 0 && t instanceof Se && (e = t);
|
|
106
106
|
}), e || console.log("Bone not found: ", s, c.name), e;
|
|
107
107
|
}
|
|
108
|
-
async function
|
|
109
|
-
const e = await
|
|
108
|
+
async function je(c, s) {
|
|
109
|
+
const e = await fe.createFromOptions(c, {
|
|
110
110
|
baseOptions: {
|
|
111
111
|
modelAssetPath: (s == null ? void 0 : s.modelPath) ?? "pose_landmarker_lite.task",
|
|
112
112
|
//modelAssetPath: `https://storage.googleapis.com/mediapipe-models/pose_landmarker/pose_landmarker_lite/float16/1/pose_landmarker_lite.task`,
|
|
@@ -116,9 +116,9 @@ async function Ce(c, s) {
|
|
|
116
116
|
runningMode: "VIDEO",
|
|
117
117
|
numPoses: 1
|
|
118
118
|
});
|
|
119
|
-
return new
|
|
119
|
+
return new Je(e, s);
|
|
120
120
|
}
|
|
121
|
-
const
|
|
121
|
+
const Ke = {
|
|
122
122
|
hips: [24, 23],
|
|
123
123
|
neck: [12, 11],
|
|
124
124
|
leftLeg: 23,
|
|
@@ -140,12 +140,12 @@ const ze = {
|
|
|
140
140
|
torso: [24, 23, 12, 11],
|
|
141
141
|
leftEar: 7,
|
|
142
142
|
rightEar: 8
|
|
143
|
-
},
|
|
144
|
-
class
|
|
143
|
+
}, Xe = new u.Vector3(), te = new u.Vector3(), Qe = new u.Vector3(), Ye = new u.Vector3(), Ze = new u.Vector3(), oe = new u.Vector3(), se = new u.Vector3();
|
|
144
|
+
class Je extends H {
|
|
145
145
|
constructor(e, t) {
|
|
146
|
-
super(
|
|
147
|
-
|
|
148
|
-
|
|
146
|
+
super(Ke, fe.POSE_CONNECTIONS);
|
|
147
|
+
P(this, "_leftWristNormalizedPosition");
|
|
148
|
+
P(this, "_rightWristNormalizedPosition");
|
|
149
149
|
this.poseLandmarker = e, this.config = t, this.root.scale.y *= -2, this.root.scale.z *= -2, this.root.scale.x *= 2;
|
|
150
150
|
}
|
|
151
151
|
/**
|
|
@@ -174,44 +174,44 @@ class $e extends I {
|
|
|
174
174
|
// this.syncObjects(objects, delta, torsoNormal);
|
|
175
175
|
// }
|
|
176
176
|
bind(e, t) {
|
|
177
|
-
var
|
|
177
|
+
var r;
|
|
178
178
|
const o = {
|
|
179
|
-
hips:
|
|
180
|
-
neck:
|
|
181
|
-
leftArm:
|
|
182
|
-
leftElbow:
|
|
183
|
-
leftWrist:
|
|
184
|
-
rightArm:
|
|
185
|
-
rightElbow:
|
|
186
|
-
rightWrist:
|
|
187
|
-
head:
|
|
188
|
-
torso:
|
|
189
|
-
leftLeg:
|
|
190
|
-
leftKnee:
|
|
191
|
-
leftFoot:
|
|
192
|
-
rightLeg:
|
|
193
|
-
rightKnee:
|
|
194
|
-
rightFoot:
|
|
179
|
+
hips: g(e, t.hips),
|
|
180
|
+
neck: g(e, t.neck),
|
|
181
|
+
leftArm: g(e, t.armL),
|
|
182
|
+
leftElbow: g(e, t.forearmL),
|
|
183
|
+
leftWrist: g(e, t.handL),
|
|
184
|
+
rightArm: g(e, t.armR),
|
|
185
|
+
rightElbow: g(e, t.forearmR),
|
|
186
|
+
rightWrist: g(e, t.handR),
|
|
187
|
+
head: g(e, t.head),
|
|
188
|
+
torso: g(e, t.torso),
|
|
189
|
+
leftLeg: g(e, t.thighL),
|
|
190
|
+
leftKnee: g(e, t.shinL),
|
|
191
|
+
leftFoot: g(e, t.footL),
|
|
192
|
+
rightLeg: g(e, t.thighR),
|
|
193
|
+
rightKnee: g(e, t.shinR),
|
|
194
|
+
rightFoot: g(e, t.footR)
|
|
195
195
|
};
|
|
196
|
-
(
|
|
197
|
-
const n = new
|
|
198
|
-
if (!
|
|
199
|
-
const
|
|
200
|
-
|
|
201
|
-
const
|
|
202
|
-
M(
|
|
196
|
+
(r = this.config) != null && r.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);
|
|
197
|
+
const n = new u.Vector3(), a = new u.Vector3(), i = (l, h, f, x, d, m) => {
|
|
198
|
+
if (!h) return;
|
|
199
|
+
const y = this.marks[x].getWorldPosition(n).sub(this.marks[f].getWorldPosition(a)).normalize();
|
|
200
|
+
S(oe, h, e).add(y).applyMatrix4(e.matrixWorld), S(se, h, e).add(d).applyMatrix4(e.matrixWorld);
|
|
201
|
+
const p = this.getGhost(h);
|
|
202
|
+
M(p, oe, se, m), p.rotateX(Math.PI / 2), p.lerp(h, l);
|
|
203
203
|
};
|
|
204
204
|
return {
|
|
205
205
|
update: (l) => {
|
|
206
|
-
const
|
|
207
|
-
i(l, o.hips, "hips", "torso",
|
|
206
|
+
const h = this.marks.leftLeg.getWorldPosition(Xe).sub(this.marks.rightLeg.getWorldPosition(te)).normalize(), f = this.marks.leftArm.getWorldPosition(te).sub(this.marks.rightArm.getWorldPosition(Qe)).normalize(), x = this.marks.leftEar.getWorldPosition(Ye).sub(this.marks.rightEar.getWorldPosition(Ze)).normalize();
|
|
207
|
+
i(l, o.hips, "hips", "torso", h, "+x"), i(l, o.torso, "torso", "neck", f, "+x"), i(l, o.neck, "neck", "head", x, "+x"), i(l, o.head, "neck", "head", x, "+x"), i(l, o.leftArm, "leftArm", "leftElbow", f, "-x"), i(l, o.leftElbow, "leftElbow", "leftWrist", f, "-x"), i(l, o.leftLeg, "leftLeg", "leftKnee", h, "+x"), i(l, o.leftKnee, "leftKnee", "leftFoot", h, "+x"), i(l, o.leftFoot, "leftFoot", "leftToes", h, "+x"), i(l, o.rightArm, "rightArm", "rightElbow", f, "-x"), i(l, o.rightElbow, "rightElbow", "rightWrist", f, "-x"), i(l, o.rightLeg, "rightLeg", "rightKnee", h, "+x"), i(l, o.rightKnee, "rightKnee", "rightFoot", h, "+x"), i(l, o.rightFoot, "rightFoot", "rightToes", h, "+x");
|
|
208
208
|
}
|
|
209
209
|
};
|
|
210
210
|
}
|
|
211
211
|
}
|
|
212
|
-
const
|
|
213
|
-
async function
|
|
214
|
-
const e = await
|
|
212
|
+
const ne = new u.Vector2(), ie = new u.Vector2();
|
|
213
|
+
async function et(c, s) {
|
|
214
|
+
const e = await U.createFromOptions(c, {
|
|
215
215
|
baseOptions: {
|
|
216
216
|
modelAssetPath: s.modelPath ?? "hand_landmarker.task",
|
|
217
217
|
//modelAssetPath: `https://storage.googleapis.com/mediapipe-models/hand_landmarker/hand_landmarker/float16/1/hand_landmarker.task`,
|
|
@@ -219,20 +219,20 @@ async function He(c, s) {
|
|
|
219
219
|
},
|
|
220
220
|
runningMode: "VIDEO",
|
|
221
221
|
numHands: 2
|
|
222
|
-
}), t = (o, n,
|
|
222
|
+
}), t = (o, n, a) => {
|
|
223
223
|
try {
|
|
224
|
-
|
|
224
|
+
ne.copy(o()), ie.copy(n());
|
|
225
225
|
} catch (i) {
|
|
226
226
|
return console.warn("No pose data... will just be optimitic and say yes to everything.", i), !0;
|
|
227
227
|
}
|
|
228
|
-
return
|
|
228
|
+
return ne.distanceTo(a) < ie.distanceTo(a);
|
|
229
229
|
};
|
|
230
230
|
return {
|
|
231
|
-
left: new
|
|
232
|
-
right: new
|
|
231
|
+
left: new me(e, "Left", t.bind(null, s.leftWrist, s.rightWrist), s.drawLandmarks),
|
|
232
|
+
right: new me(e, "Right", t.bind(null, s.rightWrist, s.leftWrist), s.drawLandmarks)
|
|
233
233
|
};
|
|
234
234
|
}
|
|
235
|
-
const
|
|
235
|
+
const tt = {
|
|
236
236
|
wrist: 0,
|
|
237
237
|
palm: [9, 13],
|
|
238
238
|
thumb1: 1,
|
|
@@ -261,32 +261,32 @@ const je = {
|
|
|
261
261
|
middle: ["middle1", "middle2", "middle3", "middle4"],
|
|
262
262
|
ring: ["ring1", "ring2", "ring3", "ring4"],
|
|
263
263
|
pinky: ["pinky1", "pinky2", "pinky3", "pinky4"]
|
|
264
|
-
},
|
|
265
|
-
new
|
|
266
|
-
new
|
|
267
|
-
new
|
|
268
|
-
const
|
|
269
|
-
class
|
|
264
|
+
}, ot = new u.Vector3(), re = new u.Vector3(), ae = new u.Vector3(), de = new u.Vector3(), ce = new u.Vector3(), le = new u.Vector3();
|
|
265
|
+
new u.Vector3();
|
|
266
|
+
new u.Vector3();
|
|
267
|
+
new u.Vector3();
|
|
268
|
+
const he = new u.Vector3(), pe = Math.PI / 2, st = new u.Vector3(0, -1, 0);
|
|
269
|
+
class me extends H {
|
|
270
270
|
constructor(e, t, o, n = !0) {
|
|
271
|
-
super(
|
|
272
|
-
|
|
273
|
-
|
|
271
|
+
super(tt, U.HAND_CONNECTIONS);
|
|
272
|
+
P(this, "sign");
|
|
273
|
+
P(this, "isLeft");
|
|
274
274
|
/**
|
|
275
275
|
* the axis used to look at the pole
|
|
276
276
|
*/
|
|
277
|
-
|
|
277
|
+
P(this, "lookAtPoleAxis");
|
|
278
278
|
this.handLandmarker = e, this.side = t, this.isMyWrist = o, this.drawLandmarks = n, this.sign = this.side == "Left" ? -1 : 1, this.isLeft = this.side == "Left", this.lookAtPoleAxis = this.sign < 0 ? "+x" : "-x", this.root.scale.setScalar(7), this.root.scale.y *= -1, this.root.scale.z *= -1;
|
|
279
279
|
}
|
|
280
280
|
predict(e, t) {
|
|
281
281
|
const o = this.handLandmarker.detectForVideo(e, performance.now());
|
|
282
282
|
if (o.landmarks.length)
|
|
283
283
|
for (let n = 0; n < o.landmarks.length; n++) {
|
|
284
|
-
const
|
|
284
|
+
const a = o.landmarks[n], i = a[this.points.wrist];
|
|
285
285
|
if (this.isMyWrist(i)) {
|
|
286
|
-
this.updateLandmarks(o.worldLandmarks[n]), this.drawLandmarks && (t.drawConnectors(
|
|
286
|
+
this.updateLandmarks(o.worldLandmarks[n]), this.drawLandmarks && (t.drawConnectors(a, U.HAND_CONNECTIONS, {
|
|
287
287
|
color: this.side == "Left" ? "#00FF00" : "#0000FF",
|
|
288
288
|
lineWidth: 4
|
|
289
|
-
}), t.drawLandmarks(
|
|
289
|
+
}), t.drawLandmarks(a, { color: this.side == "Left" ? "#00FF00" : "#0000FF", lineWidth: 3, radius: 1 }));
|
|
290
290
|
break;
|
|
291
291
|
}
|
|
292
292
|
}
|
|
@@ -301,56 +301,56 @@ class re extends I {
|
|
|
301
301
|
* @see https://ai.google.dev/edge/mediapipe/solutions/vision/hand_landmarker
|
|
302
302
|
*/
|
|
303
303
|
syncHandBones(e, t, o) {
|
|
304
|
-
const n =
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
).normalize(),
|
|
308
|
-
if (!(
|
|
304
|
+
const n = ot.crossVectors(
|
|
305
|
+
re.copy(this.marks.index1.worldPosition).sub(this.marks.wrist.worldPosition),
|
|
306
|
+
ae.copy(this.marks.pinky1.worldPosition).sub(this.marks.wrist.worldPosition)
|
|
307
|
+
).normalize(), a = re.copy(this.marks.palm.worldPosition).sub(this.marks.wrist.worldPosition).normalize(), i = ae.copy(this.marks.pinky1.worldPosition).sub(this.marks.index1.worldPosition).normalize();
|
|
308
|
+
if (!(a.dot(st) > 0.8)) {
|
|
309
309
|
if (t.wrist) {
|
|
310
|
-
const
|
|
311
|
-
M(
|
|
310
|
+
const r = S(de, t.wrist, o).add(a).applyMatrix4(o.matrixWorld), l = S(ce, t.wrist, o).sub(i).applyMatrix4(o.matrixWorld), h = this.getGhost(t.wrist);
|
|
311
|
+
M(h, r, l, "-y"), h.rotateX(pe), h.lerp(t.wrist, e);
|
|
312
312
|
}
|
|
313
|
-
this.syncFinger(e, o, n,
|
|
313
|
+
this.syncFinger(e, o, n, a, i, t, N.index, "middle1"), this.syncFinger(e, o, n, a, i, t, N.middle, "ring1"), this.syncFinger(e, o, n, a, i, t, N.ring, "pinky1"), this.syncFinger(e, o, n, a, i, t, N.pinky, "ring1", !0), this.syncFinger(e, o, n, a, i, t, N.thumb, "index1");
|
|
314
314
|
}
|
|
315
315
|
}
|
|
316
|
-
syncFinger(e, t, o, n,
|
|
317
|
-
for (let f = 0; f <
|
|
318
|
-
const
|
|
319
|
-
if (!
|
|
320
|
-
const d = this.getGhost(
|
|
316
|
+
syncFinger(e, t, o, n, a, i, r, l, h = !1) {
|
|
317
|
+
for (let f = 0; f < r.length - 1; f++) {
|
|
318
|
+
const x = i[r[f]];
|
|
319
|
+
if (!x) continue;
|
|
320
|
+
const d = this.getGhost(x), m = de.copy(this.marks[r[f + 1]].worldPosition).sub(this.marks[r[f]].worldPosition).normalize(), y = S(ce, x, t);
|
|
321
321
|
if (f == 0) {
|
|
322
|
-
const
|
|
323
|
-
|
|
322
|
+
const p = le.copy(this.marks[l].worldPosition).sub(this.marks[r[0]].worldPosition).normalize();
|
|
323
|
+
h && p.negate(), he.copy(p), M(
|
|
324
324
|
d,
|
|
325
|
-
|
|
326
|
-
|
|
325
|
+
m.add(y).applyMatrix4(t.matrixWorld),
|
|
326
|
+
p.add(y).applyMatrix4(t.matrixWorld),
|
|
327
327
|
this.lookAtPoleAxis
|
|
328
328
|
);
|
|
329
329
|
} else
|
|
330
330
|
M(
|
|
331
331
|
d,
|
|
332
|
-
|
|
333
|
-
|
|
332
|
+
m.add(y).applyMatrix4(t.matrixWorld),
|
|
333
|
+
le.copy(he).add(y).applyMatrix4(t.matrixWorld),
|
|
334
334
|
this.lookAtPoleAxis
|
|
335
335
|
);
|
|
336
|
-
d.rotateX(
|
|
336
|
+
d.rotateX(pe), d.lerp(x, e);
|
|
337
337
|
}
|
|
338
338
|
}
|
|
339
339
|
bind(e, t) {
|
|
340
|
-
const o = {}, n = (
|
|
341
|
-
const
|
|
342
|
-
if (
|
|
343
|
-
return o[i] =
|
|
340
|
+
const o = {}, n = (a, i) => {
|
|
341
|
+
const r = g(e, a);
|
|
342
|
+
if (r)
|
|
343
|
+
return o[i] = r, i;
|
|
344
344
|
};
|
|
345
345
|
return n(this.isLeft ? t.handL : t.handR, "wrist"), n(this.isLeft ? t.index1L : t.index1R, "index1"), n(this.isLeft ? t.index2L : t.index2R, "index2"), n(this.isLeft ? t.index3L : t.index3R, "index3"), n(this.isLeft ? t.middle1L : t.middle1R, "middle1"), n(this.isLeft ? t.middle2L : t.middle2R, "middle2"), n(this.isLeft ? t.middle3L : t.middle3R, "middle3"), n(this.isLeft ? t.ring1L : t.ring1R, "ring1"), n(this.isLeft ? t.ring2L : t.ring2R, "ring2"), n(this.isLeft ? t.ring3L : t.ring3R, "ring3"), n(this.isLeft ? t.pinky1L : t.pinky1R, "pinky1"), n(this.isLeft ? t.pinky2L : t.pinky2R, "pinky2"), n(this.isLeft ? t.pinky3L : t.pinky3R, "pinky3"), n(this.isLeft ? t.thumb1L : t.thumb1R, "thumb1"), n(this.isLeft ? t.thumb2L : t.thumb2R, "thumb2"), n(this.isLeft ? t.thumb3L : t.thumb3R, "thumb3"), {
|
|
346
|
-
update: (
|
|
347
|
-
this.syncHandBones(
|
|
346
|
+
update: (a) => {
|
|
347
|
+
this.syncHandBones(a, o, e);
|
|
348
348
|
}
|
|
349
349
|
};
|
|
350
350
|
}
|
|
351
351
|
}
|
|
352
|
-
async function
|
|
353
|
-
const e = await
|
|
352
|
+
async function nt(c, s) {
|
|
353
|
+
const e = await G.createFromOptions(c, {
|
|
354
354
|
baseOptions: {
|
|
355
355
|
modelAssetPath: (s == null ? void 0 : s.modelPath) ?? "face_landmarker.task",
|
|
356
356
|
delegate: "GPU"
|
|
@@ -359,9 +359,9 @@ async function Xe(c, s) {
|
|
|
359
359
|
runningMode: "VIDEO",
|
|
360
360
|
numFaces: 1
|
|
361
361
|
});
|
|
362
|
-
return new
|
|
362
|
+
return new lt(e, { ...s });
|
|
363
363
|
}
|
|
364
|
-
const
|
|
364
|
+
const it = {
|
|
365
365
|
eyeL: 473,
|
|
366
366
|
eyeR: 468,
|
|
367
367
|
eyeStartL: 463,
|
|
@@ -374,24 +374,24 @@ const Qe = {
|
|
|
374
374
|
noseBone: 6,
|
|
375
375
|
chin: 152,
|
|
376
376
|
forehead: 10
|
|
377
|
-
},
|
|
378
|
-
new
|
|
379
|
-
class
|
|
377
|
+
}, rt = new b(), at = new b(), ye = new b(), dt = new b(), ct = new b();
|
|
378
|
+
new b();
|
|
379
|
+
class lt extends H {
|
|
380
380
|
constructor(e, t) {
|
|
381
|
-
super(
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
381
|
+
super(it, G.FACE_LANDMARKS_TESSELATION);
|
|
382
|
+
P(this, "blendshapeCategories");
|
|
383
|
+
P(this, "blendshapeMap", /* @__PURE__ */ new Map());
|
|
384
|
+
P(this, "smoothed", {});
|
|
385
|
+
P(this, "smoothing", 3e-4);
|
|
386
386
|
// lower = smoother but more lag, higher = more responsive
|
|
387
|
-
|
|
387
|
+
P(this, "_faceLandmarks", []);
|
|
388
388
|
this.faceLandmarker = e, this.cfg = t, this.root.scale.y *= -1, this.root.scale.z *= -1, this.root.scale.multiplyScalar(3);
|
|
389
389
|
}
|
|
390
390
|
predict(e, t) {
|
|
391
|
-
var n,
|
|
391
|
+
var n, a, i;
|
|
392
392
|
const o = this.faceLandmarker.detectForVideo(e, performance.now());
|
|
393
|
-
o.faceLandmarks[0] && (this.cfg.drawLandmarks && (t.drawConnectors(o.faceLandmarks[0],
|
|
394
|
-
this.blendshapeMap.set(
|
|
393
|
+
o.faceLandmarks[0] && (this.cfg.drawLandmarks && (t.drawConnectors(o.faceLandmarks[0], G.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._faceLandmarks = o.faceLandmarks[0], this.blendshapeCategories = (a = (n = o.faceBlendshapes) == null ? void 0 : n[0]) == null ? void 0 : a.categories, (i = this.blendshapeCategories) == null || i.forEach((r) => {
|
|
394
|
+
this.blendshapeMap.set(r.categoryName, r.score);
|
|
395
395
|
});
|
|
396
396
|
}
|
|
397
397
|
get lastKnownLandmarks() {
|
|
@@ -402,23 +402,23 @@ class tt extends I {
|
|
|
402
402
|
return {
|
|
403
403
|
update: (o) => {
|
|
404
404
|
var n;
|
|
405
|
-
(n = this.blendshapeCategories) == null || n.forEach((
|
|
406
|
-
const { categoryName: i, score:
|
|
405
|
+
(n = this.blendshapeCategories) == null || n.forEach((a) => {
|
|
406
|
+
const { categoryName: i, score: r } = a;
|
|
407
407
|
if (!(t != null && t.hasOwnProperty(i))) return;
|
|
408
|
-
this.smoothed[i] === void 0 && (this.smoothed[i] =
|
|
408
|
+
this.smoothed[i] === void 0 && (this.smoothed[i] = r);
|
|
409
409
|
const l = 1 - Math.pow(this.smoothing, o);
|
|
410
|
-
this.smoothed[i] += (
|
|
410
|
+
this.smoothed[i] += (r - this.smoothed[i]) * l, e.morphTargetInfluences[t[i]] = this.smoothed[i];
|
|
411
411
|
});
|
|
412
412
|
}
|
|
413
413
|
};
|
|
414
414
|
}
|
|
415
415
|
bind(e) {
|
|
416
|
-
const t = new
|
|
416
|
+
const t = new ue(e, "L"), o = new ue(e, "R"), n = g(e, "head");
|
|
417
417
|
return {
|
|
418
|
-
update: (
|
|
419
|
-
if (t.update(
|
|
420
|
-
const i =
|
|
421
|
-
M(n,
|
|
418
|
+
update: (a) => {
|
|
419
|
+
if (t.update(a, this.blendshapeMap), o.update(a, this.blendshapeMap), !n) return;
|
|
420
|
+
const i = rt.copy(this.marks.earL.worldPosition), r = at.copy(this.marks.earR.worldPosition), l = ye.subVectors(i, r).multiplyScalar(0.5).add(r), h = dt.subVectors(this.marks.noseTip.worldPosition, l), f = i.sub(r), x = S(ct, n, e), d = f.add(x).applyMatrix4(e.matrixWorld), m = h.add(x).applyMatrix4(e.matrixWorld);
|
|
421
|
+
M(n, m, d, "+x");
|
|
422
422
|
}
|
|
423
423
|
};
|
|
424
424
|
}
|
|
@@ -429,61 +429,70 @@ class tt extends I {
|
|
|
429
429
|
* @param mesh basically either the original or a clone of the canonical_face_model
|
|
430
430
|
*/
|
|
431
431
|
bindGeometry(e, t) {
|
|
432
|
-
const o = new
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
432
|
+
const o = new b(), n = new b(), a = new b();
|
|
433
|
+
new b();
|
|
434
|
+
const i = e.geometry, r = i.attributes.position, l = [], h = /* @__PURE__ */ new Map(), f = [];
|
|
435
|
+
for (let F = 0; F < r.count; F++) {
|
|
436
|
+
const v = `${r.getX(F).toFixed(6)},${r.getY(F).toFixed(6)},${r.getZ(F).toFixed(6)}`;
|
|
437
|
+
h.has(v) || (h.set(v, l.length), l.push(F)), f.push(h.get(v));
|
|
436
438
|
}
|
|
437
|
-
const
|
|
438
|
-
|
|
439
|
-
const
|
|
440
|
-
let
|
|
439
|
+
const x = _(new b(0.5, 0.5, 0.5));
|
|
440
|
+
i.setAttribute("landmarkIndex", new Ee(new Uint16Array(f), 1));
|
|
441
|
+
const d = Me("landmarkIndex", "uint"), m = Ve(468, "vec3"), y = Ne(m.element(d)).xy;
|
|
442
|
+
let p;
|
|
443
|
+
const R = 116, k = 346, E = a.subVectors(
|
|
444
|
+
new b(r.getX(R), r.getY(R), r.getZ(R)),
|
|
445
|
+
new b(r.getX(k), r.getY(k), r.getZ(k))
|
|
446
|
+
).lengthSq(), L = _(E), w = _(1), A = _(1);
|
|
441
447
|
return {
|
|
442
|
-
update: (
|
|
443
|
-
var
|
|
444
|
-
if (!
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
const
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
448
|
+
update: (F) => {
|
|
449
|
+
var O, j;
|
|
450
|
+
if (!p) {
|
|
451
|
+
const W = (j = (O = this.cfg) == null ? void 0 : O.videoElementRef) == null ? void 0 : j.call(O);
|
|
452
|
+
if (!W || !W.videoWidth || !W.videoHeight) return;
|
|
453
|
+
p = W;
|
|
454
|
+
const K = new We(p);
|
|
455
|
+
K.colorSpace = Fe;
|
|
456
|
+
const xe = p.videoWidth / p.videoHeight, X = m.element(d).sub(x).xzy.mul(Oe(1, -1, 1 / xe)).mul(A), Q = Te(K, _e(y.x, y.y.oneMinus()));
|
|
457
|
+
t ? t(X, Q) : e.material = new Ae({
|
|
458
|
+
positionNode: X,
|
|
459
|
+
colorNode: Q,
|
|
452
460
|
roughness: 0.93
|
|
453
461
|
});
|
|
454
462
|
}
|
|
455
|
-
const
|
|
456
|
-
if (!
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
+
const v = this.lastKnownLandmarks;
|
|
464
|
+
if (!(v != null && v.length)) return;
|
|
465
|
+
w.value = a.subVectors(v[k], v[R]).lengthSq(), w.needsUpdate = !0;
|
|
466
|
+
const D = m.value.array;
|
|
467
|
+
for (let W = 0; W < v.length; W++)
|
|
468
|
+
D[W * 3] = v[W].x, D[W * 3 + 1] = v[W].y, D[W * 3 + 2] = v[W].z;
|
|
469
|
+
m.value.needsUpdate = !0;
|
|
470
|
+
const ke = v[234], $ = v[93], be = v[454], q = v[323];
|
|
471
|
+
o.copy(ke).sub($).divideScalar(2).add($), n.copy(be).sub(q).divideScalar(2).add(q), x.value.subVectors(n, o).divideScalar(2).add(o), x.needsUpdate = !0, A.value = Math.sqrt(L.value / w.value), A.needsUpdate = !0;
|
|
463
472
|
}
|
|
464
473
|
};
|
|
465
474
|
}
|
|
466
475
|
}
|
|
467
|
-
class
|
|
476
|
+
class ue {
|
|
468
477
|
constructor(s, e) {
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
478
|
+
P(this, "eyeBone");
|
|
479
|
+
P(this, "eyeLookOut");
|
|
480
|
+
P(this, "eyeLookIn");
|
|
481
|
+
P(this, "eyeLookUp");
|
|
482
|
+
P(this, "eyeLookDown");
|
|
483
|
+
P(this, "sign", 1);
|
|
475
484
|
this.rig = s, this.side = e, this.eyeBone = s.getObjectByName(`eye${e}`);
|
|
476
485
|
const t = e == "L" ? "Left" : "Right";
|
|
477
486
|
this.eyeLookOut = `eyeLookOut${t}`, this.eyeLookIn = `eyeLookIn${t}`, this.eyeLookUp = `eyeLookUp${t}`, this.eyeLookDown = `eyeLookDown${t}`, this.sign = e == "L" ? -1 : 1;
|
|
478
487
|
}
|
|
479
488
|
update(s, e) {
|
|
480
489
|
if (!this.eyeBone) return;
|
|
481
|
-
|
|
482
|
-
const t = e.get(this.eyeLookOut) ?? 0, o = e.get(this.eyeLookIn) ?? 0, n = e.get(this.eyeLookUp) ?? 0,
|
|
483
|
-
this.eyeBone.rotation.y = i * this.sign / 2, this.eyeBone.rotation.x =
|
|
490
|
+
S(ye, this.eyeBone, this.rig);
|
|
491
|
+
const t = e.get(this.eyeLookOut) ?? 0, o = e.get(this.eyeLookIn) ?? 0, n = e.get(this.eyeLookUp) ?? 0, a = e.get(this.eyeLookDown) ?? 0, i = o - t, r = a - n;
|
|
492
|
+
this.eyeBone.rotation.y = i * this.sign / 2, this.eyeBone.rotation.x = r / 2;
|
|
484
493
|
}
|
|
485
494
|
}
|
|
486
|
-
const
|
|
495
|
+
const Le = {
|
|
487
496
|
faceMesh: "face",
|
|
488
497
|
head: "head",
|
|
489
498
|
hips: "hips",
|
|
@@ -531,7 +540,7 @@ const he = {
|
|
|
531
540
|
thumb1R: "thumb1R",
|
|
532
541
|
thumb2R: "thumb2R",
|
|
533
542
|
thumb3R: "thumb3R"
|
|
534
|
-
},
|
|
543
|
+
}, ht = [
|
|
535
544
|
"eyeBlinkLeft",
|
|
536
545
|
"eyeBlinkRight",
|
|
537
546
|
"eyeLookDownLeft",
|
|
@@ -585,93 +594,93 @@ const he = {
|
|
|
585
594
|
"mouthUpperUpRight",
|
|
586
595
|
"tongueOut"
|
|
587
596
|
];
|
|
588
|
-
function
|
|
597
|
+
function pt(c, s, e = 30) {
|
|
589
598
|
const t = [], o = c.getObjectByName(
|
|
590
599
|
s.faceMesh
|
|
591
600
|
), n = /* @__PURE__ */ new Set();
|
|
592
601
|
if (o != null && o.morphTargetDictionary)
|
|
593
|
-
for (const
|
|
594
|
-
|
|
595
|
-
const
|
|
596
|
-
c.traverse((
|
|
597
|
-
if (
|
|
598
|
-
const
|
|
599
|
-
|
|
600
|
-
ref:
|
|
601
|
-
name:
|
|
602
|
-
normalizedName:
|
|
602
|
+
for (const y in o.morphTargetDictionary)
|
|
603
|
+
ht.includes(y) && n.add(y);
|
|
604
|
+
const a = Object.keys(s);
|
|
605
|
+
c.traverse((y) => {
|
|
606
|
+
if (y instanceof T.Bone) {
|
|
607
|
+
const p = a.find((R) => y.name.indexOf(s[R]) === 0);
|
|
608
|
+
p && t.push({
|
|
609
|
+
ref: y,
|
|
610
|
+
name: y.name,
|
|
611
|
+
normalizedName: p
|
|
603
612
|
});
|
|
604
613
|
}
|
|
605
614
|
});
|
|
606
|
-
const i = [],
|
|
607
|
-
let
|
|
608
|
-
function
|
|
609
|
-
|
|
615
|
+
const i = [], r = /* @__PURE__ */ new Map(), l = /* @__PURE__ */ new Map();
|
|
616
|
+
let h = !1, f = 0;
|
|
617
|
+
function x() {
|
|
618
|
+
r.clear(), l.clear(), i.length = 0, f = performance.now() / 1e3, h = !0;
|
|
610
619
|
}
|
|
611
620
|
function d() {
|
|
612
|
-
if (!
|
|
613
|
-
const
|
|
614
|
-
i.push(
|
|
615
|
-
for (const
|
|
616
|
-
|
|
617
|
-
const
|
|
618
|
-
|
|
621
|
+
if (!h) return;
|
|
622
|
+
const y = performance.now() / 1e3 - f;
|
|
623
|
+
i.push(y);
|
|
624
|
+
for (const p of t) {
|
|
625
|
+
r.has(p.name) || r.set(p.name, []);
|
|
626
|
+
const R = r.get(p.name), k = p.ref.quaternion;
|
|
627
|
+
R.push(k.x, k.y, k.z, k.w);
|
|
619
628
|
}
|
|
620
|
-
for (const
|
|
621
|
-
l.has(
|
|
622
|
-
const
|
|
623
|
-
|
|
629
|
+
for (const p of n) {
|
|
630
|
+
l.has(p) || l.set(p, []);
|
|
631
|
+
const R = l.get(p), k = o.morphTargetDictionary[p], E = o.morphTargetInfluences[k];
|
|
632
|
+
R.push(E);
|
|
624
633
|
}
|
|
625
634
|
}
|
|
626
|
-
function
|
|
627
|
-
|
|
628
|
-
const
|
|
629
|
-
for (const [
|
|
630
|
-
|
|
631
|
-
new
|
|
632
|
-
`${
|
|
635
|
+
function m(y = "RecordedClip") {
|
|
636
|
+
h = !1;
|
|
637
|
+
const p = [];
|
|
638
|
+
for (const [k, E] of r)
|
|
639
|
+
p.push(
|
|
640
|
+
new T.QuaternionKeyframeTrack(
|
|
641
|
+
`${k}.quaternion`,
|
|
633
642
|
i,
|
|
634
643
|
E
|
|
635
644
|
)
|
|
636
645
|
);
|
|
637
|
-
for (const [
|
|
638
|
-
|
|
639
|
-
new
|
|
640
|
-
`${
|
|
646
|
+
for (const [k, E] of l)
|
|
647
|
+
p.push(
|
|
648
|
+
new T.NumberKeyframeTrack(
|
|
649
|
+
`${Le.faceMesh}.morphTargetInfluences[${k}]`,
|
|
641
650
|
i,
|
|
642
651
|
E
|
|
643
652
|
)
|
|
644
653
|
);
|
|
645
|
-
const
|
|
654
|
+
const R = new T.AnimationClip(y, -1, p);
|
|
646
655
|
return {
|
|
647
|
-
clip:
|
|
656
|
+
clip: R,
|
|
648
657
|
saveToFile: () => {
|
|
649
|
-
new
|
|
658
|
+
new Ce().parse(
|
|
650
659
|
c,
|
|
651
660
|
(E) => {
|
|
652
|
-
const
|
|
661
|
+
const L = new Blob([E], {
|
|
653
662
|
type: "model/gltf-binary"
|
|
654
|
-
}),
|
|
655
|
-
|
|
663
|
+
}), w = URL.createObjectURL(L), A = document.createElement("a");
|
|
664
|
+
A.href = w, A.download = y + ".glb", A.click();
|
|
656
665
|
},
|
|
657
666
|
(E) => {
|
|
658
667
|
console.error(E);
|
|
659
668
|
},
|
|
660
669
|
{
|
|
661
670
|
binary: !0,
|
|
662
|
-
animations: [
|
|
671
|
+
animations: [R]
|
|
663
672
|
}
|
|
664
673
|
);
|
|
665
674
|
}
|
|
666
675
|
};
|
|
667
676
|
}
|
|
668
|
-
return { start:
|
|
677
|
+
return { start: x, captureFrame: d, stop: m, isRecording: () => h };
|
|
669
678
|
}
|
|
670
|
-
const
|
|
679
|
+
const mt = () => {
|
|
671
680
|
var c;
|
|
672
681
|
return !!((c = navigator.mediaDevices) != null && c.getUserMedia);
|
|
673
682
|
};
|
|
674
|
-
async function
|
|
683
|
+
async function bt(c) {
|
|
675
684
|
const s = {
|
|
676
685
|
debugFrame: void 0,
|
|
677
686
|
displayScale: 1,
|
|
@@ -689,50 +698,50 @@ async function ht(c) {
|
|
|
689
698
|
...c
|
|
690
699
|
};
|
|
691
700
|
let e;
|
|
692
|
-
const t = await
|
|
701
|
+
const t = await ve.forVisionTasks(s.modelPaths.vision ?? "/wasm"), o = s.onlyFace ? void 0 : await je(t, {
|
|
693
702
|
ignoreLegs: s.ignoreLegs,
|
|
694
703
|
modelPath: s.modelPaths.pose,
|
|
695
704
|
drawLandmarks: s.drawLandmarksOverlay
|
|
696
|
-
}), n = s.onlyFace ? void 0 : await
|
|
705
|
+
}), n = s.onlyFace ? void 0 : await et(t, {
|
|
697
706
|
leftWrist: () => o.leftWristNormalizedPosition,
|
|
698
707
|
rightWrist: () => o.rightWristNormalizedPosition,
|
|
699
708
|
modelPath: s.modelPaths.hand,
|
|
700
709
|
drawLandmarks: s.drawLandmarksOverlay,
|
|
701
710
|
...c == null ? void 0 : c.handsTrackerOptions
|
|
702
|
-
}),
|
|
711
|
+
}), a = s.ignoreFace ? void 0 : await nt(t, { modelPath: s.modelPaths.face, videoElementRef: () => e, drawLandmarks: s.drawLandmarksOverlay }), i = document.createElement("div");
|
|
703
712
|
i.style.position = "absolute", i.style.top = "0px", i.style.left = "0px", i.style.zIndex = "21", i.classList.add("three-mediapipe-rig"), document.body.appendChild(i);
|
|
704
|
-
const
|
|
705
|
-
|
|
713
|
+
const r = document.createElement("canvas"), l = r.getContext("2d"), h = new ge(l);
|
|
714
|
+
r.style.zIndex = "22", r.style.position = "absolute", r.style.top = "0px", r.style.left = "0px", r.style.pointerEvents = "none", i.appendChild(r);
|
|
706
715
|
function f(d) {
|
|
707
|
-
l.save(), l.clearRect(0, 0,
|
|
716
|
+
l.save(), l.clearRect(0, 0, r.width, r.height), o == null || o.predict(d, h), n == null || n.left.predict(d, h), n == null || n.right.predict(d, h), a == null || a.predict(d, h), l.restore();
|
|
708
717
|
}
|
|
709
|
-
function
|
|
718
|
+
function x() {
|
|
710
719
|
e = document.createElement("video"), i.appendChild(e);
|
|
711
720
|
let d = -1;
|
|
712
721
|
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());
|
|
713
|
-
function
|
|
714
|
-
d !== e.currentTime && (f(e), d = e.currentTime), window.requestAnimationFrame(
|
|
722
|
+
function m() {
|
|
723
|
+
d !== e.currentTime && (f(e), d = e.currentTime), window.requestAnimationFrame(m);
|
|
715
724
|
}
|
|
716
725
|
e.addEventListener("loadeddata", () => {
|
|
717
|
-
e.width = e.videoWidth * s.displayScale, e.height = e.videoHeight * s.displayScale,
|
|
726
|
+
e.width = e.videoWidth * s.displayScale, e.height = e.videoHeight * s.displayScale, r.width = e.videoWidth, r.height = e.videoHeight, r.style.height = e.height + "px", r.style.width = e.width + "px", window.requestAnimationFrame(m);
|
|
718
727
|
});
|
|
719
728
|
}
|
|
720
729
|
if (s.debugFrame) {
|
|
721
730
|
const d = document.createElement("img");
|
|
722
731
|
d.src = s.debugFrame, d.style.zIndex = "21", d.style.position = "absolute", d.style.top = "0px", d.style.left = "0px", i.appendChild(d), d.addEventListener("load", () => {
|
|
723
|
-
d.width = d.naturalWidth * s.displayScale, d.height = d.naturalHeight * s.displayScale,
|
|
724
|
-
function
|
|
732
|
+
d.width = d.naturalWidth * s.displayScale, d.height = d.naturalHeight * s.displayScale, r.width = d.naturalWidth, r.height = d.naturalWidth, r.style.width = d.width + "px", r.style.height = d.height + "px";
|
|
733
|
+
function m() {
|
|
725
734
|
f(d);
|
|
726
735
|
}
|
|
727
|
-
window.requestAnimationFrame(
|
|
736
|
+
window.requestAnimationFrame(m);
|
|
728
737
|
});
|
|
729
|
-
} else s.debugVideo &&
|
|
738
|
+
} else s.debugVideo && x();
|
|
730
739
|
return {
|
|
731
740
|
poseTracker: o,
|
|
732
741
|
handsTracker: n,
|
|
733
|
-
faceTracker:
|
|
742
|
+
faceTracker: a,
|
|
734
743
|
video: e,
|
|
735
|
-
canvas:
|
|
744
|
+
canvas: r,
|
|
736
745
|
/**
|
|
737
746
|
* A div that contains the video and canvas used to display the landmarks stacked on top of each other.
|
|
738
747
|
*/
|
|
@@ -742,54 +751,54 @@ async function ht(c) {
|
|
|
742
751
|
*/
|
|
743
752
|
start: async () => {
|
|
744
753
|
let d = !1;
|
|
745
|
-
if (!
|
|
754
|
+
if (!mt())
|
|
746
755
|
throw new Error("Webcam not supported");
|
|
747
|
-
e ||
|
|
748
|
-
let
|
|
749
|
-
function
|
|
750
|
-
console.warn("Camera track ended, attempting recovery..."),
|
|
756
|
+
e || x();
|
|
757
|
+
let m;
|
|
758
|
+
function y(L) {
|
|
759
|
+
console.warn("Camera track ended, attempting recovery..."), p(L), R(L);
|
|
751
760
|
}
|
|
752
|
-
function
|
|
753
|
-
|
|
761
|
+
function p(L) {
|
|
762
|
+
m == null || m.getTracks().forEach((w) => w.stop()), m = void 0, L.srcObject = null;
|
|
754
763
|
}
|
|
755
|
-
async function
|
|
756
|
-
const
|
|
757
|
-
if (
|
|
764
|
+
async function R(L, w = 0) {
|
|
765
|
+
const F = Math.min(1e3 * 2 ** w, 16e3);
|
|
766
|
+
if (w >= 5)
|
|
758
767
|
throw new Error("Camera recovery failed after max attempts");
|
|
759
|
-
if (await new Promise((
|
|
768
|
+
if (await new Promise((v) => setTimeout(v, F)), !d)
|
|
760
769
|
try {
|
|
761
|
-
await
|
|
770
|
+
await k(L), console.log("Camera recovered successfully");
|
|
762
771
|
} catch {
|
|
763
|
-
|
|
772
|
+
R(L, w + 1);
|
|
764
773
|
}
|
|
765
774
|
}
|
|
766
|
-
async function
|
|
775
|
+
async function k(L) {
|
|
767
776
|
try {
|
|
768
|
-
|
|
769
|
-
|
|
777
|
+
m = await navigator.mediaDevices.getUserMedia({ video: !0 }), L.srcObject = m, await L.play(), m.getVideoTracks().forEach((w) => {
|
|
778
|
+
w.addEventListener("ended", () => y(L));
|
|
770
779
|
});
|
|
771
|
-
} catch (
|
|
772
|
-
E(
|
|
780
|
+
} catch (w) {
|
|
781
|
+
E(w, L);
|
|
773
782
|
}
|
|
774
783
|
}
|
|
775
|
-
function E(
|
|
776
|
-
if (
|
|
777
|
-
switch (
|
|
784
|
+
function E(L, w) {
|
|
785
|
+
if (L instanceof DOMException)
|
|
786
|
+
switch (L.name) {
|
|
778
787
|
case "NotAllowedError":
|
|
779
788
|
throw new Error("Permission denied — prompt user to allow camera");
|
|
780
789
|
case "NotFoundError":
|
|
781
|
-
console.error("No camera found — retry when device is connected"),
|
|
790
|
+
console.error("No camera found — retry when device is connected"), R(w);
|
|
782
791
|
break;
|
|
783
792
|
case "NotReadableError":
|
|
784
|
-
console.error("Camera in use by another app"),
|
|
793
|
+
console.error("Camera in use by another app"), R(w);
|
|
785
794
|
break;
|
|
786
795
|
default:
|
|
787
|
-
console.error("Camera error:",
|
|
796
|
+
console.error("Camera error:", L.message), R(w);
|
|
788
797
|
}
|
|
789
798
|
}
|
|
790
|
-
return await
|
|
799
|
+
return await k(e), {
|
|
791
800
|
stop: () => {
|
|
792
|
-
d = !0,
|
|
801
|
+
d = !0, p(e);
|
|
793
802
|
}
|
|
794
803
|
};
|
|
795
804
|
},
|
|
@@ -798,33 +807,33 @@ async function ht(c) {
|
|
|
798
807
|
* @param rig The rig that contains all the bones and skinned meshes of your character.
|
|
799
808
|
* @param magging The bone mapping to use for the rig.
|
|
800
809
|
*/
|
|
801
|
-
bind: (d,
|
|
802
|
-
if (
|
|
810
|
+
bind: (d, m) => {
|
|
811
|
+
if (m = m || Le, !o) throw new Error("Pose tracker not initialized");
|
|
803
812
|
if (!n) throw new Error("Hands tracker not initialized");
|
|
804
|
-
if (!
|
|
805
|
-
const
|
|
806
|
-
let
|
|
807
|
-
const E =
|
|
808
|
-
d.traverse((
|
|
809
|
-
|
|
813
|
+
if (!a) throw new Error("Face tracker not initialized");
|
|
814
|
+
const y = o.bind(d, m), p = n.left.bind(d, m), R = n.right.bind(d, m);
|
|
815
|
+
let k;
|
|
816
|
+
const E = a == null ? void 0 : a.bind(d);
|
|
817
|
+
d.traverse((w) => {
|
|
818
|
+
w instanceof u.Mesh && w.name.indexOf(m.faceMesh) === 0 && (w.frustumCulled = !1, k = a == null ? void 0 : a.bindShapeKeys(w));
|
|
810
819
|
});
|
|
811
|
-
const
|
|
820
|
+
const L = pt(d, m);
|
|
812
821
|
return {
|
|
813
822
|
/**
|
|
814
823
|
* Will save the tracked movement of the rig to an animation clip.
|
|
815
824
|
* Only the bones moved by the bone mapping will be recorded.
|
|
816
825
|
*/
|
|
817
|
-
startRecording:
|
|
818
|
-
stopRecording:
|
|
819
|
-
isRecording: () =>
|
|
820
|
-
update: (
|
|
821
|
-
|
|
826
|
+
startRecording: L.start,
|
|
827
|
+
stopRecording: L.stop,
|
|
828
|
+
isRecording: () => L.isRecording(),
|
|
829
|
+
update: (w) => {
|
|
830
|
+
y.update(w), p.update(w), R.update(w), k == null || k.update(w), E == null || E.update(w), L.isRecording() && L.captureFrame();
|
|
822
831
|
}
|
|
823
832
|
};
|
|
824
833
|
}
|
|
825
834
|
};
|
|
826
835
|
}
|
|
827
836
|
export {
|
|
828
|
-
|
|
837
|
+
bt as setupTracker
|
|
829
838
|
};
|
|
830
839
|
//# sourceMappingURL=three-mediapipe-rig.js.map
|