public bool Solve( FullBodyIK fullBodyIK )
{
if( _neckBone == null || !_neckBone.transformIsAlive ||
_headBone == null || !_headBone.transformIsAlive ||
_headBone.parentBone == null || !_headBone.parentBone.transformIsAlive ) {
return false;
}
_SyncDisplacement( fullBodyIK );
float headPositionWeight = _headEffector.positionEnabled ? _headEffector.positionWeight : 0.0f;
float eyesPositionWeight = _eyesEffector.positionEnabled ? _eyesEffector.positionWeight : 0.0f;
if( headPositionWeight <= IKEpsilon && eyesPositionWeight <= IKEpsilon ) {
Quaternion parentWorldRotation = _neckBone.parentBone.worldRotation;
Quaternion parentBaseRotation;
SAFBIKQuatMult( out parentBaseRotation, ref parentWorldRotation, ref _neckBone.parentBone._worldToBaseRotation );
if( _internalValues.resetTransforms ) {
Quaternion tempRotation;
SAFBIKQuatMult( out tempRotation, ref parentBaseRotation, ref _neckBone._baseToWorldRotation );
_neckBone.worldRotation = tempRotation;
}
float headRotationWeight = _headEffector.rotationEnabled ? _headEffector.rotationWeight : 0.0f;
if( headRotationWeight > IKEpsilon ) {
Quaternion headEffectorWorldRotation = _headEffector.worldRotation;
Quaternion toRotation;
SAFBIKQuatMult( out toRotation, ref headEffectorWorldRotation, ref _headEffectorToWorldRotation );
if( headRotationWeight < 1.0f - IKEpsilon ) {
Quaternion fromRotation;
if( _internalValues.resetTransforms ) {
SAFBIKQuatMult( out fromRotation, ref parentBaseRotation, ref _headBone._baseToWorldRotation );
} else {
fromRotation = _headBone.worldRotation; // This is able to use _headBone.worldRotation directly.
}
_headBone.worldRotation = Quaternion.Lerp( fromRotation, toRotation, headRotationWeight );
} else {
_headBone.worldRotation = toRotation;
}
_HeadRotationLimit();
} else {
if( _internalValues.resetTransforms ) {
Quaternion tempRotation;
SAFBIKQuatMult( out tempRotation, ref parentBaseRotation, ref _headBone._baseToWorldRotation );
_headBone.worldRotation = tempRotation;
}
}
if( _internalValues.resetTransforms ) {
if( _isEnabledCustomEyes ) {
fullBodyIK._ResetCustomEyes();
} else {
_ResetEyes();
}
}
return _internalValues.resetTransforms || (headRotationWeight > IKEpsilon);
}
_Solve( fullBodyIK );
return true;
}