improved morph export

This commit is contained in:
Perfare 2019-07-16 13:21:32 +08:00
parent eb4981808b
commit a6264b39d1
11 changed files with 110 additions and 284 deletions

View File

@ -246,18 +246,27 @@ namespace AssetStudio
public class ImportedMorph public class ImportedMorph
{ {
public string Path { get; set; } public string Path { get; set; }
public string ClipName { get; set; } public List<ImportedMorphChannel> Channels { get; set; }
public List<Tuple<float, int, int>> Channels { get; set; } }
public class ImportedMorphChannel
{
public string Name { get; set; }
public List<ImportedMorphKeyframe> KeyframeList { get; set; } public List<ImportedMorphKeyframe> KeyframeList { get; set; }
public List<ushort> MorphedVertexIndices { get; set; }
} }
public class ImportedMorphKeyframe public class ImportedMorphKeyframe
{ {
public string Name { get; set; } public bool hasNormals { get; set; }
public List<ImportedVertex> VertexList { get; set; } public bool hasTangents { get; set; }
public List<ushort> MorphedVertexIndices { get; set; }
public float Weight { get; set; } public float Weight { get; set; }
public List<ImportedMorphVertex> VertexList { get; set; }
}
public class ImportedMorphVertex
{
public uint Index { get; set; }
public ImportedVertex Vertex { get; set; }
} }
public static class ImportedHelpers public static class ImportedHelpers

View File

@ -48,7 +48,7 @@ namespace AssetStudio {
ref class Exporter ref class Exporter
{ {
public: public:
static void Export(String^ name, IImported^ imported, bool eulerFilter, float filterPrecision, bool allFrames, bool allBones, bool skins, float boneSize, float scaleFactor, bool flatInbetween, int versionIndex, bool isAscii); static void Export(String^ name, IImported^ imported, bool eulerFilter, float filterPrecision, bool allFrames, bool allBones, bool skins, float boneSize, float scaleFactor, int versionIndex, bool isAscii);
private: private:
bool exportSkins; bool exportSkins;
@ -77,9 +77,9 @@ namespace AssetStudio {
void ExportFrame(FbxNode* pParentNode, ImportedFrame^ frame); void ExportFrame(FbxNode* pParentNode, ImportedFrame^ frame);
void ExportMesh(FbxNode* pFrameNode, ImportedMesh^ meshList); void ExportMesh(FbxNode* pFrameNode, ImportedMesh^ meshList);
FbxFileTexture* ExportTexture(ImportedTexture^ matTex); FbxFileTexture* ExportTexture(ImportedTexture^ matTex);
void ExportAnimations(bool eulerFilter, float filterValue, bool flatInbetween); void ExportAnimations(bool eulerFilter, float filterValue);
void ExportKeyframedAnimation(ImportedKeyframedAnimation^ parser, FbxString& kTakeName, FbxAnimCurveFilterUnroll* eulerFilter, float filterPrecision, bool flatInbetween); void ExportKeyframedAnimation(ImportedKeyframedAnimation^ parser, FbxString& kTakeName, FbxAnimCurveFilterUnroll* eulerFilter, float filterPrecision);
void ExportMorphs(bool morphMask, bool flatInbetween); void ExportMorphs();
}; };
}; };
} }

View File

@ -2,7 +2,7 @@
namespace AssetStudio namespace AssetStudio
{ {
void Fbx::Exporter::Export(String^ path, IImported^ imported, bool eulerFilter, float filterPrecision, bool allFrames, bool allBones, bool skins, float boneSize, float scaleFactor, bool flatInbetween, int versionIndex, bool isAscii) void Fbx::Exporter::Export(String^ path, IImported^ imported, bool eulerFilter, float filterPrecision, bool allFrames, bool allBones, bool skins, float boneSize, float scaleFactor, int versionIndex, bool isAscii)
{ {
FileInfo^ file = gcnew FileInfo(path); FileInfo^ file = gcnew FileInfo(path);
DirectoryInfo^ dir = file->Directory; DirectoryInfo^ dir = file->Directory;
@ -14,8 +14,8 @@ namespace AssetStudio
Directory::SetCurrentDirectory(dir->FullName); Directory::SetCurrentDirectory(dir->FullName);
auto name = Path::GetFileName(path); auto name = Path::GetFileName(path);
Exporter^ exporter = gcnew Exporter(name, imported, allFrames, allBones, skins, boneSize, scaleFactor, versionIndex, isAscii); Exporter^ exporter = gcnew Exporter(name, imported, allFrames, allBones, skins, boneSize, scaleFactor, versionIndex, isAscii);
//TODO exporter->ExportMorphs(false, flatInbetween); exporter->ExportMorphs();
exporter->ExportAnimations(eulerFilter, filterPrecision, flatInbetween); exporter->ExportAnimations(eulerFilter, filterPrecision);
exporter->pExporter->Export(exporter->pScene); exporter->pExporter->Export(exporter->pScene);
delete exporter; delete exporter;
@ -629,7 +629,7 @@ namespace AssetStudio
prop.ConnectSrcObject(pTexture); prop.ConnectSrcObject(pTexture);
} }
void Fbx::Exporter::ExportAnimations(bool eulerFilter, float filterPrecision, bool flatInbetween) void Fbx::Exporter::ExportAnimations(bool eulerFilter, float filterPrecision)
{ {
auto importedAnimationList = imported->AnimationList; auto importedAnimationList = imported->AnimationList;
if (importedAnimationList == nullptr) if (importedAnimationList == nullptr)
@ -656,11 +656,11 @@ namespace AssetStudio
{ {
kTakeName = FbxString("Take") + FbxString(i); kTakeName = FbxString("Take") + FbxString(i);
} }
ExportKeyframedAnimation(importedAnimation, kTakeName, lFilter, filterPrecision, flatInbetween); ExportKeyframedAnimation(importedAnimation, kTakeName, lFilter, filterPrecision);
} }
} }
void Fbx::Exporter::ExportKeyframedAnimation(ImportedKeyframedAnimation^ parser, FbxString& kTakeName, FbxAnimCurveFilterUnroll* eulerFilter, float filterPrecision, bool flatInbetween) void Fbx::Exporter::ExportKeyframedAnimation(ImportedKeyframedAnimation^ parser, FbxString& kTakeName, FbxAnimCurveFilterUnroll* eulerFilter, float filterPrecision)
{ {
List<ImportedAnimationKeyframedTrack^>^ pAnimationList = parser->TrackList; List<ImportedAnimationKeyframedTrack^>^ pAnimationList = parser->TrackList;
@ -753,206 +753,60 @@ namespace AssetStudio
} }
} }
void Fbx::Exporter::ExportMorphs(bool morphMask, bool flatInbetween) void Fbx::Exporter::ExportMorphs()
{ {
/*if (imported->MeshList == nullptr) if (imported->MeshList == nullptr)
{ {
return; return;
} }
for each (ImportedMorph^ morph in imported->MorphList)
for (int meshIdx = 0; meshIdx < imported->MeshList->Count; meshIdx++)
{ {
ImportedMesh^ meshList = imported->MeshList[meshIdx]; auto frame = imported->RootFrame->FindFrameByPath(morph->Path);
FbxNode* pBaseNode = NULL; if (frame != nullptr)
for (int nodeIdx = 0; nodeIdx < pMeshNodes->GetCount(); nodeIdx++)
{ {
FbxNode* pMeshNode = pMeshNodes->GetAt(nodeIdx); FbxNode* pNode = (FbxNode*)frameToNode[frame];
String^ framePath = gcnew String(pMeshNode->GetName()); FbxMesh* pMesh = pNode->GetMesh();
FbxNode* rootNode = pMeshNode;
while ((rootNode = rootNode->GetParent()) != pScene->GetRootNode())
{
framePath = gcnew String(rootNode->GetName()) + "/" + framePath;
}
if (framePath == meshList->Path)
{
pBaseNode = pMeshNode;
break;
}
}
if (pBaseNode == NULL)
{
continue;
}
for each (ImportedMorph^ morph in imported->MorphList) FbxBlendShape* lBlendShape = FbxBlendShape::Create(pScene, pNode->GetName());
{ pMesh->AddDeformer(lBlendShape);
if (morph->Path != meshList->Path)
{
continue;
}
int meshVertexIndex = 0; for (int i = 0; i < morph->Channels->Count; i++)
for (int meshObjIdx = pBaseNode->GetChildCount() - meshList->SubmeshList->Count; meshObjIdx < meshList->SubmeshList->Count; meshObjIdx++)
{ {
List<ImportedVertex^>^ vertList = meshList->SubmeshList[meshObjIdx]->VertexList; auto channel = morph->Channels[i];
FbxNode* pBaseMeshNode = pBaseNode->GetChild(meshObjIdx);
FbxMesh* pBaseMesh = pBaseMeshNode->GetMesh();
int numColourSets = pBaseMesh->GetElementVertexColorCount();
FbxBlendShape* lBlendShape; FbxBlendShapeChannel* lBlendShapeChannel;
WITH_MARSHALLED_STRING WITH_MARSHALLED_STRING
( (
pShapeName, pChannelName,
morph->ClipName + (meshList->SubmeshList->Count > 1 ? "_" + meshObjIdx : String::Empty), channel->Name,
lBlendShape = FbxBlendShape::Create(pScene, pShapeName); lBlendShapeChannel = FbxBlendShapeChannel::Create(pScene, pChannelName);
); );
FbxProperty rootGroupProp = FbxProperty::Create(lBlendShape, FbxStringDT, "RootGroup"); lBlendShape->AddBlendShapeChannel(lBlendShapeChannel);
pBaseMesh->AddDeformer(lBlendShape);
List<ImportedMorphKeyframe^>^ keyframes = morph->KeyframeList; for each(ImportedMorphKeyframe^ keyframe in channel->KeyframeList)
for (int i = 0; i < morph->Channels->Count; i++)
{ {
FbxBlendShapeChannel* lBlendShapeChannel; FbxShape* lShape = FbxShape::Create(pScene, "");
if (!flatInbetween) lBlendShapeChannel->AddTargetShape(lShape, keyframe->Weight);
auto vectorCount = pMesh->GetControlPointsCount();
FbxVector4* orilVector4 = pMesh->GetControlPoints();
lShape->InitControlPoints(vectorCount);
FbxVector4* lVector4 = lShape->GetControlPoints();
for (int j = 0; j < vectorCount; j++)
{ {
WITH_MARSHALLED_STRING auto vertex = orilVector4[j];
( lVector4[j] = FbxVector4(vertex);
pChannelName,
gcnew String(lBlendShape->GetName()) + "." + keyframes[morph->Channels[i]->Item2]->Name->Substring(0, keyframes[morph->Channels[i]->Item2]->Name->LastIndexOf("_")),
lBlendShapeChannel = FbxBlendShapeChannel::Create(pScene, pChannelName);
);
lBlendShapeChannel->DeformPercent = morph->Channels[i]->Item1;
lBlendShape->AddBlendShapeChannel(lBlendShapeChannel);
} }
for (int j = 0; j < keyframe->VertexList->Count; j++)
for (int frameIdx = 0; frameIdx < morph->Channels[i]->Item3; frameIdx++)
{ {
int shapeIdx = morph->Channels[i]->Item2 + frameIdx; auto index = keyframe->VertexList[j]->Index;
ImportedMorphKeyframe^ keyframe = keyframes[shapeIdx]; auto coords = keyframe->VertexList[j]->Vertex->Position;
lVector4[index] = FbxVector4(coords.X, coords.Y, coords.Z, 0);
FbxShape* pShape;
if (!flatInbetween)
{
char* pMorphShapeName;
try
{
pMorphShapeName = StringToCharArray(keyframe->Name);
if (pScene->FindMember<FbxShape>(pMorphShapeName))
{
Marshal::FreeHGlobal((IntPtr)pMorphShapeName);
pMorphShapeName = StringToCharArray(morph->ClipName + (meshList->SubmeshList->Count > 1 ? "_" + meshObjIdx : String::Empty) + "__" + keyframe->Name);
}
pShape = FbxShape::Create(pScene, pMorphShapeName);
}
finally
{
Marshal::FreeHGlobal((IntPtr)pMorphShapeName);
}
if (frameIdx == morph->Channels[i]->Item3 - 1)
{
FbxProperty::Create(lBlendShape, FbxStringDT, rootGroupProp.GetName() + "|" + pShape->GetName());
}
lBlendShapeChannel->AddTargetShape(pShape, keyframe->Weight);
}
else
{
lBlendShapeChannel = FbxBlendShapeChannel::Create(pScene, "");
lBlendShapeChannel->DeformPercent = morph->Channels[i]->Item1;
lBlendShape->AddBlendShapeChannel(lBlendShapeChannel);
WITH_MARSHALLED_STRING
(
pMorphShapeName,
morph->ClipName + (meshList->SubmeshList->Count > 1 ? "_" + meshObjIdx : String::Empty) + "." + keyframe->Name,
pShape = FbxShape::Create(pScene, pMorphShapeName);
);
lBlendShapeChannel->AddTargetShape(pShape, 100);
FbxProperty weightProp;
WITH_MARSHALLED_STRING
(
pWeightName,
gcnew String(pShape->GetName()) + ".Weight",
weightProp = FbxProperty::Create(pBaseMesh, FbxDoubleDT, pWeightName);
);
weightProp.ModifyFlag(FbxPropertyFlags::eUserDefined, true);
weightProp.Set<double>(keyframe->Weight);
}
pShape->InitControlPoints(vertList->Count);
FbxVector4* pControlPoints = pShape->GetControlPoints();
for (int j = 0; j < vertList->Count; j++)
{
ImportedVertex^ vertex = vertList[j];
Vector3 coords = vertex->Position;
pControlPoints[j] = FbxVector4(coords.X, coords.Y, coords.Z, 0);
}
List<unsigned short>^ meshIndices = keyframe->MorphedVertexIndices;
for (int j = 0; j < meshIndices->Count; j++)
{
int controlPointIndex = meshIndices[j] - meshVertexIndex;
if (controlPointIndex >= 0 && controlPointIndex < vertList->Count)
{
Vector3 coords = keyframe->VertexList[j]->Position;
pControlPoints[controlPointIndex] = FbxVector4(coords.X, coords.Y, coords.Z, 0);
}
}
if (flatInbetween && meshIndices->Count == 0)
{
Vector3 coords = vertList[0]->Position;
pControlPoints[0] = FbxVector4(coords.X - 1.0e-6, coords.Y, coords.Z, 0);
}
if (flatInbetween && frameIdx > 0)
{
int shapeIdx = morph->Channels[i]->Item2 + frameIdx - 1;
ImportedMorphKeyframe^ keyframe = keyframes[shapeIdx];
List<unsigned short>^ meshIndices = keyframe->MorphedVertexIndices;
for (int j = 0; j < meshIndices->Count; j++)
{
int controlPointIndex = meshIndices[j] - meshVertexIndex;
if (controlPointIndex >= 0 && controlPointIndex < vertList->Count)
{
Vector3 coords = keyframe->VertexList[j]->Position - vertList[controlPointIndex]->Position;
pControlPoints[controlPointIndex] -= FbxVector4(coords.X, coords.Y, coords.Z, 0);
}
}
}
if (morphMask && frameIdx == 0)
{
int colourSetIdx = numColourSets + shapeIdx;
FbxGeometryElementVertexColor* lGeometryElementVertexColor = pBaseMesh->GetElementVertexColor(colourSetIdx);
if (lGeometryElementVertexColor == NULL)
{
lGeometryElementVertexColor = pBaseMesh->CreateElementVertexColor();
}
lGeometryElementVertexColor->SetMappingMode(FbxGeometryElement::eByControlPoint);
lGeometryElementVertexColor->SetReferenceMode(FbxGeometryElement::eDirect);
WITH_MARSHALLED_STRING
(
pColourLayerName, morph->ClipName + (meshList->SubmeshList->Count > 1 ? "_" + meshObjIdx : String::Empty) + "." + keyframe->Name,
lGeometryElementVertexColor->SetName(pColourLayerName);
);
for (int j = 0; j < vertList->Count; j++)
{
lGeometryElementVertexColor->GetDirectArray().Add(FbxColor(1, 1, 1));
}
for (int j = 0; j < meshIndices->Count; j++)
{
int controlPointIndex = meshIndices[j] - meshVertexIndex;
if (controlPointIndex >= 0 && controlPointIndex < vertList->Count)
{
lGeometryElementVertexColor->GetDirectArray().SetAt(controlPointIndex, FbxColor(0, 0, 1));
}
}
}
} }
} }
meshVertexIndex += meshList->SubmeshList[meshObjIdx]->VertexList->Count;
} }
} }
}*/ }
} }
} }

View File

@ -44,7 +44,6 @@
this.label4 = new System.Windows.Forms.Label(); this.label4 = new System.Windows.Forms.Label();
this.fbxVersion = new System.Windows.Forms.ComboBox(); this.fbxVersion = new System.Windows.Forms.ComboBox();
this.label3 = new System.Windows.Forms.Label(); this.label3 = new System.Windows.Forms.Label();
this.flatInbetween = new System.Windows.Forms.CheckBox();
this.boneSize = new System.Windows.Forms.NumericUpDown(); this.boneSize = new System.Windows.Forms.NumericUpDown();
this.label2 = new System.Windows.Forms.Label(); this.label2 = new System.Windows.Forms.Label();
this.skins = new System.Windows.Forms.CheckBox(); this.skins = new System.Windows.Forms.CheckBox();
@ -63,7 +62,7 @@
// //
// OKbutton // OKbutton
// //
this.OKbutton.Location = new System.Drawing.Point(321, 267); this.OKbutton.Location = new System.Drawing.Point(321, 244);
this.OKbutton.Name = "OKbutton"; this.OKbutton.Name = "OKbutton";
this.OKbutton.Size = new System.Drawing.Size(75, 21); this.OKbutton.Size = new System.Drawing.Size(75, 21);
this.OKbutton.TabIndex = 6; this.OKbutton.TabIndex = 6;
@ -74,7 +73,7 @@
// Cancel // Cancel
// //
this.Cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; this.Cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.Cancel.Location = new System.Drawing.Point(402, 267); this.Cancel.Location = new System.Drawing.Point(402, 244);
this.Cancel.Name = "Cancel"; this.Cancel.Name = "Cancel";
this.Cancel.Size = new System.Drawing.Size(75, 21); this.Cancel.Size = new System.Drawing.Size(75, 21);
this.Cancel.TabIndex = 7; this.Cancel.TabIndex = 7;
@ -170,7 +169,6 @@
this.groupBox2.Controls.Add(this.label4); this.groupBox2.Controls.Add(this.label4);
this.groupBox2.Controls.Add(this.fbxVersion); this.groupBox2.Controls.Add(this.fbxVersion);
this.groupBox2.Controls.Add(this.label3); this.groupBox2.Controls.Add(this.label3);
this.groupBox2.Controls.Add(this.flatInbetween);
this.groupBox2.Controls.Add(this.boneSize); this.groupBox2.Controls.Add(this.boneSize);
this.groupBox2.Controls.Add(this.label2); this.groupBox2.Controls.Add(this.label2);
this.groupBox2.Controls.Add(this.skins); this.groupBox2.Controls.Add(this.skins);
@ -181,7 +179,7 @@
this.groupBox2.Controls.Add(this.eulerFilter); this.groupBox2.Controls.Add(this.eulerFilter);
this.groupBox2.Location = new System.Drawing.Point(12, 12); this.groupBox2.Location = new System.Drawing.Point(12, 12);
this.groupBox2.Name = "groupBox2"; this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(214, 276); this.groupBox2.Size = new System.Drawing.Size(214, 255);
this.groupBox2.TabIndex = 11; this.groupBox2.TabIndex = 11;
this.groupBox2.TabStop = false; this.groupBox2.TabStop = false;
this.groupBox2.Text = "Fbx"; this.groupBox2.Text = "Fbx";
@ -221,7 +219,7 @@
this.fbxFormat.Items.AddRange(new object[] { this.fbxFormat.Items.AddRange(new object[] {
"Binary", "Binary",
"Ascii"}); "Ascii"});
this.fbxFormat.Location = new System.Drawing.Point(75, 207); this.fbxFormat.Location = new System.Drawing.Point(77, 186);
this.fbxFormat.Name = "fbxFormat"; this.fbxFormat.Name = "fbxFormat";
this.fbxFormat.Size = new System.Drawing.Size(61, 20); this.fbxFormat.Size = new System.Drawing.Size(61, 20);
this.fbxFormat.TabIndex = 18; this.fbxFormat.TabIndex = 18;
@ -229,7 +227,7 @@
// label4 // label4
// //
this.label4.AutoSize = true; this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(4, 210); this.label4.Location = new System.Drawing.Point(6, 189);
this.label4.Name = "label4"; this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(59, 12); this.label4.Size = new System.Drawing.Size(59, 12);
this.label4.TabIndex = 17; this.label4.TabIndex = 17;
@ -246,7 +244,7 @@
"7.3", "7.3",
"7.4", "7.4",
"7.5"}); "7.5"});
this.fbxVersion.Location = new System.Drawing.Point(75, 236); this.fbxVersion.Location = new System.Drawing.Point(77, 215);
this.fbxVersion.Name = "fbxVersion"; this.fbxVersion.Name = "fbxVersion";
this.fbxVersion.Size = new System.Drawing.Size(47, 20); this.fbxVersion.Size = new System.Drawing.Size(47, 20);
this.fbxVersion.TabIndex = 16; this.fbxVersion.TabIndex = 16;
@ -254,22 +252,12 @@
// label3 // label3
// //
this.label3.AutoSize = true; this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(4, 239); this.label3.Location = new System.Drawing.Point(6, 218);
this.label3.Name = "label3"; this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(65, 12); this.label3.Size = new System.Drawing.Size(65, 12);
this.label3.TabIndex = 15; this.label3.TabIndex = 15;
this.label3.Text = "FBXVersion"; this.label3.Text = "FBXVersion";
// //
// flatInbetween
//
this.flatInbetween.AutoSize = true;
this.flatInbetween.Location = new System.Drawing.Point(6, 182);
this.flatInbetween.Name = "flatInbetween";
this.flatInbetween.Size = new System.Drawing.Size(102, 16);
this.flatInbetween.TabIndex = 12;
this.flatInbetween.Text = "FlatInbetween";
this.flatInbetween.UseVisualStyleBackColor = true;
//
// boneSize // boneSize
// //
this.boneSize.Location = new System.Drawing.Point(65, 128); this.boneSize.Location = new System.Drawing.Point(65, 128);
@ -345,6 +333,8 @@
// allFrames // allFrames
// //
this.allFrames.AutoSize = true; this.allFrames.AutoSize = true;
this.allFrames.Checked = true;
this.allFrames.CheckState = System.Windows.Forms.CheckState.Checked;
this.allFrames.Location = new System.Drawing.Point(6, 61); this.allFrames.Location = new System.Drawing.Point(6, 61);
this.allFrames.Name = "allFrames"; this.allFrames.Name = "allFrames";
this.allFrames.Size = new System.Drawing.Size(78, 16); this.allFrames.Size = new System.Drawing.Size(78, 16);
@ -370,7 +360,7 @@
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.Cancel; this.CancelButton = this.Cancel;
this.ClientSize = new System.Drawing.Size(490, 301); this.ClientSize = new System.Drawing.Size(490, 277);
this.Controls.Add(this.groupBox2); this.Controls.Add(this.groupBox2);
this.Controls.Add(this.groupBox1); this.Controls.Add(this.groupBox1);
this.Controls.Add(this.Cancel); this.Controls.Add(this.Cancel);
@ -408,7 +398,6 @@
private System.Windows.Forms.CheckBox convertAudio; private System.Windows.Forms.CheckBox convertAudio;
private System.Windows.Forms.Panel panel1; private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.GroupBox groupBox2; private System.Windows.Forms.GroupBox groupBox2;
private System.Windows.Forms.CheckBox flatInbetween;
private System.Windows.Forms.NumericUpDown boneSize; private System.Windows.Forms.NumericUpDown boneSize;
private System.Windows.Forms.Label label2; private System.Windows.Forms.Label label2;
private System.Windows.Forms.CheckBox skins; private System.Windows.Forms.CheckBox skins;

View File

@ -33,7 +33,6 @@ namespace AssetStudioGUI
skins.Checked = (bool)Properties.Settings.Default["skins"]; skins.Checked = (bool)Properties.Settings.Default["skins"];
boneSize.Value = (decimal)Properties.Settings.Default["boneSize"]; boneSize.Value = (decimal)Properties.Settings.Default["boneSize"];
scaleFactor.Value = (decimal)Properties.Settings.Default["scaleFactor"]; scaleFactor.Value = (decimal)Properties.Settings.Default["scaleFactor"];
flatInbetween.Checked = (bool)Properties.Settings.Default["flatInbetween"];
fbxVersion.SelectedIndex = (int)Properties.Settings.Default["fbxVersion"]; fbxVersion.SelectedIndex = (int)Properties.Settings.Default["fbxVersion"];
fbxFormat.SelectedIndex = (int)Properties.Settings.Default["fbxFormat"]; fbxFormat.SelectedIndex = (int)Properties.Settings.Default["fbxFormat"];
} }
@ -63,7 +62,6 @@ namespace AssetStudioGUI
Properties.Settings.Default["skins"] = skins.Checked; Properties.Settings.Default["skins"] = skins.Checked;
Properties.Settings.Default["boneSize"] = boneSize.Value; Properties.Settings.Default["boneSize"] = boneSize.Value;
Properties.Settings.Default["scaleFactor"] = scaleFactor.Value; Properties.Settings.Default["scaleFactor"] = scaleFactor.Value;
Properties.Settings.Default["flatInbetween"] = flatInbetween.Checked;
Properties.Settings.Default["fbxVersion"] = fbxVersion.SelectedIndex; Properties.Settings.Default["fbxVersion"] = fbxVersion.SelectedIndex;
Properties.Settings.Default["fbxFormat"] = fbxFormat.SelectedIndex; Properties.Settings.Default["fbxFormat"] = fbxFormat.SelectedIndex;
Properties.Settings.Default.Save(); Properties.Settings.Default.Save();

View File

@ -318,10 +318,9 @@ namespace AssetStudioGUI
var skins = (bool)Properties.Settings.Default["skins"]; var skins = (bool)Properties.Settings.Default["skins"];
var boneSize = (int)(decimal)Properties.Settings.Default["boneSize"]; var boneSize = (int)(decimal)Properties.Settings.Default["boneSize"];
var scaleFactor = (float)(decimal)Properties.Settings.Default["scaleFactor"]; var scaleFactor = (float)(decimal)Properties.Settings.Default["scaleFactor"];
var flatInbetween = (bool)Properties.Settings.Default["flatInbetween"];
var fbxVersion = (int)Properties.Settings.Default["fbxVersion"]; var fbxVersion = (int)Properties.Settings.Default["fbxVersion"];
var fbxFormat = (int)Properties.Settings.Default["fbxFormat"]; var fbxFormat = (int)Properties.Settings.Default["fbxFormat"];
ModelExporter.ExportFbx(exportPath, convert, eulerFilter, filterPrecision, allFrames, allBones, skins, boneSize, scaleFactor, flatInbetween, fbxVersion, fbxFormat == 1); ModelExporter.ExportFbx(exportPath, convert, eulerFilter, filterPrecision, allFrames, allBones, skins, boneSize, scaleFactor, fbxVersion, fbxFormat == 1);
return true; return true;
} }
} }

View File

@ -203,18 +203,6 @@ namespace AssetStudioGUI.Properties {
} }
} }
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public bool flatInbetween {
get {
return ((bool)(this["flatInbetween"]));
}
set {
this["flatInbetween"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()] [global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3")] [global::System.Configuration.DefaultSettingValueAttribute("3")]

View File

@ -47,9 +47,6 @@
<Setting Name="boneSize" Type="System.Decimal" Scope="User"> <Setting Name="boneSize" Type="System.Decimal" Scope="User">
<Value Profile="(Default)">10</Value> <Value Profile="(Default)">10</Value>
</Setting> </Setting>
<Setting Name="flatInbetween" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="fbxVersion" Type="System.Int32" Scope="User"> <Setting Name="fbxVersion" Type="System.Int32" Scope="User">
<Value Profile="(Default)">3</Value> <Value Profile="(Default)">3</Value>
</Setting> </Setting>

View File

@ -52,9 +52,6 @@
<setting name="boneSize" serializeAs="String"> <setting name="boneSize" serializeAs="String">
<value>10</value> <value>10</value>
</setting> </setting>
<setting name="flatInbetween" serializeAs="String">
<value>False</value>
</setting>
<setting name="fbxVersion" serializeAs="String"> <setting name="fbxVersion" serializeAs="String">
<value>3</value> <value>3</value>
</setting> </setting>

View File

@ -403,55 +403,50 @@ namespace AssetStudio
} }
//Morphs //Morphs
if (mesh.m_Shapes?.shapes != null) if (mesh.m_Shapes?.channels?.Length > 0)
{ {
if (mesh.m_Shapes.shapes.Length > 0) var morph = new ImportedMorph();
MorphList.Add(morph);
morph.Path = iMesh.Path;
morph.Channels = new List<ImportedMorphChannel>(mesh.m_Shapes.channels.Length);
for (int i = 0; i < mesh.m_Shapes.channels.Length; i++)
{ {
ImportedMorph morph = null; var channel = new ImportedMorphChannel();
string lastGroup = ""; morph.Channels.Add(channel);
for (int i = 0; i < mesh.m_Shapes.channels.Length; i++) var shapeChannel = mesh.m_Shapes.channels[i];
channel.Name = shapeChannel.name;
channel.KeyframeList = new List<ImportedMorphKeyframe>(shapeChannel.frameCount);
var frameEnd = shapeChannel.frameIndex + shapeChannel.frameCount;
for (int frameIdx = shapeChannel.frameIndex; frameIdx < frameEnd; frameIdx++)
{ {
string group = BlendShapeNameGroup(mesh, i); var keyframe = new ImportedMorphKeyframe();
if (group != lastGroup) channel.KeyframeList.Add(keyframe);
keyframe.Weight = mesh.m_Shapes.fullWeights[frameIdx];
var shape = mesh.m_Shapes.shapes[frameIdx];
keyframe.hasNormals = shape.hasNormals;
keyframe.hasTangents = shape.hasTangents;
keyframe.VertexList = new List<ImportedMorphVertex>((int)shape.vertexCount);
var vertexEnd = shape.firstVertex + shape.vertexCount;
for (uint j = shape.firstVertex; j < vertexEnd; j++)
{ {
morph = new ImportedMorph(); var destVertex = new ImportedMorphVertex();
MorphList.Add(morph); keyframe.VertexList.Add(destVertex);
morph.Path = iMesh.Path; var morphVertex = mesh.m_Shapes.vertices[j];
morph.ClipName = group; destVertex.Index = morphVertex.index;
morph.Channels = new List<Tuple<float, int, int>>(mesh.m_Shapes.channels.Length); var sourceVertex = GetSourceVertex(iMesh.SubmeshList, (int)morphVertex.index);
morph.KeyframeList = new List<ImportedMorphKeyframe>(mesh.m_Shapes.shapes.Length); destVertex.Vertex = new ImportedVertex();
lastGroup = group; var morphPos = morphVertex.vertex;
} destVertex.Vertex.Position = sourceVertex.Position + new Vector3(-morphPos.X, morphPos.Y, morphPos.Z);
if (shape.hasNormals)
morph.Channels.Add(new Tuple<float, int, int>(i < sMesh.m_BlendShapeWeights.Length ? sMesh.m_BlendShapeWeights[i] : 0f, morph.KeyframeList.Count, mesh.m_Shapes.channels[i].frameCount));
for (int frameIdx = 0; frameIdx < mesh.m_Shapes.channels[i].frameCount; frameIdx++)
{
ImportedMorphKeyframe keyframe = new ImportedMorphKeyframe();
keyframe.Name = BlendShapeNameExtension(mesh, i) + "_" + frameIdx;
int shapeIdx = mesh.m_Shapes.channels[i].frameIndex + frameIdx;
keyframe.VertexList = new List<ImportedVertex>((int)mesh.m_Shapes.shapes[shapeIdx].vertexCount);
keyframe.MorphedVertexIndices = new List<ushort>((int)mesh.m_Shapes.shapes[shapeIdx].vertexCount);
keyframe.Weight = shapeIdx < mesh.m_Shapes.fullWeights.Length ? mesh.m_Shapes.fullWeights[shapeIdx] : 100f;
int lastVertIndex = (int)(mesh.m_Shapes.shapes[shapeIdx].firstVertex + mesh.m_Shapes.shapes[shapeIdx].vertexCount);
for (int j = (int)mesh.m_Shapes.shapes[shapeIdx].firstVertex; j < lastVertIndex; j++)
{ {
var morphVert = mesh.m_Shapes.vertices[j]; var morphNormal = morphVertex.normal;
ImportedVertex vert = GetSourceVertex(iMesh.SubmeshList, (int)morphVert.index); destVertex.Vertex.Normal = new Vector3(-morphNormal.X, morphNormal.Y, morphNormal.Z);
ImportedVertex destVert = new ImportedVertex(); }
Vector3 morphPos = morphVert.vertex; if (shape.hasTangents)
morphPos.X *= -1; {
destVert.Position = vert.Position + morphPos; var morphTangent = morphVertex.tangent;
Vector3 morphNormal = morphVert.normal; destVertex.Vertex.Tangent = new Vector4(-morphTangent.X, morphTangent.Y, morphTangent.Z, 0);
morphNormal.X *= -1;
destVert.Normal = morphNormal;
Vector4 morphTangent = new Vector4(morphVert.tangent, 0);
morphTangent.X *= -1;
destVert.Tangent = morphTangent;
keyframe.VertexList.Add(destVert);
keyframe.MorphedVertexIndices.Add((ushort)morphVert.index);
} }
morph.KeyframeList.Add(keyframe);
} }
} }
} }

View File

@ -2,9 +2,9 @@
{ {
public static class ModelExporter public static class ModelExporter
{ {
public static void ExportFbx(string path, IImported imported, bool eulerFilter, float filterPrecision, bool allFrames, bool allBones, bool skins, float boneSize, float scaleFactor, bool flatInbetween, int versionIndex, bool isAscii) public static void ExportFbx(string path, IImported imported, bool eulerFilter, float filterPrecision, bool allFrames, bool allBones, bool skins, float boneSize, float scaleFactor, int versionIndex, bool isAscii)
{ {
Fbx.Exporter.Export(path, imported, eulerFilter, filterPrecision, allFrames, allBones, skins, boneSize, scaleFactor, flatInbetween, versionIndex, isAscii); Fbx.Exporter.Export(path, imported, eulerFilter, filterPrecision, allFrames, allBones, skins, boneSize, scaleFactor, versionIndex, isAscii);
} }
} }
} }