Я пытаюсь написать код для передачи анимации, которая была разработана для одного скелета, чтобы он выглядел правильно на другом скелете. Исходные анимации состоят только из вращений, за исключением переводов в корне (это анимации mocap из базы данных захвата движения CMU ). Многие 3D-приложения (например, Maya) имеют встроенную функцию, но я пытаюсь написать (очень простую) версию для моей игры.
Я проделал некоторую работу по картированию костей, и, поскольку скелеты иерархически похожи (двуногие), я могу сделать картирование костей 1: 1 для всего, кроме позвоночника (с этим можно будет поработать позже). Проблема, однако, заключается в том, что базовые позы скелета / связывания отличаются, а кости имеют разные масштабы (короче / длиннее), поэтому, если я просто скопирую вращение по прямой, это будет выглядеть очень странно.
Я попытался сделать несколько вещей, похожих на приведенное ниже решение Лоранку, но безрезультатно (то есть умножить каждый кадр в анимации на умножитель для кости). Если у кого-то есть ресурсы на такие вещи (документы, исходный код и т. Д.), Это было бы очень полезно.
источник
Ответы:
Проблема заключалась в численной стабильности. Приблизительно 30 часов работы над этим в течение 2 месяцев, только чтобы понять, что я делал это правильно с самого начала. Когда я нормализовал матрицы вращения перед тем, как вставить их в код ретаргетинга, простое решение умножения исходного * обратного (целевого) отлично сработало. Конечно, есть еще кое-что для ретаргетинга (в частности, принимая во внимание различные формы скелета, например, ширину плеч и т. Д.). Вот код, который я использую для простого, наивного подхода, если кому-то интересно:
источник
Я считаю, что ваш самый простой вариант - просто сопоставить исходную позу связывания с вашим новым скелетом, если у вас есть такая возможность (если ваш новый скелет еще не снят).
Если вы не можете сделать это, вот что вы можете попробовать. Это просто интуиция, я, вероятно, упускаю из виду многие вещи, но это может помочь вам найти свет. Для каждой кости:
В вашей «старой» позе связывания у вас есть один кватернион, который описывает относительное вращение этой кости по сравнению с ее родительской костью. Вот подсказка о том, как его найти. Давайте назовем это
q_old
.Там же. для вашей "новой" позы связывания, давайте назовем это
q_new
.Вы можете найти относительное вращение от «новой» позы привязки к «старой» позе бина, как описано здесь . Это
q_new_to_old = inverse(q_new) * q_old
.Затем в одном ключе анимации вы получите один кватернион, который преобразует эту кость из «старой» позы связывания в анимированную позу. Давайте назовем это
q_anim
.Вместо
q_anim
непосредственного использования , попробуйте использоватьq_new_to_old * q_anim
. Это должно «отменить» различия в ориентации между позами привязки перед применением анимации.Это может помочь.
РЕДАКТИРОВАТЬ
Ваш код выше, кажется, следует логике, которую я здесь описываю, но что-то перевернуто. Вместо этого:
Вы можете попробовать это:
Я думаю, что вам нужно перейти от вашей цели к вашему источнику перед применением исходной анимации, чтобы получить ту же конечную ориентацию.
источник