- Home /
Issues constraining angles in CCD
I'm terrible at maths and have been working on an IK solution to try and get more comfortable with using maths/angles in Unity.
I've been able to made a CCD solution which works like this: https://www.youtube.com/watch?v=tZvdZGUxbbc
But when I try to put angle constraints on the joints, I get some weird behaviour - shown here: https://www.youtube.com/watch?v=iYh80XrmDJs&feature=youtu.be
When constrained there seems to be a dead zone around the hips where the limb fails to reach to target properly and even appears to move away from it.
Here is the code to calculate each joint rotation in the chain:
Vector3 vectorCurrJointToEndEffector = (joints[joints.Length - 1].transform.position - joints[i].transform.position).normalized; //normalised vector from current joint to end effector position
Vector3 vectorCurrJointToTarget = (target.transform.position - joints[i].transform.position).normalized; //normalised vector from current joint to targetposition
float cosineAngle = Mathf.Clamp(Vector3.Dot(vectorCurrJointToEndEffector, vectorCurrJointToTarget), -1.0f, 1.0f); //dot product gives the cosine of the angle for the corrective rotation
//clamping to value between -1 and 1 removes any floating errors
Vector3 crossProduct = Vector3.Cross(vectorCurrJointToEndEffector, vectorCurrJointToTarget).normalized; //normalised cross product gives the axis on which to rotate the joint
float toRotateDegrees = Mathf.Acos(cosineAngle); //calculate joint rotation, in radians
toRotateDegrees = toRotateDegrees * Mathf.Rad2Deg; //get rotation in degrees
joints[i].transform.rotation = Quaternion.AngleAxis(toRotateDegrees, crossProduct) * joints[i].transform.rotation; //apply joint rotation
Here is the code to constrain the joint angles:
Vector3 currentJointEulerAngles = joints[i].joint.transform.localRotation.eulerAngles; //get rotation
//ensure rotation angles stay relative regardless of rotation extent
//X
if (currentJointEulerAngles.x > 180f)
{
currentJointEulerAngles.x -= 360f;
}
currentJointEulerAngles.x = Mathf.Clamp(currentJointEulerAngles.x, joints[i].XaxisMin, joints[i].XaxisMax); //clamp x
//Y
if (currentJointEulerAngles.y > 180f)
{
currentJointEulerAngles.y -= 360f;
}
currentJointEulerAngles.y = Mathf.Clamp(currentJointEulerAngles.y, joints[i].YaxisMin, joints[i].YaxisMax); //clamp y
//Z
if (currentJointEulerAngles.z > 180f)
{
currentJointEulerAngles.z -= 360f;
}
currentJointEulerAngles.z = Mathf.Clamp(currentJointEulerAngles.z, joints[i].ZaxisMin, joints[i].ZaxisMax); //clamp z
joints[i].joint.transform.localEulerAngles = currentJointEulerAngles; //set clamped rotation
Can anyone suggest/provide a fix for this?
Any help is appreciated. I have been stuck at this stage for over a week now!
Thanks