From a28531d834cf7a558fc07d5176fa1e6ed24c2f13 Mon Sep 17 00:00:00 2001 From: lzwdgc Date: Sun, 10 Mar 2019 22:15:51 +0300 Subject: [PATCH] Improve coordinates loading. --- src/mmo_extractor/mmo_extractor.cpp | 12 +++- src/mod_converter/fbx.cpp | 63 ++++++++++++------- src/mod_converter/fbx.h | 3 - src/mod_converter/mod_converter.cpp | 5 +- src/model/model.cpp | 98 ++++++++++++++++++++++++----- src/model/model.h | 5 +- sw.cpp | 5 +- 7 files changed, 141 insertions(+), 50 deletions(-) delete mode 100644 src/mod_converter/fbx.h diff --git a/src/mmo_extractor/mmo_extractor.cpp b/src/mmo_extractor/mmo_extractor.cpp index fd5691c..8eef60b 100644 --- a/src/mmo_extractor/mmo_extractor.cpp +++ b/src/mmo_extractor/mmo_extractor.cpp @@ -122,8 +122,10 @@ void write_mmo(Storage *storage, const mmo_storage &s) if (map_id == 0) { - printf("error: this map is not found in the database\n"); - return; + auto m = storage->addMap(); + m->text_id = map_name; + map_id = m->getId(); + //throw SW_RUNTIME_ERROR("error: map '" + map_name + "' is not found in the database"); } auto this_map = storage->maps[map_id]; @@ -312,7 +314,13 @@ int main(int argc, char *argv[]) } else { + bool e = fs::exists(db_path); auto storage = initStorage(db_path.u8string()); + if (!e) + { + storage->create(); + storage->save(); + } storage->load(); action([&storage](const path &, const auto &m) {write_mmo(storage.get(), m); }); if (inserted_all) diff --git a/src/mod_converter/fbx.cpp b/src/mod_converter/fbx.cpp index c13e6ac..6f4d421 100644 --- a/src/mod_converter/fbx.cpp +++ b/src/mod_converter/fbx.cpp @@ -1,9 +1,9 @@ -#include "fbx.h" - #include "model.h" #include #include +#include +#include #include #ifdef IOS_REF @@ -11,6 +11,9 @@ #define IOS_REF (*(pManager->GetIOSettings())) #endif +cl::opt text_fbx("t", cl::desc("Produce ascii .fbx")); +extern cl::opt all_formats; + bool CreateScene(const model &m, const std::string &name, FbxManager* pSdkManager, FbxScene* pScene); void InitializeSdkObjects(FbxManager*& pManager, FbxScene*& pScene) @@ -38,6 +41,10 @@ void InitializeSdkObjects(FbxManager*& pManager, FbxScene*& pScene) FBXSDK_printf("Error: Unable to create FBX scene!\n"); exit(1); } + + pScene->GetSceneInfo()->LastSaved_ApplicationVendor.Set("lzwdgc's"); + pScene->GetSceneInfo()->LastSaved_ApplicationName.Set("mod_converter"); + pScene->GetSceneInfo()->LastSaved_ApplicationVersion.Set(version().c_str()); } void DestroySdkObjects(FbxManager* pManager, bool pExitStatus) @@ -57,7 +64,9 @@ bool SaveScene(FbxManager* pManager, FbxDocument* pScene, const char* pFilename, // Create an exporter. FbxExporter* lExporter = FbxExporter::Create(pManager, ""); - auto pFileFormat = pManager->GetIOPluginRegistry()->GetNativeWriterFormat(); // 1 for ascii + auto pFileFormat = pManager->GetIOPluginRegistry()->GetNativeWriterFormat(); + if (text_fbx) + pFileFormat = 1; // 1 for ascii FbxString lDesc = pManager->GetIOPluginRegistry()->GetWriterFormatDescription(pFileFormat); // Set the export states. By default, the export states are always set to @@ -210,12 +219,15 @@ void model::printFbx(const std::string &fn) const // Prepare the FBX SDK. InitializeSdkObjects(lSdkManager, lScene); + //FbxAxisSystem::MayaZUp.ConvertScene(lScene); + // Create the scene. CreateScene(*this, fn, lSdkManager, lScene); - SaveScene(lSdkManager, lScene, (fn + "_ue4.fbx").c_str()); - if (all_formats) - SaveScene(lSdkManager, lScene, (fn + "_blender.fbx").c_str(), true); + SaveScene(lSdkManager, lScene, (fn + ".fbx").c_str()); + //SaveScene(lSdkManager, lScene, (fn + "_ue4.fbx").c_str()); + //if (all_formats) + //SaveScene(lSdkManager, lScene, (fn + "_blender.fbx").c_str(), true); // Destroy all objects created by the FBX SDK. DestroySdkObjects(lSdkManager, true); @@ -230,7 +242,7 @@ bool CreateScene(const model &model, const std::string &name, FbxManager* pSdkMa auto create_socket_named = [&pScene](const std::string &name) { FbxNode *socket = FbxNode::Create(pScene, ("SOCKET_" + name).c_str()); - auto n = FbxNull::Create(socket, ""); + auto n = FbxNull::Create(pScene, ""); socket->SetNodeAttribute(n); pScene->GetRootNode()->AddChild(socket); return socket; @@ -242,24 +254,24 @@ bool CreateScene(const model &model, const std::string &name, FbxManager* pSdkMa for (auto &v : b.vertices) { FbxVector4 x; - x.Set(v.coordinates.z * scale_mult, v.coordinates.y * scale_mult, v.coordinates.x * scale_mult, v.coordinates.w); + x.Set(v.coordinates.x * scale_mult(), v.coordinates.y * scale_mult(), v.coordinates.z * scale_mult(), v.coordinates.w); c += x; } 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[2] = -c.mData[2]; + c.mData[get_x_coordinate_id()] = -c.mData[get_x_coordinate_id()]; s->LclTranslation.Set(c); + //s->LclScaling.Set(FbxDouble3(scale_mult(), scale_mult(), scale_mult())); }; - //std::mapSetNodeAttribute(m); - //node->SetShadingMode(FbxNode::eTextureShading); // change?! was texture sh + node->SetShadingMode(FbxNode::eFullShading); // change?! was texture sh // vertices m->InitControlPoints(b.vertices.size()); @@ -324,13 +336,11 @@ bool CreateScene(const model &model, const std::string &name, FbxManager* pSdkMa auto s_uv = create_uv(gSpecularElementName); // add vertices, normals, uvs - int i = 0; - for (auto &v : b.vertices) + for (const auto &[i,v] : enumerate(b.vertices)) { - FbxVector4 x; - x.Set(v.coordinates.z * scale_mult, v.coordinates.x * scale_mult, v.coordinates.y * scale_mult, v.coordinates.w); - m->SetControlPointAt(x, i++); - normal->GetDirectArray().Add(FbxVector4(v.normal.z, -v.normal.x, v.normal.y)); + FbxVector4 x(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); float f; auto uc = modf(fabs(v.texture_coordinates.u), &f); @@ -346,11 +356,16 @@ bool CreateScene(const model &model, const std::string &name, FbxManager* pSdkMa // Set the control point indices of the bottom side of the pyramid m->BeginPolygon(); m->AddPolygon(v.x); - m->AddPolygon(v.z); m->AddPolygon(v.y); + m->AddPolygon(v.z); m->EndPolygon(); } + m->BuildMeshEdgeArray(); + + //if (m->GenerateNormals(true)) + //throw SW_RUNTIME_ERROR("Cannot generate normals"); + // mats auto lMaterial = node->GetSrcObject(0); if (!lMaterial) @@ -393,7 +408,7 @@ bool CreateScene(const model &model, const std::string &name, FbxManager* pSdkMa lMaterial->DiffuseFactor.Set(b.mat.diffuse.r); //lMaterial->TransparencyFactor.Set(0.4); - //lMaterial->ShadingModel.Set(lShadingName); + lMaterial->ShadingModel.Set(lShadingName); //lMaterial->Shininess.Set(0.5); lMaterial->Specular.Set(lSpecularColor); @@ -442,8 +457,12 @@ bool CreateScene(const model &model, const std::string &name, FbxManager* pSdkMa //convert soft/hard edge info to smoothing group info lGeometryConverter.ComputePolygonSmoothingFromEdgeSmoothing(m); + // scale + //node->LclScaling.Set(FbxDouble3(scale_mult(), scale_mult(), scale_mult())); + // pScene->GetRootNode()->AddChild(node); } + return true; } diff --git a/src/mod_converter/fbx.h b/src/mod_converter/fbx.h deleted file mode 100644 index d265d7b..0000000 --- a/src/mod_converter/fbx.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -inline bool all_formats = false; diff --git a/src/mod_converter/mod_converter.cpp b/src/mod_converter/mod_converter.cpp index 47fb2a5..a0fe304 100644 --- a/src/mod_converter/mod_converter.cpp +++ b/src/mod_converter/mod_converter.cpp @@ -17,7 +17,6 @@ */ #include -#include "fbx.h" #include "model.h" #include @@ -41,6 +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("a", cl::desc("All formats")); yaml root; cl::opt stats("i", cl::desc("Gather information from (models)")); @@ -84,15 +84,12 @@ void convert_model(const path &fn) int main(int argc, char *argv[]) { - cl::opt af("a", cl::desc("All formats")); cl::opt mr("mr", cl::desc("AIM Racing MOD file")); cl::ParseCommandLineOptions(argc, argv); if (mr) gameType = GameType::AimR; - if (af) - all_formats = true; if (fs::is_regular_file(p)) convert_model(p); diff --git a/src/model/model.cpp b/src/model/model.cpp index f187ab3..06db190 100644 --- a/src/model/model.cpp +++ b/src/model/model.cpp @@ -31,12 +31,14 @@ //#include #include - +#include #include #include #include +cl::opt scale_multiplier("s", cl::desc("Model scale multiplier"), cl::init(1.0f)); + template inline bool replace_all(T &str, const T &from, const T &to) { @@ -58,6 +60,11 @@ inline bool replace_all(std::string &str, const std::string &from, const std::st std::string version(); +float scale_mult() +{ + return scale_multiplier; +} + // UE does not recognize russian strings in .obj // what about fbx? // TODO: what to do with signs: soft sign -> ' ? @@ -77,19 +84,71 @@ std::string translate(const std::string &s) return s3; } +enum class AxisSystem +{ + MayaYUpZFrontRH, + AIM, + UE4 = AIM, +}; + +AxisSystem AS = AxisSystem::AIM; + +int get_x_coordinate_id() +{ + switch (AS) + { + case AxisSystem::MayaYUpZFrontRH: + return 0; + case AxisSystem::AIM: + return 1; + default: + return 0; + } +} + template void aim_vector3::load(const buffer &b) { - READ(b, base::x); - x = -x; // fix ue4 left hand coordinate system - READ(b, base::z); - READ(b, base::y); + /* + Our coord system: + + ^ z + | + ---> y + / + v x + + AIM Coordinates: + 1st number: +Y (left) (or -Y (right)?) + 2nd number: +X (front) - 100% sure + 3rd number: +Z (up) - 100% sure + + This is Z UP, LH axis system. + + Also see https://twitter.com/FreyaHolmer/status/644881436982575104 + */ + + switch (AS) + { + case AxisSystem::MayaYUpZFrontRH: + // MAYA Y UP, Z FRONT (RH) + READ(b, base::x); + READ(b, base::z); + READ(b, base::y); + break; + case AxisSystem::AIM: + // AIM viewer, UE4, Z UP (LH) + READ(b, base::y); + READ(b, base::x); + READ(b, base::z); + break; + default: + throw SW_RUNTIME_ERROR("Unknown Axis System"); + } /* - // direction will match to m viewer - READ(b, base::y); - READ(b, base::x); - READ(b, base::z); + // Y UP, X FRONT (LH?) (blender accepts such fbx) + z,x,y */ } @@ -110,7 +169,8 @@ std::string aim_vector4::print() const void vertex::load(const buffer &b, uint32_t flags) { coordinates.load(b, flags); - READ(b, normal); + normal.load(b); + //READ(b, normal); READ(b, texture_coordinates); } @@ -129,18 +189,18 @@ std::string vertex::printVertex(bool rotate_x_90) const { // that rotation is really equivalent to exchanging y and z and z sign s = "v " + - std::to_string(-coordinates.x * scale_mult) + " " + - std::to_string(coordinates.z * scale_mult) + " " + - std::to_string(coordinates.y * scale_mult) + " " + + std::to_string(-coordinates.x * scale_mult()) + " " + + std::to_string(coordinates.z * scale_mult()) + " " + + std::to_string(coordinates.y * scale_mult()) + " " + std::to_string(coordinates.w) ; } else { s = "v " + - std::to_string(-coordinates.x * scale_mult) + " " + - std::to_string(coordinates.y * scale_mult) + " " + - std::to_string(-coordinates.z * scale_mult) + " " + + std::to_string(-coordinates.x * scale_mult()) + " " + + std::to_string(coordinates.y * scale_mult()) + " " + + std::to_string(-coordinates.z * scale_mult()) + " " + std::to_string(coordinates.w) ; } @@ -440,7 +500,7 @@ void block::loadPayload(const buffer &data) v.load(data, flags); faces.resize(n_triangles); for (auto &t : faces) - READ(data, t); + t.load(data); // animations for (auto &a : animations) @@ -515,6 +575,10 @@ bool block::canPrint() const if (h.type == BlockType::ParticleEmitter) return false; + // collision object + if (h.name == "SHAPE") + return false; + // default return false; } diff --git a/src/model/model.h b/src/model/model.h index d5e6a0a..ebc7cb8 100644 --- a/src/model/model.h +++ b/src/model/model.h @@ -20,13 +20,13 @@ #include "types.h" +//#include #include #include #include #include -const float scale_mult = 30.f; const std::string texture_extension = ".TM.bmp"; class buffer; @@ -296,3 +296,6 @@ struct model void printFbx(const std::string &fn) const; void save(yaml &root) const; }; + +float scale_mult(); +int get_x_coordinate_id(); diff --git a/sw.cpp b/sw.cpp index eedb2b5..44dea55 100644 --- a/sw.cpp +++ b/sw.cpp @@ -55,7 +55,10 @@ void build(Solution &s) auto &model = tools.addStaticLibrary("model"); model.CPPVersion = CPPLanguageStandard::CPP17; model.setRootDirectory("src/model"); - model.Public += common, "org.sw.demo.unicode.icu.i18n-*"_dep; + model.Public += common, + "org.sw.demo.unicode.icu.i18n"_dep, + "org.sw.demo.eigen"_dep + ; add_exe("mod_reader") += model;