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