From 32ee8b326fa711fe982732bd454ba8de5d44d53b Mon Sep 17 00:00:00 2001 From: Ishotihadus Date: Wed, 16 Sep 2020 19:44:11 +0900 Subject: [PATCH] fix problems in exporting fbx with multiple blendshapes --- AssetStudioFBXNative/api.cpp | 33 ++++++++++++++----- AssetStudioFBXNative/api.h | 6 +++- .../FbxExporterContext.PInvoke.cs | 16 ++++++++- AssetStudioFBXWrapper/FbxExporterContext.cs | 17 ++++++++-- AssetStudioUtility/ModelConverter.cs | 2 +- 5 files changed, 60 insertions(+), 14 deletions(-) diff --git a/AssetStudioFBXNative/api.cpp b/AssetStudioFBXNative/api.cpp index 9d24976..2353d7a 100644 --- a/AssetStudioFBXNative/api.cpp +++ b/AssetStudioFBXNative/api.cpp @@ -1093,7 +1093,7 @@ AS_API(void) AsFbxMorphAddBlendShapeChannel(AsFbxContext* pContext, AsFbxMorphCo } } -AS_API(void) AsFbxMorphAddBlendShapeChannelShape(AsFbxContext* pContext, AsFbxMorphContext* pMorphContext, float weight) +AS_API(void) AsFbxMorphAddBlendShapeChannelShape(AsFbxContext* pContext, AsFbxMorphContext* pMorphContext, float weight, const char* shapeName) { if (pContext == nullptr || pContext->pScene == nullptr) { @@ -1105,7 +1105,7 @@ AS_API(void) AsFbxMorphAddBlendShapeChannelShape(AsFbxContext* pContext, AsFbxMo return; } - auto lShape = FbxShape::Create(pContext->pScene, FbxString(weight)); + auto lShape = FbxShape::Create(pContext->pScene, shapeName); pMorphContext->lShape = lShape; if (pMorphContext->lBlendShapeChannel != nullptr) { @@ -1126,12 +1126,9 @@ AS_API(void) AsFbxMorphCopyBlendShapeControlPoints(AsFbxMorphContext* pMorphCont pMorphContext->lShape->InitControlPoints(vectorCount); - auto dstControlPoints = pMorphContext->lShape->GetControlPoints(); - for (int j = 0; j < vectorCount; j++) { - auto vertex = srcControlPoints[j]; - dstControlPoints[j] = FbxVector4(vertex); + pMorphContext->lShape->SetControlPointAt(FbxVector4(srcControlPoints[j]), j);; } } @@ -1142,7 +1139,25 @@ AS_API(void) AsFbxMorphSetBlendShapeVertex(AsFbxMorphContext* pMorphContext, uin return; } - auto pControlPoints = pMorphContext->lShape->GetControlPoints(); - - pControlPoints[index] = FbxVector4(x, y, z, 0); + pMorphContext->lShape->SetControlPointAt(FbxVector4(x, y, z, 0), index); +} + +AS_API(void) AsFbxMorphCopyBlendShapeControlPointsNormal(AsFbxMorphContext* pMorphContext) +{ + if (pMorphContext == nullptr || pMorphContext->pMesh == nullptr || pMorphContext->lShape == nullptr) + { + return; + } + + pMorphContext->lShape->InitNormals(pMorphContext->pMesh); +} + +AS_API(void) AsFbxMorphSetBlendShapeVertexNormal(AsFbxMorphContext* pMorphContext, uint32_t index, float x, float y, float z) +{ + if (pMorphContext == nullptr || pMorphContext->lShape == nullptr) + { + return; + } + + pMorphContext->lShape->SetControlPointNormalAt(FbxVector4(x, y, z, 0), index); } diff --git a/AssetStudioFBXNative/api.h b/AssetStudioFBXNative/api.h index fb21034..444d6e5 100644 --- a/AssetStudioFBXNative/api.h +++ b/AssetStudioFBXNative/api.h @@ -150,8 +150,12 @@ AS_API(void) AsFbxMorphDisposeContext(AsFbxMorphContext** ppMorphContext); AS_API(void) AsFbxMorphAddBlendShapeChannel(AsFbxContext* pContext, AsFbxMorphContext* pMorphContext, const char* channelName); -AS_API(void) AsFbxMorphAddBlendShapeChannelShape(AsFbxContext* pContext, AsFbxMorphContext* pMorphContext, float weight); +AS_API(void) AsFbxMorphAddBlendShapeChannelShape(AsFbxContext* pContext, AsFbxMorphContext* pMorphContext, float weight, const char* shapeName); AS_API(void) AsFbxMorphCopyBlendShapeControlPoints(AsFbxMorphContext* pMorphContext); AS_API(void) AsFbxMorphSetBlendShapeVertex(AsFbxMorphContext* pMorphContext, uint32_t index, float x, float y, float z); + +AS_API(void) AsFbxMorphCopyBlendShapeControlPointsNormal(AsFbxMorphContext* pMorphContext); + +AS_API(void) AsFbxMorphSetBlendShapeVertexNormal(AsFbxMorphContext* pMorphContext, uint32_t index, float x, float y, float z); diff --git a/AssetStudioFBXWrapper/FbxExporterContext.PInvoke.cs b/AssetStudioFBXWrapper/FbxExporterContext.PInvoke.cs index 57334db..82c5e1f 100644 --- a/AssetStudioFBXWrapper/FbxExporterContext.PInvoke.cs +++ b/AssetStudioFBXWrapper/FbxExporterContext.PInvoke.cs @@ -298,8 +298,16 @@ namespace AssetStudio.FbxInterop [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)] private static extern void AsFbxMorphAddBlendShapeChannel(IntPtr pContext, IntPtr pMorphContext, IntPtr strChannelName); + private static void AsFbxMorphAddBlendShapeChannelShape(IntPtr pContext, IntPtr pMorphContext, float weight, string shapeName) + { + using (var shapeNameUtf8 = new Utf8StringHandle(shapeName)) + { + AsFbxMorphAddBlendShapeChannelShape(pContext, pMorphContext, weight, shapeNameUtf8.DangerousGetHandle()); + } + } + [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)] - private static extern void AsFbxMorphAddBlendShapeChannelShape(IntPtr pContext, IntPtr pMorphContext, float weight); + private static extern void AsFbxMorphAddBlendShapeChannelShape(IntPtr pContext, IntPtr pMorphContext, float weight, IntPtr strShapeName); [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)] private static extern void AsFbxMorphCopyBlendShapeControlPoints(IntPtr pMorphContext); @@ -307,5 +315,11 @@ namespace AssetStudio.FbxInterop [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)] private static extern void AsFbxMorphSetBlendShapeVertex(IntPtr pMorphContext, uint index, float x, float y, float z); + [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)] + private static extern void AsFbxMorphCopyBlendShapeControlPointsNormal(IntPtr pMorphContext); + + [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)] + private static extern void AsFbxMorphSetBlendShapeVertexNormal(IntPtr pMorphContext, uint index, float x, float y, float z); + } } diff --git a/AssetStudioFBXWrapper/FbxExporterContext.cs b/AssetStudioFBXWrapper/FbxExporterContext.cs index 24e24b5..d18beb3 100644 --- a/AssetStudioFBXWrapper/FbxExporterContext.cs +++ b/AssetStudioFBXWrapper/FbxExporterContext.cs @@ -611,9 +611,11 @@ namespace AssetStudio.FbxInterop { AsFbxMorphAddBlendShapeChannel(_pContext, pMorphContext, channel.Name); - foreach (var keyframe in channel.KeyframeList) + for (var i = 0; i < channel.KeyframeList.Count; i++) { - AsFbxMorphAddBlendShapeChannelShape(_pContext, pMorphContext, keyframe.Weight); + var keyframe = channel.KeyframeList[i]; + + AsFbxMorphAddBlendShapeChannelShape(_pContext, pMorphContext, keyframe.Weight, i == 0 ? channel.Name : $"{channel.Name}_{i + 1}"); AsFbxMorphCopyBlendShapeControlPoints(pMorphContext); @@ -622,6 +624,17 @@ namespace AssetStudio.FbxInterop var v = vertex.Vertex.Vertex; AsFbxMorphSetBlendShapeVertex(pMorphContext, vertex.Index, v.X, v.Y, v.Z); } + + if (keyframe.hasNormals) + { + AsFbxMorphCopyBlendShapeControlPointsNormal(pMorphContext); + + foreach (var vertex in keyframe.VertexList) + { + var v = vertex.Vertex.Normal; + AsFbxMorphSetBlendShapeVertexNormal(pMorphContext, vertex.Index, v.X, v.Y, v.Z); + } + } } } } diff --git a/AssetStudioUtility/ModelConverter.cs b/AssetStudioUtility/ModelConverter.cs index df29d4b..e24cbb7 100644 --- a/AssetStudioUtility/ModelConverter.cs +++ b/AssetStudioUtility/ModelConverter.cs @@ -500,7 +500,7 @@ namespace AssetStudio crc.Update(bytes, 0, (uint)bytes.Length); morphChannelNames[crc.GetDigest()] = blendShapeName; - channel.Name = shapeChannel.name; + channel.Name = shapeChannel.name.Split('.').Last(); channel.KeyframeList = new List(shapeChannel.frameCount); var frameEnd = shapeChannel.frameIndex + shapeChannel.frameCount; for (int frameIdx = shapeChannel.frameIndex; frameIdx < frameEnd; frameIdx++)