3#include <BufferStream.h>
9constexpr int32_t
MDL_ID =
'I' + (
'D' << 8) + (
'S' << 16) + (
'T' << 24);
11bool MDL::open(
const std::byte* data, std::size_t size) {
12 BufferStreamReadOnly stream{data, size};
14 if (stream.read<int32_t>() !=
MDL_ID) {
18 if (stream.read(this->version); this->version < 44 || this->version > 49) {
33 this->
flags =
static_cast<Flags>(stream.read<int32_t>());
35 const auto boneCount = stream.read<int32_t>();
36 const auto boneOffset = stream.read<int32_t>();
38 const auto boneControllerCount = stream.read<int32_t>();
39 const auto boneControllerOffset = stream.read<int32_t>();
41 const auto hitboxSetCount = stream.read<int32_t>();
42 const auto hitboxSetOffset = stream.read<int32_t>();
46 stream.skip<int32_t>(2);
50 stream.skip<int32_t>(2);
56 const auto materialCount = stream.read<int32_t>();
57 const auto materialOffset = stream.read<int32_t>();
59 const auto materialDirCount = stream.read<int32_t>();
60 const auto materialDirOffset = stream.read<int32_t>();
62 const auto skinReferenceCount = stream.read<int32_t>();
63 const auto skinReferenceFamilyCount = stream.read<int32_t>();
64 const auto skinReferenceOffset = stream.read<int32_t>();
66 const auto bodyPartCount = stream.read<int32_t>();
67 const auto bodyPartOffset = stream.read<int32_t>();
71 stream.seek(boneOffset);
72 for (
int i = 0; i < boneCount; i++) {
73 auto& bone = this->
bones.emplace_back();
78 .read(bone.boneController)
80 .read(bone.rotationQuat)
81 .read(bone.rotationEuler)
82 .read(bone.positionScale)
83 .read(bone.rotationScale)
84 .read(bone.poseToBose)
89 .read(bone.physicsBone);
91 stream.read(bone.contents);
94 stream.skip<int32_t>(8);
97 stream.seek(boneControllerOffset);
98 for (
int i = 0; i < boneControllerCount; i++) {
102 stream.skip<int32_t>(8);
105 for (
int i = 0; i < hitboxSetCount; i++) {
106 const auto hitboxSetPos = hitboxSetOffset + i * (
sizeof(int32_t) * 3);
107 stream.seek_u(hitboxSetPos);
109 auto& hitboxSet = this->
hitboxSets.emplace_back();
112 const auto hitboxCount = stream.read<int32_t>();
113 const auto hitboxOffset = stream.read<int32_t>();
115 for (
int j = 0; j < hitboxCount; j++) {
116 const auto hitboxPos = hitboxOffset + j * (
sizeof(int32_t) * 11 +
sizeof(math::Vec3f) * 2);
117 stream.seek_u(hitboxSetPos + hitboxPos);
119 auto& hitbox = hitboxSet.hitboxes.emplace_back();
124 .read(hitbox.bboxMin)
125 .read(hitbox.bboxMax);
130 stream.skip<int32_t>();
134 stream.skip<int32_t>(8);
150 stream.seek(materialOffset);
151 for (
int i = 0; i < materialCount; i++) {
152 auto& material = this->
materials.emplace_back();
155 stream.read(material.flags);
158 stream.skip<int32_t>();
160 stream.skip<int32_t>(13);
163 stream.seek(materialDirOffset);
164 for (
int i = 0; i < materialDirCount; i++) {
170 stream.seek(skinReferenceOffset);
171 for (
int i = 0; i < skinReferenceFamilyCount; i++) {
172 std::vector<int16_t> skinFamily;
173 skinFamily.reserve(skinReferenceCount);
174 for (
int j = 0; j < skinReferenceCount; j++) {
175 skinFamily.push_back(stream.read<int16_t>());
177 this->
skins.push_back(std::move(skinFamily));
180 for (
int i = 0; i < bodyPartCount; i++) {
181 const auto bodyPartPos = bodyPartOffset + i * (
sizeof(int32_t) * 4);
182 stream.seek_u(bodyPartPos);
184 auto& bodyPart = this->
bodyParts.emplace_back();
188 const auto modelsCount = stream.read<int32_t>();
189 stream.skip<int32_t>();
190 const auto modelsOffset = stream.read<int32_t>();
192 for (
int j = 0; j < modelsCount; j++) {
193 auto modelPos = modelsOffset + j * (64 +
sizeof(float) +
sizeof(int32_t) * 20);
194 stream.seek_u(bodyPartPos + modelPos);
196 auto& model = bodyPart.models.emplace_back();
199 .read(model.name, 64)
201 .read(model.boundingRadius);
203 const auto meshesCount = stream.read<int32_t>();
204 const auto meshesOffset = stream.read<int32_t>();
207 .read(model.verticesCount)
208 .read(model.verticesOffset);
210 for (
int k = 0; k < meshesCount; k++) {
211 const auto meshPos = meshesOffset + k * (
sizeof(int32_t) * (18 +
MAX_LOD_COUNT) +
sizeof(math::Vec3f));
212 stream.seek_u(bodyPartPos + modelPos + meshPos);
214 auto& mesh = model.meshes.emplace_back();
219 .read(mesh.verticesCount)
220 .read(mesh.verticesOffset)
222 .read(mesh.materialType)
223 .read(mesh.materialParam)
constexpr int MAX_LOD_COUNT
void readStringAtOffset(BufferStream &stream, std::string &str, std::ios::seekdir offsetFrom=std::ios::cur, std::size_t subtractFromOffset=sizeof(int32_t))
Reads an integer from the stream, seeks there, reads a string, and seeks back.
sourcepp::math::Vec3f viewBBoxMax
sourcepp::math::Vec3f hullMax
std::vector< Material > materials
int32_t activityListVersion
bool open(const std::byte *data, std::size_t size)
sourcepp::math::Vec3f viewBBoxMin
sourcepp::math::Vec3f eyePosition
sourcepp::math::Vec3f hullMin
std::vector< std::vector< int16_t > > skins
std::vector< std::string > materialDirectories
sourcepp::math::Vec3f illuminationPosition
std::vector< BodyPart > bodyParts
std::vector< BoneController > boneControllers
std::vector< Bone > bones
std::vector< HitboxSet > hitboxSets