Coverage Report

Created: 2025-06-22 07:30

/src/assimp/code/AssetLib/Assbin/AssbinLoader.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
---------------------------------------------------------------------------
3
Open Asset Import Library (assimp)
4
---------------------------------------------------------------------------
5
6
Copyright (c) 2006-2025, assimp team
7
8
All rights reserved.
9
10
Redistribution and use of this software in source and binary forms,
11
with or without modification, are permitted provided that the following
12
conditions are met:
13
14
* Redistributions of source code must retain the above
15
  copyright notice, this list of conditions and the
16
  following disclaimer.
17
18
* Redistributions in binary form must reproduce the above
19
  copyright notice, this list of conditions and the
20
  following disclaimer in the documentation and/or other
21
  materials provided with the distribution.
22
23
* Neither the name of the assimp team, nor the names of its
24
  contributors may be used to endorse or promote products
25
  derived from this software without specific prior
26
  written permission of the assimp team.
27
28
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39
---------------------------------------------------------------------------
40
*/
41
42
/** @file  AssbinLoader.cpp
43
 *  @brief Implementation of the .assbin importer class
44
 *
45
 *  see assbin_chunks.h
46
 */
47
48
#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER
49
50
// internal headers
51
#include "AssbinLoader.h"
52
#include "Common/assbin_chunks.h"
53
#include <assimp/MemoryIOWrapper.h>
54
#include <assimp/anim.h>
55
#include <assimp/importerdesc.h>
56
#include <assimp/mesh.h>
57
#include <assimp/scene.h>
58
#include <memory>
59
60
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
61
#include <zlib.h>
62
#else
63
#include <contrib/zlib/zlib.h>
64
#endif
65
66
using namespace Assimp;
67
68
static constexpr aiImporterDesc desc = {
69
    "Assimp Binary Importer",
70
    "Gargaj / Conspiracy",
71
    "",
72
    "",
73
    aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_SupportCompressedFlavour,
74
    0,
75
    0,
76
    0,
77
    0,
78
    "assbin"
79
};
80
81
// -----------------------------------------------------------------------------------
82
2.35k
const aiImporterDesc *AssbinImporter::GetInfo() const {
83
2.35k
    return &desc;
84
2.35k
}
85
86
// -----------------------------------------------------------------------------------
87
86
bool AssbinImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
88
86
    IOStream *in = pIOHandler->Open(pFile);
89
86
    if (nullptr == in) {
90
0
        return false;
91
0
    }
92
93
86
    char s[32];
94
86
    const size_t read = in->Read(s, sizeof(char), 32);
95
96
86
    pIOHandler->Close(in);
97
98
86
    if (read < 19) {
99
0
      return false;
100
0
    }
101
102
86
    return strncmp(s, "ASSIMP.binary-dump.", 19) == 0;
103
86
}
104
105
// -----------------------------------------------------------------------------------
106
template <typename T>
107
7
T Read(IOStream *stream) {
108
7
    T t;
109
7
    size_t res = stream->Read(&t, sizeof(T), 1);
110
7
    if (res != 1) {
111
0
        throw DeadlyImportError("Unexpected EOF");
112
0
    }
113
7
    return t;
114
7
}
Unexecuted instantiation: float Read<float>(Assimp::IOStream*)
unsigned int Read<unsigned int>(Assimp::IOStream*)
Line
Count
Source
107
5
T Read(IOStream *stream) {
108
5
    T t;
109
5
    size_t res = stream->Read(&t, sizeof(T), 1);
110
5
    if (res != 1) {
111
0
        throw DeadlyImportError("Unexpected EOF");
112
0
    }
113
5
    return t;
114
5
}
Unexecuted instantiation: double Read<double>(Assimp::IOStream*)
unsigned short Read<unsigned short>(Assimp::IOStream*)
Line
Count
Source
107
2
T Read(IOStream *stream) {
108
2
    T t;
109
2
    size_t res = stream->Read(&t, sizeof(T), 1);
110
2
    if (res != 1) {
111
0
        throw DeadlyImportError("Unexpected EOF");
112
0
    }
113
2
    return t;
114
2
}
Unexecuted instantiation: bool Read<bool>(Assimp::IOStream*)
Unexecuted instantiation: int Read<int>(Assimp::IOStream*)
Unexecuted instantiation: unsigned long Read<unsigned long>(Assimp::IOStream*)
Unexecuted instantiation: aiColor3D Read<aiColor3D>(Assimp::IOStream*)
115
116
// -----------------------------------------------------------------------------------
117
template <>
118
0
aiVector3D Read<aiVector3D>(IOStream *stream) {
119
0
    aiVector3D v;
120
0
    v.x = Read<ai_real>(stream);
121
0
    v.y = Read<ai_real>(stream);
122
0
    v.z = Read<ai_real>(stream);
123
0
    return v;
124
0
}
125
126
// -----------------------------------------------------------------------------------
127
template <>
128
0
aiColor4D Read<aiColor4D>(IOStream *stream) {
129
0
    aiColor4D c;
130
0
    c.r = Read<ai_real>(stream);
131
0
    c.g = Read<ai_real>(stream);
132
0
    c.b = Read<ai_real>(stream);
133
0
    c.a = Read<ai_real>(stream);
134
0
    return c;
135
0
}
136
137
// -----------------------------------------------------------------------------------
138
template <>
139
0
aiQuaternion Read<aiQuaternion>(IOStream *stream) {
140
0
    aiQuaternion v;
141
0
    v.w = Read<ai_real>(stream);
142
0
    v.x = Read<ai_real>(stream);
143
0
    v.y = Read<ai_real>(stream);
144
0
    v.z = Read<ai_real>(stream);
145
0
    return v;
146
0
}
147
148
// -----------------------------------------------------------------------------------
149
template <>
150
0
aiString Read<aiString>(IOStream *stream) {
151
0
    aiString s;
152
0
    stream->Read(&s.length, 4, 1);
153
0
    if (s.length) {
154
0
        stream->Read(s.data, s.length, 1);
155
0
    }
156
0
    s.data[s.length] = 0;
157
158
0
    return s;
159
0
}
160
161
// -----------------------------------------------------------------------------------
162
template <>
163
0
aiVertexWeight Read<aiVertexWeight>(IOStream *stream) {
164
0
    aiVertexWeight w;
165
0
    w.mVertexId = Read<unsigned int>(stream);
166
0
    w.mWeight = Read<ai_real>(stream);
167
0
    return w;
168
0
}
169
170
// -----------------------------------------------------------------------------------
171
template <>
172
0
aiMatrix4x4 Read<aiMatrix4x4>(IOStream *stream) {
173
0
    aiMatrix4x4 m;
174
0
    for (unsigned int i = 0; i < 4; ++i) {
175
0
        for (unsigned int i2 = 0; i2 < 4; ++i2) {
176
0
            m[i][i2] = Read<ai_real>(stream);
177
0
        }
178
0
    }
179
0
    return m;
180
0
}
181
182
// -----------------------------------------------------------------------------------
183
template <>
184
0
aiVectorKey Read<aiVectorKey>(IOStream *stream) {
185
0
    aiVectorKey v;
186
0
    v.mTime = Read<double>(stream);
187
0
    v.mValue = Read<aiVector3D>(stream);
188
0
    return v;
189
0
}
190
191
// -----------------------------------------------------------------------------------
192
template <>
193
0
aiQuatKey Read<aiQuatKey>(IOStream *stream) {
194
0
    aiQuatKey v;
195
0
    v.mTime = Read<double>(stream);
196
0
    v.mValue = Read<aiQuaternion>(stream);
197
0
    return v;
198
0
}
199
200
// -----------------------------------------------------------------------------------
201
template <typename T>
202
0
void ReadArray(IOStream *stream, T *out, unsigned int size) {
203
0
    ai_assert(nullptr != stream);
204
0
    ai_assert(nullptr != out);
205
206
0
    for (unsigned int i = 0; i < size; i++) {
207
0
        out[i] = Read<T>(stream);
208
0
    }
209
0
}
Unexecuted instantiation: void ReadArray<aiVertexWeight>(Assimp::IOStream*, aiVertexWeight*, unsigned int)
Unexecuted instantiation: void ReadArray<aiVector3t<float> >(Assimp::IOStream*, aiVector3t<float>*, unsigned int)
Unexecuted instantiation: void ReadArray<aiColor4t<float> >(Assimp::IOStream*, aiColor4t<float>*, unsigned int)
Unexecuted instantiation: void ReadArray<aiVectorKey>(Assimp::IOStream*, aiVectorKey*, unsigned int)
Unexecuted instantiation: void ReadArray<aiQuatKey>(Assimp::IOStream*, aiQuatKey*, unsigned int)
210
211
// -----------------------------------------------------------------------------------
212
template <typename T>
213
0
void ReadBounds(IOStream *stream, T * /*p*/, unsigned int n) {
214
    // not sure what to do here, the data isn't really useful.
215
0
    stream->Seek(sizeof(T) * n, aiOrigin_CUR);
216
0
}
Unexecuted instantiation: void ReadBounds<aiVertexWeight>(Assimp::IOStream*, aiVertexWeight*, unsigned int)
Unexecuted instantiation: void ReadBounds<aiVector3t<float> >(Assimp::IOStream*, aiVector3t<float>*, unsigned int)
Unexecuted instantiation: void ReadBounds<aiColor4t<float> >(Assimp::IOStream*, aiColor4t<float>*, unsigned int)
Unexecuted instantiation: void ReadBounds<aiVectorKey>(Assimp::IOStream*, aiVectorKey*, unsigned int)
Unexecuted instantiation: void ReadBounds<aiQuatKey>(Assimp::IOStream*, aiQuatKey*, unsigned int)
217
218
// -----------------------------------------------------------------------------------
219
0
void AssbinImporter::ReadBinaryNode(IOStream *stream, aiNode **onode, aiNode *parent) {
220
0
    if (Read<uint32_t>(stream) != ASSBIN_CHUNK_AINODE)
221
0
        throw DeadlyImportError("Magic chunk identifiers are wrong!");
222
0
    /*uint32_t size =*/Read<uint32_t>(stream);
223
224
0
    std::unique_ptr<aiNode> node(new aiNode());
225
226
0
    node->mName = Read<aiString>(stream);
227
0
    node->mTransformation = Read<aiMatrix4x4>(stream);
228
0
    unsigned numChildren = Read<unsigned int>(stream);
229
0
    unsigned numMeshes = Read<unsigned int>(stream);
230
0
    unsigned int nb_metadata = Read<unsigned int>(stream);
231
232
0
    if (parent) {
233
0
        node->mParent = parent;
234
0
    }
235
236
0
    if (numMeshes) {
237
0
        node->mMeshes = new unsigned int[numMeshes];
238
0
        for (unsigned int i = 0; i < numMeshes; ++i) {
239
0
            node->mMeshes[i] = Read<unsigned int>(stream);
240
0
            node->mNumMeshes++;
241
0
        }
242
0
    }
243
244
0
    if (numChildren) {
245
0
        node->mChildren = new aiNode *[numChildren];
246
0
        for (unsigned int i = 0; i < numChildren; ++i) {
247
0
            ReadBinaryNode(stream, &node->mChildren[i], node.get());
248
0
            node->mNumChildren++;
249
0
        }
250
0
    }
251
252
0
    if (nb_metadata > 0) {
253
0
        node->mMetaData = aiMetadata::Alloc(nb_metadata);
254
0
        for (unsigned int i = 0; i < nb_metadata; ++i) {
255
0
            node->mMetaData->mKeys[i] = Read<aiString>(stream);
256
0
            node->mMetaData->mValues[i].mType = (aiMetadataType)Read<uint16_t>(stream);
257
0
            void *data = nullptr;
258
259
0
            switch (node->mMetaData->mValues[i].mType) {
260
0
            case AI_BOOL:
261
0
                data = new bool(Read<bool>(stream));
262
0
                break;
263
0
            case AI_INT32:
264
0
                data = new int32_t(Read<int32_t>(stream));
265
0
                break;
266
0
            case AI_UINT64:
267
0
                data = new uint64_t(Read<uint64_t>(stream));
268
0
                break;
269
0
            case AI_FLOAT:
270
0
                data = new ai_real(Read<ai_real>(stream));
271
0
                break;
272
0
            case AI_DOUBLE:
273
0
                data = new double(Read<double>(stream));
274
0
                break;
275
0
            case AI_AISTRING:
276
0
                data = new aiString(Read<aiString>(stream));
277
0
                break;
278
0
            case AI_AIVECTOR3D:
279
0
                data = new aiVector3D(Read<aiVector3D>(stream));
280
0
                break;
281
0
#ifndef SWIG
282
0
            case FORCE_32BIT:
283
0
#endif // SWIG
284
0
            default:
285
0
                break;
286
0
            }
287
288
0
            node->mMetaData->mValues[i].mData = data;
289
0
        }
290
0
    }
291
0
    *onode = node.release();
292
0
}
293
294
// -----------------------------------------------------------------------------------
295
0
void AssbinImporter::ReadBinaryBone(IOStream *stream, aiBone *b) {
296
0
    if (Read<uint32_t>(stream) != ASSBIN_CHUNK_AIBONE)
297
0
        throw DeadlyImportError("Magic chunk identifiers are wrong!");
298
0
    /*uint32_t size =*/Read<uint32_t>(stream);
299
300
0
    b->mName = Read<aiString>(stream);
301
0
    b->mNumWeights = Read<unsigned int>(stream);
302
0
    b->mOffsetMatrix = Read<aiMatrix4x4>(stream);
303
304
    // for the moment we write dumb min/max values for the bones, too.
305
    // maybe I'll add a better, hash-like solution later
306
0
    if (shortened) {
307
0
        ReadBounds(stream, b->mWeights, b->mNumWeights);
308
0
    } else {
309
        // else write as usual
310
0
        b->mWeights = new aiVertexWeight[b->mNumWeights];
311
0
        ReadArray<aiVertexWeight>(stream, b->mWeights, b->mNumWeights);
312
0
    }
313
0
}
314
315
// -----------------------------------------------------------------------------------
316
0
static bool fitsIntoUI16(unsigned int mNumVertices) {
317
0
    return (mNumVertices < (1u << 16));
318
0
}
319
320
// -----------------------------------------------------------------------------------
321
0
void AssbinImporter::ReadBinaryMesh(IOStream *stream, aiMesh *mesh) {
322
0
    if (Read<uint32_t>(stream) != ASSBIN_CHUNK_AIMESH)
323
0
        throw DeadlyImportError("Magic chunk identifiers are wrong!");
324
0
    /*uint32_t size =*/Read<uint32_t>(stream);
325
326
0
    mesh->mPrimitiveTypes = Read<unsigned int>(stream);
327
0
    mesh->mNumVertices = Read<unsigned int>(stream);
328
0
    mesh->mNumFaces = Read<unsigned int>(stream);
329
0
    mesh->mNumBones = Read<unsigned int>(stream);
330
0
    mesh->mMaterialIndex = Read<unsigned int>(stream);
331
332
    // first of all, write bits for all existent vertex components
333
0
    unsigned int c = Read<unsigned int>(stream);
334
335
0
    if (c & ASSBIN_MESH_HAS_POSITIONS) {
336
0
        if (shortened) {
337
0
            ReadBounds(stream, mesh->mVertices, mesh->mNumVertices);
338
0
        } else {
339
            // else write as usual
340
0
            mesh->mVertices = new aiVector3D[mesh->mNumVertices];
341
0
            ReadArray<aiVector3D>(stream, mesh->mVertices, mesh->mNumVertices);
342
0
        }
343
0
    }
344
0
    if (c & ASSBIN_MESH_HAS_NORMALS) {
345
0
        if (shortened) {
346
0
            ReadBounds(stream, mesh->mNormals, mesh->mNumVertices);
347
0
        } else {
348
            // else write as usual
349
0
            mesh->mNormals = new aiVector3D[mesh->mNumVertices];
350
0
            ReadArray<aiVector3D>(stream, mesh->mNormals, mesh->mNumVertices);
351
0
        }
352
0
    }
353
0
    if (c & ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS) {
354
0
        if (shortened) {
355
0
            ReadBounds(stream, mesh->mTangents, mesh->mNumVertices);
356
0
            ReadBounds(stream, mesh->mBitangents, mesh->mNumVertices);
357
0
        } else {
358
            // else write as usual
359
0
            mesh->mTangents = new aiVector3D[mesh->mNumVertices];
360
0
            ReadArray<aiVector3D>(stream, mesh->mTangents, mesh->mNumVertices);
361
0
            mesh->mBitangents = new aiVector3D[mesh->mNumVertices];
362
0
            ReadArray<aiVector3D>(stream, mesh->mBitangents, mesh->mNumVertices);
363
0
        }
364
0
    }
365
0
    for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS; ++n) {
366
0
        if (!(c & ASSBIN_MESH_HAS_COLOR(n))) {
367
0
            break;
368
0
        }
369
370
0
        if (shortened) {
371
0
            ReadBounds(stream, mesh->mColors[n], mesh->mNumVertices);
372
0
        } else {
373
            // else write as usual
374
0
            mesh->mColors[n] = new aiColor4D[mesh->mNumVertices];
375
0
            ReadArray<aiColor4D>(stream, mesh->mColors[n], mesh->mNumVertices);
376
0
        }
377
0
    }
378
0
    for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++n) {
379
0
        if (!(c & ASSBIN_MESH_HAS_TEXCOORD(n))) {
380
0
            break;
381
0
        }
382
383
        // write number of UV components
384
0
        mesh->mNumUVComponents[n] = Read<unsigned int>(stream);
385
386
0
        if (shortened) {
387
0
            ReadBounds(stream, mesh->mTextureCoords[n], mesh->mNumVertices);
388
0
        } else {
389
            // else write as usual
390
0
            mesh->mTextureCoords[n] = new aiVector3D[mesh->mNumVertices];
391
0
            ReadArray<aiVector3D>(stream, mesh->mTextureCoords[n], mesh->mNumVertices);
392
0
        }
393
0
    }
394
395
    // write faces. There are no floating-point calculations involved
396
    // in these, so we can write a simple hash over the face data
397
    // to the dump file. We generate a single 32 Bit hash for 512 faces
398
    // using Assimp's standard hashing function.
399
0
    if (shortened) {
400
0
        Read<unsigned int>(stream);
401
0
    } else {
402
        // else write as usual
403
        // if there are less than 2^16 vertices, we can simply use 16 bit integers ...
404
0
        mesh->mFaces = new aiFace[mesh->mNumFaces];
405
0
        for (unsigned int i = 0; i < mesh->mNumFaces; ++i) {
406
0
            aiFace &f = mesh->mFaces[i];
407
408
0
            static_assert(AI_MAX_FACE_INDICES <= 0xffff, "AI_MAX_FACE_INDICES <= 0xffff");
409
0
            f.mNumIndices = Read<uint16_t>(stream);
410
0
            f.mIndices = new unsigned int[f.mNumIndices];
411
412
0
            for (unsigned int a = 0; a < f.mNumIndices; ++a) {
413
                // Check if unsigned  short ( 16 bit  ) are big enough for the indices
414
0
                if (fitsIntoUI16(mesh->mNumVertices)) {
415
0
                    f.mIndices[a] = Read<uint16_t>(stream);
416
0
                } else {
417
0
                    f.mIndices[a] = Read<unsigned int>(stream);
418
0
                }
419
0
            }
420
0
        }
421
0
    }
422
423
    // write bones
424
0
    if (mesh->mNumBones) {
425
0
        mesh->mBones = new C_STRUCT aiBone *[mesh->mNumBones];
426
0
        for (unsigned int a = 0; a < mesh->mNumBones; ++a) {
427
0
            mesh->mBones[a] = new aiBone();
428
0
            ReadBinaryBone(stream, mesh->mBones[a]);
429
0
        }
430
0
    }
431
0
}
432
433
// -----------------------------------------------------------------------------------
434
0
void AssbinImporter::ReadBinaryMaterialProperty(IOStream *stream, aiMaterialProperty *prop) {
435
0
    if (Read<uint32_t>(stream) != ASSBIN_CHUNK_AIMATERIALPROPERTY)
436
0
        throw DeadlyImportError("Magic chunk identifiers are wrong!");
437
0
    /*uint32_t size =*/Read<uint32_t>(stream);
438
439
0
    prop->mKey = Read<aiString>(stream);
440
0
    prop->mSemantic = Read<unsigned int>(stream);
441
0
    prop->mIndex = Read<unsigned int>(stream);
442
443
0
    prop->mDataLength = Read<unsigned int>(stream);
444
0
    prop->mType = (aiPropertyTypeInfo)Read<unsigned int>(stream);
445
0
    prop->mData = new char[prop->mDataLength];
446
0
    stream->Read(prop->mData, 1, prop->mDataLength);
447
0
}
448
449
// -----------------------------------------------------------------------------------
450
0
void AssbinImporter::ReadBinaryMaterial(IOStream *stream, aiMaterial *mat) {
451
0
    if (Read<uint32_t>(stream) != ASSBIN_CHUNK_AIMATERIAL)
452
0
        throw DeadlyImportError("Magic chunk identifiers are wrong!");
453
0
    /*uint32_t size =*/Read<uint32_t>(stream);
454
455
0
    mat->mNumAllocated = mat->mNumProperties = Read<unsigned int>(stream);
456
0
    if (mat->mNumProperties) {
457
0
        if (mat->mProperties) {
458
0
            delete[] mat->mProperties;
459
0
        }
460
0
        mat->mProperties = new aiMaterialProperty *[mat->mNumProperties];
461
0
        for (unsigned int i = 0; i < mat->mNumProperties; ++i) {
462
0
            mat->mProperties[i] = new aiMaterialProperty();
463
0
            ReadBinaryMaterialProperty(stream, mat->mProperties[i]);
464
0
        }
465
0
    }
466
0
}
467
468
// -----------------------------------------------------------------------------------
469
0
void AssbinImporter::ReadBinaryNodeAnim(IOStream *stream, aiNodeAnim *nd) {
470
0
    if (Read<uint32_t>(stream) != ASSBIN_CHUNK_AINODEANIM)
471
0
        throw DeadlyImportError("Magic chunk identifiers are wrong!");
472
0
    /*uint32_t size =*/Read<uint32_t>(stream);
473
474
0
    nd->mNodeName = Read<aiString>(stream);
475
0
    nd->mNumPositionKeys = Read<unsigned int>(stream);
476
0
    nd->mNumRotationKeys = Read<unsigned int>(stream);
477
0
    nd->mNumScalingKeys = Read<unsigned int>(stream);
478
0
    nd->mPreState = (aiAnimBehaviour)Read<unsigned int>(stream);
479
0
    nd->mPostState = (aiAnimBehaviour)Read<unsigned int>(stream);
480
481
0
    if (nd->mNumPositionKeys) {
482
0
        if (shortened) {
483
0
            ReadBounds(stream, nd->mPositionKeys, nd->mNumPositionKeys);
484
485
0
        } // else write as usual
486
0
        else {
487
0
            nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys];
488
0
            ReadArray<aiVectorKey>(stream, nd->mPositionKeys, nd->mNumPositionKeys);
489
0
        }
490
0
    }
491
0
    if (nd->mNumRotationKeys) {
492
0
        if (shortened) {
493
0
            ReadBounds(stream, nd->mRotationKeys, nd->mNumRotationKeys);
494
495
0
        } else {
496
            // else write as usual
497
0
            nd->mRotationKeys = new aiQuatKey[nd->mNumRotationKeys];
498
0
            ReadArray<aiQuatKey>(stream, nd->mRotationKeys, nd->mNumRotationKeys);
499
0
        }
500
0
    }
501
0
    if (nd->mNumScalingKeys) {
502
0
        if (shortened) {
503
0
            ReadBounds(stream, nd->mScalingKeys, nd->mNumScalingKeys);
504
505
0
        } else {
506
            // else write as usual
507
0
            nd->mScalingKeys = new aiVectorKey[nd->mNumScalingKeys];
508
0
            ReadArray<aiVectorKey>(stream, nd->mScalingKeys, nd->mNumScalingKeys);
509
0
        }
510
0
    }
511
0
}
512
513
// -----------------------------------------------------------------------------------
514
0
void AssbinImporter::ReadBinaryAnim(IOStream *stream, aiAnimation *anim) {
515
0
    if (Read<uint32_t>(stream) != ASSBIN_CHUNK_AIANIMATION)
516
0
        throw DeadlyImportError("Magic chunk identifiers are wrong!");
517
0
    /*uint32_t size =*/Read<uint32_t>(stream);
518
519
0
    anim->mName = Read<aiString>(stream);
520
0
    anim->mDuration = Read<double>(stream);
521
0
    anim->mTicksPerSecond = Read<double>(stream);
522
0
    anim->mNumChannels = Read<unsigned int>(stream);
523
524
0
    if (anim->mNumChannels) {
525
0
        anim->mChannels = new aiNodeAnim *[anim->mNumChannels];
526
0
        for (unsigned int a = 0; a < anim->mNumChannels; ++a) {
527
0
            anim->mChannels[a] = new aiNodeAnim();
528
0
            ReadBinaryNodeAnim(stream, anim->mChannels[a]);
529
0
        }
530
0
    }
531
0
}
532
533
// -----------------------------------------------------------------------------------
534
0
void AssbinImporter::ReadBinaryTexture(IOStream *stream, aiTexture *tex) {
535
0
    if (Read<uint32_t>(stream) != ASSBIN_CHUNK_AITEXTURE)
536
0
        throw DeadlyImportError("Magic chunk identifiers are wrong!");
537
0
    /*uint32_t size =*/Read<uint32_t>(stream);
538
539
0
    tex->mWidth = Read<unsigned int>(stream);
540
0
    tex->mHeight = Read<unsigned int>(stream);
541
0
    stream->Read(tex->achFormatHint, sizeof(char), HINTMAXTEXTURELEN - 1);
542
543
0
    if (!shortened) {
544
0
        if (!tex->mHeight) {
545
0
            tex->pcData = new aiTexel[tex->mWidth];
546
0
            stream->Read(tex->pcData, 1, tex->mWidth);
547
0
        } else {
548
0
            tex->pcData = new aiTexel[tex->mWidth * tex->mHeight];
549
0
            stream->Read(tex->pcData, 1, tex->mWidth * tex->mHeight * 4);
550
0
        }
551
0
    }
552
0
}
553
554
// -----------------------------------------------------------------------------------
555
0
void AssbinImporter::ReadBinaryLight(IOStream *stream, aiLight *l) {
556
0
    if (Read<uint32_t>(stream) != ASSBIN_CHUNK_AILIGHT)
557
0
        throw DeadlyImportError("Magic chunk identifiers are wrong!");
558
0
    /*uint32_t size =*/Read<uint32_t>(stream);
559
560
0
    l->mName = Read<aiString>(stream);
561
0
    l->mType = (aiLightSourceType)Read<unsigned int>(stream);
562
563
0
    l->mPosition = Read<aiVector3D>(stream);
564
0
    l->mDirection = Read<aiVector3D>(stream);
565
0
    l->mUp = Read<aiVector3D>(stream);
566
567
0
    if (l->mType != aiLightSource_DIRECTIONAL) {
568
0
        l->mAttenuationConstant = Read<float>(stream);
569
0
        l->mAttenuationLinear = Read<float>(stream);
570
0
        l->mAttenuationQuadratic = Read<float>(stream);
571
0
    }
572
573
0
    l->mColorDiffuse = Read<aiColor3D>(stream);
574
0
    l->mColorSpecular = Read<aiColor3D>(stream);
575
0
    l->mColorAmbient = Read<aiColor3D>(stream);
576
577
0
    if (l->mType == aiLightSource_SPOT) {
578
0
        l->mAngleInnerCone = Read<float>(stream);
579
0
        l->mAngleOuterCone = Read<float>(stream);
580
0
    }
581
0
}
582
583
// -----------------------------------------------------------------------------------
584
0
void AssbinImporter::ReadBinaryCamera(IOStream *stream, aiCamera *cam) {
585
0
    if (Read<uint32_t>(stream) != ASSBIN_CHUNK_AICAMERA)
586
0
        throw DeadlyImportError("Magic chunk identifiers are wrong!");
587
0
    /*uint32_t size =*/Read<uint32_t>(stream);
588
589
0
    cam->mName = Read<aiString>(stream);
590
0
    cam->mPosition = Read<aiVector3D>(stream);
591
0
    cam->mLookAt = Read<aiVector3D>(stream);
592
0
    cam->mUp = Read<aiVector3D>(stream);
593
0
    cam->mHorizontalFOV = Read<float>(stream);
594
0
    cam->mClipPlaneNear = Read<float>(stream);
595
0
    cam->mClipPlaneFar = Read<float>(stream);
596
0
    cam->mAspect = Read<float>(stream);
597
0
}
598
599
// -----------------------------------------------------------------------------------
600
0
void AssbinImporter::ReadBinaryScene(IOStream *stream, aiScene *scene) {
601
0
    if (Read<uint32_t>(stream) != ASSBIN_CHUNK_AISCENE)
602
0
        throw DeadlyImportError("Magic chunk identifiers are wrong!");
603
0
    /*uint32_t size =*/Read<uint32_t>(stream);
604
605
0
    scene->mFlags = Read<unsigned int>(stream);
606
0
    scene->mNumMeshes = Read<unsigned int>(stream);
607
0
    scene->mNumMaterials = Read<unsigned int>(stream);
608
0
    scene->mNumAnimations = Read<unsigned int>(stream);
609
0
    scene->mNumTextures = Read<unsigned int>(stream);
610
0
    scene->mNumLights = Read<unsigned int>(stream);
611
0
    scene->mNumCameras = Read<unsigned int>(stream);
612
613
    // Read node graph
614
    //scene->mRootNode = new aiNode[1];
615
0
    ReadBinaryNode(stream, &scene->mRootNode, (aiNode *)nullptr);
616
617
    // Read all meshes
618
0
    if (scene->mNumMeshes) {
619
0
        scene->mMeshes = new aiMesh *[scene->mNumMeshes];
620
0
        memset(scene->mMeshes, 0, scene->mNumMeshes * sizeof(aiMesh *));
621
0
        for (unsigned int i = 0; i < scene->mNumMeshes; ++i) {
622
0
            scene->mMeshes[i] = new aiMesh();
623
0
            ReadBinaryMesh(stream, scene->mMeshes[i]);
624
0
        }
625
0
    }
626
627
    // Read materials
628
0
    if (scene->mNumMaterials) {
629
0
        scene->mMaterials = new aiMaterial *[scene->mNumMaterials];
630
0
        memset(scene->mMaterials, 0, scene->mNumMaterials * sizeof(aiMaterial *));
631
0
        for (unsigned int i = 0; i < scene->mNumMaterials; ++i) {
632
0
            scene->mMaterials[i] = new aiMaterial();
633
0
            ReadBinaryMaterial(stream, scene->mMaterials[i]);
634
0
        }
635
0
    }
636
637
    // Read all animations
638
0
    if (scene->mNumAnimations) {
639
0
        scene->mAnimations = new aiAnimation *[scene->mNumAnimations];
640
0
        memset(scene->mAnimations, 0, scene->mNumAnimations * sizeof(aiAnimation *));
641
0
        for (unsigned int i = 0; i < scene->mNumAnimations; ++i) {
642
0
            scene->mAnimations[i] = new aiAnimation();
643
0
            ReadBinaryAnim(stream, scene->mAnimations[i]);
644
0
        }
645
0
    }
646
647
    // Read all textures
648
0
    if (scene->mNumTextures) {
649
0
        scene->mTextures = new aiTexture *[scene->mNumTextures];
650
0
        memset(scene->mTextures, 0, scene->mNumTextures * sizeof(aiTexture *));
651
0
        for (unsigned int i = 0; i < scene->mNumTextures; ++i) {
652
0
            scene->mTextures[i] = new aiTexture();
653
0
            ReadBinaryTexture(stream, scene->mTextures[i]);
654
0
        }
655
0
    }
656
657
    // Read lights
658
0
    if (scene->mNumLights) {
659
0
        scene->mLights = new aiLight *[scene->mNumLights];
660
0
        memset(scene->mLights, 0, scene->mNumLights * sizeof(aiLight *));
661
0
        for (unsigned int i = 0; i < scene->mNumLights; ++i) {
662
0
            scene->mLights[i] = new aiLight();
663
0
            ReadBinaryLight(stream, scene->mLights[i]);
664
0
        }
665
0
    }
666
667
    // Read cameras
668
0
    if (scene->mNumCameras) {
669
0
        scene->mCameras = new aiCamera *[scene->mNumCameras];
670
0
        memset(scene->mCameras, 0, scene->mNumCameras * sizeof(aiCamera *));
671
0
        for (unsigned int i = 0; i < scene->mNumCameras; ++i) {
672
0
            scene->mCameras[i] = new aiCamera();
673
0
            ReadBinaryCamera(stream, scene->mCameras[i]);
674
0
        }
675
0
    }
676
0
}
677
678
// -----------------------------------------------------------------------------------
679
1
void AssbinImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
680
1
    IOStream *stream = pIOHandler->Open(pFile, "rb");
681
1
    if (nullptr == stream) {
682
0
        throw DeadlyImportError("ASSBIN: Could not open ", pFile);
683
0
    }
684
685
    // signature
686
1
    stream->Seek(44, aiOrigin_CUR);
687
688
1
    unsigned int versionMajor = Read<unsigned int>(stream);
689
1
    unsigned int versionMinor = Read<unsigned int>(stream);
690
1
    if (versionMinor != ASSBIN_VERSION_MINOR || versionMajor != ASSBIN_VERSION_MAJOR) {
691
0
        pIOHandler->Close(stream);
692
0
        throw DeadlyImportError("Invalid version, data format not compatible!");
693
0
    }
694
695
1
    /*unsigned int versionRevision =*/Read<unsigned int>(stream);
696
1
    /*unsigned int compileFlags =*/Read<unsigned int>(stream);
697
698
1
    shortened = Read<uint16_t>(stream) > 0;
699
1
    compressed = Read<uint16_t>(stream) > 0;
700
701
1
    if (shortened) {
702
0
        pIOHandler->Close(stream);
703
0
        throw DeadlyImportError("Shortened binaries are not supported!");
704
0
    }
705
706
1
    stream->Seek(256, aiOrigin_CUR); // original filename
707
1
    stream->Seek(128, aiOrigin_CUR); // options
708
1
    stream->Seek(64, aiOrigin_CUR); // padding
709
710
1
    if (compressed) {
711
1
        uLongf uncompressedSize = Read<uint32_t>(stream);
712
1
        uLongf compressedSize = static_cast<uLongf>(stream->FileSize() - stream->Tell());
713
714
1
        unsigned char *compressedData = new unsigned char[compressedSize];
715
1
        size_t len = stream->Read(compressedData, 1, compressedSize);
716
1
        ai_assert(len == compressedSize);
717
718
1
        unsigned char *uncompressedData = new unsigned char[uncompressedSize];
719
720
1
        int res = uncompress(uncompressedData, &uncompressedSize, compressedData, (uLong)len);
721
1
        if (res != Z_OK) {
722
1
            delete[] uncompressedData;
723
1
            delete[] compressedData;
724
1
            pIOHandler->Close(stream);
725
1
            throw DeadlyImportError("Zlib decompression failed.");
726
1
        }
727
728
0
        MemoryIOStream io(uncompressedData, uncompressedSize);
729
730
0
        ReadBinaryScene(&io, pScene);
731
732
0
        delete[] uncompressedData;
733
0
        delete[] compressedData;
734
0
    } else {
735
0
        ReadBinaryScene(stream, pScene);
736
0
    }
737
738
0
    pIOHandler->Close(stream);
739
0
}
740
741
#endif // !! ASSIMP_BUILD_NO_ASSBIN_IMPORTER