Ich habe einen einfachen CCD-Algorithmus erstellt, der sich wie beabsichtigt verhält:
Aber wenn ich versuche, Einschränkungen zu den Gelenkwinkeln hinzuzufügen, ist das Verhalten ungenau und verzerrt:
Derzeit habe ich eine for-Schleife, die alle Gelenke in der Kette durchläuft, solange das Ziel nicht erreicht wird und die aktuellen Versuche < Versuchsschwellenwert sind.
Sobald die Korrekturdrehung für jedes Gelenk berechnet ist, wende ich sie auf Gelenk an.
Dann überprüfe ich die Drehung an jedem Gelenk und klemme es ein Es ist der Min-Max-Bereich.
Hier ist der Code, der die Rotation anwendet und dann die Rotationsgrenzen überprüft:
Code: Select all
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 = Vector3.Dot(vectorCurrJointToEndEffector, vectorCurrJointToTarget); //dot product gives the cosine of the angle for the corrective rotation
//limit possibilities
if (cosineAngle < 1)
{
Vector3 crossProduct = Vector3.Cross(vectorCurrJointToEndEffector, vectorCurrJointToTarget).normalized; //normalised cross product gives the axis on which to rotate the joint
float toRotateDegrees = Mathf.Acos(cosineAngle) * Mathf.Rad2Deg; //calculate joint rotation in degrees
joints[i].transform.rotation = Quaternion.AngleAxis(toRotateDegrees, crossProduct) * joints[i].transform.rotation; //apply joint rotation
joints[i].transform.rotation = Quaternion.AngleAxis(toRotateDegrees, crossProduct) * joints[i].transform.rotation; //apply joint rotation
//clamp current joint rotation within set limits
Vector3 currentJointEulerAngles = joints[i].joint.transform.localRotation.eulerAngles;
if (currentJointEulerAngles.x > 180f)
currentJointEulerAngles.x -= 360f;
currentJointEulerAngles.x = Mathf.Clamp(currentJointEulerAngles.x, joints[i].XaxisMin, joints[i].XaxisMax);
if (currentJointEulerAngles.y > 180f)
currentJointEulerAngles.y -= 360f;
currentJointEulerAngles.y = Mathf.Clamp(currentJointEulerAngles.y, joints[i].YaxisMin, joints[i].YaxisMax);
if (currentJointEulerAngles.z > 180f)
currentJointEulerAngles.z -= 360f;
currentJointEulerAngles.z = Mathf.Clamp(currentJointEulerAngles.z, joints[i].ZaxisMin, joints[i].ZaxisMax);
joints[i].joint.transform.localEulerAngles = currentJointEulerAngles;
Könnte jemand eine Lösung vorschlagen und möglicherweise eine Erklärung, warum das nicht funktioniert?
Aktualisierter, korrigierter Tippfehler im eingefügten Code.
Mobile version