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 string Path { get; set; }
public string ClipName { get; set; }
public List<Tuple<float, int, int>> Channels { get; set; }
public List<ImportedMorphChannel> Channels { get; set; }
}
public class ImportedMorphChannel
{
public string Name { get; set; }
public List<ImportedMorphKeyframe> KeyframeList { get; set; }
public List<ushort> MorphedVertexIndices { get; set; }
}
public class ImportedMorphKeyframe
{
public string Name { get; set; }
public List<ImportedVertex> VertexList { get; set; }
public List<ushort> MorphedVertexIndices { get; set; }
public bool hasNormals { get; set; }
public bool hasTangents { 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

View File

@ -48,7 +48,7 @@ namespace AssetStudio {
ref class Exporter
{
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:
bool exportSkins;
@ -77,9 +77,9 @@ namespace AssetStudio {
void ExportFrame(FbxNode* pParentNode, ImportedFrame^ frame);
void ExportMesh(FbxNode* pFrameNode, ImportedMesh^ meshList);
FbxFileTexture* ExportTexture(ImportedTexture^ matTex);
void ExportAnimations(bool eulerFilter, float filterValue, bool flatInbetween);
void ExportKeyframedAnimation(ImportedKeyframedAnimation^ parser, FbxString& kTakeName, FbxAnimCurveFilterUnroll* eulerFilter, float filterPrecision, bool flatInbetween);
void ExportMorphs(bool morphMask, bool flatInbetween);
void ExportAnimations(bool eulerFilter, float filterValue);
void ExportKeyframedAnimation(ImportedKeyframedAnimation^ parser, FbxString& kTakeName, FbxAnimCurveFilterUnroll* eulerFilter, float filterPrecision);
void ExportMorphs();
};
};
}

View File

@ -2,7 +2,7 @@
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);
DirectoryInfo^ dir = file->Directory;
@ -14,8 +14,8 @@ namespace AssetStudio
Directory::SetCurrentDirectory(dir->FullName);
auto name = Path::GetFileName(path);
Exporter^ exporter = gcnew Exporter(name, imported, allFrames, allBones, skins, boneSize, scaleFactor, versionIndex, isAscii);
//TODO exporter->ExportMorphs(false, flatInbetween);
exporter->ExportAnimations(eulerFilter, filterPrecision, flatInbetween);
exporter->ExportMorphs();
exporter->ExportAnimations(eulerFilter, filterPrecision);
exporter->pExporter->Export(exporter->pScene);
delete exporter;
@ -629,7 +629,7 @@ namespace AssetStudio
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;
if (importedAnimationList == nullptr)
@ -656,11 +656,11 @@ namespace AssetStudio
{
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;
@ -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;
}
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)
{
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;
for (int meshObjIdx = pBaseNode->GetChildCount() - meshList->SubmeshList->Count; meshObjIdx < meshList->SubmeshList->Count; meshObjIdx++)
{
List<ImportedVertex^>^ vertList = meshList->SubmeshList[meshObjIdx]->VertexList;
FbxNode* pBaseMeshNode = pBaseNode->GetChild(meshObjIdx);
FbxMesh* pBaseMesh = pBaseMeshNode->GetMesh();
int numColourSets = pBaseMesh->GetElementVertexColorCount();
FbxBlendShape* lBlendShape = FbxBlendShape::Create(pScene, pNode->GetName());
pMesh->AddDeformer(lBlendShape);
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++)
{
auto channel = morph->Channels[i];
FbxBlendShapeChannel* lBlendShapeChannel;
if (!flatInbetween)
{
WITH_MARSHALLED_STRING
(
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->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);
WITH_MARSHALLED_STRING
(
pMorphShapeName,
morph->ClipName + (meshList->SubmeshList->Count > 1 ? "_" + meshObjIdx : String::Empty) + "." + keyframe->Name,
pShape = FbxShape::Create(pScene, pMorphShapeName);
);
lBlendShapeChannel->AddTargetShape(pShape, 100);
for each(ImportedMorphKeyframe^ keyframe in channel->KeyframeList)
{
FbxShape* lShape = FbxShape::Create(pScene, "");
lBlendShapeChannel->AddTargetShape(lShape, keyframe->Weight);
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);
}
auto vectorCount = pMesh->GetControlPointsCount();
FbxVector4* orilVector4 = pMesh->GetControlPoints();
lShape->InitControlPoints(vectorCount);
FbxVector4* lVector4 = lShape->GetControlPoints();
pShape->InitControlPoints(vertList->Count);
FbxVector4* pControlPoints = pShape->GetControlPoints();
for (int j = 0; j < vertList->Count; j++)
for (int j = 0; j < vectorCount; j++)
{
ImportedVertex^ vertex = vertList[j];
Vector3 coords = vertex->Position;
pControlPoints[j] = FbxVector4(coords.X, coords.Y, coords.Z, 0);
auto vertex = orilVector4[j];
lVector4[j] = FbxVector4(vertex);
}
List<unsigned short>^ meshIndices = keyframe->MorphedVertexIndices;
for (int j = 0; j < meshIndices->Count; j++)
for (int j = 0; j < keyframe->VertexList->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));
auto index = keyframe->VertexList[j]->Index;
auto coords = keyframe->VertexList[j]->Vertex->Position;
lVector4[index] = FbxVector4(coords.X, coords.Y, coords.Z, 0);
}
}
}
}
}
meshVertexIndex += meshList->SubmeshList[meshObjIdx]->VertexList->Count;
}
}
}*/
}
}

View File

@ -44,7 +44,6 @@
this.label4 = new System.Windows.Forms.Label();
this.fbxVersion = new System.Windows.Forms.ComboBox();
this.label3 = new System.Windows.Forms.Label();
this.flatInbetween = new System.Windows.Forms.CheckBox();
this.boneSize = new System.Windows.Forms.NumericUpDown();
this.label2 = new System.Windows.Forms.Label();
this.skins = new System.Windows.Forms.CheckBox();
@ -63,7 +62,7 @@
//
// 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.Size = new System.Drawing.Size(75, 21);
this.OKbutton.TabIndex = 6;
@ -74,7 +73,7 @@
// 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.Size = new System.Drawing.Size(75, 21);
this.Cancel.TabIndex = 7;
@ -170,7 +169,6 @@
this.groupBox2.Controls.Add(this.label4);
this.groupBox2.Controls.Add(this.fbxVersion);
this.groupBox2.Controls.Add(this.label3);
this.groupBox2.Controls.Add(this.flatInbetween);
this.groupBox2.Controls.Add(this.boneSize);
this.groupBox2.Controls.Add(this.label2);
this.groupBox2.Controls.Add(this.skins);
@ -181,7 +179,7 @@
this.groupBox2.Controls.Add(this.eulerFilter);
this.groupBox2.Location = new System.Drawing.Point(12, 12);
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.TabStop = false;
this.groupBox2.Text = "Fbx";
@ -221,7 +219,7 @@
this.fbxFormat.Items.AddRange(new object[] {
"Binary",
"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.Size = new System.Drawing.Size(61, 20);
this.fbxFormat.TabIndex = 18;
@ -229,7 +227,7 @@
// label4
//
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.Size = new System.Drawing.Size(59, 12);
this.label4.TabIndex = 17;
@ -246,7 +244,7 @@
"7.3",
"7.4",
"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.Size = new System.Drawing.Size(47, 20);
this.fbxVersion.TabIndex = 16;
@ -254,22 +252,12 @@
// label3
//
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.Size = new System.Drawing.Size(65, 12);
this.label3.TabIndex = 15;
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
//
this.boneSize.Location = new System.Drawing.Point(65, 128);
@ -345,6 +333,8 @@
// allFrames
//
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.Name = "allFrames";
this.allFrames.Size = new System.Drawing.Size(78, 16);
@ -370,7 +360,7 @@
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
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.groupBox1);
this.Controls.Add(this.Cancel);
@ -408,7 +398,6 @@
private System.Windows.Forms.CheckBox convertAudio;
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.GroupBox groupBox2;
private System.Windows.Forms.CheckBox flatInbetween;
private System.Windows.Forms.NumericUpDown boneSize;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.CheckBox skins;

View File

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

View File

@ -318,10 +318,9 @@ namespace AssetStudioGUI
var skins = (bool)Properties.Settings.Default["skins"];
var boneSize = (int)(decimal)Properties.Settings.Default["boneSize"];
var scaleFactor = (float)(decimal)Properties.Settings.Default["scaleFactor"];
var flatInbetween = (bool)Properties.Settings.Default["flatInbetween"];
var fbxVersion = (int)Properties.Settings.Default["fbxVersion"];
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;
}
}

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.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3")]

View File

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

View File

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

View File

@ -403,55 +403,50 @@ namespace AssetStudio
}
//Morphs
if (mesh.m_Shapes?.shapes != null)
if (mesh.m_Shapes?.channels?.Length > 0)
{
if (mesh.m_Shapes.shapes.Length > 0)
{
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();
var morph = new ImportedMorph();
MorphList.Add(morph);
morph.Path = iMesh.Path;
morph.ClipName = group;
morph.Channels = new List<Tuple<float, int, int>>(mesh.m_Shapes.channels.Length);
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++)
morph.Channels = new List<ImportedMorphChannel>(mesh.m_Shapes.channels.Length);
for (int i = 0; i < mesh.m_Shapes.channels.Length; i++)
{
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 channel = new ImportedMorphChannel();
morph.Channels.Add(channel);
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++)
{
var morphVert = mesh.m_Shapes.vertices[j];
ImportedVertex vert = GetSourceVertex(iMesh.SubmeshList, (int)morphVert.index);
ImportedVertex destVert = new ImportedVertex();
Vector3 morphPos = morphVert.vertex;
morphPos.X *= -1;
destVert.Position = vert.Position + morphPos;
Vector3 morphNormal = morphVert.normal;
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);
var keyframe = new ImportedMorphKeyframe();
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++)
{
var destVertex = new ImportedMorphVertex();
keyframe.VertexList.Add(destVertex);
var morphVertex = mesh.m_Shapes.vertices[j];
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 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);
}
}
}