Add tga writer.

This commit is contained in:
lzwdgc 2015-11-28 00:46:36 +03:00
parent 79bf2cc606
commit 0fdf743260
5 changed files with 137 additions and 55 deletions

View file

@ -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
View 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)

View file

@ -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,22 +153,29 @@ 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)
{ {
MapBuilding mb; MapBuilding mb;
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++;
} }
} }
} }
} }
if (inserted)
storage->save(); 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];

View file

@ -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");
{
ofstream ofile(string(argv[1]) + ".error.txt");
ofile << error; 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;
} }

View file

@ -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);