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