improved bone export

This commit is contained in:
Perfare 2019-07-29 13:41:42 +08:00
parent e62b6c3d77
commit de54257eef
2 changed files with 94 additions and 60 deletions

View File

@ -333,33 +333,31 @@ namespace AssetStudio
hasBones = false; hasBones = false;
} }
FbxArray<FbxNode*>* pBoneNodeList = nullptr;
FbxArray<FbxCluster*>* pClusterArray = nullptr; FbxArray<FbxCluster*>* pClusterArray = nullptr;
try try
{ {
if (hasBones) if (hasBones)
{ {
pBoneNodeList = new FbxArray<FbxNode*>(); pClusterArray = new FbxArray<FbxCluster*>(boneList->Count);
pBoneNodeList->Reserve(boneList->Count);
for (int i = 0; i < boneList->Count; i++) for (int i = 0; i < boneList->Count; i++)
{ {
auto bone = boneList[i]; auto bone = boneList[i];
auto frame = imported->RootFrame->FindFrameByPath(bone->Path); if (bone->Path != nullptr)
auto frameNode = (FbxNode*)frameToNode[frame]; {
pBoneNodeList->Add(frameNode); auto frame = imported->RootFrame->FindFrameByPath(bone->Path);
} auto boneNode = (FbxNode*)frameToNode[frame];
FbxString lClusterName = boneNode->GetNameOnly() + FbxString("Cluster");
pClusterArray = new FbxArray<FbxCluster*>(); FbxCluster* pCluster = FbxCluster::Create(pScene, lClusterName.Buffer());
pClusterArray->Reserve(boneList->Count); pCluster->SetLink(boneNode);
for (int i = 0; i < boneList->Count; i++) pCluster->SetLinkMode(FbxCluster::eTotalOne);
{ pClusterArray->Add(pCluster);
FbxNode* pNode = pBoneNodeList->GetAt(i); }
FbxString lClusterName = pNode->GetNameOnly() + FbxString("Cluster"); else
FbxCluster* pCluster = FbxCluster::Create(pScene, lClusterName.Buffer()); {
pCluster->SetLink(pNode); pClusterArray->Add(NULL);
pCluster->SetLinkMode(FbxCluster::eTotalOne); }
pClusterArray->Add(pCluster);
} }
} }
@ -532,7 +530,10 @@ namespace AssetStudio
if (boneIndices[k] < boneList->Count && weights4[k] > 0) if (boneIndices[k] < boneList->Count && weights4[k] > 0)
{ {
FbxCluster* pCluster = pClusterArray->GetAt(boneIndices[k]); FbxCluster* pCluster = pClusterArray->GetAt(boneIndices[k]);
pCluster->AddControlPointIndex(j + firstVertex, weights4[k]); if (pCluster)
{
pCluster->AddControlPointIndex(j + firstVertex, weights4[k]);
}
} }
} }
} }
@ -558,20 +559,23 @@ namespace AssetStudio
for (int j = 0; j < boneList->Count; j++) for (int j = 0; j < boneList->Count; j++)
{ {
FbxCluster* pCluster = pClusterArray->GetAt(j); FbxCluster* pCluster = pClusterArray->GetAt(j);
auto boneMatrix = boneList[j]->Matrix; if (pCluster)
FbxAMatrix lBoneMatrix;
for (int m = 0; m < 4; m++)
{ {
for (int n = 0; n < 4; n++) auto boneMatrix = boneList[j]->Matrix;
FbxAMatrix lBoneMatrix;
for (int m = 0; m < 4; m++)
{ {
lBoneMatrix.mData[m][n] = boneMatrix[m, n]; for (int n = 0; n < 4; n++)
{
lBoneMatrix.mData[m][n] = boneMatrix[m, n];
}
} }
pCluster->SetTransformMatrix(lMeshMatrix);
pCluster->SetTransformLinkMatrix(lMeshMatrix * lBoneMatrix.Inverse());
pSkin->AddCluster(pCluster);
} }
pCluster->SetTransformMatrix(lMeshMatrix);
pCluster->SetTransformLinkMatrix(lMeshMatrix * lBoneMatrix.Inverse());
pSkin->AddCluster(pCluster);
} }
if (pSkin->GetClusterCount() > 0) if (pSkin->GetClusterCount() > 0)
@ -582,10 +586,6 @@ namespace AssetStudio
} }
finally finally
{ {
if (pBoneNodeList != NULL)
{
delete pBoneNodeList;
}
if (pClusterArray != NULL) if (pClusterArray != NULL)
{ {
delete pClusterArray; delete pClusterArray;

View File

@ -392,44 +392,78 @@ namespace AssetStudio
if (meshR is SkinnedMeshRenderer sMesh) if (meshR is SkinnedMeshRenderer sMesh)
{ {
//Bone //Bone
/*
* 0 - None
* 1 - m_Bones
* 2 - m_BoneNameHashes
*/
var boneType = 0;
if (sMesh.m_Bones.Length > 0) if (sMesh.m_Bones.Length > 0)
{ {
var boneMax = Math.Min(sMesh.m_Bones.Length, mesh.m_BindPose.Length); if (sMesh.m_Bones.Length == mesh.m_BindPose.Length)
iMesh.BoneList = new List<ImportedBone>(boneMax); {
for (int i = 0; i < boneMax; i++) var verifiedBoneCount = sMesh.m_Bones.Count(x => x.TryGet(out _));
if (verifiedBoneCount > 0)
{
boneType = 1;
}
if (verifiedBoneCount != sMesh.m_Bones.Length)
{
//尝试使用m_BoneNameHashes 4.3 and up
if (mesh.m_BindPose.Length > 0 && (mesh.m_BindPose.Length == mesh.m_BoneNameHashes?.Length))
{
//有效bone数量是否大于SkinnedMeshRenderer
var verifiedBoneCount2 = mesh.m_BoneNameHashes.Count(x => FixBonePath(GetPathFromHash(x)) != null);
if (verifiedBoneCount2 > verifiedBoneCount)
{
boneType = 2;
}
}
}
}
else
{
//Logger.Error("");
}
}
else
{
//尝试使用m_BoneNameHashes 4.3 and up
if (mesh.m_BindPose.Length > 0 && (mesh.m_BindPose.Length == mesh.m_BoneNameHashes?.Length))
{
boneType = 2;
}
}
if (boneType == 1)
{
var boneCount = sMesh.m_Bones.Length;
iMesh.BoneList = new List<ImportedBone>(boneCount);
for (int i = 0; i < boneCount; i++)
{ {
var bone = new ImportedBone(); var bone = new ImportedBone();
if (sMesh.m_Bones[i].TryGet(out var m_Transform)) if (sMesh.m_Bones[i].TryGet(out var m_Transform))
{ {
bone.Path = GetTransformPath(m_Transform); bone.Path = GetTransformPath(m_Transform);
} }
if (!string.IsNullOrEmpty(bone.Path)) var convert = Matrix4x4.Scale(new Vector3(-1, 1, 1));
{ bone.Matrix = convert * mesh.m_BindPose[i] * convert;
var convert = Matrix4x4.Scale(new Vector3(-1, 1, 1)); iMesh.BoneList.Add(bone);
bone.Matrix = convert * mesh.m_BindPose[i] * convert;
iMesh.BoneList.Add(bone);
}
} }
} }
if (iMesh.BoneList == null || iMesh.BoneList.Count == 0) else if (boneType == 2)
{ {
if (mesh.m_BindPose.Length > 0 && mesh.m_BoneNameHashes?.Length > 0) var boneCount = mesh.m_BindPose.Length;
iMesh.BoneList = new List<ImportedBone>(boneCount);
for (int i = 0; i < boneCount; i++)
{ {
var boneMax = Math.Min(mesh.m_BindPose.Length, mesh.m_BoneNameHashes.Length); var bone = new ImportedBone();
iMesh.BoneList = new List<ImportedBone>(boneMax); var boneHash = mesh.m_BoneNameHashes[i];
for (int i = 0; i < boneMax; i++) var path = GetPathFromHash(boneHash);
{ bone.Path = FixBonePath(path);
var bone = new ImportedBone(); var convert = Matrix4x4.Scale(new Vector3(-1, 1, 1));
var boneHash = mesh.m_BoneNameHashes[i]; bone.Matrix = convert * mesh.m_BindPose[i] * convert;
var path = GetPathFromHash(boneHash); iMesh.BoneList.Add(bone);
bone.Path = FixBonePath(path);
if (!string.IsNullOrEmpty(bone.Path))
{
var convert = Matrix4x4.Scale(new Vector3(-1, 1, 1));
bone.Matrix = convert * mesh.m_BindPose[i] * convert;
iMesh.BoneList.Add(bone);
}
}
} }
} }
@ -446,7 +480,7 @@ namespace AssetStudio
morph.Channels.Add(channel); morph.Channels.Add(channel);
var shapeChannel = mesh.m_Shapes.channels[i]; var shapeChannel = mesh.m_Shapes.channels[i];
morphChannelNames.Add(shapeChannel.nameHash, shapeChannel.name); morphChannelNames[shapeChannel.nameHash] = shapeChannel.name;
channel.Name = shapeChannel.name; channel.Name = shapeChannel.name;
channel.KeyframeList = new List<ImportedMorphKeyframe>(shapeChannel.frameCount); channel.KeyframeList = new List<ImportedMorphKeyframe>(shapeChannel.frameCount);