diff --git a/modules/lipsync-it.mjs b/modules/lipsync-it.mjs new file mode 100644 index 0000000..892e97f --- /dev/null +++ b/modules/lipsync-it.mjs @@ -0,0 +1,272 @@ +/** +* @class Italian lip-sync processor +* @autor Andrea Santaniello +*/ + +class LipsyncIt { + + /** + * @constructor + */ + constructor() { + this.rules = { + 'A': [ + "[A] =aa", "[AN] =aa nn", "[AM] =aa mm", "[AR] =aa rr", "[A]LL =aa", + " [ARE] =aa rr", "[AR]I=aa rr I", "[AT]O=aa tt O", "[AU] =aa U", "[AV]O=aa v O" + ], + 'B': [ + " [B]=bb", "[B]R=bb rr", "[B]L=bb ll" + ], + 'C': [ + "[CH]=k", "[C]A=kk aa", "[C]O=kk O", "[C]U=kk U", "[CI]=ch I", "[CE]=ch E" + ], + 'D': [ + " [D]=dd", "[D]I=dd I", "[D]O=dd O", "[DI]A=dd I aa", "[DI]O=dd I O" + ], + 'E': [ + "[E]=E", "[ER]=E rr", "[E]L=E ll", "[EM]=E mm", "[EN]=E nn", "[ES]=E ss" + ], + 'F': [ + " [F]=ff", "[F]I=ff I", "[F]O=ff O", "[F]U=ff U", "[FR]=ff rr", "[FL]=ff ll" + ], + 'G': [ + "[GH]=g", "[G]A=g aa", "[G]O=g O", "[G]U=g U", "[GI]=j I", "[GE]=j E" + ], + 'H': [ + " [H]=h", "[H]O=h O", "[H]A=h aa", "[H]U=h U" + ], + 'I': [ + "[I]=I", "[IN]=I nn", "[IM]=I mm", "[IR]=I rr" + ], + 'L': [ + " [L]=ll", "[L]A=ll aa", "[L]O=ll O", "[L]U=ll U", "[LI]=ll I", "[LE]=ll E" + ], + 'M': [ + " [M]=mm", "[M]A=mm aa", "[M]O=mm O", "[M]U=mm U", "[MI]=mm I", "[ME]=mm E" + ], + 'N': [ + " [N]=nn", "[N]A=nn aa", "[N]O=nn O", "[N]U=nn U", "[NI]=nn I", "[NE]=nn E" + ], + 'O': [ + "[O]=O", "[OR]=O rr", "[ON]=O nn", "[OM]=O mm", "[OS]=O ss" + ], + 'P': [ + " [P]=pp", "[P]A=pp aa", "[P]O=pp O", "[P]U=pp U", "[PI]=pp I", "[PE]=pp E" + ], + 'Q': [ + " [Q]=kw", "[Q]A=kw aa", "[Q]O=kw O", "[Q]U=kw U", "[QI]=kw I", "[QE]=kw E" + ], + 'R': [ + " [R]=rr", "[R]A=rr aa", "[R]O=rr O", "[R]U=rr U", "[RI]=rr I", "[RE]=rr E" + ], + 'S': [ + " [S]=ss", "[S]A=ss aa", "[S]O=ss O", "[S]U=ss U", "[SI]=ss I", "[SE]=ss E" + ], + 'T': [ + " [T]=tt", "[T]A=tt aa", "[T]O=tt O", "[T]U=tt U", "[TI]=tt I", "[TE]=tt E" + ], + 'U': [ + "[U]=U", "[UN]=U nn", "[UM]=U mm", "[UR]=U rr", "[US]=U ss" + ], + 'V': [ + " [V]=vv", "[V]A=vv aa", "[V]O=vv O", "[V]U=vv U", "[VI]=vv I", "[VE]=vv E" + ], + 'Z': [ + " [Z]=zz", "[Z]A=zz aa", "[Z]O=zz O", "[Z]U=zz U", "[ZI]=zz I", "[ZE]=zz E" + ] + }; + + const ops = { + '#': '[AEIOUY]+', // One or more vowels AEIOUY + '.': '[BDVGJLMNRWZ]', // One voiced consonant BDVGJLMNRWZ + '%': '(?:ER|E|ES|ED|ING|ELY)', // One of ER, E, ES, ED, ING, ELY + '&': '(?:[SCGZXJ]|CH|SH)', // One of S, C, G, Z, X, J, CH, SH + '@': '(?:[TSRDLZNJ]|TH|CH|SH)', // One of T, S, R, D, L, Z, N, J, TH, CH, SH + '^': '[BCDFGHJKLMNPQRSTVWXZ]', // One consonant BCDFGHJKLMNPQRSTVWXZ + '+': '[EIY]', // One of E, I, Y + ':': '[BCDFGHJKLMNPQRSTVWXZ]*', // Zero or more consonants BCDFGHJKLMNPQRSTVWXZ + ' ': '\\b' // Start/end of the word + }; + + Object.keys(this.rules).forEach(key => { + this.rules[key] = this.rules[key].map(rule => { + const posL = rule.indexOf('['); + const posR = rule.indexOf(']'); + const posE = rule.indexOf('='); + const strLeft = rule.substring(0, posL); + const strLetters = rule.substring(posL + 1, posR); + const strRight = rule.substring(posR + 1, posE); + const strVisemes = rule.substring(posE + 1); + + const o = { regex: '', move: 0, visemes: [] }; + + let exp = ''; + exp += [...strLeft].map(x => ops[x] || x).join(''); + const ctxLetters = [...strLetters]; + ctxLetters[0] = ctxLetters[0].toLowerCase(); + exp += ctxLetters.join(''); + o.move = ctxLetters.length; + exp += [...strRight].map(x => ops[x] || x).join(''); + o.regex = new RegExp(exp); + + if (strVisemes.length) { + strVisemes.split(' ').forEach(viseme => { + o.visemes.push(viseme); + }); + } + + return o; + }); + }); + + this.visemeDurations = { + 'aa': 0.95, 'E': 0.90, 'I': 0.92, 'O': 0.96, 'U': 0.95, 'PP': 1.08, + 'SS': 1.23, 'TH': 1, 'DD': 1.05, 'FF': 1.00, 'kk': 1.21, 'nn': 0.88, + 'RR': 0.88, 'DD': 1.05, 'sil': 1 + }; + + this.specialDurations = { ' ': 1, ',': 3, '-': 0.5, "'": 0.5 }; + + this.digits = ['zero', 'uno', 'due', 'tre', 'quattro', 'cinque', 'sei', 'sette', 'otto', 'nove']; + this.ones = ['', 'uno', 'due', 'tre', 'quattro', 'cinque', 'sei', 'sette', 'otto', 'nove']; + this.tens = ['', '', 'venti', 'trenta', 'quaranta', 'cinquanta', 'sessanta', 'settanta', 'ottanta', 'novanta']; + this.teens = ['dieci', 'undici', 'dodici', 'tredici', 'quattordici', 'quindici', 'sedici', 'diciassette', 'diciotto', 'diciannove']; + + this.symbols = { + '%': 'percento', '€': 'euro', '&': 'e', '+': 'più', '$': 'dollari', '-': 'meno', '/': 'diviso', '*': 'per', ':': 'due punti', ';': 'punto e virgola' + }; + this.symbolsReg = /[%€&\+\$]/g; + } + + convert_digit_by_digit(num) { + num = String(num).split(""); + let numWords = ""; + for (let m = 0; m < num.length; m++) { + numWords += this.digits[num[m]] + " "; + } + numWords = numWords.substring(0, numWords.length - 1); + return numWords; + } + + convert_sets_of_two(num) { + let firstNumHalf = String(num).substring(0, 2); + let secondNumHalf = String(num).substring(2, 4); + let numWords = this.convert_tens(firstNumHalf); + numWords += " " + this.convert_tens(secondNumHalf); + return numWords; + } + + convert_millions(num) { + if (num >= 1000000) { + return this.convert_millions(Math.floor(num / 1000000)) + " milioni " + this.convert_thousands(num % 1000000); + } else { + return this.convert_thousands(num); + } + } + + convert_thousands(num) { + if (num >= 1000) { + return this.convert_hundreds(Math.floor(num / 1000)) + " mila " + this.convert_hundreds(num % 1000); + } else { + return this.convert_hundreds(num); + } + } + + convert_hundreds(num) { + if (num > 99) { + return this.ones[Math.floor(num / 100)] + " cento " + this.convert_tens(num % 100); + } else { + return this.convert_tens(num); + } + } + + convert_tens(num) { + if (num < 10) return this.ones[num]; + else if (num >= 10 && num < 20) { + return this.teens[num - 10]; + } else { + return this.tens[Math.floor(num / 10)] + " " + this.ones[num % 10]; + } + } + + convertNumberToWords(num) { + if (num == 0) { + return "zero"; + } else if ((num < 1000 && num > 99) || (num > 10000 && num < 1000000)) { + return this.convert_digit_by_digit(num); + } else if ((num > 1000 && num < 2000) || (num > 2009 && num < 3000)) { + return this.convert_sets_of_two(num); + } else { + return this.convert_millions(num); + } + } + + /** + * Preprocess text: + * - convert symbols to words + * - convert numbers to words + * - filter out characters that should be left unspoken + * @param {string} s Text + * @return {string} Pre-processsed text. + */ + preProcessText(s) { + return s.replace('/[#_*\":;]/g', '') + .replace(this.symbolsReg, (symbol) => { + return ' ' + this.symbols[symbol] + ' '; + }) + .replace(/(\d)\,(\d)/g, '$1 punto $2') // Number separator + .replace(/\d+/g, this.convertNumberToWords.bind(this)) // Numbers to words + .replace(/(\D)\1\1+/g, "$1$1") // max 2 repeating chars + .replaceAll(' ', ' ') // Only one repeating space + .normalize('NFD').replace(/[\u0300-\u036f]/g, '').normalize('NFC') // Remove non-Italian diacritics + .trim(); + } + + /** + * Convert word to Oculus LipSync Visemes and durations + * @param {string} w Text + * @return {Object} Oculus LipSync Visemes and durations. + */ + wordsToVisemes(w) { + let o = { words: w.toUpperCase(), visemes: [], times: [], durations: [], i: 0 }; + let t = 0; + + const chars = [...o.words]; + while (o.i < chars.length) { + const c = chars[o.i]; + const ruleset = this.rules[c]; + if (ruleset) { + for (let i = 0; i < ruleset.length; i++) { + const rule = ruleset[i]; + const test = o.words.substring(0, o.i) + c.toLowerCase() + o.words.substring(o.i + 1); + let matches = test.match(rule.regex); + if (matches) { + rule.visemes.forEach(viseme => { + if (o.visemes.length && o.visemes[o.visemes.length - 1] === viseme) { + const d = 0.7 * (this.visemeDurations[viseme] || 1); + o.durations[o.durations.length - 1] += d; + t += d; + } else { + const d = this.visemeDurations[viseme] || 1; + o.visemes.push(viseme); + o.times.push(t); + o.durations.push(d); + t += d; + } + }) + o.i += rule.move; + break; + } + } + } else { + o.i++; + t += this.specialDurations[c] || 0; + } + } + + return o; + } + +} + +export { LipsyncIt }; diff --git a/modules/talkinghead.mjs b/modules/talkinghead.mjs index 47c74d5..97de3f3 100755 --- a/modules/talkinghead.mjs +++ b/modules/talkinghead.mjs @@ -137,9 +137,7 @@ class TalkingHead { this.poseTemplates = { 'side': { standing: true, - props: { - 'Hips.position':{x:0, y:1, z:0}, 'Hips.rotation':{x:-0.003, y:-0.017, z:0.1}, 'Spine.rotation':{x:-0.103, y:-0.002, z:-0.063}, 'Spine1.rotation':{x:0.042, y:-0.02, z:-0.069}, 'Spine2.rotation':{x:0.131, y:-0.012, z:-0.065}, 'Neck.rotation':{x:0.027, y:0.006, z:0}, 'Head.rotation':{x:0.077, y:-0.065, z:0}, 'LeftShoulder.rotation':{x:1.599, y:0.084, z:-1.77}, 'LeftArm.rotation':{x:1.364, y:0.052, z:-0.044}, 'LeftForeArm.rotation':{x:0.002, y:-0.007, z:0.331}, 'LeftHand.rotation':{x:0.104, y:-0.067, z:-0.174}, 'LeftHandThumb1.rotation':{x:0.231, y:0.258, z:0.355}, 'LeftHandThumb2.rotation':{x:-0.106, y:-0.339, z:-0.454}, 'LeftHandThumb3.rotation':{x:-0.02, y:-0.142, z:-0.004}, 'LeftHandIndex1.rotation':{x:0.148, y:0.032, z:-0.069}, 'LeftHandIndex2.rotation':{x:0.326, y:-0.049, z:-0.029}, 'LeftHandIndex3.rotation':{x:0.247, y:-0.053, z:-0.073}, 'LeftHandMiddle1.rotation':{x:0.238, y:-0.057, z:-0.089}, 'LeftHandMiddle2.rotation':{x:0.469, y:-0.036, z:-0.081}, 'LeftHandMiddle3.rotation':{x:0.206, y:-0.015, z:-0.017}, 'LeftHandRing1.rotation':{x:0.187, y:-0.118, z:-0.157}, 'LeftHandRing2.rotation':{x:0.579, y:0.02, z:-0.097}, 'LeftHandRing3.rotation':{x:0.272, y:0.021, z:-0.063}, 'LeftHandPinky1.rotation':{x:0.405, y:-0.182, z:-0.138}, 'LeftHandPinky2.rotation':{x:0.613, y:0.128, z:-0.144}, 'LeftHandPinky3.rotation':{x:0.268, y:0.094, z:-0.081}, 'RightShoulder.rotation':{x:1.541, y:0.192, z:1.775}, 'RightArm.rotation':{x:1.273, y:-0.352, z:-0.067}, 'RightForeArm.rotation':{x:-0.011, y:-0.031, z:-0.357}, 'RightHand.rotation':{x:-0.008, y:0.312, z:-0.028}, 'RightHandThumb1.rotation':{x:0.23, y:-0.258, z:-0.355}, 'RightHandThumb2.rotation':{x:-0.107, y:0.339, z:0.454}, 'RightHandThumb3.rotation':{x:-0.02, y:0.142, z:0.004}, 'RightHandIndex1.rotation':{x:0.148, y:-0.031, z:0.069}, 'RightHandIndex2.rotation':{x:0.326, y:0.049, z:0.029}, 'RightHandIndex3.rotation':{x:0.247, y:0.053, z:0.073}, 'RightHandMiddle1.rotation':{x:0.237, y:0.057, z:0.089}, 'RightHandMiddle2.rotation':{x:0.469, y:0.036, z:0.081}, 'RightHandMiddle3.rotation':{x:0.206, y:0.015, z:0.017}, 'RightHandRing1.rotation':{x:0.204, y:0.086, z:0.135}, 'RightHandRing2.rotation':{x:0.579, y:-0.02, z:0.098}, 'RightHandRing3.rotation':{x:0.272, y:-0.021, z:0.063}, 'RightHandPinky1.rotation':{x:0.404, y:0.182, z:0.137}, 'RightHandPinky2.rotation':{x:0.613, y:-0.128, z:0.144}, 'RightHandPinky3.rotation':{x:0.268, y:-0.094, z:0.081}, 'LeftUpLeg.rotation':{x:0.096, y:0.209, z:2.983}, 'LeftLeg.rotation':{x:-0.053, y:0.042, z:-0.017}, 'LeftFoot.rotation':{x:1.091, y:0.15, z:0.026}, 'LeftToeBase.rotation':{x:0.469, y:-0.07, z:-0.015}, 'RightUpLeg.rotation':{x:-0.307, y:-0.219, z:2.912}, 'RightLeg.rotation':{x:-0.359, y:0.164, z:0.015}, 'RightFoot.rotation':{x:1.035, y:0.11, z:0.005}, 'RightToeBase.rotation':{x:0.467, y:0.07, z:0.015} - } + props: {'Spine.rotation':{x:-0.017, y:0.011, z:0.027}, 'Spine1.rotation':{x:0.042, y:0.024, z:0.052}, 'Spine2.rotation':{x:0.042, y:0.024, z:0.052}, 'LeftArm.rotation':{x:0.98, y:0.397, z:0.013}, 'LeftHand.rotation':{x:-0.152, y:-0.27, z:0.203}, 'RightArm.rotation':{x:1.01, y:-0.494, z:0.099}, 'RightHand.rotation':{x:-0.366, y:0.481, z:-0.072}, 'LeftUpLeg.rotation':{x:-0.245, y:0.032, z:-3.005}, 'LeftLeg.rotation':{x:-0.28, y:-0.002, z:0.014}, 'LeftFoot.rotation':{x:0.935, y:-0.194, z:0.171}, 'RightUpLeg.rotation':{x:-0.028, y:-0.122, z:-3.019}, 'Hips.position':{x:0.001, y:0, z:0.021}, 'Hips.rotation':{x:1.557, y:-0.081, z:-0.048}, 'Neck.rotation':{x:-0.143, y:0.004, z:-0.006}, 'Head.rotation':{x:0.075, y:0.01, z:-0.081}, 'LeftShoulder.rotation':{x:1.63, y:-0.464, z:-1.463}, 'LeftForeArm.rotation':{x:0.007, y:-0.008, z:0.149}, 'LeftHandIndex1.rotation':{x:0.238, y:-0.14, z:-0.056}, 'LeftHandIndex2.rotation':{x:0.199, y:0.005, z:-0.016}, 'LeftHandMiddle1.rotation':{x:0.184, y:-0.017, z:0.001}, 'LeftHandMiddle2.rotation':{x:0.18, y:0.001, z:0.012}, 'LeftHandRing1.rotation':{x:0.329, y:0.029, z:-0.002}, 'LeftHandRing2.rotation':{x:0.182, y:-0.002, z:0.004}, 'LeftHandPinky1.rotation':{x:0.488, y:0.105, z:-0.054}, 'LeftHandPinky2.rotation':{x:0.284, y:0.008, z:0.06}, 'RightShoulder.rotation':{x:1.605, y:0.415, z:1.527}, 'RightForeArm.rotation':{x:0.012, y:0.015, z:-0.175}, 'RightHandIndex1.rotation':{x:0.246, y:0.117, z:-0.018}, 'RightHandIndex2.rotation':{x:0.091, y:0.001, z:0.009}, 'RightHandMiddle1.rotation':{x:0.24, y:-0.003, z:-0.014}, 'RightHandMiddle2.rotation':{x:0.182, y:0, z:-0.013}, 'RightHandRing1.rotation':{x:0.355, y:-0.006, z:-0.055}, 'RightHandRing2.rotation':{x:0.163, y:0.004, z:-0.011}, 'RightHandPinky1.rotation':{x:0.386, y:-0.058, z:-0.046}, 'RightHandPinky2.rotation':{x:0.216, y:0.003, z:-0.079}, 'LeftToeBase.rotation':{x:0.67, y:-0.094, z:0.112}, 'RightLeg.rotation':{x:-0.177, y:0.004, z:-0.019}, 'RightFoot.rotation':{x:1.032, y:0.028, z:-0.166}, 'RightToeBase.rotation':{x:0, y:0, z:0}, 'LeftHandThumb1.rotation':{x:0.233, y:0.257, z:0.355}, 'LeftHandThumb2.rotation':{x:-0.105, y:-0.338, z:-0.452}, 'LeftHandThumb3.rotation':{x:-0.02, y:-0.141, z:-0.004}, 'LeftHandIndex3.rotation':{x:0.246, y:-0.053, z:-0.073}, 'LeftHandMiddle3.rotation':{x:0.205, y:-0.015, z:-0.017}, 'LeftHandRing3.rotation':{x:0.271, y:0.021, z:-0.063}, 'LeftHandPinky3.rotation':{x:0.267, y:0.094, z:-0.081}, 'RightHandThumb1.rotation':{x:0.23, y:-0.256, z:-0.355}, 'RightHandThumb2.rotation':{x:-0.106, y:0.338, z:0.452}, 'RightHandThumb3.rotation':{x:-0.02, y:0.141, z:0.004}, 'RightHandIndex3.rotation':{x:0.246, y:0.053, z:0.073}, 'RightHandMiddle3.rotation':{x:0.205, y:0.015, z:0.017}, 'RightHandRing3.rotation':{x:0.271, y:-0.021, z:0.063}, 'RightHandPinky3.rotation':{x:0.267, y:-0.094, z:0.081}} }, 'hip':{ @@ -172,9 +170,7 @@ class TalkingHead { 'straight':{ standing: true, - props: { - 'Hips.position':{x:0, y:0.989, z:0.001}, 'Hips.rotation':{x:0.047, y:0.007, z:-0.007}, 'Spine.rotation':{x:-0.143, y:-0.007, z:0.005}, 'Spine1.rotation':{x:-0.043, y:-0.014, z:0.012}, 'Spine2.rotation':{x:0.072, y:-0.013, z:0.013}, 'Neck.rotation':{x:0.048, y:-0.003, z:0.012}, 'Head.rotation':{x:0.05, y:-0.02, z:-0.017}, 'LeftShoulder.rotation':{x:1.62, y:-0.166, z:-1.605}, 'LeftArm.rotation':{x:1.275, y:0.544, z:-0.092}, 'LeftForeArm.rotation':{x:0, y:0, z:0.302}, 'LeftHand.rotation':{x:-0.225, y:-0.154, z:0.11}, 'LeftHandThumb1.rotation':{x:0.435, y:-0.044, z:0.457}, 'LeftHandThumb2.rotation':{x:-0.028, y:0.002, z:-0.246}, 'LeftHandThumb3.rotation':{x:-0.236, y:-0.025, z:0.113}, 'LeftHandIndex1.rotation':{x:0.218, y:0.008, z:-0.081}, 'LeftHandIndex2.rotation':{x:0.165, y:-0.001, z:-0.017}, 'LeftHandIndex3.rotation':{x:0.165, y:-0.001, z:-0.017}, 'LeftHandMiddle1.rotation':{x:0.235, y:-0.011, z:-0.065}, 'LeftHandMiddle2.rotation':{x:0.182, y:-0.002, z:-0.019}, 'LeftHandMiddle3.rotation':{x:0.182, y:-0.002, z:-0.019}, 'LeftHandRing1.rotation':{x:0.316, y:-0.017, z:0.008}, 'LeftHandRing2.rotation':{x:0.253, y:-0.003, z:-0.026}, 'LeftHandRing3.rotation':{x:0.255, y:-0.003, z:-0.026}, 'LeftHandPinky1.rotation':{x:0.336, y:-0.062, z:0.088}, 'LeftHandPinky2.rotation':{x:0.276, y:-0.004, z:-0.028}, 'LeftHandPinky3.rotation':{x:0.276, y:-0.004, z:-0.028}, 'RightShoulder.rotation':{x:1.615, y:0.064, z:1.53}, 'RightArm.rotation':{x:1.313, y:-0.424, z:0.131}, 'RightForeArm.rotation':{x:0, y:0, z:-0.317}, 'RightHand.rotation':{x:-0.158, y:-0.639, z:-0.196}, 'RightHandThumb1.rotation':{x:0.44, y:0.048, z:-0.549}, 'RightHandThumb2.rotation':{x:-0.056, y:-0.008, z:0.274}, 'RightHandThumb3.rotation':{x:-0.258, y:0.031, z:-0.095}, 'RightHandIndex1.rotation':{x:0.169, y:-0.011, z:0.105}, 'RightHandIndex2.rotation':{x:0.134, y:0.001, z:0.011}, 'RightHandIndex3.rotation':{x:0.134, y:0.001, z:0.011}, 'RightHandMiddle1.rotation':{x:0.288, y:0.014, z:0.092}, 'RightHandMiddle2.rotation':{x:0.248, y:0.003, z:0.02}, 'RightHandMiddle3.rotation':{x:0.249, y:0.003, z:0.02}, 'RightHandRing1.rotation':{x:0.369, y:0.019, z:0.006}, 'RightHandRing2.rotation':{x:0.321, y:0.004, z:0.026}, 'RightHandRing3.rotation':{x:0.323, y:0.004, z:0.026}, 'RightHandPinky1.rotation':{x:0.468, y:0.085, z:-0.03}, 'RightHandPinky2.rotation':{x:0.427, y:0.007, z:0.034}, 'RightHandPinky3.rotation':{x:0.142, y:0.001, z:0.012}, 'LeftUpLeg.rotation':{x:-0.077, y:-0.058, z:3.126}, 'LeftLeg.rotation':{x:-0.252, y:0.001, z:-0.018}, 'LeftFoot.rotation':{x:1.315, y:-0.064, z:0.315}, 'LeftToeBase.rotation':{x:0.577, y:-0.07, z:-0.009}, 'RightUpLeg.rotation':{x:-0.083, y:-0.032, z:3.124}, 'RightLeg.rotation':{x:-0.272, y:-0.003, z:0.021}, 'RightFoot.rotation':{x:1.342, y:0.076, z:-0.222}, 'RightToeBase.rotation':{x:0.44, y:0.069, z:0.016} - } + props: {'Spine.rotation':{x:-0.017, y:0.011, z:0.027}, 'Spine1.rotation':{x:0.042, y:0.024, z:0.052}, 'Spine2.rotation':{x:0.042, y:0.024, z:0.052}, 'LeftArm.rotation':{x:0.98, y:0.397, z:0.013}, 'LeftHand.rotation':{x:-0.152, y:-0.27, z:0.203}, 'RightArm.rotation':{x:1.01, y:-0.494, z:0.099}, 'RightHand.rotation':{x:-0.366, y:0.481, z:-0.072}, 'LeftUpLeg.rotation':{x:-0.245, y:0.032, z:-3.005}, 'LeftLeg.rotation':{x:-0.28, y:-0.002, z:0.014}, 'LeftFoot.rotation':{x:0.935, y:-0.194, z:0.171}, 'RightUpLeg.rotation':{x:-0.028, y:-0.122, z:-3.019}, 'Hips.position':{x:0.001, y:0, z:0.021}, 'Hips.rotation':{x:1.557, y:-0.081, z:-0.048}, 'Neck.rotation':{x:-0.143, y:0.004, z:-0.006}, 'Head.rotation':{x:0.075, y:0.01, z:-0.081}, 'LeftShoulder.rotation':{x:1.63, y:-0.464, z:-1.463}, 'LeftForeArm.rotation':{x:0.007, y:-0.008, z:0.149}, 'LeftHandIndex1.rotation':{x:0.238, y:-0.14, z:-0.056}, 'LeftHandIndex2.rotation':{x:0.199, y:0.005, z:-0.016}, 'LeftHandMiddle1.rotation':{x:0.184, y:-0.017, z:0.001}, 'LeftHandMiddle2.rotation':{x:0.18, y:0.001, z:0.012}, 'LeftHandRing1.rotation':{x:0.329, y:0.029, z:-0.002}, 'LeftHandRing2.rotation':{x:0.182, y:-0.002, z:0.004}, 'LeftHandPinky1.rotation':{x:0.488, y:0.105, z:-0.054}, 'LeftHandPinky2.rotation':{x:0.284, y:0.008, z:0.06}, 'RightShoulder.rotation':{x:1.605, y:0.415, z:1.527}, 'RightForeArm.rotation':{x:0.012, y:0.015, z:-0.175}, 'RightHandIndex1.rotation':{x:0.246, y:0.117, z:-0.018}, 'RightHandIndex2.rotation':{x:0.091, y:0.001, z:0.009}, 'RightHandMiddle1.rotation':{x:0.24, y:-0.003, z:-0.014}, 'RightHandMiddle2.rotation':{x:0.182, y:0, z:-0.013}, 'RightHandRing1.rotation':{x:0.355, y:-0.006, z:-0.055}, 'RightHandRing2.rotation':{x:0.163, y:0.004, z:-0.011}, 'RightHandPinky1.rotation':{x:0.386, y:-0.058, z:-0.046}, 'RightHandPinky2.rotation':{x:0.216, y:0.003, z:-0.079}, 'LeftToeBase.rotation':{x:0.67, y:-0.094, z:0.112}, 'RightLeg.rotation':{x:-0.177, y:0.004, z:-0.019}, 'RightFoot.rotation':{x:1.032, y:0.028, z:-0.166}, 'RightToeBase.rotation':{x:0, y:0, z:0}, 'LeftHandThumb1.rotation':{x:0.233, y:0.257, z:0.355}, 'LeftHandThumb2.rotation':{x:-0.105, y:-0.338, z:-0.452}, 'LeftHandThumb3.rotation':{x:-0.02, y:-0.141, z:-0.004}, 'LeftHandIndex3.rotation':{x:0.246, y:-0.053, z:-0.073}, 'LeftHandMiddle3.rotation':{x:0.205, y:-0.015, z:-0.017}, 'LeftHandRing3.rotation':{x:0.271, y:0.021, z:-0.063}, 'LeftHandPinky3.rotation':{x:0.267, y:0.094, z:-0.081}, 'RightHandThumb1.rotation':{x:0.23, y:-0.256, z:-0.355}, 'RightHandThumb2.rotation':{x:-0.106, y:0.338, z:0.452}, 'RightHandThumb3.rotation':{x:-0.02, y:0.141, z:0.004}, 'RightHandIndex3.rotation':{x:0.246, y:0.053, z:0.073}, 'RightHandMiddle3.rotation':{x:0.205, y:0.015, z:0.017}, 'RightHandRing3.rotation':{x:0.271, y:-0.021, z:0.063}, 'RightHandPinky3.rotation':{x:0.267, y:-0.094, z:0.081}} }, 'wide':{