diff options
author | Sean Harmer <sean.harmer@kdab.com> | 2017-05-24 12:09:44 +0100 |
---|---|---|
committer | Sean Harmer <sean.harmer@kdab.com> | 2017-05-24 12:10:02 +0100 |
commit | 77d294db076dac19e8b549b445ffede9f7260c84 (patch) | |
tree | 828ee7a6862ec5c0bd24f97cb540625a2c647376 /src/3rdparty/assimp/code/AssbinExporter.cpp | |
parent | 59f8fec8a41606b3185fe3a4e276978e3e1ed5ef (diff) | |
parent | 939b9b4b7591e8a421cf048a0a84ed3e75d81d21 (diff) |
Merge branch 'dev' into wip/animationwip/animation
Change-Id: I6e770609c90a7745d08fa4e2f424e865678c5d6f
Diffstat (limited to 'src/3rdparty/assimp/code/AssbinExporter.cpp')
-rw-r--r-- | src/3rdparty/assimp/code/AssbinExporter.cpp | 768 |
1 files changed, 768 insertions, 0 deletions
diff --git a/src/3rdparty/assimp/code/AssbinExporter.cpp b/src/3rdparty/assimp/code/AssbinExporter.cpp new file mode 100644 index 000000000..9240d3739 --- /dev/null +++ b/src/3rdparty/assimp/code/AssbinExporter.cpp @@ -0,0 +1,768 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2016, assimp team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ +/** @file AssbinExporter.cpp + * ASSBIN exporter main code + */ +#include "assbin_chunks.h" +#include <assimp/version.h> +#include <assimp/IOStream.hpp> +#include <assimp/IOSystem.hpp> +#include <assimp/Exporter.hpp> +#include "ProcessHelper.h" +#include "Exceptional.h" + +#ifdef ASSIMP_BUILD_NO_OWN_ZLIB +# include <zlib.h> +#else +# include "../contrib/zlib/zlib.h" +#endif + +#include <time.h> + + +#ifndef ASSIMP_BUILD_NO_EXPORT +#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER + +using namespace Assimp; + +namespace Assimp { + +template <typename T> +size_t Write(IOStream * stream, const T& v) +{ + return stream->Write( &v, sizeof(T), 1 ); +} + + +// ----------------------------------------------------------------------------------- +// Serialize an aiString +template <> +inline size_t Write<aiString>(IOStream * stream, const aiString& s) +{ + const size_t s2 = (uint32_t)s.length; + stream->Write(&s,4,1); + stream->Write(s.data,s2,1); + return s2+4; +} + +// ----------------------------------------------------------------------------------- +// Serialize an unsigned int as uint32_t +template <> +inline size_t Write<unsigned int>(IOStream * stream, const unsigned int& w) +{ + const uint32_t t = (uint32_t)w; + if (w > t) { + // this shouldn't happen, integers in Assimp data structures never exceed 2^32 + throw new DeadlyExportError("loss of data due to 64 -> 32 bit integer conversion"); + } + + stream->Write(&t,4,1); + return 4; +} + +// ----------------------------------------------------------------------------------- +// Serialize an unsigned int as uint16_t +template <> +inline size_t Write<uint16_t>(IOStream * stream, const uint16_t& w) +{ + static_assert(sizeof(uint16_t)==2, "sizeof(uint16_t)==2"); + stream->Write(&w,2,1); + return 2; +} + +// ----------------------------------------------------------------------------------- +// Serialize a float +template <> +inline size_t Write<float>(IOStream * stream, const float& f) +{ + static_assert(sizeof(float)==4, "sizeof(float)==4"); + stream->Write(&f,4,1); + return 4; +} + +// ----------------------------------------------------------------------------------- +// Serialize a double +template <> +inline size_t Write<double>(IOStream * stream, const double& f) +{ + static_assert(sizeof(double)==8, "sizeof(double)==8"); + stream->Write(&f,8,1); + return 8; +} + +// ----------------------------------------------------------------------------------- +// Serialize a vec3 +template <> +inline size_t Write<aiVector3D>(IOStream * stream, const aiVector3D& v) +{ + size_t t = Write<float>(stream,v.x); + t += Write<float>(stream,v.y); + t += Write<float>(stream,v.z); + return t; +} + +// ----------------------------------------------------------------------------------- +// Serialize a color value +template <> +inline size_t Write<aiColor4D>(IOStream * stream, const aiColor4D& v) +{ + size_t t = Write<float>(stream,v.r); + t += Write<float>(stream,v.g); + t += Write<float>(stream,v.b); + t += Write<float>(stream,v.a); + return t; +} + +// ----------------------------------------------------------------------------------- +// Serialize a quaternion +template <> +inline size_t Write<aiQuaternion>(IOStream * stream, const aiQuaternion& v) +{ + size_t t = Write<float>(stream,v.w); + t += Write<float>(stream,v.x); + t += Write<float>(stream,v.y); + t += Write<float>(stream,v.z); + return 16; +} + + +// ----------------------------------------------------------------------------------- +// Serialize a vertex weight +template <> +inline size_t Write<aiVertexWeight>(IOStream * stream, const aiVertexWeight& v) +{ + size_t t = Write<unsigned int>(stream,v.mVertexId); + return t+Write<float>(stream,v.mWeight); +} + +// ----------------------------------------------------------------------------------- +// Serialize a mat4x4 +template <> +inline size_t Write<aiMatrix4x4>(IOStream * stream, const aiMatrix4x4& m) +{ + for (unsigned int i = 0; i < 4;++i) { + for (unsigned int i2 = 0; i2 < 4;++i2) { + Write<float>(stream,m[i][i2]); + } + } + return 64; +} + +// ----------------------------------------------------------------------------------- +// Serialize an aiVectorKey +template <> +inline size_t Write<aiVectorKey>(IOStream * stream, const aiVectorKey& v) +{ + const size_t t = Write<double>(stream,v.mTime); + return t + Write<aiVector3D>(stream,v.mValue); +} + +// ----------------------------------------------------------------------------------- +// Serialize an aiQuatKey +template <> +inline size_t Write<aiQuatKey>(IOStream * stream, const aiQuatKey& v) +{ + const size_t t = Write<double>(stream,v.mTime); + return t + Write<aiQuaternion>(stream,v.mValue); +} + +template <typename T> +inline size_t WriteBounds(IOStream * stream, const T* in, unsigned int size) +{ + T minc,maxc; + ArrayBounds(in,size,minc,maxc); + + const size_t t = Write<T>(stream,minc); + return t + Write<T>(stream,maxc); +} + +// We use this to write out non-byte arrays so that we write using the specializations. +// This way we avoid writing out extra bytes that potentially come from struct alignment. +template <typename T> +inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size) +{ + size_t n = 0; + for (unsigned int i=0; i<size; i++) n += Write<T>(stream,in[i]); + return n; +} + + // ---------------------------------------------------------------------------------- + /** @class AssbinChunkWriter + * @brief Chunk writer mechanism for the .assbin file structure + * + * This is a standard in-memory IOStream (most of the code is based on BlobIOStream), + * the difference being that this takes another IOStream as a "container" in the + * constructor, and when it is destroyed, it appends the magic number, the chunk size, + * and the chunk contents to the container stream. This allows relatively easy chunk + * chunk construction, even recursively. + */ + class AssbinChunkWriter : public IOStream + { + private: + + uint8_t* buffer; + uint32_t magic; + IOStream * container; + size_t cur_size, cursor, initial; + + private: + // ------------------------------------------------------------------- + void Grow(size_t need = 0) + { + size_t new_size = std::max(initial, std::max( need, cur_size+(cur_size>>1) )); + + const uint8_t* const old = buffer; + buffer = new uint8_t[new_size]; + + if (old) { + memcpy(buffer,old,cur_size); + delete[] old; + } + + cur_size = new_size; + } + + public: + + AssbinChunkWriter( IOStream * container, uint32_t magic, size_t initial = 4096) + : buffer(NULL), magic(magic), container(container), cur_size(0), cursor(0), initial(initial) + { + } + + virtual ~AssbinChunkWriter() + { + if (container) { + container->Write( &magic, sizeof(uint32_t), 1 ); + container->Write( &cursor, sizeof(uint32_t), 1 ); + container->Write( buffer, 1, cursor ); + } + if (buffer) delete[] buffer; + } + + void * GetBufferPointer() { return buffer; } + + // ------------------------------------------------------------------- + virtual size_t Read(void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) { return 0; } + virtual aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/) { return aiReturn_FAILURE; } + virtual size_t Tell() const { return cursor; } + virtual void Flush() { } + + virtual size_t FileSize() const + { + return cursor; + } + + // ------------------------------------------------------------------- + virtual size_t Write(const void* pvBuffer, size_t pSize, size_t pCount) + { + pSize *= pCount; + if (cursor + pSize > cur_size) { + Grow(cursor + pSize); + } + + memcpy(buffer+cursor, pvBuffer, pSize); + cursor += pSize; + + return pCount; + } + + }; + + // ---------------------------------------------------------------------------------- + /** @class AssbinExport + * @brief Assbin exporter class + * + * This class performs the .assbin exporting, and is responsible for the file layout. + */ + class AssbinExport + { + private: + bool shortened; + bool compressed; + + protected: + + // ----------------------------------------------------------------------------------- + void WriteBinaryNode( IOStream * container, const aiNode* node) + { + AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AINODE ); + + Write<aiString>(&chunk,node->mName); + Write<aiMatrix4x4>(&chunk,node->mTransformation); + Write<unsigned int>(&chunk,node->mNumChildren); + Write<unsigned int>(&chunk,node->mNumMeshes); + + for (unsigned int i = 0; i < node->mNumMeshes;++i) { + Write<unsigned int>(&chunk,node->mMeshes[i]); + } + + for (unsigned int i = 0; i < node->mNumChildren;++i) { + WriteBinaryNode( &chunk, node->mChildren[i] ); + } + } + + // ----------------------------------------------------------------------------------- + void WriteBinaryTexture(IOStream * container, const aiTexture* tex) + { + AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AITEXTURE ); + + Write<unsigned int>(&chunk,tex->mWidth); + Write<unsigned int>(&chunk,tex->mHeight); + chunk.Write( tex->achFormatHint, sizeof(char), 4 ); + + if(!shortened) { + if (!tex->mHeight) { + chunk.Write(tex->pcData,1,tex->mWidth); + } + else { + chunk.Write(tex->pcData,1,tex->mWidth*tex->mHeight*4); + } + } + + } + + // ----------------------------------------------------------------------------------- + void WriteBinaryBone(IOStream * container, const aiBone* b) + { + AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIBONE ); + + Write<aiString>(&chunk,b->mName); + Write<unsigned int>(&chunk,b->mNumWeights); + Write<aiMatrix4x4>(&chunk,b->mOffsetMatrix); + + // for the moment we write dumb min/max values for the bones, too. + // maybe I'll add a better, hash-like solution later + if (shortened) { + WriteBounds(&chunk,b->mWeights,b->mNumWeights); + } // else write as usual + else WriteArray<aiVertexWeight>(&chunk,b->mWeights,b->mNumWeights); + } + + // ----------------------------------------------------------------------------------- + void WriteBinaryMesh(IOStream * container, const aiMesh* mesh) + { + AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIMESH ); + + Write<unsigned int>(&chunk,mesh->mPrimitiveTypes); + Write<unsigned int>(&chunk,mesh->mNumVertices); + Write<unsigned int>(&chunk,mesh->mNumFaces); + Write<unsigned int>(&chunk,mesh->mNumBones); + Write<unsigned int>(&chunk,mesh->mMaterialIndex); + + // first of all, write bits for all existent vertex components + unsigned int c = 0; + if (mesh->mVertices) { + c |= ASSBIN_MESH_HAS_POSITIONS; + } + if (mesh->mNormals) { + c |= ASSBIN_MESH_HAS_NORMALS; + } + if (mesh->mTangents && mesh->mBitangents) { + c |= ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS; + } + for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) { + if (!mesh->mTextureCoords[n]) { + break; + } + c |= ASSBIN_MESH_HAS_TEXCOORD(n); + } + for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) { + if (!mesh->mColors[n]) { + break; + } + c |= ASSBIN_MESH_HAS_COLOR(n); + } + Write<unsigned int>(&chunk,c); + + aiVector3D minVec, maxVec; + if (mesh->mVertices) { + if (shortened) { + WriteBounds(&chunk,mesh->mVertices,mesh->mNumVertices); + } // else write as usual + else WriteArray<aiVector3D>(&chunk,mesh->mVertices,mesh->mNumVertices); + } + if (mesh->mNormals) { + if (shortened) { + WriteBounds(&chunk,mesh->mNormals,mesh->mNumVertices); + } // else write as usual + else WriteArray<aiVector3D>(&chunk,mesh->mNormals,mesh->mNumVertices); + } + if (mesh->mTangents && mesh->mBitangents) { + if (shortened) { + WriteBounds(&chunk,mesh->mTangents,mesh->mNumVertices); + WriteBounds(&chunk,mesh->mBitangents,mesh->mNumVertices); + } // else write as usual + else { + WriteArray<aiVector3D>(&chunk,mesh->mTangents,mesh->mNumVertices); + WriteArray<aiVector3D>(&chunk,mesh->mBitangents,mesh->mNumVertices); + } + } + for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) { + if (!mesh->mColors[n]) + break; + + if (shortened) { + WriteBounds(&chunk,mesh->mColors[n],mesh->mNumVertices); + } // else write as usual + else WriteArray<aiColor4D>(&chunk,mesh->mColors[n],mesh->mNumVertices); + } + for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) { + if (!mesh->mTextureCoords[n]) + break; + + // write number of UV components + Write<unsigned int>(&chunk,mesh->mNumUVComponents[n]); + + if (shortened) { + WriteBounds(&chunk,mesh->mTextureCoords[n],mesh->mNumVertices); + } // else write as usual + else WriteArray<aiVector3D>(&chunk,mesh->mTextureCoords[n],mesh->mNumVertices); + } + + // write faces. There are no floating-point calculations involved + // in these, so we can write a simple hash over the face data + // to the dump file. We generate a single 32 Bit hash for 512 faces + // using Assimp's standard hashing function. + if (shortened) { + unsigned int processed = 0; + for (unsigned int job;(job = std::min(mesh->mNumFaces-processed,512u));processed += job) { + + uint32_t hash = 0; + for (unsigned int a = 0; a < job;++a) { + + const aiFace& f = mesh->mFaces[processed+a]; + uint32_t tmp = f.mNumIndices; + hash = SuperFastHash(reinterpret_cast<const char*>(&tmp),sizeof tmp,hash); + for (unsigned int i = 0; i < f.mNumIndices; ++i) { + static_assert(AI_MAX_VERTICES <= 0xffffffff, "AI_MAX_VERTICES <= 0xffffffff"); + tmp = static_cast<uint32_t>( f.mIndices[i] ); + hash = SuperFastHash(reinterpret_cast<const char*>(&tmp),sizeof tmp,hash); + } + } + Write<unsigned int>(&chunk,hash); + } + } + else // else write as usual + { + // if there are less than 2^16 vertices, we can simply use 16 bit integers ... + for (unsigned int i = 0; i < mesh->mNumFaces;++i) { + const aiFace& f = mesh->mFaces[i]; + + static_assert(AI_MAX_FACE_INDICES <= 0xffff, "AI_MAX_FACE_INDICES <= 0xffff"); + Write<uint16_t>(&chunk,f.mNumIndices); + + for (unsigned int a = 0; a < f.mNumIndices;++a) { + if (mesh->mNumVertices < (1u<<16)) { + Write<uint16_t>(&chunk,f.mIndices[a]); + } + else Write<unsigned int>(&chunk,f.mIndices[a]); + } + } + } + + // write bones + if (mesh->mNumBones) { + for (unsigned int a = 0; a < mesh->mNumBones;++a) { + const aiBone* b = mesh->mBones[a]; + WriteBinaryBone(&chunk,b); + } + } + } + + // ----------------------------------------------------------------------------------- + void WriteBinaryMaterialProperty(IOStream * container, const aiMaterialProperty* prop) + { + AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIMATERIALPROPERTY ); + + Write<aiString>(&chunk,prop->mKey); + Write<unsigned int>(&chunk,prop->mSemantic); + Write<unsigned int>(&chunk,prop->mIndex); + + Write<unsigned int>(&chunk,prop->mDataLength); + Write<unsigned int>(&chunk,(unsigned int)prop->mType); + chunk.Write(prop->mData,1,prop->mDataLength); + } + + // ----------------------------------------------------------------------------------- + void WriteBinaryMaterial(IOStream * container, const aiMaterial* mat) + { + AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIMATERIAL); + + Write<unsigned int>(&chunk,mat->mNumProperties); + for (unsigned int i = 0; i < mat->mNumProperties;++i) { + WriteBinaryMaterialProperty( &chunk, mat->mProperties[i]); + } + } + + // ----------------------------------------------------------------------------------- + void WriteBinaryNodeAnim(IOStream * container, const aiNodeAnim* nd) + { + AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AINODEANIM ); + + Write<aiString>(&chunk,nd->mNodeName); + Write<unsigned int>(&chunk,nd->mNumPositionKeys); + Write<unsigned int>(&chunk,nd->mNumRotationKeys); + Write<unsigned int>(&chunk,nd->mNumScalingKeys); + Write<unsigned int>(&chunk,nd->mPreState); + Write<unsigned int>(&chunk,nd->mPostState); + + if (nd->mPositionKeys) { + if (shortened) { + WriteBounds(&chunk,nd->mPositionKeys,nd->mNumPositionKeys); + + } // else write as usual + else WriteArray<aiVectorKey>(&chunk,nd->mPositionKeys,nd->mNumPositionKeys); + } + if (nd->mRotationKeys) { + if (shortened) { + WriteBounds(&chunk,nd->mRotationKeys,nd->mNumRotationKeys); + + } // else write as usual + else WriteArray<aiQuatKey>(&chunk,nd->mRotationKeys,nd->mNumRotationKeys); + } + if (nd->mScalingKeys) { + if (shortened) { + WriteBounds(&chunk,nd->mScalingKeys,nd->mNumScalingKeys); + + } // else write as usual + else WriteArray<aiVectorKey>(&chunk,nd->mScalingKeys,nd->mNumScalingKeys); + } + } + + + // ----------------------------------------------------------------------------------- + void WriteBinaryAnim( IOStream * container, const aiAnimation* anim ) + { + AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIANIMATION ); + + Write<aiString>(&chunk,anim->mName); + Write<double>(&chunk,anim->mDuration); + Write<double>(&chunk,anim->mTicksPerSecond); + Write<unsigned int>(&chunk,anim->mNumChannels); + + for (unsigned int a = 0; a < anim->mNumChannels;++a) { + const aiNodeAnim* nd = anim->mChannels[a]; + WriteBinaryNodeAnim(&chunk,nd); + } + } + + // ----------------------------------------------------------------------------------- + void WriteBinaryLight( IOStream * container, const aiLight* l ) + { + AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AILIGHT ); + + Write<aiString>(&chunk,l->mName); + Write<unsigned int>(&chunk,l->mType); + + if (l->mType != aiLightSource_DIRECTIONAL) { + Write<float>(&chunk,l->mAttenuationConstant); + Write<float>(&chunk,l->mAttenuationLinear); + Write<float>(&chunk,l->mAttenuationQuadratic); + } + + Write<aiVector3D>(&chunk,(const aiVector3D&)l->mColorDiffuse); + Write<aiVector3D>(&chunk,(const aiVector3D&)l->mColorSpecular); + Write<aiVector3D>(&chunk,(const aiVector3D&)l->mColorAmbient); + + if (l->mType == aiLightSource_SPOT) { + Write<float>(&chunk,l->mAngleInnerCone); + Write<float>(&chunk,l->mAngleOuterCone); + } + + } + + // ----------------------------------------------------------------------------------- + void WriteBinaryCamera( IOStream * container, const aiCamera* cam ) + { + AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AICAMERA ); + + Write<aiString>(&chunk,cam->mName); + Write<aiVector3D>(&chunk,cam->mPosition); + Write<aiVector3D>(&chunk,cam->mLookAt); + Write<aiVector3D>(&chunk,cam->mUp); + Write<float>(&chunk,cam->mHorizontalFOV); + Write<float>(&chunk,cam->mClipPlaneNear); + Write<float>(&chunk,cam->mClipPlaneFar); + Write<float>(&chunk,cam->mAspect); + } + + // ----------------------------------------------------------------------------------- + void WriteBinaryScene( IOStream * container, const aiScene* scene) + { + AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AISCENE ); + + // basic scene information + Write<unsigned int>(&chunk,scene->mFlags); + Write<unsigned int>(&chunk,scene->mNumMeshes); + Write<unsigned int>(&chunk,scene->mNumMaterials); + Write<unsigned int>(&chunk,scene->mNumAnimations); + Write<unsigned int>(&chunk,scene->mNumTextures); + Write<unsigned int>(&chunk,scene->mNumLights); + Write<unsigned int>(&chunk,scene->mNumCameras); + + // write node graph + WriteBinaryNode( &chunk, scene->mRootNode ); + + // write all meshes + for (unsigned int i = 0; i < scene->mNumMeshes;++i) { + const aiMesh* mesh = scene->mMeshes[i]; + WriteBinaryMesh( &chunk,mesh); + } + + // write materials + for (unsigned int i = 0; i< scene->mNumMaterials; ++i) { + const aiMaterial* mat = scene->mMaterials[i]; + WriteBinaryMaterial(&chunk,mat); + } + + // write all animations + for (unsigned int i = 0; i < scene->mNumAnimations;++i) { + const aiAnimation* anim = scene->mAnimations[i]; + WriteBinaryAnim(&chunk,anim); + } + + + // write all textures + for (unsigned int i = 0; i < scene->mNumTextures;++i) { + const aiTexture* mesh = scene->mTextures[i]; + WriteBinaryTexture(&chunk,mesh); + } + + // write lights + for (unsigned int i = 0; i < scene->mNumLights;++i) { + const aiLight* l = scene->mLights[i]; + WriteBinaryLight(&chunk,l); + } + + // write cameras + for (unsigned int i = 0; i < scene->mNumCameras;++i) { + const aiCamera* cam = scene->mCameras[i]; + WriteBinaryCamera(&chunk,cam); + } + + } + + public: + AssbinExport() + : shortened(false), compressed(false) // temporary settings until properties are introduced for exporters + { + } + + // ----------------------------------------------------------------------------------- + // Write a binary model dump + void WriteBinaryDump(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene) + { + IOStream * out = pIOSystem->Open( pFile, "wb" ); + if (!out) return; + + time_t tt = time(NULL); + tm* p = gmtime(&tt); + + // header + char s[64]; + memset( s, 0, 64 ); +#if _MSC_VER >= 1400 + sprintf_s(s,"ASSIMP.binary-dump.%s",asctime(p)); +#else + ai_snprintf(s,64,"ASSIMP.binary-dump.%s",asctime(p)); +#endif + out->Write( s, 44, 1 ); + // == 44 bytes + + Write<unsigned int>( out, ASSBIN_VERSION_MAJOR ); + Write<unsigned int>( out, ASSBIN_VERSION_MINOR ); + Write<unsigned int>( out, aiGetVersionRevision() ); + Write<unsigned int>( out, aiGetCompileFlags() ); + Write<uint16_t>( out, shortened ); + Write<uint16_t>( out, compressed ); + // == 20 bytes + + char buff[256]; + strncpy(buff,pFile,256); + out->Write(buff,sizeof(char),256); + + char cmd[] = "\0"; + strncpy(buff,cmd,128); + out->Write(buff,sizeof(char),128); + + // leave 64 bytes free for future extensions + memset(buff,0xcd,64); + out->Write(buff,sizeof(char),64); + // == 435 bytes + + // ==== total header size: 512 bytes + ai_assert( out->Tell() == ASSBIN_HEADER_LENGTH ); + + // Up to here the data is uncompressed. For compressed files, the rest + // is compressed using standard DEFLATE from zlib. + if (compressed) + { + AssbinChunkWriter uncompressedStream( NULL, 0 ); + WriteBinaryScene( &uncompressedStream, pScene ); + + uLongf uncompressedSize = uncompressedStream.Tell(); + uLongf compressedSize = (uLongf)(uncompressedStream.Tell() * 1.001 + 12.); + uint8_t* compressedBuffer = new uint8_t[ compressedSize ]; + + compress2( compressedBuffer, &compressedSize, (const Bytef*)uncompressedStream.GetBufferPointer(), uncompressedSize, 9 ); + + out->Write( &uncompressedSize, sizeof(uint32_t), 1 ); + out->Write( compressedBuffer, sizeof(char), compressedSize ); + + delete[] compressedBuffer; + } + else + { + WriteBinaryScene( out, pScene ); + } + + pIOSystem->Close( out ); + } + }; + +void ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties) +{ + AssbinExport exporter; + exporter.WriteBinaryDump( pFile, pIOSystem, pScene ); +} +} // end of namespace Assimp + +#endif // ASSIMP_BUILD_NO_ASSBIN_EXPORTER +#endif // ASSIMP_BUILD_NO_EXPORT |