SourcePP
Several modern C++20 libraries for sanely parsing Valve's formats.
Loading...
Searching...
No Matches
VTX.cpp
Go to the documentation of this file.
1#include <mdlpp/structs/VTX.h>
2
3#include <BufferStream.h>
4
5using namespace mdlpp::VTX;
6
7bool VTX::open(const std::byte* data, std::size_t size, const MDL::MDL& mdl) {
8 BufferStreamReadOnly stream{data, size};
9
10 if (stream.read(this->version); this->version != 7) {
11 return false;
12 }
13
14 stream
15 .read(this->vertexCacheSize)
16 .read(this->maxBonesPerStrip)
17 .read(this->maxBonesPerTriangle)
18 .read(this->maxBonesPerVertex);
19
20 if (stream.read<int32_t>() != mdl.checksum) {
21 return false;
22 }
23
24 stream.read(this->numLODs);
25
26 // todo: read material replacement list
27 stream.skip<int32_t>();
28
29 const auto bodyPartCount = stream.read<int32_t>();
30 const auto bodyPartOffset = stream.read<int32_t>();
31
32 for (int i = 0; i < bodyPartCount; i++) {
33 const auto bodyPartPos = bodyPartOffset + i * ((sizeof(int32_t) * 2));
34 stream.seek_u(bodyPartPos);
35
36 auto& bodyPart = this->bodyParts.emplace_back();
37
38 const auto modelCount = stream.read<int32_t>();
39 const auto modelOffset = stream.read<int32_t>();
40
41 for (int j = 0; j < modelCount; j++) {
42 const auto modelPos = modelOffset + j * (sizeof(int32_t) * 2);
43 stream.seek_u(bodyPartPos + modelPos);
44
45 auto& model = bodyPart.models.emplace_back();
46
47 const auto modelLODCount = stream.read<int32_t>();
48 const auto modelLODOffset = stream.read<int32_t>();
49
50 for (int k = 0; k < modelLODCount; k++) {
51 const auto modelLODPos = modelLODOffset + k * (sizeof(int32_t) * 2 + sizeof(float));
52 stream.seek_u(bodyPartPos + modelPos + modelLODPos);
53
54 auto& modelLOD = model.modelLODs.emplace_back();
55
56 const auto meshCount = stream.read<int32_t>();
57 const auto meshOffset = stream.read<int32_t>();
58
59 stream.read(modelLOD.switchDistance);
60
61 for (int l = 0; l < meshCount; l++) {
62 const auto meshPos = meshOffset + l * (sizeof(int32_t) * 2 + sizeof(Mesh::Flags));
63 stream.seek_u(bodyPartPos + modelPos + modelLODPos + meshPos);
64
65 auto& mesh = modelLOD.meshes.emplace_back();
66
67 const auto stripGroupCount = stream.read<int32_t>();
68 const auto stripGroupOffset = stream.read<int32_t>();
69
70 stream.read(mesh.flags);
71
72 for (int m = 0; m < stripGroupCount; m++) {
73 int stripGroupNumInts = 6;
74 if (mdl.version >= 49) {
75 stripGroupNumInts += 2;
76 }
77 const auto stripGroupPos = stripGroupOffset + m * (sizeof(int32_t) * stripGroupNumInts + sizeof(StripGroup::Flags));
78 stream.seek_u(bodyPartPos + modelPos + modelLODPos + meshPos + stripGroupPos);
79
80 auto& stripGroup = mesh.stripGroups.emplace_back();
81
82 const auto vertexCount = stream.read<int32_t>();
83 const auto vertexOffset = stream.read<int32_t>();
84
85 auto stripGroupCurrentPos = stream.tell();
86 stream.seek_u(bodyPartPos + modelPos + modelLODPos + meshPos + stripGroupPos + vertexOffset);
87 for (int n = 0; n < vertexCount; n++) {
88 auto& [meshVertexID] = stripGroup.vertices.emplace_back();
89
90 // todo: process bone data
91 stream.skip<uint8_t>(4);
92
93 stream.read(meshVertexID);
94
95 // ditto
96 stream.skip<int8_t>(3);
97 }
98 stream.seek_u(stripGroupCurrentPos);
99
100 const auto indexCount = stream.read<int32_t>();
101 const auto indexOffset = stream.read<int32_t>();
102
103 stripGroupCurrentPos = stream.tell();
104 stream.seek_u(bodyPartPos + modelPos + modelLODPos + meshPos + stripGroupPos + indexOffset);
105 for (int n = 0; n < indexCount; n++) {
106 auto& index = stripGroup.indices.emplace_back();
107 stream.read(index);
108 }
109 stream.seek_u(stripGroupCurrentPos);
110
111 const auto stripCount = stream.read<int32_t>();
112 const auto stripOffset = stream.read<int32_t>();
113
114 stream.read(stripGroup.flags);
115
116 if (mdl.version >= 49) {
117 // mesh topology
118 stream.skip<int32_t>(2);
119 }
120
121 stream.seek_u(bodyPartPos + modelPos + modelLODPos + meshPos + stripGroupPos + stripOffset);
122 for (int n = 0; n < stripCount; n++) {
123 auto& strip = stripGroup.strips.emplace_back();
124
125 const auto indicesCount = stream.read<int32_t>();
126 stream.read(strip.indicesOffset);
127 // todo: check if offset is in bytes
128 strip.indices = std::span(stripGroup.indices.begin() + strip.indicesOffset, indicesCount);
129
130 const auto verticesCount = stream.read<int32_t>();
131 stream.read(strip.verticesOffset);
132 // todo: check if offset is in bytes
133 strip.vertices = std::span(stripGroup.vertices.begin() + strip.verticesOffset, verticesCount);
134
135 stream
136 .read(strip.boneCount)
137 .read(strip.flags);
138
139 // todo: bone stuff
140 stream.skip<int32_t>(2);
141
142 if (mdl.version >= 49) {
143 // mesh topology
144 stream.skip<int32_t>(2);
145 }
146 }
147 }
148 }
149 }
150 }
151 }
152
153 return true;
154}
Definition: VTX.h:10
int32_t checksum
Definition: MDL.h:287
int32_t version
Definition: MDL.h:286
int32_t numLODs
Definition: VTX.h:119
int32_t vertexCacheSize
Definition: VTX.h:114
std::vector< BodyPart > bodyParts
Definition: VTX.h:125
uint16_t maxBonesPerTriangle
Definition: VTX.h:116
int32_t maxBonesPerVertex
Definition: VTX.h:117
bool open(const std::byte *data, std::size_t size, const MDL::MDL &mdl)
Definition: VTX.cpp:7
uint16_t maxBonesPerStrip
Definition: VTX.h:115