mirror of
https://github.com/aimrebirth/tools.git
synced 2026-04-14 17:33:25 +00:00
Add tm converter (into tga).
This commit is contained in:
parent
972bd3e1e8
commit
75a4f2b0d7
7 changed files with 314 additions and 91 deletions
|
|
@ -21,4 +21,8 @@ file(GLOB mod_converter_src "mod_converter/*")
|
|||
add_executable(mod_converter ${mod_converter_src})
|
||||
target_link_libraries(mod_converter common)
|
||||
|
||||
file(GLOB tm_converter_src "tm_converter/*")
|
||||
add_executable(tm_converter ${tm_converter_src})
|
||||
target_link_libraries(tm_converter common)
|
||||
|
||||
add_subdirectory(common)
|
||||
|
|
@ -50,15 +50,31 @@ std::vector<uint8_t> readFile(const std::string &fn)
|
|||
return buf;
|
||||
}
|
||||
|
||||
void writeFile(const std::string &fn, const std::vector<uint8_t> &data)
|
||||
{
|
||||
FILE *f = fopen(fn.c_str(), "wb");
|
||||
if (!f)
|
||||
throw std::runtime_error("Cannot open file " + fn);
|
||||
fwrite(data.data(), 1, data.size(), f);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
buffer::buffer()
|
||||
{
|
||||
}
|
||||
|
||||
buffer::buffer(size_t size)
|
||||
: buf(new std::vector<uint8_t>(size))
|
||||
{
|
||||
this->size = buf->size();
|
||||
skip(0);
|
||||
}
|
||||
|
||||
buffer::buffer(const std::vector<uint8_t> &buf, uint32_t data_offset)
|
||||
: buf(new std::vector<uint8_t>(buf)), data_offset(data_offset)
|
||||
{
|
||||
skip(0);
|
||||
size = buf.size();
|
||||
size = this->buf->size();
|
||||
}
|
||||
|
||||
buffer::buffer(buffer &rhs, uint32_t size)
|
||||
|
|
@ -80,7 +96,7 @@ buffer::buffer(buffer &rhs, uint32_t size, uint32_t offset)
|
|||
this->size = index + size;
|
||||
}
|
||||
|
||||
uint32_t buffer::read(void *dst, uint32_t size, bool nothrow)
|
||||
uint32_t buffer::read(void *dst, uint32_t size, bool nothrow) const
|
||||
{
|
||||
if (!buf)
|
||||
throw std::logic_error("buffer: not initialized");
|
||||
|
|
@ -91,13 +107,40 @@ uint32_t buffer::read(void *dst, uint32_t size, bool nothrow)
|
|||
throw std::logic_error("buffer: out of range");
|
||||
}
|
||||
if (index + size > this->size)
|
||||
{
|
||||
if (!nothrow)
|
||||
throw std::logic_error("buffer: too much data");
|
||||
size = this->size - index;
|
||||
}
|
||||
memcpy(dst, buf->data() + index, size);
|
||||
skip(size);
|
||||
return size;
|
||||
}
|
||||
|
||||
void buffer::skip(int n)
|
||||
uint32_t buffer::write(const void *src, uint32_t size, bool nothrow)
|
||||
{
|
||||
if (!buf)
|
||||
{
|
||||
buf = std::make_shared<std::vector<uint8_t>>(size);
|
||||
this->size = buf->size();
|
||||
}
|
||||
if (index > this->size)
|
||||
{
|
||||
if (nothrow)
|
||||
return 0;
|
||||
throw std::logic_error("buffer: out of range");
|
||||
}
|
||||
if (index + size > this->size)
|
||||
{
|
||||
buf->resize(index + size);
|
||||
this->size = buf->size();
|
||||
}
|
||||
memcpy((uint8_t *)buf->data() + index, src, size);
|
||||
skip(size);
|
||||
return size;
|
||||
}
|
||||
|
||||
void buffer::skip(int n) const
|
||||
{
|
||||
if (!buf)
|
||||
throw std::logic_error("buffer: not initialized");
|
||||
|
|
@ -106,6 +149,13 @@ void buffer::skip(int n)
|
|||
ptr = (uint8_t *)buf->data() + index;
|
||||
}
|
||||
|
||||
void buffer::reset() const
|
||||
{
|
||||
index = 0;
|
||||
data_offset = 0;
|
||||
ptr = (uint8_t *)buf->data();
|
||||
}
|
||||
|
||||
bool buffer::check(int index) const
|
||||
{
|
||||
return this->index == index;
|
||||
|
|
@ -125,3 +175,10 @@ uint32_t buffer::getSize() const
|
|||
{
|
||||
return this->size;
|
||||
}
|
||||
|
||||
const std::vector<uint8_t> &buffer::getBuf() const
|
||||
{
|
||||
if (!buf)
|
||||
throw std::logic_error("buffer: not initialized");
|
||||
return *buf;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,30 +26,42 @@
|
|||
#define READ(b, var) b.read(&var, sizeof(var))
|
||||
#define READ_NOTHROW(b, var) b.read(&var, sizeof(var), true)
|
||||
#define READ_N(b, var, sz) b.read(&var, sz)
|
||||
#define WRITE(b, var) b.write(&var, sizeof(var))
|
||||
|
||||
std::string version();
|
||||
std::vector<uint8_t> readFile(const std::string &fn);
|
||||
void writeFile(const std::string &fn, const std::vector<uint8_t> &data);
|
||||
|
||||
class buffer
|
||||
{
|
||||
public:
|
||||
buffer();
|
||||
buffer(size_t size);
|
||||
buffer(const std::vector<uint8_t> &buf, uint32_t data_offset = 0);
|
||||
buffer(buffer &rhs, uint32_t size);
|
||||
buffer(buffer &rhs, uint32_t size, uint32_t offset);
|
||||
|
||||
uint32_t read(void *dst, uint32_t size, bool nothrow = false);
|
||||
void skip(int n);
|
||||
uint32_t read(void *dst, uint32_t size, bool nothrow = false) const;
|
||||
uint32_t write(const void *src, uint32_t size, bool nothrow = false);
|
||||
template <typename T>
|
||||
uint32_t write(const T &src, bool nothrow = false)
|
||||
{
|
||||
return write(&src, sizeof(src), nothrow);
|
||||
}
|
||||
|
||||
void skip(int n) const;
|
||||
bool eof() const;
|
||||
bool check(int index) const;
|
||||
void reset() const;
|
||||
|
||||
uint32_t getIndex() const;
|
||||
uint32_t getSize() const;
|
||||
const std::vector<uint8_t> &getBuf() const;
|
||||
|
||||
private:
|
||||
std::shared_ptr<const std::vector<uint8_t>> buf;
|
||||
uint32_t index = 0;
|
||||
uint8_t *ptr = 0;
|
||||
uint32_t data_offset = 0;
|
||||
uint32_t size = 0;
|
||||
std::shared_ptr<std::vector<uint8_t>> buf;
|
||||
mutable uint32_t index = 0;
|
||||
mutable uint8_t *ptr = 0;
|
||||
mutable uint32_t data_offset = 0;
|
||||
mutable uint32_t size = 0;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include "model.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
|
@ -28,6 +29,13 @@ using namespace std;
|
|||
|
||||
std::string version();
|
||||
|
||||
std::string Vector4::print() const
|
||||
{
|
||||
string s;
|
||||
s += to_string(x) + " " + to_string(y) + " " + to_string(z);
|
||||
return s;
|
||||
}
|
||||
|
||||
void vertex::load(buffer &b, uint32_t flags)
|
||||
{
|
||||
READ(b, vX);
|
||||
|
|
@ -66,6 +74,116 @@ std::string vertex::printTex() const
|
|||
return s;
|
||||
}
|
||||
|
||||
void damage_model::load(buffer &b)
|
||||
{
|
||||
READ(b, n_polygons);
|
||||
polygons.resize(n_polygons);
|
||||
READ(b, unk8);
|
||||
READ(b, name);
|
||||
for (auto &t : polygons)
|
||||
READ(b, t);
|
||||
READ(b, unk6);
|
||||
READ(b, flags);
|
||||
READ(b, n_vertex);
|
||||
vertices.resize(n_vertex);
|
||||
READ(b, n_triangles);
|
||||
triangles.resize(n_triangles);
|
||||
for (auto &v : vertices)
|
||||
v.load(b, flags);
|
||||
for (auto &t : triangles)
|
||||
READ(b, t);
|
||||
}
|
||||
|
||||
void animation::load(buffer &b)
|
||||
{
|
||||
READ(b, type);
|
||||
READ(b, name);
|
||||
for (auto &s : segments)
|
||||
s.loadHeader(b);
|
||||
if (segments[0].n)
|
||||
for (auto &s : segments)
|
||||
s.loadData(b);
|
||||
}
|
||||
|
||||
void animation::segment::loadHeader(buffer &b)
|
||||
{
|
||||
READ(b, n);
|
||||
READ(b, unk0);
|
||||
READ(b, unk1);
|
||||
}
|
||||
|
||||
void animation::segment::loadData(buffer &b)
|
||||
{
|
||||
if (n == 0)
|
||||
return;
|
||||
if (unk0)
|
||||
{
|
||||
triangles.resize(n);
|
||||
for (auto &t : triangles)
|
||||
READ(b, t);
|
||||
}
|
||||
unk2.resize(n);
|
||||
for (auto &unk : unk2)
|
||||
READ(b, unk);
|
||||
}
|
||||
|
||||
std::string block::printMtl(const std::string &mtl_name) const
|
||||
{
|
||||
string s;
|
||||
s += "newmtl " + mtl_name + "\n";
|
||||
s += "\n";
|
||||
s += "Ka " + material.ambient.print() + "\n";
|
||||
s += "Kd " + material.diffuse.print() + "\n";
|
||||
s += "Ks " + material.specular.print() + "\n";
|
||||
s += " Ns " + to_string(material.power) + "\n";
|
||||
// d 1.0
|
||||
// illum
|
||||
s += "\n";
|
||||
s += "map_Ka " + string(tex_mask) + ".tga\n";
|
||||
s += "map_Kd " + string(tex_mask) + ".tga\n";
|
||||
s += "map_Ks " + string(tex_spec) + ".tga\n";
|
||||
s += "map_Ns " + string(tex_spec) + ".tga\n";
|
||||
s += "\n";
|
||||
return s;
|
||||
}
|
||||
|
||||
std::string block::printObj() const
|
||||
{
|
||||
string s;
|
||||
s += string("o ") + name + "\n";
|
||||
s += string("g ") + name + "\n";
|
||||
s += "s off\n";
|
||||
s += "\n";
|
||||
s += "usemtl main\n";
|
||||
s += "\n";
|
||||
|
||||
for (auto &v : vertices)
|
||||
s += v.printVertex() + "\n";
|
||||
s += "\n";
|
||||
for (auto &v : vertices)
|
||||
s += v.printNormal() + "\n";
|
||||
s += "\n";
|
||||
for (auto &v : vertices)
|
||||
s += v.printTex() + "\n";
|
||||
s += "\n";
|
||||
|
||||
if (n_triangles)
|
||||
for (int i = 0; i <= n_triangles - 3; i += 3)
|
||||
{
|
||||
auto x = to_string(triangles[i] + 1);
|
||||
auto y = to_string(triangles[i + 2] + 1);
|
||||
auto z = to_string(triangles[i + 1] + 1);
|
||||
x += "/" + x;
|
||||
y += "/" + y;
|
||||
z += "/" + z;
|
||||
s += "f " + x + " " + y + " " + z + "\n";
|
||||
}
|
||||
|
||||
s += "\n";
|
||||
s += "\n";
|
||||
return s;
|
||||
}
|
||||
|
||||
void block::load(buffer &b)
|
||||
{
|
||||
// header
|
||||
|
|
@ -143,59 +261,6 @@ void block::load(buffer &b)
|
|||
throw std::logic_error("extraction error: block #" + std::string(name));
|
||||
}
|
||||
|
||||
void damage_model::load(buffer &b)
|
||||
{
|
||||
READ(b, n_polygons);
|
||||
polygons.resize(n_polygons);
|
||||
READ(b, unk8);
|
||||
READ(b, name);
|
||||
for (auto &t : polygons)
|
||||
READ(b, t);
|
||||
READ(b, unk6);
|
||||
READ(b, flags);
|
||||
READ(b, n_vertex);
|
||||
vertices.resize(n_vertex);
|
||||
READ(b, n_triangles);
|
||||
triangles.resize(n_triangles);
|
||||
for (auto &v : vertices)
|
||||
v.load(b, flags);
|
||||
for (auto &t : triangles)
|
||||
READ(b, t);
|
||||
}
|
||||
|
||||
void animation::load(buffer &b)
|
||||
{
|
||||
READ(b, type);
|
||||
READ(b, name);
|
||||
for (auto &s : segments)
|
||||
s.loadHeader(b);
|
||||
if (segments[0].n)
|
||||
for (auto &s : segments)
|
||||
s.loadData(b);
|
||||
}
|
||||
|
||||
void animation::segment::loadHeader(buffer &b)
|
||||
{
|
||||
READ(b, n);
|
||||
READ(b, unk0);
|
||||
READ(b, unk1);
|
||||
}
|
||||
|
||||
void animation::segment::loadData(buffer &b)
|
||||
{
|
||||
if (n == 0)
|
||||
return;
|
||||
if (unk0)
|
||||
{
|
||||
triangles.resize(n);
|
||||
for (auto &t : triangles)
|
||||
READ(b, t);
|
||||
}
|
||||
unk2.resize(n);
|
||||
for (auto &unk : unk2)
|
||||
READ(b, unk);
|
||||
}
|
||||
|
||||
void model::load(buffer &b)
|
||||
{
|
||||
READ(b, n_blocks);
|
||||
|
|
@ -216,34 +281,19 @@ void model::writeObj(std::string fn)
|
|||
o << "# A.I.M. Model Converter (ver. " << version() << ")\n";
|
||||
o << "#" << "\n";
|
||||
o << "\n";
|
||||
o << "o " << f.name << "\n";
|
||||
o << "g " << f.name << "\n";
|
||||
o << "s off\n";
|
||||
int p1 = fn.rfind("\\");
|
||||
int p2 = fn.rfind("/");
|
||||
auto mtl = fn.substr(std::max(p1, p2) + 1);
|
||||
mtl += string(".") + f.name;
|
||||
o << "mtllib " << mtl << ".mtl\n";
|
||||
o << "\n";
|
||||
o << f.printObj();
|
||||
|
||||
for (auto &v : f.vertices)
|
||||
o << v.printVertex() << "\n";
|
||||
o << "\n";
|
||||
for (auto &v : f.vertices)
|
||||
o << v.printNormal() << "\n";
|
||||
o << "\n";
|
||||
for (auto &v : f.vertices)
|
||||
o << v.printTex() << "\n";
|
||||
o << "\n";
|
||||
|
||||
if (f.n_triangles)
|
||||
for (int i = 0; i <= f.n_triangles - 3; i += 3)
|
||||
{
|
||||
auto x = to_string(f.triangles[i] + 1);
|
||||
auto y = to_string(f.triangles[i + 2] + 1);
|
||||
auto z = to_string(f.triangles[i + 1] + 1);
|
||||
x += "/" + x;
|
||||
y += "/" + y;
|
||||
z += "/" + z;
|
||||
o << "f " << x << " " << y << " " << z << "\n";
|
||||
}
|
||||
|
||||
o << "\n";
|
||||
o << "\n";
|
||||
ofstream m(fn + "." + f.name + ".mtl");
|
||||
m << "#" << "\n";
|
||||
m << "# A.I.M. Model Converter (ver. " << version() << ")\n";
|
||||
m << "#" << "\n";
|
||||
m << "\n";
|
||||
m << f.printMtl(mtl);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,6 +58,8 @@ struct Vector4
|
|||
float y;
|
||||
float z;
|
||||
float w;
|
||||
|
||||
std::string print() const;
|
||||
};
|
||||
|
||||
struct vertex
|
||||
|
|
@ -211,6 +213,8 @@ struct block
|
|||
std::vector<damage_model> damage_models;
|
||||
|
||||
void load(buffer &b);
|
||||
std::string printMtl(const std::string &mtl_name) const;
|
||||
std::string printObj() const;
|
||||
};
|
||||
|
||||
struct model
|
||||
|
|
|
|||
96
src/tm_converter/tm_converter.cpp
Normal file
96
src/tm_converter/tm_converter.cpp
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* AIM tm_converter
|
||||
* 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 <algorithm>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
#include <common.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
void tm2tga(string fn)
|
||||
{
|
||||
int width, height;
|
||||
|
||||
buffer src(readFile(fn));
|
||||
READ(src, width);
|
||||
READ(src, height);
|
||||
src.reset();
|
||||
src.skip(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), false);
|
||||
|
||||
int size = width * height * 2;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
uint8_t c;
|
||||
READ(src, c);
|
||||
uint8_t lo = c & 0x0F;
|
||||
uint8_t hi = (c & 0xF0) >> 4;
|
||||
dst.write(uint8_t((lo << 4) | lo));
|
||||
dst.write(uint8_t((hi << 4) | hi));
|
||||
}
|
||||
|
||||
transform(fn.begin(), fn.end(), fn.begin(), tolower);
|
||||
fn = fn.substr(0, fn.rfind(".tm")) + ".tga";
|
||||
writeFile(fn, dst.getBuf());
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
try
|
||||
{
|
||||
if (argc != 2)
|
||||
{
|
||||
printf("Usage: %s file.tm\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
tm2tga(argv[1]);
|
||||
return 0;
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
printf("%s\n", argv[1]);
|
||||
printf("error: %s\n", e.what());
|
||||
return 1;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
printf("%s\n", argv[1]);
|
||||
printf("error: unknown exception\n");
|
||||
return 1;
|
||||
}
|
||||
Loading…
Reference in a new issue