我正在使用 Assimp 從 fbx 檔案加載影片資料,但是當我使用 Blender 加載 fbx 并比較 Blender 和 Assimp 提供的值之間的關鍵幀值時,它們并不相同。
根據
但是,Assimp 會為同一影片通道回傳以下關鍵幀值:
Time: 0 Value: 2.34362
Time: 1 Value: 2.04054
Time: 2 Value: 1.73746
Time: 3 Value: 1.43438
Time: 4 Value: 1.13131
Time: 5 Value: 0.828227
Time: 6 Value: 0.525148
Time: 7 Value: 0.22207
Time: 8 Value: -0.0225141
Time: 9 Value: -0.267098
Time: 10 Value: -0.511682
Time: 11 Value: -0.756265
Time: 12 Value: -1.00085
Time: 13 Value: -1.24543
Time: 14 Value: -1.49002
Time: 15 Value: -1.7346
Time: 16 Value: -1.72213
...
Time: 30 Value: 2.34362
當我進一步調查時,Assimp 回傳的這些值似乎已映射到模型空間,如這里所示。
這一發現似乎讓我離修正影片資料更近了一步,因為我只需要將影片資料從模型空間轉換到骨骼空間。幸運的是,AssimpmOffsetMatrix在每個骨骼上提供了一個屬性,記錄為
以系結姿勢從骨骼空間轉換到網格空間的矩陣。這個矩陣描述了當骨架被系結時網格在這個骨骼的區域空間中的位置。
據此,mOffsetMatrix似乎與我想要的相反,所以我應該只需要通過這個矩陣的倒數來轉換影片資料。相反,逆矩陣變換繼續給我無效資料,但令我驚訝的是,按mOffsetMatrix原樣(而不是倒置)變換影片資料給了我正確的值:
Time: 0 Value: -2.12155
Time: 1 Value: -1.81847
Time: 2 Value: -1.51539
Time: 3 Value: -1.21231
Time: 4 Value: -0.909236
Time: 5 Value: -0.606157
Time: 6 Value: -0.303079
Time: 7 Value: 0
Time: 8 Value: 0.244584
Time: 9 Value: 0.489167
Time: 10 Value: 0.733751
Time: 11 Value: 0.978335
Time: 12 Value: 1.22292
Time: 13 Value: 1.4675
Time: 14 Value: 1.71209
Time: 15 Value: 1.95667
Time: 16 Value: 1.9442
...
Time: 30 Value: -2.12155
這似乎是我的答案,但當然這太容易了。這種轉換只為應用于根骨骼的影片提供了正確的影片值。子骨骼的影片資料完全不正確,我一生都無法弄清楚影片資料所在的空間。我嘗試了各種組合來自父節點的矩陣創建矩陣來轉換影片資料進入骨骼空間,但沒有一個資料看起來很正確。即使將 Assimp 回傳的影片值與模型空間值進行比較,就像我對根骨骼所做的那樣,這些值也不正確,這意味著 Assimp 回傳的影片資料既不在骨骼空間中,也不在模型空間中。
Assimp 的檔案在影片資料所在的空間和mOffsetMatrix代表的兩個方面似乎都不正確,除非我完全誤解了它在說什么。但這里有一個難題:
Assimp 的影片資料在什么空間中,如何將其轉換為骨骼空間?
uj5u.com熱心網友回復:
Asset-Importer-Lib 的影片系統使用基于資產根節點的偏移矩陣。因此,所有資訊都基于您匯入模式的本地模型空間。
我不確定為什么孩子的影片資料不正確。我已經為這個問題開了一張票(見Children-bone transformation is broken)。
uj5u.com熱心網友回復:
該檔案是正確的。所有影片資料都與父骨骼/節點相關,但物件mOffsetMatrix上的屬性aiBone保存從網格空間到骨骼空間的轉換(與檔案所示的骨骼空間到網格空間相反)。
要將影片資料從父骨骼空間變換到區域骨骼空間,資料應該從父骨骼空間變換到網格空間,然后從網格空間變換到當前骨骼空間。這可以通過找到父骨骼并創建一個復合矩陣來完成,即aiMatrix4x4 parentBoneToChildBone(bone.mOffsetMatrix * aiMatrix4x4(parentBone.mOffsetMatrix).Inverse());
然后使用該矩陣來轉換影片資料。(注意.Inverse()修改原始矩陣,因此在反轉之前應進行復制。)
如果有問題的骨骼沒有父骨骼,那么您可以簡單地將影片資料轉換為bone.mOffsetMatrix. 由于根骨骼的父級應該是骨架(可能也與網格在同一空間中),并且影片資料是相對于骨骼的父級(在這種情況下應該是骨架/網格空間),我們可以mOffsetMatrix用來將影片資料直接轉換到骨骼空間中。
const aiMatrix4x4& modelToBone(bone.mOffsetMatrix); // Renamed for clarity...
aiMatrix4x4 parentToBone;
const auto parentBoneI = bonesByName.find(bone.mNode->mParent->mName.C_Str());
if (parentBoneI != bonesByName.cend())
{
aiMatrix4x4 parentToModel(parentBoneI->second->mOffsetMatrix);
parentToModel.Inverse();
parentToBone = modelToBone * parentToModel;
}
else
{
parentToBone = modelToBone;
}
// ...
// Convert position data from parent's bone space to the current bone's space...
const aiVectorKey& positionKey = channel.mPositionKeys[keyIndex];
const aiVector3D position(parentToBone * positionKey.mValue);
// Convert rotation data into bone space...
const aiQuatKey& rotationKey = channel.mRotationKeys[keyIndex];
const aiQuaternion rotation(aiQuaternion(aiMatrix3x3(parentToBone)) * rotationKey.mValue);
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/506589.html
