xr_face_modifier_3d.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616
  1. /**************************************************************************/
  2. /* xr_face_modifier_3d.cpp */
  3. /**************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /**************************************************************************/
  8. /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
  9. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /**************************************************************************/
  30. #include "xr_face_modifier_3d.h"
  31. #include "servers/xr/xr_face_tracker.h"
  32. #include "servers/xr_server.h"
  33. // This method takes the name of a mesh blend shape and returns the
  34. // corresponding XRFaceTracker blend shape. If no match is
  35. // found then the function returns -1.
  36. static int find_face_blend_shape(const StringName &p_name) {
  37. // Entry for blend shape name table.
  38. struct blend_map_entry {
  39. int blend;
  40. const char *name[4];
  41. };
  42. // Table of blend shape names.
  43. //
  44. // This table consists of the XRFaceTracker blend shape and
  45. // the corresponding names (lowercase and no underscore) of:
  46. // - The Unified Expression blend shape name.
  47. // - The ARKit blend shape name (if present and different).
  48. // - The SRanipal blend shape name (if present and different).
  49. // - The Meta blend shape name (if present and different).
  50. static constexpr blend_map_entry blend_map[] = {
  51. { XRFaceTracker::FT_EYE_LOOK_OUT_RIGHT,
  52. { "eyelookoutright", "eyerightright", "eyeslookoutr" } },
  53. { XRFaceTracker::FT_EYE_LOOK_IN_RIGHT,
  54. { "eyelookinright", "eyerightleft", "eyeslookinr" } },
  55. { XRFaceTracker::FT_EYE_LOOK_UP_RIGHT,
  56. { "eyelookupright", "eyerightlookup", "eyeslookupr" } },
  57. { XRFaceTracker::FT_EYE_LOOK_DOWN_RIGHT,
  58. { "eyelookdownright", "eyerightlookdown", "eyeslookdownr" } },
  59. { XRFaceTracker::FT_EYE_LOOK_OUT_LEFT,
  60. { "eyelookoutleft", "eyeleftleft", "eyeslookoutl" } },
  61. { XRFaceTracker::FT_EYE_LOOK_IN_LEFT,
  62. { "eyelookinleft", "eyeleftright", "eyeslookinl" } },
  63. { XRFaceTracker::FT_EYE_LOOK_UP_LEFT,
  64. { "eyelookupleft", "eyeleftlookup", "eyeslookupl" } },
  65. { XRFaceTracker::FT_EYE_LOOK_DOWN_LEFT,
  66. { "eyelookdownleft", "eyeleftlookdown", "eyeslookdownl" } },
  67. { XRFaceTracker::FT_EYE_CLOSED_RIGHT,
  68. { "eyeclosedright", "eyeblinkright", "eyerightblink", "eyesclosedr" } },
  69. { XRFaceTracker::FT_EYE_CLOSED_LEFT,
  70. { "eyeclosedleft", "eyeblinkleft", "eyeleftblink", "eyesclosedl" } },
  71. { XRFaceTracker::FT_EYE_SQUINT_RIGHT,
  72. { "eyesquintright", "eyessquintr" } },
  73. { XRFaceTracker::FT_EYE_SQUINT_LEFT,
  74. { "eyesquintleft", "eyessquintl" } },
  75. { XRFaceTracker::FT_EYE_WIDE_RIGHT,
  76. { "eyewideright", "eyerightwide", "eyeswidenr" } },
  77. { XRFaceTracker::FT_EYE_WIDE_LEFT,
  78. { "eyewideleft", "eyeleftwide", "eyeswidenl" } },
  79. { XRFaceTracker::FT_EYE_DILATION_RIGHT,
  80. { "eyedilationright", "eyerightdilation" } },
  81. { XRFaceTracker::FT_EYE_DILATION_LEFT,
  82. { "eyedilationleft", "eyeleftdilation" } },
  83. { XRFaceTracker::FT_EYE_CONSTRICT_RIGHT,
  84. { "eyeconstrictright", "eyerightconstrict" } },
  85. { XRFaceTracker::FT_EYE_CONSTRICT_LEFT,
  86. { "eyeconstrictleft", "eyeleftconstrict" } },
  87. { XRFaceTracker::FT_BROW_PINCH_RIGHT,
  88. { "browpinchright" } },
  89. { XRFaceTracker::FT_BROW_PINCH_LEFT,
  90. { "browpinchleft" } },
  91. { XRFaceTracker::FT_BROW_LOWERER_RIGHT,
  92. { "browlowererright" } },
  93. { XRFaceTracker::FT_BROW_LOWERER_LEFT,
  94. { "browlowererleft" } },
  95. { XRFaceTracker::FT_BROW_INNER_UP_RIGHT,
  96. { "browinnerupright", "innerbrowraiserr" } },
  97. { XRFaceTracker::FT_BROW_INNER_UP_LEFT,
  98. { "browinnerupleft", "innerbrowraiserl" } },
  99. { XRFaceTracker::FT_BROW_OUTER_UP_RIGHT,
  100. { "browouterupright", "outerbrowraiserr" } },
  101. { XRFaceTracker::FT_BROW_OUTER_UP_LEFT,
  102. { "browouterupleft", "outerbrowraiserl" } },
  103. { XRFaceTracker::FT_NOSE_SNEER_RIGHT,
  104. { "nosesneerright", "nosewrinklerr" } },
  105. { XRFaceTracker::FT_NOSE_SNEER_LEFT,
  106. { "nosesneerleft", "nosewrinklerl" } },
  107. { XRFaceTracker::FT_NASAL_DILATION_RIGHT,
  108. { "nasaldilationright" } },
  109. { XRFaceTracker::FT_NASAL_DILATION_LEFT,
  110. { "nasaldilationleft" } },
  111. { XRFaceTracker::FT_NASAL_CONSTRICT_RIGHT,
  112. { "nasalconstrictright" } },
  113. { XRFaceTracker::FT_NASAL_CONSTRICT_LEFT,
  114. { "nasalconstrictleft" } },
  115. { XRFaceTracker::FT_CHEEK_SQUINT_RIGHT,
  116. { "cheeksquintright", "cheekraiserr" } },
  117. { XRFaceTracker::FT_CHEEK_SQUINT_LEFT,
  118. { "cheeksquintleft", "cheekraiserl" } },
  119. { XRFaceTracker::FT_CHEEK_PUFF_RIGHT,
  120. { "cheekpuffright", "cheekpuffr" } },
  121. { XRFaceTracker::FT_CHEEK_PUFF_LEFT,
  122. { "cheekpuffleft", "cheekpuffl" } },
  123. { XRFaceTracker::FT_CHEEK_SUCK_RIGHT,
  124. { "cheeksuckright", "cheeksuckr" } },
  125. { XRFaceTracker::FT_CHEEK_SUCK_LEFT,
  126. { "cheeksuckleft", "cheeksuckl" } },
  127. { XRFaceTracker::FT_JAW_OPEN,
  128. { "jawopen", "jawdrop" } },
  129. { XRFaceTracker::FT_MOUTH_CLOSED,
  130. { "mouthclosed", "mouthclose", "mouthapeshape", "lipstoward" } },
  131. { XRFaceTracker::FT_JAW_RIGHT,
  132. { "jawright", "jawsidewaysright" } },
  133. { XRFaceTracker::FT_JAW_LEFT,
  134. { "jawleft", "jawsidewaysleft" } },
  135. { XRFaceTracker::FT_JAW_FORWARD,
  136. { "jawforward", "jawthrust" } },
  137. { XRFaceTracker::FT_JAW_BACKWARD,
  138. { "jawbackward" } },
  139. { XRFaceTracker::FT_JAW_CLENCH,
  140. { "jawclench" } },
  141. { XRFaceTracker::FT_JAW_MANDIBLE_RAISE,
  142. { "jawmandibleraise" } },
  143. { XRFaceTracker::FT_LIP_SUCK_UPPER_RIGHT,
  144. { "lipsuckupperright", "lipsuckrt" } },
  145. { XRFaceTracker::FT_LIP_SUCK_UPPER_LEFT,
  146. { "lipsuckupperleft", "lipsucklt" } },
  147. { XRFaceTracker::FT_LIP_SUCK_LOWER_RIGHT,
  148. { "lipsucklowerright", "lipsuckrb" } },
  149. { XRFaceTracker::FT_LIP_SUCK_LOWER_LEFT,
  150. { "lipsucklowerleft", "lipsucklb" } },
  151. { XRFaceTracker::FT_LIP_SUCK_CORNER_RIGHT,
  152. { "lipsuckcornerright" } },
  153. { XRFaceTracker::FT_LIP_SUCK_CORNER_LEFT,
  154. { "lipsuckcornerleft" } },
  155. { XRFaceTracker::FT_LIP_FUNNEL_UPPER_RIGHT,
  156. { "lipfunnelupperright", "lipfunnelerrt" } },
  157. { XRFaceTracker::FT_LIP_FUNNEL_UPPER_LEFT,
  158. { "lipfunnelupperleft", "lipfunnelerlt" } },
  159. { XRFaceTracker::FT_LIP_FUNNEL_LOWER_RIGHT,
  160. { "lipfunnellowerright", "lipsuckrb" } },
  161. { XRFaceTracker::FT_LIP_FUNNEL_LOWER_LEFT,
  162. { "lipfunnellowerleft", "lipsucklb" } },
  163. { XRFaceTracker::FT_LIP_PUCKER_UPPER_RIGHT,
  164. { "lippuckerupperright" } },
  165. { XRFaceTracker::FT_LIP_PUCKER_UPPER_LEFT,
  166. { "lippuckerupperleft" } },
  167. { XRFaceTracker::FT_LIP_PUCKER_LOWER_RIGHT,
  168. { "lippuckerlowerright" } },
  169. { XRFaceTracker::FT_LIP_PUCKER_LOWER_LEFT,
  170. { "lippuckerlowerleft" } },
  171. { XRFaceTracker::FT_MOUTH_UPPER_UP_RIGHT,
  172. { "mouthupperupright", "upperlipraiserr" } },
  173. { XRFaceTracker::FT_MOUTH_UPPER_UP_LEFT,
  174. { "mouthupperupleft", "upperlipraiserl" } },
  175. { XRFaceTracker::FT_MOUTH_LOWER_DOWN_RIGHT,
  176. { "mouthlowerdownright", "mouthlowerupright", "lowerlipdepressorr" } },
  177. { XRFaceTracker::FT_MOUTH_LOWER_DOWN_LEFT,
  178. { "mouthlowerdownleft", "mouthlowerupleft", "lowerlipdepressorl" } },
  179. { XRFaceTracker::FT_MOUTH_UPPER_DEEPEN_RIGHT,
  180. { "mouthupperdeepenright" } },
  181. { XRFaceTracker::FT_MOUTH_UPPER_DEEPEN_LEFT,
  182. { "mouthupperdeepenleft" } },
  183. { XRFaceTracker::FT_MOUTH_UPPER_RIGHT,
  184. { "mouthupperright" } },
  185. { XRFaceTracker::FT_MOUTH_UPPER_LEFT,
  186. { "mouthupperleft" } },
  187. { XRFaceTracker::FT_MOUTH_LOWER_RIGHT,
  188. { "mouthlowerright" } },
  189. { XRFaceTracker::FT_MOUTH_LOWER_LEFT,
  190. { "mouthlowerleft" } },
  191. { XRFaceTracker::FT_MOUTH_CORNER_PULL_RIGHT,
  192. { "mouthcornerpullright" } },
  193. { XRFaceTracker::FT_MOUTH_CORNER_PULL_LEFT,
  194. { "mouthcornerpullleft" } },
  195. { XRFaceTracker::FT_MOUTH_CORNER_SLANT_RIGHT,
  196. { "mouthcornerslantright" } },
  197. { XRFaceTracker::FT_MOUTH_CORNER_SLANT_LEFT,
  198. { "mouthcornerslantleft" } },
  199. { XRFaceTracker::FT_MOUTH_FROWN_RIGHT,
  200. { "mouthfrownright", "lipcornerdepressorr" } },
  201. { XRFaceTracker::FT_MOUTH_FROWN_LEFT,
  202. { "mouthfrownleft", "lipcornerdepressorl" } },
  203. { XRFaceTracker::FT_MOUTH_STRETCH_RIGHT,
  204. { "mouthstretchright", "lipstretcherr" } },
  205. { XRFaceTracker::FT_MOUTH_STRETCH_LEFT,
  206. { "mouthstretchleft", "lipstretcherl" } },
  207. { XRFaceTracker::FT_MOUTH_DIMPLE_RIGHT,
  208. { "mouthdimplerright", "mouthdimpleright", "dimplerr" } },
  209. { XRFaceTracker::FT_MOUTH_DIMPLE_LEFT,
  210. { "mouthdimplerleft", "mouthdimpleleft", "dimplerl" } },
  211. { XRFaceTracker::FT_MOUTH_RAISER_UPPER,
  212. { "mouthraiserupper", "mouthshrugupper", "chinraisert" } },
  213. { XRFaceTracker::FT_MOUTH_RAISER_LOWER,
  214. { "mouthraiserlower", "mouthshruglower", "mouthloweroverlay", "chinraiserb" } },
  215. { XRFaceTracker::FT_MOUTH_PRESS_RIGHT,
  216. { "mouthpressright", "lippressorr" } },
  217. { XRFaceTracker::FT_MOUTH_PRESS_LEFT,
  218. { "mouthpressleft", "lippressorl" } },
  219. { XRFaceTracker::FT_MOUTH_TIGHTENER_RIGHT,
  220. { "mouthtightenerright", "liptightenerr" } },
  221. { XRFaceTracker::FT_MOUTH_TIGHTENER_LEFT,
  222. { "mouthtightenerleft", "liptightenerl" } },
  223. { XRFaceTracker::FT_TONGUE_OUT,
  224. { "tongueout", "tonguelongstep2" } },
  225. { XRFaceTracker::FT_TONGUE_UP,
  226. { "tongueup" } },
  227. { XRFaceTracker::FT_TONGUE_DOWN,
  228. { "tonguedown" } },
  229. { XRFaceTracker::FT_TONGUE_RIGHT,
  230. { "tongueright" } },
  231. { XRFaceTracker::FT_TONGUE_LEFT,
  232. { "tongueleft" } },
  233. { XRFaceTracker::FT_TONGUE_ROLL,
  234. { "tongueroll" } },
  235. { XRFaceTracker::FT_TONGUE_BLEND_DOWN,
  236. { "tongueblenddown" } },
  237. { XRFaceTracker::FT_TONGUE_CURL_UP,
  238. { "tonguecurlup" } },
  239. { XRFaceTracker::FT_TONGUE_SQUISH,
  240. { "tonguesquish" } },
  241. { XRFaceTracker::FT_TONGUE_FLAT,
  242. { "tongueflat" } },
  243. { XRFaceTracker::FT_TONGUE_TWIST_RIGHT,
  244. { "tonguetwistright" } },
  245. { XRFaceTracker::FT_TONGUE_TWIST_LEFT,
  246. { "tonguetwistleft" } },
  247. { XRFaceTracker::FT_SOFT_PALATE_CLOSE,
  248. { "softpalateclose" } },
  249. { XRFaceTracker::FT_THROAT_SWALLOW,
  250. { "throatswallow" } },
  251. { XRFaceTracker::FT_NECK_FLEX_RIGHT,
  252. { "neckflexright" } },
  253. { XRFaceTracker::FT_NECK_FLEX_LEFT,
  254. { "neckflexleft" } },
  255. { XRFaceTracker::FT_EYE_CLOSED,
  256. { "eyeclosed" } },
  257. { XRFaceTracker::FT_EYE_WIDE,
  258. { "eyewide" } },
  259. { XRFaceTracker::FT_EYE_SQUINT,
  260. { "eyesquint" } },
  261. { XRFaceTracker::FT_EYE_DILATION,
  262. { "eyedilation" } },
  263. { XRFaceTracker::FT_EYE_CONSTRICT,
  264. { "eyeconstrict" } },
  265. { XRFaceTracker::FT_BROW_DOWN_RIGHT,
  266. { "browdownright", "browlowererr" } },
  267. { XRFaceTracker::FT_BROW_DOWN_LEFT,
  268. { "browdownleft", "browlowererl" } },
  269. { XRFaceTracker::FT_BROW_DOWN,
  270. { "browdown" } },
  271. { XRFaceTracker::FT_BROW_UP_RIGHT,
  272. { "browupright" } },
  273. { XRFaceTracker::FT_BROW_UP_LEFT,
  274. { "browupleft" } },
  275. { XRFaceTracker::FT_BROW_UP,
  276. { "browup" } },
  277. { XRFaceTracker::FT_NOSE_SNEER,
  278. { "nosesneer" } },
  279. { XRFaceTracker::FT_NASAL_DILATION,
  280. { "nasaldilation" } },
  281. { XRFaceTracker::FT_NASAL_CONSTRICT,
  282. { "nasalconstrict" } },
  283. { XRFaceTracker::FT_CHEEK_PUFF,
  284. { "cheekpuff" } },
  285. { XRFaceTracker::FT_CHEEK_SUCK,
  286. { "cheeksuck" } },
  287. { XRFaceTracker::FT_CHEEK_SQUINT,
  288. { "cheeksquint" } },
  289. { XRFaceTracker::FT_LIP_SUCK_UPPER,
  290. { "lipsuckupper", "mouthrollupper", "mouthupperinside" } },
  291. { XRFaceTracker::FT_LIP_SUCK_LOWER,
  292. { "lipsucklower", "mouthrolllower", "mouthlowerinside" } },
  293. { XRFaceTracker::FT_LIP_SUCK,
  294. { "lipsuck" } },
  295. { XRFaceTracker::FT_LIP_FUNNEL_UPPER,
  296. { "lipfunnelupper", "mouthupperoverturn" } },
  297. { XRFaceTracker::FT_LIP_FUNNEL_LOWER,
  298. { "lipfunnellower", "mouthloweroverturn" } },
  299. { XRFaceTracker::FT_LIP_FUNNEL,
  300. { "lipfunnel", "mouthfunnel" } },
  301. { XRFaceTracker::FT_LIP_PUCKER_UPPER,
  302. { "lippuckerupper" } },
  303. { XRFaceTracker::FT_LIP_PUCKER_LOWER,
  304. { "lippuckerlower" } },
  305. { XRFaceTracker::FT_LIP_PUCKER,
  306. { "lippucker", "mouthpucker", "mouthpout" } },
  307. { XRFaceTracker::FT_MOUTH_UPPER_UP,
  308. { "mouthupperup" } },
  309. { XRFaceTracker::FT_MOUTH_LOWER_DOWN,
  310. { "mouthlowerdown" } },
  311. { XRFaceTracker::FT_MOUTH_OPEN,
  312. { "mouthopen" } },
  313. { XRFaceTracker::FT_MOUTH_RIGHT,
  314. { "mouthright" } },
  315. { XRFaceTracker::FT_MOUTH_LEFT,
  316. { "mouthleft" } },
  317. { XRFaceTracker::FT_MOUTH_SMILE_RIGHT,
  318. { "mouthsmileright", "lipcornerpullerr" } },
  319. { XRFaceTracker::FT_MOUTH_SMILE_LEFT,
  320. { "mouthsmileleft", "lipcornerpullerl" } },
  321. { XRFaceTracker::FT_MOUTH_SMILE,
  322. { "mouthsmile" } },
  323. { XRFaceTracker::FT_MOUTH_SAD_RIGHT,
  324. { "mouthsadright" } },
  325. { XRFaceTracker::FT_MOUTH_SAD_LEFT,
  326. { "mouthsadleft" } },
  327. { XRFaceTracker::FT_MOUTH_SAD,
  328. { "mouthsad" } },
  329. { XRFaceTracker::FT_MOUTH_STRETCH,
  330. { "mouthstretch" } },
  331. { XRFaceTracker::FT_MOUTH_DIMPLE,
  332. { "mouthdimple" } },
  333. { XRFaceTracker::FT_MOUTH_TIGHTENER,
  334. { "mouthtightener" } },
  335. { XRFaceTracker::FT_MOUTH_PRESS,
  336. { "mouthpress" } }
  337. };
  338. // Convert the name to lower-case and strip non-alphanumeric characters.
  339. const String name = String(p_name).to_lower().replace("_", "");
  340. // Iterate through the blend map.
  341. for (const blend_map_entry &entry : blend_map) {
  342. for (const char *n : entry.name) {
  343. if (n == nullptr) {
  344. break;
  345. }
  346. if (name == n) {
  347. return entry.blend;
  348. }
  349. }
  350. }
  351. // Blend shape not found.
  352. return -1;
  353. }
  354. // This method adds all the identified XRFaceTracker blend shapes of
  355. // the mesh to the p_blend_mapping map. The map is indexed by the
  356. // XRFaceTracker blend shape, and the value is the index of the mesh
  357. // blend shape.
  358. static void identify_face_blend_shapes(RBMap<int, int> &p_blend_mapping, const Ref<Mesh> &mesh) {
  359. // Find all blend shapes.
  360. const int count = mesh->get_blend_shape_count();
  361. for (int i = 0; i < count; i++) {
  362. const int blend = find_face_blend_shape(mesh->get_blend_shape_name(i));
  363. if (blend >= 0) {
  364. p_blend_mapping[blend] = i;
  365. }
  366. }
  367. }
  368. // This method removes any unified blend shapes from the p_blend_mapping map
  369. // if all the individual blend shapes are found and going to be driven.
  370. static void remove_driven_unified_blend_shapes(RBMap<int, int> &p_blend_mapping) {
  371. // Entry for unified blend table.
  372. struct unified_blend_entry {
  373. int unified;
  374. int individual[4];
  375. };
  376. // Table of unified blend shapes.
  377. //
  378. // This table consists of:
  379. // - The XRFaceTracker unified blend shape.
  380. // - The individual blend shapes that make up the unified blend shape.
  381. static constexpr unified_blend_entry unified_blends[] = {
  382. { XRFaceTracker::FT_EYE_CLOSED,
  383. { XRFaceTracker::FT_EYE_CLOSED_RIGHT, XRFaceTracker::FT_EYE_CLOSED_LEFT, -1, -1 } },
  384. { XRFaceTracker::FT_EYE_WIDE,
  385. { XRFaceTracker::FT_EYE_WIDE_RIGHT, XRFaceTracker::FT_EYE_WIDE_LEFT, -1, -1 } },
  386. { XRFaceTracker::FT_EYE_SQUINT,
  387. { XRFaceTracker::FT_EYE_SQUINT_RIGHT, XRFaceTracker::FT_EYE_SQUINT_LEFT, -1, -1 } },
  388. { XRFaceTracker::FT_EYE_DILATION,
  389. { XRFaceTracker::FT_EYE_DILATION_RIGHT, XRFaceTracker::FT_EYE_DILATION_LEFT, -1, -1 } },
  390. { XRFaceTracker::FT_EYE_CONSTRICT,
  391. { XRFaceTracker::FT_EYE_CONSTRICT_RIGHT, XRFaceTracker::FT_EYE_CONSTRICT_LEFT, -1, -1 } },
  392. { XRFaceTracker::FT_BROW_DOWN_RIGHT,
  393. { XRFaceTracker::FT_BROW_LOWERER_RIGHT, XRFaceTracker::FT_BROW_PINCH_RIGHT, -1, -1 } },
  394. { XRFaceTracker::FT_BROW_DOWN_LEFT,
  395. { XRFaceTracker::FT_BROW_LOWERER_LEFT, XRFaceTracker::FT_BROW_PINCH_LEFT, -1, -1 } },
  396. { XRFaceTracker::FT_BROW_DOWN,
  397. { XRFaceTracker::FT_BROW_LOWERER_RIGHT, XRFaceTracker::FT_BROW_PINCH_RIGHT, XRFaceTracker::FT_BROW_LOWERER_LEFT, XRFaceTracker::FT_BROW_PINCH_LEFT } },
  398. { XRFaceTracker::FT_BROW_UP_RIGHT,
  399. { XRFaceTracker::FT_BROW_INNER_UP_RIGHT, XRFaceTracker::FT_BROW_OUTER_UP_RIGHT, -1, -1 } },
  400. { XRFaceTracker::FT_BROW_UP_LEFT,
  401. { XRFaceTracker::FT_BROW_INNER_UP_LEFT, XRFaceTracker::FT_BROW_OUTER_UP_LEFT, -1, -1 } },
  402. { XRFaceTracker::FT_BROW_UP,
  403. { XRFaceTracker::FT_BROW_INNER_UP_RIGHT, XRFaceTracker::FT_BROW_OUTER_UP_RIGHT, XRFaceTracker::FT_BROW_INNER_UP_LEFT, XRFaceTracker::FT_BROW_OUTER_UP_LEFT } },
  404. { XRFaceTracker::FT_NOSE_SNEER,
  405. { XRFaceTracker::FT_NOSE_SNEER_RIGHT, XRFaceTracker::FT_NOSE_SNEER_LEFT, -1, -1 } },
  406. { XRFaceTracker::FT_NASAL_DILATION,
  407. { XRFaceTracker::FT_NASAL_DILATION_RIGHT, XRFaceTracker::FT_NASAL_DILATION_LEFT, -1, -1 } },
  408. { XRFaceTracker::FT_NASAL_CONSTRICT,
  409. { XRFaceTracker::FT_NASAL_CONSTRICT_RIGHT, XRFaceTracker::FT_NASAL_CONSTRICT_LEFT, -1, -1 } },
  410. { XRFaceTracker::FT_CHEEK_PUFF,
  411. { XRFaceTracker::FT_CHEEK_PUFF_RIGHT, XRFaceTracker::FT_CHEEK_PUFF_LEFT, -1, -1 } },
  412. { XRFaceTracker::FT_CHEEK_SUCK,
  413. { XRFaceTracker::FT_CHEEK_SUCK_RIGHT, XRFaceTracker::FT_CHEEK_SUCK_LEFT, -1, -1 } },
  414. { XRFaceTracker::FT_CHEEK_SQUINT,
  415. { XRFaceTracker::FT_CHEEK_SQUINT_RIGHT, XRFaceTracker::FT_CHEEK_SQUINT_LEFT, -1, -1 } },
  416. { XRFaceTracker::FT_LIP_SUCK_UPPER,
  417. { XRFaceTracker::FT_LIP_SUCK_UPPER_RIGHT, XRFaceTracker::FT_LIP_SUCK_UPPER_LEFT, -1, -1 } },
  418. { XRFaceTracker::FT_LIP_SUCK_LOWER,
  419. { XRFaceTracker::FT_LIP_SUCK_LOWER_RIGHT, XRFaceTracker::FT_LIP_SUCK_LOWER_LEFT, -1, -1 } },
  420. { XRFaceTracker::FT_LIP_SUCK,
  421. { XRFaceTracker::FT_LIP_SUCK_UPPER_RIGHT, XRFaceTracker::FT_LIP_SUCK_UPPER_LEFT, XRFaceTracker::FT_LIP_SUCK_LOWER_RIGHT, XRFaceTracker::FT_LIP_SUCK_LOWER_LEFT } },
  422. { XRFaceTracker::FT_LIP_FUNNEL_UPPER,
  423. { XRFaceTracker::FT_LIP_FUNNEL_UPPER_RIGHT, XRFaceTracker::FT_LIP_FUNNEL_UPPER_LEFT, -1, -1 } },
  424. { XRFaceTracker::FT_LIP_FUNNEL_LOWER,
  425. { XRFaceTracker::FT_LIP_FUNNEL_LOWER_RIGHT, XRFaceTracker::FT_LIP_FUNNEL_LOWER_LEFT, -1, -1 } },
  426. { XRFaceTracker::FT_LIP_FUNNEL,
  427. { XRFaceTracker::FT_LIP_FUNNEL_UPPER_RIGHT, XRFaceTracker::FT_LIP_FUNNEL_UPPER_LEFT, XRFaceTracker::FT_LIP_FUNNEL_LOWER_RIGHT, XRFaceTracker::FT_LIP_FUNNEL_LOWER_LEFT } },
  428. { XRFaceTracker::FT_LIP_PUCKER_UPPER,
  429. { XRFaceTracker::FT_LIP_PUCKER_UPPER_RIGHT, XRFaceTracker::FT_LIP_PUCKER_UPPER_LEFT, -1, -1 } },
  430. { XRFaceTracker::FT_LIP_PUCKER_LOWER,
  431. { XRFaceTracker::FT_LIP_PUCKER_LOWER_RIGHT, XRFaceTracker::FT_LIP_PUCKER_LOWER_LEFT, -1, -1 } },
  432. { XRFaceTracker::FT_LIP_PUCKER,
  433. { XRFaceTracker::FT_LIP_PUCKER_UPPER_RIGHT, XRFaceTracker::FT_LIP_PUCKER_UPPER_LEFT, XRFaceTracker::FT_LIP_PUCKER_LOWER_RIGHT, XRFaceTracker::FT_LIP_PUCKER_LOWER_LEFT } },
  434. { XRFaceTracker::FT_MOUTH_UPPER_UP,
  435. { XRFaceTracker::FT_MOUTH_UPPER_UP_RIGHT, XRFaceTracker::FT_MOUTH_UPPER_UP_LEFT, -1, -1 } },
  436. { XRFaceTracker::FT_MOUTH_LOWER_DOWN,
  437. { XRFaceTracker::FT_MOUTH_LOWER_DOWN_RIGHT, XRFaceTracker::FT_MOUTH_LOWER_DOWN_LEFT, -1, -1 } },
  438. { XRFaceTracker::FT_MOUTH_OPEN,
  439. { XRFaceTracker::FT_MOUTH_UPPER_UP_RIGHT, XRFaceTracker::FT_MOUTH_UPPER_UP_LEFT, XRFaceTracker::FT_MOUTH_LOWER_DOWN_RIGHT, XRFaceTracker::FT_MOUTH_LOWER_DOWN_LEFT } },
  440. { XRFaceTracker::FT_MOUTH_RIGHT,
  441. { XRFaceTracker::FT_MOUTH_UPPER_RIGHT, XRFaceTracker::FT_MOUTH_LOWER_RIGHT, -1, -1 } },
  442. { XRFaceTracker::FT_MOUTH_LEFT,
  443. { XRFaceTracker::FT_MOUTH_UPPER_LEFT, XRFaceTracker::FT_MOUTH_LOWER_LEFT, -1, -1 } },
  444. { XRFaceTracker::FT_MOUTH_SMILE_RIGHT,
  445. { XRFaceTracker::FT_MOUTH_CORNER_PULL_RIGHT, XRFaceTracker::FT_MOUTH_CORNER_SLANT_RIGHT, -1, -1 } },
  446. { XRFaceTracker::FT_MOUTH_SMILE_LEFT,
  447. { XRFaceTracker::FT_MOUTH_CORNER_PULL_LEFT, XRFaceTracker::FT_MOUTH_CORNER_SLANT_LEFT, -1, -1 } },
  448. { XRFaceTracker::FT_MOUTH_SMILE,
  449. { XRFaceTracker::FT_MOUTH_CORNER_PULL_RIGHT, XRFaceTracker::FT_MOUTH_CORNER_SLANT_RIGHT, XRFaceTracker::FT_MOUTH_CORNER_PULL_LEFT, XRFaceTracker::FT_MOUTH_CORNER_SLANT_LEFT } },
  450. { XRFaceTracker::FT_MOUTH_SAD_RIGHT,
  451. { XRFaceTracker::FT_MOUTH_FROWN_RIGHT, XRFaceTracker::FT_MOUTH_STRETCH_RIGHT, -1, -1 } },
  452. { XRFaceTracker::FT_MOUTH_SAD_LEFT,
  453. { XRFaceTracker::FT_MOUTH_FROWN_LEFT, XRFaceTracker::FT_MOUTH_STRETCH_LEFT, -1, -1 } },
  454. { XRFaceTracker::FT_MOUTH_SAD,
  455. { XRFaceTracker::FT_MOUTH_FROWN_RIGHT, XRFaceTracker::FT_MOUTH_STRETCH_RIGHT, XRFaceTracker::FT_MOUTH_FROWN_LEFT, XRFaceTracker::FT_MOUTH_STRETCH_LEFT } },
  456. { XRFaceTracker::FT_MOUTH_STRETCH,
  457. { XRFaceTracker::FT_MOUTH_STRETCH_RIGHT, XRFaceTracker::FT_MOUTH_STRETCH_LEFT, -1, -1 } },
  458. { XRFaceTracker::FT_MOUTH_DIMPLE,
  459. { XRFaceTracker::FT_MOUTH_DIMPLE_RIGHT, XRFaceTracker::FT_MOUTH_DIMPLE_LEFT, -1, -1 } },
  460. { XRFaceTracker::FT_MOUTH_TIGHTENER,
  461. { XRFaceTracker::FT_MOUTH_TIGHTENER_RIGHT, XRFaceTracker::FT_MOUTH_TIGHTENER_LEFT, -1, -1 } },
  462. { XRFaceTracker::FT_MOUTH_PRESS,
  463. { XRFaceTracker::FT_MOUTH_PRESS_RIGHT, XRFaceTracker::FT_MOUTH_PRESS_LEFT, -1, -1 } }
  464. };
  465. // Remove unified blend shapes if individual blend shapes are found.
  466. for (const unified_blend_entry &entry : unified_blends) {
  467. // Check if all individual blend shapes are found.
  468. bool found = true;
  469. for (const int i : entry.individual) {
  470. if (i >= 0 && !p_blend_mapping.find(i)) {
  471. found = false;
  472. break;
  473. }
  474. }
  475. // If all individual blend shapes are found then remove the unified blend shape.
  476. if (found) {
  477. p_blend_mapping.erase(entry.unified);
  478. }
  479. }
  480. }
  481. void XRFaceModifier3D::_bind_methods() {
  482. ClassDB::bind_method(D_METHOD("set_face_tracker", "tracker_name"), &XRFaceModifier3D::set_face_tracker);
  483. ClassDB::bind_method(D_METHOD("get_face_tracker"), &XRFaceModifier3D::get_face_tracker);
  484. ADD_PROPERTY(PropertyInfo(Variant::STRING, "face_tracker", PROPERTY_HINT_ENUM_SUGGESTION, "/user/face_tracker"), "set_face_tracker", "get_face_tracker");
  485. ClassDB::bind_method(D_METHOD("set_target", "target"), &XRFaceModifier3D::set_target);
  486. ClassDB::bind_method(D_METHOD("get_target"), &XRFaceModifier3D::get_target);
  487. ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "target", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "MeshInstance3D"), "set_target", "get_target");
  488. }
  489. void XRFaceModifier3D::set_face_tracker(const StringName &p_tracker_name) {
  490. tracker_name = p_tracker_name;
  491. }
  492. StringName XRFaceModifier3D::get_face_tracker() const {
  493. return tracker_name;
  494. }
  495. void XRFaceModifier3D::set_target(const NodePath &p_target) {
  496. target = p_target;
  497. if (is_inside_tree()) {
  498. _get_blend_data();
  499. }
  500. }
  501. NodePath XRFaceModifier3D::get_target() const {
  502. return target;
  503. }
  504. MeshInstance3D *XRFaceModifier3D::get_mesh_instance() const {
  505. if (!has_node(target)) {
  506. return nullptr;
  507. }
  508. Node *node = get_node(target);
  509. if (!node) {
  510. return nullptr;
  511. }
  512. return Object::cast_to<MeshInstance3D>(node);
  513. }
  514. void XRFaceModifier3D::_get_blend_data() {
  515. // This method constructs the blend mapping from the XRFaceTracker
  516. // blend shapes to the available blend shapes of the target mesh. It does this
  517. // by:
  518. //
  519. // 1. Identifying the blend shapes of the target mesh and identifying what
  520. // XRFaceTracker blend shape they correspond to. The results are
  521. // placed in the blend_mapping map.
  522. // 2. Prevent over-driving facial blend-shapes by removing any unified blend
  523. // shapes from the map if all the individual blend shapes are already
  524. // found and going to be driven.
  525. blend_mapping.clear();
  526. // Get the target MeshInstance3D.
  527. const MeshInstance3D *mesh_instance = get_mesh_instance();
  528. if (!mesh_instance) {
  529. return;
  530. }
  531. // Get the mesh.
  532. const Ref<Mesh> mesh = mesh_instance->get_mesh();
  533. if (mesh.is_null()) {
  534. return;
  535. }
  536. // Identify all face blend shapes and populate the map.
  537. identify_face_blend_shapes(blend_mapping, mesh);
  538. // Remove the unified blend shapes if all the individual blend shapes are found.
  539. remove_driven_unified_blend_shapes(blend_mapping);
  540. }
  541. void XRFaceModifier3D::_update_face_blends() const {
  542. // Get the XR Server.
  543. const XRServer *xr_server = XRServer::get_singleton();
  544. if (!xr_server) {
  545. return;
  546. }
  547. // Get the face tracker.
  548. const Ref<XRFaceTracker> tracker = xr_server->get_tracker(tracker_name);
  549. if (!tracker.is_valid()) {
  550. return;
  551. }
  552. // Get the face mesh.
  553. MeshInstance3D *mesh_instance = get_mesh_instance();
  554. if (!mesh_instance) {
  555. return;
  556. }
  557. // Get the blend weights.
  558. const PackedFloat32Array weights = tracker->get_blend_shapes();
  559. // Apply all the face blend weights to the mesh.
  560. for (const KeyValue<int, int> &it : blend_mapping) {
  561. mesh_instance->set_blend_shape_value(it.value, weights[it.key]);
  562. }
  563. }
  564. void XRFaceModifier3D::_notification(int p_what) {
  565. switch (p_what) {
  566. case NOTIFICATION_ENTER_TREE: {
  567. _get_blend_data();
  568. set_process_internal(true);
  569. } break;
  570. case NOTIFICATION_EXIT_TREE: {
  571. set_process_internal(false);
  572. blend_mapping.clear();
  573. } break;
  574. case NOTIFICATION_INTERNAL_PROCESS: {
  575. _update_face_blends();
  576. } break;
  577. default: {
  578. } break;
  579. }
  580. }