diff --git a/Gems/MotionMatching/Assets/Animations/Acceleration1.fbx b/Gems/MotionMatching/Assets/Animations/Acceleration1.fbx
new file mode 100644
index 0000000000..c2c167cdd1
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/Acceleration1.fbx
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:33d5b3035966ac54bbb97a207ca14868a6daef9ad9e596281f7930764b54c819
+size 2527664
diff --git a/Gems/MotionMatching/Assets/Animations/Circles1.fbx b/Gems/MotionMatching/Assets/Animations/Circles1.fbx
new file mode 100644
index 0000000000..fcdecc0ab5
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/Circles1.fbx
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:91d6a8c16bae554339d1849285804b798e136113c6aecc3dfed1be635c484600
+size 4750720
diff --git a/Gems/MotionMatching/Assets/Animations/Crouching1.fbx b/Gems/MotionMatching/Assets/Animations/Crouching1.fbx
new file mode 100644
index 0000000000..bf5c171f8b
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/Crouching1.fbx
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e18101baa7b33af4ac26181b7c3c20d5c12e9d9d2f57bd24271c6e4665e1a65a
+size 3001296
diff --git a/Gems/MotionMatching/Assets/Animations/FreeRoaming1.fbx b/Gems/MotionMatching/Assets/Animations/FreeRoaming1.fbx
new file mode 100644
index 0000000000..f44eba537a
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/FreeRoaming1.fbx
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:8eda027438797e48e6b00745e17e3ec4da6d507735c754056a8fea19c465a528
+size 5926096
diff --git a/Gems/MotionMatching/Assets/Animations/FreeRoaming2.fbx b/Gems/MotionMatching/Assets/Animations/FreeRoaming2.fbx
new file mode 100644
index 0000000000..837f8df648
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/FreeRoaming2.fbx
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:0c2af3ea28464b4d7269f54c1ff1ded691b19b826d5de85139d20ae825aae992
+size 5085168
diff --git a/Gems/MotionMatching/Assets/Animations/Jog1.fbx b/Gems/MotionMatching/Assets/Animations/Jog1.fbx
new file mode 100644
index 0000000000..02e6c73ac5
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/Jog1.fbx
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:25593a1e4670dbb9cb1c5a0fc375ba2bf7862784c45847d76eefd44d39df86f9
+size 2974896
diff --git a/Gems/MotionMatching/Assets/Animations/JogPivotTurn1.fbx b/Gems/MotionMatching/Assets/Animations/JogPivotTurn1.fbx
new file mode 100644
index 0000000000..51fac75ca6
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/JogPivotTurn1.fbx
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e21e3f9b7db6572f740a99159bba72eca3697d3d3e1c07562579be9599bcebb7
+size 2511488
diff --git a/Gems/MotionMatching/Assets/Animations/Jumps1.fbx b/Gems/MotionMatching/Assets/Animations/Jumps1.fbx
new file mode 100644
index 0000000000..d075da8991
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/Jumps1.fbx
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:3802b0e44b3e0aa6610a4157510c3038bfe4038211202cebd6eb116ffd53cee9
+size 2587408
diff --git a/Gems/MotionMatching/Assets/Animations/JumpsFreeRoam1.fbx b/Gems/MotionMatching/Assets/Animations/JumpsFreeRoam1.fbx
new file mode 100644
index 0000000000..d384c9f156
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/JumpsFreeRoam1.fbx
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:0f07e278fcee81d719ec2e7c02417e2ee710b9d224a29798cfb97b55a9ffe351
+size 3515488
diff --git a/Gems/MotionMatching/Assets/Animations/MixedLocomotion1.fbx b/Gems/MotionMatching/Assets/Animations/MixedLocomotion1.fbx
new file mode 100644
index 0000000000..317fa22e76
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/MixedLocomotion1.fbx
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:cc4d0b653f910cea3c7c3b8d08963af0cc331ad91e467c7becb2c7f9b9c5b402
+size 4068144
diff --git a/Gems/MotionMatching/Assets/Animations/OutofRange1.fbx b/Gems/MotionMatching/Assets/Animations/OutofRange1.fbx
new file mode 100644
index 0000000000..ecde12dee1
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/OutofRange1.fbx
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:58cd43568cdd3f9b9585b65208cfff6d6c5f5bea9ad67878a1efbeebb8ef8a6d
+size 1812176
diff --git a/Gems/MotionMatching/Assets/Animations/Pushes1.fbx b/Gems/MotionMatching/Assets/Animations/Pushes1.fbx
new file mode 100644
index 0000000000..d89c45a611
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/Pushes1.fbx
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:18a831cfe702120d163e44a27d5cd33faf64f5f892da3789aea1bbfecd528e72
+size 3288400
diff --git a/Gems/MotionMatching/Assets/Animations/Run1.fbx b/Gems/MotionMatching/Assets/Animations/Run1.fbx
new file mode 100644
index 0000000000..150ae00f4f
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/Run1.fbx
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:3649e2d0b239f9da45af2b04e937ce6113e8dee74a70a3cef748995ea15f6120
+size 2354544
diff --git a/Gems/MotionMatching/Assets/Animations/RunPivotTurn1.fbx b/Gems/MotionMatching/Assets/Animations/RunPivotTurn1.fbx
new file mode 100644
index 0000000000..8e67a72016
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/RunPivotTurn1.fbx
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:207378e42ebdad1c3dfe8cefc84ed50e1d322895f018e2efca14fdcbf2e6600f
+size 1890352
diff --git a/Gems/MotionMatching/Assets/Animations/Snake1.fbx b/Gems/MotionMatching/Assets/Animations/Snake1.fbx
new file mode 100644
index 0000000000..ff597b968d
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/Snake1.fbx
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:78c68566aba845544ec96a92f2cf4e36350c74c16e931c3aa9e14151bcaed8e8
+size 3881680
diff --git a/Gems/MotionMatching/Assets/Animations/TurnOnSpot1.fbx b/Gems/MotionMatching/Assets/Animations/TurnOnSpot1.fbx
new file mode 100644
index 0000000000..ac71a0f42b
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/TurnOnSpot1.fbx
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:73560b662d3819647985c3f7b0544ba3ad71365e8393a3915630b254f86c6286
+size 3669552
diff --git a/Gems/MotionMatching/Assets/Animations/Walk1.fbx b/Gems/MotionMatching/Assets/Animations/Walk1.fbx
new file mode 100644
index 0000000000..423a59b31f
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/Walk1.fbx
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e2fad264af33252d49c6e3a0b6c6ef83697b951a54c7ab0cd4259f145024d915
+size 3962336
diff --git a/Gems/MotionMatching/Assets/Animations/Walk2.fbx b/Gems/MotionMatching/Assets/Animations/Walk2.fbx
new file mode 100644
index 0000000000..0aaf74b496
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/Walk2.fbx
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:149ae8bfc0dc4ad8471e79f5cd8ce5420c02bc5c8a5cf1971ebbf997cae21096
+size 3834704
diff --git a/Gems/MotionMatching/Assets/Animations/WalkPivotTurn1.fbx b/Gems/MotionMatching/Assets/Animations/WalkPivotTurn1.fbx
new file mode 100644
index 0000000000..1dac028839
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/WalkPivotTurn1.fbx
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b6468a660cfd88c350443e92b31e41362909d705c344cda6640c65a5e1fd2a29
+size 2288048
diff --git a/Gems/MotionMatching/Assets/Animations/WalkStopTurn1.fbx b/Gems/MotionMatching/Assets/Animations/WalkStopTurn1.fbx
new file mode 100644
index 0000000000..20f967fece
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/WalkStopTurn1.fbx
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b824d6fd5bb3e7f6b4f29ff90b406179539e1c155ba9f8870ef54f1d1d0e22e7
+size 3128032
diff --git a/Gems/MotionMatching/Assets/Animations/WalkStopTurnPivot1.fbx b/Gems/MotionMatching/Assets/Animations/WalkStopTurnPivot1.fbx
new file mode 100644
index 0000000000..50f69af25c
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/WalkStopTurnPivot1.fbx
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:38f0f9e280ff686032aa223cc8ce754442edc616d28a16d39a87c90bd221c91a
+size 2807280
diff --git a/Gems/MotionMatching/Assets/Animations/WalkTurns1.fbx b/Gems/MotionMatching/Assets/Animations/WalkTurns1.fbx
new file mode 100644
index 0000000000..acdb27e1d9
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/WalkTurns1.fbx
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:862ddf8893923169938db017f573f63228bb5aec3d4892d21a525200dd6c4680
+size 4063280
diff --git a/Gems/MotionMatching/Assets/Animations/acceleration1.fbx.assetinfo b/Gems/MotionMatching/Assets/Animations/acceleration1.fbx.assetinfo
new file mode 100644
index 0000000000..c9749b8bf3
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/acceleration1.fbx.assetinfo
@@ -0,0 +1,50 @@
+{
+ "values": [
+ {
+ "$type": "MotionGroup",
+ "name": "acceleration1",
+ "selectedRootBone": "RootNode.root",
+ "id": "{ADB2CDC1-8EA3-5B21-90D6-43EBE9991709}",
+ "rules": {
+ "rules": [
+ {
+ "$type": "EMotionFX::Pipeline::Rule::MotionMetaDataRule",
+ "data": {
+ "motionEventTable": {
+ "tracks": [
+ {
+ "name": "Sync",
+ "deletable": false,
+ "events": [
+ {
+ "eventDatas": [
+ {
+ "$type": "DiscardFrameEventData"
+ }
+ ],
+ "startTime": 19.600000381469727,
+ "endTime": 20.666667938232422
+ },
+ {
+ "eventDatas": [
+ {
+ "$type": "DiscardFrameEventData"
+ }
+ ],
+ "startTime": 50.599998474121094,
+ "endTime": 53.19999694824219
+ }
+ ]
+ }
+ ]
+ }
+ }
+ },
+ {
+ "$type": "MotionSamplingRule"
+ }
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Gems/MotionMatching/Assets/Animations/circles1.fbx.assetinfo b/Gems/MotionMatching/Assets/Animations/circles1.fbx.assetinfo
new file mode 100644
index 0000000000..4276767f05
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/circles1.fbx.assetinfo
@@ -0,0 +1,41 @@
+{
+ "values": [
+ {
+ "$type": "MotionGroup",
+ "name": "circles1",
+ "selectedRootBone": "RootNode.root",
+ "id": "{BF21E0D5-87F6-5A3F-B100-507F217D4C7E}",
+ "rules": {
+ "rules": [
+ {
+ "$type": "EMotionFX::Pipeline::Rule::MotionMetaDataRule",
+ "data": {
+ "motionEventTable": {
+ "tracks": [
+ {
+ "name": "Sync",
+ "deletable": false,
+ "events": [
+ {
+ "eventDatas": [
+ {
+ "$type": "DiscardFrameEventData"
+ }
+ ],
+ "startTime": 112.73334503173828,
+ "endTime": 114.00001525878906
+ }
+ ]
+ }
+ ]
+ }
+ }
+ },
+ {
+ "$type": "MotionSamplingRule"
+ }
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Gems/MotionMatching/Assets/Animations/crouching1.fbx.assetinfo b/Gems/MotionMatching/Assets/Animations/crouching1.fbx.assetinfo
new file mode 100644
index 0000000000..2f2f8c52e5
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/crouching1.fbx.assetinfo
@@ -0,0 +1,125 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Gems/MotionMatching/Assets/Animations/freeroaming1.fbx.assetinfo b/Gems/MotionMatching/Assets/Animations/freeroaming1.fbx.assetinfo
new file mode 100644
index 0000000000..0a6534208d
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/freeroaming1.fbx.assetinfo
@@ -0,0 +1,59 @@
+{
+ "values": [
+ {
+ "$type": "MotionGroup",
+ "name": "freeroaming1",
+ "selectedRootBone": "RootNode.root",
+ "id": "{A07E54E7-BB49-5DB3-BCA1-5EC8B4FA74A3}",
+ "rules": {
+ "rules": [
+ {
+ "$type": "EMotionFX::Pipeline::Rule::MotionMetaDataRule",
+ "data": {
+ "motionEventTable": {
+ "tracks": [
+ {
+ "name": "Sync",
+ "deletable": false,
+ "events": [
+ {
+ "eventDatas": [
+ {
+ "$type": "DiscardFrameEventData"
+ }
+ ],
+ "startTime": 73.33333587646484,
+ "endTime": 111.13333129882813
+ },
+ {
+ "eventDatas": [
+ {
+ "$type": "DiscardFrameEventData"
+ }
+ ],
+ "startTime": 134.3333282470703,
+ "endTime": 136.13333129882813
+ },
+ {
+ "eventDatas": [
+ {
+ "$type": "DiscardFrameEventData"
+ }
+ ],
+ "startTime": 145.1999969482422,
+ "endTime": 146.13333129882813
+ }
+ ]
+ }
+ ]
+ }
+ }
+ },
+ {
+ "$type": "MotionSamplingRule"
+ }
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Gems/MotionMatching/Assets/Animations/freeroaming2.fbx.assetinfo b/Gems/MotionMatching/Assets/Animations/freeroaming2.fbx.assetinfo
new file mode 100644
index 0000000000..bdb6c10668
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/freeroaming2.fbx.assetinfo
@@ -0,0 +1,41 @@
+{
+ "values": [
+ {
+ "$type": "MotionGroup",
+ "name": "freeroaming2",
+ "selectedRootBone": "RootNode.root",
+ "id": "{96DC1ABD-1F72-5546-8B7F-7092C3AC0E5D}",
+ "rules": {
+ "rules": [
+ {
+ "$type": "EMotionFX::Pipeline::Rule::MotionMetaDataRule",
+ "data": {
+ "motionEventTable": {
+ "tracks": [
+ {
+ "name": "Sync",
+ "deletable": false,
+ "events": [
+ {
+ "eventDatas": [
+ {
+ "$type": "DiscardFrameEventData"
+ }
+ ],
+ "startTime": 119.26667022705078,
+ "endTime": 123.4000015258789
+ }
+ ]
+ }
+ ]
+ }
+ }
+ },
+ {
+ "$type": "MotionSamplingRule"
+ }
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Gems/MotionMatching/Assets/Animations/jog1.fbx.assetinfo b/Gems/MotionMatching/Assets/Animations/jog1.fbx.assetinfo
new file mode 100644
index 0000000000..dbb83cb4d3
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/jog1.fbx.assetinfo
@@ -0,0 +1,41 @@
+{
+ "values": [
+ {
+ "$type": "MotionGroup",
+ "name": "jog1",
+ "selectedRootBone": "RootNode.root",
+ "id": "{9200D325-808C-5B2D-B323-1FF9790C07B7}",
+ "rules": {
+ "rules": [
+ {
+ "$type": "EMotionFX::Pipeline::Rule::MotionMetaDataRule",
+ "data": {
+ "motionEventTable": {
+ "tracks": [
+ {
+ "name": "Sync",
+ "deletable": false,
+ "events": [
+ {
+ "eventDatas": [
+ {
+ "$type": "DiscardFrameEventData"
+ }
+ ],
+ "startTime": 64.0,
+ "endTime": 65.53333282470703
+ }
+ ]
+ }
+ ]
+ }
+ }
+ },
+ {
+ "$type": "MotionSamplingRule"
+ }
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Gems/MotionMatching/Assets/Animations/jogpivotturn1.fbx.assetinfo b/Gems/MotionMatching/Assets/Animations/jogpivotturn1.fbx.assetinfo
new file mode 100644
index 0000000000..10b3e2e59a
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/jogpivotturn1.fbx.assetinfo
@@ -0,0 +1,53 @@
+{
+ "values": [
+ {
+ "$type": "MotionGroup",
+ "name": "jogpivotturn1",
+ "selectedRootBone": "RootNode.root",
+ "id": "{596210E7-A7F4-511D-886B-AA4FED4AC92B}",
+ "rules": {
+ "rules": [
+ {
+ "$type": "EMotionFX::Pipeline::Rule::MotionMetaDataRule",
+ "data": {
+ "motionEventTable": {
+ "tracks": [
+ {
+ "name": "Sync",
+ "deletable": false
+ },
+ {
+ "name": "Event Track 2",
+ "events": [
+ {
+ "eventDatas": [
+ {
+ "$type": "DiscardFrameEventData"
+ }
+ ],
+ "startTime": 36.66666793823242,
+ "endTime": 40.733333587646484
+ },
+ {
+ "eventDatas": [
+ {
+ "$type": "DiscardFrameEventData"
+ }
+ ],
+ "startTime": 41.733333587646484,
+ "endTime": 53.06666564941406
+ }
+ ]
+ }
+ ]
+ }
+ }
+ },
+ {
+ "$type": "MotionSamplingRule"
+ }
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Gems/MotionMatching/Assets/Animations/mixedlocomotion1.fbx.assetinfo b/Gems/MotionMatching/Assets/Animations/mixedlocomotion1.fbx.assetinfo
new file mode 100644
index 0000000000..d8d1a4d4e6
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/mixedlocomotion1.fbx.assetinfo
@@ -0,0 +1,53 @@
+{
+ "values": [
+ {
+ "$type": "MotionGroup",
+ "name": "mixedlocomotion1",
+ "selectedRootBone": "RootNode.root",
+ "id": "{2F7682E4-235E-5A31-B450-266D7DC00E39}",
+ "rules": {
+ "rules": [
+ {
+ "$type": "EMotionFX::Pipeline::Rule::MotionMetaDataRule",
+ "data": {
+ "motionEventTable": {
+ "tracks": [
+ {
+ "name": "Sync",
+ "deletable": false
+ },
+ {
+ "name": "Event Track 2",
+ "events": [
+ {
+ "eventDatas": [
+ {
+ "$type": "DiscardFrameEventData"
+ }
+ ],
+ "startTime": 27.53333282470703,
+ "endTime": 29.999998092651367
+ },
+ {
+ "eventDatas": [
+ {
+ "$type": "DiscardFrameEventData"
+ }
+ ],
+ "startTime": 56.53333282470703,
+ "endTime": 60.666664123535156
+ }
+ ]
+ }
+ ]
+ }
+ }
+ },
+ {
+ "$type": "MotionSamplingRule"
+ }
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Gems/MotionMatching/Assets/Animations/outofrange1.fbx.assetinfo b/Gems/MotionMatching/Assets/Animations/outofrange1.fbx.assetinfo
new file mode 100644
index 0000000000..9e206c09ae
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/outofrange1.fbx.assetinfo
@@ -0,0 +1,41 @@
+{
+ "values": [
+ {
+ "$type": "MotionGroup",
+ "name": "outofrange1",
+ "selectedRootBone": "RootNode.root",
+ "id": "{6B28C886-471C-5506-AD03-DF19025F6DA1}",
+ "rules": {
+ "rules": [
+ {
+ "$type": "EMotionFX::Pipeline::Rule::MotionMetaDataRule",
+ "data": {
+ "motionEventTable": {
+ "tracks": [
+ {
+ "name": "Sync",
+ "deletable": false,
+ "events": [
+ {
+ "eventDatas": [
+ {
+ "$type": "DiscardFrameEventData"
+ }
+ ],
+ "startTime": 29.299814224243164,
+ "endTime": 33.83555221557617
+ }
+ ]
+ }
+ ]
+ }
+ }
+ },
+ {
+ "$type": "MotionSamplingRule"
+ }
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Gems/MotionMatching/Assets/Animations/run1.fbx.assetinfo b/Gems/MotionMatching/Assets/Animations/run1.fbx.assetinfo
new file mode 100644
index 0000000000..fe0bd2f197
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/run1.fbx.assetinfo
@@ -0,0 +1,41 @@
+{
+ "values": [
+ {
+ "$type": "MotionGroup",
+ "name": "run1",
+ "selectedRootBone": "RootNode.root",
+ "id": "{12953346-AF3A-5481-A54F-9119523C4538}",
+ "rules": {
+ "rules": [
+ {
+ "$type": "EMotionFX::Pipeline::Rule::MotionMetaDataRule",
+ "data": {
+ "motionEventTable": {
+ "tracks": [
+ {
+ "name": "Sync",
+ "deletable": false,
+ "events": [
+ {
+ "eventDatas": [
+ {
+ "$type": "DiscardFrameEventData"
+ }
+ ],
+ "startTime": 23.600000381469727,
+ "endTime": 27.933334350585938
+ }
+ ]
+ }
+ ]
+ }
+ }
+ },
+ {
+ "$type": "MotionSamplingRule"
+ }
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Gems/MotionMatching/Assets/Animations/runpivotturn1.fbx.assetinfo b/Gems/MotionMatching/Assets/Animations/runpivotturn1.fbx.assetinfo
new file mode 100644
index 0000000000..353f4bd81c
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/runpivotturn1.fbx.assetinfo
@@ -0,0 +1,50 @@
+{
+ "values": [
+ {
+ "$type": "MotionGroup",
+ "name": "runpivotturn1",
+ "selectedRootBone": "RootNode.root",
+ "id": "{DEF0D469-00AB-57D0-AF05-6AF1D6563D4A}",
+ "rules": {
+ "rules": [
+ {
+ "$type": "EMotionFX::Pipeline::Rule::MotionMetaDataRule",
+ "data": {
+ "motionEventTable": {
+ "tracks": [
+ {
+ "name": "Sync",
+ "deletable": false,
+ "events": [
+ {
+ "eventDatas": [
+ {
+ "$type": "DiscardFrameEventData"
+ }
+ ],
+ "startTime": 25.080034255981445,
+ "endTime": 28.964109420776367
+ },
+ {
+ "eventDatas": [
+ {
+ "$type": "DiscardFrameEventData"
+ }
+ ],
+ "startTime": 29.574464797973633,
+ "endTime": 36.288368225097656
+ }
+ ]
+ }
+ ]
+ }
+ }
+ },
+ {
+ "$type": "MotionSamplingRule"
+ }
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Gems/MotionMatching/Assets/Animations/snake1.fbx.assetinfo b/Gems/MotionMatching/Assets/Animations/snake1.fbx.assetinfo
new file mode 100644
index 0000000000..5c8961c700
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/snake1.fbx.assetinfo
@@ -0,0 +1,50 @@
+{
+ "values": [
+ {
+ "$type": "MotionGroup",
+ "name": "snake1",
+ "selectedRootBone": "RootNode.root",
+ "id": "{4A29F10E-0083-559F-A78B-282A9EF87E00}",
+ "rules": {
+ "rules": [
+ {
+ "$type": "EMotionFX::Pipeline::Rule::MotionMetaDataRule",
+ "data": {
+ "motionEventTable": {
+ "tracks": [
+ {
+ "name": "Sync",
+ "deletable": false,
+ "events": [
+ {
+ "eventDatas": [
+ {
+ "$type": "DiscardFrameEventData"
+ }
+ ],
+ "startTime": 34.46666717529297,
+ "endTime": 38.733333587646484
+ },
+ {
+ "eventDatas": [
+ {
+ "$type": "DiscardFrameEventData"
+ }
+ ],
+ "startTime": 89.4000015258789,
+ "endTime": 90.86666870117188
+ }
+ ]
+ }
+ ]
+ }
+ }
+ },
+ {
+ "$type": "MotionSamplingRule"
+ }
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Gems/MotionMatching/Assets/Animations/turnonspot1.fbx.assetinfo b/Gems/MotionMatching/Assets/Animations/turnonspot1.fbx.assetinfo
new file mode 100644
index 0000000000..76c0729bb2
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/turnonspot1.fbx.assetinfo
@@ -0,0 +1,106 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Gems/MotionMatching/Assets/Animations/walk1.fbx.assetinfo b/Gems/MotionMatching/Assets/Animations/walk1.fbx.assetinfo
new file mode 100644
index 0000000000..f21f187899
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/walk1.fbx.assetinfo
@@ -0,0 +1,59 @@
+{
+ "values": [
+ {
+ "$type": "MotionGroup",
+ "name": "walk1",
+ "selectedRootBone": "RootNode.root",
+ "id": "{B161FB42-0EC0-51DA-BB0E-F04B73C0DE0C}",
+ "rules": {
+ "rules": [
+ {
+ "$type": "EMotionFX::Pipeline::Rule::MotionMetaDataRule",
+ "data": {
+ "motionEventTable": {
+ "tracks": [
+ {
+ "name": "Sync",
+ "deletable": false,
+ "events": [
+ {
+ "eventDatas": [
+ {
+ "$type": "DiscardFrameEventData"
+ }
+ ],
+ "startTime": 11.533333778381348,
+ "endTime": 12.533333778381348
+ },
+ {
+ "eventDatas": [
+ {
+ "$type": "DiscardFrameEventData"
+ }
+ ],
+ "startTime": 35.20000076293945,
+ "endTime": 37.53333282470703
+ },
+ {
+ "eventDatas": [
+ {
+ "$type": "DiscardFrameEventData"
+ }
+ ],
+ "startTime": 76.33333587646484,
+ "endTime": 93.66667175292969
+ }
+ ]
+ }
+ ]
+ }
+ }
+ },
+ {
+ "$type": "MotionSamplingRule"
+ }
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Gems/MotionMatching/Assets/Animations/walk2.fbx.assetinfo b/Gems/MotionMatching/Assets/Animations/walk2.fbx.assetinfo
new file mode 100644
index 0000000000..c945ba6a6d
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/walk2.fbx.assetinfo
@@ -0,0 +1,50 @@
+{
+ "values": [
+ {
+ "$type": "MotionGroup",
+ "name": "walk2",
+ "selectedRootBone": "RootNode.root",
+ "id": "{D4D1809B-5085-59E4-B98C-D29AE1A90277}",
+ "rules": {
+ "rules": [
+ {
+ "$type": "EMotionFX::Pipeline::Rule::MotionMetaDataRule",
+ "data": {
+ "motionEventTable": {
+ "tracks": [
+ {
+ "name": "Sync",
+ "deletable": false,
+ "events": [
+ {
+ "eventDatas": [
+ {
+ "$type": "DiscardFrameEventData"
+ }
+ ],
+ "startTime": 37.599998474121094,
+ "endTime": 40.266666412353516
+ },
+ {
+ "eventDatas": [
+ {
+ "$type": "DiscardFrameEventData"
+ }
+ ],
+ "startTime": 81.26667022705078,
+ "endTime": 84.0666732788086
+ }
+ ]
+ }
+ ]
+ }
+ }
+ },
+ {
+ "$type": "MotionSamplingRule"
+ }
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Gems/MotionMatching/Assets/Animations/walkpivotturn1.fbx.assetinfo b/Gems/MotionMatching/Assets/Animations/walkpivotturn1.fbx.assetinfo
new file mode 100644
index 0000000000..f603a5858e
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/walkpivotturn1.fbx.assetinfo
@@ -0,0 +1,106 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Gems/MotionMatching/Assets/Animations/walkstopturn1.fbx.assetinfo b/Gems/MotionMatching/Assets/Animations/walkstopturn1.fbx.assetinfo
new file mode 100644
index 0000000000..ffd5dbbd0e
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/walkstopturn1.fbx.assetinfo
@@ -0,0 +1,41 @@
+{
+ "values": [
+ {
+ "$type": "MotionGroup",
+ "name": "walkstopturn1",
+ "selectedRootBone": "RootNode.root",
+ "id": "{D38F0C22-1841-5EBB-A198-9D9441CD7C80}",
+ "rules": {
+ "rules": [
+ {
+ "$type": "EMotionFX::Pipeline::Rule::MotionMetaDataRule",
+ "data": {
+ "motionEventTable": {
+ "tracks": [
+ {
+ "name": "Sync",
+ "deletable": false,
+ "events": [
+ {
+ "eventDatas": [
+ {
+ "$type": "DiscardFrameEventData"
+ }
+ ],
+ "startTime": 63.53333282470703,
+ "endTime": 70.53333282470703
+ }
+ ]
+ }
+ ]
+ }
+ }
+ },
+ {
+ "$type": "MotionSamplingRule"
+ }
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Gems/MotionMatching/Assets/Animations/walkstopturnpivot1.fbx.assetinfo b/Gems/MotionMatching/Assets/Animations/walkstopturnpivot1.fbx.assetinfo
new file mode 100644
index 0000000000..121124029b
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/walkstopturnpivot1.fbx.assetinfo
@@ -0,0 +1,41 @@
+{
+ "values": [
+ {
+ "$type": "MotionGroup",
+ "name": "walkstopturnpivot1",
+ "selectedRootBone": "RootNode.root",
+ "id": "{FCD5DF16-A875-552E-9333-3C7BF8554CBB}",
+ "rules": {
+ "rules": [
+ {
+ "$type": "EMotionFX::Pipeline::Rule::MotionMetaDataRule",
+ "data": {
+ "motionEventTable": {
+ "tracks": [
+ {
+ "name": "Sync",
+ "deletable": false,
+ "events": [
+ {
+ "eventDatas": [
+ {
+ "$type": "DiscardFrameEventData"
+ }
+ ],
+ "startTime": 53.06666564941406,
+ "endTime": 55.86666488647461
+ }
+ ]
+ }
+ ]
+ }
+ }
+ },
+ {
+ "$type": "MotionSamplingRule"
+ }
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Gems/MotionMatching/Assets/Animations/walkturns1.fbx.assetinfo b/Gems/MotionMatching/Assets/Animations/walkturns1.fbx.assetinfo
new file mode 100644
index 0000000000..5f200f546e
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Animations/walkturns1.fbx.assetinfo
@@ -0,0 +1,50 @@
+{
+ "values": [
+ {
+ "$type": "MotionGroup",
+ "name": "walkturns1",
+ "selectedRootBone": "RootNode.root",
+ "id": "{FD1981AB-0270-56F7-9062-ABA4D73686F9}",
+ "rules": {
+ "rules": [
+ {
+ "$type": "EMotionFX::Pipeline::Rule::MotionMetaDataRule",
+ "data": {
+ "motionEventTable": {
+ "tracks": [
+ {
+ "name": "Sync",
+ "deletable": false,
+ "events": [
+ {
+ "eventDatas": [
+ {
+ "$type": "DiscardFrameEventData"
+ }
+ ],
+ "startTime": 32.266666412353516,
+ "endTime": 51.33333206176758
+ },
+ {
+ "eventDatas": [
+ {
+ "$type": "DiscardFrameEventData"
+ }
+ ],
+ "startTime": 86.86666870117188,
+ "endTime": 89.46666717529297
+ }
+ ]
+ }
+ ]
+ }
+ }
+ },
+ {
+ "$type": "MotionSamplingRule"
+ }
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Gems/MotionMatching/Assets/Character/Rin.fbx b/Gems/MotionMatching/Assets/Character/Rin.fbx
new file mode 100644
index 0000000000..3041a9efe1
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Character/Rin.fbx
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d38ee57dcf86d1209982ffa29cf5a2b42f5e0e0b86f5045a8485e3e431d74b03
+size 12267120
diff --git a/Gems/MotionMatching/Assets/Character/Rin.fbx.assetinfo b/Gems/MotionMatching/Assets/Character/Rin.fbx.assetinfo
new file mode 100644
index 0000000000..1a3d8be596
--- /dev/null
+++ b/Gems/MotionMatching/Assets/Character/Rin.fbx.assetinfo
@@ -0,0 +1,1543 @@
+{
+ "values": [
+ {
+ "$type": "ActorGroup",
+ "name": "RinMM",
+ "id": "{3B0C7D44-39A9-5B89-B361-4789175AE832}",
+ "rules": {
+ "rules": [
+ {
+ "$type": "MetaDataRule",
+ "metaData": "AdjustActor -actorID $(ACTORID) -name \"RinMM\"\nActorSetCollisionMeshes -actorID $(ACTORID) -lod 0 -nodeList \"\"\nAdjustActor -actorID $(ACTORID) -nodesExcludedFromBounds \"\" -nodeAction \"select\"\nAdjustActor -actorID $(ACTORID) -nodeAction \"replace\" -attachmentNodes \"\"\nAdjustActor -actorID $(ACTORID) -motionExtractionNodeName \"root\"\nAdjustActor -actorID $(ACTORID) -mirrorSetup \"L_leg_JNT,R_leg_JNT;R_leg_JNT,L_leg_JNT;L_ribbon_01_JNT,R_ribbon_01_JNT;R_ribbon_01_JNT,L_ribbon_01_JNT;L_knee_JNT,R_knee_JNT;L_leg_twist_JNT,R_leg_twist_JNT;R_knee_JNT,L_knee_JNT;R_leg_twist_JNT,L_leg_twist_JNT;L_ribbon_02_JNT,R_ribbon_02_JNT;R_ribbon_02_JNT,L_ribbon_02_JNT;L_foot_JNT,R_foot_JNT;L_knee_twist_JNT,R_knee_twist_JNT;R_foot_JNT,L_foot_JNT;R_knee_twist_JNT,L_knee_twist_JNT;L_toe_JNT,R_toe_JNT;R_toe_JNT,L_toe_JNT;L_clavicle_JNT,R_clavicle_JNT;R_clavicle_JNT,L_clavicle_JNT;L_neckCollar_01_JNT,R_neckCollar_01_JNT;L_neckCollar_02_JNT,R_neckCollar_02_JNT;R_neckCollar_01_JNT,L_neckCollar_01_JNT;R_neckCollar_02_JNT,L_neckCollar_02_JNT;L_arm_JNT,R_arm_JNT;L_tassle_01_JNT,R_tassle_01_JNT;L_tassleLoop_01_JNT,R_tassleLoop_01_JNT;L_armPit_corr_JNT,R_armPit_corr_JNT;R_arm_JNT,L_arm_JNT;R_tassle_01_JNT,L_tassle_01_JNT;R_tassleLoop_01_JNT,L_tassleLoop_01_JNT;R_armPit_corr_JNT,L_armPit_corr_JNT;L_elbow_JNT,R_elbow_JNT;L_arm_twist_JNT,R_arm_twist_JNT;L_armBulge_corr_JNT,R_armBulge_corr_JNT;L_tassle_02_JNT,R_tassle_02_JNT;L_tassleLoop_02_JNT,R_tassleLoop_02_JNT;R_elbow_JNT,L_elbow_JNT;R_arm_twist_JNT,L_arm_twist_JNT;R_armBulge_corr_JNT,L_armBulge_corr_JNT;R_tassle_02_JNT,L_tassle_02_JNT;R_tassleLoop_02_JNT,L_tassleLoop_02_JNT;L_wrist_JNT,R_wrist_JNT;L_elbow_twist_JNT,R_elbow_twist_JNT;L_tassle_03_JNT,R_tassle_03_JNT;L_brow_inner_JNT,R_brow_inner_JNT;L_brow_mid_JNT,R_brow_mid_JNT;L_brow_outer_JNT,R_brow_outer_JNT;L_nostril_inner_JNT,R_nostril_inner_JNT;L_nostril_outer_JNT,R_nostril_outer_JNT;L_cheekUpper_inner_JNT,R_cheekUpper_inner_JNT;L_squint_mid_JNT,R_squint_mid_JNT;L_squint_outer_JNT,R_squint_outer_JNT;L_squint_inner_JNT,R_squint_inner_JNT;L_zygomatic_outer_JNT,R_zygomatic_outer_JNT;L_cheekBone_JNT,R_cheekBone_JNT;L_ear_JNT,R_ear_JNT;L_chin_below_JNT,R_chin_below_JNT;L_eyelid_lower_JNT,R_eyelid_lower_JNT;L_eyelid_upper_JNT,R_eyelid_upper_JNT;L_eye_JNT,R_eye_JNT;L_lipUpper_JNT,R_lipUpper_JNT;L_lipLevator_inner_JNT,R_lipLevator_inner_JNT;L_lipLevator_corner_JNT,R_lipLevator_corner_JNT;L_cheekUpper_outer_JNT,R_cheekUpper_outer_JNT;L_cheekUpper_mid_JNT,R_cheekUpper_mid_JNT;R_eyelid_upper_JNT,L_eyelid_upper_JNT;R_eyelid_lower_JNT,L_eyelid_lower_JNT;R_nostril_inner_JNT,L_nostril_inner_JNT;R_lipLevator_inner_JNT,L_lipLevator_inner_JNT;R_cheekBone_JNT,L_cheekBone_JNT;R_zygomatic_outer_JNT,L_zygomatic_outer_JNT;R_lipUpper_JNT,L_lipUpper_JNT;R_chin_below_JNT,L_chin_below_JNT;R_ear_JNT,L_ear_JNT;R_eye_JNT,L_eye_JNT;R_brow_inner_JNT,L_brow_inner_JNT;R_brow_mid_JNT,L_brow_mid_JNT;R_brow_outer_JNT,L_brow_outer_JNT;R_lipLevator_corner_JNT,L_lipLevator_corner_JNT;R_cheekUpper_outer_JNT,L_cheekUpper_outer_JNT;R_cheekUpper_mid_JNT,L_cheekUpper_mid_JNT;R_nostril_outer_JNT,L_nostril_outer_JNT;R_cheekUpper_inner_JNT,L_cheekUpper_inner_JNT;R_squint_inner_JNT,L_squint_inner_JNT;R_squint_mid_JNT,L_squint_mid_JNT;R_squint_outer_JNT,L_squint_outer_JNT;L_lipUpper_corner_JNT,R_lipUpper_corner_JNT;R_lipUpper_corner_JNT,L_lipUpper_corner_JNT;R_frontalis_inner_JNT,L_frontalis_inner_JNT;R_frontalis_outer_JNT,L_frontalis_outer_JNT;L_frontalis_outer_JNT,R_frontalis_outer_JNT;L_frontalis_inner_JNT,R_frontalis_inner_JNT;R_eyelid_fold_JNT,L_eyelid_fold_JNT;L_eyelid_fold_JNT,R_eyelid_fold_JNT;L_eye_bulge_JNT,R_eye_bulge_JNT;R_eye_bulge_JNT,L_eye_bulge_JNT;R_wrist_JNT,L_wrist_JNT;R_elbow_twist_JNT,L_elbow_twist_JNT;R_tassle_03_JNT,L_tassle_03_JNT;L_thumb_01_JNT,R_thumb_01_JNT;L_index_root_JNT,R_index_root_JNT;L_middle_root_JNT,R_middle_root_JNT;L_ring_root_JNT,R_ring_root_JNT;L_pinky_root_JNT,R_pinky_root_JNT;L_depressor_JNT,R_depressor_JNT;R_depressor_JNT,L_depressor_JNT;L_lip_nasolabial_JNT,R_lip_nasolabial_JNT;R_mouth_corner_JNT,L_mouth_corner_JNT;R_lip_nasolabial_JNT,L_lip_nasolabial_JNT;R_lipLower_corner_JNT,L_lipLower_corner_JNT;R_lipLower_JNT,L_lipLower_JNT;L_lipLower_JNT,R_lipLower_JNT;L_mouth_corner_JNT,R_mouth_corner_JNT;L_lipLower_corner_JNT,R_lipLower_corner_JNT;R_jaw_clench_JNT,L_jaw_clench_JNT;L_jaw_clench_JNT,R_jaw_clench_JNT;L_zygomatic_inner_JNT,R_zygomatic_inner_JNT;R_zygomatic_inner_JNT,L_zygomatic_inner_JNT;R_thumb_01_JNT,L_thumb_01_JNT;R_index_root_JNT,L_index_root_JNT;R_middle_root_JNT,L_middle_root_JNT;R_ring_root_JNT,L_ring_root_JNT;R_pinky_root_JNT,L_pinky_root_JNT;L_thumb_02_JNT,R_thumb_02_JNT;L_index_01_JNT,R_index_01_JNT;L_middle_01_JNT,R_middle_01_JNT;L_ring_01_JNT,R_ring_01_JNT;L_pinky_01_JNT,R_pinky_01_JNT;R_thumb_02_JNT,L_thumb_02_JNT;R_index_01_JNT,L_index_01_JNT;R_middle_01_JNT,L_middle_01_JNT;R_ring_01_JNT,L_ring_01_JNT;R_pinky_01_JNT,L_pinky_01_JNT;L_thumb_03_JNT,R_thumb_03_JNT;L_index_02_JNT,R_index_02_JNT;L_middle_02_JNT,R_middle_02_JNT;L_ring_02_JNT,R_ring_02_JNT;L_pinky_02_JNT,R_pinky_02_JNT;R_thumb_03_JNT,L_thumb_03_JNT;R_index_02_JNT,L_index_02_JNT;R_middle_02_JNT,L_middle_02_JNT;R_ring_02_JNT,L_ring_02_JNT;R_pinky_02_JNT,L_pinky_02_JNT;L_index_03_JNT,R_index_03_JNT;L_middle_03_JNT,R_middle_03_JNT;L_ring_03_JNT,R_ring_03_JNT;L_pinky_03_JNT,R_pinky_03_JNT;R_index_03_JNT,L_index_03_JNT;R_middle_03_JNT,L_middle_03_JNT;R_ring_03_JNT,L_ring_03_JNT;R_pinky_03_JNT,L_pinky_03_JNT;\"\n"
+ }
+ ]
+ }
+ },
+ {
+ "$type": "{5B03C8E6-8CEE-4DA0-A7FA-CD88689DD45B} MeshGroup",
+ "id": "{3C9D4C02-8F36-5F94-8B47-CEC412E736F3}",
+ "name": "anigmarinactor",
+ "NodeSelectionList": {
+ "unselectedNodes": [
+ "RootNode",
+ "RootNode.rin_eyeballs",
+ "RootNode.rin_haircap",
+ "RootNode.rin_cloth",
+ "RootNode.rin_leather",
+ "RootNode.rin_armor",
+ "RootNode.rin_hands",
+ "RootNode.rin_props",
+ "RootNode.rin_teeth_low",
+ "RootNode.rin_teeth_up",
+ "RootNode.rin_tongue",
+ "RootNode.rin_face",
+ "RootNode.rin_armorstraps",
+ "RootNode.rin_hairplanes",
+ "RootNode.rin_eyebrows_top",
+ "RootNode.rin_eyelashes_top",
+ "RootNode.rin_eyelashes_lower",
+ "RootNode.rin_eyecover",
+ "RootNode.rin_facefuzz",
+ "RootNode.rin_haircards",
+ "RootNode.rin_lash_01",
+ "RootNode.rin_lash_02",
+ "RootNode.rin_lash_03",
+ "RootNode.rin_eyewetness",
+ "RootNode.rin_eyebrows_lower",
+ "RootNode.rin_tearduct",
+ "RootNode.root",
+ "RootNode.rin_eyeballs.rin_eyeballs_1",
+ "RootNode.rin_eyeballs.rin_eyeballs_2",
+ "RootNode.rin_haircap.rin_haircap_1",
+ "RootNode.rin_haircap.rin_haircap_2",
+ "RootNode.rin_cloth.rin_cloth_1",
+ "RootNode.rin_cloth.rin_cloth_2",
+ "RootNode.rin_leather.rin_leather_1",
+ "RootNode.rin_leather.rin_leather_2",
+ "RootNode.rin_armor.rin_armor_1",
+ "RootNode.rin_armor.rin_armor_2",
+ "RootNode.rin_hands.rin_hands_1",
+ "RootNode.rin_hands.rin_hands_2",
+ "RootNode.rin_props.rin_props_1",
+ "RootNode.rin_props.rin_props_2",
+ "RootNode.rin_teeth_low.rin_teeth_low_1",
+ "RootNode.rin_teeth_low.rin_teeth_low_2",
+ "RootNode.rin_teeth_up.rin_teeth_up_1",
+ "RootNode.rin_teeth_up.rin_teeth_up_2",
+ "RootNode.rin_tongue.rin_tongue_1",
+ "RootNode.rin_tongue.rin_tongue_2",
+ "RootNode.rin_face.rin_face_1",
+ "RootNode.rin_face.rin_face_2",
+ "RootNode.rin_armorstraps.rin_armorstraps_1",
+ "RootNode.rin_armorstraps.rin_armorstraps_2",
+ "RootNode.rin_hairplanes.rin_hairplanes_1",
+ "RootNode.rin_hairplanes.rin_hairplanes_2",
+ "RootNode.rin_eyebrows_top.rin_eyebrows_top_1",
+ "RootNode.rin_eyebrows_top.rin_eyebrows_top_2",
+ "RootNode.rin_eyelashes_top.rin_eyelashes_top_1",
+ "RootNode.rin_eyelashes_top.rin_eyelashes_top_2",
+ "RootNode.rin_eyelashes_lower.rin_eyelashes_lower_1",
+ "RootNode.rin_eyelashes_lower.rin_eyelashes_lower_2",
+ "RootNode.rin_eyecover.rin_eyecover_1",
+ "RootNode.rin_eyecover.rin_eyecover_2",
+ "RootNode.rin_facefuzz.rin_facefuzz_1",
+ "RootNode.rin_facefuzz.rin_facefuzz_2",
+ "RootNode.rin_haircards.rin_haircards_1",
+ "RootNode.rin_haircards.rin_haircards_2",
+ "RootNode.rin_lash_01.rin_lash_01_1",
+ "RootNode.rin_lash_01.rin_lash_01_2",
+ "RootNode.rin_lash_02.rin_lash_02_1",
+ "RootNode.rin_lash_02.rin_lash_02_2",
+ "RootNode.rin_lash_03.rin_lash_03_1",
+ "RootNode.rin_lash_03.rin_lash_03_2",
+ "RootNode.rin_eyewetness.rin_eyewetness_1",
+ "RootNode.rin_eyewetness.rin_eyewetness_2",
+ "RootNode.rin_eyebrows_lower.rin_eyebrows_lower_1",
+ "RootNode.rin_eyebrows_lower.rin_eyebrows_lower_2",
+ "RootNode.rin_tearduct.rin_tearduct_1",
+ "RootNode.rin_tearduct.rin_tearduct_2",
+ "RootNode.root.C_pelvis_JNT",
+ "RootNode.rin_eyeballs.rin_eyeballs_1.Bitangent",
+ "RootNode.rin_eyeballs.rin_eyeballs_1.SkinWeight_",
+ "RootNode.rin_eyeballs.rin_eyeballs_1.transform",
+ "RootNode.rin_eyeballs.rin_eyeballs_1.Tangent",
+ "RootNode.rin_eyeballs.rin_eyeballs_1.map1",
+ "RootNode.rin_eyeballs.rin_eyeballs_1.rin_m_eyeballs",
+ "RootNode.rin_eyeballs.rin_eyeballs_2.Bitangent",
+ "RootNode.rin_eyeballs.rin_eyeballs_2.SkinWeight_",
+ "RootNode.rin_eyeballs.rin_eyeballs_2.transform",
+ "RootNode.rin_eyeballs.rin_eyeballs_2.Tangent",
+ "RootNode.rin_eyeballs.rin_eyeballs_2.map1",
+ "RootNode.rin_eyeballs.rin_eyeballs_2.rin_m_eyeballs",
+ "RootNode.rin_haircap.rin_haircap_1.Bitangent",
+ "RootNode.rin_haircap.rin_haircap_1.SkinWeight_",
+ "RootNode.rin_haircap.rin_haircap_1.transform",
+ "RootNode.rin_haircap.rin_haircap_1.Tangent",
+ "RootNode.rin_haircap.rin_haircap_1.map1",
+ "RootNode.rin_haircap.rin_haircap_1.rin_m_haircap",
+ "RootNode.rin_haircap.rin_haircap_2.Bitangent",
+ "RootNode.rin_haircap.rin_haircap_2.SkinWeight_",
+ "RootNode.rin_haircap.rin_haircap_2.transform",
+ "RootNode.rin_haircap.rin_haircap_2.Tangent",
+ "RootNode.rin_haircap.rin_haircap_2.map1",
+ "RootNode.rin_haircap.rin_haircap_2.rin_m_haircap",
+ "RootNode.rin_cloth.rin_cloth_1.Col0",
+ "RootNode.rin_cloth.rin_cloth_1.Bitangent",
+ "RootNode.rin_cloth.rin_cloth_1.SkinWeight_",
+ "RootNode.rin_cloth.rin_cloth_1.transform",
+ "RootNode.rin_cloth.rin_cloth_1.Tangent",
+ "RootNode.rin_cloth.rin_cloth_1.UVMap",
+ "RootNode.rin_cloth.rin_cloth_1.rin_m_cloth",
+ "RootNode.rin_cloth.rin_cloth_2.Col0",
+ "RootNode.rin_cloth.rin_cloth_2.Bitangent",
+ "RootNode.rin_cloth.rin_cloth_2.SkinWeight_",
+ "RootNode.rin_cloth.rin_cloth_2.transform",
+ "RootNode.rin_cloth.rin_cloth_2.Tangent",
+ "RootNode.rin_cloth.rin_cloth_2.UVMap",
+ "RootNode.rin_cloth.rin_cloth_2.rin_m_cloth",
+ "RootNode.rin_leather.rin_leather_1.Col0",
+ "RootNode.rin_leather.rin_leather_1.Bitangent",
+ "RootNode.rin_leather.rin_leather_1.SkinWeight_",
+ "RootNode.rin_leather.rin_leather_1.transform",
+ "RootNode.rin_leather.rin_leather_1.Tangent",
+ "RootNode.rin_leather.rin_leather_1.UVMap",
+ "RootNode.rin_leather.rin_leather_1.rin_m_leather",
+ "RootNode.rin_leather.rin_leather_2.Col0",
+ "RootNode.rin_leather.rin_leather_2.Bitangent",
+ "RootNode.rin_leather.rin_leather_2.SkinWeight_",
+ "RootNode.rin_leather.rin_leather_2.transform",
+ "RootNode.rin_leather.rin_leather_2.Tangent",
+ "RootNode.rin_leather.rin_leather_2.UVMap",
+ "RootNode.rin_leather.rin_leather_2.rin_m_leather",
+ "RootNode.rin_armor.rin_armor_1.Col0",
+ "RootNode.rin_armor.rin_armor_1.Bitangent",
+ "RootNode.rin_armor.rin_armor_1.SkinWeight_",
+ "RootNode.rin_armor.rin_armor_1.transform",
+ "RootNode.rin_armor.rin_armor_1.Tangent",
+ "RootNode.rin_armor.rin_armor_1.UVMap",
+ "RootNode.rin_armor.rin_armor_1.rin_m_armor",
+ "RootNode.rin_armor.rin_armor_2.Col0",
+ "RootNode.rin_armor.rin_armor_2.Bitangent",
+ "RootNode.rin_armor.rin_armor_2.SkinWeight_",
+ "RootNode.rin_armor.rin_armor_2.transform",
+ "RootNode.rin_armor.rin_armor_2.Tangent",
+ "RootNode.rin_armor.rin_armor_2.UVMap",
+ "RootNode.rin_armor.rin_armor_2.rin_m_armor",
+ "RootNode.rin_hands.rin_hands_1.Col0",
+ "RootNode.rin_hands.rin_hands_1.Bitangent",
+ "RootNode.rin_hands.rin_hands_1.SkinWeight_",
+ "RootNode.rin_hands.rin_hands_1.transform",
+ "RootNode.rin_hands.rin_hands_1.Tangent",
+ "RootNode.rin_hands.rin_hands_1.UVMap",
+ "RootNode.rin_hands.rin_hands_1.rin_m_hands",
+ "RootNode.rin_hands.rin_hands_2.Col0",
+ "RootNode.rin_hands.rin_hands_2.Bitangent",
+ "RootNode.rin_hands.rin_hands_2.SkinWeight_",
+ "RootNode.rin_hands.rin_hands_2.transform",
+ "RootNode.rin_hands.rin_hands_2.Tangent",
+ "RootNode.rin_hands.rin_hands_2.UVMap",
+ "RootNode.rin_hands.rin_hands_2.rin_m_hands",
+ "RootNode.rin_props.rin_props_1.Bitangent",
+ "RootNode.rin_props.rin_props_1.SkinWeight_",
+ "RootNode.rin_props.rin_props_1.transform",
+ "RootNode.rin_props.rin_props_1.Tangent",
+ "RootNode.rin_props.rin_props_1.UVMap",
+ "RootNode.rin_props.rin_props_1.map1",
+ "RootNode.rin_props.rin_props_1.rin_m_props",
+ "RootNode.rin_props.rin_props_2.Bitangent",
+ "RootNode.rin_props.rin_props_2.SkinWeight_",
+ "RootNode.rin_props.rin_props_2.transform",
+ "RootNode.rin_props.rin_props_2.Tangent",
+ "RootNode.rin_props.rin_props_2.UVMap",
+ "RootNode.rin_props.rin_props_2.map1",
+ "RootNode.rin_props.rin_props_2.rin_m_props",
+ "RootNode.rin_teeth_low.rin_teeth_low_1.Bitangent",
+ "RootNode.rin_teeth_low.rin_teeth_low_1.SkinWeight_",
+ "RootNode.rin_teeth_low.rin_teeth_low_1.transform",
+ "RootNode.rin_teeth_low.rin_teeth_low_1.Tangent",
+ "RootNode.rin_teeth_low.rin_teeth_low_1.map1",
+ "RootNode.rin_teeth_low.rin_teeth_low_1.rin_m_mouth",
+ "RootNode.rin_teeth_low.rin_teeth_low_2.Bitangent",
+ "RootNode.rin_teeth_low.rin_teeth_low_2.SkinWeight_",
+ "RootNode.rin_teeth_low.rin_teeth_low_2.transform",
+ "RootNode.rin_teeth_low.rin_teeth_low_2.Tangent",
+ "RootNode.rin_teeth_low.rin_teeth_low_2.map1",
+ "RootNode.rin_teeth_low.rin_teeth_low_2.rin_m_mouth",
+ "RootNode.rin_teeth_up.rin_teeth_up_1.Bitangent",
+ "RootNode.rin_teeth_up.rin_teeth_up_1.SkinWeight_",
+ "RootNode.rin_teeth_up.rin_teeth_up_1.transform",
+ "RootNode.rin_teeth_up.rin_teeth_up_1.Tangent",
+ "RootNode.rin_teeth_up.rin_teeth_up_1.map1",
+ "RootNode.rin_teeth_up.rin_teeth_up_1.rin_m_mouth",
+ "RootNode.rin_teeth_up.rin_teeth_up_2.Bitangent",
+ "RootNode.rin_teeth_up.rin_teeth_up_2.SkinWeight_",
+ "RootNode.rin_teeth_up.rin_teeth_up_2.transform",
+ "RootNode.rin_teeth_up.rin_teeth_up_2.Tangent",
+ "RootNode.rin_teeth_up.rin_teeth_up_2.map1",
+ "RootNode.rin_teeth_up.rin_teeth_up_2.rin_m_mouth",
+ "RootNode.rin_tongue.rin_tongue_1.Bitangent",
+ "RootNode.rin_tongue.rin_tongue_1.SkinWeight_",
+ "RootNode.rin_tongue.rin_tongue_1.transform",
+ "RootNode.rin_tongue.rin_tongue_1.Tangent",
+ "RootNode.rin_tongue.rin_tongue_1.map1",
+ "RootNode.rin_tongue.rin_tongue_1.rin_m_mouth",
+ "RootNode.rin_tongue.rin_tongue_2.Bitangent",
+ "RootNode.rin_tongue.rin_tongue_2.SkinWeight_",
+ "RootNode.rin_tongue.rin_tongue_2.transform",
+ "RootNode.rin_tongue.rin_tongue_2.Tangent",
+ "RootNode.rin_tongue.rin_tongue_2.map1",
+ "RootNode.rin_tongue.rin_tongue_2.rin_m_mouth",
+ "RootNode.rin_face.rin_face_1.Bitangent",
+ "RootNode.rin_face.rin_face_1.SkinWeight_",
+ "RootNode.rin_face.rin_face_1.transform",
+ "RootNode.rin_face.rin_face_1.Tangent",
+ "RootNode.rin_face.rin_face_1.map1",
+ "RootNode.rin_face.rin_face_1.rin_m_face",
+ "RootNode.rin_face.rin_face_2.Bitangent",
+ "RootNode.rin_face.rin_face_2.SkinWeight_",
+ "RootNode.rin_face.rin_face_2.transform",
+ "RootNode.rin_face.rin_face_2.Tangent",
+ "RootNode.rin_face.rin_face_2.map1",
+ "RootNode.rin_face.rin_face_2.rin_m_face",
+ "RootNode.rin_armorstraps.rin_armorstraps_1.Bitangent",
+ "RootNode.rin_armorstraps.rin_armorstraps_1.SkinWeight_",
+ "RootNode.rin_armorstraps.rin_armorstraps_1.transform",
+ "RootNode.rin_armorstraps.rin_armorstraps_1.Tangent",
+ "RootNode.rin_armorstraps.rin_armorstraps_1.map1",
+ "RootNode.rin_armorstraps.rin_armorstraps_1.rin_m_armor",
+ "RootNode.rin_armorstraps.rin_armorstraps_2.Bitangent",
+ "RootNode.rin_armorstraps.rin_armorstraps_2.SkinWeight_",
+ "RootNode.rin_armorstraps.rin_armorstraps_2.transform",
+ "RootNode.rin_armorstraps.rin_armorstraps_2.Tangent",
+ "RootNode.rin_armorstraps.rin_armorstraps_2.map1",
+ "RootNode.rin_armorstraps.rin_armorstraps_2.rin_m_armor",
+ "RootNode.rin_hairplanes.rin_hairplanes_1.Bitangent",
+ "RootNode.rin_hairplanes.rin_hairplanes_1.SkinWeight_",
+ "RootNode.rin_hairplanes.rin_hairplanes_1.transform",
+ "RootNode.rin_hairplanes.rin_hairplanes_1.Tangent",
+ "RootNode.rin_hairplanes.rin_hairplanes_1.map1",
+ "RootNode.rin_hairplanes.rin_hairplanes_1.rin_m_hairplanes",
+ "RootNode.rin_hairplanes.rin_hairplanes_2.Bitangent",
+ "RootNode.rin_hairplanes.rin_hairplanes_2.SkinWeight_",
+ "RootNode.rin_hairplanes.rin_hairplanes_2.transform",
+ "RootNode.rin_hairplanes.rin_hairplanes_2.Tangent",
+ "RootNode.rin_hairplanes.rin_hairplanes_2.map1",
+ "RootNode.rin_hairplanes.rin_hairplanes_2.rin_m_hairplanes",
+ "RootNode.rin_eyebrows_top.rin_eyebrows_top_1.Bitangent",
+ "RootNode.rin_eyebrows_top.rin_eyebrows_top_1.SkinWeight_",
+ "RootNode.rin_eyebrows_top.rin_eyebrows_top_1.transform",
+ "RootNode.rin_eyebrows_top.rin_eyebrows_top_1.Tangent",
+ "RootNode.rin_eyebrows_top.rin_eyebrows_top_1.map1",
+ "RootNode.rin_eyebrows_top.rin_eyebrows_top_1.rin_m_eyebrow",
+ "RootNode.rin_eyebrows_top.rin_eyebrows_top_2.Bitangent",
+ "RootNode.rin_eyebrows_top.rin_eyebrows_top_2.SkinWeight_",
+ "RootNode.rin_eyebrows_top.rin_eyebrows_top_2.transform",
+ "RootNode.rin_eyebrows_top.rin_eyebrows_top_2.Tangent",
+ "RootNode.rin_eyebrows_top.rin_eyebrows_top_2.map1",
+ "RootNode.rin_eyebrows_top.rin_eyebrows_top_2.rin_m_eyebrow",
+ "RootNode.rin_eyelashes_top.rin_eyelashes_top_1.Bitangent",
+ "RootNode.rin_eyelashes_top.rin_eyelashes_top_1.SkinWeight_",
+ "RootNode.rin_eyelashes_top.rin_eyelashes_top_1.transform",
+ "RootNode.rin_eyelashes_top.rin_eyelashes_top_1.Tangent",
+ "RootNode.rin_eyelashes_top.rin_eyelashes_top_1.map1",
+ "RootNode.rin_eyelashes_top.rin_eyelashes_top_1.rin_m_lashes",
+ "RootNode.rin_eyelashes_top.rin_eyelashes_top_2.Bitangent",
+ "RootNode.rin_eyelashes_top.rin_eyelashes_top_2.SkinWeight_",
+ "RootNode.rin_eyelashes_top.rin_eyelashes_top_2.transform",
+ "RootNode.rin_eyelashes_top.rin_eyelashes_top_2.Tangent",
+ "RootNode.rin_eyelashes_top.rin_eyelashes_top_2.map1",
+ "RootNode.rin_eyelashes_top.rin_eyelashes_top_2.rin_m_lashes",
+ "RootNode.rin_eyelashes_lower.rin_eyelashes_lower_1.Bitangent",
+ "RootNode.rin_eyelashes_lower.rin_eyelashes_lower_1.SkinWeight_",
+ "RootNode.rin_eyelashes_lower.rin_eyelashes_lower_1.transform",
+ "RootNode.rin_eyelashes_lower.rin_eyelashes_lower_1.Tangent",
+ "RootNode.rin_eyelashes_lower.rin_eyelashes_lower_1.map1",
+ "RootNode.rin_eyelashes_lower.rin_eyelashes_lower_1.rin_m_eyebrow",
+ "RootNode.rin_eyelashes_lower.rin_eyelashes_lower_2.Bitangent",
+ "RootNode.rin_eyelashes_lower.rin_eyelashes_lower_2.SkinWeight_",
+ "RootNode.rin_eyelashes_lower.rin_eyelashes_lower_2.transform",
+ "RootNode.rin_eyelashes_lower.rin_eyelashes_lower_2.Tangent",
+ "RootNode.rin_eyelashes_lower.rin_eyelashes_lower_2.map1",
+ "RootNode.rin_eyelashes_lower.rin_eyelashes_lower_2.rin_m_eyebrow",
+ "RootNode.rin_eyecover.rin_eyecover_1.Bitangent",
+ "RootNode.rin_eyecover.rin_eyecover_1.SkinWeight_",
+ "RootNode.rin_eyecover.rin_eyecover_1.transform",
+ "RootNode.rin_eyecover.rin_eyecover_1.Tangent",
+ "RootNode.rin_eyecover.rin_eyecover_1.map1",
+ "RootNode.rin_eyecover.rin_eyecover_1.rin_m_eyecover",
+ "RootNode.rin_eyecover.rin_eyecover_2.Bitangent",
+ "RootNode.rin_eyecover.rin_eyecover_2.SkinWeight_",
+ "RootNode.rin_eyecover.rin_eyecover_2.transform",
+ "RootNode.rin_eyecover.rin_eyecover_2.Tangent",
+ "RootNode.rin_eyecover.rin_eyecover_2.map1",
+ "RootNode.rin_eyecover.rin_eyecover_2.rin_m_eyecover",
+ "RootNode.rin_facefuzz.rin_facefuzz_1.Bitangent",
+ "RootNode.rin_facefuzz.rin_facefuzz_1.SkinWeight_",
+ "RootNode.rin_facefuzz.rin_facefuzz_1.transform",
+ "RootNode.rin_facefuzz.rin_facefuzz_1.Tangent",
+ "RootNode.rin_facefuzz.rin_facefuzz_1.map1",
+ "RootNode.rin_facefuzz.rin_facefuzz_1.rin_m_fuzz",
+ "RootNode.rin_facefuzz.rin_facefuzz_2.Bitangent",
+ "RootNode.rin_facefuzz.rin_facefuzz_2.SkinWeight_",
+ "RootNode.rin_facefuzz.rin_facefuzz_2.transform",
+ "RootNode.rin_facefuzz.rin_facefuzz_2.Tangent",
+ "RootNode.rin_facefuzz.rin_facefuzz_2.map1",
+ "RootNode.rin_facefuzz.rin_facefuzz_2.rin_m_fuzz",
+ "RootNode.rin_haircards.rin_haircards_1.Bitangent",
+ "RootNode.rin_haircards.rin_haircards_1.SkinWeight_",
+ "RootNode.rin_haircards.rin_haircards_1.transform",
+ "RootNode.rin_haircards.rin_haircards_1.Tangent",
+ "RootNode.rin_haircards.rin_haircards_1.map1",
+ "RootNode.rin_haircards.rin_haircards_1.rin_m_haircards",
+ "RootNode.rin_haircards.rin_haircards_2.Bitangent",
+ "RootNode.rin_haircards.rin_haircards_2.SkinWeight_",
+ "RootNode.rin_haircards.rin_haircards_2.transform",
+ "RootNode.rin_haircards.rin_haircards_2.Tangent",
+ "RootNode.rin_haircards.rin_haircards_2.map1",
+ "RootNode.rin_haircards.rin_haircards_2.rin_m_haircards",
+ "RootNode.rin_lash_01.rin_lash_01_1.Bitangent",
+ "RootNode.rin_lash_01.rin_lash_01_1.SkinWeight_",
+ "RootNode.rin_lash_01.rin_lash_01_1.transform",
+ "RootNode.rin_lash_01.rin_lash_01_1.Tangent",
+ "RootNode.rin_lash_01.rin_lash_01_1.map1",
+ "RootNode.rin_lash_01.rin_lash_01_1.rin_m_lashes",
+ "RootNode.rin_lash_01.rin_lash_01_2.Bitangent",
+ "RootNode.rin_lash_01.rin_lash_01_2.SkinWeight_",
+ "RootNode.rin_lash_01.rin_lash_01_2.transform",
+ "RootNode.rin_lash_01.rin_lash_01_2.Tangent",
+ "RootNode.rin_lash_01.rin_lash_01_2.map1",
+ "RootNode.rin_lash_01.rin_lash_01_2.rin_m_lashes",
+ "RootNode.rin_lash_02.rin_lash_02_1.Bitangent",
+ "RootNode.rin_lash_02.rin_lash_02_1.SkinWeight_",
+ "RootNode.rin_lash_02.rin_lash_02_1.transform",
+ "RootNode.rin_lash_02.rin_lash_02_1.Tangent",
+ "RootNode.rin_lash_02.rin_lash_02_1.map1",
+ "RootNode.rin_lash_02.rin_lash_02_1.rin_m_lashes",
+ "RootNode.rin_lash_02.rin_lash_02_2.Bitangent",
+ "RootNode.rin_lash_02.rin_lash_02_2.SkinWeight_",
+ "RootNode.rin_lash_02.rin_lash_02_2.transform",
+ "RootNode.rin_lash_02.rin_lash_02_2.Tangent",
+ "RootNode.rin_lash_02.rin_lash_02_2.map1",
+ "RootNode.rin_lash_02.rin_lash_02_2.rin_m_lashes",
+ "RootNode.rin_lash_03.rin_lash_03_1.Bitangent",
+ "RootNode.rin_lash_03.rin_lash_03_1.SkinWeight_",
+ "RootNode.rin_lash_03.rin_lash_03_1.transform",
+ "RootNode.rin_lash_03.rin_lash_03_1.Tangent",
+ "RootNode.rin_lash_03.rin_lash_03_1.map1",
+ "RootNode.rin_lash_03.rin_lash_03_1.rin_m_lashes",
+ "RootNode.rin_lash_03.rin_lash_03_2.Bitangent",
+ "RootNode.rin_lash_03.rin_lash_03_2.SkinWeight_",
+ "RootNode.rin_lash_03.rin_lash_03_2.transform",
+ "RootNode.rin_lash_03.rin_lash_03_2.Tangent",
+ "RootNode.rin_lash_03.rin_lash_03_2.map1",
+ "RootNode.rin_lash_03.rin_lash_03_2.rin_m_lashes",
+ "RootNode.rin_eyewetness.rin_eyewetness_1.Bitangent",
+ "RootNode.rin_eyewetness.rin_eyewetness_1.SkinWeight_",
+ "RootNode.rin_eyewetness.rin_eyewetness_1.transform",
+ "RootNode.rin_eyewetness.rin_eyewetness_1.Tangent",
+ "RootNode.rin_eyewetness.rin_eyewetness_1.map1",
+ "RootNode.rin_eyewetness.rin_eyewetness_1.rin_m_eyewetness",
+ "RootNode.rin_eyewetness.rin_eyewetness_2.Bitangent",
+ "RootNode.rin_eyewetness.rin_eyewetness_2.SkinWeight_",
+ "RootNode.rin_eyewetness.rin_eyewetness_2.transform",
+ "RootNode.rin_eyewetness.rin_eyewetness_2.Tangent",
+ "RootNode.rin_eyewetness.rin_eyewetness_2.map1",
+ "RootNode.rin_eyewetness.rin_eyewetness_2.rin_m_eyewetness",
+ "RootNode.rin_eyebrows_lower.rin_eyebrows_lower_1.Bitangent",
+ "RootNode.rin_eyebrows_lower.rin_eyebrows_lower_1.SkinWeight_",
+ "RootNode.rin_eyebrows_lower.rin_eyebrows_lower_1.transform",
+ "RootNode.rin_eyebrows_lower.rin_eyebrows_lower_1.Tangent",
+ "RootNode.rin_eyebrows_lower.rin_eyebrows_lower_1.map1",
+ "RootNode.rin_eyebrows_lower.rin_eyebrows_lower_1.rin_m_eyebrow",
+ "RootNode.rin_eyebrows_lower.rin_eyebrows_lower_2.Bitangent",
+ "RootNode.rin_eyebrows_lower.rin_eyebrows_lower_2.SkinWeight_",
+ "RootNode.rin_eyebrows_lower.rin_eyebrows_lower_2.transform",
+ "RootNode.rin_eyebrows_lower.rin_eyebrows_lower_2.Tangent",
+ "RootNode.rin_eyebrows_lower.rin_eyebrows_lower_2.map1",
+ "RootNode.rin_eyebrows_lower.rin_eyebrows_lower_2.rin_m_eyebrow",
+ "RootNode.rin_tearduct.rin_tearduct_1.Bitangent",
+ "RootNode.rin_tearduct.rin_tearduct_1.SkinWeight_",
+ "RootNode.rin_tearduct.rin_tearduct_1.transform",
+ "RootNode.rin_tearduct.rin_tearduct_1.Tangent",
+ "RootNode.rin_tearduct.rin_tearduct_1.map1",
+ "RootNode.rin_tearduct.rin_tearduct_1.rin_m_tearduct",
+ "RootNode.rin_tearduct.rin_tearduct_2.Bitangent",
+ "RootNode.rin_tearduct.rin_tearduct_2.SkinWeight_",
+ "RootNode.rin_tearduct.rin_tearduct_2.transform",
+ "RootNode.rin_tearduct.rin_tearduct_2.Tangent",
+ "RootNode.rin_tearduct.rin_tearduct_2.map1",
+ "RootNode.rin_tearduct.rin_tearduct_2.rin_m_tearduct",
+ "RootNode.root.C_pelvis_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT",
+ "RootNode.root.C_pelvis_JNT.L_leg_JNT",
+ "RootNode.root.C_pelvis_JNT.R_leg_JNT",
+ "RootNode.root.C_pelvis_JNT.L_ribbon_01_JNT",
+ "RootNode.root.C_pelvis_JNT.R_ribbon_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_legArmor_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_sword_JNT",
+ "RootNode.root.C_pelvis_JNT.L_leg_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.L_leg_JNT.L_knee_JNT",
+ "RootNode.root.C_pelvis_JNT.L_leg_JNT.L_leg_twist_JNT",
+ "RootNode.root.C_pelvis_JNT.R_leg_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.R_leg_JNT.R_knee_JNT",
+ "RootNode.root.C_pelvis_JNT.R_leg_JNT.R_leg_twist_JNT",
+ "RootNode.root.C_pelvis_JNT.L_ribbon_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.L_ribbon_01_JNT.L_ribbon_02_JNT",
+ "RootNode.root.C_pelvis_JNT.R_ribbon_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.R_ribbon_01_JNT.R_ribbon_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_legArmor_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_sword_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.L_leg_JNT.L_knee_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.L_leg_JNT.L_knee_JNT.L_foot_JNT",
+ "RootNode.root.C_pelvis_JNT.L_leg_JNT.L_knee_JNT.L_knee_twist_JNT",
+ "RootNode.root.C_pelvis_JNT.L_leg_JNT.L_leg_twist_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.R_leg_JNT.R_knee_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.R_leg_JNT.R_knee_JNT.R_foot_JNT",
+ "RootNode.root.C_pelvis_JNT.R_leg_JNT.R_knee_JNT.R_knee_twist_JNT",
+ "RootNode.root.C_pelvis_JNT.R_leg_JNT.R_leg_twist_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.L_ribbon_01_JNT.L_ribbon_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.R_ribbon_01_JNT.R_ribbon_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT",
+ "RootNode.root.C_pelvis_JNT.L_leg_JNT.L_knee_JNT.L_foot_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.L_leg_JNT.L_knee_JNT.L_foot_JNT.L_toe_JNT",
+ "RootNode.root.C_pelvis_JNT.L_leg_JNT.L_knee_JNT.L_knee_twist_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.R_leg_JNT.R_knee_JNT.R_foot_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.R_leg_JNT.R_knee_JNT.R_foot_JNT.R_toe_JNT",
+ "RootNode.root.C_pelvis_JNT.R_leg_JNT.R_knee_JNT.R_knee_twist_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_hood_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neckCollar_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_neckCollar_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_neckCollar_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_neckCollar_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_neckCollar_02_JNT",
+ "RootNode.root.C_pelvis_JNT.L_leg_JNT.L_knee_JNT.L_foot_JNT.L_toe_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.R_leg_JNT.R_knee_JNT.R_foot_JNT.R_toe_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_tassle_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_tassleLoop_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_armPit_corr_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_tassle_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_tassleLoop_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_armPit_corr_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_hood_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_hood_01_JNT.C_hood_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neckCollar_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_neckCollar_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_neckCollar_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_neckCollar_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_neckCollar_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_arm_twist_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_armBulge_corr_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_tassle_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_tassle_01_JNT.L_tassle_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_tassleLoop_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_tassleLoop_01_JNT.L_tassleLoop_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_armPit_corr_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_throat_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_arm_twist_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_armBulge_corr_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_tassle_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_tassle_01_JNT.R_tassle_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_tassleLoop_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_tassleLoop_01_JNT.R_tassleLoop_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_armPit_corr_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_hood_01_JNT.C_hood_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_hood_01_JNT.C_hood_02_JNT.C_hood_03_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_elbow_twist_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_arm_twist_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_armBulge_corr_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_tassle_01_JNT.L_tassle_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_tassle_01_JNT.L_tassle_02_JNT.L_tassle_03_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_tassleLoop_01_JNT.L_tassleLoop_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_brow_inner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_brow_mid_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_brow_outer_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_corrugator_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_noseBridge_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_nostril_inner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_nostril_outer_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_cheekUpper_inner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_squint_mid_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_squint_outer_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_squint_inner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_zygomatic_outer_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_cheekBone_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_ear_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_nose_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_chin_below_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_chin_below_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_eyelid_lower_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_eyelid_upper_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_eyelid_levator_mid_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_eye_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_lipLevator_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_lipUpper_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_lipUpper_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_lipLevator_inner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_lipLevator_corner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_cheekUpper_outer_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_cheekUpper_mid_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_eyelid_upper_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_eyelid_lower_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_nostril_inner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_lipLevator_inner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_cheekBone_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_zygomatic_outer_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_lipUpper_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_chin_below_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_ear_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_nose_slide_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_eye_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_brow_inner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_brow_mid_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_brow_outer_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_lipLevator_corner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_cheekUpper_outer_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_cheekUpper_mid_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_nostril_outer_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_cheekUpper_inner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_squint_inner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_squint_mid_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_squint_outer_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_lipUpper_corner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_lipUpper_corner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_frontalis_inner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_frontalis_outer_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_frontalis_outer_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_frontalis_inner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_eyelid_fold_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_eyelid_fold_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_eye_bulge_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_eye_bulge_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_throat_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_elbow_twist_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_arm_twist_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_armBulge_corr_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_tassle_01_JNT.R_tassle_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_tassle_01_JNT.R_tassle_02_JNT.R_tassle_03_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_tassleLoop_01_JNT.R_tassleLoop_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_hood_01_JNT.C_hood_02_JNT.C_hood_03_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_thumb_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_index_root_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_middle_root_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_ring_root_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_pinky_root_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_elbow_twist_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_tassle_01_JNT.L_tassle_02_JNT.L_tassle_03_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_brow_inner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_brow_mid_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_brow_outer_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_corrugator_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_noseBridge_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_nostril_inner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_nostril_outer_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_cheekUpper_inner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_squint_mid_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_squint_outer_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_squint_inner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_zygomatic_outer_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_cheekBone_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_ear_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_nose_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_chin_below_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_chin_below_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_eyelid_lower_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_eyelid_upper_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_eyelid_levator_mid_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_eye_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_lipLevator_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_lipUpper_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_lipUpper_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_lipLevator_inner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_lipLevator_corner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.C_mentalis_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.L_depressor_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.R_depressor_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.L_lip_nasolabial_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.R_mouth_corner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.C_lip_below_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.R_lip_nasolabial_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.R_lipLower_corner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.R_lipLower_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.C_lipLower_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.L_lipLower_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.L_mouth_corner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.L_lipLower_corner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.R_jaw_clench_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.L_jaw_clench_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.L_zygomatic_inner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.R_zygomatic_inner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.C_tongue_root_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_cheekUpper_outer_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_cheekUpper_mid_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_eyelid_upper_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_eyelid_lower_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_nostril_inner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_lipLevator_inner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_cheekBone_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_zygomatic_outer_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_lipUpper_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_chin_below_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_ear_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_nose_slide_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_eye_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_brow_inner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_brow_mid_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_brow_outer_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_lipLevator_corner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_cheekUpper_outer_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_cheekUpper_mid_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_nostril_outer_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_cheekUpper_inner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_squint_inner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_squint_mid_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_squint_outer_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_lipUpper_corner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_lipUpper_corner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_frontalis_inner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_frontalis_outer_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_frontalis_outer_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_frontalis_inner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_eyelid_fold_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_eyelid_fold_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_eye_bulge_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_eye_bulge_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_thumb_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_index_root_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_middle_root_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_ring_root_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_pinky_root_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_elbow_twist_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_tassle_01_JNT.R_tassle_02_JNT.R_tassle_03_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_thumb_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_thumb_01_JNT.L_thumb_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_index_root_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_index_root_JNT.L_index_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_middle_root_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_middle_root_JNT.L_middle_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_ring_root_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_ring_root_JNT.L_ring_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_pinky_root_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_pinky_root_JNT.L_pinky_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.C_mentalis_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.L_depressor_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.R_depressor_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.L_lip_nasolabial_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.R_mouth_corner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.C_lip_below_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.R_lip_nasolabial_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.R_lipLower_corner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.R_lipLower_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.C_lipLower_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.L_lipLower_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.L_mouth_corner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.L_lipLower_corner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.R_jaw_clench_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.L_jaw_clench_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.L_zygomatic_inner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.R_zygomatic_inner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.C_tongue_root_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.C_tongue_root_JNT.C_tongue_mid_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_thumb_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_thumb_01_JNT.R_thumb_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_index_root_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_index_root_JNT.R_index_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_middle_root_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_middle_root_JNT.R_middle_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_ring_root_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_ring_root_JNT.R_ring_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_pinky_root_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_pinky_root_JNT.R_pinky_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_thumb_01_JNT.L_thumb_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_thumb_01_JNT.L_thumb_02_JNT.L_thumb_03_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_index_root_JNT.L_index_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_index_root_JNT.L_index_01_JNT.L_index_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_middle_root_JNT.L_middle_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_middle_root_JNT.L_middle_01_JNT.L_middle_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_ring_root_JNT.L_ring_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_ring_root_JNT.L_ring_01_JNT.L_ring_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_pinky_root_JNT.L_pinky_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_pinky_root_JNT.L_pinky_01_JNT.L_pinky_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.C_tongue_root_JNT.C_tongue_mid_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.C_tongue_root_JNT.C_tongue_mid_JNT.C_tongue_tip_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_thumb_01_JNT.R_thumb_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_thumb_01_JNT.R_thumb_02_JNT.R_thumb_03_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_index_root_JNT.R_index_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_index_root_JNT.R_index_01_JNT.R_index_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_middle_root_JNT.R_middle_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_middle_root_JNT.R_middle_01_JNT.R_middle_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_ring_root_JNT.R_ring_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_ring_root_JNT.R_ring_01_JNT.R_ring_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_pinky_root_JNT.R_pinky_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_pinky_root_JNT.R_pinky_01_JNT.R_pinky_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_thumb_01_JNT.L_thumb_02_JNT.L_thumb_03_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_index_root_JNT.L_index_01_JNT.L_index_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_index_root_JNT.L_index_01_JNT.L_index_02_JNT.L_index_03_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_middle_root_JNT.L_middle_01_JNT.L_middle_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_middle_root_JNT.L_middle_01_JNT.L_middle_02_JNT.L_middle_03_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_ring_root_JNT.L_ring_01_JNT.L_ring_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_ring_root_JNT.L_ring_01_JNT.L_ring_02_JNT.L_ring_03_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_pinky_root_JNT.L_pinky_01_JNT.L_pinky_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_pinky_root_JNT.L_pinky_01_JNT.L_pinky_02_JNT.L_pinky_03_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.C_tongue_root_JNT.C_tongue_mid_JNT.C_tongue_tip_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_thumb_01_JNT.R_thumb_02_JNT.R_thumb_03_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_index_root_JNT.R_index_01_JNT.R_index_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_index_root_JNT.R_index_01_JNT.R_index_02_JNT.R_index_03_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_middle_root_JNT.R_middle_01_JNT.R_middle_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_middle_root_JNT.R_middle_01_JNT.R_middle_02_JNT.R_middle_03_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_ring_root_JNT.R_ring_01_JNT.R_ring_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_ring_root_JNT.R_ring_01_JNT.R_ring_02_JNT.R_ring_03_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_pinky_root_JNT.R_pinky_01_JNT.R_pinky_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_pinky_root_JNT.R_pinky_01_JNT.R_pinky_02_JNT.R_pinky_03_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_index_root_JNT.L_index_01_JNT.L_index_02_JNT.L_index_03_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_middle_root_JNT.L_middle_01_JNT.L_middle_02_JNT.L_middle_03_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_ring_root_JNT.L_ring_01_JNT.L_ring_02_JNT.L_ring_03_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_pinky_root_JNT.L_pinky_01_JNT.L_pinky_02_JNT.L_pinky_03_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_index_root_JNT.R_index_01_JNT.R_index_02_JNT.R_index_03_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_middle_root_JNT.R_middle_01_JNT.R_middle_02_JNT.R_middle_03_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_ring_root_JNT.R_ring_01_JNT.R_ring_02_JNT.R_ring_03_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_pinky_root_JNT.R_pinky_01_JNT.R_pinky_02_JNT.R_pinky_03_JNT.transform"
+ ]
+ }
+ },
+ {
+ "$type": "{07B356B7-3635-40B5-878A-FAC4EFD5AD86} MeshGroup",
+ "name": "RinMM",
+ "nodeSelectionList": {
+ "selectedNodes": [
+ "RootNode",
+ "RootNode.rin_eyeballs",
+ "RootNode.rin_haircap",
+ "RootNode.rin_cloth",
+ "RootNode.rin_leather",
+ "RootNode.rin_armor",
+ "RootNode.rin_hands",
+ "RootNode.rin_props",
+ "RootNode.rin_teeth_low",
+ "RootNode.rin_teeth_up",
+ "RootNode.rin_tongue",
+ "RootNode.rin_face",
+ "RootNode.rin_armorstraps",
+ "RootNode.rin_hairplanes",
+ "RootNode.rin_eyebrows_top",
+ "RootNode.rin_eyelashes_top",
+ "RootNode.rin_eyelashes_lower",
+ "RootNode.rin_eyecover",
+ "RootNode.rin_facefuzz",
+ "RootNode.rin_haircards",
+ "RootNode.rin_lash_01",
+ "RootNode.rin_lash_02",
+ "RootNode.rin_lash_03",
+ "RootNode.rin_eyewetness",
+ "RootNode.rin_eyebrows_lower",
+ "RootNode.rin_tearduct",
+ "RootNode.root",
+ "RootNode.rin_eyeballs.rin_eyeballs_1",
+ "RootNode.rin_eyeballs.rin_eyeballs_2",
+ "RootNode.rin_haircap.rin_haircap_1",
+ "RootNode.rin_haircap.rin_haircap_2",
+ "RootNode.rin_cloth.rin_cloth_1",
+ "RootNode.rin_cloth.rin_cloth_2",
+ "RootNode.rin_leather.rin_leather_1",
+ "RootNode.rin_leather.rin_leather_2",
+ "RootNode.rin_armor.rin_armor_1",
+ "RootNode.rin_armor.rin_armor_2",
+ "RootNode.rin_hands.rin_hands_1",
+ "RootNode.rin_hands.rin_hands_2",
+ "RootNode.rin_props.rin_props_1",
+ "RootNode.rin_props.rin_props_2",
+ "RootNode.rin_teeth_low.rin_teeth_low_1",
+ "RootNode.rin_teeth_low.rin_teeth_low_2",
+ "RootNode.rin_teeth_up.rin_teeth_up_1",
+ "RootNode.rin_teeth_up.rin_teeth_up_2",
+ "RootNode.rin_tongue.rin_tongue_1",
+ "RootNode.rin_tongue.rin_tongue_2",
+ "RootNode.rin_face.rin_face_1",
+ "RootNode.rin_face.rin_face_2",
+ "RootNode.rin_armorstraps.rin_armorstraps_1",
+ "RootNode.rin_armorstraps.rin_armorstraps_2",
+ "RootNode.rin_hairplanes.rin_hairplanes_1",
+ "RootNode.rin_hairplanes.rin_hairplanes_2",
+ "RootNode.rin_eyebrows_top.rin_eyebrows_top_1",
+ "RootNode.rin_eyebrows_top.rin_eyebrows_top_2",
+ "RootNode.rin_eyelashes_top.rin_eyelashes_top_1",
+ "RootNode.rin_eyelashes_top.rin_eyelashes_top_2",
+ "RootNode.rin_eyelashes_lower.rin_eyelashes_lower_1",
+ "RootNode.rin_eyelashes_lower.rin_eyelashes_lower_2",
+ "RootNode.rin_eyecover.rin_eyecover_1",
+ "RootNode.rin_eyecover.rin_eyecover_2",
+ "RootNode.rin_facefuzz.rin_facefuzz_1",
+ "RootNode.rin_facefuzz.rin_facefuzz_2",
+ "RootNode.rin_haircards.rin_haircards_1",
+ "RootNode.rin_haircards.rin_haircards_2",
+ "RootNode.rin_lash_01.rin_lash_01_1",
+ "RootNode.rin_lash_01.rin_lash_01_2",
+ "RootNode.rin_lash_02.rin_lash_02_1",
+ "RootNode.rin_lash_02.rin_lash_02_2",
+ "RootNode.rin_lash_03.rin_lash_03_1",
+ "RootNode.rin_lash_03.rin_lash_03_2",
+ "RootNode.rin_eyewetness.rin_eyewetness_1",
+ "RootNode.rin_eyewetness.rin_eyewetness_2",
+ "RootNode.rin_eyebrows_lower.rin_eyebrows_lower_1",
+ "RootNode.rin_eyebrows_lower.rin_eyebrows_lower_2",
+ "RootNode.rin_tearduct.rin_tearduct_1",
+ "RootNode.rin_tearduct.rin_tearduct_2",
+ "RootNode.root.C_pelvis_JNT",
+ "RootNode.rin_eyeballs.rin_eyeballs_1.Bitangent",
+ "RootNode.rin_eyeballs.rin_eyeballs_1.SkinWeight_",
+ "RootNode.rin_eyeballs.rin_eyeballs_1.transform",
+ "RootNode.rin_eyeballs.rin_eyeballs_1.Tangent",
+ "RootNode.rin_eyeballs.rin_eyeballs_1.map1",
+ "RootNode.rin_eyeballs.rin_eyeballs_1.rin_m_eyeballs",
+ "RootNode.rin_eyeballs.rin_eyeballs_2.Bitangent",
+ "RootNode.rin_eyeballs.rin_eyeballs_2.SkinWeight_",
+ "RootNode.rin_eyeballs.rin_eyeballs_2.transform",
+ "RootNode.rin_eyeballs.rin_eyeballs_2.Tangent",
+ "RootNode.rin_eyeballs.rin_eyeballs_2.map1",
+ "RootNode.rin_eyeballs.rin_eyeballs_2.rin_m_eyeballs",
+ "RootNode.rin_haircap.rin_haircap_1.Bitangent",
+ "RootNode.rin_haircap.rin_haircap_1.SkinWeight_",
+ "RootNode.rin_haircap.rin_haircap_1.transform",
+ "RootNode.rin_haircap.rin_haircap_1.Tangent",
+ "RootNode.rin_haircap.rin_haircap_1.map1",
+ "RootNode.rin_haircap.rin_haircap_1.rin_m_haircap",
+ "RootNode.rin_haircap.rin_haircap_2.Bitangent",
+ "RootNode.rin_haircap.rin_haircap_2.SkinWeight_",
+ "RootNode.rin_haircap.rin_haircap_2.transform",
+ "RootNode.rin_haircap.rin_haircap_2.Tangent",
+ "RootNode.rin_haircap.rin_haircap_2.map1",
+ "RootNode.rin_haircap.rin_haircap_2.rin_m_haircap",
+ "RootNode.rin_cloth.rin_cloth_1.Col0",
+ "RootNode.rin_cloth.rin_cloth_1.Bitangent",
+ "RootNode.rin_cloth.rin_cloth_1.SkinWeight_",
+ "RootNode.rin_cloth.rin_cloth_1.transform",
+ "RootNode.rin_cloth.rin_cloth_1.Tangent",
+ "RootNode.rin_cloth.rin_cloth_1.UVMap",
+ "RootNode.rin_cloth.rin_cloth_1.rin_m_cloth",
+ "RootNode.rin_cloth.rin_cloth_2.Col0",
+ "RootNode.rin_cloth.rin_cloth_2.Bitangent",
+ "RootNode.rin_cloth.rin_cloth_2.SkinWeight_",
+ "RootNode.rin_cloth.rin_cloth_2.transform",
+ "RootNode.rin_cloth.rin_cloth_2.Tangent",
+ "RootNode.rin_cloth.rin_cloth_2.UVMap",
+ "RootNode.rin_cloth.rin_cloth_2.rin_m_cloth",
+ "RootNode.rin_leather.rin_leather_1.Col0",
+ "RootNode.rin_leather.rin_leather_1.Bitangent",
+ "RootNode.rin_leather.rin_leather_1.SkinWeight_",
+ "RootNode.rin_leather.rin_leather_1.transform",
+ "RootNode.rin_leather.rin_leather_1.Tangent",
+ "RootNode.rin_leather.rin_leather_1.UVMap",
+ "RootNode.rin_leather.rin_leather_1.rin_m_leather",
+ "RootNode.rin_leather.rin_leather_2.Col0",
+ "RootNode.rin_leather.rin_leather_2.Bitangent",
+ "RootNode.rin_leather.rin_leather_2.SkinWeight_",
+ "RootNode.rin_leather.rin_leather_2.transform",
+ "RootNode.rin_leather.rin_leather_2.Tangent",
+ "RootNode.rin_leather.rin_leather_2.UVMap",
+ "RootNode.rin_leather.rin_leather_2.rin_m_leather",
+ "RootNode.rin_armor.rin_armor_1.Col0",
+ "RootNode.rin_armor.rin_armor_1.Bitangent",
+ "RootNode.rin_armor.rin_armor_1.SkinWeight_",
+ "RootNode.rin_armor.rin_armor_1.transform",
+ "RootNode.rin_armor.rin_armor_1.Tangent",
+ "RootNode.rin_armor.rin_armor_1.UVMap",
+ "RootNode.rin_armor.rin_armor_1.rin_m_armor",
+ "RootNode.rin_armor.rin_armor_2.Col0",
+ "RootNode.rin_armor.rin_armor_2.Bitangent",
+ "RootNode.rin_armor.rin_armor_2.SkinWeight_",
+ "RootNode.rin_armor.rin_armor_2.transform",
+ "RootNode.rin_armor.rin_armor_2.Tangent",
+ "RootNode.rin_armor.rin_armor_2.UVMap",
+ "RootNode.rin_armor.rin_armor_2.rin_m_armor",
+ "RootNode.rin_hands.rin_hands_1.Col0",
+ "RootNode.rin_hands.rin_hands_1.Bitangent",
+ "RootNode.rin_hands.rin_hands_1.SkinWeight_",
+ "RootNode.rin_hands.rin_hands_1.transform",
+ "RootNode.rin_hands.rin_hands_1.Tangent",
+ "RootNode.rin_hands.rin_hands_1.UVMap",
+ "RootNode.rin_hands.rin_hands_1.rin_m_hands",
+ "RootNode.rin_hands.rin_hands_2.Col0",
+ "RootNode.rin_hands.rin_hands_2.Bitangent",
+ "RootNode.rin_hands.rin_hands_2.SkinWeight_",
+ "RootNode.rin_hands.rin_hands_2.transform",
+ "RootNode.rin_hands.rin_hands_2.Tangent",
+ "RootNode.rin_hands.rin_hands_2.UVMap",
+ "RootNode.rin_hands.rin_hands_2.rin_m_hands",
+ "RootNode.rin_props.rin_props_1.Bitangent",
+ "RootNode.rin_props.rin_props_1.SkinWeight_",
+ "RootNode.rin_props.rin_props_1.transform",
+ "RootNode.rin_props.rin_props_1.Tangent",
+ "RootNode.rin_props.rin_props_1.UVMap",
+ "RootNode.rin_props.rin_props_1.map1",
+ "RootNode.rin_props.rin_props_1.rin_m_props",
+ "RootNode.rin_props.rin_props_2.Bitangent",
+ "RootNode.rin_props.rin_props_2.SkinWeight_",
+ "RootNode.rin_props.rin_props_2.transform",
+ "RootNode.rin_props.rin_props_2.Tangent",
+ "RootNode.rin_props.rin_props_2.UVMap",
+ "RootNode.rin_props.rin_props_2.map1",
+ "RootNode.rin_props.rin_props_2.rin_m_props",
+ "RootNode.rin_teeth_low.rin_teeth_low_1.Bitangent",
+ "RootNode.rin_teeth_low.rin_teeth_low_1.SkinWeight_",
+ "RootNode.rin_teeth_low.rin_teeth_low_1.transform",
+ "RootNode.rin_teeth_low.rin_teeth_low_1.Tangent",
+ "RootNode.rin_teeth_low.rin_teeth_low_1.map1",
+ "RootNode.rin_teeth_low.rin_teeth_low_1.rin_m_mouth",
+ "RootNode.rin_teeth_low.rin_teeth_low_2.Bitangent",
+ "RootNode.rin_teeth_low.rin_teeth_low_2.SkinWeight_",
+ "RootNode.rin_teeth_low.rin_teeth_low_2.transform",
+ "RootNode.rin_teeth_low.rin_teeth_low_2.Tangent",
+ "RootNode.rin_teeth_low.rin_teeth_low_2.map1",
+ "RootNode.rin_teeth_low.rin_teeth_low_2.rin_m_mouth",
+ "RootNode.rin_teeth_up.rin_teeth_up_1.Bitangent",
+ "RootNode.rin_teeth_up.rin_teeth_up_1.SkinWeight_",
+ "RootNode.rin_teeth_up.rin_teeth_up_1.transform",
+ "RootNode.rin_teeth_up.rin_teeth_up_1.Tangent",
+ "RootNode.rin_teeth_up.rin_teeth_up_1.map1",
+ "RootNode.rin_teeth_up.rin_teeth_up_1.rin_m_mouth",
+ "RootNode.rin_teeth_up.rin_teeth_up_2.Bitangent",
+ "RootNode.rin_teeth_up.rin_teeth_up_2.SkinWeight_",
+ "RootNode.rin_teeth_up.rin_teeth_up_2.transform",
+ "RootNode.rin_teeth_up.rin_teeth_up_2.Tangent",
+ "RootNode.rin_teeth_up.rin_teeth_up_2.map1",
+ "RootNode.rin_teeth_up.rin_teeth_up_2.rin_m_mouth",
+ "RootNode.rin_tongue.rin_tongue_1.Bitangent",
+ "RootNode.rin_tongue.rin_tongue_1.SkinWeight_",
+ "RootNode.rin_tongue.rin_tongue_1.transform",
+ "RootNode.rin_tongue.rin_tongue_1.Tangent",
+ "RootNode.rin_tongue.rin_tongue_1.map1",
+ "RootNode.rin_tongue.rin_tongue_1.rin_m_mouth",
+ "RootNode.rin_tongue.rin_tongue_2.Bitangent",
+ "RootNode.rin_tongue.rin_tongue_2.SkinWeight_",
+ "RootNode.rin_tongue.rin_tongue_2.transform",
+ "RootNode.rin_tongue.rin_tongue_2.Tangent",
+ "RootNode.rin_tongue.rin_tongue_2.map1",
+ "RootNode.rin_tongue.rin_tongue_2.rin_m_mouth",
+ "RootNode.rin_face.rin_face_1.Bitangent",
+ "RootNode.rin_face.rin_face_1.SkinWeight_",
+ "RootNode.rin_face.rin_face_1.transform",
+ "RootNode.rin_face.rin_face_1.Tangent",
+ "RootNode.rin_face.rin_face_1.map1",
+ "RootNode.rin_face.rin_face_1.rin_m_face",
+ "RootNode.rin_face.rin_face_2.Bitangent",
+ "RootNode.rin_face.rin_face_2.SkinWeight_",
+ "RootNode.rin_face.rin_face_2.transform",
+ "RootNode.rin_face.rin_face_2.Tangent",
+ "RootNode.rin_face.rin_face_2.map1",
+ "RootNode.rin_face.rin_face_2.rin_m_face",
+ "RootNode.rin_armorstraps.rin_armorstraps_1.Bitangent",
+ "RootNode.rin_armorstraps.rin_armorstraps_1.SkinWeight_",
+ "RootNode.rin_armorstraps.rin_armorstraps_1.transform",
+ "RootNode.rin_armorstraps.rin_armorstraps_1.Tangent",
+ "RootNode.rin_armorstraps.rin_armorstraps_1.map1",
+ "RootNode.rin_armorstraps.rin_armorstraps_1.rin_m_armor",
+ "RootNode.rin_armorstraps.rin_armorstraps_2.Bitangent",
+ "RootNode.rin_armorstraps.rin_armorstraps_2.SkinWeight_",
+ "RootNode.rin_armorstraps.rin_armorstraps_2.transform",
+ "RootNode.rin_armorstraps.rin_armorstraps_2.Tangent",
+ "RootNode.rin_armorstraps.rin_armorstraps_2.map1",
+ "RootNode.rin_armorstraps.rin_armorstraps_2.rin_m_armor",
+ "RootNode.rin_hairplanes.rin_hairplanes_1.Bitangent",
+ "RootNode.rin_hairplanes.rin_hairplanes_1.SkinWeight_",
+ "RootNode.rin_hairplanes.rin_hairplanes_1.transform",
+ "RootNode.rin_hairplanes.rin_hairplanes_1.Tangent",
+ "RootNode.rin_hairplanes.rin_hairplanes_1.map1",
+ "RootNode.rin_hairplanes.rin_hairplanes_1.rin_m_hairplanes",
+ "RootNode.rin_hairplanes.rin_hairplanes_2.Bitangent",
+ "RootNode.rin_hairplanes.rin_hairplanes_2.SkinWeight_",
+ "RootNode.rin_hairplanes.rin_hairplanes_2.transform",
+ "RootNode.rin_hairplanes.rin_hairplanes_2.Tangent",
+ "RootNode.rin_hairplanes.rin_hairplanes_2.map1",
+ "RootNode.rin_hairplanes.rin_hairplanes_2.rin_m_hairplanes",
+ "RootNode.rin_eyebrows_top.rin_eyebrows_top_1.Bitangent",
+ "RootNode.rin_eyebrows_top.rin_eyebrows_top_1.SkinWeight_",
+ "RootNode.rin_eyebrows_top.rin_eyebrows_top_1.transform",
+ "RootNode.rin_eyebrows_top.rin_eyebrows_top_1.Tangent",
+ "RootNode.rin_eyebrows_top.rin_eyebrows_top_1.map1",
+ "RootNode.rin_eyebrows_top.rin_eyebrows_top_1.rin_m_eyebrow",
+ "RootNode.rin_eyebrows_top.rin_eyebrows_top_2.Bitangent",
+ "RootNode.rin_eyebrows_top.rin_eyebrows_top_2.SkinWeight_",
+ "RootNode.rin_eyebrows_top.rin_eyebrows_top_2.transform",
+ "RootNode.rin_eyebrows_top.rin_eyebrows_top_2.Tangent",
+ "RootNode.rin_eyebrows_top.rin_eyebrows_top_2.map1",
+ "RootNode.rin_eyebrows_top.rin_eyebrows_top_2.rin_m_eyebrow",
+ "RootNode.rin_eyelashes_top.rin_eyelashes_top_1.Bitangent",
+ "RootNode.rin_eyelashes_top.rin_eyelashes_top_1.SkinWeight_",
+ "RootNode.rin_eyelashes_top.rin_eyelashes_top_1.transform",
+ "RootNode.rin_eyelashes_top.rin_eyelashes_top_1.Tangent",
+ "RootNode.rin_eyelashes_top.rin_eyelashes_top_1.map1",
+ "RootNode.rin_eyelashes_top.rin_eyelashes_top_1.rin_m_lashes",
+ "RootNode.rin_eyelashes_top.rin_eyelashes_top_2.Bitangent",
+ "RootNode.rin_eyelashes_top.rin_eyelashes_top_2.SkinWeight_",
+ "RootNode.rin_eyelashes_top.rin_eyelashes_top_2.transform",
+ "RootNode.rin_eyelashes_top.rin_eyelashes_top_2.Tangent",
+ "RootNode.rin_eyelashes_top.rin_eyelashes_top_2.map1",
+ "RootNode.rin_eyelashes_top.rin_eyelashes_top_2.rin_m_lashes",
+ "RootNode.rin_eyelashes_lower.rin_eyelashes_lower_1.Bitangent",
+ "RootNode.rin_eyelashes_lower.rin_eyelashes_lower_1.SkinWeight_",
+ "RootNode.rin_eyelashes_lower.rin_eyelashes_lower_1.transform",
+ "RootNode.rin_eyelashes_lower.rin_eyelashes_lower_1.Tangent",
+ "RootNode.rin_eyelashes_lower.rin_eyelashes_lower_1.map1",
+ "RootNode.rin_eyelashes_lower.rin_eyelashes_lower_1.rin_m_eyebrow",
+ "RootNode.rin_eyelashes_lower.rin_eyelashes_lower_2.Bitangent",
+ "RootNode.rin_eyelashes_lower.rin_eyelashes_lower_2.SkinWeight_",
+ "RootNode.rin_eyelashes_lower.rin_eyelashes_lower_2.transform",
+ "RootNode.rin_eyelashes_lower.rin_eyelashes_lower_2.Tangent",
+ "RootNode.rin_eyelashes_lower.rin_eyelashes_lower_2.map1",
+ "RootNode.rin_eyelashes_lower.rin_eyelashes_lower_2.rin_m_eyebrow",
+ "RootNode.rin_eyecover.rin_eyecover_1.Bitangent",
+ "RootNode.rin_eyecover.rin_eyecover_1.SkinWeight_",
+ "RootNode.rin_eyecover.rin_eyecover_1.transform",
+ "RootNode.rin_eyecover.rin_eyecover_1.Tangent",
+ "RootNode.rin_eyecover.rin_eyecover_1.map1",
+ "RootNode.rin_eyecover.rin_eyecover_1.rin_m_eyecover",
+ "RootNode.rin_eyecover.rin_eyecover_2.Bitangent",
+ "RootNode.rin_eyecover.rin_eyecover_2.SkinWeight_",
+ "RootNode.rin_eyecover.rin_eyecover_2.transform",
+ "RootNode.rin_eyecover.rin_eyecover_2.Tangent",
+ "RootNode.rin_eyecover.rin_eyecover_2.map1",
+ "RootNode.rin_eyecover.rin_eyecover_2.rin_m_eyecover",
+ "RootNode.rin_facefuzz.rin_facefuzz_1.Bitangent",
+ "RootNode.rin_facefuzz.rin_facefuzz_1.SkinWeight_",
+ "RootNode.rin_facefuzz.rin_facefuzz_1.transform",
+ "RootNode.rin_facefuzz.rin_facefuzz_1.Tangent",
+ "RootNode.rin_facefuzz.rin_facefuzz_1.map1",
+ "RootNode.rin_facefuzz.rin_facefuzz_1.rin_m_fuzz",
+ "RootNode.rin_facefuzz.rin_facefuzz_2.Bitangent",
+ "RootNode.rin_facefuzz.rin_facefuzz_2.SkinWeight_",
+ "RootNode.rin_facefuzz.rin_facefuzz_2.transform",
+ "RootNode.rin_facefuzz.rin_facefuzz_2.Tangent",
+ "RootNode.rin_facefuzz.rin_facefuzz_2.map1",
+ "RootNode.rin_facefuzz.rin_facefuzz_2.rin_m_fuzz",
+ "RootNode.rin_haircards.rin_haircards_1.Bitangent",
+ "RootNode.rin_haircards.rin_haircards_1.SkinWeight_",
+ "RootNode.rin_haircards.rin_haircards_1.transform",
+ "RootNode.rin_haircards.rin_haircards_1.Tangent",
+ "RootNode.rin_haircards.rin_haircards_1.map1",
+ "RootNode.rin_haircards.rin_haircards_1.rin_m_haircards",
+ "RootNode.rin_haircards.rin_haircards_2.Bitangent",
+ "RootNode.rin_haircards.rin_haircards_2.SkinWeight_",
+ "RootNode.rin_haircards.rin_haircards_2.transform",
+ "RootNode.rin_haircards.rin_haircards_2.Tangent",
+ "RootNode.rin_haircards.rin_haircards_2.map1",
+ "RootNode.rin_haircards.rin_haircards_2.rin_m_haircards",
+ "RootNode.rin_lash_01.rin_lash_01_1.Bitangent",
+ "RootNode.rin_lash_01.rin_lash_01_1.SkinWeight_",
+ "RootNode.rin_lash_01.rin_lash_01_1.transform",
+ "RootNode.rin_lash_01.rin_lash_01_1.Tangent",
+ "RootNode.rin_lash_01.rin_lash_01_1.map1",
+ "RootNode.rin_lash_01.rin_lash_01_1.rin_m_lashes",
+ "RootNode.rin_lash_01.rin_lash_01_2.Bitangent",
+ "RootNode.rin_lash_01.rin_lash_01_2.SkinWeight_",
+ "RootNode.rin_lash_01.rin_lash_01_2.transform",
+ "RootNode.rin_lash_01.rin_lash_01_2.Tangent",
+ "RootNode.rin_lash_01.rin_lash_01_2.map1",
+ "RootNode.rin_lash_01.rin_lash_01_2.rin_m_lashes",
+ "RootNode.rin_lash_02.rin_lash_02_1.Bitangent",
+ "RootNode.rin_lash_02.rin_lash_02_1.SkinWeight_",
+ "RootNode.rin_lash_02.rin_lash_02_1.transform",
+ "RootNode.rin_lash_02.rin_lash_02_1.Tangent",
+ "RootNode.rin_lash_02.rin_lash_02_1.map1",
+ "RootNode.rin_lash_02.rin_lash_02_1.rin_m_lashes",
+ "RootNode.rin_lash_02.rin_lash_02_2.Bitangent",
+ "RootNode.rin_lash_02.rin_lash_02_2.SkinWeight_",
+ "RootNode.rin_lash_02.rin_lash_02_2.transform",
+ "RootNode.rin_lash_02.rin_lash_02_2.Tangent",
+ "RootNode.rin_lash_02.rin_lash_02_2.map1",
+ "RootNode.rin_lash_02.rin_lash_02_2.rin_m_lashes",
+ "RootNode.rin_lash_03.rin_lash_03_1.Bitangent",
+ "RootNode.rin_lash_03.rin_lash_03_1.SkinWeight_",
+ "RootNode.rin_lash_03.rin_lash_03_1.transform",
+ "RootNode.rin_lash_03.rin_lash_03_1.Tangent",
+ "RootNode.rin_lash_03.rin_lash_03_1.map1",
+ "RootNode.rin_lash_03.rin_lash_03_1.rin_m_lashes",
+ "RootNode.rin_lash_03.rin_lash_03_2.Bitangent",
+ "RootNode.rin_lash_03.rin_lash_03_2.SkinWeight_",
+ "RootNode.rin_lash_03.rin_lash_03_2.transform",
+ "RootNode.rin_lash_03.rin_lash_03_2.Tangent",
+ "RootNode.rin_lash_03.rin_lash_03_2.map1",
+ "RootNode.rin_lash_03.rin_lash_03_2.rin_m_lashes",
+ "RootNode.rin_eyewetness.rin_eyewetness_1.Bitangent",
+ "RootNode.rin_eyewetness.rin_eyewetness_1.SkinWeight_",
+ "RootNode.rin_eyewetness.rin_eyewetness_1.transform",
+ "RootNode.rin_eyewetness.rin_eyewetness_1.Tangent",
+ "RootNode.rin_eyewetness.rin_eyewetness_1.map1",
+ "RootNode.rin_eyewetness.rin_eyewetness_1.rin_m_eyewetness",
+ "RootNode.rin_eyewetness.rin_eyewetness_2.Bitangent",
+ "RootNode.rin_eyewetness.rin_eyewetness_2.SkinWeight_",
+ "RootNode.rin_eyewetness.rin_eyewetness_2.transform",
+ "RootNode.rin_eyewetness.rin_eyewetness_2.Tangent",
+ "RootNode.rin_eyewetness.rin_eyewetness_2.map1",
+ "RootNode.rin_eyewetness.rin_eyewetness_2.rin_m_eyewetness",
+ "RootNode.rin_eyebrows_lower.rin_eyebrows_lower_1.Bitangent",
+ "RootNode.rin_eyebrows_lower.rin_eyebrows_lower_1.SkinWeight_",
+ "RootNode.rin_eyebrows_lower.rin_eyebrows_lower_1.transform",
+ "RootNode.rin_eyebrows_lower.rin_eyebrows_lower_1.Tangent",
+ "RootNode.rin_eyebrows_lower.rin_eyebrows_lower_1.map1",
+ "RootNode.rin_eyebrows_lower.rin_eyebrows_lower_1.rin_m_eyebrow",
+ "RootNode.rin_eyebrows_lower.rin_eyebrows_lower_2.Bitangent",
+ "RootNode.rin_eyebrows_lower.rin_eyebrows_lower_2.SkinWeight_",
+ "RootNode.rin_eyebrows_lower.rin_eyebrows_lower_2.transform",
+ "RootNode.rin_eyebrows_lower.rin_eyebrows_lower_2.Tangent",
+ "RootNode.rin_eyebrows_lower.rin_eyebrows_lower_2.map1",
+ "RootNode.rin_eyebrows_lower.rin_eyebrows_lower_2.rin_m_eyebrow",
+ "RootNode.rin_tearduct.rin_tearduct_1.Bitangent",
+ "RootNode.rin_tearduct.rin_tearduct_1.SkinWeight_",
+ "RootNode.rin_tearduct.rin_tearduct_1.transform",
+ "RootNode.rin_tearduct.rin_tearduct_1.Tangent",
+ "RootNode.rin_tearduct.rin_tearduct_1.map1",
+ "RootNode.rin_tearduct.rin_tearduct_1.rin_m_tearduct",
+ "RootNode.rin_tearduct.rin_tearduct_2.Bitangent",
+ "RootNode.rin_tearduct.rin_tearduct_2.SkinWeight_",
+ "RootNode.rin_tearduct.rin_tearduct_2.transform",
+ "RootNode.rin_tearduct.rin_tearduct_2.Tangent",
+ "RootNode.rin_tearduct.rin_tearduct_2.map1",
+ "RootNode.rin_tearduct.rin_tearduct_2.rin_m_tearduct",
+ "RootNode.root.C_pelvis_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT",
+ "RootNode.root.C_pelvis_JNT.L_leg_JNT",
+ "RootNode.root.C_pelvis_JNT.R_leg_JNT",
+ "RootNode.root.C_pelvis_JNT.L_ribbon_01_JNT",
+ "RootNode.root.C_pelvis_JNT.R_ribbon_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_legArmor_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_sword_JNT",
+ "RootNode.root.C_pelvis_JNT.L_leg_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.L_leg_JNT.L_knee_JNT",
+ "RootNode.root.C_pelvis_JNT.L_leg_JNT.L_leg_twist_JNT",
+ "RootNode.root.C_pelvis_JNT.R_leg_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.R_leg_JNT.R_knee_JNT",
+ "RootNode.root.C_pelvis_JNT.R_leg_JNT.R_leg_twist_JNT",
+ "RootNode.root.C_pelvis_JNT.L_ribbon_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.L_ribbon_01_JNT.L_ribbon_02_JNT",
+ "RootNode.root.C_pelvis_JNT.R_ribbon_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.R_ribbon_01_JNT.R_ribbon_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_legArmor_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_sword_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.L_leg_JNT.L_knee_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.L_leg_JNT.L_knee_JNT.L_foot_JNT",
+ "RootNode.root.C_pelvis_JNT.L_leg_JNT.L_knee_JNT.L_knee_twist_JNT",
+ "RootNode.root.C_pelvis_JNT.L_leg_JNT.L_leg_twist_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.R_leg_JNT.R_knee_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.R_leg_JNT.R_knee_JNT.R_foot_JNT",
+ "RootNode.root.C_pelvis_JNT.R_leg_JNT.R_knee_JNT.R_knee_twist_JNT",
+ "RootNode.root.C_pelvis_JNT.R_leg_JNT.R_leg_twist_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.L_ribbon_01_JNT.L_ribbon_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.R_ribbon_01_JNT.R_ribbon_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT",
+ "RootNode.root.C_pelvis_JNT.L_leg_JNT.L_knee_JNT.L_foot_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.L_leg_JNT.L_knee_JNT.L_foot_JNT.L_toe_JNT",
+ "RootNode.root.C_pelvis_JNT.L_leg_JNT.L_knee_JNT.L_knee_twist_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.R_leg_JNT.R_knee_JNT.R_foot_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.R_leg_JNT.R_knee_JNT.R_foot_JNT.R_toe_JNT",
+ "RootNode.root.C_pelvis_JNT.R_leg_JNT.R_knee_JNT.R_knee_twist_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_hood_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neckCollar_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_neckCollar_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_neckCollar_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_neckCollar_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_neckCollar_02_JNT",
+ "RootNode.root.C_pelvis_JNT.L_leg_JNT.L_knee_JNT.L_foot_JNT.L_toe_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.R_leg_JNT.R_knee_JNT.R_foot_JNT.R_toe_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_tassle_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_tassleLoop_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_armPit_corr_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_tassle_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_tassleLoop_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_armPit_corr_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_hood_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_hood_01_JNT.C_hood_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neckCollar_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_neckCollar_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_neckCollar_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_neckCollar_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_neckCollar_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_arm_twist_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_armBulge_corr_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_tassle_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_tassle_01_JNT.L_tassle_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_tassleLoop_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_tassleLoop_01_JNT.L_tassleLoop_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_armPit_corr_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_throat_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_arm_twist_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_armBulge_corr_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_tassle_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_tassle_01_JNT.R_tassle_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_tassleLoop_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_tassleLoop_01_JNT.R_tassleLoop_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_armPit_corr_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_hood_01_JNT.C_hood_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_hood_01_JNT.C_hood_02_JNT.C_hood_03_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_elbow_twist_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_arm_twist_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_armBulge_corr_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_tassle_01_JNT.L_tassle_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_tassle_01_JNT.L_tassle_02_JNT.L_tassle_03_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_tassleLoop_01_JNT.L_tassleLoop_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_brow_inner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_brow_mid_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_brow_outer_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_corrugator_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_noseBridge_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_nostril_inner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_nostril_outer_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_cheekUpper_inner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_squint_mid_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_squint_outer_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_squint_inner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_zygomatic_outer_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_cheekBone_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_ear_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_nose_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_chin_below_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_chin_below_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_eyelid_lower_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_eyelid_upper_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_eyelid_levator_mid_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_eye_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_lipLevator_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_lipUpper_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_lipUpper_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_lipLevator_inner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_lipLevator_corner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_cheekUpper_outer_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_cheekUpper_mid_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_eyelid_upper_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_eyelid_lower_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_nostril_inner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_lipLevator_inner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_cheekBone_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_zygomatic_outer_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_lipUpper_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_chin_below_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_ear_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_nose_slide_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_eye_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_brow_inner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_brow_mid_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_brow_outer_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_lipLevator_corner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_cheekUpper_outer_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_cheekUpper_mid_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_nostril_outer_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_cheekUpper_inner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_squint_inner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_squint_mid_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_squint_outer_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_lipUpper_corner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_lipUpper_corner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_frontalis_inner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_frontalis_outer_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_frontalis_outer_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_frontalis_inner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_eyelid_fold_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_eyelid_fold_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_eye_bulge_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_eye_bulge_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_throat_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_elbow_twist_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_arm_twist_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_armBulge_corr_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_tassle_01_JNT.R_tassle_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_tassle_01_JNT.R_tassle_02_JNT.R_tassle_03_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_tassleLoop_01_JNT.R_tassleLoop_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_hood_01_JNT.C_hood_02_JNT.C_hood_03_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_thumb_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_index_root_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_middle_root_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_ring_root_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_pinky_root_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_elbow_twist_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_tassle_01_JNT.L_tassle_02_JNT.L_tassle_03_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_brow_inner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_brow_mid_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_brow_outer_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_corrugator_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_noseBridge_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_nostril_inner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_nostril_outer_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_cheekUpper_inner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_squint_mid_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_squint_outer_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_squint_inner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_zygomatic_outer_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_cheekBone_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_ear_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_nose_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_chin_below_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_chin_below_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_eyelid_lower_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_eyelid_upper_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_eyelid_levator_mid_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_eye_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_lipLevator_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_lipUpper_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_lipUpper_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_lipLevator_inner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_lipLevator_corner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.C_mentalis_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.L_depressor_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.R_depressor_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.L_lip_nasolabial_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.R_mouth_corner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.C_lip_below_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.R_lip_nasolabial_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.R_lipLower_corner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.R_lipLower_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.C_lipLower_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.L_lipLower_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.L_mouth_corner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.L_lipLower_corner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.R_jaw_clench_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.L_jaw_clench_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.L_zygomatic_inner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.R_zygomatic_inner_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.C_tongue_root_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_cheekUpper_outer_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_cheekUpper_mid_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_eyelid_upper_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_eyelid_lower_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_nostril_inner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_lipLevator_inner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_cheekBone_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_zygomatic_outer_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_lipUpper_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_chin_below_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_ear_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_nose_slide_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_eye_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_brow_inner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_brow_mid_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_brow_outer_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_lipLevator_corner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_cheekUpper_outer_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_cheekUpper_mid_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_nostril_outer_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_cheekUpper_inner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_squint_inner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_squint_mid_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_squint_outer_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_lipUpper_corner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_lipUpper_corner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_frontalis_inner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_frontalis_outer_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_frontalis_outer_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_frontalis_inner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_eyelid_fold_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_eyelid_fold_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.L_eye_bulge_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.R_eye_bulge_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_thumb_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_index_root_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_middle_root_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_ring_root_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_pinky_root_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_elbow_twist_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_tassle_01_JNT.R_tassle_02_JNT.R_tassle_03_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_thumb_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_thumb_01_JNT.L_thumb_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_index_root_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_index_root_JNT.L_index_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_middle_root_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_middle_root_JNT.L_middle_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_ring_root_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_ring_root_JNT.L_ring_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_pinky_root_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_pinky_root_JNT.L_pinky_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.C_mentalis_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.L_depressor_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.R_depressor_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.L_lip_nasolabial_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.R_mouth_corner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.C_lip_below_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.R_lip_nasolabial_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.R_lipLower_corner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.R_lipLower_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.C_lipLower_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.L_lipLower_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.L_mouth_corner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.L_lipLower_corner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.R_jaw_clench_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.L_jaw_clench_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.L_zygomatic_inner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.R_zygomatic_inner_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.C_tongue_root_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.C_tongue_root_JNT.C_tongue_mid_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_thumb_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_thumb_01_JNT.R_thumb_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_index_root_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_index_root_JNT.R_index_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_middle_root_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_middle_root_JNT.R_middle_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_ring_root_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_ring_root_JNT.R_ring_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_pinky_root_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_pinky_root_JNT.R_pinky_01_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_thumb_01_JNT.L_thumb_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_thumb_01_JNT.L_thumb_02_JNT.L_thumb_03_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_index_root_JNT.L_index_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_index_root_JNT.L_index_01_JNT.L_index_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_middle_root_JNT.L_middle_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_middle_root_JNT.L_middle_01_JNT.L_middle_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_ring_root_JNT.L_ring_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_ring_root_JNT.L_ring_01_JNT.L_ring_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_pinky_root_JNT.L_pinky_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_pinky_root_JNT.L_pinky_01_JNT.L_pinky_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.C_tongue_root_JNT.C_tongue_mid_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.C_tongue_root_JNT.C_tongue_mid_JNT.C_tongue_tip_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_thumb_01_JNT.R_thumb_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_thumb_01_JNT.R_thumb_02_JNT.R_thumb_03_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_index_root_JNT.R_index_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_index_root_JNT.R_index_01_JNT.R_index_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_middle_root_JNT.R_middle_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_middle_root_JNT.R_middle_01_JNT.R_middle_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_ring_root_JNT.R_ring_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_ring_root_JNT.R_ring_01_JNT.R_ring_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_pinky_root_JNT.R_pinky_01_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_pinky_root_JNT.R_pinky_01_JNT.R_pinky_02_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_thumb_01_JNT.L_thumb_02_JNT.L_thumb_03_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_index_root_JNT.L_index_01_JNT.L_index_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_index_root_JNT.L_index_01_JNT.L_index_02_JNT.L_index_03_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_middle_root_JNT.L_middle_01_JNT.L_middle_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_middle_root_JNT.L_middle_01_JNT.L_middle_02_JNT.L_middle_03_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_ring_root_JNT.L_ring_01_JNT.L_ring_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_ring_root_JNT.L_ring_01_JNT.L_ring_02_JNT.L_ring_03_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_pinky_root_JNT.L_pinky_01_JNT.L_pinky_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_pinky_root_JNT.L_pinky_01_JNT.L_pinky_02_JNT.L_pinky_03_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.C_neck_01_JNT.C_neck_02_JNT.C_head_JNT.C_jaw_JNT.C_tongue_root_JNT.C_tongue_mid_JNT.C_tongue_tip_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_thumb_01_JNT.R_thumb_02_JNT.R_thumb_03_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_index_root_JNT.R_index_01_JNT.R_index_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_index_root_JNT.R_index_01_JNT.R_index_02_JNT.R_index_03_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_middle_root_JNT.R_middle_01_JNT.R_middle_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_middle_root_JNT.R_middle_01_JNT.R_middle_02_JNT.R_middle_03_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_ring_root_JNT.R_ring_01_JNT.R_ring_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_ring_root_JNT.R_ring_01_JNT.R_ring_02_JNT.R_ring_03_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_pinky_root_JNT.R_pinky_01_JNT.R_pinky_02_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_pinky_root_JNT.R_pinky_01_JNT.R_pinky_02_JNT.R_pinky_03_JNT",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_index_root_JNT.L_index_01_JNT.L_index_02_JNT.L_index_03_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_middle_root_JNT.L_middle_01_JNT.L_middle_02_JNT.L_middle_03_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_ring_root_JNT.L_ring_01_JNT.L_ring_02_JNT.L_ring_03_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.L_clavicle_JNT.L_arm_JNT.L_elbow_JNT.L_wrist_JNT.L_pinky_root_JNT.L_pinky_01_JNT.L_pinky_02_JNT.L_pinky_03_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_index_root_JNT.R_index_01_JNT.R_index_02_JNT.R_index_03_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_middle_root_JNT.R_middle_01_JNT.R_middle_02_JNT.R_middle_03_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_ring_root_JNT.R_ring_01_JNT.R_ring_02_JNT.R_ring_03_JNT.transform",
+ "RootNode.root.C_pelvis_JNT.C_spine_01_JNT.C_spine_02_JNT.C_spine_03_JNT.C_spine_04_JNT.R_clavicle_JNT.R_arm_JNT.R_elbow_JNT.R_wrist_JNT.R_pinky_root_JNT.R_pinky_01_JNT.R_pinky_02_JNT.R_pinky_03_JNT.transform"
+ ]
+ },
+ "rules": {
+ "rules": [
+ {
+ "$type": "SkinRule"
+ },
+ {
+ "$type": "StaticMeshAdvancedRule",
+ "vertexColorStreamName": "Col0"
+ },
+ {
+ "$type": "MaterialRule"
+ }
+ ]
+ },
+ "id": "{CA754822-3673-46C8-9EE7-3453CF782C5A}"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Gems/MotionMatching/Assets/MotionMatching.animgraph b/Gems/MotionMatching/Assets/MotionMatching.animgraph
new file mode 100644
index 0000000000..10707eb6c4
--- /dev/null
+++ b/Gems/MotionMatching/Assets/MotionMatching.animgraph
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:09cc2374b99c219421812ec39b68a350912d44777a50e3078c8cd67e91cc74cf
+size 30927
diff --git a/Gems/MotionMatching/Assets/MotionMatching.emfxworkspace b/Gems/MotionMatching/Assets/MotionMatching.emfxworkspace
new file mode 100644
index 0000000000..6d59fa310d
--- /dev/null
+++ b/Gems/MotionMatching/Assets/MotionMatching.emfxworkspace
@@ -0,0 +1,3 @@
+[General]
+version=1
+startScript="ImportActor -filename \"Character/RinMM.actor\"\nCreateActorInstance -actorID %LASTRESULT% -xPos 4.585605 -yPos -7.166286 -zPos 0.000000 -xScale 1.000000 -yScale 1.000000 -zScale 1.000000 -rot 0.00000000,0.00000000,0.98711985,-0.15998250\nLoadMotionSet -filename \"@products@/MotionMatching.motionset\"\nLoadAnimGraph -filename \"@products@/MotionMatching.animgraph\"\nActivateAnimGraph -actorInstanceID %LASTRESULT3% -animGraphID %LASTRESULT1% -motionSetID %LASTRESULT2% -visualizeScale 1.000000\n"
diff --git a/Gems/MotionMatching/Assets/MotionMatching.motionset b/Gems/MotionMatching/Assets/MotionMatching.motionset
new file mode 100644
index 0000000000..276895e3a0
--- /dev/null
+++ b/Gems/MotionMatching/Assets/MotionMatching.motionset
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:9c895a1696f5f37492089ceaef11210d704c1fb7e3dd31305cf4732d63489507
+size 13645
diff --git a/Gems/MotionMatching/CMakeLists.txt b/Gems/MotionMatching/CMakeLists.txt
new file mode 100644
index 0000000000..341df6e33d
--- /dev/null
+++ b/Gems/MotionMatching/CMakeLists.txt
@@ -0,0 +1,16 @@
+#
+# Copyright (c) Contributors to the Open 3D Engine Project.
+# For complete copyright and license terms please see the LICENSE at the root of this distribution.
+#
+# SPDX-License-Identifier: Apache-2.0 OR MIT
+#
+#
+
+set(o3de_gem_path ${CMAKE_CURRENT_LIST_DIR})
+set(o3de_gem_json ${o3de_gem_path}/gem.json)
+o3de_read_json_key(o3de_gem_name ${o3de_gem_json} "gem_name")
+o3de_restricted_path(${o3de_gem_json} o3de_gem_restricted_path)
+
+ly_add_external_target_path(${CMAKE_CURRENT_LIST_DIR}/3rdParty)
+
+add_subdirectory(Code)
diff --git a/Gems/MotionMatching/Code/CMakeLists.txt b/Gems/MotionMatching/Code/CMakeLists.txt
new file mode 100644
index 0000000000..275f8f2530
--- /dev/null
+++ b/Gems/MotionMatching/Code/CMakeLists.txt
@@ -0,0 +1,155 @@
+#
+# Copyright (c) Contributors to the Open 3D Engine Project.
+# For complete copyright and license terms please see the LICENSE at the root of this distribution.
+#
+# SPDX-License-Identifier: Apache-2.0 OR MIT
+#
+#
+
+# Add the MotionMatching.Static target
+ly_add_target(
+ NAME MotionMatching.Static STATIC
+ NAMESPACE Gem
+ FILES_CMAKE
+ motionmatching_files.cmake
+ INCLUDE_DIRECTORIES
+ PUBLIC
+ Include
+ PRIVATE
+ Source
+ BUILD_DEPENDENCIES
+ PUBLIC
+ AZ::AzCore
+ AZ::AzFramework
+ Gem::EMotionFXStaticLib
+ Gem::ImguiAtom.Static
+)
+
+# Here add MotionMatching target, it depends on the MotionMatching.Static
+ly_add_target(
+ NAME MotionMatching ${PAL_TRAIT_MONOLITHIC_DRIVEN_MODULE_TYPE}
+ NAMESPACE Gem
+ FILES_CMAKE
+ motionmatching_shared_files.cmake
+ INCLUDE_DIRECTORIES
+ PUBLIC
+ Include
+ PRIVATE
+ Source
+ BUILD_DEPENDENCIES
+ PRIVATE
+ Gem::MotionMatching.Static
+ Gem::ImGui.Static
+ Gem::ImGui.ImGuiLYUtils
+)
+
+# By default, we will specify that the above target MotionMatching would be used by
+# Client and Server type targets when this gem is enabled. If you don't want it
+# active in Clients or Servers by default, delete one of both of the following lines:
+ly_create_alias(NAME MotionMatching.Clients NAMESPACE Gem TARGETS Gem::MotionMatching)
+ly_create_alias(NAME MotionMatching.Servers NAMESPACE Gem TARGETS Gem::MotionMatching)
+
+# If we are on a host platform, we want to add the host tools targets like the MotionMatching.Editor target which
+# will also depend on MotionMatching.Static
+if(PAL_TRAIT_BUILD_HOST_TOOLS)
+ ly_add_target(
+ NAME MotionMatching.Editor.Static STATIC
+ NAMESPACE Gem
+ FILES_CMAKE
+ motionmatching_editor_files.cmake
+ INCLUDE_DIRECTORIES
+ PRIVATE
+ Source
+ PUBLIC
+ Include
+ BUILD_DEPENDENCIES
+ PUBLIC
+ AZ::AzToolsFramework
+ Gem::MotionMatching.Static
+ )
+
+ ly_add_target(
+ NAME MotionMatching.Editor GEM_MODULE
+ NAMESPACE Gem
+ AUTOMOC
+ OUTPUT_NAME Gem.MotionMatching.Editor
+ FILES_CMAKE
+ motionmatching_editor_shared_files.cmake
+ INCLUDE_DIRECTORIES
+ PRIVATE
+ Source
+ PUBLIC
+ Include
+ BUILD_DEPENDENCIES
+ PUBLIC
+ Gem::MotionMatching.Editor.Static
+ )
+
+ # By default, we will specify that the above target MotionMatching would be used by
+ # Tool and Builder type targets when this gem is enabled. If you don't want it
+ # active in Tools or Builders by default, delete one of both of the following lines:
+ ly_create_alias(NAME MotionMatching.Tools NAMESPACE Gem TARGETS Gem::MotionMatching.Editor)
+ ly_create_alias(NAME MotionMatching.Builders NAMESPACE Gem TARGETS Gem::MotionMatching.Editor)
+
+
+endif()
+
+################################################################################
+# Tests
+################################################################################
+# See if globally, tests are supported
+if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
+ # We globally support tests, see if we support tests on this platform for MotionMatching.Static
+ if(PAL_TRAIT_MOTIONMATCHING_TEST_SUPPORTED)
+ # We support MotionMatching.Tests on this platform, add MotionMatching.Tests target which depends on MotionMatching.Static
+ ly_add_target(
+ NAME MotionMatching.Tests ${PAL_TRAIT_TEST_TARGET_TYPE}
+ NAMESPACE Gem
+ FILES_CMAKE
+ motionmatching_files.cmake
+ motionmatching_tests_files.cmake
+ INCLUDE_DIRECTORIES
+ PRIVATE
+ Tests
+ Source
+ BUILD_DEPENDENCIES
+ PRIVATE
+ AZ::AzTest
+ AZ::AzFramework
+ Gem::EMotionFX.Tests.Static
+ Gem::MotionMatching.Static
+ )
+
+ # Add MotionMatching.Tests to googletest
+ ly_add_googletest(
+ NAME Gem::MotionMatching.Tests
+ )
+ endif()
+
+ # If we are a host platform we want to add tools test like editor tests here
+ if(PAL_TRAIT_BUILD_HOST_TOOLS)
+ # We are a host platform, see if Editor tests are supported on this platform
+ if(PAL_TRAIT_MOTIONMATCHING_EDITOR_TEST_SUPPORTED)
+ # We support MotionMatching.Editor.Tests on this platform, add MotionMatching.Editor.Tests target which depends on MotionMatching.Editor
+ ly_add_target(
+ NAME MotionMatching.Editor.Tests ${PAL_TRAIT_TEST_TARGET_TYPE}
+ NAMESPACE Gem
+ FILES_CMAKE
+ motionmatching_editor_tests_files.cmake
+ INCLUDE_DIRECTORIES
+ PRIVATE
+ Tests
+ Source
+ BUILD_DEPENDENCIES
+ PRIVATE
+ AZ::AzTest
+ Gem::MotionMatching.Editor
+ )
+
+ # Add MotionMatching.Editor.Tests to googletest
+ ly_add_googletest(
+ NAME Gem::MotionMatching.Editor.Tests
+ )
+ endif()
+ endif()
+endif()
diff --git a/Gems/MotionMatching/Code/Include/MotionMatching/MotionMatchingBus.h b/Gems/MotionMatching/Code/Include/MotionMatching/MotionMatchingBus.h
new file mode 100644
index 0000000000..5b2bc1847a
--- /dev/null
+++ b/Gems/MotionMatching/Code/Include/MotionMatching/MotionMatchingBus.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include
+#include
+
+namespace EMotionFX::MotionMatching
+{
+ class MotionMatchingRequests
+ {
+ public:
+ AZ_RTTI(MotionMatchingRequests, "{b08f73cc-a922-49ef-8c0e-07166b43ea65}");
+ virtual ~MotionMatchingRequests() = default;
+ // Put your public methods here
+ };
+
+ class MotionMatchingBusTraits
+ : public AZ::EBusTraits
+ {
+ public:
+ //////////////////////////////////////////////////////////////////////////
+ // EBusTraits overrides
+ static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
+ static constexpr AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
+ //////////////////////////////////////////////////////////////////////////
+ };
+
+ using MotionMatchingRequestBus = AZ::EBus;
+ using MotionMatchingInterface = AZ::Interface;
+
+} // namespace EMotionFX::MotionMatching
diff --git a/Gems/MotionMatching/Code/Source/Allocators.h b/Gems/MotionMatching/Code/Source/Allocators.h
new file mode 100644
index 0000000000..af6fa27cc8
--- /dev/null
+++ b/Gems/MotionMatching/Code/Source/Allocators.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include
+
+namespace EMotionFX::MotionMatching
+{
+ using MotionMatchAllocator = AZ::SystemAllocator;
+} // namespace MotionMatching
diff --git a/Gems/MotionMatching/Code/Source/BlendTreeMotionMatchNode.cpp b/Gems/MotionMatching/Code/Source/BlendTreeMotionMatchNode.cpp
new file mode 100644
index 0000000000..58cd3903e1
--- /dev/null
+++ b/Gems/MotionMatching/Code/Source/BlendTreeMotionMatchNode.cpp
@@ -0,0 +1,373 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+namespace EMotionFX::MotionMatching
+{
+ AZ_CLASS_ALLOCATOR_IMPL(BlendTreeMotionMatchNode, AnimGraphAllocator, 0)
+ AZ_CLASS_ALLOCATOR_IMPL(BlendTreeMotionMatchNode::UniqueData, AnimGraphObjectUniqueDataAllocator, 0)
+
+ BlendTreeMotionMatchNode::BlendTreeMotionMatchNode()
+ : AnimGraphNode()
+ {
+ // Setup the input ports.
+ InitInputPorts(2);
+ SetupInputPort("Goal Pos", INPUTPORT_TARGETPOS, MCore::AttributeVector3::TYPE_ID, PORTID_INPUT_TARGETPOS);
+ SetupInputPort("Goal Facing Dir", INPUTPORT_TARGETFACINGDIR, MCore::AttributeVector3::TYPE_ID, PORTID_INPUT_TARGETFACINGDIR);
+
+ // Setup the output ports.
+ InitOutputPorts(1);
+ SetupOutputPortAsPose("Output Pose", OUTPUTPORT_POSE, PORTID_OUTPUT_POSE);
+ }
+
+ BlendTreeMotionMatchNode::~BlendTreeMotionMatchNode()
+ {
+ }
+
+ bool BlendTreeMotionMatchNode::InitAfterLoading(AnimGraph* animGraph)
+ {
+ if (!AnimGraphNode::InitAfterLoading(animGraph))
+ {
+ return false;
+ }
+
+ // Automatically register the default feature schema in case the schema is empty after loading the node.
+ if (m_featureSchema.GetNumFeatures() == 0)
+ {
+ AZStd::string rootJointName;
+ if (m_animGraph->GetNumAnimGraphInstances() > 0)
+ {
+ const Actor* actor = m_animGraph->GetAnimGraphInstance(0)->GetActorInstance()->GetActor();
+ const Node* rootJoint = actor->GetMotionExtractionNode();
+ if (rootJoint)
+ {
+ rootJointName = rootJoint->GetNameString();
+ }
+ }
+
+ DefaultFeatureSchemaInitSettings defaultSettings;
+ defaultSettings.m_rootJointName = rootJointName.c_str();
+ defaultSettings.m_leftFootJointName = "L_foot_JNT";
+ defaultSettings.m_rightFootJointName = "R_foot_JNT";
+ defaultSettings.m_pelvisJointName = "C_pelvis_JNT";
+ DefaultFeatureSchema(m_featureSchema, defaultSettings);
+ }
+
+ InitInternalAttributesForAllInstances();
+
+ Reinit();
+ return true;
+ }
+
+ const char* BlendTreeMotionMatchNode::GetPaletteName() const
+ {
+ return "Motion Matching";
+ }
+
+ AnimGraphObject::ECategory BlendTreeMotionMatchNode::GetPaletteCategory() const
+ {
+ return AnimGraphObject::CATEGORY_SOURCES;
+ }
+
+ void BlendTreeMotionMatchNode::UniqueData::Update()
+ {
+ AZ_PROFILE_SCOPE(Animation, "BlendTreeMotionMatchNode::UniqueData::Update");
+
+ auto animGraphNode = azdynamic_cast(m_object);
+ AZ_Assert(animGraphNode, "Unique data linked to incorrect node type.");
+
+ ActorInstance* actorInstance = m_animGraphInstance->GetActorInstance();
+
+ // Clear existing data.
+ delete m_instance;
+ delete m_data;
+
+ m_data = aznew MotionMatching::MotionMatchingData(animGraphNode->m_featureSchema);
+ m_instance = aznew MotionMatching::MotionMatchingInstance();
+
+ MotionSet* motionSet = m_animGraphInstance->GetMotionSet();
+ if (!motionSet)
+ {
+ SetHasError(true);
+ return;
+ }
+
+ //---------------------------------
+ AZ::Debug::Timer timer;
+ timer.Stamp();
+
+ // Build a list of motions we want to import the frames from.
+ AZ_Printf("Motion Matching", "Importing motion database...");
+ MotionMatching::MotionMatchingData::InitSettings settings;
+ settings.m_actorInstance = actorInstance;
+ settings.m_frameImportSettings.m_sampleRate = animGraphNode->m_sampleRate;
+ settings.m_importMirrored = animGraphNode->m_mirror;
+ settings.m_maxKdTreeDepth = animGraphNode->m_maxKdTreeDepth;
+ settings.m_minFramesPerKdTreeNode = animGraphNode->m_minFramesPerKdTreeNode;
+ settings.m_motionList.reserve(animGraphNode->m_motionIds.size());
+ for (const AZStd::string& id : animGraphNode->m_motionIds)
+ {
+ Motion* motion = motionSet->RecursiveFindMotionById(id);
+ if (motion)
+ {
+ settings.m_motionList.emplace_back(motion);
+ }
+ else
+ {
+ AZ_Warning("Motion Matching", false, "Failed to get motion for motionset entry id '%s'", id.c_str());
+ }
+ }
+
+ // Initialize the motion matching data (slow).
+ AZ_Printf("Motion Matching", "Initializing motion matching...");
+ if (!m_data->Init(settings))
+ {
+ AZ_Warning("Motion Matching", false, "Failed to initialize motion matching for anim graph node '%s'!", animGraphNode->GetName());
+ SetHasError(true);
+ return;
+ }
+
+ // Initialize the instance.
+ AZ_Printf("Motion Matching", "Initializing instance...");
+ MotionMatching::MotionMatchingInstance::InitSettings initSettings;
+ initSettings.m_actorInstance = actorInstance;
+ initSettings.m_data = m_data;
+ m_instance->Init(initSettings);
+
+ const float initTime = timer.GetDeltaTimeInSeconds();
+ const size_t memUsage = m_data->GetFrameDatabase().CalcMemoryUsageInBytes();
+ AZ_Printf("Motion Matching", "Finished in %.2f seconds (mem usage=%d bytes or %.2f mb)", initTime, memUsage, memUsage / (float)(1024 * 1024));
+ //---------------------------------
+
+ SetHasError(false);
+ }
+
+ void BlendTreeMotionMatchNode::Update(AnimGraphInstance* animGraphInstance, float timePassedInSeconds)
+ {
+ AZ_PROFILE_SCOPE(Animation, "BlendTreeMotionMatchNode::Update");
+
+ m_timer.Stamp();
+
+ UniqueData* uniqueData = static_cast(FindOrCreateUniqueNodeData(animGraphInstance));
+ UpdateAllIncomingNodes(animGraphInstance, timePassedInSeconds);
+ uniqueData->Clear();
+ if (uniqueData->GetHasError())
+ {
+ m_updateTimeInMs = 0.0f;
+ m_postUpdateTimeInMs = 0.0f;
+ m_outputTimeInMs = 0.0f;
+ return;
+ }
+
+ AZ::Vector3 targetPos = AZ::Vector3::CreateZero();
+ TryGetInputVector3(animGraphInstance, INPUTPORT_TARGETPOS, targetPos);
+
+ AZ::Vector3 targetFacingDir = AZ::Vector3::CreateAxisY();
+ TryGetInputVector3(animGraphInstance, INPUTPORT_TARGETFACINGDIR, targetFacingDir);
+
+ MotionMatching::MotionMatchingInstance* instance = uniqueData->m_instance;
+ instance->Update(timePassedInSeconds, targetPos, targetFacingDir, m_trajectoryQueryMode, m_pathRadius, m_pathSpeed);
+
+ // set the current time to the new calculated time
+ uniqueData->ClearInheritFlags();
+ uniqueData->SetPreSyncTime(instance->GetMotionInstance()->GetCurrentTime());
+ uniqueData->SetCurrentPlayTime(instance->GetNewMotionTime());
+
+ if (uniqueData->GetPreSyncTime() > uniqueData->GetCurrentPlayTime())
+ {
+ uniqueData->SetPreSyncTime(uniqueData->GetCurrentPlayTime());
+ }
+
+ m_updateTimeInMs = m_timer.GetDeltaTimeInSeconds() * 1000.0f;
+ }
+
+ void BlendTreeMotionMatchNode::PostUpdate(AnimGraphInstance* animGraphInstance, float timePassedInSeconds)
+ {
+ AZ_PROFILE_SCOPE(Animation, "BlendTreeMotionMatchNode::PostUpdate");
+
+ AZ_UNUSED(animGraphInstance);
+ AZ_UNUSED(timePassedInSeconds);
+ m_timer.Stamp();
+
+ for (AZ::u32 i = 0; i < GetNumConnections(); ++i)
+ {
+ AnimGraphNode* node = GetConnection(i)->GetSourceNode();
+ node->PerformPostUpdate(animGraphInstance, timePassedInSeconds);
+ }
+
+ UniqueData* uniqueData = static_cast(FindOrCreateUniqueNodeData(animGraphInstance));
+ MotionMatching::MotionMatchingInstance* instance = uniqueData->m_instance;
+
+ RequestRefDatas(animGraphInstance);
+ AnimGraphRefCountedData* data = uniqueData->GetRefCountedData();
+ data->ClearEventBuffer();
+ data->ZeroTrajectoryDelta();
+
+ if (uniqueData->GetHasError())
+ {
+ return;
+ }
+
+ MotionInstance* motionInstance = instance->GetMotionInstance();
+ motionInstance->UpdateByTimeValues(uniqueData->GetPreSyncTime(), uniqueData->GetCurrentPlayTime(), &data->GetEventBuffer());
+
+ uniqueData->SetCurrentPlayTime(motionInstance->GetCurrentTime());
+ data->GetEventBuffer().UpdateEmitters(this);
+
+ instance->PostUpdate(timePassedInSeconds);
+
+ const Transform& trajectoryDelta = instance->GetMotionExtractionDelta();
+ data->SetTrajectoryDelta(trajectoryDelta);
+ data->SetTrajectoryDeltaMirrored(trajectoryDelta); // TODO: use a real mirrored version here.
+
+ m_postUpdateTimeInMs = m_timer.GetDeltaTimeInSeconds() * 1000.0f;
+ }
+
+ void BlendTreeMotionMatchNode::Output(AnimGraphInstance* animGraphInstance)
+ {
+ AZ_PROFILE_SCOPE(Animation, "BlendTreeMotionMatchNode::Output");
+
+ AZ_UNUSED(animGraphInstance);
+ m_timer.Stamp();
+
+ AnimGraphPose* outputPose;
+
+ // Initialize to bind pose.
+ ActorInstance* actorInstance = animGraphInstance->GetActorInstance();
+ RequestPoses(animGraphInstance);
+ outputPose = GetOutputPose(animGraphInstance, OUTPUTPORT_POSE)->GetValue();
+ outputPose->InitFromBindPose(actorInstance);
+
+ if (m_disabled)
+ {
+ return;
+ }
+
+ UniqueData* uniqueData = static_cast(FindOrCreateUniqueNodeData(animGraphInstance));
+ if (GetEMotionFX().GetIsInEditorMode())
+ {
+ SetHasError(uniqueData, uniqueData->GetHasError());
+ }
+
+ if (uniqueData->GetHasError())
+ {
+ return;
+ }
+
+ OutputIncomingNode(animGraphInstance, GetInputNode(INPUTPORT_TARGETPOS));
+ OutputIncomingNode(animGraphInstance, GetInputNode(INPUTPORT_TARGETFACINGDIR));
+
+ MotionMatching::MotionMatchingInstance* instance = uniqueData->m_instance;
+ instance->SetLowestCostSearchFrequency(m_lowestCostSearchFrequency);
+
+ Pose& outTransformPose = outputPose->GetPose();
+ instance->Output(outTransformPose);
+
+ // Performance metrics
+ m_outputTimeInMs = m_timer.GetDeltaTimeInSeconds() * 1000.0f;
+ {
+ //AZ_Printf("MotionMatch", "Update = %.2f, PostUpdate = %.2f, Output = %.2f", m_updateTime, m_postUpdateTime, m_outputTime);
+#ifdef IMGUI_ENABLED
+ ImGuiMonitorRequestBus::Broadcast(&ImGuiMonitorRequests::PushPerformanceHistogramValue, "Update", m_updateTimeInMs);
+ ImGuiMonitorRequestBus::Broadcast(&ImGuiMonitorRequests::PushPerformanceHistogramValue, "Post Update", m_postUpdateTimeInMs);
+ ImGuiMonitorRequestBus::Broadcast(&ImGuiMonitorRequests::PushPerformanceHistogramValue, "Output", m_outputTimeInMs);
+#endif
+ }
+
+ instance->DebugDraw();
+ }
+
+ void BlendTreeMotionMatchNode::Reflect(AZ::ReflectContext* context)
+ {
+ AZ::SerializeContext* serializeContext = azrtti_cast(context);
+ if (!serializeContext)
+ {
+ return;
+ }
+
+ serializeContext->Class()
+ ->Version(9)
+ ->Field("sampleRate", &BlendTreeMotionMatchNode::m_sampleRate)
+ ->Field("lowestCostSearchFrequency", &BlendTreeMotionMatchNode::m_lowestCostSearchFrequency)
+ ->Field("maxKdTreeDepth", &BlendTreeMotionMatchNode::m_maxKdTreeDepth)
+ ->Field("minFramesPerKdTreeNode", &BlendTreeMotionMatchNode::m_minFramesPerKdTreeNode)
+ ->Field("mirror", &BlendTreeMotionMatchNode::m_mirror)
+ ->Field("controlSplineMode", &BlendTreeMotionMatchNode::m_trajectoryQueryMode)
+ ->Field("pathRadius", &BlendTreeMotionMatchNode::m_pathRadius)
+ ->Field("pathSpeed", &BlendTreeMotionMatchNode::m_pathSpeed)
+ ->Field("featureSchema", &BlendTreeMotionMatchNode::m_featureSchema)
+ ->Field("motionIds", &BlendTreeMotionMatchNode::m_motionIds)
+ ;
+
+ AZ::EditContext* editContext = serializeContext->GetEditContext();
+ if (!editContext)
+ {
+ return;
+ }
+
+ editContext->Class("Motion Matching Node", "Motion Matching Attributes")
+ ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
+ ->Attribute(AZ::Edit::Attributes::AutoExpand, "")
+ ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
+ ->DataElement(AZ::Edit::UIHandlers::Default, &BlendTreeMotionMatchNode::m_sampleRate, "Feature sample rate", "The sample rate (in Hz) used for extracting the features from the animations. The higher the sample rate, the more data will be used and the more options the motion matching search has available for the best matching frame.")
+ ->Attribute(AZ::Edit::Attributes::Min, 1)
+ ->Attribute(AZ::Edit::Attributes::Max, 240)
+ ->Attribute(AZ::Edit::Attributes::ChangeNotify, &BlendTreeMotionMatchNode::Reinit)
+ ->DataElement(AZ::Edit::UIHandlers::Default, &BlendTreeMotionMatchNode::m_lowestCostSearchFrequency, "Search frequency", "How often per second we apply the motion matching search and find the lowest cost / best matching frame, and start to blend towards it.")
+ ->Attribute(AZ::Edit::Attributes::Min, 0.001f)
+ ->Attribute(AZ::Edit::Attributes::Max, std::numeric_limits::max())
+ ->Attribute(AZ::Edit::Attributes::Step, 0.05f)
+ ->DataElement(AZ::Edit::UIHandlers::Default, &BlendTreeMotionMatchNode::m_maxKdTreeDepth, "Max kdTree depth", "The maximum number of hierarchy levels in the kdTree.")
+ ->Attribute(AZ::Edit::Attributes::Min, 1)
+ ->Attribute(AZ::Edit::Attributes::Max, 20)
+ ->Attribute(AZ::Edit::Attributes::ChangeNotify, &BlendTreeMotionMatchNode::Reinit)
+ ->DataElement(AZ::Edit::UIHandlers::Default, &BlendTreeMotionMatchNode::m_minFramesPerKdTreeNode, "Min kdTree node size", "The minimum number of frames to store per kdTree node.")
+ ->Attribute(AZ::Edit::Attributes::Min, 1)
+ ->Attribute(AZ::Edit::Attributes::Max, 100000)
+ ->Attribute(AZ::Edit::Attributes::ChangeNotify, &BlendTreeMotionMatchNode::Reinit)
+ ->DataElement(AZ::Edit::UIHandlers::Default, &BlendTreeMotionMatchNode::m_pathRadius, "Path radius", "")
+ ->Attribute(AZ::Edit::Attributes::Min, 0.0001f)
+ ->Attribute(AZ::Edit::Attributes::Max, std::numeric_limits::max())
+ ->Attribute(AZ::Edit::Attributes::Step, 0.01f)
+ ->DataElement(AZ::Edit::UIHandlers::Default, &BlendTreeMotionMatchNode::m_pathSpeed, "Path speed", "")
+ ->Attribute(AZ::Edit::Attributes::Min, 0.0001f)
+ ->Attribute(AZ::Edit::Attributes::Max, std::numeric_limits::max())
+ ->Attribute(AZ::Edit::Attributes::Step, 0.01f)
+ ->DataElement(AZ::Edit::UIHandlers::ComboBox, &BlendTreeMotionMatchNode::m_trajectoryQueryMode, "Trajectory mode", "Desired future trajectory generation mode.")
+ ->EnumAttribute(TrajectoryQuery::MODE_TARGETDRIVEN, "Target driven")
+ ->EnumAttribute(TrajectoryQuery::MODE_ONE, "Mode one")
+ ->EnumAttribute(TrajectoryQuery::MODE_TWO, "Mode two")
+ ->EnumAttribute(TrajectoryQuery::MODE_THREE, "Mode three")
+ ->EnumAttribute(TrajectoryQuery::MODE_FOUR, "Mode four")
+ ->DataElement(AZ::Edit::UIHandlers::Default, &BlendTreeMotionMatchNode::m_featureSchema, "FeatureSchema", "")
+ ->Attribute(AZ::Edit::Attributes::AutoExpand, "")
+ ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
+ ->Attribute(AZ::Edit::Attributes::ChangeNotify, &BlendTreeMotionMatchNode::Reinit)
+ ->DataElement(AZ_CRC("MotionSetMotionIds", 0x8695c0fa), &BlendTreeMotionMatchNode::m_motionIds, "Motions", "")
+ ->Attribute(AZ::Edit::Attributes::ChangeNotify, &BlendTreeMotionMatchNode::Reinit)
+ ->Attribute(AZ::Edit::Attributes::ContainerCanBeModified, false)
+ ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::HideChildren)
+ ;
+ }
+} // namespace EMotionFX::MotionMatching
diff --git a/Gems/MotionMatching/Code/Source/BlendTreeMotionMatchNode.h b/Gems/MotionMatching/Code/Source/BlendTreeMotionMatchNode.h
new file mode 100644
index 0000000000..3acae96d2c
--- /dev/null
+++ b/Gems/MotionMatching/Code/Source/BlendTreeMotionMatchNode.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace EMotionFX::MotionMatching
+{
+ class EMFX_API BlendTreeMotionMatchNode
+ : public AnimGraphNode
+ {
+ public:
+ AZ_RTTI(BlendTreeMotionMatchNode, "{1DC80DCD-6536-4950-9260-A4615C03E3C5}", AnimGraphNode)
+ AZ_CLASS_ALLOCATOR_DECL
+
+ enum
+ {
+ INPUTPORT_TARGETPOS = 0,
+ INPUTPORT_TARGETFACINGDIR = 1,
+ OUTPUTPORT_POSE = 0
+ };
+
+ enum
+ {
+ PORTID_INPUT_TARGETPOS = 0,
+ PORTID_INPUT_TARGETFACINGDIR = 1,
+ PORTID_OUTPUT_POSE = 0
+ };
+
+ class EMFX_API UniqueData
+ : public AnimGraphNodeData
+ {
+ EMFX_ANIMGRAPHOBJECTDATA_IMPLEMENT_LOADSAVE
+ public:
+ AZ_CLASS_ALLOCATOR_DECL
+
+ UniqueData(AnimGraphNode* node, AnimGraphInstance* animGraphInstance)
+ : AnimGraphNodeData(node, animGraphInstance)
+ {
+ }
+
+ ~UniqueData()
+ {
+ delete m_data;
+ delete m_instance;
+ }
+
+ void Update() override;
+
+ public:
+ MotionMatching::MotionMatchingInstance* m_instance = nullptr;
+ MotionMatching::MotionMatchingData* m_data = nullptr;
+ };
+
+ BlendTreeMotionMatchNode();
+ ~BlendTreeMotionMatchNode();
+
+ bool InitAfterLoading(AnimGraph* animGraph) override;
+
+ bool GetSupportsVisualization() const override { return true; }
+ bool GetHasOutputPose() const override { return true; }
+ bool GetSupportsDisable() const override { return true; }
+ AZ::Color GetVisualColor() const override { return AZ::Colors::Green; }
+ AnimGraphPose* GetMainOutputPose(AnimGraphInstance* animGraphInstance) const override { return GetOutputPose(animGraphInstance, OUTPUTPORT_POSE)->GetValue(); }
+
+ const char* GetPaletteName() const override;
+ AnimGraphObject::ECategory GetPaletteCategory() const override;
+
+ AnimGraphObjectData* CreateUniqueData(AnimGraphInstance* animGraphInstance) override { return aznew UniqueData(this, animGraphInstance); }
+
+ static void Reflect(AZ::ReflectContext* context);
+
+ private:
+ void Output(AnimGraphInstance* animGraphInstance) override;
+ void Update(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) override;
+ void PostUpdate(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) override;
+
+ FeatureSchema m_featureSchema;
+ AZStd::vector m_motionIds;
+
+ float m_pathRadius = 1.0f;
+ float m_pathSpeed = 1.0f;
+ float m_lowestCostSearchFrequency = 5.0f;
+ AZ::u32 m_sampleRate = 30;
+ AZ::u32 m_maxKdTreeDepth = 15;
+ AZ::u32 m_minFramesPerKdTreeNode = 1000;
+ TrajectoryQuery::EMode m_trajectoryQueryMode = TrajectoryQuery::MODE_TARGETDRIVEN;
+ bool m_mirror = false;
+
+ AZ::Debug::Timer m_timer;
+ float m_updateTimeInMs = 0.0f;
+ float m_postUpdateTimeInMs = 0.0f;
+ float m_outputTimeInMs = 0.0f;
+
+#ifdef IMGUI_ENABLED
+ ImGuiMonitor m_imguiMonitor;
+#endif
+ };
+} // namespace EMotionFX::MotionMatching
diff --git a/Gems/MotionMatching/Code/Source/EventData.cpp b/Gems/MotionMatching/Code/Source/EventData.cpp
new file mode 100644
index 0000000000..32c05ee58b
--- /dev/null
+++ b/Gems/MotionMatching/Code/Source/EventData.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include
+#include
+#include
+
+#include
+#include
+
+namespace EMotionFX::MotionMatching
+{
+ AZ_CLASS_ALLOCATOR_IMPL(DiscardFrameEventData, MotionEventAllocator, 0)
+
+ bool DiscardFrameEventData::Equal([[maybe_unused]]const EventData& rhs, [[maybe_unused]] bool ignoreEmptyFields) const
+ {
+ return true;
+ }
+
+ void DiscardFrameEventData::Reflect(AZ::ReflectContext* context)
+ {
+ AZ::SerializeContext* serializeContext = azrtti_cast(context);
+ if (!serializeContext)
+ {
+ return;
+ }
+
+ serializeContext->Class()
+ ->Version(1)
+ ;
+
+ AZ::EditContext* editContext = serializeContext->GetEditContext();
+ if (!editContext)
+ {
+ return;
+ }
+
+ editContext->Class("[Motion Matching] Discard Frame", "Event used for discarding ranges of the animation..")
+ ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
+ ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
+ ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
+ ->Attribute(AZ_CRC_CE("Creatable"), true)
+ ;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ AZ_CLASS_ALLOCATOR_IMPL(TagEventData, MotionEventAllocator, 0)
+
+ bool TagEventData::Equal(const EventData& rhs, [[maybe_unused]] bool ignoreEmptyFields) const
+ {
+ const TagEventData* other = azdynamic_cast(&rhs);
+ if (other)
+ {
+ return AZ::StringFunc::Equal(m_tag.c_str(), other->m_tag.c_str(), /*caseSensitive=*/false);
+ }
+ return false;
+ }
+
+ void TagEventData::Reflect(AZ::ReflectContext* context)
+ {
+ AZ::SerializeContext* serializeContext = azrtti_cast(context);
+ if (!serializeContext)
+ {
+ return;
+ }
+
+ serializeContext->Class()
+ ->Version(1)
+ ->Field("tag", &TagEventData::m_tag)
+ ;
+
+ AZ::EditContext* editContext = serializeContext->GetEditContext();
+ if (!editContext)
+ {
+ return;
+ }
+
+ editContext->Class("[Motion Matching] Tag", "")
+ ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
+ ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
+ ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
+ ->Attribute(AZ_CRC_CE("Creatable"), true)
+ ->DataElement(AZ::Edit::UIHandlers::Default, &TagEventData::m_tag, "Tag", "The tag that should be active.")
+ ;
+ }
+} // namespace EMotionFX::MotionMatching
diff --git a/Gems/MotionMatching/Code/Source/EventData.h b/Gems/MotionMatching/Code/Source/EventData.h
new file mode 100644
index 0000000000..8b80499b78
--- /dev/null
+++ b/Gems/MotionMatching/Code/Source/EventData.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include
+
+namespace AZ
+{
+ class ReflectContext;
+}
+
+namespace EMotionFX::MotionMatching
+{
+ class EMFX_API DiscardFrameEventData
+ : public EventData
+ {
+ public:
+ AZ_RTTI(DiscardFrameEventData, "{25499823-E611-4958-85B7-476BC1918744}", EventData);
+ AZ_CLASS_ALLOCATOR_DECL
+
+ DiscardFrameEventData() = default;
+ ~DiscardFrameEventData() override = default;
+
+ static void Reflect(AZ::ReflectContext* context);
+
+ bool Equal(const EventData& rhs, bool ignoreEmptyFields = false) const override;
+
+ private:
+ AZStd::string m_tag;
+ };
+
+ class EMFX_API TagEventData
+ : public EventData
+ {
+ public:
+ AZ_RTTI(TagEventData, "{FEFEA2C7-CD68-43B2-94D6-85559E29EABF}", EventData);
+ AZ_CLASS_ALLOCATOR_DECL
+
+ TagEventData() = default;
+ ~TagEventData() override = default;
+
+ static void Reflect(AZ::ReflectContext* context);
+
+ bool Equal(const EventData& rhs, bool ignoreEmptyFields = false) const override;
+
+ private:
+ AZStd::string m_tag;
+ };
+} // namespace EMotionFX::MotionMatching
diff --git a/Gems/MotionMatching/Code/Source/Feature.cpp b/Gems/MotionMatching/Code/Source/Feature.cpp
new file mode 100644
index 0000000000..0d135d6ed8
--- /dev/null
+++ b/Gems/MotionMatching/Code/Source/Feature.cpp
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+
+namespace EMotionFX::MotionMatching
+{
+ AZ_CLASS_ALLOCATOR_IMPL(Feature, MotionMatchAllocator, 0)
+
+ bool Feature::Init(const InitSettings& settings)
+ {
+ const Actor* actor = settings.m_actorInstance->GetActor();
+ const Skeleton* skeleton = actor->GetSkeleton();
+
+ const Node* joint = skeleton->FindNodeByNameNoCase(m_jointName.c_str());
+ m_jointIndex = joint ? joint->GetNodeIndex() : InvalidIndex;
+ if (m_jointIndex == InvalidIndex)
+ {
+ AZ_Error("MotionMatching", false, "Feature::Init(): Cannot find index for joint named '%s'.", m_jointName.c_str());
+ return false;
+ }
+
+ const Node* relativeToJoint = skeleton->FindNodeByNameNoCase(m_relativeToJointName.c_str());
+ m_relativeToNodeIndex = relativeToJoint ? relativeToJoint->GetNodeIndex() : InvalidIndex;
+ if (m_relativeToNodeIndex == InvalidIndex)
+ {
+ AZ_Error("MotionMatching", false, "Feature::Init(): Cannot find index for joint named '%s'.", m_relativeToJointName.c_str());
+ return false;
+ }
+
+ // Set a default feature name in case it did not get set manually.
+ if (m_name.empty())
+ {
+ AZStd::string featureTypeName = this->RTTI_GetTypeName();
+ AzFramework::StringFunc::Replace(featureTypeName, "Feature", "");
+ m_name = AZStd::string::format("%s (%s)", featureTypeName.c_str(), m_jointName.c_str());
+ }
+ return true;
+ }
+
+ void Feature::SetDebugDrawColor(const AZ::Color& color)
+ {
+ m_debugColor = color;
+ }
+
+ const AZ::Color& Feature::GetDebugDrawColor() const
+ {
+ return m_debugColor;
+ }
+
+ void Feature::SetDebugDrawEnabled(bool enabled)
+ {
+ m_debugDrawEnabled = enabled;
+ }
+
+ bool Feature::GetDebugDrawEnabled() const
+ {
+ return m_debugDrawEnabled;
+ }
+
+ float Feature::CalculateFrameCost([[maybe_unused]] size_t frameIndex, [[maybe_unused]] const FrameCostContext& context) const
+ {
+ AZ_Assert(false, "Feature::CalculateFrameCost(): Not implemented for the given feature.");
+ return 0.0f;
+ }
+
+ void Feature::SetRelativeToNodeIndex(size_t nodeIndex)
+ {
+ m_relativeToNodeIndex = nodeIndex;
+ }
+
+ void Feature::CalculateVelocity(size_t jointIndex, size_t relativeToJointIndex, MotionInstance* motionInstance, AZ::Vector3& outVelocity)
+ {
+ const float originalTime = motionInstance->GetCurrentTime();
+
+ // Prepare for sampling.
+ ActorInstance* actorInstance = motionInstance->GetActorInstance();
+ AnimGraphPosePool& posePool = GetEMotionFX().GetThreadData(actorInstance->GetThreadIndex())->GetPosePool();
+ AnimGraphPose* prevPose = posePool.RequestPose(actorInstance);
+ AnimGraphPose* currentPose = posePool.RequestPose(actorInstance);
+ Pose* bindPose = actorInstance->GetTransformData()->GetBindPose();
+
+ const size_t numSamples = 3;
+ const float timeRange = 0.05f; // secs
+ const float halfTimeRange = timeRange * 0.5f;
+ const float startTime = originalTime - halfTimeRange;
+ const float frameDelta = timeRange / numSamples;
+
+ AZ::Vector3 accumulatedVelocity = AZ::Vector3::CreateZero();
+
+ for (size_t sampleIndex = 0; sampleIndex < numSamples + 1; ++sampleIndex)
+ {
+ float sampleTime = startTime + sampleIndex * frameDelta;
+ if (sampleTime < 0.0f)
+ {
+ sampleTime = 0.0f;
+ }
+ if (sampleTime >= motionInstance->GetMotion()->GetDuration())
+ {
+ sampleTime = motionInstance->GetMotion()->GetDuration();
+ }
+
+ if (sampleIndex == 0)
+ {
+ motionInstance->SetCurrentTime(sampleTime);
+ motionInstance->GetMotion()->Update(bindPose, &prevPose->GetPose(), motionInstance);
+ continue;
+ }
+
+ motionInstance->SetCurrentTime(sampleTime);
+ motionInstance->GetMotion()->Update(bindPose, ¤tPose->GetPose(), motionInstance);
+
+ const Transform inverseJointWorldTransform = currentPose->GetPose().GetWorldSpaceTransform(relativeToJointIndex).Inversed();
+
+ // Calculate the velocity.
+ const AZ::Vector3 prevPosition = prevPose->GetPose().GetWorldSpaceTransform(jointIndex).m_position;
+ const AZ::Vector3 currentPosition = currentPose->GetPose().GetWorldSpaceTransform(jointIndex).m_position;
+ const AZ::Vector3 velocity = CalculateLinearVelocity(prevPosition, currentPosition, frameDelta);
+
+ accumulatedVelocity += inverseJointWorldTransform.TransformVector(velocity);
+
+ *prevPose = *currentPose;
+ }
+
+ outVelocity = accumulatedVelocity / aznumeric_cast(numSamples);
+
+ motionInstance->SetCurrentTime(originalTime); // set back to what it was
+
+ posePool.FreePose(prevPose);
+ posePool.FreePose(currentPose);
+ }
+
+ void Feature::CalculateVelocity(const ActorInstance* actorInstance, size_t jointIndex, size_t relativeToJointIndex, const Frame& frame, AZ::Vector3& outVelocity)
+ {
+ AnimGraphPosePool& posePool = GetEMotionFX().GetThreadData(actorInstance->GetThreadIndex())->GetPosePool();
+ AnimGraphPose* prevPose = posePool.RequestPose(actorInstance);
+ AnimGraphPose* currentPose = posePool.RequestPose(actorInstance);
+
+ const size_t numSamples = 3;
+ const float timeRange = 0.05f; // secs
+ const float halfTimeRange = timeRange * 0.5f;
+ const float frameDelta = timeRange / numSamples;
+
+ AZ::Vector3 accumulatedVelocity = AZ::Vector3::CreateZero();
+
+ for (size_t sampleIndex = 0; sampleIndex < numSamples + 1; ++sampleIndex)
+ {
+ const float sampleTimeOffset = (-halfTimeRange) + sampleIndex * frameDelta;
+
+ if (sampleIndex == 0)
+ {
+ frame.SamplePose(&prevPose->GetPose(), sampleTimeOffset);
+ continue;
+ }
+
+ frame.SamplePose(¤tPose->GetPose(), sampleTimeOffset);
+ const Transform inverseJointWorldTransform = currentPose->GetPose().GetWorldSpaceTransform(relativeToJointIndex).Inversed();
+
+ // Calculate the velocity.
+ const AZ::Vector3 prevPosition = prevPose->GetPose().GetWorldSpaceTransform(jointIndex).m_position;
+ const AZ::Vector3 currentPosition = currentPose->GetPose().GetWorldSpaceTransform(jointIndex).m_position;
+ const AZ::Vector3 velocity = CalculateLinearVelocity(prevPosition, currentPosition, frameDelta);
+
+ accumulatedVelocity += inverseJointWorldTransform.TransformVector(velocity);
+
+ *prevPose = *currentPose;
+ }
+
+ outVelocity = accumulatedVelocity / aznumeric_cast(numSamples);
+
+ posePool.FreePose(prevPose);
+ posePool.FreePose(currentPose);
+ }
+
+ float Feature::GetNormalizedDirectionDifference(const AZ::Vector2& directionA, const AZ::Vector2& directionB) const
+ {
+ const float dotProduct = directionA.GetNormalized().Dot(directionB.GetNormalized());
+ const float normalizedDirectionDifference = (2.0f - (1.0f + dotProduct)) * 0.5f;
+ return AZ::GetAbs(normalizedDirectionDifference);
+ }
+
+ float Feature::GetNormalizedDirectionDifference(const AZ::Vector3& directionA, const AZ::Vector3& directionB) const
+ {
+ const float dotProduct = directionA.GetNormalized().Dot(directionB.GetNormalized());
+ const float normalizedDirectionDifference = (2.0f - (1.0f + dotProduct)) * 0.5f;
+ return AZ::GetAbs(normalizedDirectionDifference);
+ }
+
+ float Feature::CalcResidual(float value) const
+ {
+ if (m_residualType == ResidualType::Squared)
+ {
+ return value * value;
+ }
+
+ return AZ::Abs(value);
+ }
+
+ float Feature::CalcResidual(const AZ::Vector3& a, const AZ::Vector3& b) const
+ {
+ const float euclideanDistance = (b - a).GetLength();
+ return CalcResidual(euclideanDistance);
+ }
+
+ AZ::Crc32 Feature::GetCostFactorVisibility() const
+ {
+ return AZ::Edit::PropertyVisibility::Show;
+ }
+
+ void Feature::Reflect(AZ::ReflectContext* context)
+ {
+ AZ::SerializeContext* serializeContext = azrtti_cast(context);
+ if (!serializeContext)
+ {
+ return;
+ }
+
+ serializeContext->Class()
+ ->Version(2)
+ ->Field("id", &Feature::m_id)
+ ->Field("name", &Feature::m_name)
+ ->Field("jointName", &Feature::m_jointName)
+ ->Field("relativeToJointName", &Feature::m_relativeToJointName)
+ ->Field("debugDraw", &Feature::m_debugDrawEnabled)
+ ->Field("debugColor", &Feature::m_debugColor)
+ ->Field("costFactor", &Feature::m_costFactor)
+ ->Field("residualType", &Feature::m_residualType)
+ ;
+
+ AZ::EditContext* editContext = serializeContext->GetEditContext();
+ if (!editContext)
+ {
+ return;
+ }
+
+ editContext->Class("Feature", "Base class for a feature")
+ ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
+ ->Attribute(AZ::Edit::Attributes::AutoExpand, "")
+ ->DataElement(AZ::Edit::UIHandlers::Default, &Feature::m_name, "Name", "Custom name of the feature used for identification and debug visualizations.")
+ ->DataElement(AZ_CRC_CE("ActorNode"), &Feature::m_jointName, "Joint", "The joint to extract the data from.")
+ ->DataElement(AZ_CRC_CE("ActorNode"), &Feature::m_relativeToJointName, "Relative To Joint", "When extracting feature data, convert it to relative-space to the given joint.")
+ ->DataElement(AZ::Edit::UIHandlers::Default, &Feature::m_debugDrawEnabled, "Debug Draw", "Are debug visualizations enabled for this feature?")
+ ->DataElement(AZ::Edit::UIHandlers::Default, &Feature::m_debugColor, "Debug Draw Color", "Color used for debug visualizations to identify the feature.")
+ ->DataElement(AZ::Edit::UIHandlers::SpinBox, &Feature::m_costFactor, "Cost Factor", "The cost factor for the feature is multiplied with the actual and can be used to change a feature's influence in the motion matching search.")
+ ->Attribute(AZ::Edit::Attributes::Min, 0.0f)
+ ->Attribute(AZ::Edit::Attributes::Max, 100.0f)
+ ->Attribute(AZ::Edit::Attributes::Step, 0.1f)
+ ->Attribute(AZ::Edit::Attributes::Visibility, &Feature::GetCostFactorVisibility)
+ ->DataElement(AZ::Edit::UIHandlers::ComboBox, &Feature::m_residualType, "Residual", "Use 'Squared' in case minimal differences should be ignored and larger differences should overweight others. Use 'Absolute' for linear differences and don't want the mentioned effect.")
+ ->EnumAttribute(ResidualType::Absolute, "Absolute")
+ ->EnumAttribute(ResidualType::Squared, "Squared")
+ ;
+ }
+} // namespace EMotionFX::MotionMatching
diff --git a/Gems/MotionMatching/Code/Source/Feature.h b/Gems/MotionMatching/Code/Source/Feature.h
new file mode 100644
index 0000000000..9a0fe9fa8c
--- /dev/null
+++ b/Gems/MotionMatching/Code/Source/Feature.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+
+#include
+
+namespace EMotionFX
+{
+ class ActorInstance;
+ class MotionInstance;
+ class Pose;
+ class Motion;
+};
+
+namespace EMotionFX::MotionMatching
+{
+ class Frame;
+ class FrameDatabase;
+ class MotionMatchingInstance;
+ class TrajectoryQuery;
+
+ class EMFX_API Feature
+ {
+ public:
+ AZ_RTTI(Feature, "{DE9CBC48-9176-4DF1-8306-4B1E621F0E76}")
+ AZ_CLASS_ALLOCATOR_DECL
+
+ Feature() = default;
+ virtual ~Feature() = default;
+
+ ////////////////////////////////////////////////////////////////////////
+ // Initialization
+ struct EMFX_API InitSettings
+ {
+ ActorInstance* m_actorInstance = nullptr;
+ FeatureMatrix::Index m_featureColumnStartOffset = 0;
+ };
+ virtual bool Init(const InitSettings& settings);
+
+ ////////////////////////////////////////////////////////////////////////
+ // Feature extraction
+ struct EMFX_API ExtractFeatureContext
+ {
+ ExtractFeatureContext(FeatureMatrix& featureMatrix)
+ : m_featureMatrix(featureMatrix)
+ {
+ }
+
+ FrameDatabase* m_frameDatabase = nullptr;
+ FeatureMatrix& m_featureMatrix;
+
+ size_t m_frameIndex = InvalidIndex;
+ const Pose* m_framePose = nullptr; //! Pre-sampled pose for the given frame.
+
+ ActorInstance* m_actorInstance = nullptr;
+ };
+ virtual void ExtractFeatureValues(const ExtractFeatureContext& context) = 0;
+
+ ////////////////////////////////////////////////////////////////////////
+ // Feature cost
+ struct EMFX_API FrameCostContext
+ {
+ FrameCostContext(const FeatureMatrix& featureMatrix, const Pose& currentPose)
+ : m_featureMatrix(featureMatrix)
+ , m_currentPose(currentPose)
+ {
+ }
+
+ const FeatureMatrix& m_featureMatrix;
+ const ActorInstance* m_actorInstance = nullptr;
+ const Pose& m_currentPose; //! Current actor instance pose.
+ const TrajectoryQuery* m_trajectoryQuery;
+ };
+ virtual float CalculateFrameCost(size_t frameIndex, const FrameCostContext& context) const;
+
+ //! Specifies how the feature value differences (residuals), between the input query values
+ //! and the frames in the motion database that sum up the feature cost, are calculated.
+ enum ResidualType
+ {
+ Absolute,
+ Squared
+ };
+
+ void SetCostFactor(float costFactor) { m_costFactor = costFactor; }
+ float GetCostFactor() const { return m_costFactor; }
+
+ virtual void FillQueryFeatureValues([[maybe_unused]] size_t startIndex,
+ [[maybe_unused]] AZStd::vector& queryFeatureValues,
+ [[maybe_unused]] const FrameCostContext& context) {}
+
+ virtual void DebugDraw([[maybe_unused]] AzFramework::DebugDisplayRequests& debugDisplay,
+ [[maybe_unused]] MotionMatchingInstance* instance,
+ [[maybe_unused]] size_t frameIndex) {}
+
+ void SetDebugDrawColor(const AZ::Color& color);
+ const AZ::Color& GetDebugDrawColor() const;
+
+ void SetDebugDrawEnabled(bool enabled);
+ bool GetDebugDrawEnabled() const;
+
+ void SetJointName(const AZStd::string& jointName) { m_jointName = jointName; }
+ const AZStd::string& GetJointName() const { return m_jointName; }
+
+ void SetRelativeToJointName(const AZStd::string& jointName) { m_relativeToJointName = jointName; }
+ const AZStd::string& GetRelativeToJointName() const { return m_relativeToJointName; }
+
+ void SetName(const AZStd::string& name) { m_name = name; }
+ const AZStd::string& GetName() const { return m_name; }
+
+ // Column offset for the first value for the given feature inside the feature matrix.
+ virtual size_t GetNumDimensions() const = 0;
+ virtual AZStd::string GetDimensionName([[maybe_unused]] size_t index) const { return "Unknown"; }
+ FeatureMatrix::Index GetColumnOffset() const { return m_featureColumnOffset; }
+ void SetColumnOffset(FeatureMatrix::Index offset) { m_featureColumnOffset = offset; }
+
+ const AZ::TypeId& GetId() const { return m_id; }
+ size_t GetRelativeToNodeIndex() const { return m_relativeToNodeIndex; }
+ void SetRelativeToNodeIndex(size_t nodeIndex);
+
+ static void Reflect(AZ::ReflectContext* context);
+ static void CalculateVelocity(size_t jointIndex, size_t relativeToJointIndex, MotionInstance* motionInstance, AZ::Vector3& outVelocity);
+ static void CalculateVelocity(const ActorInstance* actorInstance, size_t jointIndex, size_t relativeToJointIndex, const Frame& frame, AZ::Vector3& outVelocity);
+
+ protected:
+ /**
+ * Calculate a normalized direction vector difference between the two given vectors.
+ * A dot product of the two vectors is taken and the result in range [-1, 1] is scaled to [0, 1].
+ * @result Normalized, absolute difference between the vectors.
+ * Angle difference dot result cost
+ * 0.0 degrees 1.0 0.0
+ * 90.0 degrees 0.0 0.5
+ * 180.0 degrees -1.0 1.0
+ * 270.0 degrees 0.0 0.5
+ **/
+ float GetNormalizedDirectionDifference(const AZ::Vector2& directionA, const AZ::Vector2& directionB) const;
+ float GetNormalizedDirectionDifference(const AZ::Vector3& directionA, const AZ::Vector3& directionB) const;
+
+ float CalcResidual(float value) const;
+ float CalcResidual(const AZ::Vector3& a, const AZ::Vector3& b) const;
+
+ virtual AZ::Crc32 GetCostFactorVisibility() const;
+
+ // Shared and reflected data.
+ AZ::TypeId m_id = AZ::TypeId::CreateRandom(); //< The feature identification number. Use this instead of the RTTI class ID so that we can have multiple of the same type.
+ AZStd::string m_name; //< Display name used for feature identification and debug visualizations.
+ AZStd::string m_jointName; //< Joint name to extract the data from.
+ AZStd::string m_relativeToJointName; //< When extracting feature data, convert it to relative-space to the given joint.
+ AZ::Color m_debugColor = AZ::Colors::Green; //< Color used for debug visualizations to identify the feature.
+ bool m_debugDrawEnabled = false; //< Are debug visualizations enabled for this feature?
+ float m_costFactor = 1.0f; //< The cost factor for the feature is multiplied with the actual and can be used to change a feature's influence in the motion matching search.
+ ResidualType m_residualType = ResidualType::Squared; //< How do we calculate the differences (residuals) between the input query values and the frames in the motion database that sum up the feature cost.
+
+ // Instance data (depends on the feature schema or actor instance).
+ FeatureMatrix::Index m_featureColumnOffset; //< Float/Value offset, starting column for where the feature should be places at.
+ size_t m_relativeToNodeIndex = InvalidIndex;
+ size_t m_jointIndex = InvalidIndex;
+ };
+} // namespace EMotionFX::MotionMatching
diff --git a/Gems/MotionMatching/Code/Source/FeatureMatrix.cpp b/Gems/MotionMatching/Code/Source/FeatureMatrix.cpp
new file mode 100644
index 0000000000..7da9e146d9
--- /dev/null
+++ b/Gems/MotionMatching/Code/Source/FeatureMatrix.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include
+#include
+
+#include
+#include
+#include
+
+namespace EMotionFX::MotionMatching
+{
+ AZ_CLASS_ALLOCATOR_IMPL(FeatureMatrix, MotionMatchAllocator, 0)
+
+ void FeatureMatrix::Clear()
+ {
+ resize(0, 0);
+ }
+
+ void FeatureMatrix::SaveAsCsv(const AZStd::string& filename, const AZStd::vector& columnNames)
+ {
+ std::ofstream file(filename.c_str());
+
+ // Save column names in the first row
+ if (!columnNames.empty())
+ {
+ for (size_t i = 0; i < columnNames.size(); ++i)
+ {
+ if (i != 0)
+ {
+ file << ",";
+ }
+
+ file << columnNames[i].c_str();
+ }
+ file << "\n";
+ }
+
+ // Save coefficients
+#ifdef O3DE_USE_EIGEN
+ // Force specify precision, else wise values close to 0.0 get rounded to 0.0.
+ const static Eigen::IOFormat csvFormat(/*Eigen::StreamPrecision|FullPrecision*/8, Eigen::DontAlignCols, ", ", "\n");
+ file << format(csvFormat);
+#endif
+ }
+
+ void FeatureMatrix::SaveAsCsv(const AZStd::string& filename, const FeatureSchema* featureSchema)
+ {
+ AZStd::vector columnNames;
+
+ for (Feature* feature: featureSchema->GetFeatures())
+ {
+ const size_t numDimensions = feature->GetNumDimensions();
+ for (size_t dimension = 0; dimension < numDimensions; ++dimension)
+ {
+ columnNames.push_back(feature->GetDimensionName(dimension));
+ }
+ }
+
+ SaveAsCsv(filename, columnNames);
+ }
+
+ AZ::Vector2 FeatureMatrix::GetVector2(Index row, Index startColumn) const
+ {
+ return AZ::Vector2(
+ coeff(row, startColumn + 0),
+ coeff(row, startColumn + 1));
+ }
+
+ void FeatureMatrix::SetVector2(Index row, Index startColumn, const AZ::Vector2& value)
+ {
+ operator()(row, startColumn + 0) = value.GetX();
+ operator()(row, startColumn + 1) = value.GetY();
+ }
+
+ AZ::Vector3 FeatureMatrix::GetVector3(Index row, Index startColumn) const
+ {
+ return AZ::Vector3(
+ coeff(row, startColumn + 0),
+ coeff(row, startColumn + 1),
+ coeff(row, startColumn + 2));
+ }
+
+ void FeatureMatrix::SetVector3(Index row, Index startColumn, const AZ::Vector3& value)
+ {
+ operator()(row, startColumn + 0) = value.GetX();
+ operator()(row, startColumn + 1) = value.GetY();
+ operator()(row, startColumn + 2) = value.GetZ();
+ }
+
+ size_t FeatureMatrix::CalcMemoryUsageInBytes() const
+ {
+ const size_t bytesPerValue = sizeof(O3DE_MM_FLOATTYPE);
+ const size_t numValues = size();
+ return numValues * bytesPerValue;
+ }
+} // namespace EMotionFX::MotionMatching
diff --git a/Gems/MotionMatching/Code/Source/FeatureMatrix.h b/Gems/MotionMatching/Code/Source/FeatureMatrix.h
new file mode 100644
index 0000000000..1cf42933ce
--- /dev/null
+++ b/Gems/MotionMatching/Code/Source/FeatureMatrix.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+//#define O3DE_USE_EIGEN
+#define O3DE_MM_FLOATTYPE float
+
+#ifdef O3DE_USE_EIGEN
+#pragma warning (push, 1)
+#pragma warning (disable:4834) // C4834: discarding return value of function with 'nodiscard' attribute
+#pragma warning (disable:5031) // #pragma warning(pop): likely mismatch, popping warning state pushed in different file
+#pragma warning (disable:4702) // warning C4702: unreachable code
+#pragma warning (disable:4723) // warning C4723: potential divide by 0
+#include "../../3rdParty/eigen-3.3.9/Eigen/Dense"
+#pragma warning (pop)
+#endif
+
+namespace EMotionFX::MotionMatching
+{
+ class FeatureSchema;
+
+#ifdef O3DE_USE_EIGEN
+ // Features are stored in columns, each row represents a frame
+ // RowMajor: Store row components next to each other in memory for cache-optimized feature access for a given frame.
+ using FeatureMatrixType = Eigen::Matrix;
+#else
+ /**
+ * Small wrapper for a 2D matrix similar to the Eigen::Matrix.
+ */
+ class FeatureMatrixType
+ {
+ public:
+ size_t size() const
+ {
+ return m_data.size();
+ }
+
+ size_t rows() const
+ {
+ return m_rowCount;
+ }
+
+ size_t cols() const
+ {
+ return m_columnCount;
+ }
+
+ void resize(size_t rowCount, size_t columnCount)
+ {
+ m_rowCount = rowCount;
+ m_columnCount = columnCount;
+ m_data.resize(m_rowCount * m_columnCount);
+ }
+
+ float& operator()(size_t row, size_t column)
+ {
+ return m_data[row * m_columnCount + column];
+ }
+
+ const float& operator()(size_t row, size_t column) const
+ {
+ return m_data[row * m_columnCount + column];
+ }
+
+ float coeff(size_t row, size_t column) const
+ {
+ return m_data[row * m_columnCount + column];
+ }
+
+ private:
+ AZStd::vector m_data;
+ size_t m_rowCount = 0;
+ size_t m_columnCount = 0;
+ };
+#endif
+
+ class FeatureMatrix
+ : public FeatureMatrixType
+ {
+ public:
+ AZ_RTTI(FeatureMatrix, "{E063C9CB-7147-4776-A6E0-98584DD93FEF}");
+ AZ_CLASS_ALLOCATOR_DECL
+
+#ifdef O3DE_USE_EIGEN
+ using Index = Eigen::Index;
+#else
+ using Index = size_t;
+#endif
+
+ virtual ~FeatureMatrix() = default;
+
+ void Clear();
+
+ void SaveAsCsv(const AZStd::string& filename, const AZStd::vector& columnNames = {});
+ void SaveAsCsv(const AZStd::string& filename, const FeatureSchema* featureSchema);
+
+ size_t CalcMemoryUsageInBytes() const;
+
+ AZ::Vector2 GetVector2(Index row, Index startColumn) const;
+ void SetVector2(Index row, Index startColumn, const AZ::Vector2& value);
+
+ AZ::Vector3 GetVector3(Index row, Index startColumn) const;
+ void SetVector3(Index row, Index startColumn, const AZ::Vector3& value);
+ };
+} // namespace EMotionFX::MotionMatching
diff --git a/Gems/MotionMatching/Code/Source/FeaturePosition.cpp b/Gems/MotionMatching/Code/Source/FeaturePosition.cpp
new file mode 100644
index 0000000000..b81ec081f7
--- /dev/null
+++ b/Gems/MotionMatching/Code/Source/FeaturePosition.cpp
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+
+namespace EMotionFX::MotionMatching
+{
+ AZ_CLASS_ALLOCATOR_IMPL(FeaturePosition, MotionMatchAllocator, 0)
+
+ void FeaturePosition::FillQueryFeatureValues(size_t startIndex, AZStd::vector& queryFeatureValues, const FrameCostContext& context)
+ {
+ const Transform invRootTransform = context.m_currentPose.GetWorldSpaceTransform(m_relativeToNodeIndex).Inversed();
+ const AZ::Vector3 worldInputPosition = context.m_currentPose.GetWorldSpaceTransform(m_jointIndex).m_position;
+ const AZ::Vector3 relativeInputPosition = invRootTransform.TransformPoint(worldInputPosition);
+ queryFeatureValues[startIndex + 0] = relativeInputPosition.GetX();
+ queryFeatureValues[startIndex + 1] = relativeInputPosition.GetY();
+ queryFeatureValues[startIndex + 2] = relativeInputPosition.GetZ();
+ }
+
+ void FeaturePosition::ExtractFeatureValues(const ExtractFeatureContext& context)
+ {
+ const Transform invRootTransform = context.m_framePose->GetWorldSpaceTransform(m_relativeToNodeIndex).Inversed();
+ const AZ::Vector3 nodeWorldPosition = context.m_framePose->GetWorldSpaceTransform(m_jointIndex).m_position;
+ const AZ::Vector3 position = invRootTransform.TransformPoint(nodeWorldPosition);
+ SetFeatureData(context.m_featureMatrix, context.m_frameIndex, position);
+ }
+
+ void FeaturePosition::DebugDraw(AzFramework::DebugDisplayRequests& debugDisplay,
+ MotionMatchingInstance* instance,
+ size_t frameIndex)
+ {
+ const MotionMatchingData* data = instance->GetData();
+ const ActorInstance* actorInstance = instance->GetActorInstance();
+ const Pose* pose = actorInstance->GetTransformData()->GetCurrentPose();
+ const Transform jointModelTM = pose->GetModelSpaceTransform(m_jointIndex);
+ const Transform relativeToWorldTM = pose->GetWorldSpaceTransform(m_relativeToNodeIndex);
+
+ const AZ::Vector3 position = GetFeatureData(data->GetFeatureMatrix(), frameIndex);
+ const AZ::Vector3 transformedPos = relativeToWorldTM.TransformPoint(position);
+
+ constexpr float markerSize = 0.03f;
+ debugDisplay.DepthTestOff();
+ debugDisplay.SetColor(m_debugColor);
+ debugDisplay.DrawBall(transformedPos, markerSize, /*drawShaded=*/false);
+ }
+
+ float FeaturePosition::CalculateFrameCost(size_t frameIndex, const FrameCostContext& context) const
+ {
+ const Transform invRootTransform = context.m_currentPose.GetWorldSpaceTransform(m_relativeToNodeIndex).Inversed();
+ const AZ::Vector3 worldInputPosition = context.m_currentPose.GetWorldSpaceTransform(m_jointIndex).m_position;
+ const AZ::Vector3 relativeInputPosition = invRootTransform.TransformPoint(worldInputPosition);
+ const AZ::Vector3 framePosition = GetFeatureData(context.m_featureMatrix, frameIndex); // This is already relative to the root node
+ return CalcResidual(relativeInputPosition, framePosition);
+ }
+
+ void FeaturePosition::Reflect(AZ::ReflectContext* context)
+ {
+ AZ::SerializeContext* serializeContext = azrtti_cast(context);
+ if (!serializeContext)
+ {
+ return;
+ }
+
+ serializeContext->Class()
+ ->Version(1);
+
+ AZ::EditContext* editContext = serializeContext->GetEditContext();
+ if (!editContext)
+ {
+ return;
+ }
+
+ editContext->Class("FeaturePosition", "Matches joint positions.")
+ ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
+ ->Attribute(AZ::Edit::Attributes::AutoExpand, "")
+ ;
+ }
+
+ size_t FeaturePosition::GetNumDimensions() const
+ {
+ return 3;
+ }
+
+ AZStd::string FeaturePosition::GetDimensionName(size_t index) const
+ {
+ AZStd::string result = m_jointName;
+ result += '.';
+
+ switch (index)
+ {
+ case 0: { result += "PosX"; break; }
+ case 1: { result += "PosY"; break; }
+ case 2: { result += "PosZ"; break; }
+ default: { result += Feature::GetDimensionName(index); }
+ }
+
+ return result;
+ }
+
+ AZ::Vector3 FeaturePosition::GetFeatureData(const FeatureMatrix& featureMatrix, size_t frameIndex) const
+ {
+ return featureMatrix.GetVector3(frameIndex, m_featureColumnOffset);
+ }
+
+ void FeaturePosition::SetFeatureData(FeatureMatrix& featureMatrix, size_t frameIndex, const AZ::Vector3& position)
+ {
+ featureMatrix.SetVector3(frameIndex, m_featureColumnOffset, position);
+ }
+} // namespace EMotionFX::MotionMatching
diff --git a/Gems/MotionMatching/Code/Source/FeaturePosition.h b/Gems/MotionMatching/Code/Source/FeaturePosition.h
new file mode 100644
index 0000000000..d62dce9a18
--- /dev/null
+++ b/Gems/MotionMatching/Code/Source/FeaturePosition.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+namespace AZ
+{
+ class ReflectContext;
+}
+
+namespace EMotionFX::MotionMatching
+{
+ class FrameDatabase;
+
+ class EMFX_API FeaturePosition
+ : public Feature
+ {
+ public:
+ AZ_RTTI(FeaturePosition, "{3EAA6459-DB59-4EA1-B8B3-C933A83AA77D}", Feature)
+ AZ_CLASS_ALLOCATOR_DECL
+
+ FeaturePosition() = default;
+ ~FeaturePosition() override = default;
+
+ void ExtractFeatureValues(const ExtractFeatureContext& context) override;
+ void DebugDraw(AzFramework::DebugDisplayRequests& debugDisplay,
+ MotionMatchingInstance* instance,
+ size_t frameIndex) override;
+
+ float CalculateFrameCost(size_t frameIndex, const FrameCostContext& context) const override;
+
+ void FillQueryFeatureValues(size_t startIndex, AZStd::vector& queryFeatureValues, const FrameCostContext& context) override;
+
+ static void Reflect(AZ::ReflectContext* context);
+
+ size_t GetNumDimensions() const override;
+ AZStd::string GetDimensionName(size_t index) const override;
+ AZ::Vector3 GetFeatureData(const FeatureMatrix& featureMatrix, size_t frameIndex) const;
+ void SetFeatureData(FeatureMatrix& featureMatrix, size_t frameIndex, const AZ::Vector3& position);
+ };
+} // namespace EMotionFX::MotionMatching
diff --git a/Gems/MotionMatching/Code/Source/FeatureSchema.cpp b/Gems/MotionMatching/Code/Source/FeatureSchema.cpp
new file mode 100644
index 0000000000..1e36a755ee
--- /dev/null
+++ b/Gems/MotionMatching/Code/Source/FeatureSchema.cpp
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include
+#include
+#include
+
+#include
+#include
+
+namespace EMotionFX::MotionMatching
+{
+ AZ_CLASS_ALLOCATOR_IMPL(FeatureSchema, MotionMatchAllocator, 0)
+
+ FeatureSchema::~FeatureSchema()
+ {
+ Clear();
+ }
+
+ Feature* FeatureSchema::GetFeature(size_t index) const
+ {
+ return m_features[index];
+ }
+
+ const AZStd::vector& FeatureSchema::GetFeatures() const
+ {
+ return m_features;
+ }
+
+ void FeatureSchema::AddFeature(Feature* feature)
+ {
+ // Try to see if there is a feature with the same id already.
+ auto iterator = AZStd::find_if(m_featuresById.begin(), m_featuresById.end(), [&feature](const auto& curEntry) -> bool {
+ return (feature->GetId() == curEntry.second->GetId());
+ });
+
+ if (iterator != m_featuresById.end())
+ {
+ AZ_Assert(false, "Cannot add feature. Feature with id '%s' has already been registered.", feature->GetId().data);
+ return;
+ }
+
+ m_featuresById.emplace(feature->GetId(), feature);
+ m_features.emplace_back(feature);
+ }
+
+ void FeatureSchema::Clear()
+ {
+ for (Feature* feature : m_features)
+ {
+ delete feature;
+ }
+ m_featuresById.clear();
+ m_features.clear();
+ }
+
+ size_t FeatureSchema::GetNumFeatures() const
+ {
+ return m_features.size();
+ }
+
+ Feature* FeatureSchema::FindFeatureById(const AZ::TypeId& featureId) const
+ {
+ const auto result = m_featuresById.find(featureId);
+ if (result == m_featuresById.end())
+ {
+ return nullptr;
+ }
+
+ return result->second;
+ }
+
+ Feature* FeatureSchema::CreateFeatureByType(const AZ::TypeId& typeId)
+ {
+ AZ::SerializeContext* context = nullptr;
+ AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationBus::Events::GetSerializeContext);
+ if (!context)
+ {
+ AZ_Error("Motion Matching", false, "Can't get serialize context from component application.");
+ return nullptr;
+ }
+
+ const AZ::SerializeContext::ClassData* classData = context->FindClassData(typeId);
+ if (!classData)
+ {
+ AZ_Warning("Motion Matching", false, "Can't find class data for this type.");
+ return nullptr;
+ }
+
+ Feature* featureObject = reinterpret_cast(classData->m_factory->Create(classData->m_name));
+ return featureObject;
+ }
+
+ void FeatureSchema::Reflect(AZ::ReflectContext* context)
+ {
+ AZ::SerializeContext* serializeContext = azrtti_cast(context);
+ if (!serializeContext)
+ {
+ return;
+ }
+
+ serializeContext->Class()
+ ->Version(1)
+ ->Field("features", &FeatureSchema::m_features);
+
+ AZ::EditContext* editContext = serializeContext->GetEditContext();
+ if (!editContext)
+ {
+ return;
+ }
+
+ editContext->Class("FeatureSchema", "")
+ ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
+ ->DataElement(AZ::Edit::UIHandlers::Default, &FeatureSchema::m_features, "Features", "")
+ ->Attribute(AZ::Edit::Attributes::AutoExpand, "")
+ ;
+ }
+} // namespace EMotionFX::MotionMatching
diff --git a/Gems/MotionMatching/Code/Source/FeatureSchema.h b/Gems/MotionMatching/Code/Source/FeatureSchema.h
new file mode 100644
index 0000000000..d1005ef6dc
--- /dev/null
+++ b/Gems/MotionMatching/Code/Source/FeatureSchema.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include
+#include
+#include
+#include
+
+#include
+
+namespace EMotionFX::MotionMatching
+{
+ //! The set of features involved in the motion matching search.
+ //! The schema represents the order of the features as well as their settings while the feature matrix stores the actual feature data.
+ class EMFX_API FeatureSchema
+ {
+ public:
+ AZ_RTTI(FrameDatabase, "{E34F6BFE-73DB-4DED-AAB9-09FBC5113236}")
+ AZ_CLASS_ALLOCATOR_DECL
+
+ virtual ~FeatureSchema();
+
+ void AddFeature(Feature* feature);
+ void Clear();
+
+ size_t GetNumFeatures() const;
+ Feature* GetFeature(size_t index) const;
+ const AZStd::vector& GetFeatures() const;
+
+ Feature* FindFeatureById(const AZ::TypeId& featureId) const;
+
+ static void Reflect(AZ::ReflectContext* context);
+
+ protected:
+ static Feature* CreateFeatureByType(const AZ::TypeId& typeId);
+
+ AZStd::vector m_features; //< Ordered set of features (Owns the feature objects).
+ AZStd::unordered_map m_featuresById; //< Hash-map for fast access to the features by ID. (Weak ownership)
+ };
+} // namespace EMotionFX::MotionMatching
diff --git a/Gems/MotionMatching/Code/Source/FeatureSchemaDefault.cpp b/Gems/MotionMatching/Code/Source/FeatureSchemaDefault.cpp
new file mode 100644
index 0000000000..9201c525b6
--- /dev/null
+++ b/Gems/MotionMatching/Code/Source/FeatureSchemaDefault.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include
+#include
+#include
+#include
+
+namespace EMotionFX::MotionMatching
+{
+ void DefaultFeatureSchema(FeatureSchema& featureSchema, DefaultFeatureSchemaInitSettings settings)
+ {
+ featureSchema.Clear();
+ const AZStd::string rootJointName = settings.m_rootJointName;
+
+ //----------------------------------------------------------------------------------------------------------
+ // Past and future root trajectory
+ FeatureTrajectory* rootTrajectory = aznew FeatureTrajectory();
+ rootTrajectory->SetJointName(rootJointName);
+ rootTrajectory->SetRelativeToJointName(rootJointName);
+ rootTrajectory->SetDebugDrawColor(AZ::Color::CreateFromRgba(157,78,221,255));
+ rootTrajectory->SetDebugDrawEnabled(true);
+ featureSchema.AddFeature(rootTrajectory);
+
+ //----------------------------------------------------------------------------------------------------------
+ // Left foot position
+ FeaturePosition* leftFootPosition = aznew FeaturePosition();
+ leftFootPosition->SetName("Left Foot Position");
+ leftFootPosition->SetJointName(settings.m_leftFootJointName);
+ leftFootPosition->SetRelativeToJointName(rootJointName);
+ leftFootPosition->SetDebugDrawColor(AZ::Color::CreateFromRgba(255,173,173,255));
+ leftFootPosition->SetDebugDrawEnabled(true);
+ featureSchema.AddFeature(leftFootPosition);
+
+ //----------------------------------------------------------------------------------------------------------
+ // Right foot position
+ FeaturePosition* rightFootPosition = aznew FeaturePosition();
+ rightFootPosition->SetName("Right Foot Position");
+ rightFootPosition->SetJointName(settings.m_rightFootJointName);
+ rightFootPosition->SetRelativeToJointName(rootJointName);
+ rightFootPosition->SetDebugDrawColor(AZ::Color::CreateFromRgba(253,255,182,255));
+ rightFootPosition->SetDebugDrawEnabled(true);
+ featureSchema.AddFeature(rightFootPosition);
+
+ //----------------------------------------------------------------------------------------------------------
+ // Left foot velocity
+ FeatureVelocity* leftFootVelocity = aznew FeatureVelocity();
+ leftFootVelocity->SetName("Left Foot Velocity");
+ leftFootVelocity->SetJointName(settings.m_leftFootJointName);
+ leftFootVelocity->SetRelativeToJointName(rootJointName);
+ leftFootVelocity->SetDebugDrawColor(AZ::Color::CreateFromRgba(155,246,255,255));
+ leftFootVelocity->SetDebugDrawEnabled(true);
+ leftFootVelocity->SetCostFactor(0.75f);
+ featureSchema.AddFeature(leftFootVelocity);
+
+ //----------------------------------------------------------------------------------------------------------
+ // Right foot velocity
+ FeatureVelocity* rightFootVelocity = aznew FeatureVelocity();
+ rightFootVelocity->SetName("Right Foot Velocity");
+ rightFootVelocity->SetJointName(settings.m_rightFootJointName);
+ rightFootVelocity->SetRelativeToJointName(rootJointName);
+ rightFootVelocity->SetDebugDrawColor(AZ::Color::CreateFromRgba(189,178,255,255));
+ rightFootVelocity->SetDebugDrawEnabled(true);
+ rightFootVelocity->SetCostFactor(0.75f);
+ featureSchema.AddFeature(rightFootVelocity);
+
+ //----------------------------------------------------------------------------------------------------------
+ // Pelvis velocity
+ FeatureVelocity* pelvisVelocity = aznew FeatureVelocity();
+ pelvisVelocity->SetName("Pelvis Velocity");
+ pelvisVelocity->SetJointName(settings.m_pelvisJointName);
+ pelvisVelocity->SetRelativeToJointName(rootJointName);
+ pelvisVelocity->SetDebugDrawColor(AZ::Color::CreateFromRgba(185,255,175,255));
+ pelvisVelocity->SetDebugDrawEnabled(true);
+ featureSchema.AddFeature(pelvisVelocity);
+ }
+} // namespace EMotionFX::MotionMatching
diff --git a/Gems/MotionMatching/Code/Source/FeatureSchemaDefault.h b/Gems/MotionMatching/Code/Source/FeatureSchemaDefault.h
new file mode 100644
index 0000000000..0c9cda228f
--- /dev/null
+++ b/Gems/MotionMatching/Code/Source/FeatureSchemaDefault.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include
+
+namespace EMotionFX::MotionMatching
+{
+ struct DefaultFeatureSchemaInitSettings
+ {
+ AZStd::string m_rootJointName;
+ AZStd::string m_leftFootJointName;
+ AZStd::string m_rightFootJointName;
+ AZStd::string m_pelvisJointName;
+ };
+ void DefaultFeatureSchema(FeatureSchema& featureSchema, DefaultFeatureSchemaInitSettings settings);
+} // namespace EMotionFX::MotionMatching
diff --git a/Gems/MotionMatching/Code/Source/FeatureTrajectory.cpp b/Gems/MotionMatching/Code/Source/FeatureTrajectory.cpp
new file mode 100644
index 0000000000..3de6053b06
--- /dev/null
+++ b/Gems/MotionMatching/Code/Source/FeatureTrajectory.cpp
@@ -0,0 +1,450 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+namespace EMotionFX::MotionMatching
+{
+ AZ_CLASS_ALLOCATOR_IMPL(FeatureTrajectory, MotionMatchAllocator, 0)
+
+ bool FeatureTrajectory::Init(const InitSettings& settings)
+ {
+ const bool result = Feature::Init(settings);
+ UpdateFacingAxis();
+ return result;
+ }
+
+ size_t FeatureTrajectory::CalcNumSamplesPerFrame() const
+ {
+ return m_numPastSamples + 1 + m_numFutureSamples;
+ }
+
+ void FeatureTrajectory::SetFacingAxis(const Axis axis)
+ {
+ m_facingAxis = axis;
+ UpdateFacingAxis();
+ }
+
+ void FeatureTrajectory::UpdateFacingAxis()
+ {
+ switch (m_facingAxis)
+ {
+ case Axis::X:
+ {
+ m_facingAxisDir = AZ::Vector3::CreateAxisX();
+ break;
+ }
+ case Axis::Y:
+ {
+ m_facingAxisDir = AZ::Vector3::CreateAxisY();
+ break;
+ }
+ case Axis::X_NEGATIVE:
+ {
+ m_facingAxisDir = -AZ::Vector3::CreateAxisX();
+ break;
+ }
+ case Axis::Y_NEGATIVE:
+ {
+ m_facingAxisDir = -AZ::Vector3::CreateAxisY();
+ break;
+ }
+ default:
+ {
+ AZ_Assert(false, "Facing direction axis unknown.");
+ }
+ }
+ }
+
+ AZ::Vector2 FeatureTrajectory::CalculateFacingDirection(const Pose& pose, const Transform& invRootTransform) const
+ {
+ // Get the facing direction of the given joint for the given pose in animation world space.
+ // The given pose is either sampled into the relative past or future based on the frame we want to extract the feature for.
+ const AZ::Vector3 facingDirAnimationWorldSpace = pose.GetWorldSpaceTransform(m_jointIndex).TransformVector(m_facingAxisDir);
+
+ // The invRootTransform is the inverse of the world space transform for the given joint at the frame we want to extract the feature for.
+ // The result after this will be the facing direction relative to the frame we want to extract the feature for.
+ const AZ::Vector3 facingDirection = invRootTransform.TransformVector(facingDirAnimationWorldSpace);
+
+ // Project to the ground plane and make sure the direction is normalized.
+ return AZ::Vector2(facingDirection).GetNormalizedSafe();
+ }
+
+ FeatureTrajectory::Sample FeatureTrajectory::GetSampleFromPose(const Pose& pose, const Transform& invRootTransform) const
+ {
+ // Position of the root joint in the model space relative to frame to extract.
+ const AZ::Vector2 position = AZ::Vector2(invRootTransform.TransformPoint(pose.GetWorldSpaceTransform(m_jointIndex).m_position));
+
+ // Calculate the facing direction.
+ const AZ::Vector2 facingDirection = CalculateFacingDirection(pose, invRootTransform);
+
+ return { position, facingDirection };
+ }
+
+ void FeatureTrajectory::ExtractFeatureValues(const ExtractFeatureContext& context)
+ {
+ const ActorInstance* actorInstance = context.m_actorInstance;
+ AnimGraphPosePool& posePool = GetEMotionFX().GetThreadData(actorInstance->GetThreadIndex())->GetPosePool();
+ AnimGraphPose* samplePose = posePool.RequestPose(actorInstance);
+ AnimGraphPose* nextSamplePose = posePool.RequestPose(actorInstance);
+
+ const size_t frameIndex = context.m_frameIndex;
+ const Frame& currentFrame = context.m_frameDatabase->GetFrame(context.m_frameIndex);
+
+ // Inverse of the root transform for the frame that we want to extract data from.
+ const Transform invRootTransform = context.m_framePose->GetWorldSpaceTransform(m_relativeToNodeIndex).Inversed();
+
+ const size_t midSampleIndex = CalcMidFrameIndex();
+ const Sample midSample = GetSampleFromPose(*context.m_framePose, invRootTransform);
+ SetFeatureData(context.m_featureMatrix, frameIndex, midSampleIndex, midSample);
+
+ // Sample the past.
+ const float pastFrameTimeDelta = m_pastTimeRange / static_cast(m_numPastSamples - 1);
+ currentFrame.SamplePose(&samplePose->GetPose());
+ for (size_t i = 0; i < m_numPastSamples; ++i)
+ {
+ // Increase the sample index by one as the zeroth past/future sample actually needs one time delta time difference to the current frame.
+ const float sampleTimeOffset = (i+1) * pastFrameTimeDelta * (-1.0f);
+ currentFrame.SamplePose(&nextSamplePose->GetPose(), sampleTimeOffset);
+
+ const Sample sample = GetSampleFromPose(samplePose->GetPose(), invRootTransform);
+ const size_t sampleIndex = CalcPastFrameIndex(i);
+ SetFeatureData(context.m_featureMatrix, frameIndex, sampleIndex, sample);
+
+ *samplePose = *nextSamplePose;
+ }
+
+ // Sample into the future.
+ const float futureFrameTimeDelta = m_futureTimeRange / (float)(m_numFutureSamples - 1);
+ currentFrame.SamplePose(&samplePose->GetPose());
+ for (size_t i = 0; i < m_numFutureSamples; ++i)
+ {
+ // Sample the value at the future sample point.
+ const float sampleTimeOffset = (i+1) * futureFrameTimeDelta;
+ currentFrame.SamplePose(&nextSamplePose->GetPose(), sampleTimeOffset);
+
+ const Sample sample = GetSampleFromPose(samplePose->GetPose(), invRootTransform);
+ const size_t sampleIndex = CalcFutureFrameIndex(i);
+ SetFeatureData(context.m_featureMatrix, frameIndex, sampleIndex, sample);
+
+ *samplePose = *nextSamplePose;
+ }
+
+ posePool.FreePose(samplePose);
+ posePool.FreePose(nextSamplePose);
+ }
+
+ void FeatureTrajectory::SetPastTimeRange(float timeInSeconds)
+ {
+ m_pastTimeRange = timeInSeconds;
+ }
+
+ void FeatureTrajectory::SetFutureTimeRange(float timeInSeconds)
+ {
+ m_futureTimeRange = timeInSeconds;
+ }
+
+ void FeatureTrajectory::SetNumPastSamplesPerFrame(size_t numHistorySamples)
+ {
+ m_numPastSamples = numHistorySamples;
+ }
+
+ void FeatureTrajectory::SetNumFutureSamplesPerFrame(size_t numFutureSamples)
+ {
+ m_numFutureSamples = numFutureSamples;
+ }
+
+ void FeatureTrajectory::DebugDrawFacingDirection(AzFramework::DebugDisplayRequests& debugDisplay,
+ const AZ::Vector3& positionWorldSpace,
+ const AZ::Vector3& facingDirectionWorldSpace)
+ {
+ const float length = 0.2f;
+ const float radius = 0.01f;
+
+ const AZ::Vector3 facingDirectionTarget = positionWorldSpace + facingDirectionWorldSpace * length;
+ debugDisplay.DrawSolidCylinder(/*center=*/(facingDirectionTarget + positionWorldSpace) * 0.5f,
+ /*direction=*/facingDirectionWorldSpace,
+ radius,
+ /*height=*/length,
+ /*drawShaded=*/false);
+ }
+
+ void FeatureTrajectory::DebugDrawFacingDirection(AzFramework::DebugDisplayRequests& debugDisplay,
+ const Transform& worldSpaceTransform,
+ const Sample& sample,
+ const AZ::Vector3& samplePosWorldSpace) const
+ {
+ const AZ::Vector3 facingDirectionWorldSpace = worldSpaceTransform.TransformVector(AZ::Vector3(sample.m_facingDirection)).GetNormalizedSafe();
+ DebugDrawFacingDirection(debugDisplay, samplePosWorldSpace, facingDirectionWorldSpace);
+ }
+
+ void FeatureTrajectory::DebugDrawTrajectory(AzFramework::DebugDisplayRequests& debugDisplay,
+ MotionMatchingInstance* instance,
+ size_t frameIndex,
+ const Transform& worldSpaceTransform,
+ const AZ::Color& color,
+ size_t numSamples,
+ const SplineToFeatureMatrixIndex& splineToFeatureMatrixIndex) const
+ {
+ if (frameIndex == InvalidIndex)
+ {
+ return;
+ }
+
+ constexpr float markerSize = 0.02f;
+ const FeatureMatrix& featureMatrix = instance->GetData()->GetFeatureMatrix();
+
+ debugDisplay.DepthTestOff();
+ debugDisplay.SetColor(color);
+
+ Sample nextSample;
+ AZ::Vector3 nextSamplePos;
+ for (size_t i = 0; i < numSamples - 1; ++i)
+ {
+ const Sample currentSample = GetFeatureData(featureMatrix, frameIndex, splineToFeatureMatrixIndex(i));
+ nextSample = GetFeatureData(featureMatrix, frameIndex, splineToFeatureMatrixIndex(i + 1));
+
+ const AZ::Vector3 currentSamplePos = worldSpaceTransform.TransformPoint(AZ::Vector3(currentSample.m_position));
+ nextSamplePos = worldSpaceTransform.TransformPoint(AZ::Vector3(nextSample.m_position));
+
+ // Line between current and next sample.
+ debugDisplay.DrawSolidCylinder(/*center=*/(nextSamplePos + currentSamplePos) * 0.5f,
+ /*direction=*/(nextSamplePos - currentSamplePos).GetNormalizedSafe(),
+ /*radius=*/0.0025f,
+ /*height=*/(nextSamplePos - currentSamplePos).GetLength(),
+ /*drawShaded=*/false);
+
+ // Sphere at the sample position and a cylinder to indicate the facing direction.
+ debugDisplay.DrawBall(currentSamplePos, markerSize, /*drawShaded=*/false);
+ DebugDrawFacingDirection(debugDisplay, worldSpaceTransform, currentSample, currentSamplePos);
+ }
+
+ debugDisplay.DrawBall(nextSamplePos, markerSize, /*drawShaded=*/false);
+ DebugDrawFacingDirection(debugDisplay, worldSpaceTransform, nextSample, nextSamplePos);
+ }
+
+ void FeatureTrajectory::DebugDraw(AzFramework::DebugDisplayRequests& debugDisplay,
+ MotionMatchingInstance* instance,
+ size_t frameIndex)
+ {
+ const ActorInstance* actorInstance = instance->GetActorInstance();
+ const Transform transform = actorInstance->GetTransformData()->GetCurrentPose()->GetWorldSpaceTransform(m_jointIndex);
+
+ DebugDrawTrajectory(debugDisplay, instance, frameIndex, transform,
+ m_debugColor, m_numPastSamples, AZStd::bind(&FeatureTrajectory::CalcPastFrameIndex, this, AZStd::placeholders::_1));
+
+ DebugDrawTrajectory(debugDisplay, instance, frameIndex, transform,
+ m_debugColor, m_numFutureSamples, AZStd::bind(&FeatureTrajectory::CalcFutureFrameIndex, this, AZStd::placeholders::_1));
+ }
+
+ size_t FeatureTrajectory::CalcMidFrameIndex() const
+ {
+ return m_numPastSamples;
+ }
+
+ size_t FeatureTrajectory::CalcPastFrameIndex(size_t historyFrameIndex) const
+ {
+ AZ_Assert(historyFrameIndex < m_numPastSamples, "The history frame index is out of range");
+ return m_numPastSamples - historyFrameIndex - 1;
+ }
+
+ size_t FeatureTrajectory::CalcFutureFrameIndex(size_t futureFrameIndex) const
+ {
+ AZ_Assert(futureFrameIndex < m_numFutureSamples, "The future frame index is out of range");
+ return CalcMidFrameIndex() + 1 + futureFrameIndex;
+ }
+
+ float FeatureTrajectory::CalculateCost(const FeatureMatrix& featureMatrix,
+ size_t frameIndex,
+ const Transform& invRootTransform,
+ const AZStd::vector& controlPoints,
+ const SplineToFeatureMatrixIndex& splineToFeatureMatrixIndex) const
+ {
+ float cost = 0.0f;
+ AZ::Vector2 lastControlPoint, lastSamplePos;
+
+ for (size_t i = 0; i < controlPoints.size(); ++i)
+ {
+ const TrajectoryQuery::ControlPoint& controlPoint = controlPoints[i];
+ const Sample sample = GetFeatureData(featureMatrix, frameIndex, splineToFeatureMatrixIndex(i));
+ const AZ::Vector2& samplePos = sample.m_position;
+ const AZ::Vector2 controlPointPos = AZ::Vector2(invRootTransform.TransformPoint(controlPoint.m_position)); // Convert so it is relative to where we are and pointing to.
+
+ if (i != 0)
+ {
+ const AZ::Vector2 controlPointDelta = controlPointPos - lastControlPoint;
+ const AZ::Vector2 sampleDelta = samplePos - lastSamplePos;
+
+ const float posDistance = (samplePos - controlPointPos).GetLength();
+ const float posDeltaDistance = (controlPointDelta - sampleDelta).GetLength();
+
+ // The facing direction from the control point (trajectory query) is in world space while the facing direction from the
+ // sample of this trajectory feature is in relative-to-frame-root-joint space.
+ const AZ::Vector2 controlPointFacingDirRelativeSpace = AZ::Vector2(invRootTransform.TransformVector(controlPoint.m_facingDirection));
+ const float facingDirectionCost = GetNormalizedDirectionDifference(sample.m_facingDirection,
+ controlPointFacingDirRelativeSpace);
+
+ // As we got two different costs for the position, double the cost of the facing direction to equal out the influence.
+ cost += CalcResidual(posDistance) + CalcResidual(posDeltaDistance) + CalcResidual(facingDirectionCost) * 2.0f;
+ }
+
+ lastControlPoint = controlPointPos;
+ lastSamplePos = samplePos;
+ }
+
+ return cost;
+ }
+
+ float FeatureTrajectory::CalculateFutureFrameCost(size_t frameIndex, const FrameCostContext& context) const
+ {
+ AZ_Assert(context.m_trajectoryQuery->GetFutureControlPoints().size() == m_numFutureSamples, "Number of future control points from the trajectory query does not match the one from the trajectory feature.");
+ const Transform invRootTransform = context.m_currentPose.GetWorldSpaceTransform(m_relativeToNodeIndex).Inversed();
+ return CalculateCost(context.m_featureMatrix, frameIndex, invRootTransform, context.m_trajectoryQuery->GetFutureControlPoints(), AZStd::bind(&FeatureTrajectory::CalcFutureFrameIndex, this, AZStd::placeholders::_1));
+ }
+
+ float FeatureTrajectory::CalculatePastFrameCost(size_t frameIndex, const FrameCostContext& context) const
+ {
+ AZ_Assert(context.m_trajectoryQuery->GetPastControlPoints().size() == m_numPastSamples, "Number of past control points from the trajectory query does not match the one from the trajectory feature");
+ const Transform invRootTransform = context.m_currentPose.GetWorldSpaceTransform(m_relativeToNodeIndex).Inversed();
+ return CalculateCost(context.m_featureMatrix, frameIndex, invRootTransform, context.m_trajectoryQuery->GetPastControlPoints(), AZStd::bind(&FeatureTrajectory::CalcPastFrameIndex, this, AZStd::placeholders::_1));
+ }
+
+ AZ::Crc32 FeatureTrajectory::GetCostFactorVisibility() const
+ {
+ return AZ::Edit::PropertyVisibility::Hide;
+ }
+
+ void FeatureTrajectory::Reflect(AZ::ReflectContext* context)
+ {
+ AZ::SerializeContext* serializeContext = azrtti_cast(context);
+ if (!serializeContext)
+ {
+ return;
+ }
+
+ serializeContext->Class()
+ ->Version(2)
+ ->Field("pastTimeRange", &FeatureTrajectory::m_pastTimeRange)
+ ->Field("numPastSamples", &FeatureTrajectory::m_numPastSamples)
+ ->Field("pastCostFactor", &FeatureTrajectory::m_pastCostFactor)
+ ->Field("futureTimeRange", &FeatureTrajectory::m_futureTimeRange)
+ ->Field("numFutureSamples", &FeatureTrajectory::m_numFutureSamples)
+ ->Field("futureCostFactor", &FeatureTrajectory::m_futureCostFactor)
+ ->Field("facingAxis", &FeatureTrajectory::m_facingAxis)
+ ;
+
+ AZ::EditContext* editContext = serializeContext->GetEditContext();
+ if (!editContext)
+ {
+ return;
+ }
+
+ editContext->Class("FeatureTrajectory", "Matches the joint past and future trajectory.")
+ ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
+ ->Attribute(AZ::Edit::Attributes::AutoExpand, "")
+ ->DataElement(AZ::Edit::UIHandlers::Default, &FeatureTrajectory::m_numPastSamples, "Past Samples", "The number of samples stored per frame for the past trajectory. [Default = 4 samples to represent the trajectory history]")
+ ->Attribute(AZ::Edit::Attributes::Min, 1)
+ ->Attribute(AZ::Edit::Attributes::Max, 100)
+ ->Attribute(AZ::Edit::Attributes::Step, 1)
+ ->DataElement(AZ::Edit::UIHandlers::Default, &FeatureTrajectory::m_pastTimeRange, "Past Time Range", "The time window the samples are distributed along for the trajectory history. [Default = 0.7 seconds]")
+ ->Attribute(AZ::Edit::Attributes::Min, 0.01f)
+ ->Attribute(AZ::Edit::Attributes::Max, 10.0f)
+ ->Attribute(AZ::Edit::Attributes::Step, 0.1f)
+ ->DataElement(AZ::Edit::UIHandlers::Default, &FeatureTrajectory::m_pastCostFactor, "Past Cost Factor", "The cost factor is multiplied with the cost from the trajectory history and can be used to change the influence of the trajectory history match in the motion matching search.")
+ ->Attribute(AZ::Edit::Attributes::Min, 0.0f)
+ ->Attribute(AZ::Edit::Attributes::Max, 100.0f)
+ ->Attribute(AZ::Edit::Attributes::Step, 0.1f)
+ ->DataElement(AZ::Edit::UIHandlers::Default, &FeatureTrajectory::m_numFutureSamples, "Future Samples", "The number of samples stored per frame for the future trajectory. [Default = 6 samples to represent the future trajectory]")
+ ->Attribute(AZ::Edit::Attributes::Min, 1)
+ ->Attribute(AZ::Edit::Attributes::Max, 100)
+ ->Attribute(AZ::Edit::Attributes::Step, 1)
+ ->DataElement(AZ::Edit::UIHandlers::Default, &FeatureTrajectory::m_futureTimeRange, "Future Time Range", "The time window the samples are distributed along for the future trajectory. [Default = 1.2 seconds]")
+ ->Attribute(AZ::Edit::Attributes::Min, 0.01f)
+ ->Attribute(AZ::Edit::Attributes::Max, 10.0f)
+ ->Attribute(AZ::Edit::Attributes::Step, 0.1f)
+ ->DataElement(AZ::Edit::UIHandlers::Default, &FeatureTrajectory::m_futureCostFactor, "Future Cost Factor", "The cost factor is multiplied with the cost from the future trajectory and can be used to change the influence of the future trajectory match in the motion matching search.")
+ ->Attribute(AZ::Edit::Attributes::Min, 0.0f)
+ ->Attribute(AZ::Edit::Attributes::Max, 100.0f)
+ ->Attribute(AZ::Edit::Attributes::Step, 0.1f)
+ ->DataElement(AZ::Edit::UIHandlers::ComboBox, &FeatureTrajectory::m_facingAxis, "Facing Axis", "The facing direction of the character. Which axis of the joint transform is facing forward? [Default = Looking into Y-axis direction]")
+ ->Attribute(AZ::Edit::Attributes::ChangeNotify, &FeatureTrajectory::UpdateFacingAxis)
+ ->EnumAttribute(Axis::X, "X")
+ ->EnumAttribute(Axis::X_NEGATIVE, "-X")
+ ->EnumAttribute(Axis::Y, "Y")
+ ->EnumAttribute(Axis::Y_NEGATIVE, "-Y")
+ ;
+ }
+
+ size_t FeatureTrajectory::GetNumDimensions() const
+ {
+ return CalcNumSamplesPerFrame() * Sample::s_componentsPerSample;
+ }
+
+ AZStd::string FeatureTrajectory::GetDimensionName(size_t index) const
+ {
+ AZStd::string result = "Trajectory";
+
+ const int sampleIndex = aznumeric_cast(index) / aznumeric_cast(Sample::s_componentsPerSample);
+ const int componentIndex = index % Sample::s_componentsPerSample;
+ const int midSampleIndex = aznumeric_cast(CalcMidFrameIndex());
+
+ if (sampleIndex == midSampleIndex)
+ {
+ result += ".Current.";
+ }
+ else if (sampleIndex < midSampleIndex)
+ {
+ result += AZStd::string::format(".Past%i.", sampleIndex - static_cast(m_numPastSamples));
+ }
+ else
+ {
+ result += AZStd::string::format(".Future%i.", sampleIndex - static_cast(m_numPastSamples));
+ }
+
+ switch (componentIndex)
+ {
+ case 0: { result += "PosX"; break; }
+ case 1: { result += "PosY"; break; }
+ case 2: { result += "FacingDirX"; break; }
+ case 3: { result += "FacingDirY"; break; }
+ default: { result += Feature::GetDimensionName(index); }
+ }
+
+ return result;
+ }
+
+ FeatureTrajectory::Sample FeatureTrajectory::GetFeatureData(const FeatureMatrix& featureMatrix, size_t frameIndex, size_t sampleIndex) const
+ {
+ const size_t columnOffset = m_featureColumnOffset + sampleIndex * Sample::s_componentsPerSample;
+ return {
+ /*.m_position =*/ featureMatrix.GetVector2(frameIndex, columnOffset + 0),
+ /*.m_facingDirection =*/ featureMatrix.GetVector2(frameIndex, columnOffset + 2),
+ };
+ }
+
+ void FeatureTrajectory::SetFeatureData(FeatureMatrix& featureMatrix, size_t frameIndex, size_t sampleIndex, const Sample& sample)
+ {
+ const size_t columnOffset = m_featureColumnOffset + sampleIndex * Sample::s_componentsPerSample;
+ featureMatrix.SetVector2(frameIndex, columnOffset + 0, sample.m_position);
+ featureMatrix.SetVector2(frameIndex, columnOffset + 2, sample.m_facingDirection);
+ }
+} // namespace EMotionFX::MotionMatching
diff --git a/Gems/MotionMatching/Code/Source/FeatureTrajectory.h b/Gems/MotionMatching/Code/Source/FeatureTrajectory.h
new file mode 100644
index 0000000000..7eacbf684c
--- /dev/null
+++ b/Gems/MotionMatching/Code/Source/FeatureTrajectory.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+namespace AZ
+{
+ class ReflectContext;
+}
+
+namespace EMotionFX::MotionMatching
+{
+ class FrameDatabase;
+
+ /**
+ * Matches the root joint past and future trajectory.
+ * For each frame in the motion database, the position and facing direction relative to the current frame of the joint will be evaluated for a past and future time window.
+ * The past and future samples together form the trajectory of the current frame within the time window. This basically describes where the character came from to reach the
+ * current frame and where it will go when continuing to play the animation.
+ **/
+ class EMFX_API FeatureTrajectory
+ : public Feature
+ {
+ public:
+ AZ_RTTI(FeatureTrajectory, "{0451E95B-A452-439A-81ED-3962A06A3992}", Feature)
+ AZ_CLASS_ALLOCATOR_DECL
+
+ enum class Axis
+ {
+ X = 0,
+ Y = 1,
+ X_NEGATIVE = 2,
+ Y_NEGATIVE = 3,
+ };
+
+ struct EMFX_API Sample
+ {
+ AZ::Vector2 m_position; //! Position in the space relative to the extracted frame.
+ AZ::Vector2 m_facingDirection; //! Facing direction in the space relative to the extracted frame.
+
+ static constexpr size_t s_componentsPerSample = 4;
+ };
+
+ FeatureTrajectory() = default;
+ ~FeatureTrajectory() override = default;
+
+ bool Init(const InitSettings& settings) override;
+ void ExtractFeatureValues(const ExtractFeatureContext& context) override;
+ void DebugDraw(AzFramework::DebugDisplayRequests& debugDisplay,
+ MotionMatchingInstance* instance,
+ size_t frameIndex) override;
+
+ float CalculateFutureFrameCost(size_t frameIndex, const FrameCostContext& context) const;
+ float CalculatePastFrameCost(size_t frameIndex, const FrameCostContext& context) const;
+
+ void SetNumPastSamplesPerFrame(size_t numHistorySamples);
+ void SetNumFutureSamplesPerFrame(size_t numFutureSamples);
+ void SetPastTimeRange(float timeInSeconds);
+ void SetFutureTimeRange(float timeInSeconds);
+ void SetFacingAxis(const Axis axis);
+ void UpdateFacingAxis();
+
+ float GetPastTimeRange() const { return m_pastTimeRange; }
+ size_t GetNumPastSamples() const { return m_numPastSamples; }
+ float GetPastCostFactor() const { return m_pastCostFactor; }
+
+ float GetFutureTimeRange() const { return m_futureTimeRange; }
+ size_t GetNumFutureSamples() const { return m_numFutureSamples; }
+ float GetFutureCostFactor() const { return m_futureCostFactor; }
+
+ AZ::Vector2 CalculateFacingDirection(const Pose& pose, const Transform& invRootTransform) const;
+ AZ::Vector3 GetFacingAxisDir() const { return m_facingAxisDir; }
+
+ static void Reflect(AZ::ReflectContext* context);
+
+ size_t GetNumDimensions() const override;
+ AZStd::string GetDimensionName(size_t index) const override;
+
+ // Shared helper function to draw a facing direction.
+ static void DebugDrawFacingDirection(AzFramework::DebugDisplayRequests& debugDisplay,
+ const AZ::Vector3& positionWorldSpace,
+ const AZ::Vector3& facingDirectionWorldSpace);
+
+ private:
+ size_t CalcMidFrameIndex() const;
+ size_t CalcPastFrameIndex(size_t historyFrameIndex) const;
+ size_t CalcFutureFrameIndex(size_t futureFrameIndex) const;
+ size_t CalcNumSamplesPerFrame() const;
+
+ using SplineToFeatureMatrixIndex = AZStd::function;
+ float CalculateCost(const FeatureMatrix& featureMatrix,
+ size_t frameIndex,
+ const Transform& invRootTransform,
+ const AZStd::vector& controlPoints,
+ const SplineToFeatureMatrixIndex& splineToFeatureMatrixIndex) const;
+
+ //! Called for every sample in the past or future range to extract its information.
+ //! @param[in] pose The sampled pose within the trajectory range [m_pastTimeRange, m_futureTimeRange].
+ //! @param[in] invRootTransform The inverse of the world space transform of the joint at frame time that the feature is extracted for.
+ Sample GetSampleFromPose(const Pose& pose, const Transform& invRootTransform) const;
+
+ Sample GetFeatureData(const FeatureMatrix& featureMatrix, size_t frameIndex, size_t sampleIndex) const;
+ void SetFeatureData(FeatureMatrix& featureMatrix, size_t frameIndex, size_t sampleIndex, const Sample& sample);
+
+ void DebugDrawTrajectory(AzFramework::DebugDisplayRequests& debugDisplay,
+ MotionMatchingInstance* instance,
+ size_t frameIndex,
+ const Transform& transform,
+ const AZ::Color& color,
+ size_t numSamples,
+ const SplineToFeatureMatrixIndex& splineToFeatureMatrixIndex) const;
+
+ void DebugDrawFacingDirection(AzFramework::DebugDisplayRequests& debugDisplay,
+ const Transform& worldSpaceTransform,
+ const Sample& sample,
+ const AZ::Vector3& samplePosWorldSpace) const;
+
+ AZ::Crc32 GetCostFactorVisibility() const override;
+
+ float m_pastTimeRange = 0.7f; //< The time window the samples are distributed along for the past trajectory.
+ size_t m_numPastSamples = 4; //< The number of samples stored per frame for the past (history) trajectory.
+ float m_pastCostFactor = 0.5f; //< Normalized value to weight or scale the future trajectory cost.
+
+ float m_futureTimeRange = 1.2f; //< The time window the samples are distributed along for the future trajectory.
+ size_t m_numFutureSamples = 6; //< The number of samples stored per frame for the future trajectory.
+ float m_futureCostFactor = 0.75f; //< Normalized value to weight or scale the future trajectory cost.
+
+ Axis m_facingAxis = Axis::Y; //< Which axis of the joint transform is facing forward?
+ AZ::Vector3 m_facingAxisDir = AZ::Vector3::CreateAxisY();
+ };
+} // namespace EMotionFX::MotionMatching
diff --git a/Gems/MotionMatching/Code/Source/FeatureVelocity.cpp b/Gems/MotionMatching/Code/Source/FeatureVelocity.cpp
new file mode 100644
index 0000000000..e210ca1a61
--- /dev/null
+++ b/Gems/MotionMatching/Code/Source/FeatureVelocity.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+namespace EMotionFX::MotionMatching
+{
+ AZ_CLASS_ALLOCATOR_IMPL(FeatureVelocity, MotionMatchAllocator, 0)
+
+ void FeatureVelocity::FillQueryFeatureValues(size_t startIndex, AZStd::vector& queryFeatureValues, const FrameCostContext& context)
+ {
+ PoseDataJointVelocities* velocityPoseData = static_cast(context.m_currentPose.GetPoseDataByType(azrtti_typeid()));
+ AZ_Assert(velocityPoseData, "Cannot calculate velocity feature cost without joint velocity pose data.");
+ const AZ::Vector3 currentVelocity = velocityPoseData->GetVelocity(m_jointIndex);
+
+ queryFeatureValues[startIndex + 0] = currentVelocity.GetX();
+ queryFeatureValues[startIndex + 1] = currentVelocity.GetY();
+ queryFeatureValues[startIndex + 2] = currentVelocity.GetZ();
+ }
+
+ void FeatureVelocity::ExtractFeatureValues(const ExtractFeatureContext& context)
+ {
+ AZ::Vector3 velocity;
+ CalculateVelocity(context.m_actorInstance, m_jointIndex, m_relativeToNodeIndex, context.m_frameDatabase->GetFrame(context.m_frameIndex), velocity);
+
+ SetFeatureData(context.m_featureMatrix, context.m_frameIndex, velocity);
+ }
+
+ void FeatureVelocity::DebugDraw(AzFramework::DebugDisplayRequests& debugDisplay,
+ MotionMatchingInstance* instance,
+ const AZ::Vector3& velocity,
+ size_t jointIndex,
+ size_t relativeToJointIndex,
+ const AZ::Color& color)
+ {
+ const ActorInstance* actorInstance = instance->GetActorInstance();
+ const Pose* pose = actorInstance->GetTransformData()->GetCurrentPose();
+ const Transform jointModelTM = pose->GetModelSpaceTransform(jointIndex);
+ const Transform relativeToWorldTM = pose->GetWorldSpaceTransform(relativeToJointIndex);
+
+ const AZ::Vector3 jointPosition = relativeToWorldTM.TransformPoint(jointModelTM.m_position);
+ const float scale = 0.15f;
+ const AZ::Vector3 velocityWorldSpace = relativeToWorldTM.TransformVector(velocity * scale);
+
+ DebugDrawVelocity(debugDisplay, jointPosition, velocityWorldSpace, color);
+ }
+
+ void FeatureVelocity::DebugDraw(AzFramework::DebugDisplayRequests& debugDisplay,
+ MotionMatchingInstance* instance,
+ size_t frameIndex)
+ {
+ if (m_jointIndex == InvalidIndex)
+ {
+ return;
+ }
+
+ const MotionMatchingData* data = instance->GetData();
+ const AZ::Vector3 velocity = GetFeatureData(data->GetFeatureMatrix(), frameIndex);
+ DebugDraw(debugDisplay, instance, velocity, m_jointIndex, m_relativeToNodeIndex, m_debugColor);
+ }
+
+ float FeatureVelocity::CalculateFrameCost(size_t frameIndex, const FrameCostContext& context) const
+ {
+ PoseDataJointVelocities* velocityPoseData = static_cast(context.m_currentPose.GetPoseDataByType(azrtti_typeid()));
+ AZ_Assert(velocityPoseData, "Cannot calculate velocity feature cost without joint velocity pose data.");
+ const AZ::Vector3 currentVelocity = velocityPoseData->GetVelocity(m_jointIndex);
+
+ const AZ::Vector3 frameVelocity = GetFeatureData(context.m_featureMatrix, frameIndex);
+
+ // Direction difference
+ const float directionDifferenceCost = GetNormalizedDirectionDifference(frameVelocity.GetNormalized(), currentVelocity.GetNormalized());
+
+ // Speed difference
+ // TODO: This needs to be normalized later on, else wise it could be that the direction difference is weights
+ // too heavily or too less compared to what the speed values are
+ const float speedDifferenceCost = frameVelocity.GetLength() - currentVelocity.GetLength();
+
+ return CalcResidual(directionDifferenceCost) + CalcResidual(speedDifferenceCost);
+ }
+
+ void FeatureVelocity::Reflect(AZ::ReflectContext* context)
+ {
+ AZ::SerializeContext* serializeContext = azrtti_cast(context);
+ if (!serializeContext)
+ {
+ return;
+ }
+
+ serializeContext->Class()
+ ->Version(1)
+ ;
+
+ AZ::EditContext* editContext = serializeContext->GetEditContext();
+ if (!editContext)
+ {
+ return;
+ }
+
+ editContext->Class("FeatureVelocity", "Matches joint velocities.")
+ ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
+ ->Attribute(AZ::Edit::Attributes::AutoExpand, "")
+ ;
+ }
+
+ size_t FeatureVelocity::GetNumDimensions() const
+ {
+ return 3;
+ }
+
+ AZStd::string FeatureVelocity::GetDimensionName(size_t index) const
+ {
+ AZStd::string result = m_jointName;
+ result += '.';
+
+ switch (index)
+ {
+ case 0: { result += "VelocityX"; break; }
+ case 1: { result += "VelocityY"; break; }
+ case 2: { result += "VelocityZ"; break; }
+ default: { result += Feature::GetDimensionName(index); }
+ }
+
+ return result;
+ }
+
+ AZ::Vector3 FeatureVelocity::GetFeatureData(const FeatureMatrix& featureMatrix, size_t frameIndex) const
+ {
+ return featureMatrix.GetVector3(frameIndex, m_featureColumnOffset);
+ }
+
+ void FeatureVelocity::SetFeatureData(FeatureMatrix& featureMatrix, size_t frameIndex, const AZ::Vector3& velocity)
+ {
+ featureMatrix.SetVector3(frameIndex, m_featureColumnOffset, velocity);
+ }
+} // namespace EMotionFX::MotionMatching
diff --git a/Gems/MotionMatching/Code/Source/FeatureVelocity.h b/Gems/MotionMatching/Code/Source/FeatureVelocity.h
new file mode 100644
index 0000000000..37cd8f3d7e
--- /dev/null
+++ b/Gems/MotionMatching/Code/Source/FeatureVelocity.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+namespace AZ
+{
+ class ReflectContext;
+}
+
+namespace EMotionFX::MotionMatching
+{
+ class FrameDatabase;
+
+ class EMFX_API FeatureVelocity
+ : public Feature
+ {
+ public:
+ AZ_RTTI(FeatureVelocity, "{DEEA4F0F-CE70-4F16-9136-C2BFDDA29336}", Feature)
+ AZ_CLASS_ALLOCATOR_DECL
+
+ FeatureVelocity() = default;
+ ~FeatureVelocity() override = default;
+
+ void ExtractFeatureValues(const ExtractFeatureContext& context) override;
+
+ static void DebugDraw(AzFramework::DebugDisplayRequests& debugDisplay,
+ MotionMatchingInstance* instance,
+ const AZ::Vector3& velocity, // in world space
+ size_t jointIndex,
+ size_t relativeToJointIndex,
+ const AZ::Color& color);
+
+ void DebugDraw(AzFramework::DebugDisplayRequests& debugDisplay,
+ MotionMatchingInstance* instance,
+ size_t frameIndex) override;
+
+ float CalculateFrameCost(size_t frameIndex, const FrameCostContext& context) const override;
+
+ void FillQueryFeatureValues(size_t startIndex, AZStd::vector& queryFeatureValues, const FrameCostContext& context) override;
+
+ static void Reflect(AZ::ReflectContext* context);
+
+ size_t GetNumDimensions() const override;
+ AZStd::string GetDimensionName(size_t index) const override;
+ AZ::Vector3 GetFeatureData(const FeatureMatrix& featureMatrix, size_t frameIndex) const;
+ void SetFeatureData(FeatureMatrix& featureMatrix, size_t frameIndex, const AZ::Vector3& velocity);
+ };
+} // namespace EMotionFX::MotionMatching
diff --git a/Gems/MotionMatching/Code/Source/Frame.cpp b/Gems/MotionMatching/Code/Source/Frame.cpp
new file mode 100644
index 0000000000..170d3050f7
--- /dev/null
+++ b/Gems/MotionMatching/Code/Source/Frame.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include
+#include
+#include
+#include
+
+namespace EMotionFX::MotionMatching
+{
+ AZ_CLASS_ALLOCATOR_IMPL(Frame, MotionMatchAllocator, 0)
+
+ Frame::Frame()
+ : m_frameIndex(InvalidIndex)
+ , m_sampleTime(0.0f)
+ , m_sourceMotion(nullptr)
+ , m_mirrored(false)
+ {
+ }
+
+ Frame::Frame(size_t frameIndex, Motion* sourceMotion, float sampleTime, bool mirrored)
+ : m_frameIndex(frameIndex)
+ , m_sourceMotion(sourceMotion)
+ , m_sampleTime(sampleTime)
+ , m_mirrored(mirrored)
+ {
+ }
+
+ void Frame::SamplePose(Pose* outputPose, float timeOffset) const
+ {
+ MotionDataSampleSettings sampleSettings;
+ sampleSettings.m_actorInstance = outputPose->GetActorInstance();
+ sampleSettings.m_inPlace = false;
+ sampleSettings.m_mirror = m_mirrored;
+ sampleSettings.m_retarget = false;
+ sampleSettings.m_inputPose = sampleSettings.m_actorInstance->GetTransformData()->GetBindPose();
+
+ sampleSettings.m_sampleTime = m_sampleTime + timeOffset;
+ sampleSettings.m_sampleTime = AZ::GetClamp(m_sampleTime + timeOffset, 0.0f, m_sourceMotion->GetDuration());
+
+ m_sourceMotion->SamplePose(outputPose, sampleSettings);
+ }
+
+ void Frame::SetFrameIndex(size_t frameIndex)
+ {
+ m_frameIndex = frameIndex;
+ }
+
+ Motion* Frame::GetSourceMotion() const
+ {
+ return m_sourceMotion;
+ }
+
+ float Frame::GetSampleTime() const
+ {
+ return m_sampleTime;
+ }
+
+ void Frame::SetSourceMotion(Motion* sourceMotion)
+ {
+ m_sourceMotion = sourceMotion;
+ }
+
+ void Frame::SetMirrored(bool enabled)
+ {
+ m_mirrored = enabled;
+ }
+
+ void Frame::SetSampleTime(float sampleTime)
+ {
+ m_sampleTime = sampleTime;
+ }
+} // namespace EMotionFX::MotionMatching
diff --git a/Gems/MotionMatching/Code/Source/Frame.h b/Gems/MotionMatching/Code/Source/Frame.h
new file mode 100644
index 0000000000..02150cfa5a
--- /dev/null
+++ b/Gems/MotionMatching/Code/Source/Frame.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include
+#include
+
+#include
+#include
+
+namespace EMotionFX
+{
+ class Motion;
+
+ namespace MotionMatching
+ {
+ /**
+ * A motion matching frame.
+ * This holds information required in order to extract a given pose in a given motion.
+ */
+ class EMFX_API Frame
+ {
+ public:
+ AZ_RTTI(Frame, "{985BD732-D80E-4898-AB6C-CAB22D88AACD}")
+ AZ_CLASS_ALLOCATOR_DECL
+
+ Frame();
+ Frame(size_t frameIndex, Motion* sourceMotion, float sampleTime, bool mirrored);
+ ~Frame() = default;
+
+ //! Sample the pose for the given frame.
+ //! @param[in] outputPose The pose used to store the sampled result.
+ //! @param[in] timeOffset Frames in the frame database are samples with a given sample rate (default = 30 fps).
+ //! For calculating velocities for example, it is needed to sample a pose close to a frame but not exactly at the frame position.
+ //! The timeOffset parameter can be used for that and represents the offset in time from the frame sample time in seconds.
+ //! In case the time offset is 0.0, the pose exactly at the frame position will be sampled.
+ void SamplePose(Pose* outputPose, float timeOffset = 0.0f) const;
+
+ Motion* GetSourceMotion() const;
+ float GetSampleTime() const;
+ size_t GetFrameIndex() const { return m_frameIndex; }
+ bool GetMirrored() const { return m_mirrored; }
+
+ void SetSourceMotion(Motion* sourceMotion);
+ void SetSampleTime(float sampleTime);
+ void SetFrameIndex(size_t frameIndex);
+ void SetMirrored(bool enabled);
+
+ private:
+ size_t m_frameIndex = 0; /**< The motion frame index inside the data object. */
+ float m_sampleTime = 0.0f; /**< The time offset in the original motion. */
+ Motion* m_sourceMotion = nullptr; /**< The original motion that we sample from to restore the pose. */
+ bool m_mirrored = false; /**< Is this frame mirrored? */
+ };
+ } // namespace MotionMatching
+} // namespace EMotionFX
diff --git a/Gems/MotionMatching/Code/Source/FrameDatabase.cpp b/Gems/MotionMatching/Code/Source/FrameDatabase.cpp
new file mode 100644
index 0000000000..7d38060dcc
--- /dev/null
+++ b/Gems/MotionMatching/Code/Source/FrameDatabase.cpp
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+namespace EMotionFX::MotionMatching
+{
+ AZ_CLASS_ALLOCATOR_IMPL(FrameDatabase, MotionMatchAllocator, 0)
+
+ FrameDatabase::FrameDatabase()
+ {
+ }
+
+ FrameDatabase::~FrameDatabase()
+ {
+ Clear();
+ }
+
+ void FrameDatabase::Clear()
+ {
+ // Clear the frames.
+ m_frames.clear();
+ m_frames.shrink_to_fit();
+
+ m_frameIndexByMotion.clear();
+
+ // Clear other things.
+ m_usedMotions.clear();
+ m_usedMotions.shrink_to_fit();
+ }
+
+ void FrameDatabase::ExtractActiveMotionEventDatas(const Motion* motion, float time, AZStd::vector& activeEventDatas)
+ {
+ activeEventDatas.clear();
+
+ // Iterate over all motion event tracks and all events inside them.
+ const MotionEventTable* eventTable = motion->GetEventTable();
+ const size_t numTracks = eventTable->GetNumTracks();
+ for (size_t t = 0; t < numTracks; ++t)
+ {
+ const MotionEventTrack* track = eventTable->GetTrack(t);
+ const size_t numEvents = track->GetNumEvents();
+ for (size_t e = 0; e < numEvents; ++e)
+ {
+ const MotionEvent& motionEvent = track->GetEvent(e);
+
+ // Only handle range based events and events that include our time value.
+ if (motionEvent.GetIsTickEvent() ||
+ motionEvent.GetStartTime() > time ||
+ motionEvent.GetEndTime() < time)
+ {
+ continue;
+ }
+
+ for (auto eventData : motionEvent.GetEventDatas())
+ {
+ activeEventDatas.emplace_back(const_cast(eventData.get()));
+ }
+ }
+ }
+ }
+
+ bool FrameDatabase::IsFrameDiscarded(const AZStd::vector& activeEventDatas) const
+ {
+ for (const EventData* eventData : activeEventDatas)
+ {
+ if (eventData->RTTI_GetType() == azrtti_typeid())
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ AZStd::tuple FrameDatabase::ImportFrames(Motion* motion, const FrameImportSettings& settings, bool mirrored)
+ {
+ AZ_PROFILE_SCOPE(Animation, "FrameDatabase::ImportFrames");
+
+ AZ_Assert(motion, "The motion cannot be a nullptr");
+ AZ_Assert(settings.m_sampleRate > 0, "The sample rate must be bigger than zero frames per second");
+ AZ_Assert(settings.m_sampleRate <= 120, "The sample rate must be smaller than 120 frames per second");
+
+ size_t numFramesImported = 0;
+ size_t numFramesDiscarded = 0;
+
+ // Calculate the number of frames we might need to import, in worst case.
+ m_sampleRate = settings.m_sampleRate;
+ const double timeStep = 1.0 / aznumeric_cast(settings.m_sampleRate);
+ const size_t worstCaseNumFrames = aznumeric_cast(ceil(motion->GetDuration() / timeStep)) + 1;
+
+ // Try to pre-allocate memory for the worst case scenario.
+ if (m_frames.capacity() < m_frames.size() + worstCaseNumFrames)
+ {
+ m_frames.reserve(m_frames.size() + worstCaseNumFrames);
+ }
+
+ AZStd::vector activeEvents;
+
+ // Iterate over all sample positions in the motion.
+ const double totalTime = aznumeric_cast(motion->GetDuration());
+ double curTime = 0.0;
+ while (curTime <= totalTime)
+ {
+ const float floatTime = aznumeric_cast(curTime);
+ ExtractActiveMotionEventDatas(motion, floatTime, activeEvents);
+ if (!IsFrameDiscarded(activeEvents))
+ {
+ ImportFrame(motion, floatTime, mirrored);
+ numFramesImported++;
+ }
+ else
+ {
+ numFramesDiscarded++;
+ }
+ curTime += timeStep;
+ }
+
+ // Make sure we include the last frame, if we stepped over it.
+ if (curTime - timeStep < totalTime - 0.000001)
+ {
+ const float floatTime = aznumeric_cast(totalTime);
+ ExtractActiveMotionEventDatas(motion, floatTime, activeEvents);
+ if (!IsFrameDiscarded(activeEvents))
+ {
+ ImportFrame(motion, floatTime, mirrored);
+ numFramesImported++;
+ }
+ else
+ {
+ numFramesDiscarded++;
+ }
+ }
+
+ // Automatically shrink the frame storage to their minimum size.
+ if (settings.m_autoShrink)
+ {
+ m_frames.shrink_to_fit();
+ }
+
+ // Register the motion.
+ if (AZStd::find(m_usedMotions.begin(), m_usedMotions.end(), motion) == m_usedMotions.end())
+ {
+ m_usedMotions.emplace_back(motion);
+ }
+
+ return { numFramesImported, numFramesDiscarded };
+ }
+
+ void FrameDatabase::ImportFrame(Motion* motion, float timeValue, bool mirrored)
+ {
+ m_frames.emplace_back(Frame(m_frames.size(), motion, timeValue, mirrored));
+ m_frameIndexByMotion[motion].emplace_back(m_frames.back().GetFrameIndex());
+ }
+
+ size_t FrameDatabase::CalcMemoryUsageInBytes() const
+ {
+ size_t total = 0;
+
+ total += m_frames.capacity() * sizeof(Frame);
+ total += sizeof(m_frames);
+ total += m_usedMotions.capacity() * sizeof(const Motion*);
+ total += sizeof(m_usedMotions);
+
+ return total;
+ }
+
+ size_t FrameDatabase::GetNumFrames() const
+ {
+ return m_frames.size();
+ }
+
+ size_t FrameDatabase::GetNumUsedMotions() const
+ {
+ return m_usedMotions.size();
+ }
+
+ const Motion* FrameDatabase::GetUsedMotion(size_t index) const
+ {
+ return m_usedMotions[index];
+ }
+
+ const Frame& FrameDatabase::GetFrame(size_t index) const
+ {
+ AZ_Assert(index < m_frames.size(), "Frame index is out of range!");
+ return m_frames[index];
+ }
+
+ AZStd::vector& FrameDatabase::GetFrames()
+ {
+ return m_frames;
+ }
+
+ const AZStd::vector& FrameDatabase::GetFrames() const
+ {
+ return m_frames;
+ }
+
+ const AZStd::vector& FrameDatabase::GetUsedMotions() const
+ {
+ return m_usedMotions;
+ }
+
+ size_t FrameDatabase::FindFrameIndex(Motion* motion, float playtime) const
+ {
+ auto iterator = m_frameIndexByMotion.find(motion);
+ if (iterator == m_frameIndexByMotion.end())
+ {
+ return InvalidIndex;
+ }
+
+ const AZStd::vector& frameIndices = iterator->second;
+ for (const size_t frameIndex : frameIndices)
+ {
+ const Frame& frame = m_frames[frameIndex];
+ if (playtime >= frame.GetSampleTime() &&
+ frameIndex + 1 < m_frames.size() &&
+ playtime <= m_frames[frameIndex + 1].GetSampleTime())
+ {
+ return frameIndex;
+ }
+ }
+
+ return InvalidIndex;
+ }
+} // namespace EMotionFX::MotionMatching
diff --git a/Gems/MotionMatching/Code/Source/FrameDatabase.h b/Gems/MotionMatching/Code/Source/FrameDatabase.h
new file mode 100644
index 0000000000..c5258e1b39
--- /dev/null
+++ b/Gems/MotionMatching/Code/Source/FrameDatabase.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include