//-------------------------------------------------------------------------------------------------------------------- // for Finger. public static bool _LimitFingerNotThumb( bool isRight, ref Vector3 dir, // dirX ref FastAngle limitYPlus, ref FastAngle limitYMinus, ref FastAngle limitZ ) { bool isLimited = false; // Yaw if( limitZ.cos > IKEpsilon ) { // Memo: Unstable when dir.z near 1. if( dir.z < -limitZ.sin || dir.z > limitZ.sin ) { isLimited = true; bool isPlus = (dir.z >= 0.0f); float lenXY = SAFBIKSqrt( dir.x * dir.x + dir.y * dir.y ); if( limitZ.sin <= IKEpsilon ) { // Optimized. if( lenXY > IKEpsilon ) { dir.z = 0.0f; dir = dir * (1.0f / lenXY); } else { // Failsafe. dir.Set( isRight ? limitZ.cos : -limitZ.cos, 0.0f, isPlus ? limitZ.sin : -limitZ.sin ); } } else { float lenZ = limitZ.sin * lenXY / limitZ.cos; dir.z = isPlus ? lenZ : -lenZ; float len = dir.magnitude; if( len > IKEpsilon ) { dir *= (1.0f / len); } else { // Failsafe. dir.Set( isRight ? limitZ.cos : -limitZ.cos, 0.0f, isPlus ? limitZ.sin : -limitZ.sin ); } } } } // Pitch { // Memo: Not use z.( For yaw limit. ) bool isPlus = (dir.y >= 0.0f); float cosPitchLimit = isPlus ? limitYPlus.cos : limitYMinus.cos; if( (isRight && dir.x < cosPitchLimit) || (!isRight && dir.x > -cosPitchLimit) ) { float lenY = SAFBIKSqrt( 1.0f - (cosPitchLimit * cosPitchLimit + dir.z * dir.z) ); dir.x = (isRight ? cosPitchLimit : -cosPitchLimit); dir.y = (isPlus ? lenY : -lenY); } } return isLimited; }
public FingerIK( FullBodyIK fullBodyIK, FingerIKType fingerIKType ) { _fingerIKType = fingerIKType; _settings = fullBodyIK.settings; _internalValues = fullBodyIK.internalValues; FingersBones fingerBones = null; FingersEffectors fingerEffectors = null; switch( fingerIKType ) { case FingerIKType.LeftWrist: _parentBone = fullBodyIK.leftArmBones.wrist; fingerBones = fullBodyIK.leftHandFingersBones; fingerEffectors = fullBodyIK.leftHandFingersEffectors; break; case FingerIKType.RightWrist: _parentBone = fullBodyIK.rightArmBones.wrist; fingerBones = fullBodyIK.rightHandFingersBones; fingerEffectors = fullBodyIK.rightHandFingersEffectors; break; } _notThumb1PitchUTraceSmooth = new FastAngle( _notThumb1PitchUTrace.angle + _notThumb1PitchUSmooth.angle ); if( fingerBones != null && fingerEffectors != null ) { for( int fingerType = 0; fingerType < (int)FingerType.Max; ++fingerType ) { Bone[] bones = null; Effector effector = null; switch( fingerType ) { case (int)FingerType.Thumb: bones = fingerBones.thumb; effector = fingerEffectors.thumb; break; case (int)FingerType.Index: bones = fingerBones.index; effector = fingerEffectors.index; break; case (int)FingerType.Middle: bones = fingerBones.middle; effector = fingerEffectors.middle; break; case (int)FingerType.Ring: bones = fingerBones.ring; effector = fingerEffectors.ring; break; case (int)FingerType.Little: bones = fingerBones.little; effector = fingerEffectors.little; break; } if( bones != null && effector != null ) { _PrepareBranch( fingerType, bones, effector ); } } } }
public static Vector3 _Rotate( ref Vector3 dirX, ref Vector3 dirY, ref FastAngle angle ) { return dirX * angle.cos + dirY * angle.sin; }