Saya mencoba menulis kode untuk mentransfer animasi yang dirancang untuk satu kerangka agar terlihat benar pada kerangka lain. Animasi sumber hanya terdiri dari rotasi kecuali untuk terjemahan di root (mereka animasi mocap dari CMU basis data gerak ). Banyak aplikasi 3D (mis. Maya) memiliki fasilitas ini, tetapi saya mencoba menulis versi (sangat sederhana) untuk game saya.
Saya telah melakukan beberapa pekerjaan pada pemetaan tulang, dan karena kerangkanya secara hierarki mirip (biped), saya dapat melakukan pemetaan tulang 1: 1 untuk semua hal kecuali tulang belakang (bisa bekerja nanti). Masalahnya, bagaimanapun, adalah bahwa kerangka dasar / pose mengikat berbeda, dan tulang-tulang adalah skala yang berbeda (lebih pendek / lebih lama), jadi jika saya hanya menyalin rotasi langsung ke atasnya terlihat sangat aneh.
Saya telah mencoba sejumlah hal yang mirip dengan solusi lorancou di bawah ini tetapi tidak berhasil (yaitu mengalikan setiap frame dalam animasi dengan pengganda spesifik-tulang). Jika ada yang punya sumber daya tentang hal-hal seperti ini (makalah, kode sumber, dll), itu akan sangat membantu.
sumber
Jawaban:
Masalahnya adalah stabilitas numerik. Kira-kira 30 jam mengerjakan ini selama 2 bulan, hanya untuk mengetahui bahwa saya sudah melakukannya sejak awal. Ketika saya ortho-dinormalisasi matriks rotasi sebelum menghubungkannya ke kode retarget, solusi sederhana mengalikan sumber * invers (target) bekerja dengan sempurna. Tentu saja, ada lebih banyak penargetan ulang dari itu (khususnya, dengan mempertimbangkan berbagai bentuk kerangka, yaitu lebar bahu, dll). Inilah kode yang saya gunakan untuk pendekatan yang sederhana dan naif, jika ada yang ingin tahu:
sumber
Saya percaya bahwa pilihan termudah Anda adalah mencocokkan pose mengikat asli dengan kerangka baru Anda jika Anda punya kemungkinan (jika kerangka baru Anda belum dikuliti).
Jika Anda tidak bisa melakukan itu, berikut ini sesuatu yang bisa Anda coba. Ini hanya intuisi, saya mungkin menghadap banyak hal, tetapi mungkin membantu Anda menemukan cahaya. Untuk setiap tulang:
Dalam pose mengikat "lama" Anda, Anda punya satu angka empat yang menggambarkan rotasi relatif dari tulang ini dibandingkan dengan tulang induknya . Berikut ini petunjuk cara menemukannya. Sebut saja
q_old
.Ibid. untuk pose mengikat "baru" Anda, sebut saja
q_new
.Anda dapat menemukan rotasi relatif dari pose bind "baru" ke pose bin "lama", seperti dijelaskan di sini . Itu
q_new_to_old = inverse(q_new) * q_old
.Kemudian dalam satu tombol animasi, Anda punya satu angka empat Anda yang mengubah tulang itu dari pose mengikat "lama" menjadi pose animasi. Sebut saja yang ini
q_anim
.Alih-alih menggunakan
q_anim
secara langsung, coba gunakanq_new_to_old * q_anim
. Ini harus "membatalkan" perbedaan orientasi antara pose mengikat, sebelum menerapkan animasi.Mungkin berhasil.
EDIT
Kode Anda di atas tampaknya mengikuti logika yang saya jelaskan di sini, tetapi ada sesuatu yang terbalik. Alih-alih melakukan ini:
Anda bisa mencobanya:
Saya pikir Anda perlu mengubah dari target Anda ke sumber Anda sebelum menerapkan animasi sumber, untuk mendapatkan orientasi akhir yang sama.
sumber