mirror of
https://github.com/aelurum/AssetStudio.git
synced 2025-05-27 22:00:23 -04:00
improved model export
This commit is contained in:
parent
e001dff3de
commit
50c17c2ec4
@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
@ -29,6 +28,21 @@ namespace AssetStudio
|
|||||||
|
|
||||||
public int Count => children.Count;
|
public int Count => children.Count;
|
||||||
|
|
||||||
|
public string Path
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var frame = this;
|
||||||
|
var path = frame.Name;
|
||||||
|
while (frame.Parent != null)
|
||||||
|
{
|
||||||
|
frame = frame.Parent;
|
||||||
|
path = frame.Name + "/" + path;
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public ImportedFrame(int childrenCount = 0)
|
public ImportedFrame(int childrenCount = 0)
|
||||||
{
|
{
|
||||||
children = new List<ImportedFrame>(childrenCount);
|
children = new List<ImportedFrame>(childrenCount);
|
||||||
@ -48,19 +62,15 @@ namespace AssetStudio
|
|||||||
|
|
||||||
public ImportedFrame FindFrameByPath(string path)
|
public ImportedFrame FindFrameByPath(string path)
|
||||||
{
|
{
|
||||||
var splitPath = path.Split('/');
|
var name = path.Substring(path.LastIndexOf('/') + 1);
|
||||||
if (Name != splitPath[0])
|
foreach (var frame in FindChilds(name))
|
||||||
throw new Exception($"Couldn't find path {path}");
|
|
||||||
var curFrame = this;
|
|
||||||
for (int i = 1; i < splitPath.Length; i++)
|
|
||||||
{
|
{
|
||||||
curFrame = curFrame.FindChild(splitPath[i], false);
|
if (frame.Path.EndsWith(path, StringComparison.Ordinal))
|
||||||
if (curFrame == null)
|
|
||||||
{
|
{
|
||||||
throw new Exception($"Couldn't find path {path}");
|
return frame;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return curFrame;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ImportedFrame FindFrame(string name)
|
public ImportedFrame FindFrame(string name)
|
||||||
@ -265,27 +275,6 @@ namespace AssetStudio
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ImportedMesh FindMesh(ImportedFrame frame, List<ImportedMesh> importedMeshList)
|
|
||||||
{
|
|
||||||
var framePath = frame.Name;
|
|
||||||
var root = frame;
|
|
||||||
while (root.Parent != null)
|
|
||||||
{
|
|
||||||
root = root.Parent;
|
|
||||||
framePath = root.Name + "/" + framePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var mesh in importedMeshList)
|
|
||||||
{
|
|
||||||
if (mesh.Path == framePath)
|
|
||||||
{
|
|
||||||
return mesh;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ImportedMaterial FindMaterial(string name, List<ImportedMaterial> importedMats)
|
public static ImportedMaterial FindMaterial(string name, List<ImportedMaterial> importedMats)
|
||||||
{
|
{
|
||||||
foreach (var mat in importedMats)
|
foreach (var mat in importedMats)
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
#include <fbxsdk.h>
|
|
||||||
#include <fbxsdk/fileio/fbxiosettings.h>
|
|
||||||
#include "AssetStudioFBX.h"
|
#include "AssetStudioFBX.h"
|
||||||
|
|
||||||
namespace AssetStudio
|
namespace AssetStudio
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <fbxsdk.h>
|
||||||
|
|
||||||
#ifdef IOS_REF
|
#ifdef IOS_REF
|
||||||
#undef IOS_REF
|
#undef IOS_REF
|
||||||
#define IOS_REF (*(pSdkManager->GetIOSettings()))
|
#define IOS_REF (*(pSdkManager->GetIOSettings()))
|
||||||
@ -48,14 +50,14 @@ namespace AssetStudio {
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static void 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);
|
static void 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);
|
||||||
static void ExportMorph(String^ path, IImported^ imported, bool morphMask, bool flatInbetween, bool skins, float boneSize, float scaleFactor, int versionIndex, bool isAscii);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HashSet<String^>^ frameNames;
|
|
||||||
bool exportSkins;
|
bool exportSkins;
|
||||||
float boneSize;
|
float boneSize;
|
||||||
|
|
||||||
IImported^ imported;
|
IImported^ imported;
|
||||||
|
HashSet<String^>^ framePaths;
|
||||||
|
Dictionary<ImportedFrame^, size_t>^ frameToNode;
|
||||||
|
List<ImportedFrame^>^ meshFrames;
|
||||||
|
|
||||||
char* cDest;
|
char* cDest;
|
||||||
FbxManager* pSdkManager;
|
FbxManager* pSdkManager;
|
||||||
@ -63,24 +65,22 @@ namespace AssetStudio {
|
|||||||
FbxExporter* pExporter;
|
FbxExporter* pExporter;
|
||||||
FbxArray<FbxSurfacePhong*>* pMaterials;
|
FbxArray<FbxSurfacePhong*>* pMaterials;
|
||||||
FbxArray<FbxFileTexture*>* pTextures;
|
FbxArray<FbxFileTexture*>* pTextures;
|
||||||
FbxArray<FbxNode*>* pMeshNodes;
|
|
||||||
FbxPose* pBindPose;
|
FbxPose* pBindPose;
|
||||||
|
|
||||||
Exporter(String^ path, IImported^ imported, bool allFrames, bool allBones, bool skins, float boneSize, float scaleFactor, int versionIndex, bool isAscii, bool normals);
|
Exporter(String^ path, IImported^ imported, bool allFrames, bool allBones, bool skins, float boneSize, float scaleFactor, int versionIndex, bool isAscii);
|
||||||
~Exporter();
|
~Exporter();
|
||||||
|
|
||||||
void Exporter::LinkTexture(ImportedMaterialTexture^ texture, FbxFileTexture* pTexture, FbxProperty& prop);
|
void Exporter::LinkTexture(ImportedMaterialTexture^ texture, FbxFileTexture* pTexture, FbxProperty& prop);
|
||||||
void SetJointsNode(FbxNode* pNode, HashSet<String^>^ boneNames, bool allBones);
|
void SetJointsNode(ImportedFrame^ frame, HashSet<String^>^ bonePaths, bool allBones);
|
||||||
HashSet<String^>^ SearchHierarchy();
|
HashSet<String^>^ SearchHierarchy();
|
||||||
void SearchHierarchy(ImportedFrame^ frame, HashSet<String^>^ exportFrames);
|
void SearchHierarchy(ImportedFrame^ frame, HashSet<String^>^ exportFrames);
|
||||||
void SetJointsFromImportedMeshes(bool allBones);
|
void SetJointsFromImportedMeshes(bool allBones);
|
||||||
void ExportFrame(FbxNode* pParentNode, ImportedFrame^ frame);
|
void ExportFrame(FbxNode* pParentNode, ImportedFrame^ frame);
|
||||||
void ExportMesh(FbxNode* pFrameNode, ImportedMesh^ meshList, bool normals);
|
void ExportMesh(FbxNode* pFrameNode, ImportedMesh^ meshList);
|
||||||
FbxNode* FindNodeByPath(String ^ path);
|
|
||||||
FbxFileTexture* ExportTexture(ImportedTexture^ matTex);
|
FbxFileTexture* ExportTexture(ImportedTexture^ matTex);
|
||||||
void ExportAnimations(bool eulerFilter, float filterValue, bool flatInbetween);
|
void ExportAnimations(bool eulerFilter, float filterValue, bool flatInbetween);
|
||||||
void ExportKeyframedAnimation(ImportedKeyframedAnimation^ parser, FbxString& kTakeName, FbxAnimCurveFilterUnroll* eulerFilter, float filterPrecision, bool flatInbetween);
|
void ExportKeyframedAnimation(ImportedKeyframedAnimation^ parser, FbxString& kTakeName, FbxAnimCurveFilterUnroll* eulerFilter, float filterPrecision, bool flatInbetween);
|
||||||
void ExportMorphs(IImported^ imported, bool morphMask, bool flatInbetween);
|
void ExportMorphs(bool morphMask, bool flatInbetween);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
#include <fbxsdk.h>
|
|
||||||
#include <fbxsdk/fileio/fbxiosettings.h>
|
|
||||||
#include "AssetStudioFBX.h"
|
#include "AssetStudioFBX.h"
|
||||||
|
|
||||||
namespace AssetStudio
|
namespace AssetStudio
|
||||||
@ -16,8 +14,8 @@ namespace AssetStudio
|
|||||||
Directory::SetCurrentDirectory(dir->FullName);
|
Directory::SetCurrentDirectory(dir->FullName);
|
||||||
path = Path::GetFileName(path);
|
path = Path::GetFileName(path);
|
||||||
|
|
||||||
Exporter^ exporter = gcnew Exporter(path, imported, allFrames, allBones, skins, boneSize, scaleFactor, versionIndex, isAscii, true);
|
Exporter^ exporter = gcnew Exporter(path, imported, allFrames, allBones, skins, boneSize, scaleFactor, versionIndex, isAscii);
|
||||||
exporter->ExportMorphs(imported, false, flatInbetween);
|
//TODO exporter->ExportMorphs(false, flatInbetween);
|
||||||
exporter->ExportAnimations(eulerFilter, filterPrecision, flatInbetween);
|
exporter->ExportAnimations(eulerFilter, filterPrecision, flatInbetween);
|
||||||
exporter->pExporter->Export(exporter->pScene);
|
exporter->pExporter->Export(exporter->pScene);
|
||||||
delete exporter;
|
delete exporter;
|
||||||
@ -25,27 +23,7 @@ namespace AssetStudio
|
|||||||
Directory::SetCurrentDirectory(currentDir);
|
Directory::SetCurrentDirectory(currentDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fbx::Exporter::ExportMorph(String^ path, IImported^ imported, bool morphMask, bool flatInbetween, bool skins, float boneSize, float scaleFactor, int versionIndex, bool isAscii)
|
Fbx::Exporter::Exporter(String^ path, IImported^ imported, bool allFrames, bool allBones, bool skins, float boneSize, float scaleFactor, int versionIndex, bool isAscii)
|
||||||
{
|
|
||||||
FileInfo^ file = gcnew FileInfo(path);
|
|
||||||
DirectoryInfo^ dir = file->Directory;
|
|
||||||
if (!dir->Exists)
|
|
||||||
{
|
|
||||||
dir->Create();
|
|
||||||
}
|
|
||||||
String^ currentDir = Directory::GetCurrentDirectory();
|
|
||||||
Directory::SetCurrentDirectory(dir->FullName);
|
|
||||||
path = Path::GetFileName(path);
|
|
||||||
|
|
||||||
Exporter^ exporter = gcnew Exporter(path, imported, false, true, skins, boneSize, scaleFactor, versionIndex, isAscii, false);
|
|
||||||
exporter->ExportMorphs(imported, morphMask, flatInbetween);
|
|
||||||
exporter->pExporter->Export(exporter->pScene);
|
|
||||||
delete exporter;
|
|
||||||
|
|
||||||
Directory::SetCurrentDirectory(currentDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
Fbx::Exporter::Exporter(String^ path, IImported^ imported, bool allFrames, bool allBones, bool skins, float boneSize, float scaleFactor, int versionIndex, bool isAscii, bool normals)
|
|
||||||
{
|
{
|
||||||
this->imported = imported;
|
this->imported = imported;
|
||||||
exportSkins = skins;
|
exportSkins = skins;
|
||||||
@ -57,7 +35,6 @@ namespace AssetStudio
|
|||||||
pExporter = NULL;
|
pExporter = NULL;
|
||||||
pMaterials = NULL;
|
pMaterials = NULL;
|
||||||
pTextures = NULL;
|
pTextures = NULL;
|
||||||
pMeshNodes = NULL;
|
|
||||||
|
|
||||||
pin_ptr<FbxManager*> pSdkManagerPin = &pSdkManager;
|
pin_ptr<FbxManager*> pSdkManagerPin = &pSdkManager;
|
||||||
pin_ptr<FbxScene*> pScenePin = &pScene;
|
pin_ptr<FbxScene*> pScenePin = &pScene;
|
||||||
@ -100,19 +77,21 @@ namespace AssetStudio
|
|||||||
throw gcnew Exception(gcnew String("Failed to initialize FbxExporter: ") + gcnew String(pExporter->GetStatus().GetErrorString()));
|
throw gcnew Exception(gcnew String("Failed to initialize FbxExporter: ") + gcnew String(pExporter->GetStatus().GetErrorString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
frameNames = nullptr;
|
framePaths = nullptr;
|
||||||
if (!allFrames)
|
if (!allFrames)
|
||||||
{
|
{
|
||||||
frameNames = SearchHierarchy();
|
framePaths = SearchHierarchy();
|
||||||
if (!frameNames)
|
if (!framePaths)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pMeshNodes = imported->MeshList != nullptr ? new FbxArray<FbxNode*>(imported->MeshList->Count) : NULL;
|
|
||||||
pBindPose = FbxPose::Create(pScene, "BindPose");
|
pBindPose = FbxPose::Create(pScene, "BindPose");
|
||||||
pBindPose->SetIsBindPose(true);
|
pBindPose->SetIsBindPose(true);
|
||||||
|
|
||||||
|
frameToNode = gcnew Dictionary<ImportedFrame^, size_t>();
|
||||||
|
meshFrames = imported->MeshList != nullptr ? gcnew List<ImportedFrame^>() : nullptr;
|
||||||
ExportFrame(pScene->GetRootNode(), imported->RootFrame);
|
ExportFrame(pScene->GetRootNode(), imported->RootFrame);
|
||||||
|
|
||||||
if (imported->MeshList != nullptr)
|
if (imported->MeshList != nullptr)
|
||||||
@ -124,31 +103,36 @@ namespace AssetStudio
|
|||||||
pMaterials->Reserve(imported->MaterialList->Count);
|
pMaterials->Reserve(imported->MaterialList->Count);
|
||||||
pTextures->Reserve(imported->TextureList->Count);
|
pTextures->Reserve(imported->TextureList->Count);
|
||||||
|
|
||||||
for (int i = 0; i < pMeshNodes->GetCount(); i++)
|
for (int i = 0; i < meshFrames->Count; i++)
|
||||||
{
|
{
|
||||||
FbxNode* meshNode = pMeshNodes->GetAt(i);
|
auto meshFram = meshFrames[i];
|
||||||
String^ meshPath = gcnew String(meshNode->GetName());
|
FbxNode* meshNode = (FbxNode*)frameToNode[meshFram];
|
||||||
FbxNode* rootNode = meshNode;
|
ImportedMesh^ mesh = ImportedHelpers::FindMesh(meshFram->Path, imported->MeshList);
|
||||||
while ((rootNode = rootNode->GetParent()) != pScene->GetRootNode())
|
ExportMesh(meshNode, mesh);
|
||||||
{
|
|
||||||
meshPath = gcnew String(rootNode->GetName()) + "/" + meshPath;
|
|
||||||
}
|
|
||||||
ImportedMesh^ mesh = ImportedHelpers::FindMesh(meshPath, imported->MeshList);
|
|
||||||
ExportMesh(meshNode, mesh, normals);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SetJointsNode(pScene->GetRootNode()->GetChild(0), nullptr, true);
|
SetJointsNode(imported->RootFrame, nullptr, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Fbx::Exporter::~Exporter()
|
Fbx::Exporter::~Exporter()
|
||||||
{
|
{
|
||||||
if (pMeshNodes != NULL)
|
imported = nullptr;
|
||||||
|
if (framePaths != nullptr)
|
||||||
{
|
{
|
||||||
delete pMeshNodes;
|
framePaths->Clear();
|
||||||
}
|
}
|
||||||
|
if (frameToNode != nullptr)
|
||||||
|
{
|
||||||
|
frameToNode->Clear();
|
||||||
|
}
|
||||||
|
if (meshFrames != nullptr)
|
||||||
|
{
|
||||||
|
meshFrames->Clear();
|
||||||
|
}
|
||||||
|
|
||||||
if (pMaterials != NULL)
|
if (pMaterials != NULL)
|
||||||
{
|
{
|
||||||
delete pMaterials;
|
delete pMaterials;
|
||||||
@ -175,30 +159,33 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fbx::Exporter::SetJointsNode(FbxNode* pNode, HashSet<String^>^ boneNames, bool allBones)
|
void Fbx::Exporter::SetJointsNode(ImportedFrame^ frame, HashSet<String^>^ bonePaths, bool allBones)
|
||||||
{
|
{
|
||||||
String^ nodeName = gcnew String(pNode->GetName());
|
size_t pointer;
|
||||||
if (allBones || boneNames->Contains(nodeName))
|
if (frameToNode->TryGetValue(frame, pointer))
|
||||||
{
|
{
|
||||||
FbxSkeleton* pJoint = FbxSkeleton::Create(pSdkManager, "");
|
auto pNode = (FbxNode*)pointer;
|
||||||
pJoint->Size.Set((double)boneSize);
|
if (allBones || bonePaths->Contains(frame->Path))
|
||||||
pJoint->SetSkeletonType(FbxSkeleton::eLimbNode);
|
|
||||||
pNode->SetNodeAttribute(pJoint);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FbxNull* pNull = FbxNull::Create(pSdkManager, "");
|
|
||||||
if (pNode->GetChildCount() > 0)
|
|
||||||
{
|
{
|
||||||
pNull->Look.Set(FbxNull::eNone);
|
FbxSkeleton* pJoint = FbxSkeleton::Create(pScene, "");
|
||||||
|
pJoint->Size.Set(FbxDouble(boneSize));
|
||||||
|
pJoint->SetSkeletonType(FbxSkeleton::eLimbNode);
|
||||||
|
pNode->SetNodeAttribute(pJoint);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FbxNull* pNull = FbxNull::Create(pScene, "");
|
||||||
|
if (pNode->GetChildCount() > 0)
|
||||||
|
{
|
||||||
|
pNull->Look.Set(FbxNull::eNone);
|
||||||
|
}
|
||||||
|
|
||||||
pNode->SetNodeAttribute(pNull);
|
pNode->SetNodeAttribute(pNull);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
for (int i = 0; i < frame->Count; i++)
|
||||||
for (int i = 0; i < pNode->GetChildCount(); i++)
|
|
||||||
{
|
{
|
||||||
SetJointsNode(pNode->GetChild(i), boneNames, allBones);
|
SetJointsNode(frame[i], bonePaths, allBones);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,13 +202,13 @@ namespace AssetStudio
|
|||||||
|
|
||||||
void Fbx::Exporter::SearchHierarchy(ImportedFrame^ frame, HashSet<String^>^ exportFrames)
|
void Fbx::Exporter::SearchHierarchy(ImportedFrame^ frame, HashSet<String^>^ exportFrames)
|
||||||
{
|
{
|
||||||
ImportedMesh^ meshListSome = ImportedHelpers::FindMesh(frame, imported->MeshList);
|
ImportedMesh^ meshListSome = ImportedHelpers::FindMesh(frame->Path, imported->MeshList);
|
||||||
if (meshListSome != nullptr)
|
if (meshListSome != nullptr)
|
||||||
{
|
{
|
||||||
ImportedFrame^ parent = frame;
|
ImportedFrame^ parent = frame;
|
||||||
while (parent != nullptr)
|
while (parent != nullptr)
|
||||||
{
|
{
|
||||||
exportFrames->Add(parent->Name);
|
exportFrames->Add(parent->Path);
|
||||||
parent = parent->Parent;
|
parent = parent->Parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,13 +217,12 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
for (int i = 0; i < boneList->Count; i++)
|
for (int i = 0; i < boneList->Count; i++)
|
||||||
{
|
{
|
||||||
String^ boneName = boneList[i]->Path->Substring(boneList[i]->Path->LastIndexOf('/') + 1);
|
if (!exportFrames->Contains(boneList[i]->Path))
|
||||||
if (!exportFrames->Contains(boneName))
|
|
||||||
{
|
{
|
||||||
ImportedFrame^ boneParent = imported->RootFrame->FindFrameByPath(boneList[i]->Path);
|
ImportedFrame^ boneParent = imported->RootFrame->FindFrameByPath(boneList[i]->Path);
|
||||||
while (boneParent != nullptr)
|
while (boneParent != nullptr)
|
||||||
{
|
{
|
||||||
exportFrames->Add(boneParent->Name);
|
exportFrames->Add(boneParent->Path);
|
||||||
boneParent = boneParent->Parent;
|
boneParent = boneParent->Parent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -256,7 +242,7 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
HashSet<String^>^ boneNames = gcnew HashSet<String^>();
|
HashSet<String^>^ bonePaths = gcnew HashSet<String^>();
|
||||||
for (int i = 0; i < imported->MeshList->Count; i++)
|
for (int i = 0; i < imported->MeshList->Count; i++)
|
||||||
{
|
{
|
||||||
ImportedMesh^ meshList = imported->MeshList[i];
|
ImportedMesh^ meshList = imported->MeshList[i];
|
||||||
@ -266,24 +252,23 @@ namespace AssetStudio
|
|||||||
for (int j = 0; j < boneList->Count; j++)
|
for (int j = 0; j < boneList->Count; j++)
|
||||||
{
|
{
|
||||||
ImportedBone^ bone = boneList[j];
|
ImportedBone^ bone = boneList[j];
|
||||||
boneNames->Add(bone->Path);
|
bonePaths->Add(bone->Path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SetJointsNode(pScene->GetRootNode()->GetChild(0), boneNames, allBones);
|
SetJointsNode(imported->RootFrame, bonePaths, allBones);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fbx::Exporter::ExportFrame(FbxNode* pParentNode, ImportedFrame^ frame)
|
void Fbx::Exporter::ExportFrame(FbxNode* pParentNode, ImportedFrame^ frame)
|
||||||
{
|
{
|
||||||
String^ frameName = frame->Name;
|
if (framePaths == nullptr || framePaths->Contains(frame->Path))
|
||||||
if ((frameNames == nullptr) || frameNames->Contains(frameName))
|
|
||||||
{
|
{
|
||||||
FbxNode* pFrameNode = NULL;
|
FbxNode* pFrameNode;
|
||||||
WITH_MARSHALLED_STRING
|
WITH_MARSHALLED_STRING
|
||||||
(
|
(
|
||||||
pName,
|
pName,
|
||||||
frameName,
|
frame->Name,
|
||||||
pFrameNode = FbxNode::Create(pScene, pName);
|
pFrameNode = FbxNode::Create(pScene, pName);
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -294,11 +279,13 @@ namespace AssetStudio
|
|||||||
pParentNode->AddChild(pFrameNode);
|
pParentNode->AddChild(pFrameNode);
|
||||||
pBindPose->Add(pFrameNode, pFrameNode->EvaluateGlobalTransform());
|
pBindPose->Add(pFrameNode, pFrameNode->EvaluateGlobalTransform());
|
||||||
|
|
||||||
if (imported->MeshList != nullptr && ImportedHelpers::FindMesh(frame, imported->MeshList) != nullptr)
|
if (imported->MeshList != nullptr && ImportedHelpers::FindMesh(frame->Path, imported->MeshList) != nullptr)
|
||||||
{
|
{
|
||||||
pMeshNodes->Add(pFrameNode);
|
meshFrames->Add(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
frameToNode->Add(frame, (size_t)pFrameNode);
|
||||||
|
|
||||||
for (int i = 0; i < frame->Count; i++)
|
for (int i = 0; i < frame->Count; i++)
|
||||||
{
|
{
|
||||||
ExportFrame(pFrameNode, frame[i]);
|
ExportFrame(pFrameNode, frame[i]);
|
||||||
@ -306,10 +293,8 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fbx::Exporter::ExportMesh(FbxNode* pFrameNode, ImportedMesh^ meshList, bool normals)
|
void Fbx::Exporter::ExportMesh(FbxNode* pFrameNode, ImportedMesh^ meshList)
|
||||||
{
|
{
|
||||||
int lastSlash = meshList->Path->LastIndexOf('/');
|
|
||||||
String^ frameName = lastSlash < 0 ? meshList->Path : meshList->Path->Substring(lastSlash + 1);
|
|
||||||
List<ImportedBone^>^ boneList = meshList->BoneList;
|
List<ImportedBone^>^ boneList = meshList->BoneList;
|
||||||
bool hasBones;
|
bool hasBones;
|
||||||
if (exportSkins && boneList != nullptr)
|
if (exportSkins && boneList != nullptr)
|
||||||
@ -321,7 +306,9 @@ namespace AssetStudio
|
|||||||
hasBones = false;
|
hasBones = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FbxArray<FbxNode*>* pBoneNodeList = NULL;
|
FbxArray<FbxNode*>* pBoneNodeList = nullptr;
|
||||||
|
FbxArray<FbxCluster*>* pClusterArray = nullptr;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (hasBones)
|
if (hasBones)
|
||||||
@ -330,280 +317,242 @@ namespace AssetStudio
|
|||||||
pBoneNodeList->Reserve(boneList->Count);
|
pBoneNodeList->Reserve(boneList->Count);
|
||||||
for (int i = 0; i < boneList->Count; i++)
|
for (int i = 0; i < boneList->Count; i++)
|
||||||
{
|
{
|
||||||
ImportedBone^ bone = boneList[i];
|
auto bone = boneList[i];
|
||||||
FbxNode* lFrame = FindNodeByPath(bone->Path);
|
auto frame = imported->RootFrame->FindFrameByPath(bone->Path);
|
||||||
pBoneNodeList->Add(lFrame);
|
auto frameNode = (FbxNode*)frameToNode[frame];
|
||||||
|
pBoneNodeList->Add(frameNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
pClusterArray = new FbxArray<FbxCluster*>();
|
||||||
|
pClusterArray->Reserve(boneList->Count);
|
||||||
|
for (int i = 0; i < boneList->Count; i++)
|
||||||
|
{
|
||||||
|
FbxNode* pNode = pBoneNodeList->GetAt(i);
|
||||||
|
FbxString lClusterName = pNode->GetNameOnly() + FbxString("Cluster");
|
||||||
|
FbxCluster* pCluster = FbxCluster::Create(pScene, lClusterName.Buffer());
|
||||||
|
pCluster->SetLink(pNode);
|
||||||
|
pCluster->SetLinkMode(FbxCluster::eTotalOne);
|
||||||
|
pClusterArray->Add(pCluster);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FbxMesh* pMesh = FbxMesh::Create(pScene, "");
|
||||||
|
pFrameNode->SetNodeAttribute(pMesh);
|
||||||
|
|
||||||
|
int vertexCount = 0;
|
||||||
for (int i = 0; i < meshList->SubmeshList->Count; i++)
|
for (int i = 0; i < meshList->SubmeshList->Count; i++)
|
||||||
{
|
{
|
||||||
char* pName = NULL;
|
vertexCount += meshList->SubmeshList[i]->VertexList->Count;
|
||||||
FbxArray<FbxCluster*>* pClusterArray = NULL;
|
}
|
||||||
try
|
|
||||||
|
pMesh->InitControlPoints(vertexCount);
|
||||||
|
FbxVector4* pControlPoints = pMesh->GetControlPoints();
|
||||||
|
|
||||||
|
FbxGeometryElementNormal* lGeometryElementNormal = pMesh->CreateElementNormal();
|
||||||
|
lGeometryElementNormal->SetMappingMode(FbxGeometryElement::eByControlPoint);
|
||||||
|
lGeometryElementNormal->SetReferenceMode(FbxGeometryElement::eDirect);
|
||||||
|
|
||||||
|
FbxGeometryElementUV* lGeometryElementUV = pMesh->CreateElementUV("UV0");
|
||||||
|
lGeometryElementUV->SetMappingMode(FbxGeometryElement::eByControlPoint);
|
||||||
|
lGeometryElementUV->SetReferenceMode(FbxGeometryElement::eDirect);
|
||||||
|
|
||||||
|
FbxGeometryElementTangent* lGeometryElementTangent = pMesh->CreateElementTangent();
|
||||||
|
lGeometryElementTangent->SetMappingMode(FbxGeometryElement::eByControlPoint);
|
||||||
|
lGeometryElementTangent->SetReferenceMode(FbxGeometryElement::eDirect);
|
||||||
|
|
||||||
|
FbxGeometryElementVertexColor* lGeometryElementVertexColor = nullptr;
|
||||||
|
bool vertexColours = vertexCount > 0 && dynamic_cast<ImportedVertexWithColour^>(meshList->SubmeshList[0]->VertexList[0]) != nullptr;
|
||||||
|
if (vertexColours)
|
||||||
|
{
|
||||||
|
lGeometryElementVertexColor = pMesh->CreateElementVertexColor();
|
||||||
|
lGeometryElementVertexColor->SetMappingMode(FbxGeometryElement::eByControlPoint);
|
||||||
|
lGeometryElementVertexColor->SetReferenceMode(FbxGeometryElement::eDirect);
|
||||||
|
}
|
||||||
|
|
||||||
|
FbxGeometryElementMaterial* lGeometryElementMaterial = pMesh->CreateElementMaterial();
|
||||||
|
lGeometryElementMaterial->SetMappingMode(FbxGeometryElement::eByPolygon);
|
||||||
|
lGeometryElementMaterial->SetReferenceMode(FbxGeometryElement::eIndexToDirect);
|
||||||
|
|
||||||
|
int firstVertex = 0;
|
||||||
|
for (int i = 0; i < meshList->SubmeshList->Count; i++)
|
||||||
|
{
|
||||||
|
ImportedSubmesh^ meshObj = meshList->SubmeshList[i];
|
||||||
|
List<ImportedVertex^>^ vertexList = meshObj->VertexList;
|
||||||
|
List<ImportedFace^>^ faceList = meshObj->FaceList;
|
||||||
|
|
||||||
|
int materialIndex = 0;
|
||||||
|
ImportedMaterial^ mat = ImportedHelpers::FindMaterial(meshObj->Material, imported->MaterialList);
|
||||||
|
if (mat != nullptr)
|
||||||
{
|
{
|
||||||
pName = StringToCharArray(frameName + "_" + i);
|
char* pMatName = NULL;
|
||||||
FbxMesh* pMesh = FbxMesh::Create(pScene, "");
|
try
|
||||||
|
|
||||||
if (hasBones)
|
|
||||||
{
|
{
|
||||||
pClusterArray = new FbxArray<FbxCluster*>();
|
pMatName = StringToCharArray(mat->Name);
|
||||||
pClusterArray->Reserve(boneList->Count);
|
int foundMat = -1;
|
||||||
|
for (int j = 0; j < pMaterials->GetCount(); j++)
|
||||||
for (int i = 0; i < boneList->Count; i++)
|
|
||||||
{
|
{
|
||||||
FbxNode* pNode = pBoneNodeList->GetAt(i);
|
FbxSurfacePhong* pMatTemp = pMaterials->GetAt(j);
|
||||||
FbxString lClusterName = pNode->GetNameOnly() + FbxString("Cluster");
|
if (strcmp(pMatTemp->GetName(), pMatName) == 0)
|
||||||
FbxCluster* pCluster = FbxCluster::Create(pSdkManager, lClusterName.Buffer());
|
{
|
||||||
pCluster->SetLink(pNode);
|
foundMat = j;
|
||||||
pCluster->SetLinkMode(FbxCluster::eTotalOne);
|
break;
|
||||||
pClusterArray->Add(pCluster);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FbxSurfacePhong* pMat;
|
||||||
|
if (foundMat >= 0)
|
||||||
|
{
|
||||||
|
pMat = pMaterials->GetAt(foundMat);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FbxString lShadingName = "Phong";
|
||||||
|
Color diffuse = mat->Diffuse;
|
||||||
|
Color ambient = mat->Ambient;
|
||||||
|
Color emissive = mat->Emissive;
|
||||||
|
Color specular = mat->Specular;
|
||||||
|
Color reflection = mat->Reflection;
|
||||||
|
pMat = FbxSurfacePhong::Create(pScene, pMatName);
|
||||||
|
pMat->Diffuse.Set(FbxDouble3(diffuse.R, diffuse.G, diffuse.B));
|
||||||
|
pMat->DiffuseFactor.Set(FbxDouble(diffuse.A));
|
||||||
|
pMat->Ambient.Set(FbxDouble3(ambient.R, ambient.G, ambient.B));
|
||||||
|
pMat->AmbientFactor.Set(FbxDouble(ambient.A));
|
||||||
|
pMat->Emissive.Set(FbxDouble3(emissive.R, emissive.G, emissive.B));
|
||||||
|
pMat->EmissiveFactor.Set(FbxDouble(emissive.A));
|
||||||
|
pMat->Specular.Set(FbxDouble3(specular.R, specular.G, specular.B));
|
||||||
|
pMat->SpecularFactor.Set(FbxDouble(specular.A));
|
||||||
|
pMat->Reflection.Set(FbxDouble3(reflection.R, reflection.G, reflection.B));
|
||||||
|
pMat->ReflectionFactor.Set(FbxDouble(reflection.A));
|
||||||
|
pMat->Shininess.Set(FbxDouble(mat->Shininess));
|
||||||
|
pMat->TransparencyFactor.Set(FbxDouble(mat->Transparency));
|
||||||
|
pMat->ShadingModel.Set(lShadingName);
|
||||||
|
pMaterials->Add(pMat);
|
||||||
|
}
|
||||||
|
materialIndex = pFrameNode->AddMaterial(pMat);
|
||||||
|
|
||||||
|
bool hasTexture = false;
|
||||||
|
|
||||||
|
for each (ImportedMaterialTexture^ texture in mat->Textures)
|
||||||
|
{
|
||||||
|
auto pTexture = ExportTexture(ImportedHelpers::FindTexture(texture->Name, imported->TextureList));
|
||||||
|
if (pTexture != NULL)
|
||||||
|
{
|
||||||
|
if (texture->Dest == 0)
|
||||||
|
{
|
||||||
|
LinkTexture(texture, pTexture, pMat->Diffuse);
|
||||||
|
hasTexture = true;
|
||||||
|
}
|
||||||
|
else if (texture->Dest == 1)
|
||||||
|
{
|
||||||
|
LinkTexture(texture, pTexture, pMat->NormalMap);
|
||||||
|
hasTexture = true;
|
||||||
|
}
|
||||||
|
else if (texture->Dest == 2)
|
||||||
|
{
|
||||||
|
LinkTexture(texture, pTexture, pMat->Specular);
|
||||||
|
hasTexture = true;
|
||||||
|
}
|
||||||
|
else if (texture->Dest == 3)
|
||||||
|
{
|
||||||
|
LinkTexture(texture, pTexture, pMat->Bump);
|
||||||
|
hasTexture = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasTexture)
|
||||||
|
{
|
||||||
|
pFrameNode->SetShadingMode(FbxNode::eTextureShading);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
ImportedSubmesh^ meshObj = meshList->SubmeshList[i];
|
|
||||||
List<ImportedFace^>^ faceList = meshObj->FaceList;
|
|
||||||
List<ImportedVertex^>^ vertexList = meshObj->VertexList;
|
|
||||||
|
|
||||||
pMesh->InitControlPoints(vertexList->Count);
|
|
||||||
FbxVector4* pControlPoints = pMesh->GetControlPoints();
|
|
||||||
|
|
||||||
FbxGeometryElementNormal* lGeometryElementNormal = NULL;
|
|
||||||
//if (normals)
|
|
||||||
{
|
{
|
||||||
lGeometryElementNormal = pMesh->GetElementNormal();
|
Marshal::FreeHGlobal((IntPtr)pMatName);
|
||||||
if (!lGeometryElementNormal)
|
}
|
||||||
{
|
}
|
||||||
lGeometryElementNormal = pMesh->CreateElementNormal();
|
|
||||||
}
|
for (int j = 0; j < vertexList->Count; j++)
|
||||||
lGeometryElementNormal->SetMappingMode(FbxGeometryElement::eByControlPoint);
|
{
|
||||||
lGeometryElementNormal->SetReferenceMode(FbxGeometryElement::eDirect);
|
ImportedVertex^ vertex = vertexList[j];
|
||||||
|
|
||||||
|
Vector3 coords = vertex->Position;
|
||||||
|
pControlPoints[j + firstVertex] = FbxVector4(coords.X, coords.Y, coords.Z, 0);
|
||||||
|
|
||||||
|
Vector3 normal = vertex->Normal;
|
||||||
|
lGeometryElementNormal->GetDirectArray().Add(FbxVector4(normal.X, normal.Y, normal.Z, 0));
|
||||||
|
|
||||||
|
array<float>^ uv = vertex->UV;
|
||||||
|
if (uv != nullptr)
|
||||||
|
{
|
||||||
|
lGeometryElementUV->GetDirectArray().Add(FbxVector2(uv[0], uv[1]));
|
||||||
}
|
}
|
||||||
|
|
||||||
FbxGeometryElementUV* lGeometryElementUV = pMesh->GetElementUV();
|
Vector4 tangent = vertex->Tangent;
|
||||||
if (!lGeometryElementUV)
|
lGeometryElementTangent->GetDirectArray().Add(FbxVector4(tangent.X, tangent.Y, tangent.Z, tangent.W));
|
||||||
{
|
|
||||||
lGeometryElementUV = pMesh->CreateElementUV("");
|
|
||||||
}
|
|
||||||
lGeometryElementUV->SetMappingMode(FbxGeometryElement::eByControlPoint);
|
|
||||||
lGeometryElementUV->SetReferenceMode(FbxGeometryElement::eDirect);
|
|
||||||
|
|
||||||
FbxGeometryElementTangent* lGeometryElementTangent = NULL;
|
|
||||||
if (normals)
|
|
||||||
{
|
|
||||||
lGeometryElementTangent = pMesh->GetElementTangent();
|
|
||||||
if (!lGeometryElementTangent)
|
|
||||||
{
|
|
||||||
lGeometryElementTangent = pMesh->CreateElementTangent();
|
|
||||||
}
|
|
||||||
lGeometryElementTangent->SetMappingMode(FbxGeometryElement::eByControlPoint);
|
|
||||||
lGeometryElementTangent->SetReferenceMode(FbxGeometryElement::eDirect);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool vertexColours = vertexList->Count > 0 && dynamic_cast<ImportedVertexWithColour^>(vertexList[0]) != nullptr;
|
|
||||||
if (vertexColours)
|
if (vertexColours)
|
||||||
{
|
{
|
||||||
FbxGeometryElementVertexColor* lGeometryElementVertexColor = pMesh->CreateElementVertexColor();
|
ImportedVertexWithColour^ vert = (ImportedVertexWithColour^)vertexList[j];
|
||||||
lGeometryElementVertexColor->SetMappingMode(FbxGeometryElement::eByControlPoint);
|
lGeometryElementVertexColor->GetDirectArray().Add(FbxColor(vert->Colour.R, vert->Colour.G, vert->Colour.B, vert->Colour.A));
|
||||||
lGeometryElementVertexColor->SetReferenceMode(FbxGeometryElement::eDirect);
|
|
||||||
for (int j = 0; j < vertexList->Count; j++)
|
|
||||||
{
|
|
||||||
ImportedVertexWithColour^ vert = (ImportedVertexWithColour^)vertexList[j];
|
|
||||||
lGeometryElementVertexColor->GetDirectArray().Add(FbxColor(vert->Colour.R, vert->Colour.G, vert->Colour.B, vert->Colour.A));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FbxNode* pMeshNode = FbxNode::Create(pScene, pName);
|
if (hasBones && vertex->BoneIndices != nullptr)
|
||||||
if (hasBones)
|
|
||||||
{
|
{
|
||||||
pBindPose->Add(pMeshNode, pMeshNode->EvaluateGlobalTransform());
|
auto boneIndices = vertex->BoneIndices;
|
||||||
}
|
auto weights4 = vertex->Weights;
|
||||||
pMeshNode->SetNodeAttribute(pMesh);
|
for (int k = 0; k < 4; k++)
|
||||||
pFrameNode->AddChild(pMeshNode);
|
|
||||||
|
|
||||||
ImportedMaterial^ mat = ImportedHelpers::FindMaterial(meshObj->Material, imported->MaterialList);
|
|
||||||
if (mat != nullptr)
|
|
||||||
{
|
|
||||||
FbxGeometryElementMaterial* lGeometryElementMaterial = pMesh->GetElementMaterial();
|
|
||||||
if (!lGeometryElementMaterial)
|
|
||||||
{
|
{
|
||||||
lGeometryElementMaterial = pMesh->CreateElementMaterial();
|
if (boneIndices[k] < boneList->Count && weights4[k] > 0)
|
||||||
}
|
|
||||||
lGeometryElementMaterial->SetMappingMode(FbxGeometryElement::eByPolygon);
|
|
||||||
lGeometryElementMaterial->SetReferenceMode(FbxGeometryElement::eIndexToDirect);
|
|
||||||
|
|
||||||
char* pMatName = NULL;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
pMatName = StringToCharArray(mat->Name);
|
|
||||||
int foundMat = -1;
|
|
||||||
for (int j = 0; j < pMaterials->GetCount(); j++)
|
|
||||||
{
|
{
|
||||||
FbxSurfacePhong* pMatTemp = pMaterials->GetAt(j);
|
FbxCluster* pCluster = pClusterArray->GetAt(boneIndices[k]);
|
||||||
if (strcmp(pMatTemp->GetName(), pMatName) == 0)
|
pCluster->AddControlPointIndex(j + firstVertex, weights4[k]);
|
||||||
{
|
|
||||||
foundMat = j;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FbxSurfacePhong* pMat;
|
|
||||||
if (foundMat >= 0)
|
|
||||||
{
|
|
||||||
pMat = pMaterials->GetAt(foundMat);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FbxString lShadingName = "Phong";
|
|
||||||
Color diffuse = mat->Diffuse;
|
|
||||||
Color ambient = mat->Ambient;
|
|
||||||
Color emissive = mat->Emissive;
|
|
||||||
Color specular = mat->Specular;
|
|
||||||
Color reflection = mat->Reflection;
|
|
||||||
pMat = FbxSurfacePhong::Create(pScene, pMatName);
|
|
||||||
pMat->Diffuse.Set(FbxDouble3(diffuse.R, diffuse.G, diffuse.B));
|
|
||||||
pMat->DiffuseFactor.Set(FbxDouble(diffuse.A));
|
|
||||||
pMat->Ambient.Set(FbxDouble3(ambient.R, ambient.G, ambient.B));
|
|
||||||
pMat->AmbientFactor.Set(FbxDouble(ambient.A));
|
|
||||||
pMat->Emissive.Set(FbxDouble3(emissive.R, emissive.G, emissive.B));
|
|
||||||
pMat->EmissiveFactor.Set(FbxDouble(emissive.A));
|
|
||||||
pMat->Specular.Set(FbxDouble3(specular.R, specular.G, specular.B));
|
|
||||||
pMat->SpecularFactor.Set(FbxDouble(specular.A));
|
|
||||||
pMat->Reflection.Set(FbxDouble3(reflection.R, reflection.G, reflection.B));
|
|
||||||
pMat->ReflectionFactor.Set(FbxDouble(reflection.A));
|
|
||||||
pMat->Shininess.Set(FbxDouble(mat->Shininess));
|
|
||||||
pMat->TransparencyFactor.Set(FbxDouble(mat->Transparency));
|
|
||||||
pMat->ShadingModel.Set(lShadingName);
|
|
||||||
foundMat = pMaterials->GetCount();
|
|
||||||
pMaterials->Add(pMat);
|
|
||||||
}
|
|
||||||
pMeshNode->AddMaterial(pMat);
|
|
||||||
|
|
||||||
bool hasTexture = false;
|
|
||||||
|
|
||||||
for each (ImportedMaterialTexture^ texture in mat->Textures)
|
|
||||||
{
|
|
||||||
auto pTexture = ExportTexture(ImportedHelpers::FindTexture(texture->Name, imported->TextureList));
|
|
||||||
if (pTexture != NULL)
|
|
||||||
{
|
|
||||||
if (texture->Dest == 0)
|
|
||||||
{
|
|
||||||
LinkTexture(texture, pTexture, pMat->Diffuse);
|
|
||||||
hasTexture = true;
|
|
||||||
}
|
|
||||||
else if (texture->Dest == 1)
|
|
||||||
{
|
|
||||||
LinkTexture(texture, pTexture, pMat->NormalMap);
|
|
||||||
hasTexture = true;
|
|
||||||
}
|
|
||||||
else if (texture->Dest == 2)
|
|
||||||
{
|
|
||||||
LinkTexture(texture, pTexture, pMat->Specular);
|
|
||||||
hasTexture = true;
|
|
||||||
}
|
|
||||||
else if (texture->Dest == 3)
|
|
||||||
{
|
|
||||||
LinkTexture(texture, pTexture, pMat->Bump);
|
|
||||||
hasTexture = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasTexture)
|
|
||||||
{
|
|
||||||
pMeshNode->SetShadingMode(FbxNode::eTextureShading);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Marshal::FreeHGlobal((IntPtr)pMatName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = 0; j < vertexList->Count; j++)
|
|
||||||
{
|
|
||||||
ImportedVertex^ vertex = vertexList[j];
|
|
||||||
Vector3 coords = vertex->Position;
|
|
||||||
pControlPoints[j] = FbxVector4(coords.X, coords.Y, coords.Z, 0);
|
|
||||||
//if (normals)
|
|
||||||
{
|
|
||||||
Vector3 normal = vertex->Normal;
|
|
||||||
lGeometryElementNormal->GetDirectArray().Add(FbxVector4(normal.X, normal.Y, normal.Z, 0));
|
|
||||||
}
|
|
||||||
array<float>^ uv = vertex->UV;
|
|
||||||
if (uv != nullptr)
|
|
||||||
lGeometryElementUV->GetDirectArray().Add(FbxVector2(uv[0], uv[1]));
|
|
||||||
if (normals)
|
|
||||||
{
|
|
||||||
Vector4 tangent = vertex->Tangent;
|
|
||||||
lGeometryElementTangent->GetDirectArray().Add(FbxVector4(tangent.X, tangent.Y, tangent.Z, tangent.W));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasBones && vertex->BoneIndices != nullptr)
|
|
||||||
{
|
|
||||||
auto boneIndices = vertex->BoneIndices;
|
|
||||||
auto weights4 = vertex->Weights;
|
|
||||||
for (int k = 0; k < weights4->Length; k++)
|
|
||||||
{
|
|
||||||
if (boneIndices[k] < boneList->Count && weights4[k] > 0)
|
|
||||||
{
|
|
||||||
FbxCluster* pCluster = pClusterArray->GetAt(boneIndices[k]);
|
|
||||||
pCluster->AddControlPointIndex(j, weights4[k]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = 0; j < faceList->Count; j++)
|
|
||||||
{
|
|
||||||
ImportedFace^ face = faceList[j];
|
|
||||||
pMesh->BeginPolygon(0);
|
|
||||||
pMesh->AddPolygon(face->VertexIndices[0]);
|
|
||||||
pMesh->AddPolygon(face->VertexIndices[1]);
|
|
||||||
pMesh->AddPolygon(face->VertexIndices[2]);
|
|
||||||
pMesh->EndPolygon();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasBones)
|
|
||||||
{
|
|
||||||
FbxAMatrix lMeshMatrix = pFrameNode->EvaluateGlobalTransform();
|
|
||||||
|
|
||||||
FbxSkin* pSkin = FbxSkin::Create(pScene, "");
|
|
||||||
for (int j = 0; j < boneList->Count; j++)
|
|
||||||
{
|
|
||||||
FbxCluster* pCluster = pClusterArray->GetAt(j);
|
|
||||||
if (pCluster->GetControlPointIndicesCount() > 0)
|
|
||||||
{
|
|
||||||
auto boneMatrix = boneList[j]->Matrix;
|
|
||||||
FbxAMatrix lBoneMatrix;
|
|
||||||
for (int m = 0; m < 4; m++)
|
|
||||||
{
|
|
||||||
for (int n = 0; n < 4; n++)
|
|
||||||
{
|
|
||||||
lBoneMatrix.mData[m][n] = boneMatrix[m, n];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pCluster->SetTransformMatrix(lMeshMatrix);
|
|
||||||
pCluster->SetTransformLinkMatrix(lMeshMatrix * lBoneMatrix.Inverse());
|
|
||||||
|
|
||||||
pSkin->AddCluster(pCluster);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pSkin->GetClusterCount() > 0)
|
|
||||||
{
|
|
||||||
pMesh->AddDeformer(pSkin);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
|
||||||
|
for (int j = 0; j < faceList->Count; j++)
|
||||||
{
|
{
|
||||||
if (pClusterArray != NULL)
|
ImportedFace^ face = faceList[j];
|
||||||
|
pMesh->BeginPolygon(materialIndex);
|
||||||
|
pMesh->AddPolygon(face->VertexIndices[0] + firstVertex);
|
||||||
|
pMesh->AddPolygon(face->VertexIndices[1] + firstVertex);
|
||||||
|
pMesh->AddPolygon(face->VertexIndices[2] + firstVertex);
|
||||||
|
pMesh->EndPolygon();
|
||||||
|
}
|
||||||
|
|
||||||
|
firstVertex += vertexList->Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasBones)
|
||||||
|
{
|
||||||
|
FbxSkin* pSkin = FbxSkin::Create(pScene, "");
|
||||||
|
FbxAMatrix lMeshMatrix = pFrameNode->EvaluateGlobalTransform();
|
||||||
|
for (int j = 0; j < boneList->Count; j++)
|
||||||
|
{
|
||||||
|
FbxCluster* pCluster = pClusterArray->GetAt(j);
|
||||||
|
if (pCluster->GetControlPointIndicesCount() > 0)
|
||||||
{
|
{
|
||||||
delete pClusterArray;
|
auto boneMatrix = boneList[j]->Matrix;
|
||||||
|
FbxAMatrix lBoneMatrix;
|
||||||
|
for (int m = 0; m < 4; m++)
|
||||||
|
{
|
||||||
|
for (int n = 0; n < 4; n++)
|
||||||
|
{
|
||||||
|
lBoneMatrix.mData[m][n] = boneMatrix[m, n];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pCluster->SetTransformMatrix(lMeshMatrix);
|
||||||
|
pCluster->SetTransformLinkMatrix(lMeshMatrix * lBoneMatrix.Inverse());
|
||||||
|
|
||||||
|
pSkin->AddCluster(pCluster);
|
||||||
}
|
}
|
||||||
Marshal::FreeHGlobal((IntPtr)pName);
|
}
|
||||||
|
|
||||||
|
if (pSkin->GetClusterCount() > 0)
|
||||||
|
{
|
||||||
|
pMesh->AddDeformer(pSkin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -613,33 +562,11 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
delete pBoneNodeList;
|
delete pBoneNodeList;
|
||||||
}
|
}
|
||||||
}
|
if (pClusterArray != NULL)
|
||||||
}
|
|
||||||
|
|
||||||
FbxNode* Fbx::Exporter::FindNodeByPath(String ^ path)
|
|
||||||
{
|
|
||||||
array<String^>^ splitPath = path->Split('/');
|
|
||||||
FbxNode* lNode = pScene->GetRootNode();
|
|
||||||
for (int i = 0; i < splitPath->Length; i++)
|
|
||||||
{
|
|
||||||
String^ frameName = splitPath[i];
|
|
||||||
char* pNodeName = NULL;
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
pNodeName = StringToCharArray(frameName);
|
delete pClusterArray;
|
||||||
FbxNode* foundNode = lNode->FindChild(pNodeName, false);
|
|
||||||
if (foundNode == NULL)
|
|
||||||
{
|
|
||||||
throw gcnew Exception(gcnew String("Couldn't find path ") + path);
|
|
||||||
}
|
|
||||||
lNode = foundNode;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Marshal::FreeHGlobal((IntPtr)pNodeName);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return lNode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FbxFileTexture* Fbx::Exporter::ExportTexture(ImportedTexture^ matTex)
|
FbxFileTexture* Fbx::Exporter::ExportTexture(ImportedTexture^ matTex)
|
||||||
@ -761,9 +688,11 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
FbxNode* pNode = FindNodeByPath(keyframeList->Path);
|
auto frame = imported->RootFrame->FindFrameByPath(keyframeList->Path);
|
||||||
if (pNode != nullptr)
|
if (frame != nullptr)
|
||||||
{
|
{
|
||||||
|
FbxNode* pNode = (FbxNode*)frameToNode[frame];
|
||||||
|
|
||||||
FbxAnimCurve* lCurveSX = pNode->LclScaling.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_X, true);
|
FbxAnimCurve* lCurveSX = pNode->LclScaling.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_X, true);
|
||||||
FbxAnimCurve* lCurveSY = pNode->LclScaling.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y, true);
|
FbxAnimCurve* lCurveSY = pNode->LclScaling.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y, true);
|
||||||
FbxAnimCurve* lCurveSZ = pNode->LclScaling.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z, true);
|
FbxAnimCurve* lCurveSZ = pNode->LclScaling.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z, true);
|
||||||
@ -835,9 +764,9 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fbx::Exporter::ExportMorphs(IImported^ imported, bool morphMask, bool flatInbetween)
|
void Fbx::Exporter::ExportMorphs(bool morphMask, bool flatInbetween)
|
||||||
{
|
{
|
||||||
if (imported->MeshList == nullptr)
|
/*if (imported->MeshList == nullptr)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -885,7 +814,7 @@ namespace AssetStudio
|
|||||||
WITH_MARSHALLED_STRING
|
WITH_MARSHALLED_STRING
|
||||||
(
|
(
|
||||||
pShapeName,
|
pShapeName,
|
||||||
morph->ClipName + (meshList->SubmeshList->Count > 1 ? "_" + meshObjIdx : String::Empty) /*+ "_BlendShape"*/,
|
morph->ClipName + (meshList->SubmeshList->Count > 1 ? "_" + meshObjIdx : String::Empty),
|
||||||
lBlendShape = FbxBlendShape::Create(pScene, pShapeName);
|
lBlendShape = FbxBlendShape::Create(pScene, pShapeName);
|
||||||
);
|
);
|
||||||
FbxProperty rootGroupProp = FbxProperty::Create(lBlendShape, FbxStringDT, "RootGroup");
|
FbxProperty rootGroupProp = FbxProperty::Create(lBlendShape, FbxStringDT, "RootGroup");
|
||||||
@ -1035,6 +964,6 @@ namespace AssetStudio
|
|||||||
meshVertexIndex += meshList->SubmeshList[meshObjIdx]->VertexList->Count;
|
meshVertexIndex += meshList->SubmeshList[meshObjIdx]->VertexList->Count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -507,34 +507,15 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
if (transformDictionary.TryGetValue(transform, out var frame))
|
if (transformDictionary.TryGetValue(transform, out var frame))
|
||||||
{
|
{
|
||||||
return GetFramePath(frame);
|
return frame.Path;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetFramePath(ImportedFrame frame)
|
|
||||||
{
|
|
||||||
var path = frame.Name;
|
|
||||||
while (frame.Parent != null)
|
|
||||||
{
|
|
||||||
frame = frame.Parent;
|
|
||||||
path = frame.Name + "/" + path;
|
|
||||||
}
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string FixBonePath(string path)
|
private string FixBonePath(string path)
|
||||||
{
|
{
|
||||||
var name = path.Substring(path.LastIndexOf('/') + 1);
|
var frame = RootFrame.FindFrameByPath(path);
|
||||||
foreach (var frame in RootFrame.FindChilds(name))
|
return frame?.Path;
|
||||||
{
|
|
||||||
var fullPath = GetFramePath(frame);
|
|
||||||
if (fullPath.EndsWith(path))
|
|
||||||
{
|
|
||||||
return fullPath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetTransformPathByFather(Transform transform)
|
private static string GetTransformPathByFather(Transform transform)
|
||||||
@ -962,6 +943,8 @@ namespace AssetStudio
|
|||||||
transformName = strs.Last();
|
transformName = strs.Last();
|
||||||
var parentFrameName = strs[strs.Length - 2];
|
var parentFrameName = strs[strs.Length - 2];
|
||||||
parentFrame = RootFrame.FindChild(parentFrameName);
|
parentFrame = RootFrame.FindChild(parentFrameName);
|
||||||
|
//var parentFramePath = path.Substring(0, path.LastIndexOf('/'));
|
||||||
|
//parentFrame = RootFrame.FindFrameByPath(parentFramePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
var skeletonPose = avatar.m_Avatar.m_DefaultPose;
|
var skeletonPose = avatar.m_Avatar.m_DefaultPose;
|
||||||
|
Loading…
Reference in New Issue
Block a user