mirror of
https://github.com/aelurum/AssetStudio.git
synced 2025-05-27 22:00:23 -04:00
Fixed #326
This commit is contained in:
parent
ff550b457f
commit
54d78d55a0
@ -9,7 +9,7 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
public PPtr<Avatar> m_Avatar;
|
public PPtr<Avatar> m_Avatar;
|
||||||
public PPtr<RuntimeAnimatorController> m_Controller;
|
public PPtr<RuntimeAnimatorController> m_Controller;
|
||||||
public bool m_HasTransformHierarchy;
|
public bool m_HasTransformHierarchy = true;
|
||||||
|
|
||||||
public Animator(ObjectReader reader) : base(reader)
|
public Animator(ObjectReader reader) : base(reader)
|
||||||
{
|
{
|
||||||
|
@ -303,18 +303,6 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string FindBoneName(uint hash)
|
|
||||||
{
|
|
||||||
foreach (var pair in m_TOS)
|
|
||||||
{
|
|
||||||
if (pair.Key == hash)
|
|
||||||
{
|
|
||||||
return pair.Value.Substring(pair.Value.LastIndexOf('/') + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string FindBonePath(uint hash)
|
public string FindBonePath(uint hash)
|
||||||
{
|
{
|
||||||
return m_TOS.FirstOrDefault(pair => pair.Key == hash).Value;
|
return m_TOS.FirstOrDefault(pair => pair.Key == hash).Value;
|
||||||
|
@ -16,7 +16,7 @@ namespace AssetStudio
|
|||||||
List<ImportedMorph> MorphList { get; }
|
List<ImportedMorph> MorphList { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ImportedFrame : IEnumerable<ImportedFrame>
|
public class ImportedFrame
|
||||||
{
|
{
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public Vector3 LocalRotation { get; set; }
|
public Vector3 LocalRotation { get; set; }
|
||||||
@ -47,20 +47,82 @@ namespace AssetStudio
|
|||||||
children.Remove(frame);
|
children.Remove(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerator<ImportedFrame> GetEnumerator()
|
public ImportedFrame FindFrameByPath(string path)
|
||||||
{
|
{
|
||||||
return children.GetEnumerator();
|
var splitPath = path.Split('/');
|
||||||
|
if (Name != splitPath[0])
|
||||||
|
throw new Exception($"Couldn't find path {path}");
|
||||||
|
var curFrame = this;
|
||||||
|
for (int i = 1; i < splitPath.Length; i++)
|
||||||
|
{
|
||||||
|
curFrame = curFrame.FindChild(splitPath[i], false);
|
||||||
|
if (curFrame == null)
|
||||||
|
{
|
||||||
|
throw new Exception($"Couldn't find path {path}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return curFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
public ImportedFrame FindFrame(string name)
|
||||||
{
|
{
|
||||||
return GetEnumerator();
|
if (Name == name)
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
foreach (var child in children)
|
||||||
|
{
|
||||||
|
var frame = child.FindFrame(name);
|
||||||
|
if (frame != null)
|
||||||
|
{
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImportedFrame FindChild(string name, bool recursive = true)
|
||||||
|
{
|
||||||
|
foreach (var child in children)
|
||||||
|
{
|
||||||
|
if (recursive)
|
||||||
|
{
|
||||||
|
var frame = child.FindFrame(name);
|
||||||
|
if (frame != null)
|
||||||
|
{
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (child.Name == name)
|
||||||
|
{
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<ImportedFrame> FindChilds(string name)
|
||||||
|
{
|
||||||
|
if (Name == name)
|
||||||
|
{
|
||||||
|
yield return this;
|
||||||
|
}
|
||||||
|
foreach (var child in children)
|
||||||
|
{
|
||||||
|
foreach (var item in child.FindChilds(name))
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ImportedMesh
|
public class ImportedMesh
|
||||||
{
|
{
|
||||||
public string Name { get; set; }
|
public string Path { get; set; }
|
||||||
public List<ImportedSubmesh> SubmeshList { get; set; }
|
public List<ImportedSubmesh> SubmeshList { get; set; }
|
||||||
public List<ImportedBone> BoneList { get; set; }
|
public List<ImportedBone> BoneList { get; set; }
|
||||||
}
|
}
|
||||||
@ -94,7 +156,7 @@ namespace AssetStudio
|
|||||||
|
|
||||||
public class ImportedBone
|
public class ImportedBone
|
||||||
{
|
{
|
||||||
public string Name { get; set; }
|
public string Path { get; set; }
|
||||||
public Matrix Matrix { get; set; }
|
public Matrix Matrix { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,12 +191,12 @@ namespace AssetStudio
|
|||||||
|
|
||||||
public List<ImportedAnimationKeyframedTrack> TrackList { get; set; }
|
public List<ImportedAnimationKeyframedTrack> TrackList { get; set; }
|
||||||
|
|
||||||
public ImportedAnimationKeyframedTrack FindTrack(string name)
|
public ImportedAnimationKeyframedTrack FindTrack(string path)
|
||||||
{
|
{
|
||||||
var track = TrackList.Find(x => x.Name == name);
|
var track = TrackList.Find(x => x.Path == path);
|
||||||
if (track == null)
|
if (track == null)
|
||||||
{
|
{
|
||||||
track = new ImportedAnimationKeyframedTrack { Name = name };
|
track = new ImportedAnimationKeyframedTrack { Path = path };
|
||||||
TrackList.Add(track);
|
TrackList.Add(track);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,11 +206,10 @@ namespace AssetStudio
|
|||||||
|
|
||||||
public class ImportedAnimationKeyframedTrack
|
public class ImportedAnimationKeyframedTrack
|
||||||
{
|
{
|
||||||
public string Name { get; set; }
|
public string Path { get; set; }
|
||||||
public List<ImportedKeyframe<Vector3>> Scalings = new List<ImportedKeyframe<Vector3>>();
|
public List<ImportedKeyframe<Vector3>> Scalings = new List<ImportedKeyframe<Vector3>>();
|
||||||
public List<ImportedKeyframe<Vector3>> Rotations = new List<ImportedKeyframe<Vector3>>();
|
public List<ImportedKeyframe<Vector3>> Rotations = new List<ImportedKeyframe<Vector3>>();
|
||||||
public List<ImportedKeyframe<Vector3>> Translations = new List<ImportedKeyframe<Vector3>>();
|
public List<ImportedKeyframe<Vector3>> Translations = new List<ImportedKeyframe<Vector3>>();
|
||||||
public List<ImportedKeyframe<float>> Curve = new List<ImportedKeyframe<float>>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ImportedKeyframe<T>
|
public class ImportedKeyframe<T>
|
||||||
@ -167,7 +228,7 @@ namespace AssetStudio
|
|||||||
|
|
||||||
public class ImportedMorph
|
public class ImportedMorph
|
||||||
{
|
{
|
||||||
public string Name { get; set; }
|
public string Path { get; set; }
|
||||||
public string ClipName { get; set; }
|
public string ClipName { get; set; }
|
||||||
public List<Tuple<float, int, int>> Channels { get; set; }
|
public List<Tuple<float, int, int>> Channels { get; set; }
|
||||||
public List<ImportedMorphKeyframe> KeyframeList { get; set; }
|
public List<ImportedMorphKeyframe> KeyframeList { get; set; }
|
||||||
@ -184,45 +245,11 @@ namespace AssetStudio
|
|||||||
|
|
||||||
public static class ImportedHelpers
|
public static class ImportedHelpers
|
||||||
{
|
{
|
||||||
public static ImportedFrame FindFrame(string name, ImportedFrame root)
|
public static ImportedMesh FindMesh(string path, List<ImportedMesh> importedMeshList)
|
||||||
{
|
|
||||||
if (root.Name == name)
|
|
||||||
{
|
|
||||||
return root;
|
|
||||||
}
|
|
||||||
foreach (var child in root)
|
|
||||||
{
|
|
||||||
var frame = FindFrame(name, child);
|
|
||||||
if (frame != null)
|
|
||||||
{
|
|
||||||
return frame;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ImportedFrame FindChildOrRoot(string name, ImportedFrame root)
|
|
||||||
{
|
|
||||||
foreach (var child in root)
|
|
||||||
{
|
|
||||||
var frame = FindFrame(name, child);
|
|
||||||
if (frame != null)
|
|
||||||
{
|
|
||||||
return frame;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (root.Name == name)
|
|
||||||
{
|
|
||||||
return root;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ImportedMesh FindMesh(string frameName, List<ImportedMesh> importedMeshList)
|
|
||||||
{
|
{
|
||||||
foreach (var mesh in importedMeshList)
|
foreach (var mesh in importedMeshList)
|
||||||
{
|
{
|
||||||
if (mesh.Name == frameName)
|
if (mesh.Path == path)
|
||||||
{
|
{
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
@ -243,7 +270,7 @@ namespace AssetStudio
|
|||||||
|
|
||||||
foreach (var mesh in importedMeshList)
|
foreach (var mesh in importedMeshList)
|
||||||
{
|
{
|
||||||
if (mesh.Name == framePath)
|
if (mesh.Path == framePath)
|
||||||
{
|
{
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,7 @@ namespace AssetStudio {
|
|||||||
void SetJointsFromImportedMeshes(bool allBones);
|
void SetJointsFromImportedMeshes(bool allBones);
|
||||||
void ExportFrame(FbxNode* pParentNode, ImportedFrame^ frame);
|
void ExportFrame(FbxNode* pParentNode, ImportedFrame^ frame);
|
||||||
void ExportMesh(FbxNode* pFrameNode, ImportedMesh^ meshList, bool normals);
|
void ExportMesh(FbxNode* pFrameNode, ImportedMesh^ meshList, bool normals);
|
||||||
|
FbxNode* FindNodeByPath(String ^ path, bool recursive);
|
||||||
FbxFileTexture* ExportTexture(ImportedTexture^ matTex, FbxMesh* pMesh);
|
FbxFileTexture* ExportTexture(ImportedTexture^ matTex, FbxMesh* pMesh);
|
||||||
void ExportAnimations(bool eulerFilter, float filterValue, bool flatInbetween);
|
void ExportAnimations(bool eulerFilter, float filterValue, bool flatInbetween);
|
||||||
void ExportKeyframedAnimation(ImportedKeyframedAnimation^ parser, FbxString& kTakeName, FbxAnimCurveFilterUnroll* eulerFilter, float filterPrecision, bool flatInbetween);
|
void ExportKeyframedAnimation(ImportedKeyframedAnimation^ parser, FbxString& kTakeName, FbxAnimCurveFilterUnroll* eulerFilter, float filterPrecision, bool flatInbetween);
|
||||||
|
@ -228,9 +228,10 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
for (int i = 0; i < boneList->Count; i++)
|
for (int i = 0; i < boneList->Count; i++)
|
||||||
{
|
{
|
||||||
if (!exportFrames->Contains(boneList[i]->Name))
|
String^ boneName = boneList[i]->Path->Substring(boneList[i]->Path->LastIndexOf('/') + 1);
|
||||||
|
if (!exportFrames->Contains(boneName))
|
||||||
{
|
{
|
||||||
ImportedFrame^ boneParent = ImportedHelpers::FindChildOrRoot(boneList[i]->Name, imported->RootFrame);
|
ImportedFrame^ boneParent = imported->RootFrame->FindFrameByPath(boneList[i]->Path);
|
||||||
while (boneParent != nullptr)
|
while (boneParent != nullptr)
|
||||||
{
|
{
|
||||||
exportFrames->Add(boneParent->Name);
|
exportFrames->Add(boneParent->Name);
|
||||||
@ -263,7 +264,7 @@ namespace AssetStudio
|
|||||||
for (int j = 0; j < boneList->Count; j++)
|
for (int j = 0; j < boneList->Count; j++)
|
||||||
{
|
{
|
||||||
ImportedBone^ bone = boneList[j];
|
ImportedBone^ bone = boneList[j];
|
||||||
boneNames->Add(bone->Name);
|
boneNames->Add(bone->Path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -307,8 +308,8 @@ namespace AssetStudio
|
|||||||
|
|
||||||
void Fbx::Exporter::ExportMesh(FbxNode* pFrameNode, ImportedMesh^ meshList, bool normals)
|
void Fbx::Exporter::ExportMesh(FbxNode* pFrameNode, ImportedMesh^ meshList, bool normals)
|
||||||
{
|
{
|
||||||
int lastSlash = meshList->Name->LastIndexOf('/');
|
int lastSlash = meshList->Path->LastIndexOf('/');
|
||||||
String^ frameName = lastSlash < 0 ? meshList->Name : meshList->Name->Substring(lastSlash + 1);
|
String^ frameName = lastSlash < 0 ? meshList->Path : meshList->Path->Substring(lastSlash + 1);
|
||||||
List<ImportedBone^>^ boneList = meshList->BoneList;
|
List<ImportedBone^>^ boneList = meshList->BoneList;
|
||||||
bool hasBones;
|
bool hasBones;
|
||||||
if (exportSkins && boneList != nullptr)
|
if (exportSkins && boneList != nullptr)
|
||||||
@ -330,22 +331,8 @@ namespace AssetStudio
|
|||||||
for (int i = 0; i < boneList->Count; i++)
|
for (int i = 0; i < boneList->Count; i++)
|
||||||
{
|
{
|
||||||
ImportedBone^ bone = boneList[i];
|
ImportedBone^ bone = boneList[i];
|
||||||
String^ boneName = bone->Name;
|
FbxNode* lFrame = FindNodeByPath(bone->Path, false);
|
||||||
char* pBoneName = NULL;
|
pBoneNodeList->Add(lFrame);
|
||||||
try
|
|
||||||
{
|
|
||||||
pBoneName = StringToCharArray(boneName);
|
|
||||||
FbxNode* foundNode = pScene->GetRootNode()->FindChild(pBoneName);
|
|
||||||
if (foundNode == NULL)
|
|
||||||
{
|
|
||||||
throw gcnew Exception(gcnew String("Couldn't find frame ") + boneName + gcnew String(" used by the bone"));
|
|
||||||
}
|
|
||||||
pBoneNodeList->Add(foundNode);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Marshal::FreeHGlobal((IntPtr)pBoneName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -628,6 +615,41 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FbxNode* Fbx::Exporter::FindNodeByPath(String ^ path, bool recursive)
|
||||||
|
{
|
||||||
|
array<String^>^ splitPath = path->Split('/');
|
||||||
|
FbxNode* lNode = pScene->GetRootNode();
|
||||||
|
for (int i = 0; i < splitPath->Length; i++)
|
||||||
|
{
|
||||||
|
String^ frameName = splitPath[i];
|
||||||
|
char* pNodeName = NULL;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
pNodeName = StringToCharArray(frameName);
|
||||||
|
FbxNode* foundNode;
|
||||||
|
if (recursive && i == 0)
|
||||||
|
{
|
||||||
|
foundNode = lNode->FindChild(pNodeName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foundNode = lNode->FindChild(pNodeName, false);
|
||||||
|
}
|
||||||
|
if (foundNode == NULL)
|
||||||
|
{
|
||||||
|
//throw gcnew Exception(gcnew String("Couldn't find path ") + path);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
lNode = foundNode;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Marshal::FreeHGlobal((IntPtr)pNodeName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lNode;
|
||||||
|
}
|
||||||
|
|
||||||
FbxFileTexture* Fbx::Exporter::ExportTexture(ImportedTexture^ matTex, FbxMesh* pMesh)
|
FbxFileTexture* Fbx::Exporter::ExportTexture(ImportedTexture^ matTex, FbxMesh* pMesh)
|
||||||
{
|
{
|
||||||
FbxFileTexture* pTex = NULL;
|
FbxFileTexture* pTex = NULL;
|
||||||
@ -749,187 +771,77 @@ namespace AssetStudio
|
|||||||
for (int j = 0; j < pAnimationList->Count; j++)
|
for (int j = 0; j < pAnimationList->Count; j++)
|
||||||
{
|
{
|
||||||
ImportedAnimationKeyframedTrack^ keyframeList = pAnimationList[j];
|
ImportedAnimationKeyframedTrack^ keyframeList = pAnimationList[j];
|
||||||
String^ name = keyframeList->Name;
|
FbxNode* pNode = FindNodeByPath(keyframeList->Path, true);
|
||||||
int dotPos = name->IndexOf('.');
|
if (pNode != nullptr)
|
||||||
if (dotPos >= 0 && !ImportedHelpers::FindChildOrRoot(name, imported->RootFrame))
|
|
||||||
{
|
{
|
||||||
name = name->Substring(0, dotPos);
|
FbxAnimCurve* lCurveSX = pNode->LclScaling.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_X, true);
|
||||||
}
|
FbxAnimCurve* lCurveSY = pNode->LclScaling.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y, true);
|
||||||
FbxNode* pNode = NULL;
|
FbxAnimCurve* lCurveSZ = pNode->LclScaling.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z, true);
|
||||||
char* pName = NULL;
|
FbxAnimCurve* lCurveRX = pNode->LclRotation.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_X, true);
|
||||||
try
|
FbxAnimCurve* lCurveRY = pNode->LclRotation.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y, true);
|
||||||
{
|
FbxAnimCurve* lCurveRZ = pNode->LclRotation.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z, true);
|
||||||
pName = StringToCharArray(name);
|
FbxAnimCurve* lCurveTX = pNode->LclTranslation.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_X, true);
|
||||||
pNode = pScene->GetRootNode()->FindChild(pName);
|
FbxAnimCurve* lCurveTY = pNode->LclTranslation.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y, true);
|
||||||
}
|
FbxAnimCurve* lCurveTZ = pNode->LclTranslation.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z, true);
|
||||||
finally
|
|
||||||
{
|
|
||||||
Marshal::FreeHGlobal((IntPtr)pName);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pNode != NULL)
|
lCurveSX->KeyModifyBegin();
|
||||||
|
lCurveSY->KeyModifyBegin();
|
||||||
|
lCurveSZ->KeyModifyBegin();
|
||||||
|
lCurveRX->KeyModifyBegin();
|
||||||
|
lCurveRY->KeyModifyBegin();
|
||||||
|
lCurveRZ->KeyModifyBegin();
|
||||||
|
lCurveTX->KeyModifyBegin();
|
||||||
|
lCurveTY->KeyModifyBegin();
|
||||||
|
lCurveTZ->KeyModifyBegin();
|
||||||
|
|
||||||
|
FbxTime lTime;
|
||||||
|
|
||||||
|
for each (auto Scaling in keyframeList->Scalings)
|
||||||
{
|
{
|
||||||
FbxAnimCurve* lCurveSX = pNode->LclScaling.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_X, true);
|
lTime.SetSecondDouble(Scaling->time);
|
||||||
FbxAnimCurve* lCurveSY = pNode->LclScaling.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y, true);
|
|
||||||
FbxAnimCurve* lCurveSZ = pNode->LclScaling.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z, true);
|
|
||||||
FbxAnimCurve* lCurveRX = pNode->LclRotation.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_X, true);
|
|
||||||
FbxAnimCurve* lCurveRY = pNode->LclRotation.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y, true);
|
|
||||||
FbxAnimCurve* lCurveRZ = pNode->LclRotation.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z, true);
|
|
||||||
FbxAnimCurve* lCurveTX = pNode->LclTranslation.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_X, true);
|
|
||||||
FbxAnimCurve* lCurveTY = pNode->LclTranslation.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y, true);
|
|
||||||
FbxAnimCurve* lCurveTZ = pNode->LclTranslation.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z, true);
|
|
||||||
|
|
||||||
lCurveSX->KeyModifyBegin();
|
lCurveSX->KeySet(lCurveSX->KeyAdd(lTime), lTime, Scaling->value.X);
|
||||||
lCurveSY->KeyModifyBegin();
|
lCurveSY->KeySet(lCurveSY->KeyAdd(lTime), lTime, Scaling->value.Y);
|
||||||
lCurveSZ->KeyModifyBegin();
|
lCurveSZ->KeySet(lCurveSZ->KeyAdd(lTime), lTime, Scaling->value.Z);
|
||||||
lCurveRX->KeyModifyBegin();
|
|
||||||
lCurveRY->KeyModifyBegin();
|
|
||||||
lCurveRZ->KeyModifyBegin();
|
|
||||||
lCurveTX->KeyModifyBegin();
|
|
||||||
lCurveTY->KeyModifyBegin();
|
|
||||||
lCurveTZ->KeyModifyBegin();
|
|
||||||
|
|
||||||
FbxTime lTime;
|
|
||||||
|
|
||||||
for each (auto Scaling in keyframeList->Scalings)
|
|
||||||
{
|
|
||||||
lTime.SetSecondDouble(Scaling->time);
|
|
||||||
|
|
||||||
lCurveSX->KeySet(lCurveSX->KeyAdd(lTime), lTime, Scaling->value.X);
|
|
||||||
lCurveSY->KeySet(lCurveSY->KeyAdd(lTime), lTime, Scaling->value.Y);
|
|
||||||
lCurveSZ->KeySet(lCurveSZ->KeyAdd(lTime), lTime, Scaling->value.Z);
|
|
||||||
}
|
|
||||||
for each (auto Rotation in keyframeList->Rotations)
|
|
||||||
{
|
|
||||||
lTime.SetSecondDouble(Rotation->time);
|
|
||||||
|
|
||||||
lCurveRX->KeySet(lCurveRX->KeyAdd(lTime), lTime, Rotation->value.X);
|
|
||||||
lCurveRY->KeySet(lCurveRY->KeyAdd(lTime), lTime, Rotation->value.Y);
|
|
||||||
lCurveRZ->KeySet(lCurveRZ->KeyAdd(lTime), lTime, Rotation->value.Z);
|
|
||||||
}
|
|
||||||
for each (auto Translation in keyframeList->Translations)
|
|
||||||
{
|
|
||||||
lTime.SetSecondDouble(Translation->time);
|
|
||||||
|
|
||||||
lCurveTX->KeySet(lCurveTX->KeyAdd(lTime), lTime, Translation->value.X);
|
|
||||||
lCurveTY->KeySet(lCurveTY->KeyAdd(lTime), lTime, Translation->value.Y);
|
|
||||||
lCurveTZ->KeySet(lCurveTZ->KeyAdd(lTime), lTime, Translation->value.Z);
|
|
||||||
}
|
|
||||||
|
|
||||||
lCurveSX->KeyModifyEnd();
|
|
||||||
lCurveSY->KeyModifyEnd();
|
|
||||||
lCurveSZ->KeyModifyEnd();
|
|
||||||
lCurveRX->KeyModifyEnd();
|
|
||||||
lCurveRY->KeyModifyEnd();
|
|
||||||
lCurveRZ->KeyModifyEnd();
|
|
||||||
lCurveTX->KeyModifyEnd();
|
|
||||||
lCurveTY->KeyModifyEnd();
|
|
||||||
lCurveTZ->KeyModifyEnd();
|
|
||||||
|
|
||||||
if (eulerFilter)
|
|
||||||
{
|
|
||||||
FbxAnimCurve* lCurve[3];
|
|
||||||
lCurve[0] = lCurveRX;
|
|
||||||
lCurve[1] = lCurveRY;
|
|
||||||
lCurve[2] = lCurveRZ;
|
|
||||||
eulerFilter->Reset();
|
|
||||||
eulerFilter->SetQualityTolerance(filterPrecision);
|
|
||||||
eulerFilter->Apply(lCurve, 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keyframeList->Curve->Count > 0)
|
|
||||||
{
|
|
||||||
FbxNode* pMeshNode = pNode->GetChild(0);
|
|
||||||
FbxMesh* pMesh = pMeshNode ? pMeshNode->GetMesh() : NULL;
|
|
||||||
if (pMesh)
|
|
||||||
{
|
|
||||||
name = keyframeList->Name->Substring(dotPos + 1);
|
|
||||||
int numBlendShapes = pMesh->GetDeformerCount(FbxDeformer::eBlendShape);
|
|
||||||
for (int bsIdx = 0; bsIdx < numBlendShapes; bsIdx++)
|
|
||||||
{
|
|
||||||
FbxBlendShape* lBlendShape = (FbxBlendShape*)pMesh->GetDeformer(bsIdx, FbxDeformer::eBlendShape);
|
|
||||||
int numChannels = lBlendShape->GetBlendShapeChannelCount();
|
|
||||||
float flatMinStrength = 0, flatMaxStrength;
|
|
||||||
String^ shapeName = nullptr;
|
|
||||||
for (int chnIdx = 0; chnIdx < numChannels; chnIdx++)
|
|
||||||
{
|
|
||||||
FbxBlendShapeChannel* lChannel = lBlendShape->GetBlendShapeChannel(chnIdx);
|
|
||||||
String^ keyframeName;
|
|
||||||
if (!flatInbetween)
|
|
||||||
{
|
|
||||||
keyframeName = gcnew String(lChannel->GetName());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
shapeName = gcnew String(lChannel->GetTargetShape(0)->GetName());
|
|
||||||
keyframeName = shapeName->Substring(0, shapeName->LastIndexOf("_"));
|
|
||||||
}
|
|
||||||
if (keyframeName == name)
|
|
||||||
{
|
|
||||||
FbxAnimCurve* lCurve = lChannel->DeformPercent.GetCurve(lAnimLayer, true);
|
|
||||||
if (flatInbetween)
|
|
||||||
{
|
|
||||||
FbxProperty weightProp;
|
|
||||||
WITH_MARSHALLED_STRING
|
|
||||||
(
|
|
||||||
weightName,
|
|
||||||
shapeName + ".Weight",
|
|
||||||
weightProp = pMesh->FindProperty(weightName);
|
|
||||||
);
|
|
||||||
if (weightProp.IsValid())
|
|
||||||
{
|
|
||||||
flatMaxStrength = (float)weightProp.Get<double>();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
flatMaxStrength = 100;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lCurve->KeyModifyBegin();
|
|
||||||
for each (auto Curve in keyframeList->Curve)
|
|
||||||
{
|
|
||||||
lTime.SetSecondDouble(Curve->time);
|
|
||||||
|
|
||||||
auto keySetIndex = lCurve->KeyAdd(lTime);
|
|
||||||
|
|
||||||
if (!flatInbetween)
|
|
||||||
{
|
|
||||||
lCurve->KeySet(keySetIndex, lTime, Curve->value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
float val = Curve->value;
|
|
||||||
if (val >= flatMinStrength && val <= flatMaxStrength)
|
|
||||||
{
|
|
||||||
val = (val - flatMinStrength) * 100 / (flatMaxStrength - flatMinStrength);
|
|
||||||
}
|
|
||||||
else if (val < flatMinStrength)
|
|
||||||
{
|
|
||||||
val = 0;
|
|
||||||
}
|
|
||||||
else if (val > flatMaxStrength)
|
|
||||||
{
|
|
||||||
val = 100;
|
|
||||||
}
|
|
||||||
lCurve->KeySet(keySetIndex, lTime, val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lCurve->KeyModifyEnd();
|
|
||||||
if (!flatInbetween)
|
|
||||||
{
|
|
||||||
bsIdx = numBlendShapes;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
flatMinStrength = flatMaxStrength;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
for each (auto Rotation in keyframeList->Rotations)
|
||||||
|
{
|
||||||
|
lTime.SetSecondDouble(Rotation->time);
|
||||||
|
|
||||||
|
lCurveRX->KeySet(lCurveRX->KeyAdd(lTime), lTime, Rotation->value.X);
|
||||||
|
lCurveRY->KeySet(lCurveRY->KeyAdd(lTime), lTime, Rotation->value.Y);
|
||||||
|
lCurveRZ->KeySet(lCurveRZ->KeyAdd(lTime), lTime, Rotation->value.Z);
|
||||||
|
}
|
||||||
|
for each (auto Translation in keyframeList->Translations)
|
||||||
|
{
|
||||||
|
lTime.SetSecondDouble(Translation->time);
|
||||||
|
|
||||||
|
lCurveTX->KeySet(lCurveTX->KeyAdd(lTime), lTime, Translation->value.X);
|
||||||
|
lCurveTY->KeySet(lCurveTY->KeyAdd(lTime), lTime, Translation->value.Y);
|
||||||
|
lCurveTZ->KeySet(lCurveTZ->KeyAdd(lTime), lTime, Translation->value.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
lCurveSX->KeyModifyEnd();
|
||||||
|
lCurveSY->KeyModifyEnd();
|
||||||
|
lCurveSZ->KeyModifyEnd();
|
||||||
|
lCurveRX->KeyModifyEnd();
|
||||||
|
lCurveRY->KeyModifyEnd();
|
||||||
|
lCurveRZ->KeyModifyEnd();
|
||||||
|
lCurveTX->KeyModifyEnd();
|
||||||
|
lCurveTY->KeyModifyEnd();
|
||||||
|
lCurveTZ->KeyModifyEnd();
|
||||||
|
|
||||||
|
if (eulerFilter)
|
||||||
|
{
|
||||||
|
FbxAnimCurve* lCurve[3];
|
||||||
|
lCurve[0] = lCurveRX;
|
||||||
|
lCurve[1] = lCurveRY;
|
||||||
|
lCurve[2] = lCurveRZ;
|
||||||
|
eulerFilter->Reset();
|
||||||
|
eulerFilter->SetQualityTolerance(filterPrecision);
|
||||||
|
eulerFilter->Apply(lCurve, 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -953,7 +865,7 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
framePath = gcnew String(rootNode->GetName()) + "/" + framePath;
|
framePath = gcnew String(rootNode->GetName()) + "/" + framePath;
|
||||||
}
|
}
|
||||||
if (framePath == meshList->Name)
|
if (framePath == meshList->Path)
|
||||||
{
|
{
|
||||||
pBaseNode = pMeshNode;
|
pBaseNode = pMeshNode;
|
||||||
break;
|
break;
|
||||||
@ -966,7 +878,7 @@ namespace AssetStudio
|
|||||||
|
|
||||||
for each (ImportedMorph^ morph in imported->MorphList)
|
for each (ImportedMorph^ morph in imported->MorphList)
|
||||||
{
|
{
|
||||||
if (morph->Name != meshList->Name)
|
if (morph->Path != meshList->Path)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -18,10 +18,10 @@ namespace AssetStudio
|
|||||||
public List<ImportedMorph> MorphList { get; protected set; } = new List<ImportedMorph>();
|
public List<ImportedMorph> MorphList { get; protected set; } = new List<ImportedMorph>();
|
||||||
|
|
||||||
private Avatar avatar;
|
private Avatar avatar;
|
||||||
private Dictionary<uint, string> morphChannelInfo = new Dictionary<uint, string>();
|
|
||||||
private HashSet<AnimationClip> animationClipHashSet = new HashSet<AnimationClip>();
|
private HashSet<AnimationClip> animationClipHashSet = new HashSet<AnimationClip>();
|
||||||
private Dictionary<uint, string> bonePathHash = new Dictionary<uint, string>();
|
private Dictionary<uint, string> bonePathHash = new Dictionary<uint, string>();
|
||||||
private Dictionary<Texture2D, string> textureNameDictionary = new Dictionary<Texture2D, string>();
|
private Dictionary<Texture2D, string> textureNameDictionary = new Dictionary<Texture2D, string>();
|
||||||
|
private Dictionary<Transform, ImportedFrame> transformDictionary = new Dictionary<Transform, ImportedFrame>();
|
||||||
|
|
||||||
public ModelConverter(GameObject m_GameObject)
|
public ModelConverter(GameObject m_GameObject)
|
||||||
{
|
{
|
||||||
@ -183,9 +183,10 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ImportedFrame ConvertTransform(Transform trans)
|
private ImportedFrame ConvertTransform(Transform trans)
|
||||||
{
|
{
|
||||||
var frame = new ImportedFrame(trans.m_Children.Length);
|
var frame = new ImportedFrame(trans.m_Children.Length);
|
||||||
|
transformDictionary.Add(trans, frame);
|
||||||
trans.m_GameObject.TryGet(out var m_GameObject);
|
trans.m_GameObject.TryGet(out var m_GameObject);
|
||||||
frame.Name = m_GameObject.m_Name;
|
frame.Name = m_GameObject.m_Name;
|
||||||
SetFrame(frame, trans.m_LocalPosition, trans.m_LocalRotation, trans.m_LocalScale);
|
SetFrame(frame, trans.m_LocalPosition, trans.m_LocalRotation, trans.m_LocalScale);
|
||||||
@ -232,7 +233,7 @@ namespace AssetStudio
|
|||||||
return;
|
return;
|
||||||
var iMesh = new ImportedMesh();
|
var iMesh = new ImportedMesh();
|
||||||
meshR.m_GameObject.TryGet(out var m_GameObject2);
|
meshR.m_GameObject.TryGet(out var m_GameObject2);
|
||||||
iMesh.Name = GetMeshPath(m_GameObject2.m_Transform);
|
iMesh.Path = GetTransformPath(m_GameObject2.m_Transform);
|
||||||
iMesh.SubmeshList = new List<ImportedSubmesh>();
|
iMesh.SubmeshList = new List<ImportedSubmesh>();
|
||||||
var subHashSet = new HashSet<int>();
|
var subHashSet = new HashSet<int>();
|
||||||
var combine = false;
|
var combine = false;
|
||||||
@ -358,46 +359,37 @@ namespace AssetStudio
|
|||||||
iMesh.SubmeshList.Add(iSubmesh);
|
iMesh.SubmeshList.Add(iSubmesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Bone
|
|
||||||
iMesh.BoneList = new List<ImportedBone>();
|
|
||||||
if (mesh.m_BindPose?.Length > 0 && mesh.m_BoneNameHashes?.Length > 0 && mesh.m_BindPose.Length == mesh.m_BoneNameHashes.Length)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < mesh.m_BindPose.Length; i++)
|
|
||||||
{
|
|
||||||
var bone = new ImportedBone();
|
|
||||||
var boneHash = mesh.m_BoneNameHashes[i];
|
|
||||||
bone.Name = GetNameFromBonePathHashes(boneHash);
|
|
||||||
if (string.IsNullOrEmpty(bone.Name))
|
|
||||||
{
|
|
||||||
bone.Name = avatar?.FindBoneName(boneHash);
|
|
||||||
}
|
|
||||||
if (string.IsNullOrEmpty(bone.Name))
|
|
||||||
{
|
|
||||||
//throw new Exception("A Bone could neither be found by hash in Avatar nor by index in SkinnedMeshRenderer.");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
var convert = Matrix.Scaling(new Vector3(-1, 1, 1));
|
|
||||||
bone.Matrix = convert * Matrix.Transpose(mesh.m_BindPose[i]) * convert;
|
|
||||||
iMesh.BoneList.Add(bone);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (meshR is SkinnedMeshRenderer sMesh)
|
if (meshR is SkinnedMeshRenderer sMesh)
|
||||||
{
|
{
|
||||||
//Bone for 4.3 down and other
|
//Bone
|
||||||
if (iMesh.BoneList.Count == 0)
|
if (sMesh.m_Bones.Length > 0)
|
||||||
{
|
{
|
||||||
|
iMesh.BoneList = new List<ImportedBone>(sMesh.m_Bones.Length);
|
||||||
for (int i = 0; i < sMesh.m_Bones.Length; i++)
|
for (int i = 0; i < sMesh.m_Bones.Length; 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))
|
||||||
{
|
{
|
||||||
if (m_Transform.m_GameObject.TryGet(out var m_GameObject))
|
bone.Path = GetTransformPath(m_Transform);
|
||||||
{
|
|
||||||
bone.Name = m_GameObject.m_Name;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!string.IsNullOrEmpty(bone.Name))
|
if (!string.IsNullOrEmpty(bone.Path))
|
||||||
|
{
|
||||||
|
var convert = Matrix.Scaling(new Vector3(-1, 1, 1));
|
||||||
|
bone.Matrix = convert * Matrix.Transpose(mesh.m_BindPose[i]) * convert;
|
||||||
|
iMesh.BoneList.Add(bone);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mesh.m_BindPose.Length > 0 && mesh.m_BoneNameHashes?.Length > 0 && mesh.m_BindPose.Length == mesh.m_BoneNameHashes.Length)
|
||||||
|
{
|
||||||
|
iMesh.BoneList = new List<ImportedBone>(mesh.m_BoneNameHashes.Length);
|
||||||
|
for (int i = 0; i < mesh.m_BoneNameHashes.Length; 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 = Matrix.Scaling(new Vector3(-1, 1, 1));
|
var convert = Matrix.Scaling(new Vector3(-1, 1, 1));
|
||||||
bone.Matrix = convert * Matrix.Transpose(mesh.m_BindPose[i]) * convert;
|
bone.Matrix = convert * Matrix.Transpose(mesh.m_BindPose[i]) * convert;
|
||||||
@ -407,12 +399,8 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Morphs
|
//Morphs
|
||||||
if (mesh.m_Shapes?.channels != null)
|
if (mesh.m_Shapes?.shapes != null)
|
||||||
{
|
{
|
||||||
foreach (var channel in mesh.m_Shapes.channels)
|
|
||||||
{
|
|
||||||
morphChannelInfo[channel.nameHash] = channel.name;
|
|
||||||
}
|
|
||||||
if (mesh.m_Shapes.shapes.Length > 0)
|
if (mesh.m_Shapes.shapes.Length > 0)
|
||||||
{
|
{
|
||||||
ImportedMorph morph = null;
|
ImportedMorph morph = null;
|
||||||
@ -424,7 +412,7 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
morph = new ImportedMorph();
|
morph = new ImportedMorph();
|
||||||
MorphList.Add(morph);
|
MorphList.Add(morph);
|
||||||
morph.Name = iMesh.Name;
|
morph.Path = iMesh.Path;
|
||||||
morph.ClipName = group;
|
morph.ClipName = group;
|
||||||
morph.Channels = new List<Tuple<float, int, int>>(mesh.m_Shapes.channels.Length);
|
morph.Channels = new List<Tuple<float, int, int>>(mesh.m_Shapes.channels.Length);
|
||||||
morph.KeyframeList = new List<ImportedMorphKeyframe>(mesh.m_Shapes.shapes.Length);
|
morph.KeyframeList = new List<ImportedMorphKeyframe>(mesh.m_Shapes.shapes.Length);
|
||||||
@ -470,7 +458,7 @@ namespace AssetStudio
|
|||||||
if (combine)
|
if (combine)
|
||||||
{
|
{
|
||||||
meshR.m_GameObject.TryGet(out var m_GameObject);
|
meshR.m_GameObject.TryGet(out var m_GameObject);
|
||||||
var frame = ImportedHelpers.FindChildOrRoot(m_GameObject.m_Name, RootFrame);
|
var frame = RootFrame.FindChild(m_GameObject.m_Name);
|
||||||
frame.LocalPosition = RootFrame.LocalPosition;
|
frame.LocalPosition = RootFrame.LocalPosition;
|
||||||
frame.LocalRotation = RootFrame.LocalRotation;
|
frame.LocalRotation = RootFrame.LocalRotation;
|
||||||
while (frame.Parent != null)
|
while (frame.Parent != null)
|
||||||
@ -508,26 +496,43 @@ namespace AssetStudio
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetMeshPath(Transform meshTransform)
|
private string GetTransformPath(Transform transform)
|
||||||
{
|
{
|
||||||
meshTransform.m_GameObject.TryGet(out var m_GameObject);
|
var frame = transformDictionary[transform];
|
||||||
var curFrame = ImportedHelpers.FindChildOrRoot(m_GameObject.m_Name, RootFrame);
|
return GetFramePath(frame);
|
||||||
var path = curFrame.Name;
|
}
|
||||||
while (curFrame.Parent != null)
|
|
||||||
{
|
|
||||||
curFrame = curFrame.Parent;
|
|
||||||
path = curFrame.Name + "/" + path;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
private static string GetFramePath(ImportedFrame frame)
|
||||||
|
{
|
||||||
|
var path = frame.Name;
|
||||||
|
while (frame.Parent != null)
|
||||||
|
{
|
||||||
|
frame = frame.Parent;
|
||||||
|
path = frame.Name + "/" + path;
|
||||||
|
}
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetTransformPath(Transform transform)
|
private string FixBonePath(string path)
|
||||||
|
{
|
||||||
|
var name = path.Substring(path.LastIndexOf('/') + 1);
|
||||||
|
foreach (var frame in RootFrame.FindChilds(name))
|
||||||
|
{
|
||||||
|
var fullPath = GetFramePath(frame);
|
||||||
|
if (fullPath.EndsWith(path))
|
||||||
|
{
|
||||||
|
return fullPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetTransformPathByFather(Transform transform)
|
||||||
{
|
{
|
||||||
transform.m_GameObject.TryGet(out var m_GameObject);
|
transform.m_GameObject.TryGet(out var m_GameObject);
|
||||||
if (transform.m_Father.TryGet(out var father))
|
if (transform.m_Father.TryGet(out var father))
|
||||||
{
|
{
|
||||||
return GetTransformPath(father) + "/" + m_GameObject.m_Name;
|
return GetTransformPathByFather(father) + "/" + m_GameObject.m_Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_GameObject.m_Name;
|
return m_GameObject.m_Name;
|
||||||
@ -680,9 +685,7 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
foreach (var m_CompressedRotationCurve in animationClip.m_CompressedRotationCurves)
|
foreach (var m_CompressedRotationCurve in animationClip.m_CompressedRotationCurves)
|
||||||
{
|
{
|
||||||
var path = m_CompressedRotationCurve.m_Path;
|
var track = iAnim.FindTrack(m_CompressedRotationCurve.m_Path);
|
||||||
var boneName = path.Substring(path.LastIndexOf('/') + 1);
|
|
||||||
var track = iAnim.FindTrack(boneName);
|
|
||||||
|
|
||||||
var numKeys = m_CompressedRotationCurve.m_Times.m_NumItems;
|
var numKeys = m_CompressedRotationCurve.m_Times.m_NumItems;
|
||||||
var data = m_CompressedRotationCurve.m_Times.UnpackInts();
|
var data = m_CompressedRotationCurve.m_Times.UnpackInts();
|
||||||
@ -704,9 +707,7 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
foreach (var m_RotationCurve in animationClip.m_RotationCurves)
|
foreach (var m_RotationCurve in animationClip.m_RotationCurves)
|
||||||
{
|
{
|
||||||
var path = m_RotationCurve.path;
|
var track = iAnim.FindTrack(m_RotationCurve.path);
|
||||||
var boneName = path.Substring(path.LastIndexOf('/') + 1);
|
|
||||||
var track = iAnim.FindTrack(boneName);
|
|
||||||
foreach (var m_Curve in m_RotationCurve.curve.m_Curve)
|
foreach (var m_Curve in m_RotationCurve.curve.m_Curve)
|
||||||
{
|
{
|
||||||
var value = Fbx.QuaternionToEuler(new Quaternion(m_Curve.value.X, -m_Curve.value.Y, -m_Curve.value.Z, m_Curve.value.W));
|
var value = Fbx.QuaternionToEuler(new Quaternion(m_Curve.value.X, -m_Curve.value.Y, -m_Curve.value.Z, m_Curve.value.W));
|
||||||
@ -715,9 +716,7 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
foreach (var m_PositionCurve in animationClip.m_PositionCurves)
|
foreach (var m_PositionCurve in animationClip.m_PositionCurves)
|
||||||
{
|
{
|
||||||
var path = m_PositionCurve.path;
|
var track = iAnim.FindTrack(m_PositionCurve.path);
|
||||||
var boneName = path.Substring(path.LastIndexOf('/') + 1);
|
|
||||||
var track = iAnim.FindTrack(boneName);
|
|
||||||
foreach (var m_Curve in m_PositionCurve.curve.m_Curve)
|
foreach (var m_Curve in m_PositionCurve.curve.m_Curve)
|
||||||
{
|
{
|
||||||
track.Translations.Add(new ImportedKeyframe<Vector3>(m_Curve.time, new Vector3(-m_Curve.value.X, m_Curve.value.Y, m_Curve.value.Z)));
|
track.Translations.Add(new ImportedKeyframe<Vector3>(m_Curve.time, new Vector3(-m_Curve.value.X, m_Curve.value.Y, m_Curve.value.Z)));
|
||||||
@ -725,9 +724,7 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
foreach (var m_ScaleCurve in animationClip.m_ScaleCurves)
|
foreach (var m_ScaleCurve in animationClip.m_ScaleCurves)
|
||||||
{
|
{
|
||||||
var path = m_ScaleCurve.path;
|
var track = iAnim.FindTrack(m_ScaleCurve.path);
|
||||||
var boneName = path.Substring(path.LastIndexOf('/') + 1);
|
|
||||||
var track = iAnim.FindTrack(boneName);
|
|
||||||
foreach (var m_Curve in m_ScaleCurve.curve.m_Curve)
|
foreach (var m_Curve in m_ScaleCurve.curve.m_Curve)
|
||||||
{
|
{
|
||||||
track.Scalings.Add(new ImportedKeyframe<Vector3>(m_Curve.time, new Vector3(m_Curve.value.X, m_Curve.value.Y, m_Curve.value.Z)));
|
track.Scalings.Add(new ImportedKeyframe<Vector3>(m_Curve.time, new Vector3(m_Curve.value.X, m_Curve.value.Y, m_Curve.value.Z)));
|
||||||
@ -737,25 +734,21 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
foreach (var m_EulerCurve in animationClip.m_EulerCurves)
|
foreach (var m_EulerCurve in animationClip.m_EulerCurves)
|
||||||
{
|
{
|
||||||
var path = m_EulerCurve.path;
|
var track = iAnim.FindTrack(m_EulerCurve.path);
|
||||||
var boneName = path.Substring(path.LastIndexOf('/') + 1);
|
|
||||||
var track = iAnim.FindTrack(boneName);
|
|
||||||
foreach (var m_Curve in m_EulerCurve.curve.m_Curve)
|
foreach (var m_Curve in m_EulerCurve.curve.m_Curve)
|
||||||
{
|
{
|
||||||
track.Rotations.Add(new ImportedKeyframe<Vector3>(m_Curve.time, new Vector3(m_Curve.value.X, -m_Curve.value.Y, -m_Curve.value.Z)));
|
track.Rotations.Add(new ImportedKeyframe<Vector3>(m_Curve.time, new Vector3(m_Curve.value.X, -m_Curve.value.Y, -m_Curve.value.Z)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (var m_FloatCurve in animationClip.m_FloatCurves)
|
/*foreach (var m_FloatCurve in animationClip.m_FloatCurves)
|
||||||
{
|
{
|
||||||
var path = m_FloatCurve.path;
|
var track = iAnim.FindTrack(m_FloatCurve.path);
|
||||||
var boneName = path.Substring(path.LastIndexOf('/') + 1);
|
|
||||||
var track = iAnim.FindTrack(boneName);
|
|
||||||
foreach (var m_Curve in m_FloatCurve.curve.m_Curve)
|
foreach (var m_Curve in m_FloatCurve.curve.m_Curve)
|
||||||
{
|
{
|
||||||
track.Curve.Add(new ImportedKeyframe<float>(m_Curve.time, m_Curve.value));
|
track.Curve.Add(new ImportedKeyframe<float>(m_Curve.time, m_Curve.value));
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -810,8 +803,8 @@ namespace AssetStudio
|
|||||||
curveIndex++;
|
curveIndex++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var boneName = GetNameFromHashes(binding.path, binding.attribute);
|
|
||||||
var track = iAnim.FindTrack(boneName);
|
var track = iAnim.FindTrack(GetPathFromHash(binding.path));
|
||||||
|
|
||||||
switch (binding.attribute)
|
switch (binding.attribute)
|
||||||
{
|
{
|
||||||
@ -850,37 +843,23 @@ namespace AssetStudio
|
|||||||
)));
|
)));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
track.Curve.Add(new ImportedKeyframe<float>(time, data[curveIndex++]));
|
//track.Curve.Add(new ImportedKeyframe<float>(time, data[curveIndex++]));
|
||||||
|
curveIndex++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetNameFromHashes(uint path, uint attribute)
|
private string GetPathFromHash(uint hash)
|
||||||
{
|
{
|
||||||
var boneName = GetNameFromBonePathHashes(path);
|
bonePathHash.TryGetValue(hash, out var boneName);
|
||||||
if (string.IsNullOrEmpty(boneName))
|
if (string.IsNullOrEmpty(boneName))
|
||||||
{
|
{
|
||||||
boneName = avatar?.FindBoneName(path);
|
boneName = avatar?.FindBonePath(hash);
|
||||||
}
|
}
|
||||||
if (string.IsNullOrEmpty(boneName))
|
if (string.IsNullOrEmpty(boneName))
|
||||||
{
|
{
|
||||||
boneName = "unknown " + path;
|
boneName = "unknown " + hash;
|
||||||
}
|
}
|
||||||
if (attribute > 4)
|
|
||||||
{
|
|
||||||
if (morphChannelInfo.TryGetValue(attribute, out var morphChannel))
|
|
||||||
{
|
|
||||||
return boneName + "." + morphChannel;
|
|
||||||
}
|
|
||||||
return boneName + ".unknown_morphChannel " + attribute;
|
|
||||||
}
|
|
||||||
return boneName;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetNameFromBonePathHashes(uint path)
|
|
||||||
{
|
|
||||||
if (bonePathHash.TryGetValue(path, out var boneName))
|
|
||||||
boneName = boneName.Substring(boneName.LastIndexOf('/') + 1);
|
|
||||||
return boneName;
|
return boneName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -922,7 +901,7 @@ namespace AssetStudio
|
|||||||
|
|
||||||
private void CreateBonePathHash(Transform m_Transform)
|
private void CreateBonePathHash(Transform m_Transform)
|
||||||
{
|
{
|
||||||
var name = GetTransformPath(m_Transform);
|
var name = GetTransformPathByFather(m_Transform);
|
||||||
var crc = new SevenZip.CRC();
|
var crc = new SevenZip.CRC();
|
||||||
var bytes = Encoding.UTF8.GetBytes(name);
|
var bytes = Encoding.UTF8.GetBytes(name);
|
||||||
crc.Update(bytes, 0, (uint)bytes.Length);
|
crc.Update(bytes, 0, (uint)bytes.Length);
|
||||||
@ -971,13 +950,13 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
transformName = strs.Last();
|
transformName = strs.Last();
|
||||||
var parentFrameName = strs[strs.Length - 2];
|
var parentFrameName = strs[strs.Length - 2];
|
||||||
parentFrame = ImportedHelpers.FindChildOrRoot(parentFrameName, RootFrame);
|
parentFrame = RootFrame.FindChild(parentFrameName);
|
||||||
}
|
}
|
||||||
|
|
||||||
var skeletonPose = avatar.m_Avatar.m_DefaultPose;
|
var skeletonPose = avatar.m_Avatar.m_DefaultPose;
|
||||||
var xform = skeletonPose.m_X[i];
|
var xform = skeletonPose.m_X[i];
|
||||||
|
|
||||||
var frame = ImportedHelpers.FindChildOrRoot(transformName, RootFrame);
|
var frame = RootFrame.FindChild(transformName);
|
||||||
if (frame != null)
|
if (frame != null)
|
||||||
{
|
{
|
||||||
SetFrame(frame, xform.t, xform.q, xform.s);
|
SetFrame(frame, xform.t, xform.q, xform.s);
|
||||||
|
Loading…
Reference in New Issue
Block a user