mirror of
https://github.com/aimrebirth/tools.git
synced 2026-04-14 17:33:25 +00:00
Add DXT5 converter. Complete tm converter, mmm extractor. Add boundary building objects from AIM2.
This commit is contained in:
parent
1a237c283d
commit
5f2b0334b2
24 changed files with 429 additions and 272 deletions
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "buffer.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
62
src/common/color.h
Normal file
62
src/common/color.h
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* AIM tools
|
||||
* Copyright (C) 2015 lzwdgc
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef uint16_t color_rgb565;
|
||||
|
||||
struct color
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8_t b;
|
||||
uint8_t g;
|
||||
uint8_t r;
|
||||
uint8_t a;
|
||||
};
|
||||
uint8_t byte[4];
|
||||
uint32_t data;
|
||||
};
|
||||
|
||||
color() {}
|
||||
color(uint8_t b, uint8_t g, uint8_t r, uint8_t a)
|
||||
: b(b), g(g), r(r), a(a)
|
||||
{}
|
||||
color(const color_rgb565 &c)
|
||||
{
|
||||
static uint8_t Table5[] = {
|
||||
0, 8, 16, 25, 33, 41, 49, 58, 66, 74, 82, 90, 99, 107, 115, 123, 132,
|
||||
140, 148, 156, 165, 173, 181, 189, 197, 206, 214, 222, 230, 239, 247, 255 };
|
||||
static uint8_t Table6[] = {
|
||||
0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 45, 49, 53, 57, 61, 65, 69,
|
||||
73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 130, 134, 138,
|
||||
142, 146, 150, 154, 158, 162, 166, 170, 174, 178, 182, 186, 190, 194, 198,
|
||||
202, 206, 210, 215, 219, 223, 227, 231, 235, 239, 243, 247, 251, 255 };
|
||||
|
||||
b = Table5[c & 0x1F];
|
||||
g = Table6[(c >> 5) & 0x3F];
|
||||
r = Table5[(c >> 11) & 0x1F];
|
||||
}
|
||||
|
||||
operator uint32_t() const
|
||||
{
|
||||
return data;
|
||||
}
|
||||
};
|
||||
164
src/common/dxt5.h
Normal file
164
src/common/dxt5.h
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
* AIM tools
|
||||
* Copyright (C) 2015 lzwdgc
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "buffer.h"
|
||||
#include "color.h"
|
||||
#include "mat.h"
|
||||
|
||||
struct dxt5_block
|
||||
{
|
||||
union
|
||||
{
|
||||
uint64_t alpha_part;
|
||||
uint8_t a[8];
|
||||
};
|
||||
union
|
||||
{
|
||||
uint64_t color_part;
|
||||
uint16_t c[4];
|
||||
};
|
||||
|
||||
//
|
||||
uint8_t alpha_table[8];
|
||||
color color_table[4];
|
||||
union
|
||||
{
|
||||
color pixels[16];
|
||||
color pixel_mat[4][4];
|
||||
};
|
||||
|
||||
dxt5_block() {}
|
||||
void load(buffer &b)
|
||||
{
|
||||
READ(b, alpha_part);
|
||||
READ(b, color_part);
|
||||
}
|
||||
void unpack()
|
||||
{
|
||||
// alpha
|
||||
auto &a = alpha_table;
|
||||
a[0] = this->a[0];
|
||||
a[1] = this->a[1];
|
||||
if (a[0] > a[1])
|
||||
{
|
||||
a[2] = double(6 * a[0] + 1 * a[1]) / 7.0;
|
||||
a[3] = double(5 * a[0] + 2 * a[1]) / 7.0;
|
||||
a[4] = double(4 * a[0] + 3 * a[1]) / 7.0;
|
||||
a[5] = double(3 * a[0] + 4 * a[1]) / 7.0;
|
||||
a[6] = double(2 * a[0] + 5 * a[1]) / 7.0;
|
||||
a[7] = double(1 * a[0] + 6 * a[1]) / 7.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
a[2] = double(4 * a[0] + 1 * a[1]) / 5.0;
|
||||
a[3] = double(3 * a[0] + 2 * a[1]) / 5.0;
|
||||
a[4] = double(2 * a[0] + 3 * a[1]) / 5.0;
|
||||
a[5] = double(1 * a[0] + 4 * a[1]) / 5.0;
|
||||
a[6] = 0;
|
||||
a[7] = 255;
|
||||
}
|
||||
|
||||
// color
|
||||
auto &c = color_table;
|
||||
c[0] = color(this->c[0]);
|
||||
c[1] = color(this->c[1]);
|
||||
if (this->c[0] > this->c[1])
|
||||
{
|
||||
c[2] = interpolate(c[0], c[1], 2.f / 3.f);
|
||||
c[3] = interpolate(c[0], c[1], 1.f / 3.f);
|
||||
}
|
||||
else
|
||||
{
|
||||
c[2] = interpolate(c[0], c[1], 1.f / 2.f);
|
||||
c[3].data = 0;
|
||||
}
|
||||
|
||||
// result
|
||||
for (int p = 0; p < 16; p++)
|
||||
{
|
||||
pixels[p] = c[(color_part >> (32 + p * 2)) & 0b11];
|
||||
pixels[p].a = a[(alpha_part >> (16 + p * 3)) & 0b111];
|
||||
}
|
||||
}
|
||||
color interpolate(color c0, color c1, float m)
|
||||
{
|
||||
color r;
|
||||
for (int i = 0; i < 4; i++)
|
||||
r.byte[i] = c0.byte[i] * m + c1.byte[i] * (1 - m);
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
struct dxt5
|
||||
{
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
std::vector<dxt5_block> blocks;
|
||||
|
||||
void load(buffer &b)
|
||||
{
|
||||
READ(b, width);
|
||||
READ(b, height);
|
||||
load_blocks(b);
|
||||
}
|
||||
void load_blocks(buffer &b)
|
||||
{
|
||||
blocks.resize(width * height / 16);
|
||||
for (auto &d : blocks)
|
||||
{
|
||||
d.load(b);
|
||||
d.unpack();
|
||||
}
|
||||
}
|
||||
mat<uint32_t> unpack_mmm()
|
||||
{
|
||||
mat<uint32_t> m(width, height);
|
||||
auto big_xsegs = width / 64;
|
||||
auto big_ysegs = height / 64;
|
||||
for (int seg = 0; seg < blocks.size(); seg++)
|
||||
{
|
||||
auto &d = blocks[seg];
|
||||
int big_seg = seg / 256;
|
||||
auto big_xseg = big_seg % big_xsegs;
|
||||
auto big_yseg = big_seg / big_xsegs;
|
||||
auto xseg = seg % 16 + big_xseg * 16;
|
||||
auto yseg = seg % 256 / 16 + big_yseg * 16;
|
||||
for (int i = 0; i < 4; i++)
|
||||
memcpy(&m(height - 1 - (yseg * 4 + i), xseg * 4), d.pixel_mat[i], 16);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
mat<uint32_t> unpack_tm()
|
||||
{
|
||||
mat<uint32_t> m(width, height);
|
||||
auto xsegs = width / 4;
|
||||
for (int seg = 0; seg < blocks.size(); seg++)
|
||||
{
|
||||
auto &d = blocks[seg];
|
||||
auto xseg = seg % xsegs;
|
||||
auto yseg = seg / xsegs;
|
||||
for (int i = 0; i < 4; i++)
|
||||
memcpy(&m(height - 1 - (yseg * 4 + i), xseg * 4), d.pixel_mat[i], 16);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
};
|
||||
95
src/common/mat.h
Normal file
95
src/common/mat.h
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* AIM tools
|
||||
* Copyright (C) 2015 lzwdgc
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
|
||||
#include <bmp.h>
|
||||
|
||||
template <class T>
|
||||
class mat
|
||||
{
|
||||
public:
|
||||
using type = T;
|
||||
|
||||
public:
|
||||
mat(int w = 0, int h = 0)
|
||||
{
|
||||
width = w < 0 ? 0 : w;
|
||||
height = h < 0 ? 0 : h;
|
||||
data.resize(width * height, T());
|
||||
}
|
||||
|
||||
T &operator()(int row, int col)
|
||||
{
|
||||
assert(!(row >= height || col >= width || row < 0 || col < 0));
|
||||
return data[row * width + col];
|
||||
}
|
||||
const T &operator()(int row, int col) const
|
||||
{
|
||||
return (*const_cast<mat *>(this))(row, col);
|
||||
}
|
||||
|
||||
void clean()
|
||||
{
|
||||
std::fill(data.begin(), data.end(), T());
|
||||
}
|
||||
|
||||
int getWidth() const { return width; }
|
||||
int getHeight() const { return height; }
|
||||
int size() const { return width * height; }
|
||||
int getPos(const T *const elem) const { return elem - &data[0]; }
|
||||
const std::vector<T> &getData() const { return data; }
|
||||
std::vector<T> &getData() { return data; }
|
||||
|
||||
private:
|
||||
std::vector<T> data;
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
void write_mat_bmp(const std::string &filename, const mat<T> &m)
|
||||
{
|
||||
FILE *f = fopen(filename.c_str(), "wb");
|
||||
if (f == nullptr)
|
||||
return;
|
||||
BITMAPFILEHEADER h = { 0 };
|
||||
h.bfType = 0x4D42;
|
||||
h.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO) + m.size() * sizeof(T);
|
||||
h.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO);
|
||||
BITMAPINFO i = { 0 };
|
||||
i.bmiHeader.biSize = sizeof(i.bmiHeader);
|
||||
i.bmiHeader.biWidth = m.getWidth();
|
||||
i.bmiHeader.biHeight = m.getHeight();
|
||||
i.bmiHeader.biPlanes = 1;
|
||||
i.bmiHeader.biBitCount = sizeof(T) * 8;
|
||||
i.bmiHeader.biCompression = 0;
|
||||
i.bmiHeader.biSizeImage = 0;
|
||||
i.bmiHeader.biXPelsPerMeter = 0;
|
||||
i.bmiHeader.biYPelsPerMeter = 0;
|
||||
i.bmiHeader.biClrUsed = 0;
|
||||
i.bmiHeader.biClrImportant = 0;
|
||||
fwrite(&h, sizeof(BITMAPFILEHEADER), 1, f);
|
||||
fwrite(&i, sizeof(BITMAPINFO), 1, f);
|
||||
fwrite(&m(0, 0), m.size() * sizeof(T), 1, f);
|
||||
fclose(f);
|
||||
}
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
#include "db.h"
|
||||
|
||||
#include <common.h>
|
||||
#include <buffer.h>
|
||||
|
||||
string getSqlType(FieldType type)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <common.h>
|
||||
#include <buffer.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
#include <Windows.h>
|
||||
|
||||
#include <common.h>
|
||||
#include <buffer.h>
|
||||
|
||||
void open_db(string path, db &db)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,29 +0,0 @@
|
|||
/*
|
||||
* AIM mmm_extractor
|
||||
* Copyright (C) 2015 lzwdgc
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "mmm.h"
|
||||
|
||||
void mmm::load(buffer &b)
|
||||
{
|
||||
READ(b, unk1);
|
||||
READ(b, unk2);
|
||||
READ(b, width);
|
||||
READ(b, height);
|
||||
data.resize(width * height / 16);
|
||||
READ_N(b, data[0], data.size() * 16);
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* AIM mmm_extractor
|
||||
* Copyright (C) 2015 lzwdgc
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <common.h>
|
||||
|
||||
struct dxt5_record
|
||||
{
|
||||
char unk[0x10];
|
||||
};
|
||||
|
||||
struct mmm
|
||||
{
|
||||
uint32_t unk1;
|
||||
uint32_t unk2;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
std::vector<dxt5_record> data;
|
||||
|
||||
void load(buffer &b);
|
||||
};
|
||||
|
|
@ -21,10 +21,25 @@
|
|||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include "mmm.h"
|
||||
#include <buffer.h>
|
||||
#include <dxt5.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
struct mmm
|
||||
{
|
||||
uint32_t unk1;
|
||||
uint32_t unk2;
|
||||
dxt5 data;
|
||||
|
||||
void load(buffer &b)
|
||||
{
|
||||
READ(b, unk1);
|
||||
READ(b, unk2);
|
||||
data.load(b);
|
||||
}
|
||||
};
|
||||
|
||||
mmm read_mmm(string fn)
|
||||
{
|
||||
buffer b(readFile(fn));
|
||||
|
|
@ -33,8 +48,8 @@ mmm read_mmm(string fn)
|
|||
|
||||
if (!b.eof())
|
||||
{
|
||||
stringstream ss;
|
||||
ss << hex << b.index() << " != " << hex << b.size();
|
||||
std::stringstream ss;
|
||||
ss << std::hex << b.index() << " != " << hex << b.size();
|
||||
throw std::logic_error(ss.str());
|
||||
}
|
||||
return m;
|
||||
|
|
@ -43,16 +58,13 @@ mmm read_mmm(string fn)
|
|||
int main(int argc, char *argv[])
|
||||
try
|
||||
{
|
||||
#ifdef NDEBUG
|
||||
if (argc != 2)
|
||||
{
|
||||
cout << "Usage:\n" << argv[0] << " file.mmp" << "\n";
|
||||
return 1;
|
||||
}
|
||||
read_mmm(argv[1]);
|
||||
#else
|
||||
auto loc1 = read_mmm("h:\\Games\\AIM\\data\\minimaps.pak.dir\\location1.mmm");
|
||||
#endif
|
||||
auto m = read_mmm(argv[1]);
|
||||
write_mat_bmp(std::string(argv[1]) + ".bmp", m.data.unpack_mmm());
|
||||
return 0;
|
||||
}
|
||||
catch (std::exception &e)
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
#include <Polygon4/Storage.h>
|
||||
|
||||
#include <common.h>
|
||||
#include <buffer.h>
|
||||
|
||||
#define RAD2GRAD(x) (x) = (x) / M_PI * 180.0
|
||||
|
||||
|
|
@ -132,14 +132,14 @@ void write_mmo(string db, const storage &s)
|
|||
if (seg->segment_type == SegmentType::SHELL ||
|
||||
seg->segment_type == SegmentType::TOWER)
|
||||
{
|
||||
SegmentObjects<Shell> *segment = (SegmentObjects<Shell> *)seg;
|
||||
SegmentObjects<::MapObject> *segment = (SegmentObjects<::MapObject> *)seg;
|
||||
set<string> objs;
|
||||
std::map<string, int> bld_ids;
|
||||
for (auto &object : segment->objects)
|
||||
objs.insert(object.name1);
|
||||
objs.insert(object->name1);
|
||||
for (auto &o : objs)
|
||||
{
|
||||
auto iter = find_if(storage->buildings.begin(), storage->buildings.end(), [&](const decltype(Storage::buildings)::value_type &p)
|
||||
auto iter = find_if(storage->buildings.begin(), storage->buildings.end(), [&](const auto &p)
|
||||
{
|
||||
return p.second->text_id == o;
|
||||
});
|
||||
|
|
@ -155,18 +155,18 @@ void write_mmo(string db, const storage &s)
|
|||
for (auto &object : segment->objects)
|
||||
{
|
||||
MapBuilding mb;
|
||||
mb.text_id = object.name2;
|
||||
mb.building = storage->buildings[bld_ids[object.name1]];
|
||||
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 = object->position.x;
|
||||
mb.y = object->position.y;
|
||||
mb.z = object->position.z;
|
||||
mb.roll = 0;
|
||||
mb.pitch = 0;
|
||||
mb.yaw = acos(object.m_rotate_z[0].x);
|
||||
mb.yaw = acos(object->m_rotate_z[0].x);
|
||||
RAD2GRAD(mb.yaw);
|
||||
mb.scale = object.m_rotate_z[2].z;
|
||||
auto i = find_if(storage->mapBuildings.begin(), storage->mapBuildings.end(), [&](const decltype(Storage::mapBuildings)::value_type &p)
|
||||
mb.scale = object->m_rotate_z[2].z;
|
||||
auto i = find_if(storage->mapBuildings.begin(), storage->mapBuildings.end(), [&](const auto &p)
|
||||
{
|
||||
return *p.second.get() == mb;
|
||||
});
|
||||
|
|
@ -180,16 +180,17 @@ void write_mmo(string db, const storage &s)
|
|||
}
|
||||
if (seg->segment_type == SegmentType::SURFACE ||
|
||||
seg->segment_type == SegmentType::STONE ||
|
||||
seg->segment_type == SegmentType::EXPLOSION)
|
||||
seg->segment_type == SegmentType::EXPLOSION ||
|
||||
seg->segment_type == SegmentType::BOUNDARY)
|
||||
{
|
||||
SegmentObjects<Surface> *segment = (SegmentObjects<Surface> *)seg;
|
||||
SegmentObjects<::MapObject> *segment = (SegmentObjects<::MapObject> *)seg;
|
||||
set<string> objs;
|
||||
std::map<string, int> bld_ids;
|
||||
for (auto &object : segment->objects)
|
||||
objs.insert(object.name1);
|
||||
objs.insert(object->name1);
|
||||
for (auto &o : objs)
|
||||
{
|
||||
auto iter = find_if(storage->objects.begin(), storage->objects.end(), [&](const decltype(Storage::objects)::value_type &p)
|
||||
auto iter = find_if(storage->objects.begin(), storage->objects.end(), [&](const auto &p)
|
||||
{
|
||||
return p.second->text_id == o;
|
||||
});
|
||||
|
|
@ -205,18 +206,18 @@ void write_mmo(string db, const storage &s)
|
|||
for (auto &object : segment->objects)
|
||||
{
|
||||
detail::MapObject mb;
|
||||
mb.text_id = object.name2;
|
||||
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.object = storage->objects[bld_ids[object->name1]];
|
||||
mb.x = object->position.x;
|
||||
mb.y = object->position.y;
|
||||
mb.z = object->position.z;
|
||||
mb.roll = 0;
|
||||
mb.pitch = 0;
|
||||
mb.yaw = acos(object.m_rotate_z[0].x);
|
||||
mb.yaw = acos(object->m_rotate_z[0].x);
|
||||
RAD2GRAD(mb.yaw);
|
||||
mb.scale = object.m_rotate_z[2].z;
|
||||
auto i = find_if(storage->mapObjects.begin(), storage->mapObjects.end(), [&](const decltype(Storage::mapObjects)::value_type &p)
|
||||
mb.scale = object->m_rotate_z[2].z;
|
||||
auto i = find_if(storage->mapObjects.begin(), storage->mapObjects.end(), [&](const auto &p)
|
||||
{
|
||||
return *p.second.get() == mb;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <common.h>
|
||||
#include <buffer.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
|
@ -76,15 +76,15 @@ struct Segment
|
|||
template <class T>
|
||||
struct SegmentObjects : public Segment
|
||||
{
|
||||
vector<T> objects;
|
||||
vector<T*> objects;
|
||||
|
||||
virtual void load(buffer &b)
|
||||
{
|
||||
for (int i = 0; i < n_objects; i++)
|
||||
{
|
||||
T r;
|
||||
r.load(b);
|
||||
objects.push_back(r);
|
||||
T* o = new T;
|
||||
o->load(b);
|
||||
objects.push_back(o);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -126,16 +126,16 @@ struct MapObject : public Common
|
|||
struct MapObjectWithArray : public MapObject
|
||||
{
|
||||
uint32_t len = 0;
|
||||
vector<uint32_t> unk7;
|
||||
vector<uint32_t> unk0;
|
||||
|
||||
void load(buffer &b)
|
||||
{
|
||||
MapObject::load(b);
|
||||
|
||||
READ(b, len);
|
||||
unk7.resize(len);
|
||||
unk0.resize(len);
|
||||
for (int i = 0; i < len; i++)
|
||||
READ(b, unk7[i]);
|
||||
READ(b, unk0[i]);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <common.h>
|
||||
#include <buffer.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,47 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
|
||||
template <class T>
|
||||
class mat
|
||||
{
|
||||
public:
|
||||
using type = T;
|
||||
|
||||
public:
|
||||
mat(int w = 0, int h = 0)
|
||||
{
|
||||
width = w < 0 ? 0 : w;
|
||||
height = h < 0 ? 0 : h;
|
||||
data.resize(width * height, T());
|
||||
}
|
||||
|
||||
T &operator()(int row, int col)
|
||||
{
|
||||
assert(!(row >= height || col >= width || row < 0 || col < 0));
|
||||
return data[row * width + col];
|
||||
}
|
||||
const T &operator()(int row, int col) const
|
||||
{
|
||||
return (*const_cast<mat *>(this))(row, col);
|
||||
}
|
||||
|
||||
void clean()
|
||||
{
|
||||
std::fill(data.begin(), data.end(), T());
|
||||
}
|
||||
|
||||
int getWidth() const { return width; }
|
||||
int getHeight() const { return height; }
|
||||
int size() const { return width * height; }
|
||||
int getPos(const T *const elem) const { return elem - &data[0]; }
|
||||
const std::vector<T> &getData() const { return data; }
|
||||
std::vector<T> &getData() { return data; }
|
||||
|
||||
private:
|
||||
std::vector<T> data;
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
|
@ -22,61 +22,6 @@
|
|||
#include <fstream>
|
||||
#include <iomanip>
|
||||
|
||||
#include "bmp.h"
|
||||
|
||||
template<class T>
|
||||
void write_mat_bmp(const std::string &filename, const mat<T> &m)
|
||||
{
|
||||
FILE *f = fopen(filename.c_str(), "wb");
|
||||
if (f == nullptr)
|
||||
return;
|
||||
BITMAPFILEHEADER h = { 0 };
|
||||
h.bfType = 0x4D42;
|
||||
h.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO) + m.size() * sizeof(T);
|
||||
h.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO);
|
||||
BITMAPINFO i = { 0 };
|
||||
i.bmiHeader.biSize = sizeof(i.bmiHeader);
|
||||
i.bmiHeader.biWidth = m.getWidth();
|
||||
i.bmiHeader.biHeight = m.getHeight();
|
||||
i.bmiHeader.biPlanes = 1;
|
||||
i.bmiHeader.biBitCount = 32;
|
||||
i.bmiHeader.biCompression = 0;
|
||||
i.bmiHeader.biSizeImage = 0;
|
||||
i.bmiHeader.biXPelsPerMeter = 0;
|
||||
i.bmiHeader.biYPelsPerMeter = 0;
|
||||
i.bmiHeader.biClrUsed = 0;
|
||||
i.bmiHeader.biClrImportant = 0;
|
||||
fwrite(&h, sizeof(BITMAPFILEHEADER), 1, f);
|
||||
fwrite(&i, sizeof(BITMAPINFO), 1, f);
|
||||
fwrite(&m(0, 0), m.size() * sizeof(T), 1, f);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void write_mat_tga(const std::string &filename, const mat<uint8_t> &m)
|
||||
{
|
||||
// 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(3)); // 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(m.getWidth())); // width
|
||||
dst.write(uint16_t(m.getHeight())); // height
|
||||
dst.write(uint8_t(8)); // bitsperpixel
|
||||
dst.write(uint8_t(0x28)); // imagedescriptor
|
||||
|
||||
const char *label = "AIMMPExtractor";
|
||||
dst.write(label, strlen(label));
|
||||
|
||||
dst.write(m.getData().data(), m.getWidth() * m.getHeight());
|
||||
|
||||
writeFile(filename, dst.buf());
|
||||
}
|
||||
|
||||
void water_segment::load(buffer &b)
|
||||
{
|
||||
while (!b.eof())
|
||||
|
|
@ -247,7 +192,7 @@ void mmp::process()
|
|||
}
|
||||
textures.erase(0);
|
||||
auto textures_per_color = std::max(1U, textures.size() / 3);
|
||||
auto color_step = 200 / textures.size();
|
||||
auto color_step = 200 / std::max(1U, textures.size());
|
||||
for (int i = 0; i < textures.size(); i++)
|
||||
{
|
||||
int color_id = i / textures_per_color;
|
||||
|
|
@ -286,10 +231,14 @@ void mmp::process()
|
|||
const auto &data = segments[ys + xs].d;
|
||||
auto height = data.Heightmap[yc + xc];
|
||||
auto t = data.Infomap[yc + xc].getTexture();
|
||||
auto t_norm = textures_map[t];
|
||||
|
||||
texmap(y_rev, x) = t_norm;
|
||||
alpha_maps[t_norm.g](y_rev, x) = color{ 0,255,0,0 };
|
||||
auto t_norm = textures_map.find(t);
|
||||
if (t_norm != textures_map.end())
|
||||
{
|
||||
texmap(y_rev, x) = t_norm->second;
|
||||
alpha_maps[t_norm->second.g](y_rev, x) = color{ 0,255,0,0 };
|
||||
}
|
||||
|
||||
texmap_colored(y_rev, x) = textures_map_colored[t];
|
||||
colormap(y_rev, x) = data.Colormap[yc + xc];
|
||||
|
||||
|
|
|
|||
|
|
@ -22,9 +22,9 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#include "mat.h"
|
||||
#include <buffer.h>
|
||||
#include <color.h>
|
||||
#include <mat.h>
|
||||
|
||||
enum class WeatherType : uint32_t
|
||||
{
|
||||
|
|
@ -41,24 +41,6 @@ enum class SmokeType : uint32_t
|
|||
linear,
|
||||
};
|
||||
|
||||
struct color
|
||||
{
|
||||
uint8_t b;
|
||||
uint8_t g;
|
||||
uint8_t r;
|
||||
uint8_t a;
|
||||
|
||||
operator uint32_t() const
|
||||
{
|
||||
uint32_t color = 0;
|
||||
color |= r << 16;
|
||||
color |= g << 8;
|
||||
color |= b;
|
||||
return color;
|
||||
//return *reinterpret_cast<uint32_t *>(const_cast<uint8_t *>(&b));
|
||||
}
|
||||
};
|
||||
|
||||
struct direction
|
||||
{
|
||||
float x;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
#include <common.h>
|
||||
#include <buffer.h>
|
||||
#include "model.h"
|
||||
|
||||
using namespace std;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include <common.h>
|
||||
#include <buffer.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1,2 @@
|
|||
python tm_converter.py --dir "h:\\Games\\Epic Games\\Projects\\AIM\\models\\aim1\\"
|
||||
python tm_converter.py --dir "h:\\Games\\AIM\\data\\res1.pak.dir\\Data\\TM\\"
|
||||
python tm_converter.py --dir "h:\\Games\\Steam\\steamapps\\common\\AIM2\\Data\\tex.pak\\DATA\\TM\\"
|
||||
|
|
|
|||
|
|
@ -23,7 +23,9 @@
|
|||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
#include <common.h>
|
||||
#include <bmp.h>
|
||||
#include <buffer.h>
|
||||
#include <dxt5.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
|
@ -44,44 +46,48 @@ void convert_simple(buffer &dst, buffer &src, int width, int height)
|
|||
void tm2tga(string fn)
|
||||
{
|
||||
int width, height;
|
||||
int dxt5 = 0;
|
||||
int dxt5_flag = 0;
|
||||
|
||||
buffer src(readFile(fn));
|
||||
READ(src, width);
|
||||
READ(src, height);
|
||||
src.seek(0x10);
|
||||
src.read(&dxt5, 1);
|
||||
src.read(&dxt5_flag, 1);
|
||||
src.seek(0x4C);
|
||||
|
||||
// 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));
|
||||
|
||||
if (dxt5)
|
||||
if (dxt5_flag)
|
||||
{
|
||||
//convert_dxt5(dst, src, width, height);
|
||||
throw std::logic_error("dxt5 converter is not implemented!");
|
||||
dxt5 d;
|
||||
d.width = width;
|
||||
d.height = height;
|
||||
d.load_blocks(src);
|
||||
write_mat_bmp(fn + ".bmp", d.unpack_tm());
|
||||
}
|
||||
else
|
||||
convert_simple(dst, src, width, height);
|
||||
{
|
||||
// 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
|
||||
|
||||
transform(fn.begin(), fn.end(), fn.begin(), ::tolower);
|
||||
fn = fn.substr(0, fn.rfind(".tm")) + ".tga";
|
||||
writeFile(fn, dst.buf());
|
||||
const char *label = "AIMTMConverter";
|
||||
dst.write(label, strlen(label));
|
||||
|
||||
convert_simple(dst, src, width, height);
|
||||
transform(fn.begin(), fn.end(), fn.begin(), ::tolower);
|
||||
fn = fn.substr(0, fn.rfind(".tm")) + ".tga";
|
||||
writeFile(fn, dst.buf());
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ def run(dir):
|
|||
for file in sorted(os.listdir(dir)):
|
||||
if os.path.isdir(file) or os.path.splitext(file)[1].lower() != ".tm":
|
||||
continue
|
||||
print('processing: ' + file)
|
||||
p = subprocess.Popen(['tm_converter.exe', dir + '/' + file])
|
||||
p.communicate()
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
#define _BYTE uint8_t
|
||||
#define _WORD uint16_t
|
||||
#define _DWORD uint32_t
|
||||
#define _QWORD uint64_t
|
||||
|
||||
#define LOBYTE(x) (*((_BYTE*)&(x)))
|
||||
#define LOWORD(x) (*((_WORD*)&(x)))
|
||||
|
|
|
|||
Loading…
Reference in a new issue