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;
}
}