From 4fecc76b599084d51c65a6dbc73efc2e736f9f41 Mon Sep 17 00:00:00 2001 From: lzwdgc Date: Sat, 29 Feb 2020 03:33:55 +0300 Subject: [PATCH] Fix models export. Improve export coordinate system selection. --- src/mod_converter/fbx.cpp | 68 ++++++++++++++++++++---- src/mod_converter/mod_converter.cpp | 2 +- src/model/model.cpp | 81 ++++------------------------- src/model/model.h | 1 - 4 files changed, 68 insertions(+), 84 deletions(-) diff --git a/src/mod_converter/fbx.cpp b/src/mod_converter/fbx.cpp index 5180c22..5c6794d 100644 --- a/src/mod_converter/fbx.cpp +++ b/src/mod_converter/fbx.cpp @@ -211,6 +211,56 @@ 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) +{ + switch (AS.getValue()) + { + case FbxAxisSystem::EPreDefinedAxisSystem::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: + 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 { FbxManager* lSdkManager = NULL; @@ -219,12 +269,11 @@ void model::printFbx(const std::string &fn) const // Prepare the FBX SDK. InitializeSdkObjects(lSdkManager, lScene); - // default is ??? - //FbxAxisSystem::MayaZUp.ConvertScene(lScene); - // Create the scene. CreateScene(*this, fn, lSdkManager, lScene); + ConvertScene(lScene); + SaveScene(lSdkManager, lScene, (fn + ".fbx").c_str()); //SaveScene(lSdkManager, lScene, (fn + "_ue4.fbx").c_str()); //if (all_formats) @@ -249,7 +298,7 @@ bool CreateScene(const model &model, const std::string &name, FbxManager* pSdkMa return socket; }; - auto create_socket = [&create_socket_named](const auto &b, const std::string &name, bool mirror_x = false) + auto create_socket = [&create_socket_named](const auto &b, const std::string &name, bool mirror_y = false) { FbxVector4 c; for (auto &v : b.vertices) @@ -261,12 +310,9 @@ bool CreateScene(const model &model, const std::string &name, FbxManager* pSdkMa c /= b.vertices.size(); auto s = create_socket_named(name); - // here we must mirror 'first' number (original x) - // it depends on what order was during loading - if (mirror_x) - c.mData[get_x_coordinate_id()] = -c.mData[get_x_coordinate_id()]; + if (mirror_y) // y is the second coord, idx = 1 + c.mData[1] = -c.mData[1]; s->LclTranslation.Set(c); - //s->LclScaling.Set(FbxDouble3(scale_mult(), scale_mult(), scale_mult())); }; int engine_id = 0; @@ -339,9 +385,9 @@ bool CreateScene(const model &model, const std::string &name, FbxManager* pSdkMa // add vertices, normals, uvs for (const auto &[i,v] : enumerate(b.vertices)) { - FbxVector4 x(v.coordinates.x * scale_mult(), v.coordinates.y * scale_mult(), v.coordinates.z * scale_mult(), v.coordinates.w); + FbxVector4 cp(v.coordinates.x * scale_mult(), v.coordinates.y * scale_mult(), v.coordinates.z * scale_mult(), v.coordinates.w); FbxVector4 n(v.normal.x, v.normal.y, v.normal.z); - m->SetControlPointAt(x, n, i); + m->SetControlPointAt(cp, n, i); float f; auto uc = modf(fabs(v.texture_coordinates.u), &f); diff --git a/src/mod_converter/mod_converter.cpp b/src/mod_converter/mod_converter.cpp index 5b8e9ae..15930a3 100644 --- a/src/mod_converter/mod_converter.cpp +++ b/src/mod_converter/mod_converter.cpp @@ -40,7 +40,7 @@ bool silent = false; bool printMaxPolygonBlock = false; cl::opt p(cl::Positional, cl::desc(""), cl::value_desc("file or directory"), cl::Required); -cl::opt all_formats("af", cl::desc("All formats")); +cl::opt all_formats("af", cl::desc("All formats (.obj, .fbx)")); yaml root; cl::opt stats("i", cl::desc("Gather information from (models)")); diff --git a/src/model/model.cpp b/src/model/model.cpp index aab00de..1b1877a 100644 --- a/src/model/model.cpp +++ b/src/model/model.cpp @@ -84,82 +84,21 @@ std::string translate(const std::string &s) return s3; } -enum AxisSystem -{ - MayaYUpZFrontRH, - Windows3dViewer = MayaYUpZFrontRH, - - AIM, - UE4 = AIM, // Do not use 'Convert scene' during UE4 import! - - ax_aim = AIM, - ax_ue4 = ax_aim, - ax_maya_y = MayaYUpZFrontRH, - ax_win_3d_viewer = ax_maya_y, -}; - -cl::opt AS(cl::desc("Choose axis system:"), - cl::values( - clEnumVal(ax_ue4, "Original AIM or UE4 axis system"), - clEnumVal(ax_maya_y, "Default MAYA Y-Up Z-Front or Windows 3d Viewer axis system") - ) - , cl::init(AxisSystem::UE4) -); - -int get_x_coordinate_id() -{ - switch (AS) - { - case AxisSystem::AIM: - return 1; - default: - return 0; - } -} - static void load_translated(aim_vector3 &v, const buffer &b) { /* - Our coord system: - - ^ z - | - ---> y - / - v x - - AIM Coordinates: - 1st number: +Y (left) (or -Y (right)?) (-Y?) - 2nd number: +X (front) - 100% sure (-X?) - 3rd number: +Z (up) - 100% sure - - This is Z UP, LH axis system. - - Also see https://twitter.com/FreyaHolmer/status/644881436982575104 + AIM Coordinates (.mod file coord system, 100% sure): + 1st number: -Y (front, -ParityOdd) + 2nd number: +X (right, thus RH) + 3rd number: +Z (up) + This is Z UP, RH axis system - eMax (same as eMayaZUp) in fbx. */ - switch (AS) - { - case AxisSystem::MayaYUpZFrontRH: - // Y UP, Z FRONT (RH) - READ(b, v.x); - READ(b, v.z); - READ(b, v.y); - break; - case AxisSystem::AIM: - // Z UP, X FRONT (LH) - READ(b, v.y); - READ(b, v.x); - READ(b, v.z); - break; - default: - throw SW_RUNTIME_ERROR("Unknown Axis System"); - } - - /* - // Y UP, X FRONT (LH?) (blender accepts such fbx) - z,x,y - */ + // this is correct order and correct Y fix + READ(b, v.y); + READ(b, v.x); + READ(b, v.z); + v.y = -v.y; } void aim_vector4::load(const buffer &b, uint32_t flags) diff --git a/src/model/model.h b/src/model/model.h index 38c5ce5..957ed7c 100644 --- a/src/model/model.h +++ b/src/model/model.h @@ -306,4 +306,3 @@ struct model }; float scale_mult(); -int get_x_coordinate_id();