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 (int meshIdx = 0; meshIdx < imported->MeshList->Count; meshIdx++)
{
ImportedMesh^ meshList = imported->MeshList[meshIdx];
FbxNode* pBaseNode = NULL;
for (int nodeIdx = 0; nodeIdx < pMeshNodes->GetCount(); nodeIdx++)
{
FbxNode* pMeshNode = pMeshNodes->GetAt(nodeIdx);
String^ framePath = gcnew String(pMeshNode->GetName());
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) for each (ImportedMorph^ morph in imported->MorphList)
{ {
if (morph->Path != meshList->Path) auto frame = imported->RootFrame->FindFrameByPath(morph->Path);
if (frame != nullptr)
{ {
continue; FbxNode* pNode = (FbxNode*)frameToNode[frame];
} FbxMesh* pMesh = pNode->GetMesh();
int meshVertexIndex = 0; FbxBlendShape* lBlendShape = FbxBlendShape::Create(pScene, pNode->GetName());
for (int meshObjIdx = pBaseNode->GetChildCount() - meshList->SubmeshList->Count; meshObjIdx < meshList->SubmeshList->Count; meshObjIdx++) pMesh->AddDeformer(lBlendShape);
{
List<ImportedVertex^>^ vertList = meshList->SubmeshList[meshObjIdx]->VertexList;
FbxNode* pBaseMeshNode = pBaseNode->GetChild(meshObjIdx);
FbxMesh* pBaseMesh = pBaseMeshNode->GetMesh();
int numColourSets = pBaseMesh->GetElementVertexColorCount();
FbxBlendShape* lBlendShape;
WITH_MARSHALLED_STRING
(
pShapeName,
morph->ClipName + (meshList->SubmeshList->Count > 1 ? "_" + meshObjIdx : String::Empty),
lBlendShape = FbxBlendShape::Create(pScene, pShapeName);
);
FbxProperty rootGroupProp = FbxProperty::Create(lBlendShape, FbxStringDT, "RootGroup");
pBaseMesh->AddDeformer(lBlendShape);
List<ImportedMorphKeyframe^>^ keyframes = morph->KeyframeList;
for (int i = 0; i < morph->Channels->Count; i++) for (int i = 0; i < morph->Channels->Count; i++)
{ {
auto channel = morph->Channels[i];
FbxBlendShapeChannel* lBlendShapeChannel; FbxBlendShapeChannel* lBlendShapeChannel;
if (!flatInbetween)
{
WITH_MARSHALLED_STRING WITH_MARSHALLED_STRING
( (
pChannelName, pChannelName,
gcnew String(lBlendShape->GetName()) + "." + keyframes[morph->Channels[i]->Item2]->Name->Substring(0, keyframes[morph->Channels[i]->Item2]->Name->LastIndexOf("_")), channel->Name,
lBlendShapeChannel = FbxBlendShapeChannel::Create(pScene, pChannelName); lBlendShapeChannel = FbxBlendShapeChannel::Create(pScene, pChannelName);
); );
lBlendShapeChannel->DeformPercent = morph->Channels[i]->Item1;
lBlendShape->AddBlendShapeChannel(lBlendShapeChannel);
}
for (int frameIdx = 0; frameIdx < morph->Channels[i]->Item3; frameIdx++)
{
int shapeIdx = morph->Channels[i]->Item2 + frameIdx;
ImportedMorphKeyframe^ keyframe = keyframes[shapeIdx];
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); lBlendShape->AddBlendShapeChannel(lBlendShapeChannel);
WITH_MARSHALLED_STRING for each(ImportedMorphKeyframe^ keyframe in channel->KeyframeList)
( {
pMorphShapeName, FbxShape* lShape = FbxShape::Create(pScene, "");
morph->ClipName + (meshList->SubmeshList->Count > 1 ? "_" + meshObjIdx : String::Empty) + "." + keyframe->Name, lBlendShapeChannel->AddTargetShape(lShape, keyframe->Weight);
pShape = FbxShape::Create(pScene, pMorphShapeName);
);
lBlendShapeChannel->AddTargetShape(pShape, 100);
FbxProperty weightProp; auto vectorCount = pMesh->GetControlPointsCount();
WITH_MARSHALLED_STRING FbxVector4* orilVector4 = pMesh->GetControlPoints();
( lShape->InitControlPoints(vectorCount);
pWeightName, FbxVector4* lVector4 = lShape->GetControlPoints();
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); for (int j = 0; j < vectorCount; j++)
FbxVector4* pControlPoints = pShape->GetControlPoints();
for (int j = 0; j < vertList->Count; j++)
{ {
ImportedVertex^ vertex = vertList[j]; auto vertex = orilVector4[j];
Vector3 coords = vertex->Position; lVector4[j] = FbxVector4(vertex);
pControlPoints[j] = FbxVector4(coords.X, coords.Y, coords.Z, 0);
} }
List<unsigned short>^ meshIndices = keyframe->MorphedVertexIndices; for (int j = 0; j < keyframe->VertexList->Count; j++)
for (int j = 0; j < meshIndices->Count; j++)
{ {
int controlPointIndex = meshIndices[j] - meshVertexIndex; auto index = keyframe->VertexList[j]->Index;
if (controlPointIndex >= 0 && controlPointIndex < vertList->Count) auto coords = keyframe->VertexList[j]->Vertex->Position;
{ lVector4[index] = FbxVector4(coords.X, coords.Y, coords.Z, 0);
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();
{
ImportedMorph morph = null;
string lastGroup = "";
for (int i = 0; i < mesh.m_Shapes.channels.Length; i++)
{
string group = BlendShapeNameGroup(mesh, i);
if (group != lastGroup)
{
morph = new ImportedMorph();
MorphList.Add(morph); MorphList.Add(morph);
morph.Path = iMesh.Path; morph.Path = iMesh.Path;
morph.ClipName = group; morph.Channels = new List<ImportedMorphChannel>(mesh.m_Shapes.channels.Length);
morph.Channels = new List<Tuple<float, int, int>>(mesh.m_Shapes.channels.Length); for (int i = 0; i < mesh.m_Shapes.channels.Length; i++)
morph.KeyframeList = new List<ImportedMorphKeyframe>(mesh.m_Shapes.shapes.Length);
lastGroup = group;
}
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(); var channel = new ImportedMorphChannel();
keyframe.Name = BlendShapeNameExtension(mesh, i) + "_" + frameIdx; morph.Channels.Add(channel);
int shapeIdx = mesh.m_Shapes.channels[i].frameIndex + frameIdx; var shapeChannel = mesh.m_Shapes.channels[i];
keyframe.VertexList = new List<ImportedVertex>((int)mesh.m_Shapes.shapes[shapeIdx].vertexCount); channel.Name = shapeChannel.name;
keyframe.MorphedVertexIndices = new List<ushort>((int)mesh.m_Shapes.shapes[shapeIdx].vertexCount); channel.KeyframeList = new List<ImportedMorphKeyframe>(shapeChannel.frameCount);
keyframe.Weight = shapeIdx < mesh.m_Shapes.fullWeights.Length ? mesh.m_Shapes.fullWeights[shapeIdx] : 100f; var frameEnd = shapeChannel.frameIndex + shapeChannel.frameCount;
int lastVertIndex = (int)(mesh.m_Shapes.shapes[shapeIdx].firstVertex + mesh.m_Shapes.shapes[shapeIdx].vertexCount); for (int frameIdx = shapeChannel.frameIndex; frameIdx < frameEnd; frameIdx++)
for (int j = (int)mesh.m_Shapes.shapes[shapeIdx].firstVertex; j < lastVertIndex; j++)
{ {
var morphVert = mesh.m_Shapes.vertices[j]; var keyframe = new ImportedMorphKeyframe();
ImportedVertex vert = GetSourceVertex(iMesh.SubmeshList, (int)morphVert.index); channel.KeyframeList.Add(keyframe);
ImportedVertex destVert = new ImportedVertex(); keyframe.Weight = mesh.m_Shapes.fullWeights[frameIdx];
Vector3 morphPos = morphVert.vertex; var shape = mesh.m_Shapes.shapes[frameIdx];
morphPos.X *= -1; keyframe.hasNormals = shape.hasNormals;
destVert.Position = vert.Position + morphPos; keyframe.hasTangents = shape.hasTangents;
Vector3 morphNormal = morphVert.normal; keyframe.VertexList = new List<ImportedMorphVertex>((int)shape.vertexCount);
morphNormal.X *= -1; var vertexEnd = shape.firstVertex + shape.vertexCount;
destVert.Normal = morphNormal; for (uint j = shape.firstVertex; j < vertexEnd; j++)
Vector4 morphTangent = new Vector4(morphVert.tangent, 0); {
morphTangent.X *= -1; var destVertex = new ImportedMorphVertex();
destVert.Tangent = morphTangent; keyframe.VertexList.Add(destVertex);
keyframe.VertexList.Add(destVert); var morphVertex = mesh.m_Shapes.vertices[j];
keyframe.MorphedVertexIndices.Add((ushort)morphVert.index); destVertex.Index = morphVertex.index;
var sourceVertex = GetSourceVertex(iMesh.SubmeshList, (int)morphVertex.index);
destVertex.Vertex = new ImportedVertex();
var morphPos = morphVertex.vertex;
destVertex.Vertex.Position = sourceVertex.Position + new Vector3(-morphPos.X, morphPos.Y, morphPos.Z);
if (shape.hasNormals)
{
var morphNormal = morphVertex.normal;
destVertex.Vertex.Normal = new Vector3(-morphNormal.X, morphNormal.Y, morphNormal.Z);
}
if (shape.hasTangents)
{
var morphTangent = morphVertex.tangent;
destVertex.Vertex.Tangent = new Vector4(-morphTangent.X, morphTangent.Y, morphTangent.Z, 0);
} }
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);
} }
} }
} }