Add simple mod reader.

This commit is contained in:
lzwdgc 2017-07-29 00:46:41 +03:00
parent 986fd859d7
commit f9f9cedef8
5 changed files with 268 additions and 93 deletions

View file

@ -50,6 +50,10 @@ else()
message(STATUS "provide fbx sdk path to build mod converter") message(STATUS "provide fbx sdk path to build mod converter")
endif() endif()
file(GLOB mod_reader_src "mod_reader/*")
add_executable(mod_reader ${mod_reader_src} mod_converter/model.cpp)
target_link_libraries(mod_reader common)
file(GLOB mpj_loader_src "mpj_loader/*") file(GLOB mpj_loader_src "mpj_loader/*")
add_executable(mpj_loader ${mpj_loader_src}) add_executable(mpj_loader ${mpj_loader_src})
target_link_libraries(mpj_loader common) target_link_libraries(mpj_loader common)

View file

@ -231,7 +231,7 @@ bool CreateScene(model &model, const std::string &name, FbxManager* pSdkManager,
if (!b.canPrint()) if (!b.canPrint())
continue; continue;
auto block_name = name + "/" + b.name; auto block_name = name + "/" + b.h.name;
// mesh // mesh
auto m = FbxMesh::Create(pSdkManager, block_name.c_str()); auto m = FbxMesh::Create(pSdkManager, block_name.c_str());
@ -296,10 +296,10 @@ bool CreateScene(model &model, const std::string &name, FbxManager* pSdkManager,
{ {
FbxString lMaterialName = block_name.c_str(); FbxString lMaterialName = block_name.c_str();
FbxString lShadingName = "Phong"; FbxString lShadingName = "Phong";
FbxDouble3 lAmbientColor(b.mat.ambient.x, b.mat.ambient.y, b.mat.ambient.z); FbxDouble3 lAmbientColor(b.mat.ambient.r, b.mat.ambient.g, b.mat.ambient.b);
FbxDouble3 lSpecularColor(b.mat.specular.x, b.mat.specular.y, b.mat.specular.z); FbxDouble3 lSpecularColor(b.mat.specular.r, b.mat.specular.g, b.mat.specular.b);
FbxDouble3 lDiffuseColor(b.mat.diffuse.x, b.mat.diffuse.y, b.mat.diffuse.z); FbxDouble3 lDiffuseColor(b.mat.diffuse.r, b.mat.diffuse.g, b.mat.diffuse.b);
FbxDouble3 lEmissiveColor(b.mat.emissive.x, b.mat.emissive.y, b.mat.emissive.z); FbxDouble3 lEmissiveColor(b.mat.emissive.r, b.mat.emissive.g, b.mat.emissive.b);
FbxLayer* lLayer = m->GetLayer(0); FbxLayer* lLayer = m->GetLayer(0);
@ -322,14 +322,14 @@ bool CreateScene(model &model, const std::string &name, FbxManager* pSdkManager,
// Generate primary and secondary colors. // Generate primary and secondary colors.
lMaterial->Emissive.Set(lEmissiveColor); lMaterial->Emissive.Set(lEmissiveColor);
//lMaterial->EmissiveFactor.Set(b.material.emissive.x); lMaterial->EmissiveFactor.Set(b.mat.emissive.r);
lMaterial->Ambient.Set(lAmbientColor); lMaterial->Ambient.Set(lAmbientColor);
//lMaterial->AmbientFactor.Set(b.mat.ambient.x); lMaterial->AmbientFactor.Set(b.mat.ambient.r);
// Add texture for diffuse channel // Add texture for diffuse channel
lMaterial->Diffuse.Set(lDiffuseColor); lMaterial->Diffuse.Set(lDiffuseColor);
//lMaterial->DiffuseFactor.Set(b.mat.diffuse.x); lMaterial->DiffuseFactor.Set(b.mat.diffuse.r);
//lMaterial->TransparencyFactor.Set(0.4); //lMaterial->TransparencyFactor.Set(0.4);
//lMaterial->ShadingModel.Set(lShadingName); //lMaterial->ShadingModel.Set(lShadingName);
@ -340,42 +340,40 @@ bool CreateScene(model &model, const std::string &name, FbxManager* pSdkManager,
node->AddMaterial(lMaterial); node->AddMaterial(lMaterial);
} }
FbxFileTexture* lTexture; if (b.mat_type != MaterialType::MaterialOnly)
{
// Set texture properties. FbxFileTexture* lTexture;
lTexture = FbxFileTexture::Create(pScene, "Diffuse Texture");
lTexture->SetFileName((b.tex_mask + texture_extension).c_str()); // Resource file is in current directory.
lTexture->SetTextureUse(FbxTexture::eStandard);
lTexture->SetMappingType(FbxTexture::eUV);
lTexture->SetMaterialUse(FbxFileTexture::eModelMaterial);
lTexture->UVSet.Set(gDiffuseElementName);
if (lMaterial)
lMaterial->Diffuse.ConnectSrcObject(lTexture);
// Set texture properties.
lTexture = FbxFileTexture::Create(pScene, "Ambient Texture");
lTexture->SetFileName((b.tex_mask + texture_extension).c_str()); // Resource file is in current directory.
lTexture->SetTextureUse(FbxTexture::eStandard);
lTexture->SetMappingType(FbxTexture::eUV);
lTexture->SetMaterialUse(FbxFileTexture::eModelMaterial);
lTexture->UVSet.Set(gAmbientElementName);
if (lMaterial)
lMaterial->Ambient.ConnectSrcObject(lTexture);
// Set texture properties.
lTexture = FbxFileTexture::Create(pScene, "Specular Texture");
lTexture->SetFileName((b.tex_spec + texture_extension).c_str()); // Resource file is in current directory.
lTexture->SetTextureUse(FbxTexture::eStandard);
lTexture->SetMappingType(FbxTexture::eUV);
lTexture->SetMaterialUse(FbxFileTexture::eModelMaterial);
lTexture->UVSet.Set(gSpecularElementName);
if (lMaterial)
lMaterial->Specular.ConnectSrcObject(lTexture);
// Set texture properties.
lTexture = FbxFileTexture::Create(pScene, "Diffuse Texture");
lTexture->SetFileName((b.h.tex_mask + texture_extension).c_str()); // Resource file is in current directory.
lTexture->SetTextureUse(FbxTexture::eStandard);
lTexture->SetMappingType(FbxTexture::eUV);
lTexture->SetMaterialUse(FbxFileTexture::eModelMaterial);
lTexture->UVSet.Set(gDiffuseElementName);
if (lMaterial)
lMaterial->Diffuse.ConnectSrcObject(lTexture);
// Set texture properties.
lTexture = FbxFileTexture::Create(pScene, "Ambient Texture");
lTexture->SetFileName((b.h.tex_mask + texture_extension).c_str()); // Resource file is in current directory.
lTexture->SetTextureUse(FbxTexture::eStandard);
lTexture->SetMappingType(FbxTexture::eUV);
lTexture->SetMaterialUse(FbxFileTexture::eModelMaterial);
lTexture->UVSet.Set(gAmbientElementName);
if (lMaterial)
lMaterial->Ambient.ConnectSrcObject(lTexture);
// Set texture properties.
lTexture = FbxFileTexture::Create(pScene, "Specular Texture");
lTexture->SetFileName((b.h.tex_spec + texture_extension).c_str()); // Resource file is in current directory.
lTexture->SetTextureUse(FbxTexture::eStandard);
lTexture->SetMappingType(FbxTexture::eUV);
lTexture->SetMaterialUse(FbxFileTexture::eModelMaterial);
lTexture->UVSet.Set(gSpecularElementName);
if (lMaterial)
lMaterial->Specular.ConnectSrcObject(lTexture);
}
// add smoothing groups // add smoothing groups
FbxGeometryConverter lGeometryConverter(pSdkManager); FbxGeometryConverter lGeometryConverter(pSdkManager);
@ -383,7 +381,6 @@ bool CreateScene(model &model, const std::string &name, FbxManager* pSdkManager,
//convert soft/hard edge info to smoothing group info //convert soft/hard edge info to smoothing group info
lGeometryConverter.ComputePolygonSmoothingFromEdgeSmoothing(m); lGeometryConverter.ComputePolygonSmoothingFromEdgeSmoothing(m);
// //
pScene->GetRootNode()->AddChild(node); pScene->GetRootNode()->AddChild(node);
} }

View file

@ -27,8 +27,6 @@
#include <buffer.h> #include <buffer.h>
#include <fbxsdk.h>
//#include <Eigen/Core> //#include <Eigen/Core>
//#include <Eigen/Dense> //#include <Eigen/Dense>
@ -235,6 +233,13 @@ void damage_model::load(const buffer &b)
READ(b, t); READ(b, t);
} }
std::string mat_color::print() const
{
string s;
s += to_string(r) + " " + to_string(g) + " " + to_string(b);
return s;
}
void material::load(const buffer &b) void material::load(const buffer &b)
{ {
READ(b, diffuse); READ(b, diffuse);
@ -245,9 +250,12 @@ void material::load(const buffer &b)
auto delim_by_3 = [](auto &v) auto delim_by_3 = [](auto &v)
{ {
v.x /= 3.0f; //if (v.r > 1)
v.y /= 3.0f; //v.r /= 3.0f;
v.z /= 3.0f; //if (v.g > 1)
//v.g /= 3.0f;
//if (v.b > 1)
//v.b /= 3.0f;
}; };
// in aim - those values lie in interval [0,3] instead of [0,1] // in aim - those values lie in interval [0,3] instead of [0,1]
@ -292,7 +300,7 @@ void animation::segment::loadData(const buffer &b)
std::string block::printMtl() const std::string block::printMtl() const
{ {
string s; string s;
s += "newmtl " + name + "\n"; s += "newmtl " + h.name + "\n";
s += "\n"; s += "\n";
s += "Ka " + mat.ambient.print() + "\n"; s += "Ka " + mat.ambient.print() + "\n";
s += "Kd " + mat.diffuse.print() + "\n"; s += "Kd " + mat.diffuse.print() + "\n";
@ -301,14 +309,14 @@ std::string block::printMtl() const
// d 1.0 // d 1.0
// illum // illum
s += "\n"; s += "\n";
if (string(tex_mask) != "_DEFAULT_") if (h.tex_mask != "_DEFAULT_")
s += "map_Ka " + string(tex_mask) + texture_extension + "\n"; s += "map_Ka " + h.tex_mask + texture_extension + "\n";
if (string(tex_mask) != "_DEFAULT_") if (h.tex_mask != "_DEFAULT_")
s += "map_Kd " + string(tex_mask) + texture_extension + "\n"; s += "map_Kd " + h.tex_mask + texture_extension + "\n";
if (string(tex_spec) != "_DEFAULT_") if (h.tex_spec != "_DEFAULT_")
s += "map_Ks " + string(tex_spec) + texture_extension + "\n"; s += "map_Ks " + h.tex_spec + texture_extension + "\n";
if (string(tex_spec) != "_DEFAULT_") if (h.tex_spec != "_DEFAULT_")
s += "map_Ns " + string(tex_spec) + texture_extension + "\n"; s += "map_Ns " + h.tex_spec + texture_extension + "\n";
s += "\n"; s += "\n";
return s; return s;
} }
@ -316,9 +324,9 @@ std::string block::printMtl() const
std::string block::printObj(int group_offset, bool rotate_x_90) const std::string block::printObj(int group_offset, bool rotate_x_90) const
{ {
string s; string s;
s += "usemtl " + name + "\n"; s += "usemtl " + h.name + "\n";
s += "\n"; s += "\n";
s += "g " + name + "\n"; s += "g " + h.name + "\n";
s += "s 1\n"; // still unk how to use s += "s 1\n"; // still unk how to use
s += "\n"; s += "\n";
@ -348,9 +356,8 @@ std::string block::printObj(int group_offset, bool rotate_x_90) const
return s; return s;
} }
void block::load(const buffer &b) void block::header::load(const buffer &b)
{ {
// header
READ(b, type); READ(b, type);
READ_STRING(b, name); READ_STRING(b, name);
name = translate(name); name = translate(name);
@ -363,17 +370,27 @@ void block::load(const buffer &b)
READ(b, unk3); READ(b, unk3);
READ(b, size); READ(b, size);
READ(b, unk4); READ(b, unk4);
}
if (size == 0) // critical error!!! cannot survive void block::load(const buffer &b)
{
h.load(b);
if (h.size == 0) // critical error!!! cannot survive
throw std::runtime_error("model file has bad block size field (size == 0)"); throw std::runtime_error("model file has bad block size field (size == 0)");
// data // data
buffer data = buffer(b, size); buffer data = buffer(b, h.size);
// we cannot process this type at the moment // we cannot process this type at the moment
if (type == BlockType::ParticleEmitter) if (h.type == BlockType::ParticleEmitter)
return; return;
loadPayload(data);
}
void block::loadPayload(const buffer &data)
{
// anims // anims
uint32_t n_animations; uint32_t n_animations;
READ(data, n_animations); READ(data, n_animations);
@ -420,7 +437,7 @@ void block::load(const buffer &b)
for (auto &dm : damage_models) for (auto &dm : damage_models)
dm.load(data); dm.load(data);
string s = "extraction error: block #" + std::string(name); string s = "extraction error: block #" + std::string(h.name);
if (!data.eof()) if (!data.eof())
{ {
cerr << s << "\n"; cerr << s << "\n";
@ -442,11 +459,11 @@ void block::load(const buffer &b)
bool block::canPrint() const bool block::canPrint() const
{ {
if (type == BlockType::ParticleEmitter) if (h.type == BlockType::ParticleEmitter)
return false; return false;
if (type != BlockType::VisibleObject) if (h.type != BlockType::VisibleObject)
return false; return false;
if (!(all_lods == 15 || LODs.lod1)) if (!(h.all_lods == 15 || h.LODs.lod1))
return false; return false;
return true; return true;
} }

View file

@ -150,12 +150,22 @@ struct damage_model
virtual void load(const buffer &b); virtual void load(const buffer &b);
}; };
struct mat_color
{
float r;
float g;
float b;
float alpha;
std::string print() const;
};
struct material struct material
{ {
aim_vector4 ambient; mat_color ambient;
aim_vector4 diffuse; mat_color diffuse;
aim_vector4 specular; mat_color specular;
aim_vector4 emissive; mat_color emissive;
float power; float power;
void load(const buffer &b); void load(const buffer &b);
@ -176,26 +186,40 @@ struct additional_parameters
struct block struct block
{ {
// header struct header
BlockType type;
std::string name;
std::string tex_mask;
std::string tex_spec;
std::string tex3;
std::string tex4;
union // LODs
{ {
struct BlockType type;
std::string name;
std::string tex_mask;
std::string tex_spec;
std::string tex3;
std::string tex4;
union // LODs
{ {
uint8_t lod1 : 1; struct
uint8_t lod2 : 1; {
uint8_t lod3 : 1; uint8_t lod1 : 1;
uint8_t lod4 : 1; uint8_t lod2 : 1;
uint8_t : 4; uint8_t lod3 : 1;
} LODs; uint8_t lod4 : 1;
uint32_t all_lods; uint8_t : 4;
} LODs;
uint32_t all_lods;
};
// stuff
uint32_t size;
// unk
uint32_t unk2[3];
uint32_t unk3;
uint32_t unk4[10];
void load(const buffer &b);
}; };
header h;
// data // data
material mat; material mat;
MaterialType mat_type; MaterialType mat_type;
@ -216,13 +240,7 @@ struct block
std::vector<animation> animations; std::vector<animation> animations;
std::vector<damage_model> damage_models; std::vector<damage_model> damage_models;
// stuff
uint32_t size;
// unk // unk
uint32_t unk2[3];
uint16_t unk3[2];
uint32_t unk4[10];
uint32_t unk7; uint32_t unk7;
float unk9; float unk9;
uint32_t unk10; uint32_t unk10;
@ -231,6 +249,7 @@ struct block
uint32_t unk12; uint32_t unk12;
void load(const buffer &b); void load(const buffer &b);
void loadPayload(const buffer &b);
std::string printMtl() const; std::string printMtl() const;
std::string printObj(int group_offset, bool rotate_x_90 = false) const; std::string printObj(int group_offset, bool rotate_x_90 = false) const;

View file

@ -0,0 +1,138 @@
/*
* 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 <sstream>
#include <stdio.h>
#include <stdint.h>
#include <string>
#include <buffer.h>
#include "../mod_converter/model.h"
#include <primitives/filesystem.h>
using namespace std;
// options
bool all_formats = false;
bool silent = false;
bool printMaxPolygonBlock = false;
path p;
bool parse_cmd(int argc, char *argv[]);
void convert_model(const path &fn)
{
buffer b(read_file(fn));
block bl;
bl.loadPayload(b);
if (!b.eof())
{
stringstream ss;
ss << hex << b.index() << " != " << hex << b.size();
throw std::logic_error(ss.str());
}
}
int main(int argc, char *argv[])
try
{
if (argc < 2 || !parse_cmd(argc, argv))
{
printf("Usage: %s [OPTIONS] {model_file,model_dir}\n", argv[0]);
return 1;
}
if (fs::is_regular_file(p))
convert_model(p);
else if (fs::is_directory(p))
{
auto files = enumerate_files(p, false);
for (auto &f : files)
{
if (f.has_extension())
continue;
std::cout << "processing: " << f << "\n";
convert_model(f);
}
}
else
throw std::runtime_error("Bad fs object");
return 0;
}
catch (std::runtime_error &e)
{
if (silent)
return 1;
string error;
error += p.string();
error += "\n";
error += "fatal error: ";
error += e.what();
error += "\n";
ofstream ofile(p.string() + ".error.txt");
ofile << error;
return 1;
}
catch (std::exception &e)
{
if (silent)
return 1;
printf("%s\n", p.string().c_str());
printf("error: %s\n", e.what());
return 1;
}
catch (...)
{
if (silent)
return 1;
printf("%s\n", p.string().c_str());
printf("error: unknown exception\n");
return 1;
}
bool parse_cmd(int argc, char *argv[])
{
for (int i = 1; i < argc; i++)
{
auto arg = argv[i];
if (*arg != '-')
{
if (i != argc - 1)
return false;
p = arg;
continue;
}
switch (arg[1])
{
case 'a':
all_formats = true;
break;
case 's':
silent = true;
break;
case 'm':
printMaxPolygonBlock = true;
break;
}
}
return true;
}