Как ограничить вращение суставов в CCDC#

Место общения программистов C#
Ответить
Anonymous
 Как ограничить вращение суставов в CCD

Сообщение Anonymous »

Я отчаянно борюсь с математикой, пытаясь улучшиться. Я пытался создать решение IK в Unity.

Я создал простой алгоритм CCD, который ведет себя так, как задумано:

Но когда я пытаюсь добавить ограничения к углам соединения, поведение становится неточным и искажается:

В настоящее время у меня есть цикл for, который перебирает все соединения в цепочке, пока цель не достигнута, и текущие попытки < пороговое значение попыток.

После того, как корректирующее вращение для каждого соединения рассчитано, я применяю его к суставу .
Затем я проверяю вращение в каждом соединении, зажимая его внутри это диапазон мин-макс.

Вот код, который применяет вращение, а затем проверяет пределы вращения:

Код: Выделить всё

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;

Как показано во втором видео, результат очень плохой.

Может ли кто-нибудь предложить решение и, возможно, объяснение, почему это не работает?

обновлено, исправлена ​​опечатка во вставленном коде.>

Подробнее здесь: https://stackoverflow.com/questions/565 ... ons-in-ccd
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»