diff --git a/src/common/mat.h b/src/common/mat.h index 1685301..2821865 100644 --- a/src/common/mat.h +++ b/src/common/mat.h @@ -114,40 +114,10 @@ public: return m; } -#ifdef HAVE_OPENCV_IMGCODECS - operator cv::Mat() const - { - return flip().toCvMat(); - } -#endif - private: std::vector data; int width; int height; - -#ifdef HAVE_OPENCV_IMGCODECS - cv::Mat toCvMat() const - { - if constexpr (std::is_same_v) - { - int cols = width; - int rows = height; - cv::Mat m(height, width, CV_8UC3); - for (int row = 0; row < rows; row++) - { - for (int col = 0; col < cols; col++) - { - auto &o = operator()(row * cols + col); - m.ptr(row)[3 * col + 2] = (o >> 16) & 0xFF; - m.ptr(row)[3 * col + 1] = (o >> 8) & 0xFF; - m.ptr(row)[3 * col + 0] = (o >> 0) & 0xFF; - } - } - return m; - } - } -#endif }; inline void write_mat_bmp(const path &filename, int width, int height, int bits, const uint8_t *b, size_t s) diff --git a/src/mmp_extractor/mmp.cpp b/src/mmp_extractor/mmp.cpp index e3351d9..9b99b3a 100644 --- a/src/mmp_extractor/mmp.cpp +++ b/src/mmp_extractor/mmp.cpp @@ -18,10 +18,11 @@ #define NOMINMAX -#include #include "mmp.h" #include +#include +#include #include #include @@ -29,6 +30,8 @@ #include #include +cl::list extend("e", cl::desc("try to extend map for ue4"), cl::value_desc(" "), cl::multi_val(2)); + void water_segment::load(const buffer &b) { wg.load(b); @@ -139,6 +142,11 @@ void mmp::loadTextureNames(const path &fn) } } +static bool is_power_of_two(int x) +{ + return x != 0 && (x & (x - 1)) == 0; +} + void mmp::process() { for (auto &s : segments) @@ -172,8 +180,47 @@ void mmp::process() alpha_maps[t.second.g] = mat(h.width, h.length); } + auto wnew = h.width; + auto lnew = h.length; + + if (extend.empty()) + { + // defaults + //extend.push_back(63); + //extend.push_back(4); + extend.push_back(127); + extend.push_back(1); + } + + if (!extend.empty()) + { + int quads_per_sect = extend[0] + 1; + int sections_per_comp = extend[1]; + + if (!is_power_of_two(quads_per_sect)) + throw SW_RUNTIME_ERROR("quads per section must be 2^n-1"); + if (sections_per_comp != 1 && sections_per_comp != 4) + throw SW_RUNTIME_ERROR("sections per component must be 1 or 4"); + + if (sections_per_comp > 1) + sections_per_comp = sqrt(sections_per_comp); + + double mult = quads_per_sect * sections_per_comp - sections_per_comp; + int wcomps = ceil(h.width / mult); + int lcomps = ceil(h.length / mult); + + if (wcomps * lcomps > 1024) + { + throw SW_RUNTIME_ERROR("ue4 allows maximum 1024 components while you have: " + + std::to_string(wcomps) + "x" + std::to_string(lcomps) + " = " + std::to_string(wcomps * lcomps) + " components"); + } + + wnew = wcomps * mult + 1; + lnew = lcomps * mult + 1; + } + // merge - heightmap = decltype(heightmap)(h.width, h.length); + heightmap = decltype(heightmap)(wnew, lnew); heightmap32 = decltype(heightmap32)(h.width, h.length); //heightmap_segmented = decltype(heightmap)(segment::len, h.length); texmap = decltype(texmap)(h.width, h.length); @@ -226,7 +273,9 @@ void mmp::process() alpha_maps.erase(0); scale16 = 0xffff / (h_max - h_min); - const int unreal_koef = 51200; // 51300? + // 51300 = -25600..25600? or 51200 = -25500..25600 + // seems like 51300 + const int unreal_koef = 51300; const int aim_koef = 10; const double diff = h_max - h_min; scale = aim_koef * diff / unreal_koef; @@ -297,6 +346,40 @@ void mmp::writeTexturesList() } } +static cv::Mat toCvMat(const mat &in) +{ + int cols = in.getWidth(); + int rows = in.getHeight(); + cv::Mat m(in.getHeight(), in.getWidth(), CV_16UC1); + for (int row = 0; row < rows; row++) + { + for (int col = 0; col < cols; col++) + { + auto &o = in(row * cols + col); + m.ptr(row)[col] = o; + } + } + return m; +} + +static cv::Mat toCvMat(const mat &in) +{ + int cols = in.getWidth(); + int rows = in.getHeight(); + cv::Mat m(in.getHeight(), in.getWidth(), CV_8UC3); + for (int row = 0; row < rows; row++) + { + for (int col = 0; col < cols; col++) + { + auto &o = in(row * cols + col); + m.ptr(row)[3 * col + 2] = (o >> 16) & 0xFF; + m.ptr(row)[3 * col + 1] = (o >> 8) & 0xFF; + m.ptr(row)[3 * col + 0] = (o >> 0) & 0xFF; + } + } + return m; +} + void mmp::writeHeightMap() { auto write_hm = [this](const String &name, const auto &v, auto sz) @@ -310,7 +393,9 @@ void mmp::writeHeightMap() fclose(f); }; - write_hm(".heightmap16.r16", heightmap, sizeof(decltype(heightmap)::type)); + cv::imwrite((path(filename) += ".heightmap16.png").string(), toCvMat(heightmap)); + + //write_hm(".heightmap16.r16", heightmap, sizeof(decltype(heightmap)::type)); write_hm(".heightmap32.r32", heightmap32, sizeof(decltype(heightmap32)::type)); } @@ -386,7 +471,7 @@ void mmp::writeSplitColormap() const for (auto &pixel : m) pixel = pixel == color ? 0x0000FF00 : 0; std::cout << "\r[" << i << "/" << colors.size() << "] Processing color " << ss.str(); - cv::imwrite(fn.u8string(), cv::Mat(m)); + cv::imwrite(fn.u8string(), toCvMat(m)); } } diff --git a/src/mmp_extractor/mmp.h b/src/mmp_extractor/mmp.h index b62f210..bded21a 100644 --- a/src/mmp_extractor/mmp.h +++ b/src/mmp_extractor/mmp.h @@ -21,6 +21,7 @@ #include #include +#include #include #include diff --git a/src/mmp_extractor/mmp_extractor.cpp b/src/mmp_extractor/mmp_extractor.cpp index c29e271..f36e0a6 100644 --- a/src/mmp_extractor/mmp_extractor.cpp +++ b/src/mmp_extractor/mmp_extractor.cpp @@ -16,7 +16,6 @@ * along with this program. If not, see . */ -#include #include "mmp.h" #include @@ -37,10 +36,11 @@ int main(int argc, char *argv[]) cl::opt p(cl::Positional, cl::desc(""), cl::Required); cl::opt texture_ids(cl::Positional, cl::desc("")); cl::opt split_colormap("split_colormap", cl::desc("split colormap into separate images")); + cl::opt tex_al("texture_alphamaps", cl::desc("write texture alpha maps")); cl::ParseCommandLineOptions(argc, argv); - auto func = [&texture_ids, &split_colormap](auto &p) + auto func = [&texture_ids, &split_colormap, &tex_al](auto &p) { mmp m; if (!texture_ids.empty()) @@ -52,7 +52,8 @@ int main(int argc, char *argv[]) m.writeHeightMap(); //m.writeHeightMapSegmented(); m.writeTextureMap(); - m.writeTextureAlphaMaps(); + if (tex_al) + m.writeTextureAlphaMaps(); m.writeTextureMapColored(); m.writeColorMap(); m.writeShadowMap(); diff --git a/src/unpaker/decode.h b/src/unpaker/decode.h index 3a3aa19..6485611 100644 --- a/src/unpaker/decode.h +++ b/src/unpaker/decode.h @@ -1,5 +1,9 @@ #pragma once +#ifdef _WIN64 +#error "not available in 64-bit mode" +#endif + #define _BYTE uint8_t #define _WORD uint16_t #define _DWORD uint32_t diff --git a/src/unpaker/unpaker.cpp b/src/unpaker/unpaker.cpp index 7be1b05..eba912e 100644 --- a/src/unpaker/unpaker.cpp +++ b/src/unpaker/unpaker.cpp @@ -45,7 +45,7 @@ int main(int argc, char *argv[]) { if (argc != 2) { - cout << "Usage: " << argv[0] << " archive.pak" << "\n"; + cerr << "Usage: " << argv[0] << " archive.pak" << "\n"; return 1; } unpak(argv[1]); diff --git a/sw.cpp b/sw.cpp index fcef4b6..eedb2b5 100644 --- a/sw.cpp +++ b/sw.cpp @@ -42,7 +42,8 @@ void build(Solution &s) add_exe_with_common("tm_converter"); add_exe("name_generator"); add_exe_with_common("save_loader"); - add_exe("unpaker"); + if (s.Settings.TargetOS.Arch == ArchType::x86) + add_exe("unpaker"); // 32-bit only // not so simple targets auto &script2txt = tools.addStaticLibrary("script2txt");