Repository navigation
Expand file tree
/
Copy pathModelMesh.cc
More file actions
109 lines (92 loc) · 2.94 KB
/
Copy pathModelMesh.cc
File metadata and controls
109 lines (92 loc) · 2.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// Copyright © 2021-2024 GothicKit Contributors.
// SPDX-License-Identifier: MIT
#include "zenkit/ModelMesh.hh"
#include "zenkit/Date.hh"
#include "zenkit/Stream.hh"
namespace zenkit {
static constexpr uint32_t VERSION_G1 = 0x04030506;
static constexpr uint32_t VERSION_G2 = 0x04030506;
enum class ModelMeshChunkType : std::uint16_t {
HEADER = 0xD000,
SOURCE = 0xD010,
NODES = 0xD020,
SOFTSKINS = 0xD030,
END = 0xD040,
PROTO = 0xB100,
};
void ModelMesh::load(Read* r) {
std::vector<std::string> attachment_names {};
proto::read_chunked<ModelMeshChunkType>(
r,
"ModelMesh",
[this, &attachment_names](Read* c, ModelMeshChunkType type, size_t& end) {
switch (type) {
case ModelMeshChunkType::HEADER:
(void) /* version = */ c->read_uint();
break;
case ModelMeshChunkType::SOURCE: {
// supposedly a date? weird values
Date date {};
date.load(c);
(void) /* source file = */ c->read_line(false);
break;
}
case ModelMeshChunkType::NODES: {
auto node_count = c->read_ushort();
for (std::uint32_t i = 0; i < node_count; ++i) {
attachment_names.push_back(c->read_line(true));
}
break;
}
case ModelMeshChunkType::PROTO:
this->attachments[attachment_names[this->attachments.size()]].load_from_section(c);
break;
case ModelMeshChunkType::SOFTSKINS: {
this->checksum = c->read_uint();
// Quirk: the meshes are not embedded within the chunk (as in: the stored length does not contain
// the size of these meshes) so they have to be read directly from `in`.
this->meshes.resize(c->read_ushort());
for (auto& mesh : this->meshes) {
mesh.load(c);
}
end = c->tell();
break;
}
case ModelMeshChunkType::END:
return true;
default:
break;
}
return false;
});
}
void ModelMesh::save(Write* w, GameVersion version) const {
proto::write_chunk(w, ModelMeshChunkType::HEADER, [version](Write* wr) {
wr->write_uint(version == GameVersion::GOTHIC_1 ? VERSION_G1 : VERSION_G2);
});
/* TODO: Source Chunk
proto::write_chunk(w, ModelMeshChunkType::SOURCE, [](Write* w) {
Date date {};
date.save(w);
w->write_line("");
}); */
proto::write_chunk(w, ModelMeshChunkType::NODES, [&](Write* wr) {
wr->write_ushort(this->attachments.size());
for (auto& [key, _] : this->attachments) {
wr->write_line(key);
}
});
proto::write_chunk(w, ModelMeshChunkType::PROTO, [&](Write* wr) {
for (auto& [_, v] : this->attachments) {
v.save_to_section(wr, version);
}
});
proto::write_chunk(w, ModelMeshChunkType::SOFTSKINS, [&](Write* wr) {
wr->write_uint(this->checksum);
for (auto& msh : this->meshes) {
msh.save(wr, version);
}
});
proto::write_chunk(w, ModelMeshChunkType::END, [](Write*) {});
}
} // namespace zenkit