Próbuję napisać kod, aby przenieść animacje zaprojektowane dla jednego szkieletu, aby wyglądały poprawnie na innym szkielecie. Animacje źródłowe składają się tylko z rotacji, z wyjątkiem tłumaczeń w katalogu głównym (są to animacje mocap z bazy danych przechwytywania ruchu CMU ). Wiele aplikacji 3D (np. Maya) ma wbudowane to narzędzie, ale staram się napisać (bardzo prostą) wersję dla mojej gry.
Zrobiłem trochę pracy nad mapowaniem kości, a ponieważ szkielety są hierarchicznie podobne (dwunożne), mogę wykonać mapowanie kości 1: 1 dla wszystkiego oprócz kręgosłupa (mogę pracować nad tym później). Problemem jest jednak to, że podstawowe pozycje szkieletu / wiązania są różne, a kości mają różne skale (krótsze / dłuższe), więc jeśli po prostu skopiuję obrót prosto, wygląda to bardzo dziwnie.
Próbowałem wielu rzeczy podobnych do rozwiązania Lorancou poniżej, ale bezskutecznie (tj. Pomnożenie każdej klatki w animacji przez mnożnik właściwy dla kości). Jeśli ktoś ma jakieś zasoby na takie rzeczy (dokumenty, kod źródłowy itp.), Byłoby to naprawdę pomocne.
źródło
Odpowiedzi:
Problem polegał na stabilności liczbowej. Około 30 godzin pracy nad tym w ciągu 2 miesięcy, tylko po to, aby dowiedzieć się, że robiłem to od samego początku. Kiedy ortormalizowałem macierze rotacji przed podłączeniem ich do kodu retarget, proste rozwiązanie polegające na pomnożeniu odwrotności source * (target) działało idealnie. Oczywiście jest o wiele więcej do retargetowania niż to (w szczególności biorąc pod uwagę różne kształty szkieletu, tj. Szerokość ramion itp.). Oto kod, którego używam do prostego, naiwnego podejścia, jeśli ktoś jest ciekawy:
źródło
Uważam, że najłatwiejszą opcją jest po prostu dopasowanie oryginalnej pozycji wiązania do nowego szkieletu, jeśli masz taką możliwość (jeśli nowy szkielet nie jest jeszcze pozbawiony skórki).
Jeśli nie możesz tego zrobić, możesz spróbować. To tylko intuicja, prawdopodobnie przeoczam wiele rzeczy, ale może ci pomóc znaleźć światło. Dla każdej kości:
W „starej” pozycji wiązania masz jeden czwartorzęd, który opisuje względny obrót tej kości w porównaniu do jej kości macierzystej . Oto wskazówka, jak go znaleźć. Nazwijmy to
q_old
.Tamże na swoją „nową” pozycję wiązania, nazwijmy to
q_new
.Względny obrót można znaleźć od „nowej” pozycji wiązania do „starej” pozycji bin, jak opisano tutaj . To
q_new_to_old = inverse(q_new) * q_old
.Następnie w jednym kluczu animacji masz jedną ćwiartkę, która przekształca tę kość ze „starej” pozy wiązania w animowaną. Nazwijmy to
q_anim
.Zamiast używać
q_anim
bezpośrednio, spróbuj użyćq_new_to_old * q_anim
. Powinno to „anulować” różnice orientacji między pozycjami wiązania przed zastosowaniem animacji.To może załatwić sprawę.
EDYTOWAĆ
Powyższy kod wydaje się zgodny z logiką, którą tu opisuję, ale coś jest odwrócone. Zamiast tego:
Możesz spróbować:
Myślę, że musisz przejść od celu do źródła przed zastosowaniem animacji źródłowej, aby uzyskać tę samą ostateczną orientację.
źródło