Initial mod converter.

This commit is contained in:
lzwdgc 2015-06-28 19:25:06 +03:00
parent 0a67413c4b
commit e1f8b3b260
5 changed files with 478 additions and 0 deletions

View file

@ -13,3 +13,6 @@ add_executable(script2txt ${script2txt_src})
file(GLOB mmp_extractor_src "mmp_extractor/*")
add_executable(mmp_extractor ${mmp_extractor_src})
file(GLOB mod_converter_src "mod_converter/*")
add_executable(mod_converter ${mod_converter_src})

View file

@ -0,0 +1,72 @@
/*
* AIM mod_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 <iostream>
#include <map>
#include <set>
#include <stdio.h>
#include <stdint.h>
#include <string>
using namespace std;
#include "model.h"
model read_model(string fn)
{
model m;
FILE *f = fopen(fn.c_str(), "rb");
if (!f)
return m;
try
{
m.load(f);
}
catch (std::exception &e)
{
printf("error: %s\n", fn.c_str());
printf("%s\n", e.what());
return m;
}
auto p = ftell(f);
fseek(f, 0, SEEK_END);
auto end = ftell(f);
if (p != ftell(f))
{
printf("error: %s\n", fn.c_str());
printf(" : %x != %x\n", p, end);
}
fclose(f);
return m;
}
int main(int argc, char *argv[])
{
#ifdef NDEBUG
if (argc != 2)
{
cout << "Usage:\n" << argv[0] << " model_file" << "\n";
return 1;
}
read_model(argv[1]);
#else
#endif
return 0;
}

View file

@ -0,0 +1,24 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import argparse
import os
import subprocess
def main():
parser = argparse.ArgumentParser(description='Batch models converter')
parser.add_argument('--dir', dest='dir', help='path to directory with models')
pargs = parser.parse_args()
if pargs.dir:
run(pargs.dir)
def run(dir):
for file in os.listdir(dir):
if os.path.isdir(file):
continue
p = subprocess.Popen(['mod_converter.exe', file])
p.communicate()
if __name__ == '__main__':
main()

191
src/mod_converter/model.cpp Normal file
View file

@ -0,0 +1,191 @@
/*
* AIM mod_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 "model.h"
#include <string>
#define FREAD(var) fread(&var, 1, sizeof(var), f)
#define SREAD(var) s.read(&var, sizeof(var))
#define SREAD_N(var, sz) s.read(&var, sz)
void vertex::load(s_file &s, uint32_t flags)
{
SREAD(vX);
SREAD(vZ);
SREAD(vY);
if (flags & F_WIND)
SREAD(wind);
SREAD(nX);
SREAD(nZ);
SREAD(nY);
SREAD(t1);
SREAD(t2);
}
void fragment::load(FILE *f)
{
FREAD(type);
FREAD(name0);
FREAD(name1);
FREAD(name2);
FREAD(name3);
FREAD(name4);
FREAD(unk0);
FREAD(unk1);
FREAD(unk2);
FREAD(unk3);
FREAD(size);
FREAD(unk4);
data.resize(size);
data_offset = ftell(f);
fread(data.data(), 1, size, f);
}
bool fragment::extract()
{
s_file s(data, data_offset);
SREAD(n_segments);
segments.resize(n_segments);
SREAD(header);
SREAD(triangles_mult_7);
SREAD(unk10);
SREAD(flags);
SREAD(n_vertex);
vertices.resize(n_vertex);
SREAD(n_triangles);
if (triangles_mult_7)
n_triangles *= 7;
triangles.resize(n_triangles);
for (auto &v : vertices)
v.load(s, flags);
for (auto &t : triangles)
SREAD(t);
for (auto &seg : segments)
{
uint32_t type;
SREAD(type);
switch (type)
{
case 1:
seg = new segment1;
break;
case 2:
seg = new segment2;
break;
case 6:
seg = new segment6;
break;
default:
throw std::logic_error("unknown segment type " + std::to_string(type));
}
seg->type = type;
seg->extract(s);
}
return s.eof();
}
void segment1::extract(s_file &s)
{
SREAD(name);
SREAD(unk0);
triangles.resize(unk0[0][0]);
unk1.resize(unk0[0][0]);
for (int i = 0; i < 2; i++)
{
for (auto &t : triangles)
SREAD(t);
for (auto &unk: unk1)
SREAD(unk);
}
}
void segment2::extract(s_file &s)
{
SREAD(name);
SREAD(unk0);
triangles.resize(unk0[0][0]);
unk1.resize(unk0[0][0]);
unk1_1.resize(unk0[0][0]);
for (auto &t : triangles)
SREAD(t);
for (auto &unk : unk1)
SREAD(unk);
for (auto &unk : unk1_1)
SREAD(unk);
while (!s.eof())
{
repeater r;
r.extract(s);
unk2.push_back(r);
}
}
void segment2::repeater::extract(s_file &s)
{
SREAD(unk2);
triangles2.resize(unk2);
SREAD(unk8);
SREAD(unk3);
for (auto &t : triangles2)
SREAD(t);
SREAD(unk6);
SREAD(flags);
SREAD(n_vertex);
vertices.resize(n_vertex);
SREAD(n_triangles);
triangles.resize(n_triangles);
for (auto &v : vertices)
v.load(s, flags);
for (auto &t : triangles)
SREAD(t);
}
void segment6::extract(s_file &s)
{
SREAD(name);
SREAD(unk0);
triangles.resize(unk0[0][0]);
for (int i = 0; i < 1; i++)
{
for (auto &t : triangles)
SREAD(t);
char unk1[0x30]; // some 6 floats
for (int i = 0; i < unk0[0][0]; i++)
SREAD(unk1);
}
}
void model::load(FILE *f)
{
FREAD(n_fragments);
FREAD(header);
fragments.resize(n_fragments);
for (int i = 0; i < fragments.size(); i++)
{
fragments[i].load(f);
if (!fragments[i].extract())
throw std::logic_error("extraction error: fragment #" + std::to_string(i));
}
}

188
src/mod_converter/model.h Normal file
View file

@ -0,0 +1,188 @@
/*
* AIM mod_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/>.
*/
#pragma once
#include <stdint.h>
#include <vector>
struct s_file
{
uint32_t index = 0;
const std::vector<uint8_t> &buf;
uint8_t *ptr;
uint32_t data_offset;
s_file(const std::vector<uint8_t> &buf, uint32_t data_offset)
: buf(buf), data_offset(data_offset)
{}
uint32_t read(void *dst, uint32_t size)
{
if (index >= buf.size())
throw std::logic_error("s_file: out of range");
if (index + size > buf.size())
size = buf.size() - index;
memcpy(dst, buf.data() + index, size);
skip(size);
return size;
}
void skip(int n)
{
index += n;
data_offset += n;
ptr = (uint8_t *)buf.data() + index;
}
bool eof() const
{
return index == buf.size();
}
};
enum
{
F_WIND = 0x4,
};
struct vertex
{
float vX;
float vZ;
float vY;
float wind;
float nX;
float nZ;
float nY;
float t1;
float t2;
void load(s_file &s, uint32_t flags);
};
typedef uint16_t triangle;
struct unk_float3x4
{
float unk[4][3];
};
struct unk_float6
{
float unk[6];
};
struct segment
{
uint32_t type;
virtual void extract(s_file &s) = 0;
};
struct segment1 : public segment
{
char name[0xC];
uint32_t unk0[4][3];
std::vector<triangle> triangles;
std::vector<unk_float3x4> unk1;
virtual void extract(s_file &s);
};
struct segment2 : public segment
{
struct repeater
{
uint32_t unk2;
float unk8[3];
char unk3[0x3C];
std::vector<uint16_t> triangles2;
uint8_t unk6;
uint32_t flags;
uint32_t n_vertex;
uint32_t n_triangles;
std::vector<vertex> vertices;
std::vector<uint16_t> triangles;
virtual void extract(s_file &s);
};
char name[0xC];
uint32_t unk0[4][3];
std::vector<triangle> triangles;
std::vector<unk_float6> unk1;
std::vector<unk_float6> unk1_1;
std::vector<repeater> unk2;
virtual void extract(s_file &s);
};
struct segment6 : public segment1
{
virtual void extract(s_file &s);
};
struct fragment
{
// main header
uint32_t type;
char name0[0x20];
char name1[0x20];
char name2[0x20];
char name3[0x20];
char name4[0x20];
uint32_t unk0;
uint32_t unk1;
uint32_t unk2[2];
uint32_t unk3;
uint32_t size;
uint32_t unk4[10];
// data buffer
std::vector<uint8_t> data;
// main data
uint32_t n_segments;
char header[0x68];
uint32_t triangles_mult_7;
char unk10[0x20];
uint32_t flags;
uint32_t n_vertex;
uint32_t n_triangles;
std::vector<vertex> vertices;
std::vector<uint16_t> triangles;
// segments
std::vector<segment *> segments;
// internal vars
uint32_t data_offset;
void load(FILE *f);
bool extract();
};
struct model
{
int n_fragments;
char header[0x40];
std::vector<fragment> fragments;
void load(FILE *f);
};