More model data transformations.

This commit is contained in:
lzwdgc 2020-03-05 01:05:04 +03:00
parent 7325952708
commit baacacc44b
3 changed files with 208 additions and 138 deletions

View file

@ -258,6 +258,10 @@ bool CreateScene(const model &model, const std::string &name, FbxManager* pSdkMa
static const char* gAmbientElementName = "AmbientUV"; static const char* gAmbientElementName = "AmbientUV";
static const char* gSpecularElementName = "SpecularUV"; static const char* gSpecularElementName = "SpecularUV";
int engine_id = 0;
int fx_id = 0;
for (auto &b : model.blocks)
{
auto create_socket_named = [&pScene](const std::string &name) auto create_socket_named = [&pScene](const std::string &name)
{ {
FbxNode *socket = FbxNode::Create(pScene, ("SOCKET_" + name).c_str()); FbxNode *socket = FbxNode::Create(pScene, ("SOCKET_" + name).c_str());
@ -270,13 +274,13 @@ bool CreateScene(const model &model, const std::string &name, FbxManager* pSdkMa
auto create_socket = [&create_socket_named](const auto &b, const std::string &name, bool mirror_y = false) auto create_socket = [&create_socket_named](const auto &b, const std::string &name, bool mirror_y = false)
{ {
FbxVector4 c; FbxVector4 c;
for (auto &v : b.vertices) for (auto &v : b.pmd.vertices)
{ {
FbxVector4 x; FbxVector4 x;
x.Set(v.coordinates.x * scale_mult(), v.coordinates.y * scale_mult(), v.coordinates.z * scale_mult(), v.coordinates.w); x.Set(v.x * scale_mult(), v.y * scale_mult(), v.z * scale_mult(), v.w);
c += x; c += x;
} }
c /= b.vertices.size(); c /= b.pmd.vertices.size();
auto s = create_socket_named(name); auto s = create_socket_named(name);
if (mirror_y) // y is the second coord, idx = 1 if (mirror_y) // y is the second coord, idx = 1
@ -284,10 +288,6 @@ bool CreateScene(const model &model, const std::string &name, FbxManager* pSdkMa
s->LclTranslation.Set(c); s->LclTranslation.Set(c);
}; };
int engine_id = 0;
int fx_id = 0;
for (auto &b : model.blocks)
{
// //
if (b.isEngineFx()) if (b.isEngineFx())
{ {
@ -331,7 +331,7 @@ bool CreateScene(const model &model, const std::string &name, FbxManager* pSdkMa
node->SetShadingMode(FbxNode::eFullShading); // change?! was texture sh node->SetShadingMode(FbxNode::eFullShading); // change?! was texture sh
// vertices // vertices
m->InitControlPoints(b.vertices.size()); m->InitControlPoints(b.pmd.vertices.size());
// normals // normals
auto normal = m->CreateElementNormal(); auto normal = m->CreateElementNormal();
@ -352,27 +352,32 @@ bool CreateScene(const model &model, const std::string &name, FbxManager* pSdkMa
auto s_uv = create_uv(gSpecularElementName); auto s_uv = create_uv(gSpecularElementName);
// add vertices, normals, uvs // add vertices, normals, uvs
for (const auto &[i,v] : enumerate(b.vertices)) SW_CHECK(b.pmd.vertices.size() == b.pmd.normals.size());
for (const auto &[i,v] : enumerate(b.pmd.vertices))
{ {
FbxVector4 cp(v.coordinates.x * scale_mult(), v.coordinates.y * scale_mult(), v.coordinates.z * scale_mult(), v.coordinates.w); FbxVector4 cp(v.x * scale_mult(), v.y * scale_mult(), v.z * scale_mult(), v.w);
FbxVector4 n(v.normal.x, v.normal.y, v.normal.z); FbxVector4 n(b.pmd.normals[i].x, b.pmd.normals[i].y, b.pmd.normals[i].z);
m->SetControlPointAt(cp, n, i); m->SetControlPointAt(cp, n, i);
}
// uvs
for (const auto &[u,v] : b.pmd.uvs)
{
float f; float f;
auto uc = modf(fabs(v.texture_coordinates.u), &f); auto uc = modf(fabs(u), &f);
auto vc = modf(fabs(v.texture_coordinates.v), &f); auto vc = modf(fabs(v), &f);
d_uv->GetDirectArray().Add(FbxVector2(uc, vc)); d_uv->GetDirectArray().Add(FbxVector2(uc, vc));
a_uv->GetDirectArray().Add(FbxVector2(uc, vc)); a_uv->GetDirectArray().Add(FbxVector2(uc, vc));
s_uv->GetDirectArray().Add(FbxVector2(uc, vc)); s_uv->GetDirectArray().Add(FbxVector2(uc, vc));
} }
// faces // faces
for (auto &v : b.faces) for (auto &v : b.pmd.faces)
{ {
// Set the control point indices of the bottom side of the pyramid // Set the control point indices of the bottom side of the pyramid
m->BeginPolygon(); m->BeginPolygon();
for (auto i : v.vertex_list) for (auto &i : v.points)
m->AddPolygon(i); m->AddPolygon(i.vertex);
m->EndPolygon(); m->EndPolygon();
} }

View file

@ -171,37 +171,18 @@ static aim_vector3<T> rotate(const aim_vector3<T> &in, AxisSystem rot_type)
return v; return v;
} }
std::string vertex::printVertex(AxisSystem as) const void model_data::load(const buffer &b, uint32_t flags)
{ {
auto v = rotate(coordinates, as); uint32_t n_vertex;
uint32_t n_faces;
std::string s; READ(b, n_vertex);
s = "v " + vertices.resize(n_vertex);
print_float(v.x * scale_mult()) READ(b, n_faces);
+ " " + print_float(v.y * scale_mult()) faces.resize(n_faces / 3);
+ " " + print_float(v.z * scale_mult()) for (auto &v : vertices)
//+ " " + print_float(coordinates.w) v.load(b, flags);
; for (auto &t : faces)
return s; t.load(b);
}
std::string vertex::printNormal(AxisSystem as) const
{
auto v = rotate(normal, as);
std::string s;
s = "vn " + print_float(v.x) + " " + print_float(v.y) + " " + print_float(v.z);
return s;
}
std::string vertex::printTex() const
{
std::string s;
float i;
auto u = modf(fabs(texture_coordinates.u), &i);
auto v = modf(fabs(texture_coordinates.v), &i);
s = "vt " + print_float(u) + " " + print_float(v);
return s;
} }
void damage_model::load(const buffer &b) void damage_model::load(const buffer &b)
@ -215,16 +196,7 @@ void damage_model::load(const buffer &b)
READ(b, t); READ(b, t);
READ(b, unk6); READ(b, unk6);
READ(b, flags); READ(b, flags);
uint32_t n_vertex; data.load(b, flags);
uint32_t n_faces;
READ(b, n_vertex);
vertices.resize(n_vertex);
READ(b, n_faces);
faces.resize(n_faces / 3);
for (auto &v : vertices)
v.load(b, flags);
for (auto &t : faces)
t.load(b);
} }
std::string mat_color::print() const std::string mat_color::print() const
@ -316,21 +288,53 @@ std::string block::printMtl() const
return s; return s;
} }
static std::string print_vertices_and_faces(int group_offset, AxisSystem as, static std::string printVertex(const aim_vector4 &coordinates, AxisSystem as)
const std::vector<vertex> &vertices, const std::vector<face> &faces) {
auto v = rotate(coordinates, as);
std::string s;
s = "v " +
print_float(v.x * scale_mult())
+ " " + print_float(v.y * scale_mult())
+ " " + print_float(v.z * scale_mult())
//+ " " + print_float(coordinates.w)
;
return s;
}
static std::string printNormal(const vertex_normal &normal, AxisSystem as)
{
auto v = rotate(normal, as);
std::string s;
s = "vn " + print_float(v.x) + " " + print_float(v.y) + " " + print_float(v.z);
return s;
}
static std::string printTex(const uv &texture_coordinates)
{
std::string s;
float i;
auto u = modf(fabs(texture_coordinates.u), &i);
auto v = modf(fabs(texture_coordinates.v), &i);
s = "vt " + print_float(u) + " " + print_float(v);
return s;
}
std::string processed_model_data::print(int group_offset, AxisSystem as) const
{ {
std::string s; std::string s;
s += "# " + std::to_string(vertices.size()) + " vertices\n"; s += "# " + std::to_string(vertices.size()) + " vertices\n";
for (auto &v : vertices) for (auto &v : vertices)
s += v.printVertex(as) + "\n"; s += printVertex(v, as) + "\n";
s += "\n"; s += "\n";
s += "# " + std::to_string(vertices.size()) + " vertex normals\n"; s += "# " + std::to_string(normals.size()) + " vertex normals\n";
for (auto &v : vertices) for (auto &n : normals)
s += v.printNormal(as) + "\n"; s += printNormal(n, as) + "\n";
s += "\n"; s += "\n";
s += "# " + std::to_string(vertices.size()) + " texture coords\n"; s += "# " + std::to_string(uvs.size()) + " texture coords\n";
for (auto &v : vertices) for (auto &v : uvs)
s += v.printTex() + "\n"; s += printTex(v) + "\n";
s += "\n"; s += "\n";
s += "# " + std::to_string(vertices.size()) + " faces\n"; s += "# " + std::to_string(vertices.size()) + " faces\n";
@ -339,10 +343,14 @@ static std::string print_vertices_and_faces(int group_offset, AxisSystem as,
// no rotate here // no rotate here
// it is not face operation // it is not face operation
s += "f "; s += "f ";
for (auto v : t.vertex_list) for (auto &v : t.points)
{ {
auto x = std::to_string(v + 1 + group_offset); std::string x;
x += "/" + x + "/" + x; x += std::to_string(v.vertex + 1 + group_offset);
x += "/";
x += std::to_string(v.uv + 1 + group_offset); // uv goes second in .obj
x += "/";
x += std::to_string(v.normal + 1 + group_offset);
s += x + " "; s += x + " ";
} }
s += "\n"; s += "\n";
@ -350,8 +358,35 @@ static std::string print_vertices_and_faces(int group_offset, AxisSystem as,
return s; return s;
} }
std::string block::printObj(int group_offset, AxisSystem as, static processed_model_data process_block(const model_data &d)
const std::vector<vertex> &vertices, const std::vector<face> &faces) const {
processed_model_data pmd;
pmd.vertices.reserve(d.vertices.size());
pmd.normals.reserve(d.vertices.size());
pmd.uvs.reserve(d.vertices.size());
pmd.faces.reserve(d.faces.size());
for (auto &v : d.vertices)
{
pmd.vertices.push_back(v.coordinates);
pmd.normals.push_back(v.normal);
pmd.uvs.push_back(v.texture_coordinates);
}
for (auto &v : d.faces)
{
processed_model_data::face f;
for (const auto &[i,idx] : enumerate(v.vertex_list))
{
f.points[i].vertex = idx;
f.points[i].normal = idx;
f.points[i].uv = idx;
}
pmd.faces.push_back(f);
}
return pmd;
}
std::string block::printObj(int group_offset, AxisSystem as) const
{ {
std::string s; std::string s;
s += "usemtl " + h.name + "\n"; s += "usemtl " + h.name + "\n";
@ -360,15 +395,10 @@ std::string block::printObj(int group_offset, AxisSystem as,
s += "s 1\n"; // still unk how to use s += "s 1\n"; // still unk how to use
s += "\n"; s += "\n";
s += print_vertices_and_faces(group_offset, as, vertices, faces); s += pmd.print(group_offset, as);
return s; return s;
} }
std::string block::printObj(int group_offset, AxisSystem as) const
{
return printObj(group_offset, as, vertices, faces);
}
void block::header::texture::load(const buffer &b) void block::header::texture::load(const buffer &b)
{ {
READ_STRING(b, name); READ_STRING(b, name);
@ -422,6 +452,8 @@ void block::load(const buffer &b)
// else - pass current // else - pass current
// no copy when buffer is created before // no copy when buffer is created before
loadPayload(h.size == 0 ? b : data); loadPayload(h.size == 0 ? b : data);
pmd = process_block(md);
} }
void block::loadPayload(const buffer &data) void block::loadPayload(const buffer &data)
@ -473,10 +505,10 @@ void block::loadPayload(const buffer &data)
READ(data, unk12); READ(data, unk12);
READ(data, triangles_mult_7); // particle system? READ(data, triangles_mult_7); // particle system?
/*if (unk7 != 0) //if (unk7 != 0)
std::cout << "nonzero unk7 = " << unk7 << " in block " << h.name << "\n"; //std::cout << "nonzero unk7 = " << unk7 << " in block " << h.name << "\n";
if (unk9 != 0) //if (unk9 != 0)
std::cout << "nonzero unk9 = " << unk9 << " in block " << h.name << "\n";*/ //std::cout << "nonzero unk9 = " << unk9 << " in block " << h.name << "\n";
// //
READ(data, additional_params); READ(data, additional_params);
@ -485,17 +517,7 @@ void block::loadPayload(const buffer &data)
damage_models.resize(n_damage_models); damage_models.resize(n_damage_models);
READ(data, rot); READ(data, rot);
READ(data, flags); READ(data, flags);
uint32_t n_vertex; md.load(data, flags);
uint32_t n_faces; // ??? edges? polygons? triangles?
READ(data, n_vertex);
vertices.resize(n_vertex);
READ(data, n_faces);
auto n_triangles = n_faces / 3;
for (auto &v : vertices)
v.load(data, flags);
faces.resize(n_triangles);
for (auto &t : faces)
t.load(data);
// animations // animations
for (auto &a : animations) for (auto &a : animations)
@ -505,9 +527,10 @@ void block::loadPayload(const buffer &data)
auto read_more_faces = [&]() auto read_more_faces = [&]()
{ {
auto n_faces = md.faces.size();
n_faces *= 6; // 7 n_faces *= 6; // 7
decltype(faces) faces2; decltype(md.faces) faces2;
faces2.resize(n_faces / 3); faces2.resize(n_faces / 3);
for (auto &t : faces2) for (auto &t : faces2)
READ(data, t); READ(data, t);
@ -537,7 +560,7 @@ void block::loadPayload(const buffer &data)
else else
{ {
// unknown end of block // unknown end of block
decltype(faces) triangles2; decltype(md.faces) triangles2;
auto d = data.end() - data.index(); auto d = data.end() - data.index();
triangles2.resize(d / sizeof(face)); triangles2.resize(d / sizeof(face));
for (auto &t : triangles2) for (auto &t : triangles2)
@ -551,14 +574,17 @@ void block::loadPayload(const buffer &data)
throw std::logic_error(s); throw std::logic_error(s);
} }
static auto linkFaces(const std::vector<vertex> &vertices, const std::vector<face> &faces) static processed_model_data linkFaces(const processed_model_data &d)
{ {
// reference implementation by Razum: https://pastebin.com/KewhggDj // reference implementation by Razum: https://pastebin.com/KewhggDj
std::vector<vertex> vertices2; processed_model_data pmd = d;
/*std::vector<vertex> vertices2;
vertices2.reserve(vertices.size()); vertices2.reserve(vertices.size());
std::unordered_map<short, short> repl; std::unordered_map<short, short> vrepl, trepl;
repl.reserve(vertices.size()); vrepl.reserve(vertices.size());
trepl.reserve(vertices.size());
auto sz = vertices.size(); auto sz = vertices.size();
for (int i = 0; i < sz; i++) for (int i = 0; i < sz; i++)
@ -570,10 +596,19 @@ static auto linkFaces(const std::vector<vertex> &vertices, const std::vector<fac
if (it == vertices2.end()) if (it == vertices2.end())
{ {
vertices2.push_back(vertices[i]); vertices2.push_back(vertices[i]);
repl[i] = vertices2.size() - 1; vrepl[i] = vertices2.size() - 1;
} }
else else
repl[i] = std::distance(vertices2.begin(), it); vrepl[i] = std::distance(vertices2.begin(), it);
}
std::vector<uv> uvs2;
uvs2.reserve(uvs.size());
for (auto &f : uvs)
{
// remove duplicates
if (std::find(uvs2.begin(), uvs2.end(), f) == uvs2.end())
uvs2.push_back(f);
} }
std::vector<face> faces2; std::vector<face> faces2;
@ -581,20 +616,18 @@ static auto linkFaces(const std::vector<vertex> &vertices, const std::vector<fac
for (auto f : faces) for (auto f : faces)
{ {
for (auto &v : f.vertex_list) for (auto &v : f.vertex_list)
v = repl[v]; v = vrepl[v];
// remove duplicates // remove duplicates
if (std::find(faces2.begin(), faces2.end(), f) == faces2.end()) if (std::find(faces2.begin(), faces2.end(), f) == faces2.end())
faces2.push_back(f); faces2.push_back(f);
} }*/
return std::tuple{ vertices2, faces2 }; return pmd;
} }
void block::linkFaces() void block::linkFaces()
{ {
auto [v, f] = ::linkFaces(vertices, faces); pmd = ::linkFaces(pmd);
vertices = v;
faces = f;
} }
bool block::isEngineFx() const bool block::isEngineFx() const
@ -617,8 +650,13 @@ bool block::canPrint() const
return false; return false;
// collision object // collision object
if (h.name.find("SHAPE") != h.name.npos) if (h.name.find("SHAPE") != h.name.npos ||
h.name.find("shape") != h.name.npos
)
{
//std::cerr << "shape detected!\n";
return false; return false;
}
// default // default
return false; return false;
@ -627,7 +665,7 @@ bool block::canPrint() const
block::block_info block::save(yaml &root) const block::block_info block::save(yaml &root) const
{ {
aim_vector4 min{ 1e6, 1e6, 1e6, 1e6 }, max{ -1e6, -1e6, -1e6, -1e6 }; aim_vector4 min{ 1e6, 1e6, 1e6, 1e6 }, max{ -1e6, -1e6, -1e6, -1e6 };
for (auto &v : vertices) for (auto &v : md.vertices)
{ {
auto mm = [&v](auto &m, auto f) auto mm = [&v](auto &m, auto f)
{ {
@ -704,7 +742,7 @@ void model::print(const std::string &fn, AxisSystem as) const
continue; continue;
o << b.printObj(n_vert, as) << "\n"; o << b.printObj(n_vert, as) << "\n";
n_vert += b.vertices.size(); n_vert += b.md.vertices.size();
} }
}; };

View file

@ -132,6 +132,8 @@ struct uv
float v; float v;
void load(const buffer &b); void load(const buffer &b);
bool operator==(const uv &rhs) const { return std::tie(u, v) == std::tie(rhs.u, rhs.v); }
}; };
struct vertex struct vertex
@ -141,10 +143,6 @@ struct vertex
uv texture_coordinates; uv texture_coordinates;
void load(const buffer &b, uint32_t flags); void load(const buffer &b, uint32_t flags);
std::string printVertex(AxisSystem as) const;
std::string printNormal(AxisSystem as) const;
std::string printTex() const;
}; };
struct face struct face
@ -152,9 +150,41 @@ struct face
uint16_t vertex_list[3]; uint16_t vertex_list[3];
void load(const buffer &b); void load(const buffer &b);
bool operator==(const face &rhs) const { return vertex_list == rhs.vertex_list; } bool operator==(const face &rhs) const { return vertex_list == rhs.vertex_list; }
}; };
struct model_data
{
std::vector<vertex> vertices;
std::vector<face> faces; // triangles
void load(const buffer &b, uint32_t flags);
};
struct processed_model_data
{
struct face
{
struct point
{
// indices
uint16_t vertex;
uint16_t normal;
uint16_t uv;
};
point points[3];
};
std::vector<aim_vector4> vertices;
std::vector<vertex_normal> normals;
std::vector<uv> uvs;
std::vector<face> faces;
std::string print(int group_offset, AxisSystem as) const;
};
struct animation struct animation
{ {
// +1 +0.5 -0.5 +1 // +1 +0.5 -0.5 +1
@ -189,8 +219,7 @@ struct damage_model
std::string name; std::string name;
std::vector<uint16_t> model_polygons; std::vector<uint16_t> model_polygons;
uint32_t flags; uint32_t flags;
std::vector<vertex> vertices; model_data data;
std::vector<face> faces;
uint8_t unk6; uint8_t unk6;
float unk8[3]; float unk8[3];
@ -296,8 +325,7 @@ struct block
additional_parameters additional_params; additional_parameters additional_params;
rotation rot; rotation rot;
uint32_t flags; uint32_t flags;
std::vector<vertex> vertices; model_data md;
std::vector<face> faces; // triangles
// animations // animations
std::vector<animation> animations; std::vector<animation> animations;
@ -322,9 +350,8 @@ struct block
bool canPrint() const; bool canPrint() const;
bool isEngineFx() const; bool isEngineFx() const;
private: //
std::string block::printObj(int group_offset, AxisSystem as, processed_model_data pmd;
const std::vector<vertex> &vertices, const std::vector<face> &faces) const;
}; };
struct model struct model