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++)
for each (ImportedMorph^ morph in imported->MorphList)
{
ImportedMesh^ meshList = imported->MeshList[meshIdx];
FbxNode* pBaseNode = NULL;
for (int nodeIdx = 0; nodeIdx < pMeshNodes->GetCount(); nodeIdx++)
auto frame = imported->RootFrame->FindFrameByPath(morph->Path);
if (frame != nullptr)
{
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;
}
FbxNode* pNode = (FbxNode*)frameToNode[frame];
FbxMesh* pMesh = pNode->GetMesh();
for each (ImportedMorph^ morph in imported->MorphList)
{
if (morph->Path != meshList->Path)
{
continue;
}
FbxBlendShape* lBlendShape = FbxBlendShape::Create(pScene, pNode->GetName());
pMesh->AddDeformer(lBlendShape);
int meshVertexIndex = 0;
for (int meshObjIdx = pBaseNode->GetChildCount() - meshList->SubmeshList->Count; meshObjIdx < meshList->SubmeshList->Count; meshObjIdx++)
for (int i = 0; i < morph->Channels->Count; i++)
{
List<ImportedVertex^>^ vertList = meshList->SubmeshList[meshObjIdx]->VertexList;
FbxNode* pBaseMeshNode = pBaseNode->GetChild(meshObjIdx);
FbxMesh* pBaseMesh = pBaseMeshNode->GetMesh();
int numColourSets = pBaseMesh->GetElementVertexColorCount();
auto channel = morph->Channels[i];
FbxBlendShape* lBlendShape;
FbxBlendShapeChannel* lBlendShapeChannel;
WITH_MARSHALLED_STRING
(
pShapeName,
morph->ClipName + (meshList->SubmeshList->Count > 1 ? "_" + meshObjIdx : String::Empty),
lBlendShape = FbxBlendShape::Create(pScene, pShapeName);
pChannelName,
channel->Name,
lBlendShapeChannel = FbxBlendShapeChannel::Create(pScene, pChannelName);
);
FbxProperty rootGroupProp = FbxProperty::Create(lBlendShape, FbxStringDT, "RootGroup");
pBaseMesh->AddDeformer(lBlendShape);
List<ImportedMorphKeyframe^>^ keyframes = morph->KeyframeList;
for (int i = 0; i < morph->Channels->Count; i++)
lBlendShape->AddBlendShapeChannel(lBlendShapeChannel);
for each(ImportedMorphKeyframe^ keyframe in channel->KeyframeList)
{
FbxBlendShapeChannel* lBlendShapeChannel;
if (!flatInbetween)
FbxShape* lShape = FbxShape::Create(pScene, "");
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
(
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);
auto vertex = orilVector4[j];
lVector4[j] = FbxVector4(vertex);
}
for (int frameIdx = 0; frameIdx < morph->Channels[i]->Item3; frameIdx++)
for (int j = 0; j < keyframe->VertexList->Count; j++)
{
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);
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));
}
}
}
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)
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;
string lastGroup = "";
for (int i = 0; i < mesh.m_Shapes.channels.Length; i++)
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++)
{
string group = BlendShapeNameGroup(mesh, i);
if (group != lastGroup)
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++)
{
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++)
{
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 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 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 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);
}
}
}