diff --git a/src/mod_converter/fbx.cpp b/src/mod_converter/fbx.cpp index 5c6794d..7e0bda9 100644 --- a/src/mod_converter/fbx.cpp +++ b/src/mod_converter/fbx.cpp @@ -211,57 +211,20 @@ bool LoadScene(FbxManager* pManager, FbxDocument* pScene, const char* pFilename) return lStatus; } -// https://twitter.com/FreyaHolmer/status/644881436982575104 -// https://help.autodesk.com/view/FBX/2017/ENU/?guid=__cpp_ref_class_fbx_axis_system_html -cl::opt AS(cl::desc("Choose axis system (fbx only):"), - cl::values( -#define axisval(x, y) \ - cl::OptionEnumValue{ #x, FbxAxisSystem::EPreDefinedAxisSystem::x, y } - - axisval(eMayaZUp, "UpVector = ZAxis, FrontVector = -ParityOdd, CoordSystem = RightHanded"), - axisval(eMayaYUp, "UpVector = YAxis, FrontVector = ParityOdd, CoordSystem = RightHanded (default)"), - axisval(eMax, "UpVector = ZAxis, FrontVector = -ParityOdd, CoordSystem = RightHanded"), - cl::OptionEnumValue{"eBlender", FbxAxisSystem::EPreDefinedAxisSystem::eMax, - "UpVector = ZAxis, FrontVector = -ParityOdd, CoordSystem = RightHanded\n(when importing, disable 'Use Pre/Post Rotation')"}, - axisval(eMotionBuilder, "UpVector = YAxis, FrontVector = ParityOdd, CoordSystem = RightHanded"), - axisval(eOpenGL, "UpVector = YAxis, FrontVector = ParityOdd, CoordSystem = RightHanded"), - axisval(eDirectX, "UpVector = YAxis, FrontVector = ParityOdd, CoordSystem = LeftHanded"), - axisval(eLightwave, "UpVector = YAxis, FrontVector = ParityOdd, CoordSystem = LeftHanded") - -#undef axisval - ) - , cl::init(FbxAxisSystem::EPreDefinedAxisSystem::eMayaYUp) -); - -void ConvertScene(FbxScene* lScene) +void ConvertScene(FbxScene* lScene, AxisSystem as) { - switch (AS.getValue()) + switch (as) { - case FbxAxisSystem::EPreDefinedAxisSystem::eMayaZUp: + case AxisSystem::eMayaZUp: FbxAxisSystem::MayaZUp.ConvertScene(lScene); break; - case FbxAxisSystem::EPreDefinedAxisSystem::eMax: - FbxAxisSystem::Max.ConvertScene(lScene); - break; - case FbxAxisSystem::EPreDefinedAxisSystem::eMotionBuilder: - FbxAxisSystem::Motionbuilder.ConvertScene(lScene); - break; - case FbxAxisSystem::EPreDefinedAxisSystem::eOpenGL: - FbxAxisSystem::OpenGL.ConvertScene(lScene); - break; - case FbxAxisSystem::EPreDefinedAxisSystem::eDirectX: + case AxisSystem::eDirectX: FbxAxisSystem::DirectX.ConvertScene(lScene); break; - case FbxAxisSystem::EPreDefinedAxisSystem::eLightwave: - FbxAxisSystem::Lightwave.ConvertScene(lScene); - break; - case FbxAxisSystem::EPreDefinedAxisSystem::eMayaYUp: - default: - break; } } -void model::printFbx(const std::string &fn) const +void model::printFbx(const std::string &fn, AxisSystem as) const { FbxManager* lSdkManager = NULL; FbxScene* lScene = NULL; @@ -272,7 +235,7 @@ void model::printFbx(const std::string &fn) const // Create the scene. CreateScene(*this, fn, lSdkManager, lScene); - ConvertScene(lScene); + ConvertScene(lScene, as); SaveScene(lSdkManager, lScene, (fn + ".fbx").c_str()); //SaveScene(lSdkManager, lScene, (fn + "_ue4.fbx").c_str()); diff --git a/src/mod_converter/mod_converter.cpp b/src/mod_converter/mod_converter.cpp index 15930a3..f030cf5 100644 --- a/src/mod_converter/mod_converter.cpp +++ b/src/mod_converter/mod_converter.cpp @@ -45,6 +45,23 @@ cl::opt all_formats("af", cl::desc("All formats (.obj, .fbx)")); yaml root; cl::opt stats("i", cl::desc("Gather information from (models)")); +// https://twitter.com/FreyaHolmer/status/644881436982575104 +// https://help.autodesk.com/view/FBX/2017/ENU/?guid=__cpp_ref_class_fbx_axis_system_html +cl::opt AS(cl::desc("Choose axis system (.fbx only):"), + cl::values( +#define axisval(x, y) \ + cl::OptionEnumValue{ #x, (int)AxisSystem::x, y } + + axisval(eMayaZUp, "UpVector = ZAxis, FrontVector = -ParityOdd, CoordSystem = RightHanded ( also 3dsMax, Blender)\n" + "(Blender: when importing, disable 'Use Pre/Post Rotation')"), + axisval(eMayaYUp, "UpVector = YAxis, FrontVector = ParityOdd, CoordSystem = RightHanded (default, also MotionBuilder, OpenGL)"), + axisval(eDirectX, "UpVector = YAxis, FrontVector = ParityOdd, CoordSystem = LeftHanded ( also Lightwave)") + +#undef axisval + ) + , cl::init(AxisSystem::Default) +); + auto read_model(const path &fn) { buffer b(read_file(fn)); @@ -65,8 +82,8 @@ void convert_model(const model &m, const path &fn) { // write all if (all_formats) - m.print(fn.u8string()); - m.printFbx(fn.u8string()); + m.print(fn.u8string(), AS); + m.printFbx(fn.u8string(), AS); } void convert_model(const path &fn) diff --git a/src/model/model.cpp b/src/model/model.cpp index 14041b0..026fd07 100644 --- a/src/model/model.cpp +++ b/src/model/model.cpp @@ -151,19 +151,32 @@ static String print_float(double v) return buf; }; +// input (AIM Coordinates) are in eMayaYUp template -static aim_vector3 rotate(const aim_vector3 &in, int rot_type = 0) +static aim_vector3 rotate(const aim_vector3 &in, AxisSystem rot_type) { - // input is AIM Coordinates, Z UP, RH axis system - eMax (same as eMayaZUp) in fbx. - // TODO: perform rotations using rot_type from fbx (its constants) + // it is not so simple + // we can change coords, but normals and other stuff require recalculation? + return in; - auto v = in; + aim_vector3 v = in; + switch (rot_type) + { + case AxisSystem::eMayaZUp: + v.y = in.z; + v.z = in.y; + v.y = -v.y; + break; + case AxisSystem::eDirectX: + v.x = -v.x; + break; + } return v; } -std::string vertex::printVertex() const +std::string vertex::printVertex(AxisSystem as) const { - auto v = rotate(coordinates); + auto v = rotate(coordinates, as); std::string s; s = "v " + @@ -175,9 +188,9 @@ std::string vertex::printVertex() const return s; } -std::string vertex::printNormal() const +std::string vertex::printNormal(AxisSystem as) const { - auto v = rotate(normal); + auto v = rotate(normal, as); std::string s; s = "vn " + print_float(v.x) + " " + print_float(v.y) + " " + print_float(v.z); @@ -306,7 +319,7 @@ std::string block::printMtl() const return s; } -std::string block::printObj(int group_offset) const +std::string block::printObj(int group_offset, AxisSystem as) const { std::string s; s += "usemtl " + h.name + "\n"; @@ -317,11 +330,11 @@ std::string block::printObj(int group_offset) const s += "# " + std::to_string(vertices.size()) + " vertices\n"; for (auto &v : vertices) - s += v.printVertex() + "\n"; + s += v.printVertex(as) + "\n"; s += "\n"; s += "# " + std::to_string(vertices.size()) + " vertex normals\n"; for (auto &v : vertices) - s += v.printNormal() + "\n"; + s += v.printNormal(as) + "\n"; s += "\n"; s += "# " + std::to_string(vertices.size()) + " texture coords\n"; for (auto &v : vertices) @@ -331,7 +344,7 @@ std::string block::printObj(int group_offset) const s += "# " + std::to_string(vertices.size()) + " faces\n"; for (auto &t : faces) { - auto v = rotate(t); + auto v = rotate(t, as); auto x = std::to_string(v.x + 1 + group_offset); auto y = std::to_string(v.y + 1 + group_offset); @@ -607,7 +620,7 @@ void model::load(const buffer &b) f.load(b); } -void model::print(const std::string &fn) const +void model::print(const std::string &fn, AxisSystem as) const { auto title = [](auto &o) { @@ -629,7 +642,7 @@ void model::print(const std::string &fn) const if (!b.canPrint()) continue; - o << b.printObj(n_vert) << "\n"; + o << b.printObj(n_vert, as) << "\n"; n_vert += b.vertices.size(); } }; diff --git a/src/model/model.h b/src/model/model.h index 32023e4..4030036 100644 --- a/src/model/model.h +++ b/src/model/model.h @@ -79,6 +79,26 @@ enum class MaterialType : uint32_t Fire2 = 0x3D, }; +enum class AxisSystem +{ + // UpVector = YAxis, FrontVector = ParityOdd, CoordSystem = RightHanded + // default, AIM + eMayaYUp, + eMotionBuilder = eMayaYUp, + eOpenGL = eMayaYUp, + + // UpVector = ZAxis, FrontVector = -ParityOdd, CoordSystem = RightHanded + eMayaZUp, + eMax = eMayaZUp, + + // UpVector = YAxis, FrontVector = ParityOdd, CoordSystem = LeftHanded + eDirectX, + eLightwave = eDirectX, + + // special + Default = 0, +}; + template struct aim_vector3 : vector3 { @@ -118,8 +138,8 @@ struct vertex void load(const buffer &b, uint32_t flags); - std::string printVertex() const; - std::string printNormal() const; + std::string printVertex(AxisSystem as) const; + std::string printNormal(AxisSystem as) const; std::string printTex() const; }; @@ -289,7 +309,7 @@ struct block void loadPayload(const buffer &b); std::string printMtl() const; - std::string printObj(int group_offset) const; + std::string printObj(int group_offset, AxisSystem as) const; block_info save(yaml &root) const; bool canPrint() const; @@ -302,8 +322,8 @@ struct model void load(const buffer &b); - void print(const std::string &fn) const; - void printFbx(const std::string &fn) const; + void print(const std::string &fn, AxisSystem) const; + void printFbx(const std::string &fn, AxisSystem) const; void save(yaml &root) const; };