v3d-web-realbits
Version:
Single camera motion-tracking in browser
1,190 lines (1,128 loc) • 139 kB
JavaScript
/******/ var __webpack_modules__ = ({
/***/ "./src/helper/basis.ts":
/*!*****************************!*\
!*** ./src/helper/basis.ts ***!
\*****************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "Basis": () => (/* binding */ Basis),
/* harmony export */ "calcAvgPlane": () => (/* binding */ calcAvgPlane),
/* harmony export */ "getBasis": () => (/* binding */ getBasis),
/* harmony export */ "quaternionBetweenBases": () => (/* binding */ quaternionBetweenBases)
/* harmony export */ });
/* harmony import */ var _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babylonjs/core */ "./node_modules/@babylonjs/core/index.js");
/* harmony import */ var _quaternion__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./quaternion */ "./src/helper/quaternion.ts");
/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./utils */ "./src/helper/utils.ts");
/*
Copyright (C) 2022 The v3d Authors.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, version 3.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
// Calculate 3D rotations
class Basis {
get x() {
return this._data[0];
}
get y() {
return this._data[1];
}
get z() {
return this._data[2];
}
constructor(v33, leftHanded = true, eps = 1e-6) {
this.leftHanded = leftHanded;
this.eps = eps;
this._data = Basis.getOriginalCoordVectors();
if (v33 && v33.every((v) => (0,_utils__WEBPACK_IMPORTED_MODULE_2__.validVector3)(v)))
this.set(v33);
this._data.forEach((v) => {
Object.freeze(v);
});
}
get() {
return this._data;
}
set(v33) {
this.x.copyFrom(v33[0]);
this.y.copyFrom(v33[1]);
this.z.copyFrom(v33[2]);
this.verifyBasis();
}
verifyBasis() {
const z = this.leftHanded ? this.z : this.z.negate();
if (!(0,_quaternion__WEBPACK_IMPORTED_MODULE_1__.vectorsSameDirWithinEps)(this.x.cross(this.y), z, this.eps))
throw Error("Basis is not correct!");
}
rotateByQuaternion(q) {
const newBasisVectors = [_babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3.Zero(), _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3.Zero(), _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3.Zero()];
this._data.map((v, i) => {
v.rotateByQuaternionToRef(q, newBasisVectors[i]);
});
return new Basis(newBasisVectors);
}
// Basis validity is not checked!
negateAxes(axis) {
const x = this.x.clone();
const y = this.y.clone();
const z = this.z.clone();
switch (axis) {
case _quaternion__WEBPACK_IMPORTED_MODULE_1__.AXIS.x:
x.negateInPlace();
break;
case _quaternion__WEBPACK_IMPORTED_MODULE_1__.AXIS.y:
y.negateInPlace();
break;
case _quaternion__WEBPACK_IMPORTED_MODULE_1__.AXIS.z:
z.negateInPlace();
break;
case _quaternion__WEBPACK_IMPORTED_MODULE_1__.AXIS.xy:
x.negateInPlace();
y.negateInPlace();
break;
case _quaternion__WEBPACK_IMPORTED_MODULE_1__.AXIS.yz:
y.negateInPlace();
z.negateInPlace();
break;
case _quaternion__WEBPACK_IMPORTED_MODULE_1__.AXIS.xz:
x.negateInPlace();
z.negateInPlace();
break;
case _quaternion__WEBPACK_IMPORTED_MODULE_1__.AXIS.xyz:
x.negateInPlace();
y.negateInPlace();
z.negateInPlace();
break;
default:
throw Error("Unknown axis!");
}
return new Basis([x, y, z]);
}
transpose(order) {
// Sanity check
if (!(0,_utils__WEBPACK_IMPORTED_MODULE_2__.setEqual)(new Set(order), new Set([0, 1, 2]))) {
console.error("Basis transpose failed: wrong input.");
return this;
}
const data = [this.x.clone(), this.y.clone(), this.z.clone()];
const newData = order.map(i => data[i]);
return new Basis(newData);
}
static getOriginalCoordVectors() {
return Basis.ORIGINAL_CARTESIAN_BASIS_VECTORS.map(v => v.clone());
}
}
Basis.ORIGINAL_CARTESIAN_BASIS_VECTORS = [
new _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3(1, 0, 0),
new _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3(0, 1, 0),
new _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3(0, 0, 1),
];
function quaternionBetweenBases(basis1, basis2, prevQuaternion) {
let thisBasis1 = basis1, thisBasis2 = basis2;
if (prevQuaternion !== undefined) {
const extraQuaternionR = _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Quaternion.Inverse(prevQuaternion);
thisBasis1 = basis1.rotateByQuaternion(extraQuaternionR);
thisBasis2 = basis2.rotateByQuaternion(extraQuaternionR);
}
const rotationBasis1 = _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Quaternion.RotationQuaternionFromAxis(thisBasis1.x.clone(), thisBasis1.y.clone(), thisBasis1.z.clone());
const rotationBasis2 = _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Quaternion.RotationQuaternionFromAxis(thisBasis2.x.clone(), thisBasis2.y.clone(), thisBasis2.z.clone());
const quaternion31 = rotationBasis1.clone().normalize();
const quaternion31R = _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Quaternion.Inverse(quaternion31);
const quaternion32 = rotationBasis2.clone().normalize();
return quaternion32.multiply(quaternion31R);
}
/*
* Left handed for BJS.
* Each object is defined by 3 points.
* Assume a is origin, b points to +x, abc forms XY plane.
*/
function getBasis(obj) {
const [a, b, c] = obj;
const planeXY = _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Plane.FromPoints(a, b, c).normalize();
const axisX = b.subtract(a).normalize();
const axisZ = planeXY.normal;
// Project c onto ab
const cp = a.add(axisX.scale(_babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3.Dot(c.subtract(a), axisX) / _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3.Dot(axisX, axisX)));
const axisY = c.subtract(cp).normalize();
return new Basis([axisX, axisY, axisZ]);
}
// Project points to an average plane
function calcAvgPlane(pts, normal) {
if (pts.length === 0)
return [_babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3.Zero()];
const avgPt = pts.reduce((prev, curr) => {
return prev.add(curr);
}).scale(1 / pts.length);
const ret = pts.map((v) => {
return v.subtract(normal.scale(_babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3.Dot(normal, v.subtract(avgPt))));
});
return ret;
}
/***/ }),
/***/ "./src/helper/filter.ts":
/*!******************************!*\
!*** ./src/helper/filter.ts ***!
\******************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "EuclideanHighPassFilter": () => (/* binding */ EuclideanHighPassFilter),
/* harmony export */ "GaussianVectorFilter": () => (/* binding */ GaussianVectorFilter),
/* harmony export */ "KalmanVectorFilter": () => (/* binding */ KalmanVectorFilter),
/* harmony export */ "OneEuroVectorFilter": () => (/* binding */ OneEuroVectorFilter),
/* harmony export */ "VISIBILITY_THRESHOLD": () => (/* binding */ VISIBILITY_THRESHOLD),
/* harmony export */ "gaussianKernel1d": () => (/* binding */ gaussianKernel1d)
/* harmony export */ });
/* harmony import */ var _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babylonjs/core */ "./node_modules/@babylonjs/core/index.js");
/* harmony import */ var kalmanjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! kalmanjs */ "./node_modules/kalmanjs/lib/kalman.js");
/* harmony import */ var kalmanjs__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(kalmanjs__WEBPACK_IMPORTED_MODULE_1__);
/*
Copyright (C) 2022 The v3d Authors.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, version 3.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
const VISIBILITY_THRESHOLD = 0.6;
// 1D Gaussian Kernel
const gaussianKernel1d = (function () {
let sqr2pi = Math.sqrt(2 * Math.PI);
return function gaussianKernel1d(size, sigma) {
// ensure size is even and prepare variables
let width = (size / 2) | 0, kernel = new Array(width * 2 + 1), norm = 1.0 / (sqr2pi * sigma), coefficient = 2 * sigma * sigma, total = 0, x;
// set values and increment total
for (x = -width; x <= width; x++) {
total += kernel[width + x] = norm * Math.exp(-x * x / coefficient);
}
// divide by total to make sure the sum of all the values is equal to 1
for (x = 0; x < kernel.length; x++) {
kernel[x] /= total;
}
return kernel;
};
}());
/*
* Converted from https://github.com/jaantollander/OneEuroFilter.
*/
class OneEuroVectorFilter {
constructor(t_prev, x_prev, dx_prev = _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3.Zero(), min_cutoff = 1.0, beta = 0.0, d_cutoff = 1.0) {
this.t_prev = t_prev;
this.x_prev = x_prev;
this.dx_prev = dx_prev;
this.min_cutoff = min_cutoff;
this.beta = beta;
this.d_cutoff = d_cutoff;
}
static smoothing_factor(t_e, cutoff) {
const r = 2 * Math.PI * cutoff * t_e;
return r / (r + 1);
}
static exponential_smoothing(a, x, x_prev) {
return x.scale(a).addInPlace(x_prev.scale((1 - a)));
}
next(t, x) {
const t_e = t - this.t_prev;
// The filtered derivative of the signal.
const a_d = OneEuroVectorFilter.smoothing_factor(t_e, this.d_cutoff);
const dx = x.subtract(this.x_prev).scaleInPlace(1 / t_e);
const dx_hat = OneEuroVectorFilter.exponential_smoothing(a_d, dx, this.dx_prev);
// The filtered signal.
const cutoff = this.min_cutoff + this.beta * dx_hat.length();
const a = OneEuroVectorFilter.smoothing_factor(t_e, cutoff);
const x_hat = OneEuroVectorFilter.exponential_smoothing(a, x, this.x_prev);
// Memorize the previous values.
this.x_prev = x_hat;
this.dx_prev = dx_hat;
this.t_prev = t;
return x_hat;
}
}
class KalmanVectorFilter {
constructor(R = 0.1, Q = 3) {
this.R = R;
this.Q = Q;
this.kalmanFilterX = new (kalmanjs__WEBPACK_IMPORTED_MODULE_1___default())({ Q: Q, R: R });
this.kalmanFilterY = new (kalmanjs__WEBPACK_IMPORTED_MODULE_1___default())({ Q: Q, R: R });
this.kalmanFilterZ = new (kalmanjs__WEBPACK_IMPORTED_MODULE_1___default())({ Q: Q, R: R });
}
next(t, vec) {
const newValues = [
this.kalmanFilterX.filter(vec.x),
this.kalmanFilterY.filter(vec.y),
this.kalmanFilterZ.filter(vec.z),
];
return _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3.FromArray(newValues);
}
}
class GaussianVectorFilter {
get values() {
return this._values;
}
constructor(size, sigma) {
this.size = size;
this.sigma = sigma;
this._values = [];
if (size < 2)
throw RangeError("Filter size too short");
this.size = Math.floor(size);
this.kernel = gaussianKernel1d(size, sigma);
}
push(v) {
this.values.push(v);
if (this.values.length === this.size + 1) {
this.values.shift();
}
else if (this.values.length > this.size + 1) {
console.warn(`Internal queue has length longer than size: ${this.size}`);
this.values.slice(-this.size);
}
}
reset() {
this.values.length = 0;
}
apply() {
if (this.values.length !== this.size)
return _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3.Zero();
const ret = _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3.Zero();
const len0 = ret.length();
for (let i = 0; i < this.size; ++i) {
ret.addInPlace(this.values[i].scale(this.kernel[i]));
}
const len1 = ret.length();
// Normalize to original length
ret.scaleInPlace(len0 / len1);
return ret;
}
}
class EuclideanHighPassFilter {
get value() {
return this._value;
}
constructor(threshold) {
this.threshold = threshold;
this._value = _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3.Zero();
}
update(v) {
if (this.value.subtract(v).length() > this.threshold) {
this._value = v;
}
}
reset() {
this._value = _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3.Zero();
}
}
/***/ }),
/***/ "./src/helper/landmark.ts":
/*!********************************!*\
!*** ./src/helper/landmark.ts ***!
\********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "FACE_LANDMARK_LENGTH": () => (/* binding */ FACE_LANDMARK_LENGTH),
/* harmony export */ "FilteredLandmarkVector": () => (/* binding */ FilteredLandmarkVector),
/* harmony export */ "HAND_LANDMARKS": () => (/* binding */ HAND_LANDMARKS),
/* harmony export */ "HAND_LANDMARKS_BONE_MAPPING": () => (/* binding */ HAND_LANDMARKS_BONE_MAPPING),
/* harmony export */ "HAND_LANDMARKS_BONE_REVERSE_MAPPING": () => (/* binding */ HAND_LANDMARKS_BONE_REVERSE_MAPPING),
/* harmony export */ "HAND_LANDMARK_LENGTH": () => (/* binding */ HAND_LANDMARK_LENGTH),
/* harmony export */ "POSE_LANDMARK_LENGTH": () => (/* binding */ POSE_LANDMARK_LENGTH),
/* harmony export */ "depthFirstSearch": () => (/* binding */ depthFirstSearch),
/* harmony export */ "handLandMarkToBoneName": () => (/* binding */ handLandMarkToBoneName),
/* harmony export */ "normalizedLandmarkToVector": () => (/* binding */ normalizedLandmarkToVector),
/* harmony export */ "vectorToNormalizedLandmark": () => (/* binding */ vectorToNormalizedLandmark)
/* harmony export */ });
/* harmony import */ var _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babylonjs/core */ "./node_modules/@babylonjs/core/index.js");
/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./filter */ "./src/helper/filter.ts");
/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./utils */ "./src/helper/utils.ts");
/*
Copyright (C) 2022 The v3d Authors.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, version 3.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
class FilteredLandmarkVector {
get t() {
return this._t;
}
set t(value) {
this._t = value;
}
get pos() {
return this._pos;
}
constructor(params = {
oneEuroCutoff: 0.01,
oneEuroBeta: 0,
type: "OneEuro",
}) {
this.gaussianVectorFilter = null;
this._t = 0;
this._pos = _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3.Zero();
this.visibility = 0;
if (params.type === "Kalman")
this.mainFilter = new _filter__WEBPACK_IMPORTED_MODULE_1__.KalmanVectorFilter(params.R, params.Q);
else if (params.type === "OneEuro")
this.mainFilter = new _filter__WEBPACK_IMPORTED_MODULE_1__.OneEuroVectorFilter(this.t, this.pos, _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3.Zero(), params.oneEuroCutoff, params.oneEuroBeta);
else
throw Error("Wrong filter type!");
if (params.gaussianSigma)
this.gaussianVectorFilter = new _filter__WEBPACK_IMPORTED_MODULE_1__.GaussianVectorFilter(5, params.gaussianSigma);
}
updatePosition(pos, visibility) {
this.t += 1;
// Face Mesh has no visibility
if (visibility === undefined || visibility > _filter__WEBPACK_IMPORTED_MODULE_1__.VISIBILITY_THRESHOLD) {
pos = this.mainFilter.next(this.t, pos);
if (this.gaussianVectorFilter) {
this.gaussianVectorFilter.push(pos);
pos = this.gaussianVectorFilter.apply();
}
this._pos = pos;
this.visibility = visibility;
}
}
}
const POSE_LANDMARK_LENGTH = 33;
const FACE_LANDMARK_LENGTH = 478;
const HAND_LANDMARK_LENGTH = 21;
const normalizedLandmarkToVector = (l, scaling = 1, reverseY = false) => {
return new _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3(l.x * scaling, reverseY ? -l.y * scaling : l.y * scaling, l.z * scaling);
};
const vectorToNormalizedLandmark = (l) => {
return { x: l.x, y: l.y, z: l.z };
};
const HAND_LANDMARKS = {
WRIST: 0,
THUMB_CMC: 1,
THUMB_MCP: 2,
THUMB_IP: 3,
THUMB_TIP: 4,
INDEX_FINGER_MCP: 5,
INDEX_FINGER_PIP: 6,
INDEX_FINGER_DIP: 7,
INDEX_FINGER_TIP: 8,
MIDDLE_FINGER_MCP: 9,
MIDDLE_FINGER_PIP: 10,
MIDDLE_FINGER_DIP: 11,
MIDDLE_FINGER_TIP: 12,
RING_FINGER_MCP: 13,
RING_FINGER_PIP: 14,
RING_FINGER_DIP: 15,
RING_FINGER_TIP: 16,
PINKY_MCP: 17,
PINKY_PIP: 18,
PINKY_DIP: 19,
PINKY_TIP: 20,
};
const HAND_LANDMARKS_BONE_MAPPING = {
Hand: HAND_LANDMARKS.WRIST,
ThumbProximal: HAND_LANDMARKS.THUMB_CMC,
ThumbIntermediate: HAND_LANDMARKS.THUMB_MCP,
ThumbDistal: HAND_LANDMARKS.THUMB_IP,
IndexProximal: HAND_LANDMARKS.INDEX_FINGER_MCP,
IndexIntermediate: HAND_LANDMARKS.INDEX_FINGER_PIP,
IndexDistal: HAND_LANDMARKS.INDEX_FINGER_DIP,
MiddleProximal: HAND_LANDMARKS.MIDDLE_FINGER_MCP,
MiddleIntermediate: HAND_LANDMARKS.MIDDLE_FINGER_PIP,
MiddleDistal: HAND_LANDMARKS.MIDDLE_FINGER_DIP,
RingProximal: HAND_LANDMARKS.RING_FINGER_MCP,
RingIntermediate: HAND_LANDMARKS.RING_FINGER_PIP,
RingDistal: HAND_LANDMARKS.RING_FINGER_DIP,
LittleProximal: HAND_LANDMARKS.PINKY_MCP,
LittleIntermediate: HAND_LANDMARKS.PINKY_PIP,
LittleDistal: HAND_LANDMARKS.PINKY_DIP,
};
const HAND_LANDMARKS_BONE_REVERSE_MAPPING = (0,_utils__WEBPACK_IMPORTED_MODULE_2__.objectFlip)(HAND_LANDMARKS_BONE_MAPPING);
function handLandMarkToBoneName(landmark, isLeft) {
if (!(landmark in HAND_LANDMARKS_BONE_REVERSE_MAPPING))
throw Error("Wrong landmark given!");
return ((isLeft ? "left" : "right") +
HAND_LANDMARKS_BONE_REVERSE_MAPPING[landmark]);
}
/*
* Depth-first search/walk of a generic tree.
* Also returns a map for backtracking from leaf.
*/
function depthFirstSearch(rootNode, f) {
const stack = [];
const parentMap = new Map();
stack.push(rootNode);
while (stack.length !== 0) {
// remove the first child in the stack
const currentNode = stack.splice(-1, 1)[0];
const retVal = f(currentNode);
if (retVal)
return [currentNode, parentMap];
const currentChildren = currentNode.children;
// add any children in the node at the top of the stack
if (currentChildren !== null) {
for (let index = 0; index < currentChildren.length; index++) {
const child = currentChildren[index];
stack.push(child);
if (!parentMap.has(child)) {
parentMap.set(child, currentNode);
}
}
}
}
return [null, null];
}
/***/ }),
/***/ "./src/helper/quaternion.ts":
/*!**********************************!*\
!*** ./src/helper/quaternion.ts ***!
\**********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "AXIS": () => (/* binding */ AXIS),
/* harmony export */ "CloneableQuaternion": () => (/* binding */ CloneableQuaternion),
/* harmony export */ "CloneableQuaternionLite": () => (/* binding */ CloneableQuaternionLite),
/* harmony export */ "DegToRad": () => (/* binding */ DegToRad),
/* harmony export */ "FilteredQuaternion": () => (/* binding */ FilteredQuaternion),
/* harmony export */ "RadToDeg": () => (/* binding */ RadToDeg),
/* harmony export */ "calcSphericalCoord": () => (/* binding */ calcSphericalCoord),
/* harmony export */ "checkQuaternion": () => (/* binding */ checkQuaternion),
/* harmony export */ "cloneableQuaternionToQuaternion": () => (/* binding */ cloneableQuaternionToQuaternion),
/* harmony export */ "degreeBetweenVectors": () => (/* binding */ degreeBetweenVectors),
/* harmony export */ "degreesEqualInQuaternion": () => (/* binding */ degreesEqualInQuaternion),
/* harmony export */ "exchangeRotationAxis": () => (/* binding */ exchangeRotationAxis),
/* harmony export */ "printQuaternion": () => (/* binding */ printQuaternion),
/* harmony export */ "quaternionBetweenVectors": () => (/* binding */ quaternionBetweenVectors),
/* harmony export */ "quaternionToDegrees": () => (/* binding */ quaternionToDegrees),
/* harmony export */ "remapDegreeWithCap": () => (/* binding */ remapDegreeWithCap),
/* harmony export */ "removeRotationAxisWithCap": () => (/* binding */ removeRotationAxisWithCap),
/* harmony export */ "reverseRotation": () => (/* binding */ reverseRotation),
/* harmony export */ "scaleRotation": () => (/* binding */ scaleRotation),
/* harmony export */ "sphericalToQuaternion": () => (/* binding */ sphericalToQuaternion),
/* harmony export */ "testQuaternionEqualsByVector": () => (/* binding */ testQuaternionEqualsByVector),
/* harmony export */ "vectorsSameDirWithinEps": () => (/* binding */ vectorsSameDirWithinEps)
/* harmony export */ });
/* harmony import */ var _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babylonjs/core */ "./node_modules/@babylonjs/core/index.js");
/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./utils */ "./src/helper/utils.ts");
/* harmony import */ var _basis__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./basis */ "./src/helper/basis.ts");
/* harmony import */ var _landmark__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./landmark */ "./src/helper/landmark.ts");
/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./filter */ "./src/helper/filter.ts");
/*
Copyright (C) 2022 The v3d Authors.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, version 3.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
class CloneableQuaternionLite {
constructor(q) {
this.x = 0;
this.y = 0;
this.z = 0;
this.w = 1;
if (q) {
this.x = q.x;
this.y = q.y;
this.z = q.z;
this.w = q.w;
}
}
}
class CloneableQuaternion extends CloneableQuaternionLite {
get baseBasis() {
return this._baseBasis;
}
constructor(q, basis) {
super(q);
this._baseBasis = basis ? basis : new _basis__WEBPACK_IMPORTED_MODULE_2__.Basis(null);
}
set(q) {
this.x = q.x;
this.y = q.y;
this.z = q.z;
this.w = q.w;
}
rotateBasis(q) {
return this._baseBasis.rotateByQuaternion(q);
}
}
const cloneableQuaternionToQuaternion = (q) => {
const ret = new _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Quaternion(q.x, q.y, q.z, q.w);
return ret;
};
class FilteredQuaternion {
get t() {
return this._t;
}
set t(value) {
this._t = value;
}
get rot() {
return this._rot;
}
constructor(params = {
R: 1,
Q: 1,
type: 'Kalman'
}) {
this.gaussianVectorFilter = null;
this._t = 0;
this._rot = _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Quaternion.Identity();
if (params.type === "Kalman")
this.mainFilter = new _filter__WEBPACK_IMPORTED_MODULE_4__.KalmanVectorFilter(params.R, params.Q);
else
throw Error("Wrong filter type!");
if (params.gaussianSigma)
this.gaussianVectorFilter = new _filter__WEBPACK_IMPORTED_MODULE_4__.GaussianVectorFilter(5, params.gaussianSigma);
}
updateRotation(rot) {
this.t += 1;
let angles = rot.toEulerAngles();
angles = this.mainFilter.next(this.t, angles);
if (this.gaussianVectorFilter) {
this.gaussianVectorFilter.push(angles);
angles = this.gaussianVectorFilter.apply();
}
this._rot = _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Quaternion.FromEulerVector(angles);
}
}
var AXIS;
(function (AXIS) {
AXIS[AXIS["x"] = 0] = "x";
AXIS[AXIS["y"] = 1] = "y";
AXIS[AXIS["z"] = 2] = "z";
AXIS[AXIS["xy"] = 3] = "xy";
AXIS[AXIS["yz"] = 4] = "yz";
AXIS[AXIS["xz"] = 5] = "xz";
AXIS[AXIS["xyz"] = 6] = "xyz";
AXIS[AXIS["none"] = 10] = "none";
})(AXIS || (AXIS = {}));
// Convenience functions
const RadToDeg = (r) => {
return _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Angle.FromRadians(r).degrees();
};
const DegToRad = (d) => {
return _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Angle.FromDegrees(d).radians();
};
/**
* Check a quaternion is valid
* @param q Input quaternion
*/
function checkQuaternion(q) {
return Number.isFinite(q.x) && Number.isFinite(q.y) && Number.isFinite(q.z) && Number.isFinite(q.w);
}
// Similar to three.js Quaternion.setFromUnitVectors
const quaternionBetweenVectors = (v1, v2) => {
const angle = _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3.GetAngleBetweenVectors(v1, v2, _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3.Cross(v1, v2));
const axis = _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3.Cross(v1, v2);
axis.normalize();
return _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Quaternion.RotationAxis(axis, angle);
};
/**
* Same as above, Euler angle version
* @param v1 Input rotation in degrees 1
* @param v2 Input rotation in degrees 2
* @param remapDegree Whether re-map degrees
*/
const degreeBetweenVectors = (v1, v2, remapDegree = false) => {
return quaternionToDegrees(quaternionBetweenVectors(v1, v2), remapDegree);
};
/**
* Re-map degrees to -180 to 180
* @param deg Input angle in Degrees
*/
const remapDegreeWithCap = (deg) => {
deg = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.rangeCap)(deg, 0, 360);
return deg < 180 ? deg : deg - 360;
};
/**
* Convert quaternions to degrees
* @param q Input quaternion
* @param remapDegree whether re-map degrees
*/
const quaternionToDegrees = (q, remapDegree = false) => {
const angles = q.toEulerAngles();
const remapFn = remapDegree ? remapDegreeWithCap : (x) => x;
return new _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3(remapFn(RadToDeg(angles.x)), remapFn(RadToDeg(angles.y)), remapFn(RadToDeg(angles.z)));
};
/**
* Check whether two directions are close enough within a small values
* @param v1 Input direction 1
* @param v2 Input direction 2
* @param eps Error threshold
*/
function vectorsSameDirWithinEps(v1, v2, eps = 1e-6) {
return v1.cross(v2).length() < eps && _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3.Dot(v1, v2) > 0;
}
/**
* Test whether two quaternions have equal effects
* @param q1 Input quaternion 1
* @param q2 Input quaternion 2
*/
function testQuaternionEqualsByVector(q1, q2) {
const testVec = _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3.One();
const testVec1 = _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3.Zero();
const testVec2 = _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3.One();
testVec.rotateByQuaternionToRef(q1, testVec1);
testVec.rotateByQuaternionToRef(q2, testVec2);
return vectorsSameDirWithinEps(testVec1, testVec2);
}
/**
* Same as above, Euler angle version
* @param d1 Input degrees 1
* @param d2 Input degrees 2
*/
function degreesEqualInQuaternion(d1, d2) {
const q1 = _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Quaternion.FromEulerAngles(DegToRad(d1.x), DegToRad(d1.y), DegToRad(d1.z));
const q2 = _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Quaternion.FromEulerAngles(DegToRad(d2.x), DegToRad(d2.y), DegToRad(d2.z));
return testQuaternionEqualsByVector(q1, q2);
}
/**
* Reverse rotation Euler angles on given axes
* @param q Input quaternion
* @param axis Axes to reverse
*/
const reverseRotation = (q, axis) => {
if (axis === AXIS.none)
return q;
const angles = q.toEulerAngles();
switch (axis) {
case AXIS.x:
angles.x = -angles.x;
break;
case AXIS.y:
angles.y = -angles.y;
break;
case AXIS.z:
angles.z = -angles.z;
break;
case AXIS.xy:
angles.x = -angles.x;
angles.y = -angles.y;
break;
case AXIS.yz:
angles.y = -angles.y;
angles.z = -angles.z;
break;
case AXIS.xz:
angles.x = -angles.x;
angles.z = -angles.z;
break;
case AXIS.xyz:
angles.x = -angles.x;
angles.y = -angles.y;
angles.z = -angles.z;
break;
default:
throw Error("Unknown axis!");
}
return _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Quaternion.RotationYawPitchRoll(angles.y, angles.x, angles.z);
};
/**
* Remove rotation on given axes.
* Optionally capping rotation (in Euler angles) on two axes.
* This operation assumes re-mapped degrees.
* @param q Input quaternion
* @param axis Axes to remove
* @param capAxis1 Capping axis 1
* @param capLow1 Axis 1 lower range
* @param capHigh1 Axis 1 higher range
* @param capAxis2 Capping axis 2
* @param capLow2 Axis 2 lower range
* @param capHigh2 Axis 2 higher range
*/
const removeRotationAxisWithCap = (q, axis, capAxis1, capLow1, capHigh1, capAxis2, capLow2, capHigh2) => {
const angles = quaternionToDegrees(q, true);
switch (axis) {
case AXIS.none:
break;
case AXIS.x:
angles.x = 0;
break;
case AXIS.y:
angles.y = 0;
break;
case AXIS.z:
angles.z = 0;
break;
case AXIS.xy:
angles.x = 0;
angles.y = 0;
break;
case AXIS.yz:
angles.y = 0;
angles.z = 0;
break;
case AXIS.xz:
angles.x = 0;
angles.z = 0;
break;
case AXIS.xyz:
angles.x = 0;
angles.y = 0;
angles.z = 0;
break;
default:
throw Error("Unknown axis!");
}
if (capAxis1 !== undefined && capLow1 !== undefined && capHigh1 !== undefined) {
switch (capAxis1) {
case AXIS.x:
angles.x = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.rangeCap)(angles.x, capLow1, capHigh1);
break;
case AXIS.y:
angles.y = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.rangeCap)(angles.y, capLow1, capHigh1);
break;
case AXIS.z:
angles.z = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.rangeCap)(angles.z, capLow1, capHigh1);
break;
default:
throw Error("Unknown cap axis!");
}
}
if (capAxis2 !== undefined && capLow2 !== undefined && capHigh2 !== undefined) {
switch (capAxis2) {
case AXIS.x:
angles.x = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.rangeCap)(angles.x, capLow2, capHigh2);
break;
case AXIS.y:
angles.y = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.rangeCap)(angles.y, capLow2, capHigh2);
break;
case AXIS.z:
angles.z = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.rangeCap)(angles.z, capLow2, capHigh2);
break;
default:
throw Error("Unknown cap axis!");
}
}
return _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Quaternion.RotationYawPitchRoll(DegToRad(angles.y), DegToRad(angles.x), DegToRad(angles.z));
};
/**
* Switch rotation axes.
* @param q Input quaternion
* @param axis1 Axis 1 to switch
* @param axis2 Axis 2 to switch
*/
const exchangeRotationAxis = (q, axis1, axis2) => {
const angles = [];
q.toEulerAngles().toArray(angles);
const angle1 = angles[axis1];
const angle2 = angles[axis2];
const temp = angle1;
angles[axis1] = angle2;
angles[axis2] = temp;
return _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Quaternion.FromEulerAngles(angles[0], angles[1], angles[2]);
};
function printQuaternion(q, s) {
console.log(s, (0,_landmark__WEBPACK_IMPORTED_MODULE_3__.vectorToNormalizedLandmark)(quaternionToDegrees(q, true)));
}
/**
* Result is in Radian on unit sphere (r = 1).
* Canonical ISO 80000-2:2019 convention.
* @param pos Euclidean local position
* @param basis Local coordinate system basis
*/
function calcSphericalCoord(pos, basis) {
const qToOriginal = _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Quaternion.Inverse(_babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Quaternion.RotationQuaternionFromAxis(basis.x.clone(), basis.y.clone(), basis.z.clone())).normalize();
const posInOriginal = _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3.Zero();
pos.rotateByQuaternionToRef(qToOriginal, posInOriginal);
posInOriginal.normalize();
// Calculate theta and phi
const x = posInOriginal.x;
const y = posInOriginal.y;
const z = posInOriginal.z;
const theta = Math.acos(z);
const phi = Math.atan2(y, x);
return [theta, phi];
}
/**
* Assuming rotation starts from (1, 0, 0) in local coordinate system.
* @param basis Local coordinate system basis
* @param theta Polar angle
* @param phi Azimuthal angle
* @param prevQuaternion Parent quaternion to the local system
*/
function sphericalToQuaternion(basis, theta, phi, prevQuaternion) {
const xTz = _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Quaternion.RotationAxis(basis.y.clone(), -Math.PI / 2);
const xTzBasis = basis.rotateByQuaternion(xTz);
const q1 = _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Quaternion.RotationAxis(xTzBasis.x.clone(), phi);
const q1Basis = xTzBasis.rotateByQuaternion(q1);
const q2 = _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Quaternion.RotationAxis(q1Basis.y.clone(), theta);
const q2Basis = q1Basis.rotateByQuaternion(q2);
// Force result to face front
const planeXZ = _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Plane.FromPositionAndNormal(_babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3.Zero(), basis.y.clone());
// const intermBasis = basis.rotateByQuaternion(xTz.multiply(q1).multiplyInPlace(q2));
const intermBasis = q2Basis;
const newBasisZ = _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3.Cross(intermBasis.x.clone(), planeXZ.normal);
const newBasisY = _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3.Cross(newBasisZ, intermBasis.x.clone());
const newBasis = new _basis__WEBPACK_IMPORTED_MODULE_2__.Basis([intermBasis.x, newBasisY, newBasisZ]);
return (0,_basis__WEBPACK_IMPORTED_MODULE_2__.quaternionBetweenBases)(basis, newBasis, prevQuaternion);
}
// Scale rotation angles in place
function scaleRotation(quaternion, scale) {
const angles = quaternion.toEulerAngles();
angles.scaleInPlace(scale);
return _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Quaternion.FromEulerVector(angles);
}
/***/ }),
/***/ "./src/helper/utils.ts":
/*!*****************************!*\
!*** ./src/helper/utils.ts ***!
\*****************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "CustomLoadingScreen": () => (/* binding */ CustomLoadingScreen),
/* harmony export */ "LR": () => (/* binding */ LR),
/* harmony export */ "findPoint": () => (/* binding */ findPoint),
/* harmony export */ "fixedLengthQueue": () => (/* binding */ fixedLengthQueue),
/* harmony export */ "initArray": () => (/* binding */ initArray),
/* harmony export */ "linspace": () => (/* binding */ linspace),
/* harmony export */ "objectFlip": () => (/* binding */ objectFlip),
/* harmony export */ "pointLineDistance": () => (/* binding */ pointLineDistance),
/* harmony export */ "projectVectorOnPlane": () => (/* binding */ projectVectorOnPlane),
/* harmony export */ "range": () => (/* binding */ range),
/* harmony export */ "rangeCap": () => (/* binding */ rangeCap),
/* harmony export */ "remapRange": () => (/* binding */ remapRange),
/* harmony export */ "remapRangeNoCap": () => (/* binding */ remapRangeNoCap),
/* harmony export */ "remapRangeWithCap": () => (/* binding */ remapRangeWithCap),
/* harmony export */ "round": () => (/* binding */ round),
/* harmony export */ "setEqual": () => (/* binding */ setEqual),
/* harmony export */ "validVector3": () => (/* binding */ validVector3)
/* harmony export */ });
/* harmony import */ var _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babylonjs/core */ "./node_modules/@babylonjs/core/index.js");
/*
Copyright (C) 2021 The v3d Authors.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, version 3.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
function initArray(length, initializer) {
let arr = new Array(length);
for (let i = 0; i < length; i++)
arr[i] = initializer(i);
return arr;
}
function range(start, end, step) {
return Array.from({ length: Math.ceil((end - start) / step) }, (_, i) => start + i * step);
}
function linspace(start, end, div) {
const step = (end - start) / div;
return Array.from({ length: div }, (_, i) => start + i * step);
}
function objectFlip(obj) {
const ret = {};
Object.keys(obj).forEach((key) => {
ret[obj[key]] = key;
});
return ret;
}
const rangeCap = (v, min, max) => {
if (min > max) {
const tmp = max;
max = min;
min = tmp;
}
return Math.max(Math.min(v, max), min);
};
const remapRange = (v, src_low, src_high, dst_low, dst_high) => {
return dst_low + (v - src_low) * (dst_high - dst_low) / (src_high - src_low);
};
const remapRangeWithCap = (v, src_low, src_high, dst_low, dst_high) => {
const v1 = rangeCap(v, src_low, src_high);
return dst_low + (v1 - src_low) * (dst_high - dst_low) / (src_high - src_low);
};
const remapRangeNoCap = (v, src_low, src_high, dst_low, dst_high) => {
return dst_low + (v - src_low) * (dst_high - dst_low) / (src_high - src_low);
};
function validVector3(v) {
return Number.isFinite(v.x) && Number.isFinite(v.y) && Number.isFinite(v.z);
}
// type ReadonlyKeysOfA = ReadonlyKeys<A>;
function setEqual(as, bs) {
if (as.size !== bs.size)
return false;
for (const a of as)
if (!bs.has(a))
return false;
return true;
}
function projectVectorOnPlane(projPlane, vec) {
return vec.subtract(projPlane.normal.scale(_babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3.Dot(vec, projPlane.normal)));
}
function round(value, precision) {
const multiplier = Math.pow(10, precision || 0);
return Math.round(value * multiplier) / multiplier;
}
/**
* Simple fixed length FIFO queue.
*/
class fixedLengthQueue {
get values() {
return this._values;
}
constructor(size) {
this.size = size;
this._values = [];
}
push(v) {
this.values.push(v);
if (this.values.length === this.size + 1) {
this.values.shift();
}
else if (this.values.length > this.size + 1) {
console.warn(`Internal queue has length longer than size ${this.size}: Got length ${this.values.length}`);
this._values = this.values.slice(-this.size);
}
}
concat(arr) {
this._values = this.values.concat(arr);
if (this.values.length > this.size) {
this._values = this.values.slice(-this.size);
}
}
pop() {
return this.values.shift();
}
first() {
if (this._values.length > 0)
return this.values[0];
else
return null;
}
last() {
if (this._values.length > 0)
return this._values[this._values.length - 1];
else
return null;
}
reset() {
this.values.length = 0;
}
length() {
return this.values.length;
}
}
function findPoint(curve, x, eps = 0.001) {
const pts = curve.getPoints();
if (x > pts[0].x)
return pts[0].y;
else if (x < pts[pts.length - 1].x)
return pts[pts.length - 1].y;
for (let i = 0; i < pts.length; ++i) {
if (Math.abs(x - pts[i].x) < eps)
return pts[i].y;
}
return 0;
}
const LR = ["left", "right"];
class CustomLoadingScreen {
constructor(renderingCanvas, loadingDiv) {
this.renderingCanvas = renderingCanvas;
this.loadingDiv = loadingDiv;
//optional, but needed due to interface definitions
this.loadingUIBackgroundColor = '';
this.loadingUIText = '';
}
displayLoadingUI() {
if (!this.loadingDiv)
return;
if (this.loadingDiv.style.display === 'none') {
// Do not add a loading screen if there is already one
this.loadingDiv.style.display = "initial";
}
// this._resizeLoadingUI();
// window.addEventListener("resize", this._resizeLoadingUI);
}
hideLoadingUI() {
if (this.loadingDiv)
this.loadingDiv.style.display = "none";
}
}
function pointLineDistance(point, lineEndA, lineEndB) {
const lineDir = lineEndB.subtract(lineEndA).normalize();
const pProj = lineEndA.add(lineDir.scale(_babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3.Dot(point.subtract(lineEndA), lineDir)
/ _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__.Vector3.Dot(lineDir, lineDir)));
return point.subtract(pProj).length();
}
/***/ }),
/***/ "./src/worker/pose-processing.ts":
/*!***************************************!*\
!*** ./src/worker/pose-processing.ts ***!
\***************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "PoseKeyPoints": () => (/* binding */ PoseKeyPoints),
/* harmony export */ "Poses": () => (/* binding */ Poses),
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__),
/* harmony export */ "poseWrapper": () => (/* binding */ poseWrapper)
/* harmony export */ });
/* harmony import */ var comlink__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! comlink */ "./node_modules/comlink/dist/esm/comlink.mjs");
/* harmony import */ var _mediapipe_holistic__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @mediapipe/holistic */ "./node_modules/@mediapipe/holistic/holistic.js");
/* harmony import */ var _mediapipe_holistic__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(_mediapipe_holistic__WEBPACK_IMPORTED_MODULE_6__);
/* harmony import */ var _babylonjs_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babylonjs/core */ "./node_modules/@babylonjs/core/index.js");
/* harmony import */ var _helper_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../helper/utils */ "./src/helper/utils.ts");
/* harmony import */ var _helper_landmark__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../helper/landmark */ "./src/helper/landmark.ts");
/* harmony import */ var _helper_quaternion__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../helper/quaternion */ "./src/helper/quaternion.ts");
/* harmony import */ var _helper_basis__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../helper/basis */ "./src/helper/basis.ts");
/* harmony import */ var _helper_filter__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../helper/filter */ "./src/helper/filter.ts");
/*
Copyright (C) 2021 The v3d Authors.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, version 3.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
class PoseKeyPoints {
constructor() {
this.top_face_oval = new _helper_landmark__WEBPACK_IMPORTED_MODULE_2__.FilteredLandmarkVector();
this.left_face_oval = new _helper_landmark__WEBPACK_IMPORTED_MODULE_2__.FilteredLandmarkVector();
this.bottom_face_oval = new _helper_landmark__WEBPACK_IMPORTED_MODULE_2__.FilteredLandmarkVector();
this.right_face_oval = new _helper_landmark__WEBPACK_IMPORTED_MODULE_2__.FilteredLandmarkVector();
this.left_eye_top = new _helper_landmark__WEBPACK_IMPORTED_MODULE_2__.FilteredLandmarkVector();
this.left_eye_bottom = new _helper_landmark__WEBPACK_IMPORTED_MODULE_2__.FilteredLandmarkVector();
this.left_eye_inner = new _helper_landmark__WEBPACK_IMPORTED_MODULE_2__.FilteredLandmarkVector();
this.left_eye_outer = new _helper_landmark__WEBPACK_IMPORTED_MODULE_2__.FilteredLandmarkVector();
this.left_eye_inner_secondary = new _helper_landmark__WEBPACK_IMPORTED_MODULE_2__.FilteredLandmarkVector();
this.left_eye_outer_secondary = new _helper_landmark__WEBPACK_IMPORTED_MODULE_2__.FilteredLandmarkVector();
this.left_iris_top = new _helper_landmark__WEBPACK_IMPORTED_MODULE_2__.FilteredLandmarkVector();
this.left_iris_bottom = new _helper_landmark__WEBPACK_IMPORTED_MODULE_2__.FilteredLandmarkVector();
this.left_iris_left = new _helper_landmark__WEBPACK_IMPORTED_MODULE_2__.FilteredLandmarkVector();
this.left_iris_right = new _helper_landmark__WEBPACK_IMPORTED_MODULE_2__.FilteredLandmarkVector();
this.right_eye_top = new _helper_landmark__WEBPACK_IMPORTED_MODULE_2__.FilteredLandmarkVector();
this.right_eye_bottom = new _helper_landmark__WEBPACK_IMPORTED_MODULE_2__.FilteredLandmarkVector();
this.right_eye_inner = new _helper_landmark__WEBPACK_IMPORTED_MODULE_2__.FilteredLandmarkVector();
this.right_eye_outer = new _helper_landmark__WEBPACK_IMPORTED_MODULE_2__.FilteredLandmarkVector();
this.right_eye_inner_secondary = new _helper_landmark__WEBPACK_IMPORTED_MODULE_2__.FilteredLandmarkVector();
this.right_eye_outer_secondary = new _helper_landmar