From de54257eefea131acbff594a1cc320e54b380b02 Mon Sep 17 00:00:00 2001 From: Perfare Date: Mon, 29 Jul 2019 13:41:42 +0800 Subject: [PATCH] improved bone export --- AssetStudioFBX/AssetStudioFBXExporter.cpp | 66 ++++++++--------- AssetStudioUtility/ModelConverter.cs | 88 ++++++++++++++++------- 2 files changed, 94 insertions(+), 60 deletions(-) diff --git a/AssetStudioFBX/AssetStudioFBXExporter.cpp b/AssetStudioFBX/AssetStudioFBXExporter.cpp index ca0b84b..7e5b671 100644 --- a/AssetStudioFBX/AssetStudioFBXExporter.cpp +++ b/AssetStudioFBX/AssetStudioFBXExporter.cpp @@ -333,33 +333,31 @@ namespace AssetStudio hasBones = false; } - FbxArray* pBoneNodeList = nullptr; FbxArray* pClusterArray = nullptr; try { if (hasBones) { - pBoneNodeList = new FbxArray(); - pBoneNodeList->Reserve(boneList->Count); + pClusterArray = new FbxArray(boneList->Count); + for (int i = 0; i < boneList->Count; i++) { auto bone = boneList[i]; - auto frame = imported->RootFrame->FindFrameByPath(bone->Path); - auto frameNode = (FbxNode*)frameToNode[frame]; - pBoneNodeList->Add(frameNode); - } - - pClusterArray = new FbxArray(); - pClusterArray->Reserve(boneList->Count); - for (int i = 0; i < boneList->Count; i++) - { - FbxNode* pNode = pBoneNodeList->GetAt(i); - FbxString lClusterName = pNode->GetNameOnly() + FbxString("Cluster"); - FbxCluster* pCluster = FbxCluster::Create(pScene, lClusterName.Buffer()); - pCluster->SetLink(pNode); - pCluster->SetLinkMode(FbxCluster::eTotalOne); - pClusterArray->Add(pCluster); + if (bone->Path != nullptr) + { + auto frame = imported->RootFrame->FindFrameByPath(bone->Path); + auto boneNode = (FbxNode*)frameToNode[frame]; + FbxString lClusterName = boneNode->GetNameOnly() + FbxString("Cluster"); + FbxCluster* pCluster = FbxCluster::Create(pScene, lClusterName.Buffer()); + pCluster->SetLink(boneNode); + pCluster->SetLinkMode(FbxCluster::eTotalOne); + pClusterArray->Add(pCluster); + } + else + { + pClusterArray->Add(NULL); + } } } @@ -532,7 +530,10 @@ namespace AssetStudio if (boneIndices[k] < boneList->Count && weights4[k] > 0) { 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++) { FbxCluster* pCluster = pClusterArray->GetAt(j); - auto boneMatrix = boneList[j]->Matrix; - FbxAMatrix lBoneMatrix; - for (int m = 0; m < 4; m++) + if (pCluster) { - 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) @@ -582,10 +586,6 @@ namespace AssetStudio } finally { - if (pBoneNodeList != NULL) - { - delete pBoneNodeList; - } if (pClusterArray != NULL) { delete pClusterArray; diff --git a/AssetStudioUtility/ModelConverter.cs b/AssetStudioUtility/ModelConverter.cs index 151d306..df4334f 100644 --- a/AssetStudioUtility/ModelConverter.cs +++ b/AssetStudioUtility/ModelConverter.cs @@ -392,44 +392,78 @@ namespace AssetStudio if (meshR is SkinnedMeshRenderer sMesh) { //Bone + /* + * 0 - None + * 1 - m_Bones + * 2 - m_BoneNameHashes + */ + var boneType = 0; if (sMesh.m_Bones.Length > 0) { - var boneMax = Math.Min(sMesh.m_Bones.Length, mesh.m_BindPose.Length); - iMesh.BoneList = new List(boneMax); - for (int i = 0; i < boneMax; i++) + if (sMesh.m_Bones.Length == mesh.m_BindPose.Length) + { + 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(boneCount); + for (int i = 0; i < boneCount; i++) { var bone = new ImportedBone(); if (sMesh.m_Bones[i].TryGet(out var 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; - iMesh.BoneList.Add(bone); - } + var convert = Matrix4x4.Scale(new Vector3(-1, 1, 1)); + 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(boneCount); + for (int i = 0; i < boneCount; i++) { - var boneMax = Math.Min(mesh.m_BindPose.Length, mesh.m_BoneNameHashes.Length); - iMesh.BoneList = new List(boneMax); - for (int i = 0; i < boneMax; i++) - { - var bone = new ImportedBone(); - var boneHash = mesh.m_BoneNameHashes[i]; - var path = GetPathFromHash(boneHash); - 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); - } - } + var bone = new ImportedBone(); + var boneHash = mesh.m_BoneNameHashes[i]; + var path = GetPathFromHash(boneHash); + bone.Path = FixBonePath(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); var shapeChannel = mesh.m_Shapes.channels[i]; - morphChannelNames.Add(shapeChannel.nameHash, shapeChannel.name); + morphChannelNames[shapeChannel.nameHash] = shapeChannel.name; channel.Name = shapeChannel.name; channel.KeyframeList = new List(shapeChannel.frameCount);