diff --git a/cppan.yml b/cppan.yml index 82df841..2208beb 100644 --- a/cppan.yml +++ b/cppan.yml @@ -4,3 +4,4 @@ local_settings: - pvt.cppan.demo.eigen: 3 - pvt.egorpugin.primitives.filesystem: master - pvt.egorpugin.primitives.executor: master + - pvt.cppan.demo.unicode.icu.i18n: "*" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 33dac71..84f3783 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -41,11 +41,20 @@ file(GLOB mmp_extractor_src "mmp_extractor/*") add_executable(mmp_extractor ${mmp_extractor_src}) target_link_libraries(mmp_extractor common) +file(GLOB model_src "model/*") +add_library(model ${model_src}) +target_link_libraries(model + common + pvt.cppan.demo.unicode.icu.i18n +) +target_include_directories(model PUBLIC model) + if (DEFINED FBX_SDK_ROOT) file(GLOB mod_converter_src "mod_converter/*") add_executable(mod_converter ${mod_converter_src}) target_link_libraries(mod_converter common + model #pvt.cppan.demo.eigen debug "${FBX_SDK_ROOT}/lib/vs2015/x86/debug/libfbxsdk-md.lib" optimized "${FBX_SDK_ROOT}/lib/vs2015/x86/release/libfbxsdk-md.lib" @@ -58,8 +67,8 @@ else() endif() file(GLOB mod_reader_src "mod_reader/*") -add_executable(mod_reader ${mod_reader_src} mod_converter/model.cpp) -target_link_libraries(mod_reader common) +add_executable(mod_reader ${mod_reader_src}) +target_link_libraries(mod_reader model) file(GLOB mpj_loader_src "mpj_loader/*") add_executable(mpj_loader ${mpj_loader_src}) diff --git a/src/common/buffer.cpp b/src/common/buffer.cpp index 89d46da..e07899a 100644 --- a/src/common/buffer.cpp +++ b/src/common/buffer.cpp @@ -18,8 +18,12 @@ #include "buffer.h" +#include "common.h" + #include +#include + const int build_version = #include ; @@ -187,3 +191,30 @@ const std::vector &buffer::buf() const throw std::logic_error("buffer: not initialized"); return *buf_; } + +std::string str2utf8(const std::string &codepage_str, int cp) +{ + auto utf16_str = str2utf16(codepage_str, cp); + int utf8_size = WideCharToMultiByte(CP_UTF8, 0, utf16_str.c_str(), + utf16_str.length(), nullptr, 0, + nullptr, nullptr); + std::string utf8_str(utf8_size, '\0'); + WideCharToMultiByte(CP_UTF8, 0, utf16_str.c_str(), + utf16_str.length(), &utf8_str[0], utf8_size, + nullptr, nullptr); + return utf8_str; +} + +std::wstring str2utf16(const std::string &codepage_str, int cp) +{ + int size; + std::wstring utf16_str; + + size = MultiByteToWideChar(cp, MB_PRECOMPOSED, codepage_str.c_str(), + codepage_str.length(), nullptr, 0); + utf16_str = std::wstring(size, '\0'); + MultiByteToWideChar(cp, MB_PRECOMPOSED, codepage_str.c_str(), + codepage_str.length(), &utf16_str[0], size); + + return utf16_str; +} diff --git a/src/common/common.h b/src/common/common.h index f80278c..fed103c 100644 --- a/src/common/common.h +++ b/src/common/common.h @@ -20,21 +20,5 @@ #include -template -bool replace_all(T &str, const T &from, const T &to) -{ - bool replaced = false; - size_t start_pos = 0; - while ((start_pos = str.find(from, start_pos)) != T::npos) - { - str.replace(start_pos, from.length(), to); - start_pos += to.length(); - replaced = true; - } - return replaced; -} - -inline bool replace_all(std::string &str, const std::string &from, const std::string &to) -{ - return replace_all(str, from, to); -} +std::string str2utf8(const std::string &codepage_str, int cp = 0); +std::wstring str2utf16(const std::string &codepage_str, int cp = 0); diff --git a/src/db_add_language/db_add_language.cpp b/src/db_add_language/db_add_language.cpp index 696433b..27dc108 100644 --- a/src/db_add_language/db_add_language.cpp +++ b/src/db_add_language/db_add_language.cpp @@ -18,6 +18,8 @@ #include "../db_extractor/db.h" +#include + #include #include #include diff --git a/src/db_extractor/db.cpp b/src/db_extractor/db.cpp index a0ed7bd..e66f6ee 100644 --- a/src/db_extractor/db.cpp +++ b/src/db_extractor/db.cpp @@ -20,8 +20,6 @@ #include -#include - std::string getSqlType(FieldType type) { switch (type) @@ -152,30 +150,3 @@ void db::open(const path &p) for (auto &v : values) v.load_fields(t, b); } - -std::string str2utf8(const std::string &codepage_str, int cp) -{ - auto utf16_str = str2utf16(codepage_str, cp); - int utf8_size = WideCharToMultiByte(CP_UTF8, 0, utf16_str.c_str(), - utf16_str.length(), nullptr, 0, - nullptr, nullptr); - std::string utf8_str(utf8_size, '\0'); - WideCharToMultiByte(CP_UTF8, 0, utf16_str.c_str(), - utf16_str.length(), &utf8_str[0], utf8_size, - nullptr, nullptr); - return utf8_str; -} - -std::wstring str2utf16(const std::string &codepage_str, int cp) -{ - int size; - std::wstring utf16_str; - - size = MultiByteToWideChar(cp, MB_PRECOMPOSED, codepage_str.c_str(), - codepage_str.length(), nullptr, 0); - utf16_str = std::wstring(size, '\0'); - MultiByteToWideChar(cp, MB_PRECOMPOSED, codepage_str.c_str(), - codepage_str.length(), &utf16_str[0], size); - - return utf16_str; -} diff --git a/src/db_extractor/db.h b/src/db_extractor/db.h index c9e8d86..df207ee 100644 --- a/src/db_extractor/db.h +++ b/src/db_extractor/db.h @@ -98,6 +98,3 @@ struct db void load(const buffer &b); void open(const path &p); }; - -std::string str2utf8(const std::string &codepage_str, int cp = 0); -std::wstring str2utf16(const std::string &codepage_str, int cp = 0); diff --git a/src/db_extractor/db_extractor.cpp b/src/db_extractor/db_extractor.cpp index 7b69cab..20a8e82 100644 --- a/src/db_extractor/db_extractor.cpp +++ b/src/db_extractor/db_extractor.cpp @@ -21,6 +21,7 @@ #include #include +#include void create_sql(std::string path, const db &db) { diff --git a/src/mmo_extractor/mmo_extractor.cpp b/src/mmo_extractor/mmo_extractor.cpp index a04b7ea..f243870 100644 --- a/src/mmo_extractor/mmo_extractor.cpp +++ b/src/mmo_extractor/mmo_extractor.cpp @@ -120,26 +120,9 @@ void write_mmo(Storage *storage, const mmo_storage &s) auto this_map = storage->maps[map_id]; - auto check_val = [](auto &v) + auto calc_yaw = [](auto &v) { - if (v > 1) - { - v = v - floor(v); - std::cerr << /*object->name2 << */": yaw > 1\n"; - } - if (v < -1) - { - v = v - ceil(v); - std::cerr << /*object->name2 << */": yaw < -1\n"; - } - }; - - auto calc_yaw = [&check_val](auto &v) - { - //check_val(v[0].x); - //check_val(v[1].x); - - auto yaw = atan2(v[1].x, v[0].x); + auto yaw = atan2(v[1].x / v[2].z, v[0].x / v[2].z); yaw = RAD2GRAD(yaw); return -(yaw - 90); }; @@ -148,8 +131,9 @@ void write_mmo(Storage *storage, const mmo_storage &s) int exist = 0; for (auto &seg : s.objects.segments) { - if (seg->segment_type == ObjectType::BUILDING || - seg->segment_type == ObjectType::TOWER) + if (seg->segment_type == ObjectType::BUILDING || + seg->segment_type == ObjectType::TOWER || + 0) { SegmentObjects<::MapObject> *segment = (SegmentObjects<::MapObject> *)seg; std::set objs; @@ -175,6 +159,9 @@ void write_mmo(Storage *storage, const mmo_storage &s) } for (auto &object : segment->objects) { + // protect against nans + object->m_rotate_z[2].z = ASSIGN(object->m_rotate_z[2].z, 1); + MapBuilding mb; mb.text_id = object->name2; mb.building = storage->buildings[bld_ids[object->name1]]; @@ -184,29 +171,13 @@ void write_mmo(Storage *storage, const mmo_storage &s) mb.z = ASSIGN(object->position.z, 0); mb.roll = 0; mb.pitch = 0; - /*auto yaw = ASSIGN(object->m_rotate_z[0].x, 0); - if (yaw > 1) - { - yaw = yaw - floor(yaw); - std::cerr << object->name2 << ": yaw > 1\n"; - } - if (yaw < -1) - { - yaw = yaw - ceil(yaw); - std::cerr << object->name2 << ": yaw < -1\n"; - } - mb.yaw = acos(yaw); - RAD2GRAD(mb.yaw); - // wrong 1 - /*if (mb.yaw < 90) - mb.yaw += 90; - else - { - mb.yaw -= 90; - mb.yaw = -mb.yaw; - }*/ mb.yaw = calc_yaw(object->m_rotate_z); mb.scale = ASSIGN(object->m_rotate_z[2].z, 1); + if (mb.scale != 1) + { + int a = 5; + a++; + } auto i = find_if(storage->mapBuildings.begin(), storage->mapBuildings.end(), [&](const auto &p) { return *p.second == mb; @@ -228,7 +199,8 @@ void write_mmo(Storage *storage, const mmo_storage &s) if (seg->segment_type == ObjectType::TREE || seg->segment_type == ObjectType::STONE || seg->segment_type == ObjectType::LAMP || - seg->segment_type == ObjectType::BOUNDARY) + seg->segment_type == ObjectType::BOUNDARY || + 0) { SegmentObjects<::MapObject> *segment = (SegmentObjects<::MapObject> *)seg; std::set objs; @@ -252,6 +224,9 @@ void write_mmo(Storage *storage, const mmo_storage &s) } for (auto &object : segment->objects) { + // protect against nans + object->m_rotate_z[2].z = ASSIGN(object->m_rotate_z[2].z, 1); + detail::MapObject mb; mb.text_id = object->name2; mb.map = this_map; @@ -261,8 +236,13 @@ void write_mmo(Storage *storage, const mmo_storage &s) mb.z = ASSIGN(object->position.z, 0); mb.roll = 0; mb.pitch = 0; - mb.yaw = calc_yaw(object->m_rotate_z) - 90; + mb.yaw = calc_yaw(object->m_rotate_z); mb.scale = ASSIGN(object->m_rotate_z[2].z, 1); + if (mb.scale != 1) + { + int a = 5; + a++; + } auto i = find_if(storage->mapObjects.begin(), storage->mapObjects.end(), [&](const auto &p) { return *p.second == mb; diff --git a/src/mod_converter/fbx.cpp b/src/mod_converter/fbx.cpp index 29354ea..e24e851 100644 --- a/src/mod_converter/fbx.cpp +++ b/src/mod_converter/fbx.cpp @@ -298,7 +298,7 @@ bool CreateScene(model &model, const std::string &name, FbxManager* pSdkManager, // node FbxNode *node = FbxNode::Create(pScene, block_name.c_str()); node->SetNodeAttribute(m); - node->SetShadingMode(FbxNode::eTextureShading); // change?! was texture sh + //node->SetShadingMode(FbxNode::eTextureShading); // change?! was texture sh // vertices m->InitControlPoints(b.vertices.size()); diff --git a/src/mod_converter/mod_converter.cpp b/src/mod_converter/mod_converter.cpp index 2bbd8c3..a9cd6af 100644 --- a/src/mod_converter/mod_converter.cpp +++ b/src/mod_converter/mod_converter.cpp @@ -76,7 +76,14 @@ try if (f.has_extension()) continue; std::cout << "processing: " << f << "\n"; - convert_model(f); + try + { + convert_model(f); + } + catch (std::exception &e) + { + std::cout << "error: " << e.what() << "\n"; + } } } else diff --git a/src/mod_reader/mod_reader.cpp b/src/mod_reader/mod_reader.cpp index 68194b6..089a8ed 100644 --- a/src/mod_reader/mod_reader.cpp +++ b/src/mod_reader/mod_reader.cpp @@ -25,7 +25,7 @@ #include #include -#include "../mod_converter/model.h" +#include #include diff --git a/src/mod_converter/model.cpp b/src/model/model.cpp similarity index 92% rename from src/mod_converter/model.cpp rename to src/model/model.cpp index e6c988e..67e8773 100644 --- a/src/mod_converter/model.cpp +++ b/src/model/model.cpp @@ -30,8 +30,30 @@ //#include //#include +#include +#include + #include +template +inline bool replace_all(T &str, const T &from, const T &to) +{ + bool replaced = false; + size_t start_pos = 0; + while ((start_pos = str.find(from, start_pos)) != T::npos) + { + str.replace(start_pos, from.length(), to); + start_pos += to.length(); + replaced = true; + } + return replaced; +} + +inline bool replace_all(std::string &str, const std::string &from, const std::string &to) +{ + return replace_all(str, from, to); +} + using namespace std; const float scale_mult = 30.0f; @@ -116,16 +138,16 @@ std::string version(); // UE does not recognize russian strings in .obj string translate(const string &s) { - string o; - for (auto c : s) - { - auto i = transliteration.find(c); - if (i == transliteration.end()) - o += c; - else - o += i->second; - } - return o; + UErrorCode ec = UErrorCode::U_ZERO_ERROR; + auto tr = icu::Transliterator::createInstance("Latin-Cyrillic", UTransDirection::UTRANS_REVERSE, ec); + if (!tr || ec) + throw std::runtime_error("Cannot create translator, ec = " + std::to_string(ec)); + icu::UnicodeString s2(s.c_str()); + tr->transliterate(s2); + string s3; + s2.toUTF8String(s3); + replace_all(s3, " ", ""); + return s3; } template @@ -438,11 +460,11 @@ void block::loadPayload(const buffer &data) dm.load(data); string s = "extraction error: block #" + std::string(h.name); - if (!data.eof()) + /*if (!data.eof()) { cerr << s << "\n"; return; - } + }*/ // unknown how to proceed if (!data.eof() && triangles_mult_7) diff --git a/src/mod_converter/model.h b/src/model/model.h similarity index 100% rename from src/mod_converter/model.h rename to src/model/model.h diff --git a/src/script2txt/script.h b/src/script2txt/script.h index bd74745..7570310 100644 --- a/src/script2txt/script.h +++ b/src/script2txt/script.h @@ -23,6 +23,25 @@ #include #include +template +inline bool replace_all(T &str, const T &from, const T &to) +{ + bool replaced = false; + size_t start_pos = 0; + while ((start_pos = str.find(from, start_pos)) != T::npos) + { + str.replace(start_pos, from.length(), to); + start_pos += to.length(); + replaced = true; + } + return replaced; +} + +inline bool replace_all(std::string &str, const std::string &from, const std::string &to) +{ + return replace_all(str, from, to); +} + struct script { uint32_t file_size; @@ -55,7 +74,7 @@ struct script ss << std::hex << b.index() << " != " << std::hex << b.size(); throw std::logic_error(ss.str()); } - + fix_text(); }