diff options
Diffstat (limited to 'src/3rdparty/assimp/code/AssbinLoader.cpp')
-rw-r--r-- | src/3rdparty/assimp/code/AssbinLoader.cpp | 686 |
1 files changed, 686 insertions, 0 deletions
diff --git a/src/3rdparty/assimp/code/AssbinLoader.cpp b/src/3rdparty/assimp/code/AssbinLoader.cpp new file mode 100644 index 000000000..c4261c4cb --- /dev/null +++ b/src/3rdparty/assimp/code/AssbinLoader.cpp @@ -0,0 +1,686 @@ +/* +--------------------------------------------------------------------------- +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 AssbinLoader.cpp + * @brief Implementation of the .assbin importer class + * + * see assbin_chunks.h + */ + +#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER + +// internal headers +#include "AssbinLoader.h" +#include "assbin_chunks.h" +#include "MemoryIOWrapper.h" +#include <assimp/mesh.h> +#include <assimp/anim.h> +#include <assimp/scene.h> + +#ifdef ASSIMP_BUILD_NO_OWN_ZLIB +# include <zlib.h> +#else +# include <contrib/zlib/zlib.h> +#endif + +using namespace Assimp; + +static const aiImporterDesc desc = { + ".assbin Importer", + "Gargaj / Conspiracy", + "", + "", + aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_SupportCompressedFlavour, + 0, + 0, + 0, + 0, + "assbin" +}; + +const aiImporterDesc* AssbinImporter::GetInfo() const +{ + return &desc; +} + +bool AssbinImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/ ) const +{ + IOStream * in = pIOHandler->Open(pFile); + if (!in) + return false; + + char s[32]; + in->Read( s, sizeof(char), 32 ); + + pIOHandler->Close(in); + + return strncmp( s, "ASSIMP.binary-dump.", 19 ) == 0; +} + +template <typename T> +T Read(IOStream * stream) +{ + T t; + stream->Read( &t, sizeof(T), 1 ); + return t; +} + +template <> +aiVector3D Read<aiVector3D>(IOStream * stream) +{ + aiVector3D v; + v.x = Read<float>(stream); + v.y = Read<float>(stream); + v.z = Read<float>(stream); + return v; +} + +template <> +aiColor4D Read<aiColor4D>(IOStream * stream) +{ + aiColor4D c; + c.r = Read<float>(stream); + c.g = Read<float>(stream); + c.b = Read<float>(stream); + c.a = Read<float>(stream); + return c; +} + +template <> +aiQuaternion Read<aiQuaternion>(IOStream * stream) +{ + aiQuaternion v; + v.w = Read<float>(stream); + v.x = Read<float>(stream); + v.y = Read<float>(stream); + v.z = Read<float>(stream); + return v; +} + +template <> +aiString Read<aiString>(IOStream * stream) +{ + aiString s; + stream->Read(&s.length,4,1); + stream->Read(s.data,s.length,1); + s.data[s.length] = 0; + return s; +} + +template <> +aiVertexWeight Read<aiVertexWeight>(IOStream * stream) +{ + aiVertexWeight w; + w.mVertexId = Read<unsigned int>(stream); + w.mWeight = Read<float>(stream); + return w; +} + +template <> +aiMatrix4x4 Read<aiMatrix4x4>(IOStream * stream) +{ + aiMatrix4x4 m; + for (unsigned int i = 0; i < 4;++i) { + for (unsigned int i2 = 0; i2 < 4;++i2) { + m[i][i2] = Read<float>(stream); + } + } + return m; +} + +template <> +aiVectorKey Read<aiVectorKey>(IOStream * stream) +{ + aiVectorKey v; + v.mTime = Read<double>(stream); + v.mValue = Read<aiVector3D>(stream); + return v; +} + +template <> +aiQuatKey Read<aiQuatKey>(IOStream * stream) +{ + aiQuatKey v; + v.mTime = Read<double>(stream); + v.mValue = Read<aiQuaternion>(stream); + return v; +} + +template <typename T> +void ReadArray(IOStream * stream, T * out, unsigned int size) +{ + for (unsigned int i=0; i<size; i++) out[i] = Read<T>(stream); +} + +template <typename T> void ReadBounds( IOStream * stream, T* /*p*/, unsigned int n ) +{ + // not sure what to do here, the data isn't really useful. + stream->Seek( sizeof(T) * n, aiOrigin_CUR ); +} + +void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** node ) +{ + uint32_t chunkID = Read<uint32_t>(stream); + ai_assert(chunkID == ASSBIN_CHUNK_AINODE); + /*uint32_t size =*/ Read<uint32_t>(stream); + + *node = new aiNode(); + + (*node)->mName = Read<aiString>(stream); + (*node)->mTransformation = Read<aiMatrix4x4>(stream); + (*node)->mNumChildren = Read<unsigned int>(stream); + (*node)->mNumMeshes = Read<unsigned int>(stream); + + if ((*node)->mNumMeshes) + { + (*node)->mMeshes = new unsigned int[(*node)->mNumMeshes]; + for (unsigned int i = 0; i < (*node)->mNumMeshes; ++i) { + (*node)->mMeshes[i] = Read<unsigned int>(stream); + } + } + + if ((*node)->mNumChildren) + { + (*node)->mChildren = new aiNode*[(*node)->mNumChildren]; + for (unsigned int i = 0; i < (*node)->mNumChildren; ++i) { + ReadBinaryNode( stream, &(*node)->mChildren[i] ); + } + } + +} + +// ----------------------------------------------------------------------------------- +void AssbinImporter::ReadBinaryBone( IOStream * stream, aiBone* b ) +{ + uint32_t chunkID = Read<uint32_t>(stream); + ai_assert(chunkID == ASSBIN_CHUNK_AIBONE); + /*uint32_t size =*/ Read<uint32_t>(stream); + + b->mName = Read<aiString>(stream); + b->mNumWeights = Read<unsigned int>(stream); + b->mOffsetMatrix = Read<aiMatrix4x4>(stream); + + // 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) + { + ReadBounds(stream,b->mWeights,b->mNumWeights); + } // else write as usual + else + { + b->mWeights = new aiVertexWeight[b->mNumWeights]; + ReadArray<aiVertexWeight>(stream,b->mWeights,b->mNumWeights); + } +} + + +void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh ) +{ + uint32_t chunkID = Read<uint32_t>(stream); + ai_assert(chunkID == ASSBIN_CHUNK_AIMESH); + /*uint32_t size =*/ Read<uint32_t>(stream); + + mesh->mPrimitiveTypes = Read<unsigned int>(stream); + mesh->mNumVertices = Read<unsigned int>(stream); + mesh->mNumFaces = Read<unsigned int>(stream); + mesh->mNumBones = Read<unsigned int>(stream); + mesh->mMaterialIndex = Read<unsigned int>(stream); + + // first of all, write bits for all existent vertex components + unsigned int c = Read<unsigned int>(stream); + + if (c & ASSBIN_MESH_HAS_POSITIONS) + { + if (shortened) { + ReadBounds(stream,mesh->mVertices,mesh->mNumVertices); + } // else write as usual + else + { + mesh->mVertices = new aiVector3D[mesh->mNumVertices]; + ReadArray<aiVector3D>(stream,mesh->mVertices,mesh->mNumVertices); + } + } + if (c & ASSBIN_MESH_HAS_NORMALS) + { + if (shortened) { + ReadBounds(stream,mesh->mNormals,mesh->mNumVertices); + } // else write as usual + else + { + mesh->mNormals = new aiVector3D[mesh->mNumVertices]; + ReadArray<aiVector3D>(stream,mesh->mNormals,mesh->mNumVertices); + } + } + if (c & ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS) + { + if (shortened) { + ReadBounds(stream,mesh->mTangents,mesh->mNumVertices); + ReadBounds(stream,mesh->mBitangents,mesh->mNumVertices); + } // else write as usual + else + { + mesh->mTangents = new aiVector3D[mesh->mNumVertices]; + ReadArray<aiVector3D>(stream,mesh->mTangents,mesh->mNumVertices); + mesh->mBitangents = new aiVector3D[mesh->mNumVertices]; + ReadArray<aiVector3D>(stream,mesh->mBitangents,mesh->mNumVertices); + } + } + for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) + { + if (!(c & ASSBIN_MESH_HAS_COLOR(n))) + break; + + if (shortened) + { + ReadBounds(stream,mesh->mColors[n],mesh->mNumVertices); + } // else write as usual + else + { + mesh->mColors[n] = new aiColor4D[mesh->mNumVertices]; + ReadArray<aiColor4D>(stream,mesh->mColors[n],mesh->mNumVertices); + } + } + for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) + { + if (!(c & ASSBIN_MESH_HAS_TEXCOORD(n))) + break; + + // write number of UV components + mesh->mNumUVComponents[n] = Read<unsigned int>(stream); + + if (shortened) { + ReadBounds(stream,mesh->mTextureCoords[n],mesh->mNumVertices); + } // else write as usual + else + { + mesh->mTextureCoords[n] = new aiVector3D[mesh->mNumVertices]; + ReadArray<aiVector3D>(stream,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) { + Read<unsigned int>(stream); + } + else // else write as usual + { + // if there are less than 2^16 vertices, we can simply use 16 bit integers ... + mesh->mFaces = new aiFace[mesh->mNumFaces]; + for (unsigned int i = 0; i < mesh->mNumFaces;++i) { + aiFace& f = mesh->mFaces[i]; + + static_assert(AI_MAX_FACE_INDICES <= 0xffff, "AI_MAX_FACE_INDICES <= 0xffff"); + f.mNumIndices = Read<uint16_t>(stream); + f.mIndices = new unsigned int[f.mNumIndices]; + + for (unsigned int a = 0; a < f.mNumIndices;++a) { + if (mesh->mNumVertices < (1u<<16)) + { + f.mIndices[a] = Read<uint16_t>(stream); + } + else + { + f.mIndices[a] = Read<unsigned int>(stream); + } + } + } + } + + // write bones + if (mesh->mNumBones) { + mesh->mBones = new C_STRUCT aiBone*[mesh->mNumBones]; + for (unsigned int a = 0; a < mesh->mNumBones;++a) { + mesh->mBones[a] = new aiBone(); + ReadBinaryBone(stream,mesh->mBones[a]); + } + } +} + +void AssbinImporter::ReadBinaryMaterialProperty(IOStream * stream, aiMaterialProperty* prop) +{ + uint32_t chunkID = Read<uint32_t>(stream); + ai_assert(chunkID == ASSBIN_CHUNK_AIMATERIALPROPERTY); + /*uint32_t size =*/ Read<uint32_t>(stream); + + prop->mKey = Read<aiString>(stream); + prop->mSemantic = Read<unsigned int>(stream); + prop->mIndex = Read<unsigned int>(stream); + + prop->mDataLength = Read<unsigned int>(stream); + prop->mType = (aiPropertyTypeInfo)Read<unsigned int>(stream); + prop->mData = new char [ prop->mDataLength ]; + stream->Read(prop->mData,1,prop->mDataLength); +} + +// ----------------------------------------------------------------------------------- +void AssbinImporter::ReadBinaryMaterial(IOStream * stream, aiMaterial* mat) +{ + uint32_t chunkID = Read<uint32_t>(stream); + ai_assert(chunkID == ASSBIN_CHUNK_AIMATERIAL); + /*uint32_t size =*/ Read<uint32_t>(stream); + + mat->mNumAllocated = mat->mNumProperties = Read<unsigned int>(stream); + if (mat->mNumProperties) + { + if (mat->mProperties) + { + delete[] mat->mProperties; + } + mat->mProperties = new aiMaterialProperty*[mat->mNumProperties]; + for (unsigned int i = 0; i < mat->mNumProperties;++i) { + mat->mProperties[i] = new aiMaterialProperty(); + ReadBinaryMaterialProperty( stream, mat->mProperties[i]); + } + } +} + +// ----------------------------------------------------------------------------------- +void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd) +{ + uint32_t chunkID = Read<uint32_t>(stream); + ai_assert(chunkID == ASSBIN_CHUNK_AINODEANIM); + /*uint32_t size =*/ Read<uint32_t>(stream); + + nd->mNodeName = Read<aiString>(stream); + nd->mNumPositionKeys = Read<unsigned int>(stream); + nd->mNumRotationKeys = Read<unsigned int>(stream); + nd->mNumScalingKeys = Read<unsigned int>(stream); + nd->mPreState = (aiAnimBehaviour)Read<unsigned int>(stream); + nd->mPostState = (aiAnimBehaviour)Read<unsigned int>(stream); + + if (nd->mNumPositionKeys) { + if (shortened) { + ReadBounds(stream,nd->mPositionKeys,nd->mNumPositionKeys); + + } // else write as usual + else { + nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys]; + ReadArray<aiVectorKey>(stream,nd->mPositionKeys,nd->mNumPositionKeys); + } + } + if (nd->mNumRotationKeys) { + if (shortened) { + ReadBounds(stream,nd->mRotationKeys,nd->mNumRotationKeys); + + } // else write as usual + else + { + nd->mRotationKeys = new aiQuatKey[nd->mNumRotationKeys]; + ReadArray<aiQuatKey>(stream,nd->mRotationKeys,nd->mNumRotationKeys); + } + } + if (nd->mNumScalingKeys) { + if (shortened) { + ReadBounds(stream,nd->mScalingKeys,nd->mNumScalingKeys); + + } // else write as usual + else + { + nd->mScalingKeys = new aiVectorKey[nd->mNumScalingKeys]; + ReadArray<aiVectorKey>(stream,nd->mScalingKeys,nd->mNumScalingKeys); + } + } +} + + +// ----------------------------------------------------------------------------------- +void AssbinImporter::ReadBinaryAnim( IOStream * stream, aiAnimation* anim ) +{ + uint32_t chunkID = Read<uint32_t>(stream); + ai_assert(chunkID == ASSBIN_CHUNK_AIANIMATION); + /*uint32_t size =*/ Read<uint32_t>(stream); + + anim->mName = Read<aiString> (stream); + anim->mDuration = Read<double> (stream); + anim->mTicksPerSecond = Read<double> (stream); + anim->mNumChannels = Read<unsigned int>(stream); + + if (anim->mNumChannels) + { + anim->mChannels = new aiNodeAnim*[ anim->mNumChannels ]; + for (unsigned int a = 0; a < anim->mNumChannels;++a) { + anim->mChannels[a] = new aiNodeAnim(); + ReadBinaryNodeAnim(stream,anim->mChannels[a]); + } + } +} + +void AssbinImporter::ReadBinaryTexture(IOStream * stream, aiTexture* tex) +{ + uint32_t chunkID = Read<uint32_t>(stream); + ai_assert(chunkID == ASSBIN_CHUNK_AITEXTURE); + /*uint32_t size =*/ Read<uint32_t>(stream); + + tex->mWidth = Read<unsigned int>(stream); + tex->mHeight = Read<unsigned int>(stream); + stream->Read( tex->achFormatHint, sizeof(char), 4 ); + + if(!shortened) { + if (!tex->mHeight) { + tex->pcData = new aiTexel[ tex->mWidth ]; + stream->Read(tex->pcData,1,tex->mWidth); + } + else { + tex->pcData = new aiTexel[ tex->mWidth*tex->mHeight ]; + stream->Read(tex->pcData,1,tex->mWidth*tex->mHeight*4); + } + } + +} + +// ----------------------------------------------------------------------------------- +void AssbinImporter::ReadBinaryLight( IOStream * stream, aiLight* l ) +{ + uint32_t chunkID = Read<uint32_t>(stream); + ai_assert(chunkID == ASSBIN_CHUNK_AILIGHT); + /*uint32_t size =*/ Read<uint32_t>(stream); + + l->mName = Read<aiString>(stream); + l->mType = (aiLightSourceType)Read<unsigned int>(stream); + + if (l->mType != aiLightSource_DIRECTIONAL) { + l->mAttenuationConstant = Read<float>(stream); + l->mAttenuationLinear = Read<float>(stream); + l->mAttenuationQuadratic = Read<float>(stream); + } + + l->mColorDiffuse = Read<aiColor3D>(stream); + l->mColorSpecular = Read<aiColor3D>(stream); + l->mColorAmbient = Read<aiColor3D>(stream); + + if (l->mType == aiLightSource_SPOT) { + l->mAngleInnerCone = Read<float>(stream); + l->mAngleOuterCone = Read<float>(stream); + } + +} + +// ----------------------------------------------------------------------------------- +void AssbinImporter::ReadBinaryCamera( IOStream * stream, aiCamera* cam ) +{ + uint32_t chunkID = Read<uint32_t>(stream); + ai_assert(chunkID == ASSBIN_CHUNK_AICAMERA); + /*uint32_t size =*/ Read<uint32_t>(stream); + + cam->mName = Read<aiString>(stream); + cam->mPosition = Read<aiVector3D>(stream); + cam->mLookAt = Read<aiVector3D>(stream); + cam->mUp = Read<aiVector3D>(stream); + cam->mHorizontalFOV = Read<float>(stream); + cam->mClipPlaneNear = Read<float>(stream); + cam->mClipPlaneFar = Read<float>(stream); + cam->mAspect = Read<float>(stream); +} + +void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) +{ + uint32_t chunkID = Read<uint32_t>(stream); + ai_assert(chunkID == ASSBIN_CHUNK_AISCENE); + /*uint32_t size =*/ Read<uint32_t>(stream); + + scene->mFlags = Read<unsigned int>(stream); + scene->mNumMeshes = Read<unsigned int>(stream); + scene->mNumMaterials = Read<unsigned int>(stream); + scene->mNumAnimations = Read<unsigned int>(stream); + scene->mNumTextures = Read<unsigned int>(stream); + scene->mNumLights = Read<unsigned int>(stream); + scene->mNumCameras = Read<unsigned int>(stream); + + // Read node graph + scene->mRootNode = new aiNode[1]; + ReadBinaryNode( stream, &scene->mRootNode ); + + // Read all meshes + if (scene->mNumMeshes) + { + scene->mMeshes = new aiMesh*[scene->mNumMeshes]; + for (unsigned int i = 0; i < scene->mNumMeshes;++i) { + scene->mMeshes[i] = new aiMesh(); + ReadBinaryMesh( stream,scene->mMeshes[i]); + } + } + + // Read materials + if (scene->mNumMaterials) + { + scene->mMaterials = new aiMaterial*[scene->mNumMaterials]; + for (unsigned int i = 0; i< scene->mNumMaterials; ++i) { + scene->mMaterials[i] = new aiMaterial(); + ReadBinaryMaterial(stream,scene->mMaterials[i]); + } + } + + // Read all animations + if (scene->mNumAnimations) + { + scene->mAnimations = new aiAnimation*[scene->mNumAnimations]; + for (unsigned int i = 0; i < scene->mNumAnimations;++i) { + scene->mAnimations[i] = new aiAnimation(); + ReadBinaryAnim(stream,scene->mAnimations[i]); + } + } + + // Read all textures + if (scene->mNumTextures) + { + scene->mTextures = new aiTexture*[scene->mNumTextures]; + for (unsigned int i = 0; i < scene->mNumTextures;++i) { + scene->mTextures[i] = new aiTexture(); + ReadBinaryTexture(stream,scene->mTextures[i]); + } + } + + // Read lights + if (scene->mNumLights) + { + scene->mLights = new aiLight*[scene->mNumLights]; + for (unsigned int i = 0; i < scene->mNumLights;++i) { + scene->mLights[i] = new aiLight(); + ReadBinaryLight(stream,scene->mLights[i]); + } + } + + // Read cameras + if (scene->mNumCameras) + { + scene->mCameras = new aiCamera*[scene->mNumCameras]; + for (unsigned int i = 0; i < scene->mNumCameras;++i) { + scene->mCameras[i] = new aiCamera(); + ReadBinaryCamera(stream,scene->mCameras[i]); + } + } + +} + +void AssbinImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler ) +{ + IOStream * stream = pIOHandler->Open(pFile,"rb"); + if (!stream) + return; + + stream->Seek( 44, aiOrigin_CUR ); // signature + + /*unsigned int versionMajor =*/ Read<unsigned int>(stream); + /*unsigned int versionMinor =*/ Read<unsigned int>(stream); + /*unsigned int versionRevision =*/ Read<unsigned int>(stream); + /*unsigned int compileFlags =*/ Read<unsigned int>(stream); + + shortened = Read<uint16_t>(stream) > 0; + compressed = Read<uint16_t>(stream) > 0; + + if (shortened) + throw DeadlyImportError( "Shortened binaries are not supported!" ); + + stream->Seek( 256, aiOrigin_CUR ); // original filename + stream->Seek( 128, aiOrigin_CUR ); // options + stream->Seek( 64, aiOrigin_CUR ); // padding + + if (compressed) + { + uLongf uncompressedSize = Read<uint32_t>(stream); + uLongf compressedSize = stream->FileSize() - stream->Tell(); + + unsigned char * compressedData = new unsigned char[ compressedSize ]; + stream->Read( compressedData, 1, compressedSize ); + + unsigned char * uncompressedData = new unsigned char[ uncompressedSize ]; + + uncompress( uncompressedData, &uncompressedSize, compressedData, compressedSize ); + + MemoryIOStream io( uncompressedData, uncompressedSize ); + + ReadBinaryScene(&io,pScene); + + delete[] uncompressedData; + delete[] compressedData; + } + else + { + ReadBinaryScene(stream,pScene); + } + + pIOHandler->Close(stream); +} + +#endif // !! ASSIMP_BUILD_NO_ASSBIN_IMPORTER |