From db81b925d776103326128bf629cbdda576a223e7 Mon Sep 17 00:00:00 2001 From: sanine Date: Sat, 16 Apr 2022 11:55:09 -0500 Subject: move 3rd-party librarys into libs/ and add built-in honeysuckle --- .../assimp/code/AssetLib/Assbin/AssbinExporter.cpp | 68 ++ libs/assimp/code/AssetLib/Assbin/AssbinExporter.h | 60 ++ .../code/AssetLib/Assbin/AssbinFileWriter.cpp | 833 +++++++++++++++++++++ .../assimp/code/AssetLib/Assbin/AssbinFileWriter.h | 65 ++ libs/assimp/code/AssetLib/Assbin/AssbinLoader.cpp | 730 ++++++++++++++++++ libs/assimp/code/AssetLib/Assbin/AssbinLoader.h | 99 +++ 6 files changed, 1855 insertions(+) create mode 100644 libs/assimp/code/AssetLib/Assbin/AssbinExporter.cpp create mode 100644 libs/assimp/code/AssetLib/Assbin/AssbinExporter.h create mode 100644 libs/assimp/code/AssetLib/Assbin/AssbinFileWriter.cpp create mode 100644 libs/assimp/code/AssetLib/Assbin/AssbinFileWriter.h create mode 100644 libs/assimp/code/AssetLib/Assbin/AssbinLoader.cpp create mode 100644 libs/assimp/code/AssetLib/Assbin/AssbinLoader.h (limited to 'libs/assimp/code/AssetLib/Assbin') diff --git a/libs/assimp/code/AssetLib/Assbin/AssbinExporter.cpp b/libs/assimp/code/AssetLib/Assbin/AssbinExporter.cpp new file mode 100644 index 0000000..149b3c5 --- /dev/null +++ b/libs/assimp/code/AssetLib/Assbin/AssbinExporter.cpp @@ -0,0 +1,68 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2022, 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 + */ + +#ifndef ASSIMP_BUILD_NO_EXPORT +#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER + +#include "AssbinFileWriter.h" + +#include +#include +#include + +namespace Assimp { + +void ExportSceneAssbin(const char *pFile, IOSystem *pIOSystem, const aiScene *pScene, const ExportProperties * /*pProperties*/) { + DumpSceneToAssbin( + pFile, + "\0", // no command(s). + pIOSystem, + pScene, + false, // shortened? + false); // compressed? +} +} // end of namespace Assimp + +#endif // ASSIMP_BUILD_NO_ASSBIN_EXPORTER +#endif // ASSIMP_BUILD_NO_EXPORT diff --git a/libs/assimp/code/AssetLib/Assbin/AssbinExporter.h b/libs/assimp/code/AssetLib/Assbin/AssbinExporter.h new file mode 100644 index 0000000..1801c16 --- /dev/null +++ b/libs/assimp/code/AssetLib/Assbin/AssbinExporter.h @@ -0,0 +1,60 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2022, 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.h + * ASSBIN Exporter Main Header + */ +#pragma once +#ifndef AI_ASSBINEXPORTER_H_INC +#define AI_ASSBINEXPORTER_H_INC + +#include + +#ifndef ASSIMP_BUILD_NO_EXPORT + +// nothing really needed here - reserved for future use like properties +namespace Assimp { + +void ASSIMP_API ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/); + +} +#endif +#endif // AI_ASSBINEXPORTER_H_INC diff --git a/libs/assimp/code/AssetLib/Assbin/AssbinFileWriter.cpp b/libs/assimp/code/AssetLib/Assbin/AssbinFileWriter.cpp new file mode 100644 index 0000000..1d16f17 --- /dev/null +++ b/libs/assimp/code/AssetLib/Assbin/AssbinFileWriter.cpp @@ -0,0 +1,833 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2022, 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 AssbinFileWriter.cpp + * @brief Implementation of Assbin file writer. + */ + +#include "AssbinFileWriter.h" +#include "Common/assbin_chunks.h" +#include "PostProcessing/ProcessHelper.h" + +#include +#include +#include + +#ifdef ASSIMP_BUILD_NO_OWN_ZLIB +#include +#else +#include "../contrib/zlib/zlib.h" +#endif + +#include + +#if _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4706) +#endif // _MSC_VER + +namespace Assimp { + +template +size_t Write(IOStream *stream, const T &v) { + return stream->Write(&v, sizeof(T), 1); +} + +// ----------------------------------------------------------------------------------- +// Serialize an aiString +template <> +inline size_t Write(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(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 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(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(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(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(IOStream *stream, const aiVector3D &v) { + size_t t = Write(stream, v.x); + t += Write(stream, v.y); + t += Write(stream, v.z); + + return t; +} + +// ----------------------------------------------------------------------------------- +// Serialize a color value +template <> +inline size_t Write(IOStream *stream, const aiColor3D &v) { + size_t t = Write(stream, v.r); + t += Write(stream, v.g); + t += Write(stream, v.b); + + return t; +} + +// ----------------------------------------------------------------------------------- +// Serialize a color value +template <> +inline size_t Write(IOStream *stream, const aiColor4D &v) { + size_t t = Write(stream, v.r); + t += Write(stream, v.g); + t += Write(stream, v.b); + t += Write(stream, v.a); + + return t; +} + +// ----------------------------------------------------------------------------------- +// Serialize a quaternion +template <> +inline size_t Write(IOStream *stream, const aiQuaternion &v) { + size_t t = Write(stream, v.w); + t += Write(stream, v.x); + t += Write(stream, v.y); + t += Write(stream, v.z); + ai_assert(t == 16); + + return t; +} + +// ----------------------------------------------------------------------------------- +// Serialize a vertex weight +template <> +inline size_t Write(IOStream *stream, const aiVertexWeight &v) { + size_t t = Write(stream, v.mVertexId); + + return t + Write(stream, v.mWeight); +} + +constexpr size_t MatrixSize = 64; + +// ----------------------------------------------------------------------------------- +// Serialize a mat4x4 +template <> +inline size_t Write(IOStream *stream, const aiMatrix4x4 &m) { + for (unsigned int i = 0; i < 4; ++i) { + for (unsigned int i2 = 0; i2 < 4; ++i2) { + Write(stream, m[i][i2]); + } + } + + return MatrixSize; +} + +// ----------------------------------------------------------------------------------- +// Serialize an aiVectorKey +template <> +inline size_t Write(IOStream *stream, const aiVectorKey &v) { + const size_t t = Write(stream, v.mTime); + return t + Write(stream, v.mValue); +} + +// ----------------------------------------------------------------------------------- +// Serialize an aiQuatKey +template <> +inline size_t Write(IOStream *stream, const aiQuatKey &v) { + const size_t t = Write(stream, v.mTime); + return t + Write(stream, v.mValue); +} + +template +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(stream, minc); + return t + Write(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 +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(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(nullptr), + magic(magic), + container(container), + cur_size(0), + cursor(0), + initial(initial) { + // empty + } + + ~AssbinChunkWriter() override { + 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; } + + size_t Read(void * /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) override { + return 0; + } + + aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/) override { + return aiReturn_FAILURE; + } + + size_t Tell() const override { + return cursor; + } + + void Flush() override { + // not implemented + } + + size_t FileSize() const override { + return cursor; + } + + size_t Write(const void *pvBuffer, size_t pSize, size_t pCount) override { + pSize *= pCount; + if (cursor + pSize > cur_size) { + Grow(cursor + pSize); + } + + memcpy(buffer + cursor, pvBuffer, pSize); + cursor += pSize; + + return pCount; + } +}; + +// ---------------------------------------------------------------------------------- +/** @class AssbinFileWriter + * @brief Assbin file writer class + * + * This class writes an .assbin file, and is responsible for the file layout. + */ +class AssbinFileWriter { +private: + bool shortened; + bool compressed; + +protected: + // ----------------------------------------------------------------------------------- + void WriteBinaryNode(IOStream *container, const aiNode *node) { + AssbinChunkWriter chunk(container, ASSBIN_CHUNK_AINODE); + + unsigned int nb_metadata = (node->mMetaData != nullptr ? node->mMetaData->mNumProperties : 0); + + Write(&chunk, node->mName); + Write(&chunk, node->mTransformation); + Write(&chunk, node->mNumChildren); + Write(&chunk, node->mNumMeshes); + Write(&chunk, nb_metadata); + + for (unsigned int i = 0; i < node->mNumMeshes; ++i) { + Write(&chunk, node->mMeshes[i]); + } + + for (unsigned int i = 0; i < node->mNumChildren; ++i) { + WriteBinaryNode(&chunk, node->mChildren[i]); + } + + for (unsigned int i = 0; i < nb_metadata; ++i) { + const aiString &key = node->mMetaData->mKeys[i]; + aiMetadataType type = node->mMetaData->mValues[i].mType; + void *value = node->mMetaData->mValues[i].mData; + + Write(&chunk, key); + Write(&chunk, (uint16_t)type); + + switch (type) { + case AI_BOOL: + Write(&chunk, *((bool *)value)); + break; + case AI_INT32: + Write(&chunk, *((int32_t *)value)); + break; + case AI_UINT64: + Write(&chunk, *((uint64_t *)value)); + break; + case AI_FLOAT: + Write(&chunk, *((float *)value)); + break; + case AI_DOUBLE: + Write(&chunk, *((double *)value)); + break; + case AI_AISTRING: + Write(&chunk, *((aiString *)value)); + break; + case AI_AIVECTOR3D: + Write(&chunk, *((aiVector3D *)value)); + break; +#ifdef SWIG + case FORCE_32BIT: +#endif // SWIG + default: + break; + } + } + } + + // ----------------------------------------------------------------------------------- + void WriteBinaryTexture(IOStream *container, const aiTexture *tex) { + AssbinChunkWriter chunk(container, ASSBIN_CHUNK_AITEXTURE); + + Write(&chunk, tex->mWidth); + Write(&chunk, tex->mHeight); + // Write the texture format, but don't include the null terminator. + chunk.Write(tex->achFormatHint, sizeof(char), HINTMAXTEXTURELEN - 1); + + 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(&chunk, b->mName); + Write(&chunk, b->mNumWeights); + Write(&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(&chunk, b->mWeights, b->mNumWeights); + } + + // ----------------------------------------------------------------------------------- + void WriteBinaryMesh(IOStream *container, const aiMesh *mesh) { + AssbinChunkWriter chunk(container, ASSBIN_CHUNK_AIMESH); + + Write(&chunk, mesh->mPrimitiveTypes); + Write(&chunk, mesh->mNumVertices); + Write(&chunk, mesh->mNumFaces); + Write(&chunk, mesh->mNumBones); + Write(&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(&chunk, c); + + aiVector3D minVec, maxVec; + if (mesh->mVertices) { + if (shortened) { + WriteBounds(&chunk, mesh->mVertices, mesh->mNumVertices); + } // else write as usual + else + WriteArray(&chunk, mesh->mVertices, mesh->mNumVertices); + } + if (mesh->mNormals) { + if (shortened) { + WriteBounds(&chunk, mesh->mNormals, mesh->mNumVertices); + } // else write as usual + else + WriteArray(&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(&chunk, mesh->mTangents, mesh->mNumVertices); + WriteArray(&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(&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(&chunk, mesh->mNumUVComponents[n]); + + if (shortened) { + WriteBounds(&chunk, mesh->mTextureCoords[n], mesh->mNumVertices); + } // else write as usual + else + WriteArray(&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(&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(f.mIndices[i]); + hash = SuperFastHash(reinterpret_cast(&tmp), sizeof tmp, hash); + } + } + Write(&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(&chunk, static_cast(f.mNumIndices)); + + for (unsigned int a = 0; a < f.mNumIndices; ++a) { + if (mesh->mNumVertices < (1u << 16)) { + Write(&chunk, static_cast(f.mIndices[a])); + } else { + Write(&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(&chunk, prop->mKey); + Write(&chunk, prop->mSemantic); + Write(&chunk, prop->mIndex); + + Write(&chunk, prop->mDataLength); + Write(&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(&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(&chunk, nd->mNodeName); + Write(&chunk, nd->mNumPositionKeys); + Write(&chunk, nd->mNumRotationKeys); + Write(&chunk, nd->mNumScalingKeys); + Write(&chunk, nd->mPreState); + Write(&chunk, nd->mPostState); + + if (nd->mPositionKeys) { + if (shortened) { + WriteBounds(&chunk, nd->mPositionKeys, nd->mNumPositionKeys); + + } // else write as usual + else + WriteArray(&chunk, nd->mPositionKeys, nd->mNumPositionKeys); + } + if (nd->mRotationKeys) { + if (shortened) { + WriteBounds(&chunk, nd->mRotationKeys, nd->mNumRotationKeys); + + } // else write as usual + else + WriteArray(&chunk, nd->mRotationKeys, nd->mNumRotationKeys); + } + if (nd->mScalingKeys) { + if (shortened) { + WriteBounds(&chunk, nd->mScalingKeys, nd->mNumScalingKeys); + + } // else write as usual + else + WriteArray(&chunk, nd->mScalingKeys, nd->mNumScalingKeys); + } + } + + // ----------------------------------------------------------------------------------- + void WriteBinaryAnim(IOStream *container, const aiAnimation *anim) { + AssbinChunkWriter chunk(container, ASSBIN_CHUNK_AIANIMATION); + + Write(&chunk, anim->mName); + Write(&chunk, anim->mDuration); + Write(&chunk, anim->mTicksPerSecond); + Write(&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(&chunk, l->mName); + Write(&chunk, l->mType); + + if (l->mType != aiLightSource_DIRECTIONAL) { + Write(&chunk, l->mAttenuationConstant); + Write(&chunk, l->mAttenuationLinear); + Write(&chunk, l->mAttenuationQuadratic); + } + + Write(&chunk, l->mColorDiffuse); + Write(&chunk, l->mColorSpecular); + Write(&chunk, l->mColorAmbient); + + if (l->mType == aiLightSource_SPOT) { + Write(&chunk, l->mAngleInnerCone); + Write(&chunk, l->mAngleOuterCone); + } + } + + // ----------------------------------------------------------------------------------- + void WriteBinaryCamera(IOStream *container, const aiCamera *cam) { + AssbinChunkWriter chunk(container, ASSBIN_CHUNK_AICAMERA); + + Write(&chunk, cam->mName); + Write(&chunk, cam->mPosition); + Write(&chunk, cam->mLookAt); + Write(&chunk, cam->mUp); + Write(&chunk, cam->mHorizontalFOV); + Write(&chunk, cam->mClipPlaneNear); + Write(&chunk, cam->mClipPlaneFar); + Write(&chunk, cam->mAspect); + } + + // ----------------------------------------------------------------------------------- + void WriteBinaryScene(IOStream *container, const aiScene *scene) { + AssbinChunkWriter chunk(container, ASSBIN_CHUNK_AISCENE); + + // basic scene information + Write(&chunk, scene->mFlags); + Write(&chunk, scene->mNumMeshes); + Write(&chunk, scene->mNumMaterials); + Write(&chunk, scene->mNumAnimations); + Write(&chunk, scene->mNumTextures); + Write(&chunk, scene->mNumLights); + Write(&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: + AssbinFileWriter(bool shortened, bool compressed) : + shortened(shortened), compressed(compressed) { + } + + // ----------------------------------------------------------------------------------- + // Write a binary model dump + void WriteBinaryDump(const char *pFile, const char *cmd, IOSystem *pIOSystem, const aiScene *pScene) { + IOStream *out = pIOSystem->Open(pFile, "wb"); + if (!out) + throw std::runtime_error("Unable to open output file " + std::string(pFile) + '\n'); + + auto CloseIOStream = [&]() { + if (out) { + pIOSystem->Close(out); + out = nullptr; // Ensure this is only done once. + } + }; + + try { + time_t tt = time(nullptr); +#if _WIN32 + tm *p = gmtime(&tt); +#else + struct tm now; + tm *p = gmtime_r(&tt, &now); +#endif + + // 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(out, ASSBIN_VERSION_MAJOR); + Write(out, ASSBIN_VERSION_MINOR); + Write(out, aiGetVersionRevision()); + Write(out, aiGetCompileFlags()); + Write(out, shortened); + Write(out, compressed); + // == 20 bytes + + char buff[256] = { 0 }; + ai_snprintf(buff, 256, "%s", pFile); + out->Write(buff, sizeof(char), 256); + + memset(buff, 0, sizeof(buff)); + ai_snprintf(buff, 128, "%s", cmd); + 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(nullptr, 0); + WriteBinaryScene(&uncompressedStream, pScene); + + uLongf uncompressedSize = static_cast(uncompressedStream.Tell()); + uLongf compressedSize = (uLongf)compressBound(uncompressedSize); + uint8_t *compressedBuffer = new uint8_t[compressedSize]; + + int res = compress2(compressedBuffer, &compressedSize, (const Bytef *)uncompressedStream.GetBufferPointer(), uncompressedSize, 9); + if (res != Z_OK) { + delete[] compressedBuffer; + throw DeadlyExportError("Compression failed."); + } + + out->Write(&uncompressedSize, sizeof(uint32_t), 1); + out->Write(compressedBuffer, sizeof(char), compressedSize); + + delete[] compressedBuffer; + } else { + WriteBinaryScene(out, pScene); + } + + CloseIOStream(); + } catch (...) { + CloseIOStream(); + throw; + } + } +}; + +void DumpSceneToAssbin( + const char *pFile, const char *cmd, IOSystem *pIOSystem, + const aiScene *pScene, bool shortened, bool compressed) { + AssbinFileWriter fileWriter(shortened, compressed); + fileWriter.WriteBinaryDump(pFile, cmd, pIOSystem, pScene); +} +#if _MSC_VER +#pragma warning(pop) +#endif // _MSC_VER + +} // end of namespace Assimp diff --git a/libs/assimp/code/AssetLib/Assbin/AssbinFileWriter.h b/libs/assimp/code/AssetLib/Assbin/AssbinFileWriter.h new file mode 100644 index 0000000..cfed3b4 --- /dev/null +++ b/libs/assimp/code/AssetLib/Assbin/AssbinFileWriter.h @@ -0,0 +1,65 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2022, 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 AssbinFileWriter.h + * @brief Declaration of Assbin file writer. + */ + +#ifndef AI_ASSBINFILEWRITER_H_INC +#define AI_ASSBINFILEWRITER_H_INC + +#include +#include +#include + +namespace Assimp { + +void ASSIMP_API DumpSceneToAssbin( + const char *pFile, + const char *cmd, + IOSystem *pIOSystem, + const aiScene *pScene, + bool shortened, + bool compressed); + +} + +#endif // AI_ASSBINFILEWRITER_H_INC diff --git a/libs/assimp/code/AssetLib/Assbin/AssbinLoader.cpp b/libs/assimp/code/AssetLib/Assbin/AssbinLoader.cpp new file mode 100644 index 0000000..060ce43 --- /dev/null +++ b/libs/assimp/code/AssetLib/Assbin/AssbinLoader.cpp @@ -0,0 +1,730 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2022, 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 "AssetLib/Assbin/AssbinLoader.h" +#include "Common/assbin_chunks.h" +#include +#include +#include +#include +#include +#include + +#ifdef ASSIMP_BUILD_NO_OWN_ZLIB +#include +#else +#include +#endif + +using namespace Assimp; + +static const aiImporterDesc desc = { + "Assimp Binary 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 (nullptr == in) { + return false; + } + + char s[32]; + in->Read(s, sizeof(char), 32); + + pIOHandler->Close(in); + + return strncmp(s, "ASSIMP.binary-dump.", 19) == 0; +} + +// ----------------------------------------------------------------------------------- +template +T Read(IOStream *stream) { + T t; + size_t res = stream->Read(&t, sizeof(T), 1); + if (res != 1) { + throw DeadlyImportError("Unexpected EOF"); + } + return t; +} + +// ----------------------------------------------------------------------------------- +template <> +aiVector3D Read(IOStream *stream) { + aiVector3D v; + v.x = Read(stream); + v.y = Read(stream); + v.z = Read(stream); + return v; +} + +// ----------------------------------------------------------------------------------- +template <> +aiColor4D Read(IOStream *stream) { + aiColor4D c; + c.r = Read(stream); + c.g = Read(stream); + c.b = Read(stream); + c.a = Read(stream); + return c; +} + +// ----------------------------------------------------------------------------------- +template <> +aiQuaternion Read(IOStream *stream) { + aiQuaternion v; + v.w = Read(stream); + v.x = Read(stream); + v.y = Read(stream); + v.z = Read(stream); + return v; +} + +// ----------------------------------------------------------------------------------- +template <> +aiString Read(IOStream *stream) { + aiString s; + stream->Read(&s.length, 4, 1); + if (s.length) { + stream->Read(s.data, s.length, 1); + } + s.data[s.length] = 0; + + return s; +} + +// ----------------------------------------------------------------------------------- +template <> +aiVertexWeight Read(IOStream *stream) { + aiVertexWeight w; + w.mVertexId = Read(stream); + w.mWeight = Read(stream); + return w; +} + +// ----------------------------------------------------------------------------------- +template <> +aiMatrix4x4 Read(IOStream *stream) { + aiMatrix4x4 m; + for (unsigned int i = 0; i < 4; ++i) { + for (unsigned int i2 = 0; i2 < 4; ++i2) { + m[i][i2] = Read(stream); + } + } + return m; +} + +// ----------------------------------------------------------------------------------- +template <> +aiVectorKey Read(IOStream *stream) { + aiVectorKey v; + v.mTime = Read(stream); + v.mValue = Read(stream); + return v; +} + +// ----------------------------------------------------------------------------------- +template <> +aiQuatKey Read(IOStream *stream) { + aiQuatKey v; + v.mTime = Read(stream); + v.mValue = Read(stream); + return v; +} + +// ----------------------------------------------------------------------------------- +template +void ReadArray(IOStream *stream, T *out, unsigned int size) { + ai_assert(nullptr != stream); + ai_assert(nullptr != out); + + for (unsigned int i = 0; i < size; i++) { + out[i] = Read(stream); + } +} + +// ----------------------------------------------------------------------------------- +template +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 **onode, aiNode *parent) { + if (Read(stream) != ASSBIN_CHUNK_AINODE) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); + /*uint32_t size =*/Read(stream); + + std::unique_ptr node(new aiNode()); + + node->mName = Read(stream); + node->mTransformation = Read(stream); + unsigned numChildren = Read(stream); + unsigned numMeshes = Read(stream); + unsigned int nb_metadata = Read(stream); + + if (parent) { + node->mParent = parent; + } + + if (numMeshes) { + node->mMeshes = new unsigned int[numMeshes]; + for (unsigned int i = 0; i < numMeshes; ++i) { + node->mMeshes[i] = Read(stream); + node->mNumMeshes++; + } + } + + if (numChildren) { + node->mChildren = new aiNode *[numChildren]; + for (unsigned int i = 0; i < numChildren; ++i) { + ReadBinaryNode(stream, &node->mChildren[i], node.get()); + node->mNumChildren++; + } + } + + if (nb_metadata > 0) { + node->mMetaData = aiMetadata::Alloc(nb_metadata); + for (unsigned int i = 0; i < nb_metadata; ++i) { + node->mMetaData->mKeys[i] = Read(stream); + node->mMetaData->mValues[i].mType = (aiMetadataType)Read(stream); + void *data = nullptr; + + switch (node->mMetaData->mValues[i].mType) { + case AI_BOOL: + data = new bool(Read(stream)); + break; + case AI_INT32: + data = new int32_t(Read(stream)); + break; + case AI_UINT64: + data = new uint64_t(Read(stream)); + break; + case AI_FLOAT: + data = new ai_real(Read(stream)); + break; + case AI_DOUBLE: + data = new double(Read(stream)); + break; + case AI_AISTRING: + data = new aiString(Read(stream)); + break; + case AI_AIVECTOR3D: + data = new aiVector3D(Read(stream)); + break; +#ifndef SWIG + case FORCE_32BIT: +#endif // SWIG + default: + break; + } + + node->mMetaData->mValues[i].mData = data; + } + } + *onode = node.release(); +} + +// ----------------------------------------------------------------------------------- +void AssbinImporter::ReadBinaryBone(IOStream *stream, aiBone *b) { + if (Read(stream) != ASSBIN_CHUNK_AIBONE) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); + /*uint32_t size =*/Read(stream); + + b->mName = Read(stream); + b->mNumWeights = Read(stream); + b->mOffsetMatrix = Read(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 { + // else write as usual + b->mWeights = new aiVertexWeight[b->mNumWeights]; + ReadArray(stream, b->mWeights, b->mNumWeights); + } +} + +// ----------------------------------------------------------------------------------- +static bool fitsIntoUI16(unsigned int mNumVertices) { + return (mNumVertices < (1u << 16)); +} + +// ----------------------------------------------------------------------------------- +void AssbinImporter::ReadBinaryMesh(IOStream *stream, aiMesh *mesh) { + if (Read(stream) != ASSBIN_CHUNK_AIMESH) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); + /*uint32_t size =*/Read(stream); + + mesh->mPrimitiveTypes = Read(stream); + mesh->mNumVertices = Read(stream); + mesh->mNumFaces = Read(stream); + mesh->mNumBones = Read(stream); + mesh->mMaterialIndex = Read(stream); + + // first of all, write bits for all existent vertex components + unsigned int c = Read(stream); + + if (c & ASSBIN_MESH_HAS_POSITIONS) { + if (shortened) { + ReadBounds(stream, mesh->mVertices, mesh->mNumVertices); + } else { + // else write as usual + mesh->mVertices = new aiVector3D[mesh->mNumVertices]; + ReadArray(stream, mesh->mVertices, mesh->mNumVertices); + } + } + if (c & ASSBIN_MESH_HAS_NORMALS) { + if (shortened) { + ReadBounds(stream, mesh->mNormals, mesh->mNumVertices); + } else { + // else write as usual + mesh->mNormals = new aiVector3D[mesh->mNumVertices]; + ReadArray(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 { + // else write as usual + mesh->mTangents = new aiVector3D[mesh->mNumVertices]; + ReadArray(stream, mesh->mTangents, mesh->mNumVertices); + mesh->mBitangents = new aiVector3D[mesh->mNumVertices]; + ReadArray(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 { + // else write as usual + mesh->mColors[n] = new aiColor4D[mesh->mNumVertices]; + ReadArray(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(stream); + + if (shortened) { + ReadBounds(stream, mesh->mTextureCoords[n], mesh->mNumVertices); + } else { + // else write as usual + mesh->mTextureCoords[n] = new aiVector3D[mesh->mNumVertices]; + ReadArray(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(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(stream); + f.mIndices = new unsigned int[f.mNumIndices]; + + for (unsigned int a = 0; a < f.mNumIndices; ++a) { + // Check if unsigned short ( 16 bit ) are big enough for the indices + if (fitsIntoUI16(mesh->mNumVertices)) { + f.mIndices[a] = Read(stream); + } else { + f.mIndices[a] = Read(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) { + if (Read(stream) != ASSBIN_CHUNK_AIMATERIALPROPERTY) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); + /*uint32_t size =*/Read(stream); + + prop->mKey = Read(stream); + prop->mSemantic = Read(stream); + prop->mIndex = Read(stream); + + prop->mDataLength = Read(stream); + prop->mType = (aiPropertyTypeInfo)Read(stream); + prop->mData = new char[prop->mDataLength]; + stream->Read(prop->mData, 1, prop->mDataLength); +} + +// ----------------------------------------------------------------------------------- +void AssbinImporter::ReadBinaryMaterial(IOStream *stream, aiMaterial *mat) { + if (Read(stream) != ASSBIN_CHUNK_AIMATERIAL) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); + /*uint32_t size =*/Read(stream); + + mat->mNumAllocated = mat->mNumProperties = Read(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) { + if (Read(stream) != ASSBIN_CHUNK_AINODEANIM) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); + /*uint32_t size =*/Read(stream); + + nd->mNodeName = Read(stream); + nd->mNumPositionKeys = Read(stream); + nd->mNumRotationKeys = Read(stream); + nd->mNumScalingKeys = Read(stream); + nd->mPreState = (aiAnimBehaviour)Read(stream); + nd->mPostState = (aiAnimBehaviour)Read(stream); + + if (nd->mNumPositionKeys) { + if (shortened) { + ReadBounds(stream, nd->mPositionKeys, nd->mNumPositionKeys); + + } // else write as usual + else { + nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys]; + ReadArray(stream, nd->mPositionKeys, nd->mNumPositionKeys); + } + } + if (nd->mNumRotationKeys) { + if (shortened) { + ReadBounds(stream, nd->mRotationKeys, nd->mNumRotationKeys); + + } else { + // else write as usual + nd->mRotationKeys = new aiQuatKey[nd->mNumRotationKeys]; + ReadArray(stream, nd->mRotationKeys, nd->mNumRotationKeys); + } + } + if (nd->mNumScalingKeys) { + if (shortened) { + ReadBounds(stream, nd->mScalingKeys, nd->mNumScalingKeys); + + } else { + // else write as usual + nd->mScalingKeys = new aiVectorKey[nd->mNumScalingKeys]; + ReadArray(stream, nd->mScalingKeys, nd->mNumScalingKeys); + } + } +} + +// ----------------------------------------------------------------------------------- +void AssbinImporter::ReadBinaryAnim(IOStream *stream, aiAnimation *anim) { + if (Read(stream) != ASSBIN_CHUNK_AIANIMATION) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); + /*uint32_t size =*/Read(stream); + + anim->mName = Read(stream); + anim->mDuration = Read(stream); + anim->mTicksPerSecond = Read(stream); + anim->mNumChannels = Read(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) { + if (Read(stream) != ASSBIN_CHUNK_AITEXTURE) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); + /*uint32_t size =*/Read(stream); + + tex->mWidth = Read(stream); + tex->mHeight = Read(stream); + stream->Read(tex->achFormatHint, sizeof(char), HINTMAXTEXTURELEN - 1); + + 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) { + if (Read(stream) != ASSBIN_CHUNK_AILIGHT) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); + /*uint32_t size =*/Read(stream); + + l->mName = Read(stream); + l->mType = (aiLightSourceType)Read(stream); + + if (l->mType != aiLightSource_DIRECTIONAL) { + l->mAttenuationConstant = Read(stream); + l->mAttenuationLinear = Read(stream); + l->mAttenuationQuadratic = Read(stream); + } + + l->mColorDiffuse = Read(stream); + l->mColorSpecular = Read(stream); + l->mColorAmbient = Read(stream); + + if (l->mType == aiLightSource_SPOT) { + l->mAngleInnerCone = Read(stream); + l->mAngleOuterCone = Read(stream); + } +} + +// ----------------------------------------------------------------------------------- +void AssbinImporter::ReadBinaryCamera(IOStream *stream, aiCamera *cam) { + if (Read(stream) != ASSBIN_CHUNK_AICAMERA) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); + /*uint32_t size =*/Read(stream); + + cam->mName = Read(stream); + cam->mPosition = Read(stream); + cam->mLookAt = Read(stream); + cam->mUp = Read(stream); + cam->mHorizontalFOV = Read(stream); + cam->mClipPlaneNear = Read(stream); + cam->mClipPlaneFar = Read(stream); + cam->mAspect = Read(stream); +} + +// ----------------------------------------------------------------------------------- +void AssbinImporter::ReadBinaryScene(IOStream *stream, aiScene *scene) { + if (Read(stream) != ASSBIN_CHUNK_AISCENE) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); + /*uint32_t size =*/Read(stream); + + scene->mFlags = Read(stream); + scene->mNumMeshes = Read(stream); + scene->mNumMaterials = Read(stream); + scene->mNumAnimations = Read(stream); + scene->mNumTextures = Read(stream); + scene->mNumLights = Read(stream); + scene->mNumCameras = Read(stream); + + // Read node graph + //scene->mRootNode = new aiNode[1]; + ReadBinaryNode(stream, &scene->mRootNode, (aiNode *)nullptr); + + // Read all meshes + if (scene->mNumMeshes) { + scene->mMeshes = new aiMesh *[scene->mNumMeshes]; + memset(scene->mMeshes, 0, scene->mNumMeshes * sizeof(aiMesh *)); + 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]; + memset(scene->mMaterials, 0, scene->mNumMaterials * sizeof(aiMaterial *)); + 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]; + memset(scene->mAnimations, 0, scene->mNumAnimations * sizeof(aiAnimation *)); + 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]; + memset(scene->mTextures, 0, scene->mNumTextures * sizeof(aiTexture *)); + 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]; + memset(scene->mLights, 0, scene->mNumLights * sizeof(aiLight *)); + 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]; + memset(scene->mCameras, 0, scene->mNumCameras * sizeof(aiCamera *)); + 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 (nullptr == stream) { + throw DeadlyImportError("ASSBIN: Could not open ", pFile); + } + + // signature + stream->Seek(44, aiOrigin_CUR); + + unsigned int versionMajor = Read(stream); + unsigned int versionMinor = Read(stream); + if (versionMinor != ASSBIN_VERSION_MINOR || versionMajor != ASSBIN_VERSION_MAJOR) { + throw DeadlyImportError("Invalid version, data format not compatible!"); + } + + /*unsigned int versionRevision =*/Read(stream); + /*unsigned int compileFlags =*/Read(stream); + + shortened = Read(stream) > 0; + compressed = Read(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(stream); + uLongf compressedSize = static_cast(stream->FileSize() - stream->Tell()); + + unsigned char *compressedData = new unsigned char[compressedSize]; + size_t len = stream->Read(compressedData, 1, compressedSize); + ai_assert(len == compressedSize); + + unsigned char *uncompressedData = new unsigned char[uncompressedSize]; + + int res = uncompress(uncompressedData, &uncompressedSize, compressedData, (uLong)len); + if (res != Z_OK) { + delete[] uncompressedData; + delete[] compressedData; + pIOHandler->Close(stream); + throw DeadlyImportError("Zlib decompression failed."); + } + + MemoryIOStream io(uncompressedData, uncompressedSize); + + ReadBinaryScene(&io, pScene); + + delete[] uncompressedData; + delete[] compressedData; + } else { + ReadBinaryScene(stream, pScene); + } + + pIOHandler->Close(stream); +} + +#endif // !! ASSIMP_BUILD_NO_ASSBIN_IMPORTER diff --git a/libs/assimp/code/AssetLib/Assbin/AssbinLoader.h b/libs/assimp/code/AssetLib/Assbin/AssbinLoader.h new file mode 100644 index 0000000..f922b91 --- /dev/null +++ b/libs/assimp/code/AssetLib/Assbin/AssbinLoader.h @@ -0,0 +1,99 @@ + +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2022, 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.h + * @brief .assbin File format loader + */ +#ifndef AI_ASSBINIMPORTER_H_INC +#define AI_ASSBINIMPORTER_H_INC + +#include + +struct aiMesh; +struct aiNode; +struct aiBone; +struct aiMaterial; +struct aiMaterialProperty; +struct aiNodeAnim; +struct aiAnimation; +struct aiTexture; +struct aiLight; +struct aiCamera; + +#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER + +namespace Assimp { + +// --------------------------------------------------------------------------------- +/** Importer class for 3D Studio r3 and r4 3DS files + */ +class AssbinImporter : public BaseImporter +{ +private: + bool shortened; + bool compressed; + +public: + bool CanRead(const std::string& pFile, + IOSystem* pIOHandler, bool checkSig) const override; + const aiImporterDesc* GetInfo() const override; + void InternReadFile( + const std::string& pFile,aiScene* pScene,IOSystem* pIOHandler) override; + void ReadHeader(); + void ReadBinaryScene( IOStream * stream, aiScene* pScene ); + void ReadBinaryNode( IOStream * stream, aiNode** mRootNode, aiNode* parent ); + void ReadBinaryMesh( IOStream * stream, aiMesh* mesh ); + void ReadBinaryBone( IOStream * stream, aiBone* bone ); + void ReadBinaryMaterial(IOStream * stream, aiMaterial* mat); + void ReadBinaryMaterialProperty(IOStream * stream, aiMaterialProperty* prop); + void ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd); + void ReadBinaryAnim( IOStream * stream, aiAnimation* anim ); + void ReadBinaryTexture(IOStream * stream, aiTexture* tex); + void ReadBinaryLight( IOStream * stream, aiLight* l ); + void ReadBinaryCamera( IOStream * stream, aiCamera* cam ); +}; + +} // end of namespace Assimp + +#endif // !! ASSIMP_BUILD_NO_ASSBIN_IMPORTER + +#endif // AI_ASSBINIMPORTER_H_INC -- cgit v1.2.1