Fix : 모캡 잔떨림 관련한 대부분 관련 이슈 제거
This commit is contained in:
parent
86b743a8a1
commit
b14c3f6f40
@ -86,19 +86,354 @@ ModelImporter:
|
|||||||
skeleton:
|
skeleton:
|
||||||
- name: BaseAvatar - OptiTrack 5 bone(Clone)
|
- name: BaseAvatar - OptiTrack 5 bone(Clone)
|
||||||
parentName:
|
parentName:
|
||||||
position: {x: 0, y: 0, z: 0}
|
|
||||||
rotation: {x: 0, y: 0, z: 0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_Root
|
|
||||||
parentName: BaseAvatar - OptiTrack 5 bone(Clone)
|
|
||||||
position: {x: -0, y: 0, z: 0}
|
position: {x: -0, y: 0, z: 0}
|
||||||
rotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067}
|
rotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067}
|
||||||
scale: {x: 1, y: 1, z: 1}
|
scale: {x: 1, y: 1, z: 1}
|
||||||
- name: 001_Hips
|
- name: 001_Hips
|
||||||
parentName: 001_Root
|
parentName: BaseAvatar - OptiTrack 5 bone(Clone)
|
||||||
position: {x: -0, y: -0.00000014102463, z: 0.865603}
|
position: {x: -0, y: -0.00000014102463, z: 0.865603}
|
||||||
rotation: {x: 0.7071068, y: 0, z: -0, w: 0.7071067}
|
rotation: {x: 0.7071068, y: 0, z: -0, w: 0.7071067}
|
||||||
scale: {x: 1, y: 1, z: 1}
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_Spine
|
||||||
|
parentName: 001_Hips
|
||||||
|
position: {x: -0, y: 0.03325814, z: 0}
|
||||||
|
rotation: {x: 0.0888559, y: 0, z: -0, w: 0.9960445}
|
||||||
|
scale: {x: 1, y: 0.99999994, z: 0.99999994}
|
||||||
|
- name: 001_Spine1
|
||||||
|
parentName: 001_Spine
|
||||||
|
position: {x: -0, y: 0.059864596, z: 0}
|
||||||
|
rotation: {x: 0.0035778934, y: 0, z: -0, w: 0.9999936}
|
||||||
|
scale: {x: 1, y: 0.99999994, z: 1}
|
||||||
|
- name: 001_Spine2
|
||||||
|
parentName: 001_Spine1
|
||||||
|
position: {x: -0, y: 0.066516146, z: 0.000000011175871}
|
||||||
|
rotation: {x: -0.09237056, y: 0, z: -0, w: 0.9957247}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_Spine3
|
||||||
|
parentName: 001_Spine2
|
||||||
|
position: {x: -0, y: 0.07815656, z: 7.712515e-10}
|
||||||
|
rotation: {x: -0.049721405, y: 0, z: -0, w: 0.99876314}
|
||||||
|
scale: {x: 0.99999994, y: 0.99999994, z: 1}
|
||||||
|
- name: 001_Spine4
|
||||||
|
parentName: 001_Spine3
|
||||||
|
position: {x: -0, y: 0.17460515, z: -0.0000000069849193}
|
||||||
|
rotation: {x: -0.024432134, y: 0, z: -0, w: 0.9997015}
|
||||||
|
scale: {x: 1, y: 1, z: 0.9999999}
|
||||||
|
- name: 001_Neck
|
||||||
|
parentName: 001_Spine4
|
||||||
|
position: {x: -0, y: 0.10975203, z: 0.010808894}
|
||||||
|
rotation: {x: 0.13785088, y: 0, z: -0, w: 0.990453}
|
||||||
|
scale: {x: 1, y: 0.9999999, z: 0.9999999}
|
||||||
|
- name: 001_Neck1
|
||||||
|
parentName: 001_Neck
|
||||||
|
position: {x: -0, y: 0.0740802, z: -9.313226e-10}
|
||||||
|
rotation: {x: 0.000000052154068, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 0.99999994, z: 1}
|
||||||
|
- name: 001_Head
|
||||||
|
parentName: 001_Neck1
|
||||||
|
position: {x: -0, y: 0.07597939, z: -0.000000016763806}
|
||||||
|
rotation: {x: -0.10018798, y: 0, z: -0, w: 0.99496853}
|
||||||
|
scale: {x: 1, y: 1, z: 0.99999994}
|
||||||
|
- name: 001_HeadEnd
|
||||||
|
parentName: 001_Head
|
||||||
|
position: {x: -0, y: 0.22000016, z: -0.000000004656613}
|
||||||
|
rotation: {x: -0.000000018626451, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_HeadEnd_end
|
||||||
|
parentName: 001_HeadEnd
|
||||||
|
position: {x: -0, y: 0.22000012, z: 0}
|
||||||
|
rotation: {x: 0, y: -0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_LeftShoulder
|
||||||
|
parentName: 001_Spine4
|
||||||
|
position: {x: -0.0358696, y: 0.045248758, z: -0.0049734665}
|
||||||
|
rotation: {x: -0.00000016391277, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_LeftArm
|
||||||
|
parentName: 001_LeftShoulder
|
||||||
|
position: {x: -0.134977, y: 0.000000013154931, z: 0.000000019557774}
|
||||||
|
rotation: {x: 0.000000059604645, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 0.99999994, y: 1, z: 1}
|
||||||
|
- name: 001_LeftForeArm
|
||||||
|
parentName: 001_LeftArm
|
||||||
|
position: {x: -0.273732, y: 0.000000011816155, z: -0.000000006519258}
|
||||||
|
rotation: {x: 0.0000000037252903, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_LeftHand
|
||||||
|
parentName: 001_LeftForeArm
|
||||||
|
position: {x: -0.19546905, y: 0.000000011990778, z: -0.000000008381903}
|
||||||
|
rotation: {x: -0.00000008195639, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_LeftHandThumb1
|
||||||
|
parentName: 001_LeftHand
|
||||||
|
position: {x: -0.018752277, y: -0.021309385, z: 0.029833077}
|
||||||
|
rotation: {x: 0.45188782, y: 0.3447067, z: -0.19831167, w: 0.7985282}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_LeftHandThumb2
|
||||||
|
parentName: 001_LeftHandThumb1
|
||||||
|
position: {x: -0.02832238, y: 0.000000027939677, z: -0.000000055909595}
|
||||||
|
rotation: {x: -0.000000834465, y: -0.0000023841858, z: 0.028025687, w: 0.9996072}
|
||||||
|
scale: {x: 1, y: 0.99999994, z: 1}
|
||||||
|
- name: 001_LeftHandThumb3
|
||||||
|
parentName: 001_LeftHandThumb2
|
||||||
|
position: {x: -0.024207503, y: -0.000000015943257, z: -0.0000000066128223}
|
||||||
|
rotation: {x: 0.0000014528632, y: 0.00000007765939, z: 9.01501e-14, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_LThumb3End
|
||||||
|
parentName: 001_LeftHandThumb3
|
||||||
|
position: {x: -0.026628096, y: -0.0000000408308, z: -0.000000017800573}
|
||||||
|
rotation: {x: 0.000000014901161, y: 1.4210855e-13, z: -1.4654944e-14, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_LThumb3End_end
|
||||||
|
parentName: 001_LThumb3End
|
||||||
|
position: {x: -0, y: 0.026628118, z: 0}
|
||||||
|
rotation: {x: 0, y: -0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_LeftHandIndex1
|
||||||
|
parentName: 001_LeftHand
|
||||||
|
position: {x: -0.07671362, y: 0.000000024912879, z: 0.029833097}
|
||||||
|
rotation: {x: 0.087155744, y: 0, z: -0, w: 0.9961947}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_LeftHandIndex2
|
||||||
|
parentName: 001_LeftHandIndex1
|
||||||
|
position: {x: -0.042618692, y: -0.0000000088475645, z: -0.0000000018626451}
|
||||||
|
rotation: {x: 0.000000058207664, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 0.99999994, z: 1}
|
||||||
|
- name: 001_LeftHandIndex3
|
||||||
|
parentName: 001_LeftHandIndex2
|
||||||
|
position: {x: -0.021309257, y: -0.0000000060535967, z: -9.313226e-10}
|
||||||
|
rotation: {x: -0.000000041443855, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_LIndex3End
|
||||||
|
parentName: 001_LeftHandIndex3
|
||||||
|
position: {x: -0.023440301, y: -0.000000007916242, z: -9.313226e-10}
|
||||||
|
rotation: {x: -4.656613e-10, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_LIndex3End_end
|
||||||
|
parentName: 001_LIndex3End
|
||||||
|
position: {x: -0, y: 0.023440227, z: 0}
|
||||||
|
rotation: {x: 0, y: -0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_LeftHandMiddle1
|
||||||
|
parentName: 001_LeftHand
|
||||||
|
position: {x: -0.07671362, y: 0.00000009732321, z: 0.009887521}
|
||||||
|
rotation: {x: 0.000000067055225, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 0.99999994, z: 1}
|
||||||
|
- name: 001_LeftHandMiddle2
|
||||||
|
parentName: 001_LeftHandMiddle1
|
||||||
|
position: {x: -0.046880484, y: -0.000000022235326, z: 0.000000010244548}
|
||||||
|
rotation: {x: -0.000000040978193, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_LeftHandMiddle3
|
||||||
|
parentName: 001_LeftHandMiddle2
|
||||||
|
position: {x: -0.025571287, y: 0.00000009633368, z: 0.0000000121071935}
|
||||||
|
rotation: {x: -0.000000048428774, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_LMiddle3End
|
||||||
|
parentName: 001_LeftHandMiddle3
|
||||||
|
position: {x: -0.028128326, y: 0.00000009551877, z: 0.000000014901161}
|
||||||
|
rotation: {x: 0.0000000037252903, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_LMiddle3End_end
|
||||||
|
parentName: 001_LMiddle3End
|
||||||
|
position: {x: -0, y: 0.028128315, z: 0}
|
||||||
|
rotation: {x: 0, y: -0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_LeftHandRing1
|
||||||
|
parentName: 001_LeftHand
|
||||||
|
position: {x: -0.07245177, y: -0.00000006821938, z: -0.009887559}
|
||||||
|
rotation: {x: 0.000000115484, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_LeftHandRing2
|
||||||
|
parentName: 001_LeftHandRing1
|
||||||
|
position: {x: -0.04261875, y: 0.000000047963113, z: 0.000000013038516}
|
||||||
|
rotation: {x: -0.0000000037252903, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_LeftHandRing3
|
||||||
|
parentName: 001_LeftHandRing2
|
||||||
|
position: {x: -0.021309197, y: 0.000000047730282, z: 0.000000031664968}
|
||||||
|
rotation: {x: 0.00000033527613, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_LRing3End
|
||||||
|
parentName: 001_LeftHandRing3
|
||||||
|
position: {x: -0.023440242, y: 0.00000015622936, z: 0.000000018626451}
|
||||||
|
rotation: {x: -0.000000007450581, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_LRing3End_end
|
||||||
|
parentName: 001_LRing3End
|
||||||
|
position: {x: -0, y: 0.02344036, z: 0}
|
||||||
|
rotation: {x: 0, y: -0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_LeftHandPinky1
|
||||||
|
parentName: 001_LeftHand
|
||||||
|
position: {x: -0.06818998, y: 0.00000012246892, z: -0.0298331}
|
||||||
|
rotation: {x: -0.08715575, y: 0, z: -0, w: 0.9961947}
|
||||||
|
scale: {x: 1, y: 1.0000001, z: 0.99999994}
|
||||||
|
- name: 001_LeftHandPinky2
|
||||||
|
parentName: 001_LeftHandPinky1
|
||||||
|
position: {x: -0.03409493, y: 0.00000008754432, z: -0.000000044703484}
|
||||||
|
rotation: {x: 0.0000005662441, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_LeftHandPinky3
|
||||||
|
parentName: 001_LeftHandPinky2
|
||||||
|
position: {x: -0.017047465, y: 0.00000005122274, z: -0.0000000037252903}
|
||||||
|
rotation: {x: -0.000000692904, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_LPinky3End
|
||||||
|
parentName: 001_LeftHandPinky3
|
||||||
|
position: {x: -0.018752158, y: 0.00000009872019, z: -0.000000048428774}
|
||||||
|
rotation: {x: 0.000000014901161, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_LPinky3End_end
|
||||||
|
parentName: 001_LPinky3End
|
||||||
|
position: {x: -0, y: 0.018752106, z: 0}
|
||||||
|
rotation: {x: 0, y: -0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_RightShoulder
|
||||||
|
parentName: 001_Spine4
|
||||||
|
position: {x: 0.0358696, y: 0.045248758, z: -0.0049734665}
|
||||||
|
rotation: {x: -0.00000016391277, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_RightArm
|
||||||
|
parentName: 001_RightShoulder
|
||||||
|
position: {x: 0.134977, y: 0.000000013154931, z: 0.000000019557774}
|
||||||
|
rotation: {x: 0.000000059604645, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 0.99999994, y: 1, z: 1}
|
||||||
|
- name: 001_RightForeArm
|
||||||
|
parentName: 001_RightArm
|
||||||
|
position: {x: 0.273732, y: 0.000000011816155, z: -0.000000006519258}
|
||||||
|
rotation: {x: 0.000000007450581, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 0.99999994, z: 1}
|
||||||
|
- name: 001_RightHand
|
||||||
|
parentName: 001_RightForeArm
|
||||||
|
position: {x: 0.19546905, y: 0.00000013131648, z: -0.000000008381903}
|
||||||
|
rotation: {x: -0.000000078231096, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_RightHandThumb1
|
||||||
|
parentName: 001_RightHand
|
||||||
|
position: {x: 0.018752277, y: -0.021309385, z: 0.029833062}
|
||||||
|
rotation: {x: 0.4518857, y: -0.3447039, z: 0.1983145, w: 0.7985298}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_RightHandThumb2
|
||||||
|
parentName: 001_RightHandThumb1
|
||||||
|
position: {x: 0.028322378, y: -0.000000031664968, z: 0.000000053137}
|
||||||
|
rotation: {x: -0.0000018179417, y: -0.0000015795231, z: -0.028029457, w: 0.99960715}
|
||||||
|
scale: {x: 1.0000001, y: 1, z: 1}
|
||||||
|
- name: 001_RightHandThumb3
|
||||||
|
parentName: 001_RightHandThumb2
|
||||||
|
position: {x: 0.024207383, y: -0.000000059786174, z: -0.000000082027555}
|
||||||
|
rotation: {x: 0.0000014454124, y: -0.00000007765938, z: -9.8754345e-14, w: 1}
|
||||||
|
scale: {x: 1, y: 1.0000001, z: 1.0000001}
|
||||||
|
- name: 001_RThumb3End
|
||||||
|
parentName: 001_RightHandThumb3
|
||||||
|
position: {x: 0.026628036, y: -0.000000084079474, z: -0.00000003786181}
|
||||||
|
rotation: {x: -8.285039e-15, y: -1.2789769e-13, z: 5.162537e-15, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_RThumb3End_end
|
||||||
|
parentName: 001_RThumb3End
|
||||||
|
position: {x: -0, y: 0.026628118, z: 0}
|
||||||
|
rotation: {x: 0, y: -0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_RightHandIndex1
|
||||||
|
parentName: 001_RightHand
|
||||||
|
position: {x: 0.07671362, y: -0.00000009406358, z: 0.029833067}
|
||||||
|
rotation: {x: 0.08715574, y: 0, z: -0, w: 0.9961947}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_RightHandIndex2
|
||||||
|
parentName: 001_RightHandIndex1
|
||||||
|
position: {x: 0.04261881, y: -0.0000000088475645, z: 0.0000000027939677}
|
||||||
|
rotation: {x: 0.000000058673326, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 0.99999994, z: 1}
|
||||||
|
- name: 001_RightHandIndex3
|
||||||
|
parentName: 001_RightHandIndex2
|
||||||
|
position: {x: 0.021309316, y: -0.00000012526289, z: 0.000000004656613}
|
||||||
|
rotation: {x: -0.000000040512532, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_RIndex3End
|
||||||
|
parentName: 001_RightHandIndex3
|
||||||
|
position: {x: 0.023440242, y: -0.00000012712553, z: 0.000000004656613}
|
||||||
|
rotation: {x: 4.656613e-10, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_RIndex3End_end
|
||||||
|
parentName: 001_RIndex3End
|
||||||
|
position: {x: -0, y: 0.023440227, z: 0}
|
||||||
|
rotation: {x: 0, y: -0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_RightHandMiddle1
|
||||||
|
parentName: 001_RightHand
|
||||||
|
position: {x: 0.07671362, y: -0.00000002188608, z: 0.009887507}
|
||||||
|
rotation: {x: 0.000000059604645, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 0.99999994, z: 1}
|
||||||
|
- name: 001_RightHandMiddle2
|
||||||
|
parentName: 001_RightHandMiddle1
|
||||||
|
position: {x: 0.046880543, y: 0.00000009697396, z: -0.0000000044237822}
|
||||||
|
rotation: {x: -0.000000052154064, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_RightHandMiddle3
|
||||||
|
parentName: 001_RightHandMiddle2
|
||||||
|
position: {x: 0.025571287, y: -0.00000002287561, z: -0.000000002561137}
|
||||||
|
rotation: {x: -0.000000052154064, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_RMiddle3End
|
||||||
|
parentName: 001_RightHandMiddle3
|
||||||
|
position: {x: 0.028128386, y: -0.000000023690518, z: -0.0000000146683306}
|
||||||
|
rotation: {x: 0, y: -0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_RMiddle3End_end
|
||||||
|
parentName: 001_RMiddle3End
|
||||||
|
position: {x: -0, y: 0.028128315, z: 0}
|
||||||
|
rotation: {x: 0, y: -0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_RightHandRing1
|
||||||
|
parentName: 001_RightHand
|
||||||
|
position: {x: 0.07245177, y: -0.00000018742867, z: -0.009887574}
|
||||||
|
rotation: {x: 0.00000010803342, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_RightHandRing2
|
||||||
|
parentName: 001_RightHandRing1
|
||||||
|
position: {x: 0.042618692, y: 0.000000047963113, z: -0.0000000018626451}
|
||||||
|
rotation: {x: -0.000000007450581, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_RightHandRing3
|
||||||
|
parentName: 001_RightHandRing2
|
||||||
|
position: {x: 0.021309316, y: 0.000000047730282, z: 0.0000000018626451}
|
||||||
|
rotation: {x: 0.00000032782555, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_RRing3End
|
||||||
|
parentName: 001_RightHandRing3
|
||||||
|
position: {x: 0.023440242, y: 0.000000037020072, z: -0.000000013038516}
|
||||||
|
rotation: {x: -0.000000011175871, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_RRing3End_end
|
||||||
|
parentName: 001_RRing3End
|
||||||
|
position: {x: -0, y: 0.02344036, z: 0}
|
||||||
|
rotation: {x: 0, y: -0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_RightHandPinky1
|
||||||
|
parentName: 001_RightHand
|
||||||
|
position: {x: 0.06818998, y: 0.0000000027939677, z: -0.029833127}
|
||||||
|
rotation: {x: -0.08715576, y: 0, z: -0, w: 0.9961947}
|
||||||
|
scale: {x: 1, y: 1.0000001, z: 0.99999994}
|
||||||
|
- name: 001_RightHandPinky2
|
||||||
|
parentName: 001_RightHandPinky1
|
||||||
|
position: {x: 0.03409493, y: -0.000000029802322, z: -0.000000011175871}
|
||||||
|
rotation: {x: 0.0000005736947, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_RightHandPinky3
|
||||||
|
parentName: 001_RightHandPinky2
|
||||||
|
position: {x: 0.017047405, y: 0.000000053085387, z: -0.000000033527613}
|
||||||
|
rotation: {x: -0.00000068545336, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1.0000001, z: 1.0000001}
|
||||||
|
- name: 001_RPinky3End
|
||||||
|
parentName: 001_RightHandPinky3
|
||||||
|
position: {x: 0.018752217, y: -0.000000018626451, z: -0.000000022351742}
|
||||||
|
rotation: {x: 0.000000014901161, y: 0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
|
- name: 001_RPinky3End_end
|
||||||
|
parentName: 001_RPinky3End
|
||||||
|
position: {x: -0, y: 0.018752106, z: 0}
|
||||||
|
rotation: {x: 0, y: -0, z: -0, w: 1}
|
||||||
|
scale: {x: 1, y: 1, z: 1}
|
||||||
- name: 001_LeftUpLeg
|
- name: 001_LeftUpLeg
|
||||||
parentName: 001_Hips
|
parentName: 001_Hips
|
||||||
position: {x: -0.0897235, y: 3.3639758e-14, z: 0}
|
position: {x: -0.0897235, y: 3.3639758e-14, z: 0}
|
||||||
@ -159,346 +494,6 @@ ModelImporter:
|
|||||||
position: {x: -0, y: 0.043999996, z: 0}
|
position: {x: -0, y: 0.043999996, z: 0}
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
rotation: {x: 0, y: -0, z: -0, w: 1}
|
||||||
scale: {x: 1, y: 1, z: 1}
|
scale: {x: 1, y: 1, z: 1}
|
||||||
- name: 001_Spine
|
|
||||||
parentName: 001_Hips
|
|
||||||
position: {x: -0, y: 0.03325814, z: 0}
|
|
||||||
rotation: {x: 0.0888559, y: 0, z: -0, w: 0.9960445}
|
|
||||||
scale: {x: 1, y: 0.99999994, z: 0.99999994}
|
|
||||||
- name: 001_Spine1
|
|
||||||
parentName: 001_Spine
|
|
||||||
position: {x: -0, y: 0.059864596, z: 0}
|
|
||||||
rotation: {x: 0.0035778934, y: 0, z: -0, w: 0.9999936}
|
|
||||||
scale: {x: 1, y: 0.99999994, z: 1}
|
|
||||||
- name: 001_Spine2
|
|
||||||
parentName: 001_Spine1
|
|
||||||
position: {x: -0, y: 0.066516146, z: 0.000000011175871}
|
|
||||||
rotation: {x: -0.09237056, y: 0, z: -0, w: 0.9957247}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_Spine3
|
|
||||||
parentName: 001_Spine2
|
|
||||||
position: {x: -0, y: 0.07815656, z: 7.712515e-10}
|
|
||||||
rotation: {x: -0.049721405, y: 0, z: -0, w: 0.99876314}
|
|
||||||
scale: {x: 0.99999994, y: 0.99999994, z: 1}
|
|
||||||
- name: 001_Spine4
|
|
||||||
parentName: 001_Spine3
|
|
||||||
position: {x: -0, y: 0.17460515, z: -0.0000000069849193}
|
|
||||||
rotation: {x: -0.024432134, y: 0, z: -0, w: 0.9997015}
|
|
||||||
scale: {x: 1, y: 1, z: 0.9999999}
|
|
||||||
- name: 001_LeftShoulder
|
|
||||||
parentName: 001_Spine4
|
|
||||||
position: {x: -0.0358696, y: 0.045248758, z: -0.0049734665}
|
|
||||||
rotation: {x: -0.00000016391277, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_LeftArm
|
|
||||||
parentName: 001_LeftShoulder
|
|
||||||
position: {x: -0.134977, y: 0.000000013154931, z: 0.000000019557774}
|
|
||||||
rotation: {x: 0.000000059604645, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 0.99999994, y: 1, z: 1}
|
|
||||||
- name: 001_LeftForeArm
|
|
||||||
parentName: 001_LeftArm
|
|
||||||
position: {x: -0.273732, y: 0.000000011816155, z: -0.000000006519258}
|
|
||||||
rotation: {x: 0.0000000037252903, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_LeftHand
|
|
||||||
parentName: 001_LeftForeArm
|
|
||||||
position: {x: -0.19546905, y: 0.000000011990778, z: -0.000000008381903}
|
|
||||||
rotation: {x: -0.00000008195639, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_LeftHandIndex1
|
|
||||||
parentName: 001_LeftHand
|
|
||||||
position: {x: -0.07671362, y: 0.000000024912879, z: 0.029833097}
|
|
||||||
rotation: {x: 0.087155744, y: 0, z: -0, w: 0.9961947}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_LeftHandIndex2
|
|
||||||
parentName: 001_LeftHandIndex1
|
|
||||||
position: {x: -0.042618692, y: -0.0000000088475645, z: -0.0000000018626451}
|
|
||||||
rotation: {x: 0.000000058207664, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 0.99999994, z: 1}
|
|
||||||
- name: 001_LeftHandIndex3
|
|
||||||
parentName: 001_LeftHandIndex2
|
|
||||||
position: {x: -0.021309257, y: -0.0000000060535967, z: -9.313226e-10}
|
|
||||||
rotation: {x: -0.000000041443855, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_LIndex3End
|
|
||||||
parentName: 001_LeftHandIndex3
|
|
||||||
position: {x: -0.023440301, y: -0.000000007916242, z: -9.313226e-10}
|
|
||||||
rotation: {x: -4.656613e-10, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_LIndex3End_end
|
|
||||||
parentName: 001_LIndex3End
|
|
||||||
position: {x: -0, y: 0.023440227, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_LeftHandMiddle1
|
|
||||||
parentName: 001_LeftHand
|
|
||||||
position: {x: -0.07671362, y: 0.00000009732321, z: 0.009887521}
|
|
||||||
rotation: {x: 0.000000067055225, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 0.99999994, z: 1}
|
|
||||||
- name: 001_LeftHandMiddle2
|
|
||||||
parentName: 001_LeftHandMiddle1
|
|
||||||
position: {x: -0.046880484, y: -0.000000022235326, z: 0.000000010244548}
|
|
||||||
rotation: {x: -0.000000040978193, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_LeftHandMiddle3
|
|
||||||
parentName: 001_LeftHandMiddle2
|
|
||||||
position: {x: -0.025571287, y: 0.00000009633368, z: 0.0000000121071935}
|
|
||||||
rotation: {x: -0.000000048428774, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_LMiddle3End
|
|
||||||
parentName: 001_LeftHandMiddle3
|
|
||||||
position: {x: -0.028128326, y: 0.00000009551877, z: 0.000000014901161}
|
|
||||||
rotation: {x: 0.0000000037252903, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_LMiddle3End_end
|
|
||||||
parentName: 001_LMiddle3End
|
|
||||||
position: {x: -0, y: 0.028128315, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_LeftHandPinky1
|
|
||||||
parentName: 001_LeftHand
|
|
||||||
position: {x: -0.06818998, y: 0.00000012246892, z: -0.0298331}
|
|
||||||
rotation: {x: -0.08715575, y: 0, z: -0, w: 0.9961947}
|
|
||||||
scale: {x: 1, y: 1.0000001, z: 0.99999994}
|
|
||||||
- name: 001_LeftHandPinky2
|
|
||||||
parentName: 001_LeftHandPinky1
|
|
||||||
position: {x: -0.03409493, y: 0.00000008754432, z: -0.000000044703484}
|
|
||||||
rotation: {x: 0.0000005662441, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_LeftHandPinky3
|
|
||||||
parentName: 001_LeftHandPinky2
|
|
||||||
position: {x: -0.017047465, y: 0.00000005122274, z: -0.0000000037252903}
|
|
||||||
rotation: {x: -0.000000692904, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_LPinky3End
|
|
||||||
parentName: 001_LeftHandPinky3
|
|
||||||
position: {x: -0.018752158, y: 0.00000009872019, z: -0.000000048428774}
|
|
||||||
rotation: {x: 0.000000014901161, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_LPinky3End_end
|
|
||||||
parentName: 001_LPinky3End
|
|
||||||
position: {x: -0, y: 0.018752106, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_LeftHandRing1
|
|
||||||
parentName: 001_LeftHand
|
|
||||||
position: {x: -0.07245177, y: -0.00000006821938, z: -0.009887559}
|
|
||||||
rotation: {x: 0.000000115484, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_LeftHandRing2
|
|
||||||
parentName: 001_LeftHandRing1
|
|
||||||
position: {x: -0.04261875, y: 0.000000047963113, z: 0.000000013038516}
|
|
||||||
rotation: {x: -0.0000000037252903, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_LeftHandRing3
|
|
||||||
parentName: 001_LeftHandRing2
|
|
||||||
position: {x: -0.021309197, y: 0.000000047730282, z: 0.000000031664968}
|
|
||||||
rotation: {x: 0.00000033527613, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_LRing3End
|
|
||||||
parentName: 001_LeftHandRing3
|
|
||||||
position: {x: -0.023440242, y: 0.00000015622936, z: 0.000000018626451}
|
|
||||||
rotation: {x: -0.000000007450581, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_LRing3End_end
|
|
||||||
parentName: 001_LRing3End
|
|
||||||
position: {x: -0, y: 0.02344036, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_LeftHandThumb1
|
|
||||||
parentName: 001_LeftHand
|
|
||||||
position: {x: -0.018752277, y: -0.021309385, z: 0.029833077}
|
|
||||||
rotation: {x: 0.4072523, y: 0.34298575, z: 0.23624216, w: 0.81283206}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_LeftHandThumb2
|
|
||||||
parentName: 001_LeftHandThumb1
|
|
||||||
position: {x: -0.02832238, y: 0.000000027939677, z: -0.000000055909595}
|
|
||||||
rotation: {x: 0, y: 0, z: 0, w: 1}
|
|
||||||
scale: {x: 1, y: 0.99999994, z: 1}
|
|
||||||
- name: 001_LeftHandThumb3
|
|
||||||
parentName: 001_LeftHandThumb2
|
|
||||||
position: {x: -0.024207503, y: -0.000000015943257, z: -0.0000000066128223}
|
|
||||||
rotation: {x: 0.0000014528632, y: 0.00000007765939, z: 9.01501e-14, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_LThumb3End
|
|
||||||
parentName: 001_LeftHandThumb3
|
|
||||||
position: {x: -0.026628096, y: -0.0000000408308, z: -0.000000017800573}
|
|
||||||
rotation: {x: 0.000000014901161, y: 1.4210855e-13, z: -1.4654944e-14, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_LThumb3End_end
|
|
||||||
parentName: 001_LThumb3End
|
|
||||||
position: {x: -0, y: 0.026628118, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_Neck
|
|
||||||
parentName: 001_Spine4
|
|
||||||
position: {x: -0, y: 0.10975203, z: 0.010808894}
|
|
||||||
rotation: {x: 0.13785088, y: 0, z: -0, w: 0.990453}
|
|
||||||
scale: {x: 1, y: 0.9999999, z: 0.9999999}
|
|
||||||
- name: 001_Neck1
|
|
||||||
parentName: 001_Neck
|
|
||||||
position: {x: -0, y: 0.0740802, z: -9.313226e-10}
|
|
||||||
rotation: {x: 0.000000052154068, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 0.99999994, z: 1}
|
|
||||||
- name: 001_Head
|
|
||||||
parentName: 001_Neck1
|
|
||||||
position: {x: -0, y: 0.07597939, z: -0.000000016763806}
|
|
||||||
rotation: {x: -0.10018798, y: 0, z: -0, w: 0.99496853}
|
|
||||||
scale: {x: 1, y: 1, z: 0.99999994}
|
|
||||||
- name: 001_HeadEnd
|
|
||||||
parentName: 001_Head
|
|
||||||
position: {x: -0, y: 0.22000016, z: -0.000000004656613}
|
|
||||||
rotation: {x: -0.000000018626451, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_HeadEnd_end
|
|
||||||
parentName: 001_HeadEnd
|
|
||||||
position: {x: -0, y: 0.22000012, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_RightShoulder
|
|
||||||
parentName: 001_Spine4
|
|
||||||
position: {x: 0.0358696, y: 0.045248758, z: -0.0049734665}
|
|
||||||
rotation: {x: -0.00000016391277, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_RightArm
|
|
||||||
parentName: 001_RightShoulder
|
|
||||||
position: {x: 0.134977, y: 0.000000013154931, z: 0.000000019557774}
|
|
||||||
rotation: {x: 0.000000059604645, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 0.99999994, y: 1, z: 1}
|
|
||||||
- name: 001_RightForeArm
|
|
||||||
parentName: 001_RightArm
|
|
||||||
position: {x: 0.273732, y: 0.000000011816155, z: -0.000000006519258}
|
|
||||||
rotation: {x: 0.000000007450581, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 0.99999994, z: 1}
|
|
||||||
- name: 001_RightHand
|
|
||||||
parentName: 001_RightForeArm
|
|
||||||
position: {x: 0.19546905, y: 0.00000013131648, z: -0.000000008381903}
|
|
||||||
rotation: {x: -0.000000078231096, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_RightHandIndex1
|
|
||||||
parentName: 001_RightHand
|
|
||||||
position: {x: 0.07671362, y: -0.00000009406358, z: 0.029833067}
|
|
||||||
rotation: {x: 0.08715574, y: 0, z: -0, w: 0.9961947}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_RightHandIndex2
|
|
||||||
parentName: 001_RightHandIndex1
|
|
||||||
position: {x: 0.04261881, y: -0.0000000088475645, z: 0.0000000027939677}
|
|
||||||
rotation: {x: 0.000000058673326, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 0.99999994, z: 1}
|
|
||||||
- name: 001_RightHandIndex3
|
|
||||||
parentName: 001_RightHandIndex2
|
|
||||||
position: {x: 0.021309316, y: -0.00000012526289, z: 0.000000004656613}
|
|
||||||
rotation: {x: -0.000000040512532, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_RIndex3End
|
|
||||||
parentName: 001_RightHandIndex3
|
|
||||||
position: {x: 0.023440242, y: -0.00000012712553, z: 0.000000004656613}
|
|
||||||
rotation: {x: 4.656613e-10, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_RIndex3End_end
|
|
||||||
parentName: 001_RIndex3End
|
|
||||||
position: {x: -0, y: 0.023440227, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_RightHandMiddle1
|
|
||||||
parentName: 001_RightHand
|
|
||||||
position: {x: 0.07671362, y: -0.00000002188608, z: 0.009887507}
|
|
||||||
rotation: {x: 0.000000059604645, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 0.99999994, z: 1}
|
|
||||||
- name: 001_RightHandMiddle2
|
|
||||||
parentName: 001_RightHandMiddle1
|
|
||||||
position: {x: 0.046880543, y: 0.00000009697396, z: -0.0000000044237822}
|
|
||||||
rotation: {x: -0.000000052154064, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_RightHandMiddle3
|
|
||||||
parentName: 001_RightHandMiddle2
|
|
||||||
position: {x: 0.025571287, y: -0.00000002287561, z: -0.000000002561137}
|
|
||||||
rotation: {x: -0.000000052154064, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_RMiddle3End
|
|
||||||
parentName: 001_RightHandMiddle3
|
|
||||||
position: {x: 0.028128386, y: -0.000000023690518, z: -0.0000000146683306}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_RMiddle3End_end
|
|
||||||
parentName: 001_RMiddle3End
|
|
||||||
position: {x: -0, y: 0.028128315, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_RightHandPinky1
|
|
||||||
parentName: 001_RightHand
|
|
||||||
position: {x: 0.06818998, y: 0.0000000027939677, z: -0.029833127}
|
|
||||||
rotation: {x: -0.08715576, y: 0, z: -0, w: 0.9961947}
|
|
||||||
scale: {x: 1, y: 1.0000001, z: 0.99999994}
|
|
||||||
- name: 001_RightHandPinky2
|
|
||||||
parentName: 001_RightHandPinky1
|
|
||||||
position: {x: 0.03409493, y: -0.000000029802322, z: -0.000000011175871}
|
|
||||||
rotation: {x: 0.0000005736947, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_RightHandPinky3
|
|
||||||
parentName: 001_RightHandPinky2
|
|
||||||
position: {x: 0.017047405, y: 0.000000053085387, z: -0.000000033527613}
|
|
||||||
rotation: {x: -0.00000068545336, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1.0000001, z: 1.0000001}
|
|
||||||
- name: 001_RPinky3End
|
|
||||||
parentName: 001_RightHandPinky3
|
|
||||||
position: {x: 0.018752217, y: -0.000000018626451, z: -0.000000022351742}
|
|
||||||
rotation: {x: 0.000000014901161, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_RPinky3End_end
|
|
||||||
parentName: 001_RPinky3End
|
|
||||||
position: {x: -0, y: 0.018752106, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_RightHandRing1
|
|
||||||
parentName: 001_RightHand
|
|
||||||
position: {x: 0.07245177, y: -0.00000018742867, z: -0.009887574}
|
|
||||||
rotation: {x: 0.00000010803342, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_RightHandRing2
|
|
||||||
parentName: 001_RightHandRing1
|
|
||||||
position: {x: 0.042618692, y: 0.000000047963113, z: -0.0000000018626451}
|
|
||||||
rotation: {x: -0.000000007450581, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_RightHandRing3
|
|
||||||
parentName: 001_RightHandRing2
|
|
||||||
position: {x: 0.021309316, y: 0.000000047730282, z: 0.0000000018626451}
|
|
||||||
rotation: {x: 0.00000032782555, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_RRing3End
|
|
||||||
parentName: 001_RightHandRing3
|
|
||||||
position: {x: 0.023440242, y: 0.000000037020072, z: -0.000000013038516}
|
|
||||||
rotation: {x: -0.000000011175871, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_RRing3End_end
|
|
||||||
parentName: 001_RRing3End
|
|
||||||
position: {x: -0, y: 0.02344036, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_RightHandThumb1
|
|
||||||
parentName: 001_RightHand
|
|
||||||
position: {x: 0.018752277, y: -0.021309385, z: 0.029833062}
|
|
||||||
rotation: {x: 0.4072523, y: -0.34298575, z: -0.23624216, w: 0.81283206}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_RightHandThumb2
|
|
||||||
parentName: 001_RightHandThumb1
|
|
||||||
position: {x: 0.028322378, y: -0.000000031664968, z: 0.000000053137}
|
|
||||||
rotation: {x: 0, y: 0, z: 0, w: 1}
|
|
||||||
scale: {x: 1.0000001, y: 1, z: 1}
|
|
||||||
- name: 001_RightHandThumb3
|
|
||||||
parentName: 001_RightHandThumb2
|
|
||||||
position: {x: 0.024207383, y: -0.000000059786174, z: -0.000000082027555}
|
|
||||||
rotation: {x: 0.0000014454124, y: -0.00000007765938, z: -9.8754345e-14, w: 1}
|
|
||||||
scale: {x: 1, y: 1.0000001, z: 1.0000001}
|
|
||||||
- name: 001_RThumb3End
|
|
||||||
parentName: 001_RightHandThumb3
|
|
||||||
position: {x: 0.026628036, y: -0.000000084079474, z: -0.00000003786181}
|
|
||||||
rotation: {x: -8.285039e-15, y: -1.2789769e-13, z: 5.162537e-15, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: 001_RThumb3End_end
|
|
||||||
parentName: 001_RThumb3End
|
|
||||||
position: {x: -0, y: 0.026628118, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
armTwist: 0.5
|
armTwist: 0.5
|
||||||
foreArmTwist: 0.5
|
foreArmTwist: 0.5
|
||||||
upperLegTwist: 0.5
|
upperLegTwist: 0.5
|
||||||
@ -509,7 +504,7 @@ ModelImporter:
|
|||||||
globalScale: 1
|
globalScale: 1
|
||||||
rootMotionBoneName:
|
rootMotionBoneName:
|
||||||
hasTranslationDoF: 0
|
hasTranslationDoF: 0
|
||||||
hasExtraRoot: 1
|
hasExtraRoot: 0
|
||||||
skeletonHasParents: 1
|
skeletonHasParents: 1
|
||||||
lastHumanDescriptionAvatarSource: {instanceID: 0}
|
lastHumanDescriptionAvatarSource: {instanceID: 0}
|
||||||
autoGenerateAvatarMappingIfUnspecified: 1
|
autoGenerateAvatarMappingIfUnspecified: 1
|
||||||
|
|||||||
BIN
Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar 5bone/BaseAvatar - OptiTrack 5 bone.prefab
(Stored with Git LFS)
vendored
BIN
Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar 5bone/BaseAvatar - OptiTrack 5 bone.prefab
(Stored with Git LFS)
vendored
Binary file not shown.
BIN
Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar 5bone/OptitrackRestPose.asset
(Stored with Git LFS)
vendored
Normal file
BIN
Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar 5bone/OptitrackRestPose.asset
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
@ -1,8 +1,8 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 3d3b7ae32885a034c88552023d1db036
|
guid: 75f2e1a5c10097440b114e4fffcfb1a2
|
||||||
NativeFormatImporter:
|
NativeFormatImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
mainObjectFileID: 2100000
|
mainObjectFileID: 11400000
|
||||||
userData:
|
userData:
|
||||||
assetBundleName:
|
assetBundleName:
|
||||||
assetBundleVariant:
|
assetBundleVariant:
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 4c6874ed36813b048bb2f591a8659061
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
BIN
Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/BaseAvatar - OptiTrack ver 2.fbx
(Stored with Git LFS)
vendored
BIN
Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar ver 2/BaseAvatar - OptiTrack ver 2.fbx
(Stored with Git LFS)
vendored
Binary file not shown.
@ -1,843 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 67637b4ba7aa0214da607e0169e11290
|
|
||||||
ModelImporter:
|
|
||||||
serializedVersion: 24200
|
|
||||||
internalIDToNameTable: []
|
|
||||||
externalObjects: {}
|
|
||||||
materials:
|
|
||||||
materialImportMode: 2
|
|
||||||
materialName: 0
|
|
||||||
materialSearch: 1
|
|
||||||
materialLocation: 1
|
|
||||||
animations:
|
|
||||||
legacyGenerateAnimations: 4
|
|
||||||
bakeSimulation: 0
|
|
||||||
resampleCurves: 1
|
|
||||||
optimizeGameObjects: 0
|
|
||||||
removeConstantScaleCurves: 0
|
|
||||||
motionNodeName:
|
|
||||||
animationImportErrors:
|
|
||||||
animationImportWarnings:
|
|
||||||
animationRetargetingWarnings:
|
|
||||||
animationDoRetargetingWarnings: 0
|
|
||||||
importAnimatedCustomProperties: 0
|
|
||||||
importConstraints: 0
|
|
||||||
animationCompression: 3
|
|
||||||
animationRotationError: 0.5
|
|
||||||
animationPositionError: 0.5
|
|
||||||
animationScaleError: 0.5
|
|
||||||
animationWrapMode: 0
|
|
||||||
extraExposedTransformPaths: []
|
|
||||||
extraUserProperties: []
|
|
||||||
clipAnimations: []
|
|
||||||
isReadable: 0
|
|
||||||
meshes:
|
|
||||||
lODScreenPercentages: []
|
|
||||||
globalScale: 1
|
|
||||||
meshCompression: 0
|
|
||||||
addColliders: 0
|
|
||||||
useSRGBMaterialColor: 1
|
|
||||||
sortHierarchyByName: 1
|
|
||||||
importPhysicalCameras: 1
|
|
||||||
importVisibility: 1
|
|
||||||
importBlendShapes: 1
|
|
||||||
importCameras: 1
|
|
||||||
importLights: 1
|
|
||||||
nodeNameCollisionStrategy: 1
|
|
||||||
fileIdsGeneration: 2
|
|
||||||
swapUVChannels: 0
|
|
||||||
generateSecondaryUV: 0
|
|
||||||
useFileUnits: 1
|
|
||||||
keepQuads: 0
|
|
||||||
weldVertices: 1
|
|
||||||
bakeAxisConversion: 0
|
|
||||||
preserveHierarchy: 0
|
|
||||||
skinWeightsMode: 0
|
|
||||||
maxBonesPerVertex: 4
|
|
||||||
minBoneWeight: 0.001
|
|
||||||
optimizeBones: 1
|
|
||||||
generateMeshLods: 0
|
|
||||||
meshLodGenerationFlags: 0
|
|
||||||
maximumMeshLod: -1
|
|
||||||
meshOptimizationFlags: -1
|
|
||||||
indexFormat: 0
|
|
||||||
secondaryUVAngleDistortion: 8
|
|
||||||
secondaryUVAreaDistortion: 15.000001
|
|
||||||
secondaryUVHardAngle: 88
|
|
||||||
secondaryUVMarginMethod: 1
|
|
||||||
secondaryUVMinLightmapResolution: 40
|
|
||||||
secondaryUVMinObjectScale: 1
|
|
||||||
secondaryUVPackMargin: 4
|
|
||||||
useFileScale: 1
|
|
||||||
strictVertexDataChecks: 0
|
|
||||||
tangentSpace:
|
|
||||||
normalSmoothAngle: 60
|
|
||||||
normalImportMode: 0
|
|
||||||
tangentImportMode: 3
|
|
||||||
normalCalculationMode: 4
|
|
||||||
legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0
|
|
||||||
blendShapeNormalImportMode: 1
|
|
||||||
normalSmoothingSource: 0
|
|
||||||
referencedClips: []
|
|
||||||
importAnimation: 1
|
|
||||||
humanDescription:
|
|
||||||
serializedVersion: 3
|
|
||||||
human:
|
|
||||||
- boneName: Hips
|
|
||||||
humanName: Hips
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: LeftUpLeg
|
|
||||||
humanName: LeftUpperLeg
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: RightUpLeg
|
|
||||||
humanName: RightUpperLeg
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: LeftLeg
|
|
||||||
humanName: LeftLowerLeg
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: RightLeg
|
|
||||||
humanName: RightLowerLeg
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: LeftFoot
|
|
||||||
humanName: LeftFoot
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: RightFoot
|
|
||||||
humanName: RightFoot
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: Spine
|
|
||||||
humanName: Spine
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: Spine1
|
|
||||||
humanName: Chest
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: Neck
|
|
||||||
humanName: Neck
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: Head
|
|
||||||
humanName: Head
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: LeftShoulder
|
|
||||||
humanName: LeftShoulder
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: RightShoulder
|
|
||||||
humanName: RightShoulder
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: LeftArm
|
|
||||||
humanName: LeftUpperArm
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: RightArm
|
|
||||||
humanName: RightUpperArm
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: LeftForeArm
|
|
||||||
humanName: LeftLowerArm
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: RightForeArm
|
|
||||||
humanName: RightLowerArm
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: LeftHand
|
|
||||||
humanName: LeftHand
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: RightHand
|
|
||||||
humanName: RightHand
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: LeftToeBase
|
|
||||||
humanName: LeftToes
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: RightToeBase
|
|
||||||
humanName: RightToes
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: LeftHandThumb1
|
|
||||||
humanName: Left Thumb Proximal
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: LeftHandThumb2
|
|
||||||
humanName: Left Thumb Intermediate
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: LeftHandThumb3
|
|
||||||
humanName: Left Thumb Distal
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: LeftHandIndex1
|
|
||||||
humanName: Left Index Proximal
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: LeftHandIndex2
|
|
||||||
humanName: Left Index Intermediate
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: LeftHandIndex3
|
|
||||||
humanName: Left Index Distal
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: LeftHandMiddle1
|
|
||||||
humanName: Left Middle Proximal
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: LeftHandMiddle2
|
|
||||||
humanName: Left Middle Intermediate
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: LeftHandMiddle3
|
|
||||||
humanName: Left Middle Distal
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: LeftHandRing1
|
|
||||||
humanName: Left Ring Proximal
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: LeftHandRing2
|
|
||||||
humanName: Left Ring Intermediate
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: LeftHandRing3
|
|
||||||
humanName: Left Ring Distal
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: LeftHandPinky1
|
|
||||||
humanName: Left Little Proximal
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: LeftHandPinky2
|
|
||||||
humanName: Left Little Intermediate
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: LeftHandPinky3
|
|
||||||
humanName: Left Little Distal
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: RightHandThumb1
|
|
||||||
humanName: Right Thumb Proximal
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: RightHandThumb2
|
|
||||||
humanName: Right Thumb Intermediate
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: RightHandThumb3
|
|
||||||
humanName: Right Thumb Distal
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: RightHandIndex1
|
|
||||||
humanName: Right Index Proximal
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: RightHandIndex2
|
|
||||||
humanName: Right Index Intermediate
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: RightHandIndex3
|
|
||||||
humanName: Right Index Distal
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: RightHandMiddle1
|
|
||||||
humanName: Right Middle Proximal
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: RightHandMiddle2
|
|
||||||
humanName: Right Middle Intermediate
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: RightHandMiddle3
|
|
||||||
humanName: Right Middle Distal
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: RightHandRing1
|
|
||||||
humanName: Right Ring Proximal
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: RightHandRing2
|
|
||||||
humanName: Right Ring Intermediate
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: RightHandRing3
|
|
||||||
humanName: Right Ring Distal
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: RightHandPinky1
|
|
||||||
humanName: Right Little Proximal
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: RightHandPinky2
|
|
||||||
humanName: Right Little Intermediate
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
- boneName: RightHandPinky3
|
|
||||||
humanName: Right Little Distal
|
|
||||||
limit:
|
|
||||||
min: {x: 0, y: 0, z: 0}
|
|
||||||
max: {x: 0, y: 0, z: 0}
|
|
||||||
value: {x: 0, y: 0, z: 0}
|
|
||||||
length: 0
|
|
||||||
modified: 0
|
|
||||||
skeleton:
|
|
||||||
- name: BaseAvatar - OptiTrack ver 2(Clone)
|
|
||||||
parentName:
|
|
||||||
position: {x: -0, y: 0, z: 0}
|
|
||||||
rotation: {x: 0.000000021855694, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: Hips
|
|
||||||
parentName: BaseAvatar - OptiTrack ver 2(Clone)
|
|
||||||
position: {x: -0, y: 0.75835896, z: 0}
|
|
||||||
rotation: {x: 0.000000059604645, y: 0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: LeftUpLeg
|
|
||||||
parentName: Hips
|
|
||||||
position: {x: -0.091811396, y: 0, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: LeftLeg
|
|
||||||
parentName: LeftUpLeg
|
|
||||||
position: {x: -0, y: -0.29867896, z: -9.094947e-15}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: LeftFoot
|
|
||||||
parentName: LeftLeg
|
|
||||||
position: {x: -0, y: -0.386231, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: LeftToeBase
|
|
||||||
parentName: LeftFoot
|
|
||||||
position: {x: -0, y: -0.0596774, z: 0.137717}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: LToeEnd
|
|
||||||
parentName: LeftToeBase
|
|
||||||
position: {x: -0, y: 0, z: 0.036724567}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: RightUpLeg
|
|
||||||
parentName: Hips
|
|
||||||
position: {x: 0.091811396, y: 0, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: RightLeg
|
|
||||||
parentName: RightUpLeg
|
|
||||||
position: {x: -0, y: -0.29867896, z: -9.094947e-15}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: RightFoot
|
|
||||||
parentName: RightLeg
|
|
||||||
position: {x: -0, y: -0.386231, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: RightToeBase
|
|
||||||
parentName: RightFoot
|
|
||||||
position: {x: -0, y: -0.0596774, z: 0.137717}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: RToeEnd
|
|
||||||
parentName: RightToeBase
|
|
||||||
position: {x: -0, y: 0, z: 0.036724567}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: Spine
|
|
||||||
parentName: Hips
|
|
||||||
position: {x: -0, y: 0.07528534, z: -9.094947e-15}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: Spine1
|
|
||||||
parentName: Spine
|
|
||||||
position: {x: -0, y: 0.25163397, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: LeftShoulder
|
|
||||||
parentName: Spine1
|
|
||||||
position: {x: -0.036669, y: 0.21769409, z: -0.00494359}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: LeftArm
|
|
||||||
parentName: LeftShoulder
|
|
||||||
position: {x: -0.07529169, y: 0, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: LeftForeArm
|
|
||||||
parentName: LeftArm
|
|
||||||
position: {x: -0.30853298, y: 0, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: LeftHand
|
|
||||||
parentName: LeftForeArm
|
|
||||||
position: {x: -0.22326599, y: 0, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: LeftHandIndex1
|
|
||||||
parentName: LeftHand
|
|
||||||
position: {x: -0.078498684, y: 0, z: 0.030527297}
|
|
||||||
rotation: {x: 0.087155685, y: 0, z: -0, w: 0.9961947}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: LeftHandIndex2
|
|
||||||
parentName: LeftHandIndex1
|
|
||||||
position: {x: -0.043610383, y: 0, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: LeftHandIndex3
|
|
||||||
parentName: LeftHandIndex2
|
|
||||||
position: {x: -0.021805191, y: 0, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: LIndex3End
|
|
||||||
parentName: LeftHandIndex3
|
|
||||||
position: {x: -0.020019684, y: 0, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: LeftHandMiddle1
|
|
||||||
parentName: LeftHand
|
|
||||||
position: {x: -0.078498684, y: 0, z: 0.0101176}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: LeftHandMiddle2
|
|
||||||
parentName: LeftHandMiddle1
|
|
||||||
position: {x: -0.047971494, y: 0, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: LeftHandMiddle3
|
|
||||||
parentName: LeftHandMiddle2
|
|
||||||
position: {x: -0.026166229, y: 0, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: LMiddle3End
|
|
||||||
parentName: LeftHandMiddle3
|
|
||||||
position: {x: -0.024023589, y: 0, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: LeftHandPinky1
|
|
||||||
parentName: LeftHand
|
|
||||||
position: {x: -0.069776684, y: 0, z: -0.030527297}
|
|
||||||
rotation: {x: -0.087155685, y: 0, z: -0, w: 0.9961947}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: LeftHandPinky2
|
|
||||||
parentName: LeftHandPinky1
|
|
||||||
position: {x: -0.034888305, y: 0, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: LeftHandPinky3
|
|
||||||
parentName: LeftHandPinky2
|
|
||||||
position: {x: -0.017444229, y: 0, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: LPinky3End
|
|
||||||
parentName: LeftHandPinky3
|
|
||||||
position: {x: -0.016015777, y: 0, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: LeftHandRing1
|
|
||||||
parentName: LeftHand
|
|
||||||
position: {x: -0.07413765, y: 0, z: -0.0101176}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: LeftHandRing2
|
|
||||||
parentName: LeftHandRing1
|
|
||||||
position: {x: -0.043610383, y: 0, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: LeftHandRing3
|
|
||||||
parentName: LeftHandRing2
|
|
||||||
position: {x: -0.021805191, y: 0, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: LRing3End
|
|
||||||
parentName: LeftHandRing3
|
|
||||||
position: {x: -0.020019684, y: 0, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: LeftHandThumb1
|
|
||||||
parentName: LeftHand
|
|
||||||
position: {x: -0.019188613, y: -0.021805115, z: 0.030527297}
|
|
||||||
rotation: {x: 0.4072523, y: 0.34298575, z: 0.23624216, w: 0.81283206}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: LeftHandThumb2
|
|
||||||
parentName: LeftHandThumb1
|
|
||||||
position: {x: -0.028981552, y: 0, z: -0.000000076293944}
|
|
||||||
rotation: {x: -0.000000029802326, y: -0.000001192093, z: 0.028031828, w: 0.999607}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: LeftHandThumb3
|
|
||||||
parentName: LeftHandThumb2
|
|
||||||
position: {x: -0.02477066, y: 0, z: 0}
|
|
||||||
rotation: {x: 0.000000014901161, y: 2.842171e-14, z: -1.4210855e-14, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: LThumb3End
|
|
||||||
parentName: LeftHandThumb3
|
|
||||||
position: {x: -0.022742309, y: 0, z: 0}
|
|
||||||
rotation: {x: 0.000000014901161, y: 2.842171e-14, z: -1.4210855e-14, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: Neck
|
|
||||||
parentName: Spine1
|
|
||||||
position: {x: -0, y: 0.26999587, z: 9.094947e-15}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: Head
|
|
||||||
parentName: Neck
|
|
||||||
position: {x: -0, y: 0.14230804, z: 0.018362299}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: HeadEnd
|
|
||||||
parentName: Head
|
|
||||||
position: {x: -0, y: 0.18362273, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: RightShoulder
|
|
||||||
parentName: Spine1
|
|
||||||
position: {x: 0.036669, y: 0.21769409, z: -0.00494359}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: RightArm
|
|
||||||
parentName: RightShoulder
|
|
||||||
position: {x: 0.07529169, y: 0, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: RightForeArm
|
|
||||||
parentName: RightArm
|
|
||||||
position: {x: 0.30853298, y: 0, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: RightHand
|
|
||||||
parentName: RightForeArm
|
|
||||||
position: {x: 0.22326599, y: 0, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: RightHandIndex1
|
|
||||||
parentName: RightHand
|
|
||||||
position: {x: 0.078498684, y: 0, z: 0.030527297}
|
|
||||||
rotation: {x: 0.087155685, y: 0, z: -0, w: 0.9961947}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: RightHandIndex2
|
|
||||||
parentName: RightHandIndex1
|
|
||||||
position: {x: 0.043610383, y: 0, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: RightHandIndex3
|
|
||||||
parentName: RightHandIndex2
|
|
||||||
position: {x: 0.021805191, y: 0, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: RIndex3End
|
|
||||||
parentName: RightHandIndex3
|
|
||||||
position: {x: 0.020019684, y: 0, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: RightHandMiddle1
|
|
||||||
parentName: RightHand
|
|
||||||
position: {x: 0.078498684, y: 0, z: 0.0101176}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: RightHandMiddle2
|
|
||||||
parentName: RightHandMiddle1
|
|
||||||
position: {x: 0.047971494, y: 0, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: RightHandMiddle3
|
|
||||||
parentName: RightHandMiddle2
|
|
||||||
position: {x: 0.026166229, y: 0, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: RMiddle3End
|
|
||||||
parentName: RightHandMiddle3
|
|
||||||
position: {x: 0.024023589, y: 0, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: RightHandPinky1
|
|
||||||
parentName: RightHand
|
|
||||||
position: {x: 0.069776684, y: 0, z: -0.030527297}
|
|
||||||
rotation: {x: -0.087155685, y: 0, z: -0, w: 0.9961947}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: RightHandPinky2
|
|
||||||
parentName: RightHandPinky1
|
|
||||||
position: {x: 0.034888305, y: 0, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: RightHandPinky3
|
|
||||||
parentName: RightHandPinky2
|
|
||||||
position: {x: 0.017444229, y: 0, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: RPinky3End
|
|
||||||
parentName: RightHandPinky3
|
|
||||||
position: {x: 0.016015777, y: 0, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: RightHandRing1
|
|
||||||
parentName: RightHand
|
|
||||||
position: {x: 0.07413765, y: 0, z: -0.0101176}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: RightHandRing2
|
|
||||||
parentName: RightHandRing1
|
|
||||||
position: {x: 0.043610383, y: 0, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: RightHandRing3
|
|
||||||
parentName: RightHandRing2
|
|
||||||
position: {x: 0.021805191, y: 0, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: RRing3End
|
|
||||||
parentName: RightHandRing3
|
|
||||||
position: {x: 0.020019684, y: 0, z: 0}
|
|
||||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: RightHandThumb1
|
|
||||||
parentName: RightHand
|
|
||||||
position: {x: 0.019188613, y: -0.021805115, z: 0.030527297}
|
|
||||||
rotation: {x: 0.4072523, y: -0.34298575, z: -0.23624216, w: 0.81283206}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: RightHandThumb2
|
|
||||||
parentName: RightHandThumb1
|
|
||||||
position: {x: 0.028981552, y: 0, z: -0.000000076293944}
|
|
||||||
rotation: {x: -0.000000029802326, y: 0.000001192093, z: -0.028031828, w: 0.999607}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: RightHandThumb3
|
|
||||||
parentName: RightHandThumb2
|
|
||||||
position: {x: 0.02477066, y: 0, z: 0}
|
|
||||||
rotation: {x: 0.000000014901161, y: -2.842171e-14, z: 1.4210855e-14, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
- name: RThumb3End
|
|
||||||
parentName: RightHandThumb3
|
|
||||||
position: {x: 0.022742309, y: 0, z: 0}
|
|
||||||
rotation: {x: 0.000000014901161, y: -2.842171e-14, z: 1.4210855e-14, w: 1}
|
|
||||||
scale: {x: 1, y: 1, z: 1}
|
|
||||||
armTwist: 0.5
|
|
||||||
foreArmTwist: 0.5
|
|
||||||
upperLegTwist: 0.5
|
|
||||||
legTwist: 0.5
|
|
||||||
armStretch: 0.05
|
|
||||||
legStretch: 0.05
|
|
||||||
feetSpacing: 0
|
|
||||||
globalScale: 1
|
|
||||||
rootMotionBoneName:
|
|
||||||
hasTranslationDoF: 0
|
|
||||||
hasExtraRoot: 0
|
|
||||||
skeletonHasParents: 1
|
|
||||||
lastHumanDescriptionAvatarSource: {instanceID: 0}
|
|
||||||
autoGenerateAvatarMappingIfUnspecified: 1
|
|
||||||
animationType: 3
|
|
||||||
humanoidOversampling: 1
|
|
||||||
avatarSetup: 1
|
|
||||||
addHumanoidExtraRootOnlyWhenUsingAvatar: 1
|
|
||||||
importBlendShapeDeformPercent: 1
|
|
||||||
remapMaterialsIfMaterialImportModeIsNone: 0
|
|
||||||
additionalBone: 0
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 01e904bb240e86040803984638031e2b
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: c2a29c299fbfb684fad514a825e18e98
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
BIN
Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar/Y Bot.Avatar/VrmAvatar.asset
(Stored with Git LFS)
vendored
BIN
Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar/Y Bot.Avatar/VrmAvatar.asset
(Stored with Git LFS)
vendored
Binary file not shown.
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: acd2877d503a16e409e366297fbcea8b
|
|
||||||
NativeFormatImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
mainObjectFileID: 9000000
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 1a08ef839c7d43549985f6cb6a0267a5
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
BIN
Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar/Y Bot.Materials/Alpha_Body_MAT.asset
(Stored with Git LFS)
vendored
BIN
Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar/Y Bot.Materials/Alpha_Body_MAT.asset
(Stored with Git LFS)
vendored
Binary file not shown.
BIN
Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar/Y Bot.Materials/Alpha_Joints_MAT.asset
(Stored with Git LFS)
vendored
BIN
Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar/Y Bot.Materials/Alpha_Joints_MAT.asset
(Stored with Git LFS)
vendored
Binary file not shown.
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 17378a42694cecf4d830641783cb0c69
|
|
||||||
NativeFormatImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
mainObjectFileID: 2100000
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 19d0e42a2077486408ca1a3aa2188b02
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
BIN
Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar/Y Bot.Meshes/Alpha_Joints.baked.asset
(Stored with Git LFS)
vendored
BIN
Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar/Y Bot.Meshes/Alpha_Joints.baked.asset
(Stored with Git LFS)
vendored
Binary file not shown.
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 3fdf147a4927f794c8f15d82ff2403a3
|
|
||||||
NativeFormatImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
mainObjectFileID: 4300000
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
BIN
Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar/Y Bot.Meshes/Alpha_Surface.baked.asset
(Stored with Git LFS)
vendored
BIN
Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar/Y Bot.Meshes/Alpha_Surface.baked.asset
(Stored with Git LFS)
vendored
Binary file not shown.
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 737c3076344703b4fb517641ba144c79
|
|
||||||
NativeFormatImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
mainObjectFileID: 4300000
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
BIN
Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar/Y Bot.prefab
(Stored with Git LFS)
vendored
BIN
Assets/External/OptiTrack Unity Plugin/OptiTrack/BaseAvatar/Y Bot.prefab
(Stored with Git LFS)
vendored
Binary file not shown.
396
Assets/External/OptiTrack Unity Plugin/OptiTrack/Editor/OptitrackSetupWindow.cs
vendored
Normal file
396
Assets/External/OptiTrack Unity Plugin/OptiTrack/Editor/OptitrackSetupWindow.cs
vendored
Normal file
@ -0,0 +1,396 @@
|
|||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
public class OptitrackSetupWindow : EditorWindow
|
||||||
|
{
|
||||||
|
private OptitrackSkeletonAnimator_Mingle m_target;
|
||||||
|
private int m_tab = 0;
|
||||||
|
private static readonly string[] TabLabels = { "본 매핑", "T-포즈" };
|
||||||
|
|
||||||
|
private bool m_showMappingFoldout = true;
|
||||||
|
private Vector2 m_mappingScroll;
|
||||||
|
private Vector2 m_restPoseScroll;
|
||||||
|
private Dictionary<string, Transform> m_cachedTransformMap;
|
||||||
|
private OptitrackSkeletonAnimator_Mingle m_cachedTransformTarget;
|
||||||
|
|
||||||
|
// ── 진입점 ────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
[MenuItem("OptiTrack/Animator 설정 창")]
|
||||||
|
public static void OpenFromMenu() => GetWindow<OptitrackSetupWindow>("OptiTrack 설정").Show();
|
||||||
|
|
||||||
|
public static void Open(OptitrackSkeletonAnimator_Mingle target)
|
||||||
|
{
|
||||||
|
var win = GetWindow<OptitrackSetupWindow>("OptiTrack 설정");
|
||||||
|
win.m_target = target;
|
||||||
|
win.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSelectionChange()
|
||||||
|
{
|
||||||
|
if (Selection.activeGameObject == null) return;
|
||||||
|
var found = Selection.activeGameObject.GetComponent<OptitrackSkeletonAnimator_Mingle>();
|
||||||
|
if (found != null) { m_target = found; InvalidateTransformCache(); Repaint(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 창 ────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private void OnGUI()
|
||||||
|
{
|
||||||
|
// 대상 선택
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
var newTarget = (OptitrackSkeletonAnimator_Mingle)EditorGUILayout.ObjectField(
|
||||||
|
"대상", m_target, typeof(OptitrackSkeletonAnimator_Mingle), true);
|
||||||
|
if (EditorGUI.EndChangeCheck()) { m_target = newTarget; InvalidateTransformCache(); }
|
||||||
|
|
||||||
|
if (m_target == null)
|
||||||
|
{
|
||||||
|
EditorGUILayout.HelpBox("대상 컴포넌트를 선택하거나 Inspector에서 창을 여세요.", MessageType.Info);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SO 없으면 경고 + 생성 버튼
|
||||||
|
if (m_target.RestPoseAsset == null)
|
||||||
|
{
|
||||||
|
DrawSeparator();
|
||||||
|
EditorGUILayout.HelpBox("스켈레톤 설정 에셋이 없습니다. 생성하거나 기존 에셋을 연결하세요.", MessageType.Warning);
|
||||||
|
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
var linked = (OptitrackRestPoseData)EditorGUILayout.ObjectField(
|
||||||
|
"Setup Asset", null, typeof(OptitrackRestPoseData), false);
|
||||||
|
if (EditorGUI.EndChangeCheck() && linked != null)
|
||||||
|
AssignAsset(linked);
|
||||||
|
|
||||||
|
if (GUILayout.Button("새 설정 에셋 생성", GUILayout.Height(28)))
|
||||||
|
CreateAndAssignAsset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawSeparator();
|
||||||
|
|
||||||
|
// SO 필드
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
var newAsset = (OptitrackRestPoseData)EditorGUILayout.ObjectField(
|
||||||
|
"Setup Asset", m_target.RestPoseAsset, typeof(OptitrackRestPoseData), false);
|
||||||
|
if (EditorGUI.EndChangeCheck()) AssignAsset(newAsset);
|
||||||
|
|
||||||
|
DrawSeparator();
|
||||||
|
|
||||||
|
m_tab = GUILayout.Toolbar(m_tab, TabLabels, GUILayout.Height(26));
|
||||||
|
|
||||||
|
DrawSeparator();
|
||||||
|
|
||||||
|
switch (m_tab)
|
||||||
|
{
|
||||||
|
case 0: DrawMappingTab(); break;
|
||||||
|
case 1: DrawRestPoseTab(); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Application.isPlaying) Repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 본 매핑 탭 ────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private void DrawMappingTab()
|
||||||
|
{
|
||||||
|
var so = m_target.RestPoseAsset;
|
||||||
|
|
||||||
|
// 자동 생성 버튼
|
||||||
|
var prevBg = GUI.backgroundColor;
|
||||||
|
GUI.backgroundColor = new Color(0.4f, 0.8f, 0.4f);
|
||||||
|
if (GUILayout.Button("FBX 분석 → 자동 매핑 생성", GUILayout.Height(32)))
|
||||||
|
{
|
||||||
|
Undo.RecordObject(so, "Auto Generate Bone Mappings");
|
||||||
|
AutoGenerateMappings(so);
|
||||||
|
EditorUtility.SetDirty(so);
|
||||||
|
AssetDatabase.SaveAssets();
|
||||||
|
}
|
||||||
|
GUI.backgroundColor = prevBg;
|
||||||
|
|
||||||
|
EditorGUILayout.Space(4);
|
||||||
|
|
||||||
|
if (so.boneMappings == null || so.boneMappings.Count == 0)
|
||||||
|
{
|
||||||
|
EditorGUILayout.HelpBox("매핑 없음. 위 버튼으로 자동 생성하세요.", MessageType.None);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int mapped = 0, unmapped = 0;
|
||||||
|
foreach (var m in so.boneMappings)
|
||||||
|
{
|
||||||
|
if (m.isMapped) mapped++;
|
||||||
|
else unmapped++;
|
||||||
|
}
|
||||||
|
EditorGUILayout.HelpBox(
|
||||||
|
$"매핑: {mapped} 성공 / {unmapped} 실패 (총 {so.boneMappings.Count})",
|
||||||
|
unmapped > 0 ? MessageType.Warning : MessageType.Info);
|
||||||
|
|
||||||
|
EditorGUILayout.Space(4);
|
||||||
|
m_showMappingFoldout = EditorGUILayout.Foldout(m_showMappingFoldout,
|
||||||
|
$"본 매핑 목록 ({so.boneMappings.Count})", true, EditorStyles.foldoutHeader);
|
||||||
|
|
||||||
|
if (m_showMappingFoldout)
|
||||||
|
{
|
||||||
|
m_mappingScroll = EditorGUILayout.BeginScrollView(m_mappingScroll, GUILayout.MaxHeight(320));
|
||||||
|
DrawMappingList(so);
|
||||||
|
EditorGUILayout.EndScrollView();
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.Space(4);
|
||||||
|
prevBg = GUI.backgroundColor;
|
||||||
|
GUI.backgroundColor = new Color(0.85f, 0.35f, 0.35f);
|
||||||
|
if (GUILayout.Button("매핑 초기화"))
|
||||||
|
{
|
||||||
|
Undo.RecordObject(so, "Clear Bone Mappings");
|
||||||
|
so.boneMappings.Clear();
|
||||||
|
EditorUtility.SetDirty(so);
|
||||||
|
}
|
||||||
|
GUI.backgroundColor = prevBg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawMappingList(OptitrackRestPoseData so)
|
||||||
|
{
|
||||||
|
var transformMap = GetTransformMap();
|
||||||
|
|
||||||
|
for (int i = 0; i < so.boneMappings.Count; i++)
|
||||||
|
{
|
||||||
|
var mapping = so.boneMappings[i];
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
|
||||||
|
// 상태 아이콘
|
||||||
|
var prevContent = GUI.contentColor;
|
||||||
|
GUI.contentColor = mapping.isMapped ? Color.green : Color.red;
|
||||||
|
GUILayout.Label(mapping.isMapped ? "●" : "○", GUILayout.Width(14));
|
||||||
|
GUI.contentColor = prevContent;
|
||||||
|
|
||||||
|
GUILayout.Label(mapping.optiTrackBoneName, GUILayout.Width(90));
|
||||||
|
GUILayout.Label("→", GUILayout.Width(16));
|
||||||
|
|
||||||
|
// FBX 노드 이름 편집
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
string newName = EditorGUILayout.TextField(mapping.fbxNodeName);
|
||||||
|
if (EditorGUI.EndChangeCheck())
|
||||||
|
{
|
||||||
|
Undo.RecordObject(so, "Edit Bone Mapping");
|
||||||
|
mapping.fbxNodeName = newName;
|
||||||
|
mapping.isMapped = transformMap.ContainsKey(newName);
|
||||||
|
EditorUtility.SetDirty(so);
|
||||||
|
}
|
||||||
|
|
||||||
|
// P / R 토글
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
bool newPos = GUILayout.Toggle(mapping.applyPosition, "P", "Button", GUILayout.Width(24));
|
||||||
|
bool newRot = GUILayout.Toggle(mapping.applyRotation, "R", "Button", GUILayout.Width(24));
|
||||||
|
if (EditorGUI.EndChangeCheck())
|
||||||
|
{
|
||||||
|
Undo.RecordObject(so, "Toggle Bone Apply");
|
||||||
|
mapping.applyPosition = newPos;
|
||||||
|
mapping.applyRotation = newRot;
|
||||||
|
EditorUtility.SetDirty(so);
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── T-포즈 탭 ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private void DrawRestPoseTab()
|
||||||
|
{
|
||||||
|
var so = m_target.RestPoseAsset;
|
||||||
|
bool hasEntries = so.restPoseEntries.Count > 0;
|
||||||
|
|
||||||
|
if (hasEntries)
|
||||||
|
EditorGUILayout.HelpBox($"{so.restPoseEntries.Count}개 본 저장됨", MessageType.Info);
|
||||||
|
else
|
||||||
|
EditorGUILayout.HelpBox("T-포즈 없음 — 아바타를 T-포즈로 맞추고 캡처하세요.", MessageType.Warning);
|
||||||
|
|
||||||
|
EditorGUILayout.Space(6);
|
||||||
|
|
||||||
|
var prevBg = GUI.backgroundColor;
|
||||||
|
GUI.backgroundColor = new Color(0.35f, 0.65f, 1f);
|
||||||
|
if (GUILayout.Button("현재 포즈 → T-포즈로 캡처", GUILayout.Height(32)))
|
||||||
|
CaptureRestPose(so);
|
||||||
|
GUI.backgroundColor = prevBg;
|
||||||
|
|
||||||
|
using (new EditorGUI.DisabledScope(!hasEntries))
|
||||||
|
{
|
||||||
|
if (GUILayout.Button("씬에 적용 (미리보기)", GUILayout.Height(26)))
|
||||||
|
PreviewRestPose(so);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasEntries)
|
||||||
|
{
|
||||||
|
DrawSeparator();
|
||||||
|
EditorGUILayout.LabelField($"저장된 본 목록 ({so.restPoseEntries.Count})", EditorStyles.boldLabel);
|
||||||
|
m_restPoseScroll = EditorGUILayout.BeginScrollView(m_restPoseScroll, GUILayout.MaxHeight(260));
|
||||||
|
foreach (var e in so.restPoseEntries)
|
||||||
|
{
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
GUILayout.Label(e.boneName, GUILayout.Width(110));
|
||||||
|
GUILayout.Label($"pos {e.localPosition:F3}", EditorStyles.miniLabel);
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
}
|
||||||
|
EditorGUILayout.EndScrollView();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CaptureRestPose(OptitrackRestPoseData so)
|
||||||
|
{
|
||||||
|
var transformMap = GetTransformMap();
|
||||||
|
|
||||||
|
Undo.RecordObject(so, "Capture Rest Pose");
|
||||||
|
so.restPoseEntries.Clear();
|
||||||
|
int count = 0;
|
||||||
|
foreach (var mapping in so.boneMappings)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(mapping.fbxNodeName) || mapping.fbxNodeName.Contains("(미발견)"))
|
||||||
|
continue;
|
||||||
|
if (!transformMap.TryGetValue(mapping.fbxNodeName, out Transform t))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
so.restPoseEntries.Add(new OptitrackRestPoseData.RestPoseEntry
|
||||||
|
{
|
||||||
|
boneName = mapping.optiTrackBoneName,
|
||||||
|
localPosition = t.localPosition,
|
||||||
|
localRotation = t.localRotation
|
||||||
|
});
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorUtility.SetDirty(so);
|
||||||
|
AssetDatabase.SaveAssets();
|
||||||
|
Debug.Log($"[OptiTrack] T-포즈 캡처 완료: {count}개 본 → {AssetDatabase.GetAssetPath(so)}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PreviewRestPose(OptitrackRestPoseData so)
|
||||||
|
{
|
||||||
|
var transformMap = GetTransformMap();
|
||||||
|
var poseByName = new Dictionary<string, OptitrackRestPoseData.RestPoseEntry>(so.restPoseEntries.Count);
|
||||||
|
foreach (var e in so.restPoseEntries)
|
||||||
|
poseByName[e.boneName] = e;
|
||||||
|
|
||||||
|
foreach (var mapping in so.boneMappings)
|
||||||
|
{
|
||||||
|
if (!transformMap.TryGetValue(mapping.fbxNodeName, out Transform t)) continue;
|
||||||
|
if (!poseByName.TryGetValue(mapping.optiTrackBoneName, out var entry)) continue;
|
||||||
|
Undo.RecordObject(t, "Preview Rest Pose");
|
||||||
|
t.localPosition = entry.localPosition;
|
||||||
|
t.localRotation = entry.localRotation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── SO 관리 ───────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private void AssignAsset(OptitrackRestPoseData asset)
|
||||||
|
{
|
||||||
|
Undo.RecordObject(m_target, "Set Skeleton Setup Asset");
|
||||||
|
m_target.RestPoseAsset = asset;
|
||||||
|
EditorUtility.SetDirty(m_target);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateAndAssignAsset()
|
||||||
|
{
|
||||||
|
string path = EditorUtility.SaveFilePanelInProject(
|
||||||
|
"스켈레톤 설정 에셋 저장", "OptitrackSkeletonSetup", "asset", "저장 위치를 선택하세요.");
|
||||||
|
if (string.IsNullOrEmpty(path)) return;
|
||||||
|
|
||||||
|
var asset = ScriptableObject.CreateInstance<OptitrackRestPoseData>();
|
||||||
|
AssetDatabase.CreateAsset(asset, path);
|
||||||
|
AssetDatabase.SaveAssets();
|
||||||
|
AssignAsset(asset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 자동 매핑 생성 ────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private void AutoGenerateMappings(OptitrackRestPoseData so)
|
||||||
|
{
|
||||||
|
so.boneMappings.Clear();
|
||||||
|
var transformMap = GetTransformMap();
|
||||||
|
|
||||||
|
string prefix = "";
|
||||||
|
foreach (var kvp in transformMap)
|
||||||
|
{
|
||||||
|
if (kvp.Key.EndsWith("Hips"))
|
||||||
|
{
|
||||||
|
int idx = kvp.Key.LastIndexOf("Hips");
|
||||||
|
if (idx > 0) { prefix = kvp.Key.Substring(0, idx); break; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrEmpty(prefix))
|
||||||
|
Debug.Log($"[OptiTrack 매핑] 감지된 접두사: \"{prefix}\"");
|
||||||
|
|
||||||
|
int mapped = 0;
|
||||||
|
foreach (var kvp in OptitrackSkeletonAnimator_Mingle.DefaultOptiToFbxSuffix)
|
||||||
|
{
|
||||||
|
var mapping = new OptiTrackBoneMapping
|
||||||
|
{
|
||||||
|
optiTrackBoneName = kvp.Key,
|
||||||
|
applyPosition = true,
|
||||||
|
applyRotation = true,
|
||||||
|
isMapped = false
|
||||||
|
};
|
||||||
|
|
||||||
|
string fullName = prefix + kvp.Value;
|
||||||
|
if (transformMap.TryGetValue(fullName, out Transform found))
|
||||||
|
{
|
||||||
|
mapping.fbxNodeName = fullName;
|
||||||
|
mapping.cachedTransform = found;
|
||||||
|
mapping.isMapped = true;
|
||||||
|
}
|
||||||
|
else if (transformMap.TryGetValue(kvp.Value, out Transform found2))
|
||||||
|
{
|
||||||
|
mapping.fbxNodeName = kvp.Value;
|
||||||
|
mapping.cachedTransform = found2;
|
||||||
|
mapping.isMapped = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var t in transformMap)
|
||||||
|
{
|
||||||
|
if (t.Key.EndsWith(kvp.Value) || t.Key.EndsWith("_" + kvp.Value))
|
||||||
|
{
|
||||||
|
mapping.fbxNodeName = t.Key;
|
||||||
|
mapping.cachedTransform = t.Value;
|
||||||
|
mapping.isMapped = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mapping.isMapped)
|
||||||
|
mapping.fbxNodeName = prefix + kvp.Value + " (미발견)";
|
||||||
|
else
|
||||||
|
mapped++;
|
||||||
|
|
||||||
|
so.boneMappings.Add(mapping);
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.Log($"[OptiTrack 매핑] 완료: {mapped}/{so.boneMappings.Count} 본 매핑 성공");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 유틸 ──────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private Dictionary<string, Transform> GetTransformMap()
|
||||||
|
{
|
||||||
|
if (m_target == null) return new Dictionary<string, Transform>();
|
||||||
|
if (m_cachedTransformMap != null && m_cachedTransformTarget == m_target)
|
||||||
|
return m_cachedTransformMap;
|
||||||
|
m_cachedTransformMap = new Dictionary<string, Transform>();
|
||||||
|
foreach (var t in m_target.GetComponentsInChildren<Transform>(true))
|
||||||
|
if (!m_cachedTransformMap.ContainsKey(t.name))
|
||||||
|
m_cachedTransformMap[t.name] = t;
|
||||||
|
m_cachedTransformTarget = m_target;
|
||||||
|
return m_cachedTransformMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InvalidateTransformCache() => m_cachedTransformMap = null;
|
||||||
|
|
||||||
|
private static void DrawSeparator()
|
||||||
|
{
|
||||||
|
EditorGUILayout.Space(5);
|
||||||
|
EditorGUI.DrawRect(EditorGUILayout.GetControlRect(false, 1f), new Color(0.35f, 0.35f, 0.35f));
|
||||||
|
EditorGUILayout.Space(4);
|
||||||
|
}
|
||||||
|
}
|
||||||
2
Assets/External/OptiTrack Unity Plugin/OptiTrack/Editor/OptitrackSetupWindow.cs.meta
vendored
Normal file
2
Assets/External/OptiTrack Unity Plugin/OptiTrack/Editor/OptitrackSetupWindow.cs.meta
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: df7ba0fc2f63e424cb886dc9965c9c9c
|
||||||
@ -1,264 +1,33 @@
|
|||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
[CustomEditor(typeof(OptitrackSkeletonAnimator_Mingle))]
|
[CustomEditor(typeof(OptitrackSkeletonAnimator_Mingle))]
|
||||||
public class OptitrackSkeletonAnimatorEditor : Editor
|
public class OptitrackSkeletonAnimatorEditor : Editor
|
||||||
{
|
{
|
||||||
private bool showMappingFoldout = true;
|
|
||||||
private bool showDebugBonesFoldout = false;
|
|
||||||
|
|
||||||
public override void OnInspectorGUI()
|
public override void OnInspectorGUI()
|
||||||
{
|
{
|
||||||
DrawDefaultInspector();
|
DrawDefaultInspector();
|
||||||
|
|
||||||
OptitrackSkeletonAnimator_Mingle skeletonAnimator = (OptitrackSkeletonAnimator_Mingle)target;
|
var anim = (OptitrackSkeletonAnimator_Mingle)target;
|
||||||
|
|
||||||
GUILayout.Space(10);
|
// 연결 상태 배지
|
||||||
EditorGUILayout.LabelField("스켈레톤 상태", EditorStyles.boldLabel);
|
EditorGUILayout.Space(8);
|
||||||
|
var prevBg = GUI.backgroundColor;
|
||||||
GUI.backgroundColor = skeletonAnimator.isSkeletonFound ? Color.green : Color.red;
|
GUI.backgroundColor = anim.isSkeletonFound ? new Color(0.3f, 0.8f, 0.3f) : new Color(0.8f, 0.3f, 0.3f);
|
||||||
EditorGUILayout.BeginHorizontal(EditorStyles.helpBox);
|
EditorGUILayout.BeginHorizontal(EditorStyles.helpBox);
|
||||||
GUILayout.Label(skeletonAnimator.isSkeletonFound ? "연결됨" : "연결 안됨",
|
string status = anim.isSkeletonFound
|
||||||
new GUIStyle(EditorStyles.boldLabel) { alignment = TextAnchor.MiddleCenter });
|
? $"연결됨 — {anim.SkeletonAssetName}"
|
||||||
|
: "연결 안됨 — Motive 스켈레톤 확인 필요";
|
||||||
|
GUILayout.Label(status, new GUIStyle(EditorStyles.boldLabel) { alignment = TextAnchor.MiddleCenter });
|
||||||
EditorGUILayout.EndHorizontal();
|
EditorGUILayout.EndHorizontal();
|
||||||
GUI.backgroundColor = Color.white;
|
GUI.backgroundColor = prevBg;
|
||||||
|
|
||||||
if (skeletonAnimator.isSkeletonFound)
|
// 설정 창 열기
|
||||||
{
|
EditorGUILayout.Space(6);
|
||||||
EditorGUILayout.LabelField($"스켈레톤 이름: {skeletonAnimator.SkeletonAssetName}");
|
if (GUILayout.Button("본 매핑 / T-포즈 설정 창 열기", GUILayout.Height(28)))
|
||||||
}
|
OptitrackSetupWindow.Open(anim);
|
||||||
else
|
|
||||||
{
|
|
||||||
EditorGUILayout.HelpBox("Motive에서 스켈레톤이 활성화되어 있는지 확인해주세요.", MessageType.Warning);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── 본 매핑 도구 ──
|
|
||||||
GUILayout.Space(10);
|
|
||||||
EditorGUILayout.LabelField("본 매핑 도구", EditorStyles.boldLabel);
|
|
||||||
|
|
||||||
GUI.backgroundColor = new Color(0.4f, 0.8f, 0.4f);
|
|
||||||
if (GUILayout.Button("FBX 분석 → 자동 매핑 생성", GUILayout.Height(35)))
|
|
||||||
{
|
|
||||||
Undo.RecordObject(skeletonAnimator, "Auto Generate Bone Mappings");
|
|
||||||
AutoGenerateMappingsEditor(skeletonAnimator);
|
|
||||||
EditorUtility.SetDirty(skeletonAnimator);
|
|
||||||
}
|
|
||||||
GUI.backgroundColor = Color.white;
|
|
||||||
|
|
||||||
// 매핑 상태 요약
|
|
||||||
if (skeletonAnimator.boneMappings != null && skeletonAnimator.boneMappings.Count > 0)
|
|
||||||
{
|
|
||||||
int mapped = 0;
|
|
||||||
int unmapped = 0;
|
|
||||||
foreach (var m in skeletonAnimator.boneMappings)
|
|
||||||
{
|
|
||||||
if (m.isMapped) mapped++;
|
|
||||||
else unmapped++;
|
|
||||||
}
|
|
||||||
|
|
||||||
EditorGUILayout.Space(5);
|
|
||||||
EditorGUILayout.HelpBox(
|
|
||||||
$"매핑 상태: {mapped}개 성공 / {unmapped}개 실패 (총 {skeletonAnimator.boneMappings.Count}개)",
|
|
||||||
unmapped > 0 ? MessageType.Warning : MessageType.Info);
|
|
||||||
|
|
||||||
// 매핑 리스트
|
|
||||||
EditorGUILayout.Space(5);
|
|
||||||
showMappingFoldout = EditorGUILayout.Foldout(showMappingFoldout, $"본 매핑 목록 ({skeletonAnimator.boneMappings.Count})", true);
|
|
||||||
if (showMappingFoldout)
|
|
||||||
{
|
|
||||||
EditorGUI.indentLevel++;
|
|
||||||
for (int i = 0; i < skeletonAnimator.boneMappings.Count; i++)
|
|
||||||
{
|
|
||||||
var mapping = skeletonAnimator.boneMappings[i];
|
|
||||||
Color labelColor = mapping.isMapped ? Color.green : Color.red;
|
|
||||||
|
|
||||||
EditorGUILayout.BeginHorizontal();
|
|
||||||
|
|
||||||
var prevColor = GUI.contentColor;
|
|
||||||
GUI.contentColor = labelColor;
|
|
||||||
EditorGUILayout.LabelField(mapping.isMapped ? "●" : "○", GUILayout.Width(15));
|
|
||||||
GUI.contentColor = prevColor;
|
|
||||||
|
|
||||||
EditorGUILayout.LabelField(mapping.optiTrackBoneName, GUILayout.Width(100));
|
|
||||||
EditorGUILayout.LabelField("→", GUILayout.Width(20));
|
|
||||||
|
|
||||||
// FBX 노드 이름 — 수동 편집 가능
|
|
||||||
EditorGUI.BeginChangeCheck();
|
|
||||||
string newName = EditorGUILayout.TextField(mapping.fbxNodeName);
|
|
||||||
if (EditorGUI.EndChangeCheck())
|
|
||||||
{
|
|
||||||
Undo.RecordObject(skeletonAnimator, "Edit Bone Mapping");
|
|
||||||
mapping.fbxNodeName = newName;
|
|
||||||
var allTransforms = skeletonAnimator.GetComponentsInChildren<Transform>(true);
|
|
||||||
mapping.cachedTransform = null;
|
|
||||||
mapping.isMapped = false;
|
|
||||||
foreach (var t in allTransforms)
|
|
||||||
{
|
|
||||||
if (t.name == newName)
|
|
||||||
{
|
|
||||||
mapping.cachedTransform = t;
|
|
||||||
mapping.isMapped = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EditorUtility.SetDirty(skeletonAnimator);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Position / Rotation 토글
|
|
||||||
EditorGUI.BeginChangeCheck();
|
|
||||||
mapping.applyPosition = EditorGUILayout.ToggleLeft("P", mapping.applyPosition, GUILayout.Width(30));
|
|
||||||
mapping.applyRotation = EditorGUILayout.ToggleLeft("R", mapping.applyRotation, GUILayout.Width(30));
|
|
||||||
if (EditorGUI.EndChangeCheck())
|
|
||||||
{
|
|
||||||
Undo.RecordObject(skeletonAnimator, "Toggle Bone Apply");
|
|
||||||
EditorUtility.SetDirty(skeletonAnimator);
|
|
||||||
}
|
|
||||||
|
|
||||||
EditorGUILayout.EndHorizontal();
|
|
||||||
}
|
|
||||||
EditorGUI.indentLevel--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EditorGUILayout.Space(5);
|
|
||||||
GUI.backgroundColor = new Color(0.9f, 0.4f, 0.4f);
|
|
||||||
if (GUILayout.Button("매핑 초기화"))
|
|
||||||
{
|
|
||||||
Undo.RecordObject(skeletonAnimator, "Clear Bone Mappings");
|
|
||||||
skeletonAnimator.boneMappings.Clear();
|
|
||||||
EditorUtility.SetDirty(skeletonAnimator);
|
|
||||||
}
|
|
||||||
GUI.backgroundColor = Color.white;
|
|
||||||
|
|
||||||
// ── 런타임 수신 본 디버그 ──
|
|
||||||
GUILayout.Space(10);
|
|
||||||
EditorGUILayout.LabelField("Motive 수신 본 디버그 (런타임)", EditorStyles.boldLabel);
|
|
||||||
|
|
||||||
if (!Application.isPlaying)
|
|
||||||
{
|
|
||||||
EditorGUILayout.HelpBox("플레이 모드에서 Motive 연결 후 확인할 수 있습니다.", MessageType.Info);
|
|
||||||
}
|
|
||||||
else if (skeletonAnimator.debugReceivedBoneNames.Count == 0)
|
|
||||||
{
|
|
||||||
EditorGUILayout.HelpBox("아직 본 데이터를 수신하지 못했습니다. Motive 스켈레톤이 활성화되어 있는지 확인해주세요.", MessageType.Warning);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
EditorGUILayout.LabelField($"수신된 본 수: {skeletonAnimator.debugReceivedBoneCount}");
|
|
||||||
|
|
||||||
showDebugBonesFoldout = EditorGUILayout.Foldout(showDebugBonesFoldout, $"Motive 본 목록 ({skeletonAnimator.debugReceivedBoneNames.Count})", true);
|
|
||||||
if (showDebugBonesFoldout)
|
|
||||||
{
|
|
||||||
EditorGUI.indentLevel++;
|
|
||||||
foreach (var boneName in skeletonAnimator.debugReceivedBoneNames)
|
|
||||||
{
|
|
||||||
EditorGUILayout.LabelField(boneName);
|
|
||||||
}
|
|
||||||
EditorGUI.indentLevel--;
|
|
||||||
}
|
|
||||||
|
|
||||||
EditorGUILayout.Space(3);
|
|
||||||
if (GUILayout.Button("Console에 전체 본 목록 출력"))
|
|
||||||
{
|
|
||||||
var sb = new System.Text.StringBuilder();
|
|
||||||
sb.AppendLine($"=== Motive 수신 본 목록 ({skeletonAnimator.SkeletonAssetName}) ===");
|
|
||||||
sb.AppendLine($"총 {skeletonAnimator.debugReceivedBoneCount}개");
|
|
||||||
sb.AppendLine();
|
|
||||||
foreach (var bn in skeletonAnimator.debugReceivedBoneNames)
|
|
||||||
{
|
|
||||||
sb.AppendLine(bn);
|
|
||||||
}
|
|
||||||
Debug.Log(sb.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 플레이 모드일 때 자동 갱신
|
|
||||||
if (Application.isPlaying)
|
if (Application.isPlaying)
|
||||||
Repaint();
|
Repaint();
|
||||||
|
|
||||||
GUILayout.Space(10);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AutoGenerateMappingsEditor(OptitrackSkeletonAnimator_Mingle script)
|
|
||||||
{
|
|
||||||
script.boneMappings.Clear();
|
|
||||||
|
|
||||||
var allTransforms = script.GetComponentsInChildren<Transform>(true);
|
|
||||||
var transformMap = new Dictionary<string, Transform>();
|
|
||||||
foreach (var t in allTransforms)
|
|
||||||
{
|
|
||||||
if (!transformMap.ContainsKey(t.name))
|
|
||||||
transformMap[t.name] = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 접두사 자동 감지 (예: "001_Hips" → "001_")
|
|
||||||
string prefix = "";
|
|
||||||
foreach (var kvp in transformMap)
|
|
||||||
{
|
|
||||||
if (kvp.Key.EndsWith("Hips"))
|
|
||||||
{
|
|
||||||
int idx = kvp.Key.LastIndexOf("Hips");
|
|
||||||
if (idx > 0)
|
|
||||||
{
|
|
||||||
prefix = kvp.Key.Substring(0, idx);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(prefix))
|
|
||||||
Debug.Log($"[OptiTrack 매핑] 감지된 접두사: \"{prefix}\"");
|
|
||||||
|
|
||||||
int mapped = 0;
|
|
||||||
foreach (var kvp in OptitrackSkeletonAnimator_Mingle.DefaultOptiToFbxSuffix)
|
|
||||||
{
|
|
||||||
var mapping = new OptiTrackBoneMapping
|
|
||||||
{
|
|
||||||
optiTrackBoneName = kvp.Key,
|
|
||||||
applyPosition = true,
|
|
||||||
applyRotation = true,
|
|
||||||
isMapped = false
|
|
||||||
};
|
|
||||||
|
|
||||||
// 1순위: 접두사 + FBX 접미사
|
|
||||||
string fullName = prefix + kvp.Value;
|
|
||||||
if (transformMap.TryGetValue(fullName, out Transform found))
|
|
||||||
{
|
|
||||||
mapping.fbxNodeName = fullName;
|
|
||||||
mapping.cachedTransform = found;
|
|
||||||
mapping.isMapped = true;
|
|
||||||
}
|
|
||||||
// 2순위: 접미사만
|
|
||||||
else if (transformMap.TryGetValue(kvp.Value, out Transform found2))
|
|
||||||
{
|
|
||||||
mapping.fbxNodeName = kvp.Value;
|
|
||||||
mapping.cachedTransform = found2;
|
|
||||||
mapping.isMapped = true;
|
|
||||||
}
|
|
||||||
// 3순위: 끝나는 이름으로 부분 검색
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (var t in transformMap)
|
|
||||||
{
|
|
||||||
if (t.Key.EndsWith(kvp.Value) || t.Key.EndsWith("_" + kvp.Value))
|
|
||||||
{
|
|
||||||
mapping.fbxNodeName = t.Key;
|
|
||||||
mapping.cachedTransform = t.Value;
|
|
||||||
mapping.isMapped = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mapping.isMapped)
|
|
||||||
mapping.fbxNodeName = prefix + kvp.Value + " (미발견)";
|
|
||||||
else
|
|
||||||
mapped++;
|
|
||||||
|
|
||||||
script.boneMappings.Add(mapping);
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug.Log($"[OptiTrack 매핑] 완료: {mapped}/{script.boneMappings.Count} 본 매핑 성공");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
Assets/External/OptiTrack Unity Plugin/OptiTrack/Prefabs/BaseAvatar - OptiTrack ver 2.prefab
(Stored with Git LFS)
vendored
BIN
Assets/External/OptiTrack Unity Plugin/OptiTrack/Prefabs/BaseAvatar - OptiTrack ver 2.prefab
(Stored with Git LFS)
vendored
Binary file not shown.
BIN
Assets/External/OptiTrack Unity Plugin/OptiTrack/Prefabs/BaseAvatar - OptiTrack.prefab
(Stored with Git LFS)
vendored
BIN
Assets/External/OptiTrack Unity Plugin/OptiTrack/Prefabs/BaseAvatar - OptiTrack.prefab
(Stored with Git LFS)
vendored
Binary file not shown.
@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: c1e31e5077eae1f4f823f68fde521408
|
|
||||||
PrefabImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
BIN
Assets/External/OptiTrack Unity Plugin/OptiTrack/Prefabs/Horse_TM.fbx
(Stored with Git LFS)
vendored
BIN
Assets/External/OptiTrack Unity Plugin/OptiTrack/Prefabs/Horse_TM.fbx
(Stored with Git LFS)
vendored
Binary file not shown.
@ -1,107 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 14ec801d62fadf547921258a8b1dadc5
|
|
||||||
ModelImporter:
|
|
||||||
serializedVersion: 22200
|
|
||||||
internalIDToNameTable: []
|
|
||||||
externalObjects: {}
|
|
||||||
materials:
|
|
||||||
materialImportMode: 2
|
|
||||||
materialName: 0
|
|
||||||
materialSearch: 1
|
|
||||||
materialLocation: 1
|
|
||||||
animations:
|
|
||||||
legacyGenerateAnimations: 4
|
|
||||||
bakeSimulation: 0
|
|
||||||
resampleCurves: 1
|
|
||||||
optimizeGameObjects: 0
|
|
||||||
removeConstantScaleCurves: 0
|
|
||||||
motionNodeName:
|
|
||||||
animationImportErrors:
|
|
||||||
animationImportWarnings:
|
|
||||||
animationRetargetingWarnings:
|
|
||||||
animationDoRetargetingWarnings: 0
|
|
||||||
importAnimatedCustomProperties: 0
|
|
||||||
importConstraints: 0
|
|
||||||
animationCompression: 1
|
|
||||||
animationRotationError: 0.5
|
|
||||||
animationPositionError: 0.5
|
|
||||||
animationScaleError: 0.5
|
|
||||||
animationWrapMode: 0
|
|
||||||
extraExposedTransformPaths: []
|
|
||||||
extraUserProperties: []
|
|
||||||
clipAnimations: []
|
|
||||||
isReadable: 0
|
|
||||||
meshes:
|
|
||||||
lODScreenPercentages: []
|
|
||||||
globalScale: 1
|
|
||||||
meshCompression: 0
|
|
||||||
addColliders: 0
|
|
||||||
useSRGBMaterialColor: 1
|
|
||||||
sortHierarchyByName: 1
|
|
||||||
importPhysicalCameras: 1
|
|
||||||
importVisibility: 1
|
|
||||||
importBlendShapes: 1
|
|
||||||
importCameras: 1
|
|
||||||
importLights: 1
|
|
||||||
nodeNameCollisionStrategy: 1
|
|
||||||
fileIdsGeneration: 2
|
|
||||||
swapUVChannels: 0
|
|
||||||
generateSecondaryUV: 0
|
|
||||||
useFileUnits: 1
|
|
||||||
keepQuads: 0
|
|
||||||
weldVertices: 1
|
|
||||||
bakeAxisConversion: 0
|
|
||||||
preserveHierarchy: 0
|
|
||||||
skinWeightsMode: 0
|
|
||||||
maxBonesPerVertex: 4
|
|
||||||
minBoneWeight: 0.001
|
|
||||||
optimizeBones: 1
|
|
||||||
meshOptimizationFlags: -1
|
|
||||||
indexFormat: 0
|
|
||||||
secondaryUVAngleDistortion: 8
|
|
||||||
secondaryUVAreaDistortion: 15.000001
|
|
||||||
secondaryUVHardAngle: 88
|
|
||||||
secondaryUVMarginMethod: 1
|
|
||||||
secondaryUVMinLightmapResolution: 40
|
|
||||||
secondaryUVMinObjectScale: 1
|
|
||||||
secondaryUVPackMargin: 4
|
|
||||||
useFileScale: 1
|
|
||||||
strictVertexDataChecks: 0
|
|
||||||
tangentSpace:
|
|
||||||
normalSmoothAngle: 60
|
|
||||||
normalImportMode: 0
|
|
||||||
tangentImportMode: 3
|
|
||||||
normalCalculationMode: 4
|
|
||||||
legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0
|
|
||||||
blendShapeNormalImportMode: 1
|
|
||||||
normalSmoothingSource: 0
|
|
||||||
referencedClips: []
|
|
||||||
importAnimation: 1
|
|
||||||
humanDescription:
|
|
||||||
serializedVersion: 3
|
|
||||||
human: []
|
|
||||||
skeleton: []
|
|
||||||
armTwist: 0.5
|
|
||||||
foreArmTwist: 0.5
|
|
||||||
upperLegTwist: 0.5
|
|
||||||
legTwist: 0.5
|
|
||||||
armStretch: 0.05
|
|
||||||
legStretch: 0.05
|
|
||||||
feetSpacing: 0
|
|
||||||
globalScale: 1
|
|
||||||
rootMotionBoneName:
|
|
||||||
hasTranslationDoF: 0
|
|
||||||
hasExtraRoot: 0
|
|
||||||
skeletonHasParents: 1
|
|
||||||
lastHumanDescriptionAvatarSource: {instanceID: 0}
|
|
||||||
autoGenerateAvatarMappingIfUnspecified: 1
|
|
||||||
animationType: 2
|
|
||||||
humanoidOversampling: 1
|
|
||||||
avatarSetup: 0
|
|
||||||
addHumanoidExtraRootOnlyWhenUsingAvatar: 1
|
|
||||||
importBlendShapeDeformPercent: 1
|
|
||||||
remapMaterialsIfMaterialImportModeIsNone: 0
|
|
||||||
additionalBone: 0
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
BIN
Assets/External/OptiTrack Unity Plugin/OptiTrack/Prefabs/Retargeted Skeleton - OptiTrack.prefab
(Stored with Git LFS)
vendored
BIN
Assets/External/OptiTrack Unity Plugin/OptiTrack/Prefabs/Retargeted Skeleton - OptiTrack.prefab
(Stored with Git LFS)
vendored
Binary file not shown.
@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: afbc9c9b98650e44f97662b4f503c261
|
|
||||||
PrefabImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
48
Assets/External/OptiTrack Unity Plugin/OptiTrack/Scripts/OptitrackRestPoseData.cs
vendored
Normal file
48
Assets/External/OptiTrack Unity Plugin/OptiTrack/Scripts/OptitrackRestPoseData.cs
vendored
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// OptiTrack 스켈레톤의 본 매핑과 T-포즈를 에셋으로 영구 저장합니다.
|
||||||
|
/// 런타임에 Start()에서 자동 로드되며, CacheRestPose() 없이 즉시 복원이 가능합니다.
|
||||||
|
/// </summary>
|
||||||
|
[CreateAssetMenu(fileName = "OptitrackRestPoseData", menuName = "OptiTrack/Skeleton Setup")]
|
||||||
|
public class OptitrackRestPoseData : ScriptableObject
|
||||||
|
{
|
||||||
|
// ── 본 매핑 ───────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// OptiTrack 본 이름 ↔ FBX 노드 이름 매핑 목록.
|
||||||
|
/// Transform 참조(cachedTransform)는 씬 오브젝트라 SO에 저장되지 않으며,
|
||||||
|
/// 런타임 Start()에서 자동으로 채워집니다.
|
||||||
|
/// </summary>
|
||||||
|
public List<OptiTrackBoneMapping> boneMappings = new List<OptiTrackBoneMapping>();
|
||||||
|
|
||||||
|
// ── T-포즈 (기준 포즈) ────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class RestPoseEntry
|
||||||
|
{
|
||||||
|
public string boneName;
|
||||||
|
public Vector3 localPosition;
|
||||||
|
public Quaternion localRotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<RestPoseEntry> restPoseEntries = new List<RestPoseEntry>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// T-포즈 데이터를 런타임 딕셔너리에 복사합니다.
|
||||||
|
/// </summary>
|
||||||
|
public void LoadRestPoseIntoRuntime(
|
||||||
|
Dictionary<string, Quaternion> rotations,
|
||||||
|
Dictionary<string, Vector3> positions)
|
||||||
|
{
|
||||||
|
rotations.Clear();
|
||||||
|
positions.Clear();
|
||||||
|
foreach (var e in restPoseEntries)
|
||||||
|
{
|
||||||
|
rotations[e.boneName] = e.localRotation;
|
||||||
|
positions[e.boneName] = e.localPosition;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
2
Assets/External/OptiTrack Unity Plugin/OptiTrack/Scripts/OptitrackRestPoseData.cs.meta
vendored
Normal file
2
Assets/External/OptiTrack Unity Plugin/OptiTrack/Scripts/OptitrackRestPoseData.cs.meta
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 48d97b353e3e9b14a8b24f284c518839
|
||||||
@ -25,12 +25,23 @@ public class OptitrackSkeletonAnimator_Mingle : MonoBehaviour
|
|||||||
[Tooltip("Motive의 스켈레톤 에셋 이름")]
|
[Tooltip("Motive의 스켈레톤 에셋 이름")]
|
||||||
public string SkeletonAssetName = "Skeleton1";
|
public string SkeletonAssetName = "Skeleton1";
|
||||||
|
|
||||||
[Header("본 매핑 (OptiTrack → FBX 노드)")]
|
// 런타임 본 매핑 — SO(RestPoseAsset)에서 로드됨. 직접 편집하지 말고 설정 창 사용.
|
||||||
[Tooltip("자동 매핑 후 수동 조정 가능")]
|
[HideInInspector]
|
||||||
public List<OptiTrackBoneMapping> boneMappings = new List<OptiTrackBoneMapping>();
|
public List<OptiTrackBoneMapping> boneMappings = new List<OptiTrackBoneMapping>();
|
||||||
|
|
||||||
[Header("디버그")]
|
[Header("T-포즈 (기준 포즈)")]
|
||||||
public bool logUnmappedBones = false;
|
[Tooltip("에디터에서 캡처한 T-포즈 데이터. 비어 있으면 런타임 CacheRestPose()를 사용합니다.")]
|
||||||
|
public OptitrackRestPoseData RestPoseAsset;
|
||||||
|
|
||||||
|
[Header("본 1€ 필터 (속도 적응형 저역통과)")]
|
||||||
|
[Tooltip("활성화 시 빠른 움직임은 그대로, 정지/느린 움직임의 노이즈를 제거합니다.\n단순 EMA보다 모션 보존이 훨씬 우수합니다.")]
|
||||||
|
public bool enableBoneFilter = true;
|
||||||
|
[Tooltip("최소 차단 주파수 (Hz). 낮을수록 정지 시 노이즈 제거 강화. 권장: 1~3 Hz")]
|
||||||
|
[Range(0.1f, 10f)]
|
||||||
|
public float filterMinCutoff = 3.0f;
|
||||||
|
[Tooltip("속도 계수. 높을수록 빠른 움직임 시 지연 감소. 권장: 0.3~1.0")]
|
||||||
|
[Range(0f, 5f)]
|
||||||
|
public float filterBeta = 1.5f;
|
||||||
|
|
||||||
private OptitrackSkeletonDefinition m_skeletonDef;
|
private OptitrackSkeletonDefinition m_skeletonDef;
|
||||||
private string previousSkeletonName;
|
private string previousSkeletonName;
|
||||||
@ -38,23 +49,43 @@ public class OptitrackSkeletonAnimator_Mingle : MonoBehaviour
|
|||||||
[HideInInspector]
|
[HideInInspector]
|
||||||
public bool isSkeletonFound = false;
|
public bool isSkeletonFound = false;
|
||||||
|
|
||||||
// 에디터 디버그용 — 런타임에 Motive에서 실제로 수신된 본 목록
|
private const float k_SkeletonCheckInterval = 0.1f;
|
||||||
[HideInInspector]
|
|
||||||
public List<string> debugReceivedBoneNames = new List<string>();
|
|
||||||
[HideInInspector]
|
|
||||||
public int debugReceivedBoneCount = 0;
|
|
||||||
|
|
||||||
private float updateInterval = 0.1f;
|
|
||||||
|
|
||||||
// 본 ID → 매핑 인덱스 (빠른 룩업)
|
// 본 ID → 매핑 인덱스 (빠른 룩업)
|
||||||
private Dictionary<Int32, int> m_boneIdToMappingIndex = new Dictionary<Int32, int>();
|
private Dictionary<Int32, int> m_boneIdToMappingIndex = new Dictionary<Int32, int>();
|
||||||
// 본 이름 → Transform 캐시 (전체 하이어라키)
|
// 본 이름 → Transform 캐시 (전체 하이어라키)
|
||||||
private Dictionary<string, Transform> m_allTransforms = new Dictionary<string, Transform>();
|
private Dictionary<string, Transform> m_allTransforms = new Dictionary<string, Transform>();
|
||||||
|
|
||||||
// torn read 방지용 스냅샷 버퍼
|
// FillBoneSnapshot 용 pre-allocated 스냅샷 버퍼 (락 내부에서 채워짐 → torn read 없음)
|
||||||
private Dictionary<Int32, Vector3> m_snapshotPositions = new Dictionary<Int32, Vector3>();
|
private Dictionary<Int32, Vector3> m_snapshotPositions = new Dictionary<Int32, Vector3>();
|
||||||
private Dictionary<Int32, Quaternion> m_snapshotOrientations = new Dictionary<Int32, Quaternion>();
|
private Dictionary<Int32, Quaternion> m_snapshotOrientations = new Dictionary<Int32, Quaternion>();
|
||||||
|
|
||||||
|
// OptiTrack 본 이름 → Transform 빠른 캐시 (GetMappedTransform O(n) → O(1))
|
||||||
|
private Dictionary<string, Transform> m_optiNameTransformCache = new Dictionary<string, Transform>();
|
||||||
|
|
||||||
|
// 스파인/넥 체인 Transform 캐시 (GetSpineChainTransforms 매 호출 List 할당 방지)
|
||||||
|
private List<Transform> m_spineChainCache = new List<Transform>();
|
||||||
|
private List<Transform> m_neckChainCache = new List<Transform>();
|
||||||
|
|
||||||
|
// 힙 본 ID 캐시 (-1 = 미발견)
|
||||||
|
private int m_hipBoneId = -1;
|
||||||
|
|
||||||
|
// NatNet 하드웨어 타임스탬프 기반 실제 프레임 간격 (렌더 프레임과 독립)
|
||||||
|
private float m_natNetDt = 1f / 120f;
|
||||||
|
private OptitrackHiResTimer.Timestamp m_lastFrameTimestamp;
|
||||||
|
private bool m_hasLastFrameTimestamp = false;
|
||||||
|
|
||||||
|
// 1€ 필터 상태 (본 ID → 이전 프레임 필터 상태)
|
||||||
|
private struct BoneFilterState
|
||||||
|
{
|
||||||
|
public Quaternion prevOri;
|
||||||
|
public float dOriMag; // 필터된 각속도 크기 (rad/s)
|
||||||
|
public Vector3 prevPos;
|
||||||
|
public float dPosMag; // 필터된 선속도 크기 (m/s)
|
||||||
|
public bool initialized;
|
||||||
|
}
|
||||||
|
private Dictionary<Int32, BoneFilterState> m_filterStates = new Dictionary<Int32, BoneFilterState>();
|
||||||
|
|
||||||
// OptiTrack 본 이름 → FBX 노드 접미사 기본 매핑
|
// OptiTrack 본 이름 → FBX 노드 접미사 기본 매핑
|
||||||
public static readonly Dictionary<string, string> DefaultOptiToFbxSuffix = new Dictionary<string, string>
|
public static readonly Dictionary<string, string> DefaultOptiToFbxSuffix = new Dictionary<string, string>
|
||||||
{
|
{
|
||||||
@ -140,16 +171,42 @@ public class OptitrackSkeletonAnimator_Mingle : MonoBehaviour
|
|||||||
StreamingClient.RegisterSkeleton(this, this.SkeletonAssetName);
|
StreamingClient.RegisterSkeleton(this, this.SkeletonAssetName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 에디터에서 세팅한 매핑의 Transform 캐시 갱신
|
// SO에서 본 매핑 + T-포즈 로드
|
||||||
if (boneMappings.Count > 0)
|
if (RestPoseAsset != null && RestPoseAsset.boneMappings.Count > 0)
|
||||||
|
{
|
||||||
|
// 본 매핑: SO → MB 런타임 복사 (cachedTransform은 아래 RefreshTransformCache에서 채워짐)
|
||||||
|
boneMappings.Clear();
|
||||||
|
foreach (var src in RestPoseAsset.boneMappings)
|
||||||
|
{
|
||||||
|
boneMappings.Add(new OptiTrackBoneMapping
|
||||||
|
{
|
||||||
|
optiTrackBoneName = src.optiTrackBoneName,
|
||||||
|
fbxNodeName = src.fbxNodeName,
|
||||||
|
applyPosition = src.applyPosition,
|
||||||
|
applyRotation = src.applyRotation
|
||||||
|
});
|
||||||
|
}
|
||||||
|
RefreshTransformCache();
|
||||||
|
Debug.Log($"[OptiTrack] 본 매핑 에셋 로드 완료: {boneMappings.Count}개", this);
|
||||||
|
}
|
||||||
|
else if (boneMappings.Count > 0)
|
||||||
{
|
{
|
||||||
RefreshTransformCache();
|
RefreshTransformCache();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning("[OptiTrack] 본 매핑이 비어있습니다. Inspector에서 'FBX 분석 → 자동 매핑 생성' 버튼을 눌러주세요.", this);
|
Debug.LogWarning("[OptiTrack] 본 매핑이 비어있습니다. 설정 창에서 'FBX 분석 → 자동 매핑 생성'을 눌러주세요.", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// T-포즈 로드
|
||||||
|
if (RestPoseAsset != null && RestPoseAsset.restPoseEntries.Count > 0)
|
||||||
|
{
|
||||||
|
RestPoseAsset.LoadRestPoseIntoRuntime(m_restLocalRotations, m_restLocalPositions);
|
||||||
|
m_isRestPoseCached = true;
|
||||||
|
Debug.Log($"[OptiTrack] T-포즈 에셋 로드 완료: {m_restLocalRotations.Count}개 본", this);
|
||||||
|
}
|
||||||
|
|
||||||
|
previousSkeletonName = SkeletonAssetName;
|
||||||
StartCoroutine(CheckSkeletonConnectionPeriodically());
|
StartCoroutine(CheckSkeletonConnectionPeriodically());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,29 +229,24 @@ public class OptitrackSkeletonAnimator_Mingle : MonoBehaviour
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_skeletonDef == null)
|
if (m_skeletonDef == null) return;
|
||||||
{
|
|
||||||
m_skeletonDef = StreamingClient.GetSkeletonDefinitionByName(SkeletonAssetName);
|
|
||||||
if (m_skeletonDef == null)
|
|
||||||
return;
|
|
||||||
RebuildBoneIdMapping();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 최신 스켈레톤 상태
|
// 락 보호 하에 스냅샷 복사 + NatNet 하드웨어 타임스탬프 수신
|
||||||
OptitrackSkeletonState skelState = StreamingClient.GetLatestSkeletonState(m_skeletonDef.Id);
|
OptitrackHiResTimer.Timestamp frameTs;
|
||||||
if (skelState == null)
|
if (!StreamingClient.FillBoneSnapshot(m_skeletonDef.Id, m_snapshotPositions, m_snapshotOrientations, out frameTs))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// torn read 방지 — 스냅샷 복사
|
// ── NatNet 실제 프레임 간격 계산 (하드웨어 타이머 — 렌더 프레임 등락과 완전 독립) ──
|
||||||
m_snapshotPositions.Clear();
|
if (m_hasLastFrameTimestamp && frameTs.m_ticks != m_lastFrameTimestamp.m_ticks)
|
||||||
m_snapshotOrientations.Clear();
|
|
||||||
foreach (var kvp in skelState.BonePoses)
|
|
||||||
{
|
{
|
||||||
m_snapshotPositions[kvp.Key] = kvp.Value.Position;
|
float measuredDt = frameTs.SecondsSince(m_lastFrameTimestamp);
|
||||||
m_snapshotOrientations[kvp.Key] = kvp.Value.Orientation;
|
if (measuredDt > 0.001f && measuredDt < 0.1f) // 1ms~100ms 범위만 신뢰 (이상값 무시)
|
||||||
|
m_natNetDt = Mathf.Lerp(m_natNetDt, measuredDt, 0.1f);
|
||||||
}
|
}
|
||||||
|
m_lastFrameTimestamp = frameTs;
|
||||||
|
m_hasLastFrameTimestamp = true;
|
||||||
|
|
||||||
// 각 본 업데이트 — Transform 직접 적용
|
// ── 각 본 업데이트 ───────────────────────────────────────────────────────
|
||||||
foreach (var bone in m_skeletonDef.Bones)
|
foreach (var bone in m_skeletonDef.Bones)
|
||||||
{
|
{
|
||||||
if (!m_boneIdToMappingIndex.TryGetValue(bone.Id, out int mappingIdx))
|
if (!m_boneIdToMappingIndex.TryGetValue(bone.Id, out int mappingIdx))
|
||||||
@ -204,17 +256,26 @@ public class OptitrackSkeletonAnimator_Mingle : MonoBehaviour
|
|||||||
if (!mapping.isMapped || mapping.cachedTransform == null)
|
if (!mapping.isMapped || mapping.cachedTransform == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (m_snapshotOrientations.TryGetValue(bone.Id, out Quaternion ori))
|
if (mapping.applyRotation)
|
||||||
{
|
{
|
||||||
if (mapping.applyPosition && m_snapshotPositions.TryGetValue(bone.Id, out Vector3 pos))
|
if (!m_snapshotOrientations.TryGetValue(bone.Id, out Quaternion finalOri))
|
||||||
{
|
continue;
|
||||||
mapping.cachedTransform.localPosition = SnapPosition(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mapping.applyRotation)
|
if (enableBoneFilter)
|
||||||
{
|
finalOri = ApplyOneEuroOri(bone.Id, finalOri, m_natNetDt);
|
||||||
mapping.cachedTransform.localRotation = SnapQuaternion(ori);
|
|
||||||
}
|
mapping.cachedTransform.localRotation = finalOri;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mapping.applyPosition)
|
||||||
|
{
|
||||||
|
if (!m_snapshotPositions.TryGetValue(bone.Id, out Vector3 finalPos))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (enableBoneFilter)
|
||||||
|
finalPos = ApplyOneEuroPos(bone.Id, finalPos, m_natNetDt);
|
||||||
|
|
||||||
|
mapping.cachedTransform.localPosition = finalPos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -248,6 +309,34 @@ public class OptitrackSkeletonAnimator_Mingle : MonoBehaviour
|
|||||||
mapping.isMapped = true;
|
mapping.isMapped = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
RebuildOptiNameCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// OptiTrack 본 이름 → Transform 딕셔너리 캐시 구축 (GetMappedTransform O(n) → O(1))
|
||||||
|
/// </summary>
|
||||||
|
private void RebuildOptiNameCache()
|
||||||
|
{
|
||||||
|
m_optiNameTransformCache.Clear();
|
||||||
|
foreach (var mapping in boneMappings)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(mapping.optiTrackBoneName) && mapping.isMapped && mapping.cachedTransform != null)
|
||||||
|
m_optiNameTransformCache[mapping.optiTrackBoneName] = mapping.cachedTransform;
|
||||||
|
}
|
||||||
|
RebuildChainCaches();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RebuildChainCaches()
|
||||||
|
{
|
||||||
|
m_spineChainCache.Clear();
|
||||||
|
foreach (var name in SpineChainOptiNames)
|
||||||
|
if (m_optiNameTransformCache.TryGetValue(name, out Transform t))
|
||||||
|
m_spineChainCache.Add(t);
|
||||||
|
|
||||||
|
m_neckChainCache.Clear();
|
||||||
|
foreach (var name in NeckChainOptiNames)
|
||||||
|
if (m_optiNameTransformCache.TryGetValue(name, out Transform t))
|
||||||
|
m_neckChainCache.Add(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -256,11 +345,10 @@ public class OptitrackSkeletonAnimator_Mingle : MonoBehaviour
|
|||||||
private void RebuildBoneIdMapping()
|
private void RebuildBoneIdMapping()
|
||||||
{
|
{
|
||||||
m_boneIdToMappingIndex.Clear();
|
m_boneIdToMappingIndex.Clear();
|
||||||
debugReceivedBoneNames.Clear();
|
m_filterStates.Clear();
|
||||||
|
m_hasLastFrameTimestamp = false;
|
||||||
if (m_skeletonDef == null) return;
|
if (m_skeletonDef == null) return;
|
||||||
|
|
||||||
debugReceivedBoneCount = m_skeletonDef.Bones.Count;
|
|
||||||
|
|
||||||
var nameToIdx = new Dictionary<string, int>();
|
var nameToIdx = new Dictionary<string, int>();
|
||||||
for (int i = 0; i < boneMappings.Count; i++)
|
for (int i = 0; i < boneMappings.Count; i++)
|
||||||
{
|
{
|
||||||
@ -269,25 +357,17 @@ public class OptitrackSkeletonAnimator_Mingle : MonoBehaviour
|
|||||||
}
|
}
|
||||||
|
|
||||||
int matchCount = 0;
|
int matchCount = 0;
|
||||||
|
m_hipBoneId = -1;
|
||||||
foreach (var bone in m_skeletonDef.Bones)
|
foreach (var bone in m_skeletonDef.Bones)
|
||||||
{
|
{
|
||||||
string boneName = bone.Name;
|
string boneName = bone.Name;
|
||||||
string optiName = boneName.Contains("_") ? boneName.Substring(boneName.IndexOf('_') + 1) : boneName;
|
string optiName = boneName.Contains("_") ? boneName.Substring(boneName.IndexOf('_') + 1) : boneName;
|
||||||
|
|
||||||
// 디버그: Motive에서 수신된 모든 본 기록
|
|
||||||
string parentInfo = m_skeletonDef.BoneIdToParentIdMap.TryGetValue(bone.Id, out Int32 parentId)
|
|
||||||
? $"parent={parentId}" : "root";
|
|
||||||
debugReceivedBoneNames.Add($"[ID:{bone.Id}] {boneName} (suffix: {optiName}, {parentInfo})");
|
|
||||||
|
|
||||||
if (nameToIdx.TryGetValue(optiName, out int idx))
|
if (nameToIdx.TryGetValue(optiName, out int idx))
|
||||||
{
|
{
|
||||||
m_boneIdToMappingIndex[bone.Id] = idx;
|
m_boneIdToMappingIndex[bone.Id] = idx;
|
||||||
matchCount++;
|
matchCount++;
|
||||||
}
|
}
|
||||||
else if (logUnmappedBones)
|
if (optiName == "Hip") m_hipBoneId = bone.Id;
|
||||||
{
|
|
||||||
Debug.LogWarning($"[OptiTrack] 매핑되지 않은 OptiTrack 본: {boneName} (suffix: {optiName})");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Log($"[OptiTrack] 본 ID 매핑 완료: {matchCount}/{m_skeletonDef.Bones.Count} 매칭");
|
Debug.Log($"[OptiTrack] 본 ID 매핑 완료: {matchCount}/{m_skeletonDef.Bones.Count} 매칭");
|
||||||
@ -331,31 +411,81 @@ public class OptitrackSkeletonAnimator_Mingle : MonoBehaviour
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
yield return new WaitForSeconds(updateInterval);
|
yield return new WaitForSeconds(k_SkeletonCheckInterval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 소수점 4자리 이하 제거 (0.0001m = 0.1mm 미만 노이즈 제거)
|
// ── 1€ Filter (One Euro Filter) ──────────────────────────────────────────
|
||||||
private const float POS_PRECISION = 10000f;
|
// 참고: Géry Casiez et al., "1€ Filter: A Simple Speed-based Low-pass Filter", CHI 2012
|
||||||
private static Vector3 SnapPosition(Vector3 v)
|
// 속도가 빠를수록 cutoff 상승 → 지연 감소, 속도가 느릴수록 cutoff = minCutoff → 노이즈 제거
|
||||||
|
|
||||||
|
// dt초 간격에서의 1차 LP 필터 alpha
|
||||||
|
private static float OE_Alpha(float cutoffHz, float dt)
|
||||||
{
|
{
|
||||||
return new Vector3(
|
float r = 2f * Mathf.PI * cutoffHz * dt;
|
||||||
Mathf.Round(v.x * POS_PRECISION) / POS_PRECISION,
|
return r / (r + 1f);
|
||||||
Mathf.Round(v.y * POS_PRECISION) / POS_PRECISION,
|
|
||||||
Mathf.Round(v.z * POS_PRECISION) / POS_PRECISION
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 쿼터니언 소수점 5자리 이하 제거 + 정규화
|
private Quaternion ApplyOneEuroOri(int boneId, Quaternion raw, float dt)
|
||||||
private const float ROT_PRECISION = 100000f;
|
|
||||||
private static Quaternion SnapQuaternion(Quaternion q)
|
|
||||||
{
|
{
|
||||||
return new Quaternion(
|
const float k_DCutoff = 1f; // 도함수 필터의 고정 cutoff (Hz)
|
||||||
Mathf.Round(q.x * ROT_PRECISION) / ROT_PRECISION,
|
|
||||||
Mathf.Round(q.y * ROT_PRECISION) / ROT_PRECISION,
|
if (!m_filterStates.TryGetValue(boneId, out BoneFilterState s) || !s.initialized)
|
||||||
Mathf.Round(q.z * ROT_PRECISION) / ROT_PRECISION,
|
{
|
||||||
Mathf.Round(q.w * ROT_PRECISION) / ROT_PRECISION
|
m_filterStates[boneId] = new BoneFilterState
|
||||||
).normalized;
|
{
|
||||||
|
prevOri = raw, dOriMag = 0f,
|
||||||
|
prevPos = Vector3.zero, dPosMag = 0f,
|
||||||
|
initialized = true
|
||||||
|
};
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 각속도(rad/s) 추정
|
||||||
|
float angleDeg = Quaternion.Angle(s.prevOri, raw);
|
||||||
|
float speed = angleDeg * Mathf.Deg2Rad / Mathf.Max(dt, 1e-4f);
|
||||||
|
|
||||||
|
// 도함수를 별도 LP로 스무딩
|
||||||
|
float dAlpha = OE_Alpha(k_DCutoff, dt);
|
||||||
|
float filtDeriv = s.dOriMag + dAlpha * (speed - s.dOriMag);
|
||||||
|
|
||||||
|
// 적응 cutoff: 빠르면 cutoff 상승
|
||||||
|
float cutoff = filterMinCutoff + filterBeta * filtDeriv;
|
||||||
|
float alpha = OE_Alpha(cutoff, dt);
|
||||||
|
Quaternion filtered = Quaternion.Slerp(s.prevOri, raw, alpha);
|
||||||
|
|
||||||
|
s.prevOri = filtered;
|
||||||
|
s.dOriMag = filtDeriv;
|
||||||
|
m_filterStates[boneId] = s;
|
||||||
|
return filtered;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vector3 ApplyOneEuroPos(int boneId, Vector3 raw, float dt)
|
||||||
|
{
|
||||||
|
const float k_DCutoff = 1f;
|
||||||
|
|
||||||
|
if (!m_filterStates.TryGetValue(boneId, out BoneFilterState s) || !s.initialized)
|
||||||
|
{
|
||||||
|
// 회전 필터가 이미 초기화했을 수 있으므로 위치만 패치
|
||||||
|
s.prevPos = raw;
|
||||||
|
s.dPosMag = 0f;
|
||||||
|
s.initialized = true;
|
||||||
|
m_filterStates[boneId] = s;
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
float speed = (raw - s.prevPos).magnitude / Mathf.Max(dt, 1e-4f);
|
||||||
|
float dAlpha = OE_Alpha(k_DCutoff, dt);
|
||||||
|
float filtDeriv = s.dPosMag + dAlpha * (speed - s.dPosMag);
|
||||||
|
|
||||||
|
float cutoff = filterMinCutoff + filterBeta * filtDeriv;
|
||||||
|
float alpha = OE_Alpha(cutoff, dt);
|
||||||
|
Vector3 filtered = Vector3.Lerp(s.prevPos, raw, alpha);
|
||||||
|
|
||||||
|
s.prevPos = filtered;
|
||||||
|
s.dPosMag = filtDeriv;
|
||||||
|
m_filterStates[boneId] = s;
|
||||||
|
return filtered;
|
||||||
}
|
}
|
||||||
|
|
||||||
#region 외부 접근용 헬퍼
|
#region 외부 접근용 헬퍼
|
||||||
@ -440,10 +570,13 @@ public class OptitrackSkeletonAnimator_Mingle : MonoBehaviour
|
|||||||
public static readonly string[] NeckChainOptiNames = { "Neck", "Neck2" };
|
public static readonly string[] NeckChainOptiNames = { "Neck", "Neck2" };
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// OptiTrack 본 이름으로 매핑된 Transform 반환
|
/// OptiTrack 본 이름으로 매핑된 Transform 반환 (캐시 O(1), 미캐시 시 선형 탐색 폴백)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Transform GetMappedTransform(string optiTrackBoneName)
|
public Transform GetMappedTransform(string optiTrackBoneName)
|
||||||
{
|
{
|
||||||
|
if (m_optiNameTransformCache.TryGetValue(optiTrackBoneName, out var cached))
|
||||||
|
return cached;
|
||||||
|
// 캐시 미구축 상태 폴백 (Start() 전 호출 등)
|
||||||
foreach (var mapping in boneMappings)
|
foreach (var mapping in boneMappings)
|
||||||
{
|
{
|
||||||
if (mapping.optiTrackBoneName == optiTrackBoneName && mapping.isMapped)
|
if (mapping.optiTrackBoneName == optiTrackBoneName && mapping.isMapped)
|
||||||
@ -455,32 +588,12 @@ public class OptitrackSkeletonAnimator_Mingle : MonoBehaviour
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 스파인 체인의 모든 Transform을 순서대로 반환 (Ab → Spine2 → Spine3 → Spine4 → Chest)
|
/// 스파인 체인의 모든 Transform을 순서대로 반환 (Ab → Spine2 → Spine3 → Spine4 → Chest)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<Transform> GetSpineChainTransforms()
|
public List<Transform> GetSpineChainTransforms() => m_spineChainCache;
|
||||||
{
|
|
||||||
var chain = new List<Transform>();
|
|
||||||
foreach (var name in SpineChainOptiNames)
|
|
||||||
{
|
|
||||||
Transform t = GetMappedTransform(name);
|
|
||||||
if (t != null)
|
|
||||||
chain.Add(t);
|
|
||||||
}
|
|
||||||
return chain;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 넥 체인의 모든 Transform을 순서대로 반환
|
/// 넥 체인의 모든 Transform을 순서대로 반환
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<Transform> GetNeckChainTransforms()
|
public List<Transform> GetNeckChainTransforms() => m_neckChainCache;
|
||||||
{
|
|
||||||
var chain = new List<Transform>();
|
|
||||||
foreach (var name in NeckChainOptiNames)
|
|
||||||
{
|
|
||||||
Transform t = GetMappedTransform(name);
|
|
||||||
if (t != null)
|
|
||||||
chain.Add(t);
|
|
||||||
}
|
|
||||||
return chain;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 체인의 누적 로컬 회전을 계산 (각 본의 localRotation을 순서대로 곱함)
|
/// 체인의 누적 로컬 회전을 계산 (각 본의 localRotation을 순서대로 곱함)
|
||||||
@ -495,31 +608,49 @@ public class OptitrackSkeletonAnimator_Mingle : MonoBehaviour
|
|||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
// T-포즈 기준 포즈 데이터 (SO에서 로드 또는 CacheRestPose()로 캐싱)
|
||||||
/// 초기 포즈(T-포즈) 캐싱 — Humanoid가 아니므로 직접 캐싱
|
private Dictionary<string, Quaternion> m_restLocalRotations = new Dictionary<string, Quaternion>();
|
||||||
/// </summary>
|
private Dictionary<string, Vector3> m_restLocalPositions = new Dictionary<string, Vector3>();
|
||||||
[HideInInspector] public Dictionary<string, Quaternion> restLocalRotations = new Dictionary<string, Quaternion>();
|
private bool m_isRestPoseCached = false;
|
||||||
[HideInInspector] public Dictionary<string, Vector3> restLocalPositions = new Dictionary<string, Vector3>();
|
|
||||||
[HideInInspector] public bool isRestPoseCached = false;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 현재 포즈를 기준 포즈(T-포즈)로 캐싱
|
/// 현재 포즈를 기준 포즈(T-포즈)로 캐싱
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void CacheRestPose()
|
public void CacheRestPose()
|
||||||
{
|
{
|
||||||
restLocalRotations.Clear();
|
m_restLocalRotations.Clear();
|
||||||
restLocalPositions.Clear();
|
m_restLocalPositions.Clear();
|
||||||
|
|
||||||
foreach (var mapping in boneMappings)
|
foreach (var mapping in boneMappings)
|
||||||
{
|
{
|
||||||
if (mapping.isMapped && mapping.cachedTransform != null)
|
if (mapping.isMapped && mapping.cachedTransform != null)
|
||||||
{
|
{
|
||||||
restLocalRotations[mapping.optiTrackBoneName] = mapping.cachedTransform.localRotation;
|
m_restLocalRotations[mapping.optiTrackBoneName] = mapping.cachedTransform.localRotation;
|
||||||
restLocalPositions[mapping.optiTrackBoneName] = mapping.cachedTransform.localPosition;
|
m_restLocalPositions[mapping.optiTrackBoneName] = mapping.cachedTransform.localPosition;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
isRestPoseCached = true;
|
m_isRestPoseCached = true;
|
||||||
Debug.Log($"[OptiTrack] 기준 포즈 캐싱 완료: {restLocalRotations.Count}개 본");
|
Debug.Log($"[OptiTrack] 기준 포즈 캐싱 완료: {m_restLocalRotations.Count}개 본");
|
||||||
|
|
||||||
|
// SO가 연결되어 있으면 런타임 결과를 SO에도 반영
|
||||||
|
if (RestPoseAsset != null)
|
||||||
|
{
|
||||||
|
RestPoseAsset.restPoseEntries.Clear();
|
||||||
|
foreach (var kvp in m_restLocalRotations)
|
||||||
|
{
|
||||||
|
m_restLocalPositions.TryGetValue(kvp.Key, out Vector3 pos);
|
||||||
|
RestPoseAsset.restPoseEntries.Add(new OptitrackRestPoseData.RestPoseEntry
|
||||||
|
{
|
||||||
|
boneName = kvp.Key,
|
||||||
|
localPosition = pos,
|
||||||
|
localRotation = kvp.Value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
UnityEditor.EditorUtility.SetDirty(RestPoseAsset);
|
||||||
|
UnityEditor.AssetDatabase.SaveAssets();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -527,15 +658,15 @@ public class OptitrackSkeletonAnimator_Mingle : MonoBehaviour
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void RestoreRestPose()
|
public void RestoreRestPose()
|
||||||
{
|
{
|
||||||
if (!isRestPoseCached) return;
|
if (!m_isRestPoseCached) return;
|
||||||
|
|
||||||
foreach (var mapping in boneMappings)
|
foreach (var mapping in boneMappings)
|
||||||
{
|
{
|
||||||
if (mapping.isMapped && mapping.cachedTransform != null)
|
if (mapping.isMapped && mapping.cachedTransform != null)
|
||||||
{
|
{
|
||||||
if (restLocalRotations.TryGetValue(mapping.optiTrackBoneName, out Quaternion rot))
|
if (m_restLocalRotations.TryGetValue(mapping.optiTrackBoneName, out Quaternion rot))
|
||||||
mapping.cachedTransform.localRotation = rot;
|
mapping.cachedTransform.localRotation = rot;
|
||||||
if (restLocalPositions.TryGetValue(mapping.optiTrackBoneName, out Vector3 pos))
|
if (m_restLocalPositions.TryGetValue(mapping.optiTrackBoneName, out Vector3 pos))
|
||||||
mapping.cachedTransform.localPosition = pos;
|
mapping.cachedTransform.localPosition = pos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -546,7 +677,7 @@ public class OptitrackSkeletonAnimator_Mingle : MonoBehaviour
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Quaternion GetRestLocalRotation(string optiTrackBoneName)
|
public Quaternion GetRestLocalRotation(string optiTrackBoneName)
|
||||||
{
|
{
|
||||||
if (restLocalRotations.TryGetValue(optiTrackBoneName, out Quaternion rot))
|
if (m_restLocalRotations.TryGetValue(optiTrackBoneName, out Quaternion rot))
|
||||||
return rot;
|
return rot;
|
||||||
return Quaternion.identity;
|
return Quaternion.identity;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,10 +22,6 @@ using System.Threading;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using NaturalPoint;
|
using NaturalPoint;
|
||||||
using NaturalPoint.NatNetLib;
|
using NaturalPoint.NatNetLib;
|
||||||
using UnityEditor;
|
|
||||||
using UnityEditor.UIElements;
|
|
||||||
using UnityEngine.UIElements;
|
|
||||||
using static TMPro.SpriteAssetUtilities.TexturePacker_JsonArray;
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>Skeleton naming conventions supported by OptiTrack Motive.</summary>
|
/// <summary>Skeleton naming conventions supported by OptiTrack Motive.</summary>
|
||||||
@ -79,6 +75,8 @@ public class OptitrackSkeletonState
|
|||||||
/// <summary>Maps from OptiTrack bone IDs to their corresponding bone poses.</summary>
|
/// <summary>Maps from OptiTrack bone IDs to their corresponding bone poses.</summary>
|
||||||
public Dictionary<Int32, OptitrackPose> BonePoses;
|
public Dictionary<Int32, OptitrackPose> BonePoses;
|
||||||
public Dictionary<Int32, OptitrackPose> LocalBonePoses;
|
public Dictionary<Int32, OptitrackPose> LocalBonePoses;
|
||||||
|
/// <summary>NatNet 프레임이 수신된 시각 (고해상도 하드웨어 타이머 기반).</summary>
|
||||||
|
public OptitrackHiResTimer.Timestamp DeliveryTimestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Represents the state of a streamed trained markerset at an instant in time.</summary>
|
/// <summary>Represents the state of a streamed trained markerset at an instant in time.</summary>
|
||||||
@ -323,6 +321,9 @@ public class OptitrackStreamingClient : MonoBehaviour
|
|||||||
[Tooltip("Skips getting data descriptions. Skeletons will not work with this feature turned on, but it will reduce network usage with a large number of rigid bodies.")]
|
[Tooltip("Skips getting data descriptions. Skeletons will not work with this feature turned on, but it will reduce network usage with a large number of rigid bodies.")]
|
||||||
public bool SkipDataDescriptions = false;
|
public bool SkipDataDescriptions = false;
|
||||||
|
|
||||||
|
[Tooltip("스트리밍이 끊어졌을 때 최대 5회까지 자동으로 재연결을 시도합니다.")]
|
||||||
|
public bool AutoReconnect = true;
|
||||||
|
|
||||||
[Tooltip("Changes to the version of Natnet used by the server")]
|
[Tooltip("Changes to the version of Natnet used by the server")]
|
||||||
public string ServerNatNetVersion = "";
|
public string ServerNatNetVersion = "";
|
||||||
public string ClientNatNetVersion = "";
|
public string ClientNatNetVersion = "";
|
||||||
@ -389,6 +390,13 @@ public class OptitrackStreamingClient : MonoBehaviour
|
|||||||
/// executes on a separate thread). Note while the lock is held, any frame updates received are simply dropped.
|
/// executes on a separate thread). Note while the lock is held, any frame updates received are simply dropped.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private object m_frameDataUpdateLock = new object();
|
private object m_frameDataUpdateLock = new object();
|
||||||
|
|
||||||
|
// 중간에 새 스켈레톤이 생성된 경우 정의 재조회 플래그 (NatNet 스레드에서도 씀 → volatile)
|
||||||
|
private volatile bool m_pendingDefinitionRefresh = false;
|
||||||
|
private float m_definitionRefreshCooldown = 0f;
|
||||||
|
|
||||||
|
// 자동 재연결 진행 중 여부 (중복 재연결 방지)
|
||||||
|
private bool m_isReconnecting = false;
|
||||||
#endregion Private fields
|
#endregion Private fields
|
||||||
|
|
||||||
|
|
||||||
@ -598,6 +606,15 @@ public class OptitrackStreamingClient : MonoBehaviour
|
|||||||
m_latestTMarkMarkerSpheres.Clear();
|
m_latestTMarkMarkerSpheres.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 미등록 스켈레톤이 프레임에 등장했을 때 정의 자동 재조회 (Motive 중간 생성 대응)
|
||||||
|
if (m_pendingDefinitionRefresh && m_definitionRefreshCooldown <= 0f && m_client != null && !SkipDataDescriptions)
|
||||||
|
{
|
||||||
|
m_pendingDefinitionRefresh = false;
|
||||||
|
m_definitionRefreshCooldown = 5f;
|
||||||
|
try { UpdateDefinitions(); }
|
||||||
|
catch (Exception ex) { Debug.LogException(ex, this); }
|
||||||
|
}
|
||||||
|
m_definitionRefreshCooldown -= Time.deltaTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -655,37 +672,71 @@ public class OptitrackStreamingClient : MonoBehaviour
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void Reconnect()
|
public void Reconnect()
|
||||||
{
|
{
|
||||||
Debug.Log("OptiTrack: 재접속을 시도합니다...");
|
if (m_isReconnecting)
|
||||||
|
|
||||||
// 현재 연결이 있다면 먼저 해제
|
|
||||||
if (m_client != null)
|
|
||||||
{
|
{
|
||||||
Debug.Log("OptiTrack: 기존 연결을 해제합니다.");
|
Debug.LogWarning(GetType().FullName + ": 재연결이 이미 진행 중입니다.", this);
|
||||||
OnDisable();
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 잠시 대기 후 재연결
|
Debug.Log("OptiTrack: 재접속을 시도합니다...");
|
||||||
|
|
||||||
|
// 기존 연결 정리 (StopAllCoroutines 포함)
|
||||||
|
OnDisable();
|
||||||
|
|
||||||
StartCoroutine(ReconnectCoroutine());
|
StartCoroutine(ReconnectCoroutine());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Coroutine for handling the reconnection process with a delay.
|
/// Coroutine for handling the reconnection process with a retry loop.
|
||||||
|
/// Attempts up to 5 times: 1s delay on first attempt, 5s on subsequent.
|
||||||
|
/// Last known pose is preserved during reconnect (m_latestSkeletonStates not cleared).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private System.Collections.IEnumerator ReconnectCoroutine()
|
private System.Collections.IEnumerator ReconnectCoroutine()
|
||||||
{
|
{
|
||||||
// 1초 대기 후 재연결 시도
|
m_isReconnecting = true;
|
||||||
yield return new WaitForSeconds(1.0f);
|
const int maxAttempts = 5;
|
||||||
|
|
||||||
try
|
for (int attempt = 1; attempt <= maxAttempts; attempt++)
|
||||||
{
|
{
|
||||||
Debug.Log("OptiTrack: 서버에 재연결을 시도합니다.");
|
float delay = (attempt == 1) ? 1.0f : 5.0f;
|
||||||
OnEnable();
|
Debug.Log(string.Format("{0}: 재연결 시도 {1}/{2} — {3}초 후...", GetType().FullName, attempt, maxAttempts, delay), this);
|
||||||
Debug.Log("OptiTrack: 재연결이 완료되었습니다.");
|
yield return new WaitForSeconds(delay);
|
||||||
}
|
|
||||||
catch (System.Exception ex)
|
// ConnectCoroutine 실행: 연결 수립 + CheckConnectionHealth 시작
|
||||||
{
|
yield return StartCoroutine(ConnectCoroutine());
|
||||||
Debug.LogError("OptiTrack: 재연결 실패 - " + ex.Message);
|
|
||||||
|
// 첫 프레임 수신까지 최대 3초 대기
|
||||||
|
float deadline = Time.realtimeSinceStartup + 3.0f;
|
||||||
|
while (!m_receivedFrameSinceConnect && Time.realtimeSinceStartup < deadline)
|
||||||
|
yield return null;
|
||||||
|
|
||||||
|
if (m_receivedFrameSinceConnect)
|
||||||
|
{
|
||||||
|
Debug.Log(GetType().FullName + ": 재연결 성공.", this);
|
||||||
|
m_isReconnecting = false;
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.LogWarning(string.Format("{0}: 재연결 시도 {1}/{2} 실패 — 데이터 수신 없음.", GetType().FullName, attempt, maxAttempts), this);
|
||||||
|
|
||||||
|
// 다음 시도 전 부분 연결 정리 (ReconnectCoroutine 자신은 중지하지 않도록 StopCoroutine 사용)
|
||||||
|
if (m_connectionHealthCoroutine != null)
|
||||||
|
{
|
||||||
|
StopCoroutine(m_connectionHealthCoroutine);
|
||||||
|
m_connectionHealthCoroutine = null;
|
||||||
|
}
|
||||||
|
if (m_client != null)
|
||||||
|
{
|
||||||
|
if (RecordOnPlay) StopRecording();
|
||||||
|
try { m_client.NativeFrameReceived -= OnNatNetFrameReceived; } catch (System.Exception) { }
|
||||||
|
try { m_client.Disconnect(); } catch (System.Exception) { }
|
||||||
|
try { m_client.Dispose(); } catch (System.Exception) { }
|
||||||
|
m_client = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Debug.LogError(string.Format("{0}: {1}회 재연결 시도 모두 실패. 수동으로 재연결하십시오.", GetType().FullName, maxAttempts), this);
|
||||||
|
m_isReconnecting = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -843,6 +894,36 @@ public class OptitrackStreamingClient : MonoBehaviour
|
|||||||
return skelState;
|
return skelState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 락을 유지한 채로 스켈레톤 포즈를 pre-allocated 딕셔너리에 복사.
|
||||||
|
/// GetLatestSkeletonState() 후 락 없이 BonePoses를 순회하는 torn read를 방지.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>스켈레톤 데이터가 존재하면 true, 없으면 false.</returns>
|
||||||
|
public bool FillBoneSnapshot( Int32 skeletonId,
|
||||||
|
Dictionary<Int32, Vector3> posOut,
|
||||||
|
Dictionary<Int32, Quaternion> oriOut,
|
||||||
|
out OptitrackHiResTimer.Timestamp deliveryTimestamp )
|
||||||
|
{
|
||||||
|
deliveryTimestamp = default( OptitrackHiResTimer.Timestamp );
|
||||||
|
lock ( m_frameDataUpdateLock )
|
||||||
|
{
|
||||||
|
OptitrackSkeletonState state;
|
||||||
|
if ( !m_latestSkeletonStates.TryGetValue( skeletonId, out state ) || state == null )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
deliveryTimestamp = state.DeliveryTimestamp;
|
||||||
|
posOut.Clear();
|
||||||
|
oriOut.Clear();
|
||||||
|
foreach ( var kvp in state.BonePoses )
|
||||||
|
{
|
||||||
|
posOut[kvp.Key] = kvp.Value.Position;
|
||||||
|
oriOut[kvp.Key] = kvp.Value.Orientation;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>Get the most recently received state for the specified trained markerset.</summary>
|
/// <summary>Get the most recently received state for the specified trained markerset.</summary>
|
||||||
/// <param name="tmarkersetId">
|
/// <param name="tmarkersetId">
|
||||||
/// Taken from the corresponding <see cref="OptitrackTMarkersetDefinition.Id"/> field.
|
/// Taken from the corresponding <see cref="OptitrackTMarkersetDefinition.Id"/> field.
|
||||||
@ -1310,95 +1391,80 @@ public class OptitrackStreamingClient : MonoBehaviour
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// (Re)initializes <see cref="m_client"/> and connects to the configured streaming server.
|
/// (Re)initializes <see cref="m_client"/> and connects to the configured streaming server.
|
||||||
|
/// 연결 초기화는 코루틴으로 위임하여 Thread.Sleep으로 메인 스레드를 블락하지 않는다.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void OnEnable()
|
void OnEnable()
|
||||||
{
|
{
|
||||||
IPAddress serverAddr = IPAddress.Parse( ServerAddress );
|
m_receivedFrameSinceConnect = false;
|
||||||
IPAddress localAddr = IPAddress.Parse( LocalAddress );
|
StartCoroutine( ConnectCoroutine() );
|
||||||
|
}
|
||||||
|
|
||||||
|
private System.Collections.IEnumerator ConnectCoroutine()
|
||||||
|
{
|
||||||
|
IPAddress serverAddr;
|
||||||
|
IPAddress localAddr;
|
||||||
NatNetConnectionType connType;
|
NatNetConnectionType connType;
|
||||||
switch ( ConnectionType )
|
|
||||||
{
|
|
||||||
case ClientConnectionType.Unicast:
|
|
||||||
connType = NatNetConnectionType.NatNetConnectionType_Unicast;
|
|
||||||
break;
|
|
||||||
case ClientConnectionType.Multicast:
|
|
||||||
default:
|
|
||||||
connType = NatNetConnectionType.NatNetConnectionType_Multicast;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
serverAddr = IPAddress.Parse( ServerAddress );
|
||||||
|
localAddr = IPAddress.Parse( LocalAddress );
|
||||||
|
connType = ConnectionType == ClientConnectionType.Unicast
|
||||||
|
? NatNetConnectionType.NatNetConnectionType_Unicast
|
||||||
|
: NatNetConnectionType.NatNetConnectionType_Multicast;
|
||||||
|
|
||||||
m_client = new NatNetClient();
|
m_client = new NatNetClient();
|
||||||
m_client.Connect( connType, localAddr, serverAddr );
|
m_client.Connect( connType, localAddr, serverAddr );
|
||||||
|
|
||||||
// Remotely change the Skeleton Coordinate property to Global/Local
|
// Remotely change the Skeleton Coordinate property to Global/Local
|
||||||
if (SkeletonCoordinates == StreamingCoordinatesValues.Global)
|
if (SkeletonCoordinates == StreamingCoordinatesValues.Global)
|
||||||
{
|
|
||||||
m_client.RequestCommand("SetProperty,,Skeleton Coordinates,false");
|
m_client.RequestCommand("SetProperty,,Skeleton Coordinates,false");
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
m_client.RequestCommand("SetProperty,,Skeleton Coordinates,true");
|
m_client.RequestCommand("SetProperty,,Skeleton Coordinates,true");
|
||||||
}
|
|
||||||
|
|
||||||
// Remotely change the Bone Naming Convention to Motive/FBX/BVH
|
// Remotely change the Bone Naming Convention to Motive/FBX/BVH
|
||||||
if(BoneNamingConvention == OptitrackBoneNameConvention.Motive)
|
if (BoneNamingConvention == OptitrackBoneNameConvention.Motive)
|
||||||
{
|
|
||||||
m_client.RequestCommand("SetProperty,,Bone Naming Convention,0");
|
m_client.RequestCommand("SetProperty,,Bone Naming Convention,0");
|
||||||
}
|
|
||||||
else if (BoneNamingConvention == OptitrackBoneNameConvention.FBX)
|
else if (BoneNamingConvention == OptitrackBoneNameConvention.FBX)
|
||||||
{
|
|
||||||
m_client.RequestCommand("SetProperty,,Bone Naming Convention,1");
|
m_client.RequestCommand("SetProperty,,Bone Naming Convention,1");
|
||||||
}
|
|
||||||
else if (BoneNamingConvention == OptitrackBoneNameConvention.BVH)
|
else if (BoneNamingConvention == OptitrackBoneNameConvention.BVH)
|
||||||
{
|
|
||||||
m_client.RequestCommand("SetProperty,,Bone Naming Convention,2");
|
m_client.RequestCommand("SetProperty,,Bone Naming Convention,2");
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure that remotely setting the properties has time to complete.
|
|
||||||
Thread.Sleep(100);
|
|
||||||
|
|
||||||
if (!SkipDataDescriptions)
|
|
||||||
{
|
|
||||||
UpdateDefinitions();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ConnectionType == ClientConnectionType.Unicast)
|
|
||||||
{
|
|
||||||
// Clear all subscriptions
|
|
||||||
ResetStreamingSubscriptions();
|
|
||||||
|
|
||||||
// Re-subscribe to rigid bodies and/or skeletons in which the streaming client has data
|
|
||||||
foreach (KeyValuePair<Int32, MonoBehaviour> rb in m_rigidBodies)
|
|
||||||
{
|
|
||||||
SubscribeRigidBody(rb.Value, rb.Key);
|
|
||||||
}
|
|
||||||
foreach (KeyValuePair<string, MonoBehaviour> skel in m_skeletons)
|
|
||||||
{
|
|
||||||
SubscribeSkeleton(skel.Value, skel.Key);
|
|
||||||
}
|
|
||||||
foreach (KeyValuePair<string, MonoBehaviour> tmark in m_tmarkersets) // trained markerset added
|
|
||||||
{
|
|
||||||
SubscribeTMarkerset(tmark.Value, tmark.Key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if ( RecordOnPlay == true )
|
|
||||||
{
|
|
||||||
StartRecording();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
catch ( Exception ex )
|
catch ( Exception ex )
|
||||||
{
|
{
|
||||||
Debug.LogException( ex, this );
|
Debug.LogException( ex, this );
|
||||||
Debug.LogError( GetType().FullName + ": Error connecting to server; check your configuration, and make sure the server is currently streaming.", this );
|
Debug.LogError( GetType().FullName + ": Error connecting to server; check your configuration, and make sure the server is currently streaming.", this );
|
||||||
this.enabled = false;
|
if (m_client != null) { m_client.Dispose(); m_client = null; }
|
||||||
return;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetProperty 명령이 서버에 적용될 때까지 대기 (메인 스레드 블락 없이)
|
||||||
|
yield return new UnityEngine.WaitForSeconds( 0.1f );
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!SkipDataDescriptions)
|
||||||
|
UpdateDefinitions();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.LogException(ex, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ConnectionType == ClientConnectionType.Unicast)
|
||||||
|
{
|
||||||
|
ResetStreamingSubscriptions();
|
||||||
|
foreach (KeyValuePair<Int32, MonoBehaviour> rb in m_rigidBodies)
|
||||||
|
SubscribeRigidBody(rb.Value, rb.Key);
|
||||||
|
foreach (KeyValuePair<string, MonoBehaviour> skel in m_skeletons)
|
||||||
|
SubscribeSkeleton(skel.Value, skel.Key);
|
||||||
|
foreach (KeyValuePair<string, MonoBehaviour> tmark in m_tmarkersets) // trained markerset added
|
||||||
|
SubscribeTMarkerset(tmark.Value, tmark.Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RecordOnPlay)
|
||||||
|
StartRecording();
|
||||||
|
|
||||||
byte[] NatNetVersion = m_client.ServerDescription.NatNetVersion;
|
byte[] NatNetVersion = m_client.ServerDescription.NatNetVersion;
|
||||||
ServerNatNetVersion = NatNetVersion[0] + "." + NatNetVersion[1] + "." + NatNetVersion[2] + "." + NatNetVersion[3];
|
ServerNatNetVersion = NatNetVersion[0] + "." + NatNetVersion[1] + "." + NatNetVersion[2] + "." + NatNetVersion[3];
|
||||||
ClientNatNetVersion = "" + NatNetClient.NatNetLibVersion;
|
ClientNatNetVersion = "" + NatNetClient.NatNetLibVersion;
|
||||||
@ -1413,21 +1479,21 @@ public class OptitrackStreamingClient : MonoBehaviour
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
void OnDisable()
|
void OnDisable()
|
||||||
{
|
{
|
||||||
if ( m_connectionHealthCoroutine != null )
|
// ConnectCoroutine 포함 모든 코루틴 정지
|
||||||
{
|
StopAllCoroutines();
|
||||||
StopCoroutine( m_connectionHealthCoroutine );
|
m_connectionHealthCoroutine = null;
|
||||||
m_connectionHealthCoroutine = null;
|
m_isReconnecting = false;
|
||||||
}
|
|
||||||
|
|
||||||
if (RecordOnPlay == true)
|
if (m_client != null)
|
||||||
{
|
{
|
||||||
StopRecording();
|
if (RecordOnPlay)
|
||||||
}
|
StopRecording();
|
||||||
|
|
||||||
m_client.NativeFrameReceived -= OnNatNetFrameReceived;
|
m_client.NativeFrameReceived -= OnNatNetFrameReceived;
|
||||||
m_client.Disconnect();
|
try { m_client.Disconnect(); } catch { }
|
||||||
m_client.Dispose();
|
m_client.Dispose();
|
||||||
m_client = null;
|
m_client = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1480,6 +1546,12 @@ public class OptitrackStreamingClient : MonoBehaviour
|
|||||||
// Transition: Good health -> bad health.
|
// Transition: Good health -> bad health.
|
||||||
wasReceivingFrames = false;
|
wasReceivingFrames = false;
|
||||||
Debug.LogWarning( GetType().FullName + ": No streaming frames received from the server recently.", this );
|
Debug.LogWarning( GetType().FullName + ": No streaming frames received from the server recently.", this );
|
||||||
|
if ( AutoReconnect )
|
||||||
|
{
|
||||||
|
Debug.Log( GetType().FullName + ": 자동 재연결을 시작합니다...", this );
|
||||||
|
Reconnect();
|
||||||
|
// OnDisable() → StopAllCoroutines() 로 이 코루틴은 다음 yield 에서 중지됨
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1502,9 +1574,10 @@ public class OptitrackStreamingClient : MonoBehaviour
|
|||||||
/// <param name="eventArgs"></param>
|
/// <param name="eventArgs"></param>
|
||||||
private void OnNatNetFrameReceived( object sender, NatNetClient.NativeFrameReceivedEventArgs eventArgs )
|
private void OnNatNetFrameReceived( object sender, NatNetClient.NativeFrameReceivedEventArgs eventArgs )
|
||||||
{
|
{
|
||||||
// In the event of contention, drop the frame being delivered and return immediately.
|
// 경합 시 최대 1ms 대기 후 드롭.
|
||||||
// We don't want to stall NatNetLib's internal network service thread.
|
// FillBoneSnapshot의 락 보유 시간이 ~0.1ms이므로 정상 상황에서는 드롭 없음.
|
||||||
if ( ! Monitor.TryEnter( m_frameDataUpdateLock ) )
|
// GC Pause 등 1ms 초과 상황에서만 드롭 (허용 가능).
|
||||||
|
if ( ! Monitor.TryEnter( m_frameDataUpdateLock, 1 ) )
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1513,7 +1586,8 @@ public class OptitrackStreamingClient : MonoBehaviour
|
|||||||
{
|
{
|
||||||
// Update health markers.
|
// Update health markers.
|
||||||
m_receivedFrameSinceConnect = true;
|
m_receivedFrameSinceConnect = true;
|
||||||
Interlocked.Exchange( ref m_lastFrameDeliveryTimestamp.m_ticks, OptitrackHiResTimer.Now().m_ticks );
|
OptitrackHiResTimer.Timestamp frameTimestamp = OptitrackHiResTimer.Now();
|
||||||
|
Interlocked.Exchange( ref m_lastFrameDeliveryTimestamp.m_ticks, frameTimestamp.m_ticks );
|
||||||
|
|
||||||
// Process received frame.
|
// Process received frame.
|
||||||
IntPtr pFrame = eventArgs.NativeFramePointer;
|
IntPtr pFrame = eventArgs.NativeFramePointer;
|
||||||
@ -1572,6 +1646,7 @@ public class OptitrackStreamingClient : MonoBehaviour
|
|||||||
|
|
||||||
// Ensure we have a state corresponding to this skeleton ID.
|
// Ensure we have a state corresponding to this skeleton ID.
|
||||||
OptitrackSkeletonState skelState = GetOrCreateSkeletonState( skeletonId );
|
OptitrackSkeletonState skelState = GetOrCreateSkeletonState( skeletonId );
|
||||||
|
skelState.DeliveryTimestamp = frameTimestamp;
|
||||||
|
|
||||||
// Enumerate this skeleton's bone rigid bodies.
|
// Enumerate this skeleton's bone rigid bodies.
|
||||||
Int32 skelRbCount;
|
Int32 skelRbCount;
|
||||||
@ -1612,7 +1687,10 @@ public class OptitrackStreamingClient : MonoBehaviour
|
|||||||
OptitrackSkeletonDefinition skelDef = GetSkeletonDefinitionById(skeletonId);
|
OptitrackSkeletonDefinition skelDef = GetSkeletonDefinitionById(skeletonId);
|
||||||
if (skelDef == null)
|
if (skelDef == null)
|
||||||
{
|
{
|
||||||
Debug.LogError(GetType().FullName + ": OnNatNetFrameReceived, no corresponding skeleton definition for received skeleton frame data.", this);
|
// Motive에서 중간에 스켈레톤이 생성된 경우 — 메인 스레드에서 정의 재조회 예약
|
||||||
|
if (!m_pendingDefinitionRefresh)
|
||||||
|
Debug.LogWarning(GetType().FullName + ": 알 수 없는 스켈레톤 ID " + skeletonId + " — 정의 재조회 예약됨.", this);
|
||||||
|
m_pendingDefinitionRefresh = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
BIN
Assets/External/OptiTrack Unity Plugin/README.md
(Stored with Git LFS)
vendored
Normal file
BIN
Assets/External/OptiTrack Unity Plugin/README.md
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
@ -1,6 +1,6 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 1a66efc1999717242b75f047a3877193
|
guid: 0e7e6625c79d3c146b42d152675716c1
|
||||||
PrefabImporter:
|
TextScriptImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
userData:
|
userData:
|
||||||
assetBundleName:
|
assetBundleName:
|
||||||
@ -987,10 +987,11 @@ namespace KindRetargeting
|
|||||||
targetHips.position = adjustedPosition;
|
targetHips.position = adjustedPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 스파인/넥 분배를 먼저 실행하여 부모 계층 확정 후 자식 본(Head/Shoulder/Arm) 세팅
|
||||||
|
ApplyOptiTrackSpineNeckDistribution();
|
||||||
|
|
||||||
// 힙을 제외한 본들의 회전 동기화
|
// 힙을 제외한 본들의 회전 동기화
|
||||||
SyncBoneRotations(skipBone: HumanBodyBones.Hips);
|
SyncBoneRotations(skipBone: HumanBodyBones.Hips);
|
||||||
|
|
||||||
ApplyOptiTrackSpineNeckDistribution();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
BIN
Assets/Scripts/KindRetargeting/README.md
(Stored with Git LFS)
Normal file
BIN
Assets/Scripts/KindRetargeting/README.md
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -1,6 +1,6 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: ecb211056d7c61047aa8380b0b541a81
|
guid: d824776c483e7cc479af82ca17d3ac7f
|
||||||
PrefabImporter:
|
TextScriptImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
userData:
|
userData:
|
||||||
assetBundleName:
|
assetBundleName:
|
||||||
@ -770,12 +770,15 @@ namespace KindRetargeting.Remote
|
|||||||
{
|
{
|
||||||
var field = obj.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
|
var field = obj.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
|
||||||
if (field != null)
|
if (field != null)
|
||||||
{
|
|
||||||
return (T)field.GetValue(obj);
|
return (T)field.GetValue(obj);
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception) { }
|
|
||||||
|
|
||||||
|
// 필드를 찾지 못함 — 필드명 변경이나 오타 확인 필요
|
||||||
|
Debug.LogWarning($"[RetargetingRemote] 필드를 찾을 수 없음: {fieldName} ({obj.GetType().Name}) — 필드명 변경 여부 확인");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.LogError($"[RetargetingRemote] 필드 읽기 오류 ({fieldName}): {ex.Message}");
|
||||||
|
}
|
||||||
return default(T);
|
return default(T);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -787,7 +790,10 @@ namespace KindRetargeting.Remote
|
|||||||
if (field != null)
|
if (field != null)
|
||||||
{
|
{
|
||||||
field.SetValue(obj, value);
|
field.SetValue(obj, value);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
// 필드를 찾지 못함 — 값이 적용되지 않음
|
||||||
|
Debug.LogError($"[RetargetingRemote] 필드를 찾을 수 없음: {fieldName} ({obj.GetType().Name}) — 필드명 변경 여부 확인");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user