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;
}
// 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
{
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);

View file

@ -40,7 +40,7 @@ bool silent = 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<bool> all_formats("af", cl::desc("All formats"));
cl::opt<bool> all_formats("af", cl::desc("All formats (.obj, .fbx)"));
yaml root;
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;
}
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)
{
/*
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)
// this is correct order and correct Y fix
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
*/
v.y = -v.y;
}
void aim_vector4::load(const buffer &b, uint32_t flags)

View file

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