Propagate axis system when printing. But disable during .obj print for now.

This commit is contained in:
lzwdgc 2020-02-29 04:19:19 +03:00
parent 3c5c756eaa
commit d2b64bdc25
4 changed files with 77 additions and 64 deletions

View file

@ -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<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)
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());

View file

@ -45,6 +45,23 @@ 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)"));
// https://twitter.com/FreyaHolmer/status/644881436982575104
// https://help.autodesk.com/view/FBX/2017/ENU/?guid=__cpp_ref_class_fbx_axis_system_html
cl::opt<AxisSystem> 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)

View file

@ -151,19 +151,32 @@ static String print_float(double v)
return buf;
};
// input (AIM Coordinates) are in eMayaYUp
template <class T>
static aim_vector3<T> rotate(const aim_vector3<T> &in, int rot_type = 0)
static aim_vector3<T> rotate(const aim_vector3<T> &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<T> 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();
}
};

View file

@ -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 <typename T>
struct aim_vector3 : vector3<T>
{
@ -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;
};