WoW Model Viewer
Your premiere tool for viewing, equipping and animating World of Warcraft models.
Loading...
Searching...
No Matches
FBXAnimExporter.cpp
Go to the documentation of this file.
1/*----------------------------------------------------------------------*\
2| This file is part of WoW Model Viewer |
3| |
4| WoW Model Viewer is free software: you can redistribute it and/or |
5| modify it under the terms of the GNU General Public License as |
6| published by the Free Software Foundation, either version 3 of the |
7| License, or (at your option) any later version. |
8| |
9| WoW Model Viewer is distributed in the hope that it will be useful, |
10| but WITHOUT ANY WARRANTY; without even the implied warranty of |
11| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12| GNU General Public License for more details. |
13| |
14| You should have received a copy of the GNU General Public License |
15| along with WoW Model Viewer. |
16| If not, see <http://www.gnu.org/licenses/>. |
17\*----------------------------------------------------------------------*/
18
19/*
20 * FBXAnimExporter.cpp
21 *
22 * Created on: 14 may 2019
23 * Copyright: 2019 , WoW Model Viewer (http://wowmodelviewer.net)
24 */
25
26#include "FBXAnimExporter.h"
27
28#ifdef _WIN32
29#include <windows.h>
30#endif
31#include <filesystem>
32#include <mutex>
33#include <sstream>
34#include <fbxsdk.h>
35#include <fbxsdk/fileio/fbxiosettings.h>
36#include "GlobalSettings.h"
37#include "FBXHeaders.h"
38#include "WoWModel.h"
39
41{
42 std::lock_guard<std::mutex> locker(m_mutex);
43 const ModelAnimation curAnimation = l_model->anims[animID];
44 if (srcfileName.empty())
45 {
46 LOG_ERROR << "Unable to get FBX Animation Source Filename.";
47 return;
48 }
49
50 // Remove .fbx extension
51 auto fbxPos = srcfileName.rfind(".fbx");
52 if (fbxPos != std::string::npos)
53 srcfileName = srcfileName.substr(0, fbxPos);
54
55 std::string justfileName = srcfileName;
56 auto slashPos = justfileName.rfind('\\');
57 if (slashPos == std::string::npos)
58 slashPos = justfileName.rfind('/');
59 if (slashPos != std::string::npos)
60 justfileName = justfileName.substr(slashPos + 1);
61
62 std::string anim_name = animationName + " [" + std::to_string(curAnimation.Index) + "]";
63 std::string file_name;
64 if (useAltNaming)
65 {
66 file_name = srcfileName + "_Animations/" + justfileName + "_" +
67 std::to_string(curAnimation.Index) + "_" + animationName + ".fbx";
68 }
69 else
70 {
71 file_name = srcfileName + "_Animations/" + justfileName + "_" +
72 animationName + "_" + std::to_string(curAnimation.Index) + ".fbx";
73 }
74 LOG_INFO << "FBX Animation Filename: " << file_name.c_str();
75 auto lastSlash = file_name.rfind('/');
76 if (lastSlash != std::string::npos)
77 {
78 std::string dirPath = file_name.substr(0, lastSlash);
79 std::filesystem::create_directories(dirPath);
80 }
81
82 FbxManager* lSdkManager = FbxManager::Create();
83 if (!lSdkManager)
84 {
85 LOG_ERROR << "Unable to create the FBX SDK manager for the animation exporter";
86 return;
87 }
88
89 FbxIOSettings* ios = FbxIOSettings::Create(lSdkManager, IOSROOT);
90 lSdkManager->SetIOSettings(ios);
91
92 ios->SetBoolProp(EXP_FBX_MATERIAL, false);
93 ios->SetBoolProp(EXP_FBX_TEXTURE, false);
94 ios->SetBoolProp(EXP_FBX_EMBEDDED, false);
95 ios->SetBoolProp(EXP_FBX_SHAPE, true);
96 ios->SetBoolProp(EXP_FBX_GOBO, true);
97 ios->SetBoolProp(EXP_FBX_ANIMATION, true);
98 ios->SetBoolProp(EXP_FBX_GLOBAL_SETTINGS, true);
99
100 fbxsdk::FbxExporter* exporter = nullptr;
101 FbxScene* l_animscene = nullptr;
102 if (!FBXHeaders::createFBXHeaders(l_fileVersion, file_name, lSdkManager, exporter, l_animscene))
103 {
104 LOG_ERROR << "Unable to create Animation Headers. Aborting Export...";
105 if (lSdkManager)
106 lSdkManager->Destroy();
107 return;
108 }
109
110 FbxDocumentInfo* sceneInfo = FbxDocumentInfo::Create(lSdkManager, "SceneInfo");
111 sceneInfo->mTitle = anim_name.c_str();
112 {
113 std::wstring appName = GLOBALSETTINGS.appName();
114 if (!appName.empty())
115 {
116 int n = WideCharToMultiByte(CP_UTF8, 0, appName.c_str(), static_cast<int>(appName.size()), nullptr, 0, nullptr, nullptr);
117 std::string appNameUtf8(n, '\0');
118 WideCharToMultiByte(CP_UTF8, 0, appName.c_str(), static_cast<int>(appName.size()), appNameUtf8.data(), n, nullptr, nullptr);
119 sceneInfo->mAuthor = appNameUtf8.c_str();
120 }
121 }
122 {
123 std::wstring appVer = GLOBALSETTINGS.appVersion();
124 if (!appVer.empty())
125 {
126 int n = WideCharToMultiByte(CP_UTF8, 0, appVer.c_str(), static_cast<int>(appVer.size()), nullptr, 0, nullptr, nullptr);
127 std::string appVerUtf8(n, '\0');
128 WideCharToMultiByte(CP_UTF8, 0, appVer.c_str(), static_cast<int>(appVer.size()), appVerUtf8.data(), n, nullptr, nullptr);
129 sceneInfo->mRevision = appVerUtf8.c_str();
130 }
131 }
132 l_animscene->SetSceneInfo(sceneInfo);
133
134 std::map<int, FbxNode*> l_boneNodes;
135 FbxNode* l_skeletonNode = nullptr;
136 FBXHeaders::createSkeleton(l_model, l_animscene, l_skeletonNode, l_boneNodes);
137
138 FbxNode* root_node = l_animscene->GetRootNode();
139 root_node->AddChild(l_skeletonNode);
140
142
143 // Add this animation to our new FBX file.
144 FBXHeaders::createAnimation(l_model, l_animscene, anim_name, curAnimation, l_boneNodes);
145
146 if (!exporter->Export(l_animscene))
147 {
148 LOG_ERROR << "Unable to export FBX animation scene.";
149 if (lSdkManager)
150 lSdkManager->Destroy();
151 return;
152 }
153 LOG_INFO << "FBX Animation for" << anim_name.c_str() << "successfully exported!";
154 if (lSdkManager)
155 lSdkManager->Destroy();
156}
157
158void FBXAnimExporter::setValues(FbxString fileVersion, std::string fn, std::string an, WoWModel* m, std::vector<FbxCluster*> bc,
159 FbxNode* & meshnode, int aID, bool uan)
160{
161 std::lock_guard<std::mutex> locker(m_mutex);
162 l_fileVersion = fileVersion;
163 srcfileName = std::move(fn);
164 animationName = std::move(an);
165 l_model = m;
166 l_boneClusters = bc;
167 l_meshNode = meshnode;
168 animID = aID;
169 useAltNaming = uan;
170}
#define GLOBALSETTINGS
#define LOG_ERROR
Definition Logger.h:11
#define LOG_INFO
Definition Logger.h:10
FbxString l_fileVersion
void run()
Execute the animation export.
void setValues(FbxString fileVersion, std::string fn, std::string an, WoWModel *m, std::vector< FbxCluster * > bc, FbxNode *&meshnode, int aID, bool uan=false)
Configure the exporter with source model, animation, and output settings.
std::string animationName
std::vector< FbxCluster * > l_boneClusters
std::string srcfileName
Core WoW .m2 model: geometry, animation, textures, and character data.
Definition WoWModel.h:50
std::vector< ModelAnimation > anims
Definition WoWModel.h:178
void createSkeleton(WoWModel *l_model, FbxScene *&l_scene, FbxNode *&l_skeletonNode, std::map< int, FbxNode * > &l_boneNodes)
void createAnimation(WoWModel *l_model, FbxScene *&l_scene, std::string animName, ModelAnimation cur_anim, std::map< int, FbxNode * > &skeleton)
void storeBindPose(FbxScene *&l_scene, std::vector< FbxCluster * > l_boneClusters, FbxNode *l_meshNode)
bool createFBXHeaders(FbxString fileVersion, std::string l_FileName, FbxManager *&l_Manager, FbxExporter *&l_Exporter, FbxScene *&l_Scene)
An animation sequence entry in the M2 model (block B).