SourcePP
Several modern C++20 libraries for sanely parsing Valve's formats.
Loading...
Searching...
No Matches
mdlpp.cpp
Go to the documentation of this file.
1#include <mdlpp/mdlpp.h>
2
3#include <algorithm>
4#include <span>
5#include <utility>
6
7using namespace mdlpp;
8using namespace sourcepp;
9
10bool StudioModel::open(const std::byte* mdlData, std::size_t mdlSize,
11 const std::byte* vtxData, std::size_t vtxSize,
12 const std::byte* vvdData, std::size_t vvdSize) {
13 if (this->opened || !mdlData || !vtxData || !vvdData || !mdlSize || !vtxSize || !vvdSize) {
14 return false;
15 }
16 this->opened = this->mdl.open(mdlData, mdlSize) && this->vtx.open(vtxData, vtxSize, this->mdl) && this->vvd.open(vvdData, vvdSize, this->mdl);
17 return this->opened;
18}
19
20bool StudioModel::open(const unsigned char* mdlData, std::size_t mdlSize,
21 const unsigned char* vtxData, std::size_t vtxSize,
22 const unsigned char* vvdData, std::size_t vvdSize) {
23 return this->open(reinterpret_cast<const std::byte*>(mdlData), mdlSize,
24 reinterpret_cast<const std::byte*>(vtxData), vtxSize,
25 reinterpret_cast<const std::byte*>(vvdData), vvdSize);
26}
27
28bool StudioModel::open(const std::vector<std::byte>& mdlData,
29 const std::vector<std::byte>& vtxData,
30 const std::vector<std::byte>& vvdData) {
31 return this->open(mdlData.data(), mdlData.size(),
32 vtxData.data(), vtxData.size(),
33 vvdData.data(), vvdData.size());
34}
35
36bool StudioModel::open(const std::vector<unsigned char>& mdlData,
37 const std::vector<unsigned char>& vtxData,
38 const std::vector<unsigned char>& vvdData) {
39 return this->open(mdlData.data(), mdlData.size(),
40 vtxData.data(), vtxData.size(),
41 vvdData.data(), vvdData.size());
42}
43
44StudioModel::operator bool() const {
45 return this->opened;
46}
47
49 BakedModel model;
50
51 // According to my limited research, vertices stay constant (ignoring LOD fixups) but indices vary with LOD level
52 if (this->vvd.fixups.empty()) {
53 std::ranges::copy(this->vvd.vertices, std::back_inserter(model.vertices));
54 } else {
55 for (const auto& [LOD, sourceVertexID, vertexCount] : this->vvd.fixups) {
56 if (LOD < currentLOD) {
57 continue;
58 }
59 std::span fixupVertices{this->vvd.vertices.begin() + sourceVertexID, static_cast<std::span<const VVD::Vertex>::size_type>(vertexCount)};
60 std::ranges::copy(fixupVertices, std::back_inserter(model.vertices));
61 }
62 }
63
64 for (int bodyPartIndex = 0; bodyPartIndex < this->mdl.bodyParts.size(); bodyPartIndex++) {
65 auto& mdlBodyPart = this->mdl.bodyParts.at(bodyPartIndex);
66 const auto& [vtxModels] = this->vtx.bodyParts.at(bodyPartIndex);
67
68 for (int modelIndex = 0; modelIndex < mdlBodyPart.models.size(); modelIndex++) {
69 auto& mdlModel = mdlBodyPart.models.at(modelIndex);
70 const auto& [vtxModelLODs] = vtxModels.at(modelIndex);
71
72 if (mdlModel.verticesCount == 0) {
73 continue;
74 }
75
76 for (int meshIndex = 0; meshIndex < mdlModel.meshes.size(); meshIndex++) {
77 auto& mdlMesh = mdlModel.meshes.at(meshIndex);
78 const auto& [vtxStripGroups, vtxMeshFlags] = vtxModelLODs.at(currentLOD).meshes.at(meshIndex);
79
80 std::vector<uint16_t> indices;
81 for (const auto& stripGroup : vtxStripGroups) {
82 for (const auto& strip : stripGroup.strips) {
83 const auto addIndex = [&indices, mdlMesh, mdlModel, stripGroup](int index) {
84 indices.push_back(stripGroup.vertices.at(index).meshVertexID + mdlMesh.verticesOffset + mdlModel.verticesOffset);
85 };
86
87 // Remember to flip the winding order
88 if (strip.flags & VTX::Strip::FLAG_IS_TRILIST) {
89 for (int i = 0; i < strip.indices.size(); i += 3) {
90 addIndex(strip.indices[i+0]);
91 addIndex(strip.indices[i+2]);
92 addIndex(strip.indices[i+1]);
93 }
94 } else /* if (strip.flags & VTX::Strip::FLAG_IS_TRISTRIP) */ {
95 for (int i = 0; i < strip.indices.size() - 2; i++) {
96 if (i & 1) {
97 addIndex(strip.indices[i+0]);
98 addIndex(strip.indices[i+2]);
99 addIndex(strip.indices[i+1]);
100 } else {
101 addIndex(strip.indices[i+1]);
102 addIndex(strip.indices[i+2]);
103 addIndex(strip.indices[i+0]);
104 }
105 }
106 }
107 }
108 }
109
110 model.meshes.push_back({
111 .indices = std::move(indices),
112 .materialIndex = mdlMesh.material,
113 });
114 }
115 }
116 }
117
118 return model;
119}
Definition mdlpp.h:9
A more accessible version of StudioModel's vertex data, so it can be rendered or converted more easil...
Definition mdlpp.h:14
std::vector< VVD::Vertex > vertices
Definition mdlpp.h:15
std::vector< Mesh > meshes
Definition mdlpp.h:21
bool open(const std::byte *data, std::size_t size)
Definition MDL.cpp:51
std::vector< BodyPart > bodyParts
Definition MDL.h:760
MDL::MDL mdl
Definition mdlpp.h:45
bool open(const std::byte *mdlData, std::size_t mdlSize, const std::byte *vtxData, std::size_t vtxSize, const std::byte *vvdData, std::size_t vvdSize)
Definition mdlpp.cpp:10
BakedModel processModelData(int currentLOD=ROOT_LOD) const
Definition mdlpp.cpp:48
VVD::VVD vvd
Definition mdlpp.h:47
VTX::VTX vtx
Definition mdlpp.h:46
@ FLAG_IS_TRILIST
Definition VTX.h:31
bool open(const std::byte *data, std::size_t size, const MDL::MDL &mdl, HasTopologyIndices hasTopologyIndices=HasTopologyIndices::AUTOMATIC)
Definition VTX.cpp:12
std::vector< BodyPart > bodyParts
Definition VTX.h:142
std::vector< Fixup > fixups
Definition VVD.h:50
bool open(const std::byte *data, std::size_t size, const MDL::MDL &mdl)
Definition VVD.cpp:11
std::vector< Vertex > vertices
Definition VVD.h:53