13 const auto openInternal = [
this, data, size, checksum = mdl.
checksum](
bool useTopology) {
14 BufferStreamReadOnly stream{data, size};
16 if (stream.read(this->version); this->version != 7) {
26 if (stream.read<int32_t>() != checksum) {
32 const auto materialReplacementListOffset = stream.read<int32_t>();
34 const auto bodyPartCount = stream.read<int32_t>();
35 const auto bodyPartOffset = stream.read<int32_t>();
37 if (materialReplacementListOffset > 0) {
38 stream.seek(materialReplacementListOffset);
40 for (
int i = 0; i < this->
numLODs; i++) {
41 const auto replacementListPos = materialReplacementListOffset + i * (
sizeof(int32_t) * 2);
42 stream.seek_u(replacementListPos);
46 const auto replacementCount = stream.read<int32_t>();
47 const auto replacementOffset = stream.read<int32_t>();
49 if (replacementCount > 0 && replacementOffset > 0) {
50 for (
int j = 0; j < replacementCount; j++) {
51 const auto replacementPos = replacementOffset + j * (
sizeof(int16_t) +
sizeof(int32_t));
52 stream.seek_u(replacementListPos + replacementPos);
54 auto& replacement = replacementList.emplace_back();
55 stream.read(replacement.materialID);
63 for (
int i = 0; i < bodyPartCount; i++) {
64 const auto bodyPartPos = bodyPartOffset + i * (
sizeof(int32_t) * 2);
65 stream.seek_u(bodyPartPos);
67 auto& bodyPart = this->
bodyParts.emplace_back();
69 const auto modelCount = stream.read<int32_t>();
70 const auto modelOffset = stream.read<int32_t>();
72 for (
int j = 0; j < modelCount; j++) {
73 const auto modelPos = modelOffset + j * (
sizeof(int32_t) * 2);
74 stream.seek_u(bodyPartPos + modelPos);
76 auto& model = bodyPart.models.emplace_back();
78 const auto modelLODCount = stream.read<int32_t>();
79 const auto modelLODOffset = stream.read<int32_t>();
81 for (
int k = 0; k < modelLODCount; k++) {
82 const auto modelLODPos = modelLODOffset + k * (
sizeof(int32_t) * 2 +
sizeof(float));
83 stream.seek_u(bodyPartPos + modelPos + modelLODPos);
85 auto& modelLOD = model.modelLODs.emplace_back();
87 const auto meshCount = stream.read<int32_t>();
88 const auto meshOffset = stream.read<int32_t>();
90 stream.read(modelLOD.switchDistance);
92 for (
int l = 0; l < meshCount; l++) {
93 const auto meshPos = meshOffset + l * (
sizeof(int32_t) * 2 +
sizeof(
Mesh::Flags));
94 stream.seek_u(bodyPartPos + modelPos + modelLODPos + meshPos);
96 auto& mesh = modelLOD.meshes.emplace_back();
98 const auto stripGroupCount = stream.read<int32_t>();
99 const auto stripGroupOffset = stream.read<int32_t>();
101 stream.read(mesh.flags);
103 for (
int m = 0; m < stripGroupCount; m++) {
104 int stripGroupNumInts = 6;
106 stripGroupNumInts += 2;
108 const auto stripGroupPos = stripGroupOffset + m * (
sizeof(int32_t) * stripGroupNumInts +
sizeof(
StripGroup::Flags));
109 stream.seek_u(bodyPartPos + modelPos + modelLODPos + meshPos + stripGroupPos);
111 auto& stripGroup = mesh.stripGroups.emplace_back();
113 const auto vertexCount = stream.read<int32_t>();
114 const auto vertexOffset = stream.read<int32_t>();
116 auto stripGroupCurrentPos = stream.tell();
117 stream.seek_u(bodyPartPos + modelPos + modelLODPos + meshPos + stripGroupPos + vertexOffset);
118 for (
int n = 0; n < vertexCount; n++) {
119 auto& vertex = stripGroup.vertices.emplace_back();
122 .read(vertex.boneWeightIndex)
123 .read(vertex.boneCount)
124 .read(vertex.meshVertexID)
125 .read(vertex.boneID);
127 stream.seek_u(stripGroupCurrentPos);
129 const auto indexCount = stream.read<int32_t>();
130 const auto indexOffset = stream.read<int32_t>();
132 stripGroupCurrentPos = stream.tell();
133 stream.seek_u(bodyPartPos + modelPos + modelLODPos + meshPos + stripGroupPos + indexOffset);
134 for (
int n = 0; n < indexCount; n++) {
135 auto& index = stripGroup.indices.emplace_back();
138 stream.seek_u(stripGroupCurrentPos);
140 const auto stripCount = stream.read<int32_t>();
141 const auto stripOffset = stream.read<int32_t>();
143 stream.read(stripGroup.flags);
146 const auto topologyIndexCount = stream.read<int32_t>();
147 const auto topologyIndexOffset = stream.read<int32_t>();
149 stripGroupCurrentPos = stream.tell();
150 stream.seek_u(bodyPartPos + modelPos + modelLODPos + meshPos + stripGroupPos + topologyIndexOffset);
151 for (
int n = 0; n < topologyIndexCount; n++) {
152 auto& topologyIndex = stripGroup.topologyIndices.emplace_back();
153 stream.read(topologyIndex);
155 stream.seek_u(stripGroupCurrentPos);
158 stream.seek_u(bodyPartPos + modelPos + modelLODPos + meshPos + stripGroupPos + stripOffset);
159 for (
int n = 0; n < stripCount; n++) {
160 auto& strip = stripGroup.strips.emplace_back();
162 const auto indicesCount = stream.read<int32_t>();
163 stream.read(strip.indicesOffset);
165 strip.indices = std::span(stripGroup.indices.begin() + strip.indicesOffset, indicesCount);
167 const auto verticesCount = stream.read<int32_t>();
168 stream.read(strip.verticesOffset);
170 strip.vertices = std::span(stripGroup.vertices.begin() + strip.verticesOffset, verticesCount);
173 .read(strip.boneCount)
177 const auto boneStateChangeCount = stream.read<int32_t>();
178 const auto boneStateChangeOffset = stream.read<int32_t>();
180 if (boneStateChangeCount > 0 && boneStateChangeOffset > 0) {
181 const auto savedPos = stream.tell();
182 constexpr auto stripHeaderSize =
sizeof(int32_t) * 6 +
sizeof(int16_t) +
sizeof(
Strip::Flags);
183 const auto stripBasePos = bodyPartPos + modelPos + modelLODPos + meshPos + stripGroupPos + stripOffset + n * stripHeaderSize;
184 stream.seek_u(stripBasePos + boneStateChangeOffset);
186 for (
int p = 0; p < boneStateChangeCount; p++) {
187 auto& boneStateChange = strip.boneStateChanges.emplace_back();
189 .read(boneStateChange.hardwareID)
190 .read(boneStateChange.newBoneID);
193 stream.seek_u(savedPos);
197 const auto topologyIndicesCount = stream.read<int32_t>();
198 stream.read(strip.topologyIndicesOffset);
200 strip.topologyIndices = std::span(stripGroup.topologyIndices.begin() + strip.topologyIndicesOffset, topologyIndicesCount);
211 switch (hasTopologyIndices) {
213 const bool useTopology = mdl.
version == 49;
215 return openInternal(useTopology);
216 }
catch (
const std::overflow_error&) {
218 return openInternal(
false);
224 return openInternal(
false);
226 return openInternal(
true);
228 return openInternal(
false);