mirror of
https://github.com/aimrebirth/tools.git
synced 2026-04-15 01:43:25 +00:00
Add tga writer.
This commit is contained in:
parent
79bf2cc606
commit
0fdf743260
5 changed files with 137 additions and 55 deletions
|
|
@ -23,6 +23,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <bmp.h>
|
#include <bmp.h>
|
||||||
|
#include <tga.h>
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
class mat
|
class mat
|
||||||
|
|
@ -93,3 +94,23 @@ void write_mat_bmp(const std::string &filename, const mat<T> &m)
|
||||||
fwrite(&m(0, 0), m.size() * sizeof(T), 1, f);
|
fwrite(&m(0, 0), m.size() * sizeof(T), 1, f);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
void write_mat_tga(const std::string &filename, const mat<T> &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);
|
||||||
|
}
|
||||||
|
|
|
||||||
52
src/common/tga.h
Normal file
52
src/common/tga.h
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#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)
|
||||||
|
|
@ -36,14 +36,13 @@
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
|
||||||
#define RAD2GRAD(x) (x) = (x) / M_PI * 180.0
|
#define RAD2GRAD(x) (x) = (x) / M_PI * 180.0
|
||||||
|
#define ASSIGN(x, d) isnan(x) ? d : x
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
std::string prefix;
|
std::string prefix;
|
||||||
|
|
||||||
struct storage
|
struct storage
|
||||||
{
|
{
|
||||||
string name;
|
std::string name;
|
||||||
Objects objects;
|
Objects objects;
|
||||||
MechGroups mechGroups;
|
MechGroups mechGroups;
|
||||||
MapGoods mapGoods;
|
MapGoods mapGoods;
|
||||||
|
|
@ -74,14 +73,14 @@ struct storage
|
||||||
|
|
||||||
if (!b.eof())
|
if (!b.eof())
|
||||||
{
|
{
|
||||||
stringstream ss;
|
std::stringstream ss;
|
||||||
ss << hex << b.index() << " != " << hex << b.size();
|
ss << std::hex << b.index() << " != " << std::hex << b.size();
|
||||||
throw std::logic_error(ss.str());
|
throw std::logic_error(ss.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
storage read_mmo(string fn)
|
storage read_mmo(std::string fn)
|
||||||
{
|
{
|
||||||
buffer f(readFile(fn));
|
buffer f(readFile(fn));
|
||||||
storage s;
|
storage s;
|
||||||
|
|
@ -90,7 +89,7 @@ storage read_mmo(string fn)
|
||||||
return s;
|
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;
|
||||||
using namespace polygon4::detail;
|
using namespace polygon4::detail;
|
||||||
|
|
@ -104,12 +103,12 @@ void write_mmo(string db, const storage &s)
|
||||||
auto p2 = s.name.rfind('/');
|
auto p2 = s.name.rfind('/');
|
||||||
if (p2 == -1)
|
if (p2 == -1)
|
||||||
p2 = 0;
|
p2 = 0;
|
||||||
int p = max(p1, p2);
|
int p = std::max(p1, p2);
|
||||||
string map_name = s.name.substr(p + 1);
|
std::string map_name = s.name.substr(p + 1);
|
||||||
map_name = map_name.substr(0, map_name.find('.'));
|
map_name = map_name.substr(0, map_name.find('.'));
|
||||||
if (!prefix.empty())
|
if (!prefix.empty())
|
||||||
map_name = prefix + "." + map_name;
|
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;
|
int map_id = 0;
|
||||||
for (auto &m : storage->maps)
|
for (auto &m : storage->maps)
|
||||||
|
|
@ -129,19 +128,21 @@ void write_mmo(string db, const storage &s)
|
||||||
|
|
||||||
auto this_map = storage->maps[map_id];
|
auto this_map = storage->maps[map_id];
|
||||||
|
|
||||||
|
int inserted = 0;
|
||||||
|
int exist = 0;
|
||||||
for (auto &seg : s.objects.segments)
|
for (auto &seg : s.objects.segments)
|
||||||
{
|
{
|
||||||
if (seg->segment_type == ObjectType::BUILDING ||
|
if (seg->segment_type == ObjectType::BUILDING ||
|
||||||
seg->segment_type == ObjectType::TOWER)
|
seg->segment_type == ObjectType::TOWER)
|
||||||
{
|
{
|
||||||
SegmentObjects<::MapObject> *segment = (SegmentObjects<::MapObject> *)seg;
|
SegmentObjects<::MapObject> *segment = (SegmentObjects<::MapObject> *)seg;
|
||||||
set<string> objs;
|
std::set<std::string> objs;
|
||||||
std::map<string, int> bld_ids;
|
std::map<std::string, int> bld_ids;
|
||||||
for (auto &object : segment->objects)
|
for (auto &object : segment->objects)
|
||||||
objs.insert(object->name1);
|
objs.insert(object->name1);
|
||||||
for (auto &o : objs)
|
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;
|
return p.second->text_id == o;
|
||||||
});
|
});
|
||||||
|
|
@ -152,7 +153,9 @@ void write_mmo(string db, const storage &s)
|
||||||
bld_ids[o] = bld->getId();
|
bld_ids[o] = bld->getId();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
bld_ids[o] = iter->getId();
|
bld_ids[o] = iter->getId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (auto &object : segment->objects)
|
for (auto &object : segment->objects)
|
||||||
{
|
{
|
||||||
|
|
@ -160,14 +163,19 @@ void write_mmo(string db, const storage &s)
|
||||||
mb.text_id = object->name2;
|
mb.text_id = object->name2;
|
||||||
mb.building = storage->buildings[bld_ids[object->name1]];
|
mb.building = storage->buildings[bld_ids[object->name1]];
|
||||||
mb.map = this_map;
|
mb.map = this_map;
|
||||||
mb.x = object->position.x;
|
mb.x = ASSIGN(object->position.x, 0);
|
||||||
mb.y = object->position.y;
|
mb.y = ASSIGN(object->position.y, 0);
|
||||||
mb.z = object->position.z;
|
mb.z = ASSIGN(object->position.z, 0);
|
||||||
mb.roll = 0;
|
mb.roll = 0;
|
||||||
mb.pitch = 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);
|
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)
|
auto i = find_if(storage->mapBuildings.begin(), storage->mapBuildings.end(), [&](const auto &p)
|
||||||
{
|
{
|
||||||
return *p.second.get() == mb;
|
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());
|
auto mb2 = storage->addMapBuilding(storage->maps[map_id].get());
|
||||||
mb.setId(mb2->getId());
|
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)
|
seg->segment_type == ObjectType::BOUNDARY)
|
||||||
{
|
{
|
||||||
SegmentObjects<::MapObject> *segment = (SegmentObjects<::MapObject> *)seg;
|
SegmentObjects<::MapObject> *segment = (SegmentObjects<::MapObject> *)seg;
|
||||||
set<string> objs;
|
std::set<std::string> objs;
|
||||||
std::map<string, int> bld_ids;
|
std::map<std::string, int> bld_ids;
|
||||||
for (auto &object : segment->objects)
|
for (auto &object : segment->objects)
|
||||||
objs.insert(object->name1);
|
objs.insert(object->name1);
|
||||||
for (auto &o : objs)
|
for (auto &o : objs)
|
||||||
|
|
@ -211,14 +224,19 @@ void write_mmo(string db, const storage &s)
|
||||||
mb.text_id = object->name2;
|
mb.text_id = object->name2;
|
||||||
mb.map = this_map;
|
mb.map = this_map;
|
||||||
mb.object = storage->objects[bld_ids[object->name1]];
|
mb.object = storage->objects[bld_ids[object->name1]];
|
||||||
mb.x = object->position.x;
|
mb.x = ASSIGN(object->position.x, 0);
|
||||||
mb.y = object->position.y;
|
mb.y = ASSIGN(object->position.y, 0);
|
||||||
mb.z = object->position.z;
|
mb.z = ASSIGN(object->position.z, 0);
|
||||||
mb.roll = 0;
|
mb.roll = 0;
|
||||||
mb.pitch = 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);
|
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)
|
auto i = find_if(storage->mapObjects.begin(), storage->mapObjects.end(), [&](const auto &p)
|
||||||
{
|
{
|
||||||
return *p.second.get() == mb;
|
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());
|
auto mb2 = storage->addMapObject(storage->maps[map_id].get());
|
||||||
mb.setId(mb2->getId());
|
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[])
|
int main(int argc, char *argv[])
|
||||||
|
|
@ -240,7 +265,7 @@ try
|
||||||
{
|
{
|
||||||
if (argc != 4)
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
prefix = argv[3];
|
prefix = argv[3];
|
||||||
|
|
|
||||||
|
|
@ -121,24 +121,20 @@ catch (std::runtime_error &e)
|
||||||
if (silent)
|
if (silent)
|
||||||
return 1;
|
return 1;
|
||||||
string error;
|
string error;
|
||||||
if (argv[1])
|
error += filename;
|
||||||
error += argv[1];
|
|
||||||
error += "\n";
|
error += "\n";
|
||||||
error += "fatal error: ";
|
error += "fatal error: ";
|
||||||
error += e.what();
|
error += e.what();
|
||||||
error += "\n";
|
error += "\n";
|
||||||
if (argv[1])
|
ofstream ofile(filename + ".error.txt");
|
||||||
{
|
ofile << error;
|
||||||
ofstream ofile(string(argv[1]) + ".error.txt");
|
|
||||||
ofile << error;
|
|
||||||
}
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
catch (std::exception &e)
|
catch (std::exception &e)
|
||||||
{
|
{
|
||||||
if (silent)
|
if (silent)
|
||||||
return 1;
|
return 1;
|
||||||
printf("%s\n", argv[1]);
|
printf("%s\n", filename.c_str());
|
||||||
printf("error: %s\n", e.what());
|
printf("error: %s\n", e.what());
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
@ -146,7 +142,7 @@ catch (...)
|
||||||
{
|
{
|
||||||
if (silent)
|
if (silent)
|
||||||
return 1;
|
return 1;
|
||||||
printf("%s\n", argv[1]);
|
printf("%s\n", filename.c_str());
|
||||||
printf("error: unknown exception\n");
|
printf("error: unknown exception\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,27 +61,15 @@ void tm2tga(string fn)
|
||||||
d.width = width;
|
d.width = width;
|
||||||
d.height = height;
|
d.height = height;
|
||||||
d.load_blocks(src);
|
d.load_blocks(src);
|
||||||
write_mat_bmp(fn + ".bmp", d.unpack_tm());
|
write_mat_tga(fn + ".tga", d.unpack_tm());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// http://paulbourke.net/dataformats/tga/
|
|
||||||
buffer dst;
|
buffer dst;
|
||||||
dst.write(uint8_t(0xE)); // idlength (comment length)
|
tga t;
|
||||||
dst.write(uint8_t(0)); // colourmaptype
|
t.width = width;
|
||||||
dst.write(uint8_t(2)); // datatypecode
|
t.height = height;
|
||||||
dst.write(uint16_t(0)); // colourmaporigin
|
t.write(dst);
|
||||||
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));
|
|
||||||
|
|
||||||
convert_simple(dst, src, width, height);
|
convert_simple(dst, src, width, height);
|
||||||
transform(fn.begin(), fn.end(), fn.begin(), ::tolower);
|
transform(fn.begin(), fn.end(), fn.begin(), ::tolower);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue