diff --git a/src/common/mat.h b/src/common/mat.h index 30af547..4cca0d8 100644 --- a/src/common/mat.h +++ b/src/common/mat.h @@ -23,6 +23,7 @@ #include #include +#include template class mat @@ -93,3 +94,23 @@ void write_mat_bmp(const std::string &filename, const mat &m) fwrite(&m(0, 0), m.size() * sizeof(T), 1, f); fclose(f); } + +template +void write_mat_tga(const std::string &filename, const mat &m) +{ + FILE *f = fopen(filename.c_str(), "wb"); + if (f == nullptr) + return; + + tga t; + t.width = m.getWidth(); + t.height = m.getHeight(); + + // header + fwrite(&t, sizeof(tga), 1, f); + fwrite(t.label(), t.idlength, 1, f); + + // data + fwrite(&m(0, 0), m.size() * sizeof(T), 1, f); + fclose(f); +} diff --git a/src/common/tga.h b/src/common/tga.h new file mode 100644 index 0000000..860199f --- /dev/null +++ b/src/common/tga.h @@ -0,0 +1,52 @@ +#pragma once + +#include + +#include "buffer.h" + +#pragma pack(push, 1) + +// http://paulbourke.net/dataformats/tga/ +struct tga +{ + uint8_t idlength; // label length + uint8_t colourmaptype = 0; + uint8_t datatypecode = 2; + uint16_t colourmaporigin = 0; + uint16_t colourmaplength = 0; + uint8_t colourmapdepth = 0; + uint16_t x_origin = 0; + uint16_t y_origin = 0; + uint16_t width; + uint16_t height; + uint8_t bitsperpixel = 32; + uint8_t imagedescriptor = 0x28; + + tga() + { + idlength = strlen(label()); + } + constexpr const char *label() const + { + return "AIMTMConverter"; + } + + void write(buffer &b) + { + b.write(idlength); + b.write(colourmaptype); + b.write(datatypecode); + b.write(colourmaporigin); + b.write(colourmaplength); + b.write(colourmapdepth); + b.write(x_origin); + b.write(y_origin); + b.write(width); + b.write(height); + b.write(bitsperpixel); + b.write(imagedescriptor); + b.write(label(), idlength); + } +}; + +#pragma pack(pop) diff --git a/src/mmo_extractor/mmo_extractor.cpp b/src/mmo_extractor/mmo_extractor.cpp index 99ca3a0..2fac48b 100644 --- a/src/mmo_extractor/mmo_extractor.cpp +++ b/src/mmo_extractor/mmo_extractor.cpp @@ -36,14 +36,13 @@ #include #define RAD2GRAD(x) (x) = (x) / M_PI * 180.0 - -using namespace std; +#define ASSIGN(x, d) isnan(x) ? d : x std::string prefix; struct storage { - string name; + std::string name; Objects objects; MechGroups mechGroups; MapGoods mapGoods; @@ -74,14 +73,14 @@ struct storage if (!b.eof()) { - stringstream ss; - ss << hex << b.index() << " != " << hex << b.size(); + std::stringstream ss; + ss << std::hex << b.index() << " != " << std::hex << b.size(); throw std::logic_error(ss.str()); } } }; -storage read_mmo(string fn) +storage read_mmo(std::string fn) { buffer f(readFile(fn)); storage s; @@ -90,7 +89,7 @@ storage read_mmo(string fn) return s; } -void write_mmo(string db, const storage &s) +void write_mmo(std::string db, const storage &s) { using namespace polygon4; using namespace polygon4::detail; @@ -104,12 +103,12 @@ void write_mmo(string db, const storage &s) auto p2 = s.name.rfind('/'); if (p2 == -1) p2 = 0; - int p = max(p1, p2); - string map_name = s.name.substr(p + 1); + int p = std::max(p1, p2); + std::string map_name = s.name.substr(p + 1); map_name = map_name.substr(0, map_name.find('.')); if (!prefix.empty()) map_name = prefix + "." + map_name; - transform(map_name.begin(), map_name.end(), map_name.begin(), ::tolower); + std::transform(map_name.begin(), map_name.end(), map_name.begin(), ::tolower); int map_id = 0; for (auto &m : storage->maps) @@ -129,19 +128,21 @@ void write_mmo(string db, const storage &s) auto this_map = storage->maps[map_id]; + int inserted = 0; + int exist = 0; for (auto &seg : s.objects.segments) { if (seg->segment_type == ObjectType::BUILDING || seg->segment_type == ObjectType::TOWER) { SegmentObjects<::MapObject> *segment = (SegmentObjects<::MapObject> *)seg; - set objs; - std::map bld_ids; + std::set objs; + std::map bld_ids; for (auto &object : segment->objects) objs.insert(object->name1); for (auto &o : objs) { - auto iter = find_if(storage->buildings.begin(), storage->buildings.end(), [&](const auto &p) + auto iter = std::find_if(storage->buildings.begin(), storage->buildings.end(), [&](const auto &p) { return p.second->text_id == o; }); @@ -152,7 +153,9 @@ void write_mmo(string db, const storage &s) bld_ids[o] = bld->getId(); } else + { bld_ids[o] = iter->getId(); + } } for (auto &object : segment->objects) { @@ -160,14 +163,19 @@ void write_mmo(string db, const storage &s) mb.text_id = object->name2; mb.building = storage->buildings[bld_ids[object->name1]]; mb.map = this_map; - mb.x = object->position.x; - mb.y = object->position.y; - mb.z = object->position.z; + mb.x = ASSIGN(object->position.x, 0); + mb.y = ASSIGN(object->position.y, 0); + mb.z = ASSIGN(object->position.z, 0); mb.roll = 0; mb.pitch = 0; - mb.yaw = acos(object->m_rotate_z[0].x); + auto yaw = ASSIGN(object->m_rotate_z[0].x, 0); + if (yaw > 1) + yaw = yaw - floor(yaw); + if (yaw < -1) + yaw = yaw - ceil(yaw); + mb.yaw = acos(yaw); RAD2GRAD(mb.yaw); - mb.scale = object->m_rotate_z[2].z; + mb.scale = ASSIGN(object->m_rotate_z[2].z, 1); auto i = find_if(storage->mapBuildings.begin(), storage->mapBuildings.end(), [&](const auto &p) { return *p.second.get() == mb; @@ -176,7 +184,12 @@ void write_mmo(string db, const storage &s) { auto mb2 = storage->addMapBuilding(storage->maps[map_id].get()); mb.setId(mb2->getId()); - *mb2.ptr = mb; + *mb2 = mb; + inserted++; + } + else + { + exist++; } } } @@ -186,8 +199,8 @@ void write_mmo(string db, const storage &s) seg->segment_type == ObjectType::BOUNDARY) { SegmentObjects<::MapObject> *segment = (SegmentObjects<::MapObject> *)seg; - set objs; - std::map bld_ids; + std::set objs; + std::map bld_ids; for (auto &object : segment->objects) objs.insert(object->name1); for (auto &o : objs) @@ -211,14 +224,19 @@ void write_mmo(string db, const storage &s) mb.text_id = object->name2; mb.map = this_map; mb.object = storage->objects[bld_ids[object->name1]]; - mb.x = object->position.x; - mb.y = object->position.y; - mb.z = object->position.z; + mb.x = ASSIGN(object->position.x, 0); + mb.y = ASSIGN(object->position.y, 0); + mb.z = ASSIGN(object->position.z, 0); mb.roll = 0; mb.pitch = 0; - mb.yaw = acos(object->m_rotate_z[0].x); + auto yaw = ASSIGN(object->m_rotate_z[0].x, 0); + if (yaw > 1) + yaw = yaw - floor(yaw); + if (yaw < -1) + yaw = yaw - ceil(yaw); + mb.yaw = acos(yaw); RAD2GRAD(mb.yaw); - mb.scale = object->m_rotate_z[2].z; + mb.scale = ASSIGN(object->m_rotate_z[2].z, 1); auto i = find_if(storage->mapObjects.begin(), storage->mapObjects.end(), [&](const auto &p) { return *p.second.get() == mb; @@ -227,12 +245,19 @@ void write_mmo(string db, const storage &s) { auto mb2 = storage->addMapObject(storage->maps[map_id].get()); mb.setId(mb2->getId()); - *mb2.ptr = mb; + *mb2 = mb; + inserted++; + } + else + { + exist++; } } } } - storage->save(); + if (inserted) + storage->save(); + std::cout << "inserted: " << inserted << ", exist: " << exist << "\n"; } int main(int argc, char *argv[]) @@ -240,7 +265,7 @@ try { if (argc != 4) { - cout << "Usage:\n" << argv[0] << " db.sqlite file.mmo prefix" << "\n"; + std::cout << "Usage:\n" << argv[0] << " db.sqlite file.mmo prefix" << "\n"; return 1; } prefix = argv[3]; diff --git a/src/mod_converter/mod_converter.cpp b/src/mod_converter/mod_converter.cpp index 4659601..ff73fae 100644 --- a/src/mod_converter/mod_converter.cpp +++ b/src/mod_converter/mod_converter.cpp @@ -121,24 +121,20 @@ catch (std::runtime_error &e) if (silent) return 1; string error; - if (argv[1]) - error += argv[1]; + error += filename; error += "\n"; error += "fatal error: "; error += e.what(); error += "\n"; - if (argv[1]) - { - ofstream ofile(string(argv[1]) + ".error.txt"); - ofile << error; - } + ofstream ofile(filename + ".error.txt"); + ofile << error; return 1; } catch (std::exception &e) { if (silent) return 1; - printf("%s\n", argv[1]); + printf("%s\n", filename.c_str()); printf("error: %s\n", e.what()); return 1; } @@ -146,7 +142,7 @@ catch (...) { if (silent) return 1; - printf("%s\n", argv[1]); + printf("%s\n", filename.c_str()); printf("error: unknown exception\n"); return 1; } diff --git a/src/tm_converter/tm_converter.cpp b/src/tm_converter/tm_converter.cpp index bf7cbc9..26d9e2b 100644 --- a/src/tm_converter/tm_converter.cpp +++ b/src/tm_converter/tm_converter.cpp @@ -61,27 +61,15 @@ void tm2tga(string fn) d.width = width; d.height = height; d.load_blocks(src); - write_mat_bmp(fn + ".bmp", d.unpack_tm()); + write_mat_tga(fn + ".tga", d.unpack_tm()); } else { - // http://paulbourke.net/dataformats/tga/ buffer dst; - dst.write(uint8_t(0xE)); // idlength (comment length) - dst.write(uint8_t(0)); // colourmaptype - dst.write(uint8_t(2)); // datatypecode - dst.write(uint16_t(0)); // colourmaporigin - dst.write(uint16_t(0)); // colourmaplength - dst.write(uint8_t(0)); // colourmapdepth - dst.write(uint16_t(0)); // x_origin - dst.write(uint16_t(0)); // y_origin - dst.write(uint16_t(width)); // width - dst.write(uint16_t(height)); // height - dst.write(uint8_t(32)); // bitsperpixel - dst.write(uint8_t(0x28)); // imagedescriptor - - const char *label = "AIMTMConverter"; - dst.write(label, strlen(label)); + tga t; + t.width = width; + t.height = height; + t.write(dst); convert_simple(dst, src, width, height); transform(fn.begin(), fn.end(), fn.begin(), ::tolower);