@@ -62,6 +62,25 @@ public Vector3 GetPositionOffset()
6262            } 
6363        } 
6464
65+         /// <summary> 
66+         /// Allows one to adjust the per-joint rotation offsets computed between 
67+         /// source (OVRBody) and target characters. To avoid gimbal lock, 
68+         /// a series of rotations are permitted. 
69+         /// </summary> 
70+         [ System . Serializable ] 
71+         public  class  JointRotationTweaks 
72+         { 
73+             /// <summary> 
74+             /// Joint to affect. 
75+             /// </summary> 
76+             public  HumanBodyBones  Joint ; 
77+ 
78+             /// <summary> 
79+             /// A series of rotation tweaks. 
80+             /// </summary> 
81+             public  Quaternion [ ]  RotationTweaks ; 
82+         } 
83+ 
6584        /// <summary> 
6685        /// The array of joint position adjustments. 
6786        /// </summary> 
@@ -160,6 +179,25 @@ public RetargetingAnimationConstraint RetargetingConstraint
160179            set  {  _retargetingAnimationConstraint  =  value ;  } 
161180        } 
162181
182+         /// <summary> 
183+         /// Joint rotation tweaks array. 
184+         /// </summary> 
185+         [ SerializeField ] 
186+         [ Tooltip ( RetargetingLayerTooltips . JointRotationTweaks ) ] 
187+         protected  JointRotationTweaks [ ]  _jointRotationTweaks ; 
188+         public  JointRotationTweaks [ ]  JointRotationTweaksArray 
189+         { 
190+             get  =>  _jointRotationTweaks ; 
191+             set  =>  _jointRotationTweaks  =  value ; 
192+         } 
193+         /// <summary> 
194+         /// Pre-compute these values each time the editor changes for the purposes 
195+         /// of efficiency. 
196+         /// </summary> 
197+         private  Dictionary < HumanBodyBones ,  Quaternion >  _humanBoneToAccumulatedRotationTweaks  = 
198+             new  Dictionary < HumanBodyBones ,  Quaternion > ( ) ; 
199+         private  List < HumanBodyBones >  _bonesToRemove  =  new  List < HumanBodyBones >  ( ) ; 
200+ 
163201        private  Pose [ ]  _defaultPoses ; 
164202        private  IJointConstraint [ ]  _jointConstraints ; 
165203        private  ProxyTransformLogic  _proxyTransformLogic  =  new  ProxyTransformLogic ( ) ; 
@@ -220,6 +258,8 @@ protected override void Start()
220258            CacheJointConstraints ( ) ; 
221259
222260            ValidateHumanoid ( ) ; 
261+ 
262+             PrecomputeJointRotationTweaks ( ) ; 
223263        } 
224264
225265        private  void  ConstructDefaultPoseInformation ( ) 
@@ -305,6 +345,78 @@ protected virtual void OnApplicationFocus(bool hasFocus)
305345            _isFocusedWhileInBuild  =  hasFocus ; 
306346        } 
307347
348+         protected  virtual  void  OnValidate ( ) 
349+         { 
350+             PrecomputeJointRotationTweaks ( ) ; 
351+         } 
352+ 
353+         /// <summary> 
354+         /// When the object's properties are modified, accumulate joint rotations 
355+         /// and cache those values. This saves on computation when the tweaks field is used. 
356+         /// </summary> 
357+         protected  void  PrecomputeJointRotationTweaks ( ) 
358+         { 
359+ #if UNITY_EDITOR 
360+             if  ( ! UnityEditor . EditorApplication . isPlaying ) 
361+             { 
362+                 return ; 
363+             } 
364+ #endif
365+ 
366+             foreach  ( var  rotationTweak  in  _jointRotationTweaks ) 
367+             { 
368+                 var  allRotations  =  rotationTweak . RotationTweaks ; 
369+                 var  joint  =  rotationTweak . Joint ; 
370+ 
371+                 Quaternion  accumulatedRotation  =  Quaternion . identity ; 
372+                 foreach  ( var  rotationValue  in  allRotations ) 
373+                 { 
374+                     // Make sure the quaternion is valid. Quaternions are initialized to all 
375+                     // zeroes by default, which makes them invalid. 
376+                     if  ( rotationValue . w  <  Mathf . Epsilon  &&  rotationValue . x  <  Mathf . Epsilon  && 
377+                         rotationValue . y  <  Mathf . Epsilon  &&  rotationValue . z  <  Mathf . Epsilon ) 
378+                     { 
379+                         continue ; 
380+                     } 
381+ 
382+                     accumulatedRotation  *=  rotationValue ; 
383+                 } 
384+ 
385+                 if  ( ! _humanBoneToAccumulatedRotationTweaks . ContainsKey ( joint ) ) 
386+                 { 
387+                     _humanBoneToAccumulatedRotationTweaks . Add ( joint ,  accumulatedRotation ) ; 
388+                 } 
389+                 else 
390+                 { 
391+                     _humanBoneToAccumulatedRotationTweaks [ joint ]  =  accumulatedRotation ; 
392+                 } 
393+             } 
394+ 
395+             _bonesToRemove . Clear ( ) ; 
396+             // If the user removed bones from the UI, remove those from the dictionary. 
397+             foreach  ( var  bone  in  _humanBoneToAccumulatedRotationTweaks . Keys ) 
398+             { 
399+                 bool  boneFound  =  false ; 
400+                 foreach  ( var  rotationTweak  in  _jointRotationTweaks ) 
401+                 { 
402+                     if  ( rotationTweak . Joint  ==  bone ) 
403+                     { 
404+                         boneFound  =  true ; 
405+                         break ; 
406+                     } 
407+                 } 
408+ 
409+                 if  ( ! boneFound ) 
410+                 { 
411+                     _bonesToRemove . Add ( bone ) ; 
412+                 } 
413+             } 
414+             foreach ( var  boneToRemove  in  _bonesToRemove ) 
415+             { 
416+                 _humanBoneToAccumulatedRotationTweaks . Remove ( boneToRemove ) ; 
417+             } 
418+         } 
419+ 
308420        /// <inheritdoc /> 
309421        protected  override  void  Update ( ) 
310422        { 
@@ -419,7 +531,7 @@ private void CorrectBones()
419531                        targetJoint . rotation  = 
420532                            Quaternion . Slerp ( targetJoint . rotation , 
421533                                Bones [ i ] . Transform . rotation  * 
422-                                 targetData . CorrectionQuaternion . Value , 
534+                                 targetData . CorrectionQuaternion . Value   *   GetRotationTweak ( humanBodyBone ) , 
423535                                handWeight ) ; 
424536                    } 
425537                    if  ( _correctPositionsLateUpdate ) 
@@ -438,7 +550,7 @@ private void CorrectBones()
438550                            targetJoint . rotation  = 
439551                                Quaternion . Slerp ( targetJoint . rotation , 
440552                                    Bones [ i ] . Transform . rotation  * 
441-                                     targetData . CorrectionQuaternion . Value , 
553+                                     targetData . CorrectionQuaternion . Value   *   GetRotationTweak ( humanBodyBone ) , 
442554                                    handWeight ) ; 
443555                        } 
444556
@@ -455,6 +567,18 @@ private void CorrectBones()
455567            } 
456568        } 
457569
570+         protected  Quaternion  GetRotationTweak ( HumanBodyBones  humanBody ) 
571+         { 
572+             Quaternion  rotation ; 
573+ 
574+             if  ( ! _humanBoneToAccumulatedRotationTweaks . TryGetValue ( humanBody ,  out  rotation ) ) 
575+             { 
576+                 rotation  =  Quaternion . identity ; 
577+             } 
578+ 
579+             return  rotation ; 
580+         } 
581+ 
458582        protected  virtual  bool  ShouldUpdatePositionOfBone ( HumanBodyBones  humanBodyBone ) 
459583        { 
460584            var  bodySectionOfJoint  =  OVRHumanBodyBonesMappings . BoneToBodySection [ humanBodyBone ] ; 
@@ -516,7 +640,8 @@ public void FillTransformArrays(List<Transform> sourceTransforms,
516640                targetTransforms . Add ( targetBoneData . OriginalJoint ) ; 
517641                shouldUpdatePositions . Add ( false ) ; 
518642                shouldUpdateRotations . Add ( false ) ; 
519-                 rotationOffsets . Add ( targetBoneData . CorrectionQuaternion . Value ) ; 
643+                 rotationOffsets . Add ( targetBoneData . CorrectionQuaternion . Value  * 
644+                     GetRotationTweak ( targetHumanBodyBone ) ) ; 
520645                rotationAdjustments . Add ( Quaternion . identity ) ; 
521646            } 
522647        } 
@@ -582,14 +707,16 @@ public void UpdateAdjustments(Quaternion[] rotationOffsets,
582707
583708                if  ( adjustment  ==  null ) 
584709                { 
585-                     SetUpDefaultAdjustment ( rotationOffsets ,  shouldUpdatePositions , 
710+                     SetUpDefaultAdjustment ( targetHumanBodyBone , 
711+                         rotationOffsets ,  shouldUpdatePositions , 
586712                        shouldUpdateRotations ,  rotationAdjustments ,  arrayId , 
587713                        targetBoneData ,  bodySectionInPositionArray , 
588714                        jointFailsMask ) ; 
589715                } 
590716                else 
591717                { 
592-                     SetUpCustomAdjustment ( rotationOffsets ,  shouldUpdatePositions , 
718+                     SetUpCustomAdjustment ( targetHumanBodyBone , 
719+                         rotationOffsets ,  shouldUpdatePositions , 
593720                        shouldUpdateRotations , 
594721                        rotationAdjustments ,  adjustment ,  arrayId , 
595722                        targetBoneData ,  bodySectionInPositionArray , 
@@ -600,26 +727,28 @@ public void UpdateAdjustments(Quaternion[] rotationOffsets,
600727            } 
601728        } 
602729
603-         private  void  SetUpDefaultAdjustment ( Quaternion [ ]  rotationOffsets , 
730+         private  void  SetUpDefaultAdjustment ( HumanBodyBones   humanBodyBone ,   Quaternion [ ]  rotationOffsets , 
604731            bool [ ]  shouldUpdatePositions ,  bool [ ]  shouldUpdateRotations , 
605732            Quaternion [ ]  rotationAdjustments ,  int  arrayId , 
606733            OVRSkeletonMetadata . BoneData  targetBoneData , 
607734            bool  bodySectionInPositionArray ,  bool  jointFailsMask ) 
608735        { 
609-             rotationOffsets [ arrayId ]  =  targetBoneData . CorrectionQuaternion . Value ; 
736+             rotationOffsets [ arrayId ]  =  targetBoneData . CorrectionQuaternion . Value  * 
737+                 GetRotationTweak ( humanBodyBone ) ; 
610738            shouldUpdatePositions [ arrayId ]  =  ! jointFailsMask  &&  bodySectionInPositionArray ; 
611739            shouldUpdateRotations [ arrayId ]  =  ! jointFailsMask ; 
612740            rotationAdjustments [ arrayId ]  =  Quaternion . identity ; 
613741        } 
614742
615-         private  void  SetUpCustomAdjustment ( Quaternion [ ]  rotationOffsets , 
743+         private  void  SetUpCustomAdjustment ( HumanBodyBones   humanBodyBone ,   Quaternion [ ]  rotationOffsets , 
616744            bool [ ]  shouldUpdatePositions ,  bool [ ]  shouldUpdateRotations , 
617745            Quaternion [ ]  rotationAdjustments , 
618746            JointAdjustment  adjustment ,  int  arrayId , 
619747            OVRSkeletonMetadata . BoneData  targetBoneData , 
620748            bool  bodySectionInPositionArray ,  bool  jointFailsMask ) 
621749        { 
622-             rotationOffsets [ arrayId ]  =  targetBoneData . CorrectionQuaternion . Value ; 
750+             rotationOffsets [ arrayId ]  =  targetBoneData . CorrectionQuaternion . Value  * 
751+                 GetRotationTweak ( humanBodyBone ) ; 
623752            shouldUpdatePositions [ arrayId ]  = 
624753                ! adjustment . DisablePositionTransform  && 
625754                bodySectionInPositionArray  && 
0 commit comments