Fix models export. Improve export coordinate system selection.

This commit is contained in:
lzwdgc 2020-02-29 03:33:55 +03:00
parent 13c12f9bd3
commit 4fecc76b59
4 changed files with 68 additions and 84 deletions

View file

@ -211,6 +211,56 @@ bool LoadScene(FbxManager* pManager, FbxDocument* pScene, const char* pFilename)
return lStatus; 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<FbxAxisSystem::EPreDefinedAxisSystem> 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 void model::printFbx(const std::string &fn) const
{ {
FbxManager* lSdkManager = NULL; FbxManager* lSdkManager = NULL;
@ -219,12 +269,11 @@ void model::printFbx(const std::string &fn) const
// Prepare the FBX SDK. // Prepare the FBX SDK.
InitializeSdkObjects(lSdkManager, lScene); InitializeSdkObjects(lSdkManager, lScene);
// default is ???
//FbxAxisSystem::MayaZUp.ConvertScene(lScene);
// Create the scene. // Create the scene.
CreateScene(*this, fn, lSdkManager, lScene); CreateScene(*this, fn, lSdkManager, lScene);
ConvertScene(lScene);
SaveScene(lSdkManager, lScene, (fn + ".fbx").c_str()); SaveScene(lSdkManager, lScene, (fn + ".fbx").c_str());
//SaveScene(lSdkManager, lScene, (fn + "_ue4.fbx").c_str()); //SaveScene(lSdkManager, lScene, (fn + "_ue4.fbx").c_str());
//if (all_formats) //if (all_formats)
@ -249,7 +298,7 @@ bool CreateScene(const model &model, const std::string &name, FbxManager* pSdkMa
return socket; 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; FbxVector4 c;
for (auto &v : b.vertices) for (auto &v : b.vertices)
@ -261,12 +310,9 @@ bool CreateScene(const model &model, const std::string &name, FbxManager* pSdkMa
c /= b.vertices.size(); c /= b.vertices.size();
auto s = create_socket_named(name); auto s = create_socket_named(name);
// here we must mirror 'first' number (original x) if (mirror_y) // y is the second coord, idx = 1
// it depends on what order was during loading c.mData[1] = -c.mData[1];
if (mirror_x)
c.mData[get_x_coordinate_id()] = -c.mData[get_x_coordinate_id()];
s->LclTranslation.Set(c); s->LclTranslation.Set(c);
//s->LclScaling.Set(FbxDouble3(scale_mult(), scale_mult(), scale_mult()));
}; };
int engine_id = 0; int engine_id = 0;
@ -339,9 +385,9 @@ bool CreateScene(const model &model, const std::string &name, FbxManager* pSdkMa
// add vertices, normals, uvs // add vertices, normals, uvs
for (const auto &[i,v] : enumerate(b.vertices)) 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); FbxVector4 n(v.normal.x, v.normal.y, v.normal.z);
m->SetControlPointAt(x, n, i); m->SetControlPointAt(cp, n, i);
float f; float f;
auto uc = modf(fabs(v.texture_coordinates.u), &f); auto uc = modf(fabs(v.texture_coordinates.u), &f);

View file

@ -40,7 +40,7 @@ bool silent = false;
bool printMaxPolygonBlock = false; bool printMaxPolygonBlock = false;
cl::opt<path> p(cl::Positional, cl::desc("<MOD_ file or directory with MOD_ files>"), cl::value_desc("file or directory"), cl::Required); cl::opt<path> p(cl::Positional, cl::desc("<MOD_ file or directory with MOD_ files>"), cl::value_desc("file or directory"), cl::Required);
cl::opt<bool> all_formats("af", cl::desc("All formats")); cl::opt<bool> all_formats("af", cl::desc("All formats (.obj, .fbx)"));
yaml root; yaml root;
cl::opt<bool> stats("i", cl::desc("Gather information from (models)")); cl::opt<bool> stats("i", cl::desc("Gather information from (models)"));

View file

@ -84,82 +84,21 @@ std::string translate(const std::string &s)
return s3; 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<AxisSystem> 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<float> &v, const buffer &b) static void load_translated(aim_vector3<float> &v, const buffer &b)
{ {
/* /*
Our coord system: AIM Coordinates (.mod file coord system, 100% sure):
1st number: -Y (front, -ParityOdd)
^ z 2nd number: +X (right, thus RH)
| 3rd number: +Z (up)
---> y This is Z UP, RH axis system - eMax (same as eMayaZUp) in fbx.
/
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
*/ */
switch (AS) // this is correct order and correct Y fix
{ READ(b, v.y);
case AxisSystem::MayaYUpZFrontRH: READ(b, v.x);
// Y UP, Z FRONT (RH) READ(b, v.z);
READ(b, v.x); v.y = -v.y;
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
*/
} }
void aim_vector4::load(const buffer &b, uint32_t flags) void aim_vector4::load(const buffer &b, uint32_t flags)

View file

@ -306,4 +306,3 @@ struct model
}; };
float scale_mult(); float scale_mult();
int get_x_coordinate_id();