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 --- libs/assimp/code/AssetLib/Blender/BlenderBMesh.cpp | 184 +++ libs/assimp/code/AssetLib/Blender/BlenderBMesh.h | 94 ++ .../code/AssetLib/Blender/BlenderCustomData.cpp | 181 +++ .../code/AssetLib/Blender/BlenderCustomData.h | 89 ++ libs/assimp/code/AssetLib/Blender/BlenderDNA.cpp | 351 +++++ libs/assimp/code/AssetLib/Blender/BlenderDNA.h | 808 ++++++++++++ libs/assimp/code/AssetLib/Blender/BlenderDNA.inl | 845 ++++++++++++ .../code/AssetLib/Blender/BlenderIntermediate.h | 206 +++ .../assimp/code/AssetLib/Blender/BlenderLoader.cpp | 1340 ++++++++++++++++++++ libs/assimp/code/AssetLib/Blender/BlenderLoader.h | 198 +++ .../code/AssetLib/Blender/BlenderModifier.cpp | 299 +++++ .../assimp/code/AssetLib/Blender/BlenderModifier.h | 155 +++ libs/assimp/code/AssetLib/Blender/BlenderScene.cpp | 891 +++++++++++++ libs/assimp/code/AssetLib/Blender/BlenderScene.h | 983 ++++++++++++++ .../assimp/code/AssetLib/Blender/BlenderSceneGen.h | 272 ++++ .../code/AssetLib/Blender/BlenderTessellator.cpp | 532 ++++++++ .../code/AssetLib/Blender/BlenderTessellator.h | 214 ++++ 17 files changed, 7642 insertions(+) create mode 100644 libs/assimp/code/AssetLib/Blender/BlenderBMesh.cpp create mode 100644 libs/assimp/code/AssetLib/Blender/BlenderBMesh.h create mode 100644 libs/assimp/code/AssetLib/Blender/BlenderCustomData.cpp create mode 100644 libs/assimp/code/AssetLib/Blender/BlenderCustomData.h create mode 100644 libs/assimp/code/AssetLib/Blender/BlenderDNA.cpp create mode 100644 libs/assimp/code/AssetLib/Blender/BlenderDNA.h create mode 100644 libs/assimp/code/AssetLib/Blender/BlenderDNA.inl create mode 100644 libs/assimp/code/AssetLib/Blender/BlenderIntermediate.h create mode 100644 libs/assimp/code/AssetLib/Blender/BlenderLoader.cpp create mode 100644 libs/assimp/code/AssetLib/Blender/BlenderLoader.h create mode 100644 libs/assimp/code/AssetLib/Blender/BlenderModifier.cpp create mode 100644 libs/assimp/code/AssetLib/Blender/BlenderModifier.h create mode 100644 libs/assimp/code/AssetLib/Blender/BlenderScene.cpp create mode 100644 libs/assimp/code/AssetLib/Blender/BlenderScene.h create mode 100644 libs/assimp/code/AssetLib/Blender/BlenderSceneGen.h create mode 100644 libs/assimp/code/AssetLib/Blender/BlenderTessellator.cpp create mode 100644 libs/assimp/code/AssetLib/Blender/BlenderTessellator.h (limited to 'libs/assimp/code/AssetLib/Blender') diff --git a/libs/assimp/code/AssetLib/Blender/BlenderBMesh.cpp b/libs/assimp/code/AssetLib/Blender/BlenderBMesh.cpp new file mode 100644 index 0000000..be536eb --- /dev/null +++ b/libs/assimp/code/AssetLib/Blender/BlenderBMesh.cpp @@ -0,0 +1,184 @@ +/* +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 BlenderBMesh.cpp + * @brief Conversion of Blender's new BMesh stuff + */ + +#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER + +#include "BlenderBMesh.h" +#include "BlenderDNA.h" +#include "BlenderScene.h" +#include "BlenderTessellator.h" + +namespace Assimp { +template <> +const char *LogFunctions::Prefix() { + static auto prefix = "BLEND_BMESH: "; + return prefix; +} +} // namespace Assimp + +using namespace Assimp; +using namespace Assimp::Blender; +using namespace Assimp::Formatter; + +// ------------------------------------------------------------------------------------------------ +BlenderBMeshConverter::BlenderBMeshConverter(const Mesh *mesh) : + BMesh(mesh), + triMesh(nullptr) { + ai_assert(nullptr != mesh); +} + +// ------------------------------------------------------------------------------------------------ +BlenderBMeshConverter::~BlenderBMeshConverter() { + DestroyTriMesh(); +} + +// ------------------------------------------------------------------------------------------------ +bool BlenderBMeshConverter::ContainsBMesh() const { + // TODO - Should probably do some additional verification here + return BMesh->totpoly && BMesh->totloop && BMesh->totvert; +} + +// ------------------------------------------------------------------------------------------------ +const Mesh *BlenderBMeshConverter::TriangulateBMesh() { + AssertValidMesh(); + AssertValidSizes(); + PrepareTriMesh(); + + for (int i = 0; i < BMesh->totpoly; ++i) { + const MPoly &poly = BMesh->mpoly[i]; + ConvertPolyToFaces(poly); + } + + return triMesh; +} + +// ------------------------------------------------------------------------------------------------ +void BlenderBMeshConverter::AssertValidMesh() { + if (!ContainsBMesh()) { + ThrowException("BlenderBMeshConverter requires a BMesh with \"polygons\" - please call BlenderBMeshConverter::ContainsBMesh to check this first"); + } +} + +// ------------------------------------------------------------------------------------------------ +void BlenderBMeshConverter::AssertValidSizes() { + if (BMesh->totpoly != static_cast(BMesh->mpoly.size())) { + ThrowException("BMesh poly array has incorrect size"); + } + if (BMesh->totloop != static_cast(BMesh->mloop.size())) { + ThrowException("BMesh loop array has incorrect size"); + } +} + +// ------------------------------------------------------------------------------------------------ +void BlenderBMeshConverter::PrepareTriMesh() { + if (triMesh) { + DestroyTriMesh(); + } + + triMesh = new Mesh(*BMesh); + triMesh->totface = 0; + triMesh->mface.clear(); +} + +// ------------------------------------------------------------------------------------------------ +void BlenderBMeshConverter::DestroyTriMesh() { + delete triMesh; + triMesh = nullptr; +} + +// ------------------------------------------------------------------------------------------------ +void BlenderBMeshConverter::ConvertPolyToFaces(const MPoly &poly) { + const MLoop *polyLoop = &BMesh->mloop[poly.loopstart]; + + if (poly.totloop == 3 || poly.totloop == 4) { + AddFace(polyLoop[0].v, polyLoop[1].v, polyLoop[2].v, poly.totloop == 4 ? polyLoop[3].v : 0); + + // UVs are optional, so only convert when present. + if (BMesh->mloopuv.size()) { + if ((poly.loopstart + poly.totloop) > static_cast(BMesh->mloopuv.size())) { + ThrowException("BMesh uv loop array has incorrect size"); + } + const MLoopUV *loopUV = &BMesh->mloopuv[poly.loopstart]; + AddTFace(loopUV[0].uv, loopUV[1].uv, loopUV[2].uv, poly.totloop == 4 ? loopUV[3].uv : 0); + } + } else if (poly.totloop > 4) { +#if ASSIMP_BLEND_WITH_GLU_TESSELLATE + BlenderTessellatorGL tessGL(*this); + tessGL.Tessellate(polyLoop, poly.totloop, triMesh->mvert); +#elif ASSIMP_BLEND_WITH_POLY_2_TRI + BlenderTessellatorP2T tessP2T(*this); + tessP2T.Tessellate(polyLoop, poly.totloop, triMesh->mvert); +#endif + } +} + +// ------------------------------------------------------------------------------------------------ +void BlenderBMeshConverter::AddFace(int v1, int v2, int v3, int v4) { + MFace face; + face.v1 = v1; + face.v2 = v2; + face.v3 = v3; + face.v4 = v4; + face.flag = 0; + // TODO - Work out how materials work + face.mat_nr = 0; + triMesh->mface.push_back(face); + triMesh->totface = static_cast(triMesh->mface.size()); +} + +// ------------------------------------------------------------------------------------------------ +void BlenderBMeshConverter::AddTFace(const float *uv1, const float *uv2, const float *uv3, const float *uv4) { + MTFace mtface; + memcpy(&mtface.uv[0], uv1, sizeof(float) * 2); + memcpy(&mtface.uv[1], uv2, sizeof(float) * 2); + memcpy(&mtface.uv[2], uv3, sizeof(float) * 2); + + if (uv4) { + memcpy(&mtface.uv[3], uv4, sizeof(float) * 2); + } + + triMesh->mtface.push_back(mtface); +} + +#endif // ASSIMP_BUILD_NO_BLEND_IMPORTER diff --git a/libs/assimp/code/AssetLib/Blender/BlenderBMesh.h b/libs/assimp/code/AssetLib/Blender/BlenderBMesh.h new file mode 100644 index 0000000..45ca2c8 --- /dev/null +++ b/libs/assimp/code/AssetLib/Blender/BlenderBMesh.h @@ -0,0 +1,94 @@ +/* +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 BlenderBMesh.h + * @brief Conversion of Blender's new BMesh stuff + */ +#ifndef INCLUDED_AI_BLEND_BMESH_H +#define INCLUDED_AI_BLEND_BMESH_H + +#include + +namespace Assimp +{ + // TinyFormatter.h + namespace Formatter + { + template < typename T,typename TR, typename A > class basic_formatter; + typedef class basic_formatter< char, std::char_traits< char >, std::allocator< char > > format; + } + + // BlenderScene.h + namespace Blender + { + struct Mesh; + struct MPoly; + struct MLoop; + } + + class BlenderBMeshConverter: public LogFunctions< BlenderBMeshConverter > + { + public: + BlenderBMeshConverter( const Blender::Mesh* mesh ); + ~BlenderBMeshConverter( ); + + bool ContainsBMesh( ) const; + + const Blender::Mesh* TriangulateBMesh( ); + + private: + void AssertValidMesh( ); + void AssertValidSizes( ); + void PrepareTriMesh( ); + void DestroyTriMesh( ); + void ConvertPolyToFaces( const Blender::MPoly& poly ); + void AddFace( int v1, int v2, int v3, int v4 = 0 ); + void AddTFace( const float* uv1, const float* uv2, const float *uv3, const float* uv4 = 0 ); + + const Blender::Mesh* BMesh; + Blender::Mesh* triMesh; + + friend class BlenderTessellatorGL; + friend class BlenderTessellatorP2T; + }; + +} // end of namespace Assimp + +#endif // INCLUDED_AI_BLEND_BMESH_H diff --git a/libs/assimp/code/AssetLib/Blender/BlenderCustomData.cpp b/libs/assimp/code/AssetLib/Blender/BlenderCustomData.cpp new file mode 100644 index 0000000..c74a6bb --- /dev/null +++ b/libs/assimp/code/AssetLib/Blender/BlenderCustomData.cpp @@ -0,0 +1,181 @@ +#include "BlenderCustomData.h" +#include "BlenderDNA.h" +#include +#include + +namespace Assimp { +namespace Blender { +/** + * @brief read/convert of Structure array to memory + */ +template +bool read(const Structure &s, T *p, const size_t cnt, const FileDatabase &db) { + for (size_t i = 0; i < cnt; ++i) { + T read; + s.Convert(read, db); + *p = read; + p++; + } + return true; +} + +/** + * @brief pointer to function read memory for n CustomData types + */ +typedef bool (*PRead)(ElemBase *pOut, const size_t cnt, const FileDatabase &db); +typedef ElemBase *(*PCreate)(const size_t cnt); +typedef void (*PDestroy)(ElemBase *); + +#define IMPL_STRUCT_READ(ty) \ + bool read##ty(ElemBase *v, const size_t cnt, const FileDatabase &db) { \ + ty *ptr = dynamic_cast(v); \ + if (nullptr == ptr) { \ + return false; \ + } \ + return read(db.dna[#ty], ptr, cnt, db); \ + } + +#define IMPL_STRUCT_CREATE(ty) \ + ElemBase *create##ty(const size_t cnt) { \ + return new ty[cnt]; \ + } + +#define IMPL_STRUCT_DESTROY(ty) \ + void destroy##ty(ElemBase *pE) { \ + ty *p = dynamic_cast(pE); \ + delete[] p; \ + } + +/** + * @brief helper macro to define Structure functions + */ +#define IMPL_STRUCT(ty) \ + IMPL_STRUCT_READ(ty) \ + IMPL_STRUCT_CREATE(ty) \ + IMPL_STRUCT_DESTROY(ty) + +// supported structures for CustomData +IMPL_STRUCT(MVert) +IMPL_STRUCT(MEdge) +IMPL_STRUCT(MFace) +IMPL_STRUCT(MTFace) +IMPL_STRUCT(MTexPoly) +IMPL_STRUCT(MLoopUV) +IMPL_STRUCT(MLoopCol) +IMPL_STRUCT(MPoly) +IMPL_STRUCT(MLoop) + +/** + * @brief describes the size of data and the read function to be used for single CustomerData.type + */ +struct CustomDataTypeDescription { + PRead Read; ///< function to read one CustomData type element + PCreate Create; ///< function to allocate n type elements + PDestroy Destroy; + + CustomDataTypeDescription(PRead read, PCreate create, PDestroy destroy) : + Read(read), Create(create), Destroy(destroy) {} +}; + +/** + * @brief helper macro to define Structure type specific CustomDataTypeDescription + * @note IMPL_STRUCT_READ for same ty must be used earlier to implement the typespecific read function + */ +#define DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(ty) \ + CustomDataTypeDescription { &read##ty, &create##ty, &destroy##ty } + +/** + * @brief helper macro to define CustomDataTypeDescription for UNSUPPORTED type + */ +#define DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION \ + CustomDataTypeDescription { nullptr, nullptr, nullptr } + +/** + * @brief descriptors for data pointed to from CustomDataLayer.data + * @note some of the CustomData uses already well defined Structures + * other (like CD_ORCO, ...) uses arrays of rawtypes or even arrays of Structures + * use a special readfunction for that cases + */ +std::array customDataTypeDescriptions = { { DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MVert), + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MEdge), + DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MFace), + DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MTFace), + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MTexPoly), + DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoopUV), + DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoopCol), + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MPoly), + DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoop), + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION } }; + +bool isValidCustomDataType(const int cdtype) { + return cdtype >= 0 && cdtype < CD_NUMTYPES; +} + +bool readCustomData(std::shared_ptr &out, const int cdtype, const size_t cnt, const FileDatabase &db) { + if (!isValidCustomDataType(cdtype)) { + throw Error("CustomData.type ", cdtype, " out of index"); + } + + const CustomDataTypeDescription cdtd = customDataTypeDescriptions[cdtype]; + if (cdtd.Read && cdtd.Create && cdtd.Destroy && cnt > 0) { + // allocate cnt elements and parse them from file + out.reset(cdtd.Create(cnt), cdtd.Destroy); + return cdtd.Read(out.get(), cnt, db); + } + return false; +} + +std::shared_ptr getCustomDataLayer(const CustomData &customdata, const CustomDataType cdtype, const std::string &name) { + for (auto it = customdata.layers.begin(); it != customdata.layers.end(); ++it) { + if (it->get()->type == cdtype && name == it->get()->name) { + return *it; + } + } + return nullptr; +} + +const ElemBase *getCustomDataLayerData(const CustomData &customdata, const CustomDataType cdtype, const std::string &name) { + const std::shared_ptr pLayer = getCustomDataLayer(customdata, cdtype, name); + if (pLayer && pLayer->data) { + return pLayer->data.get(); + } + return nullptr; +} +} // namespace Blender +} // namespace Assimp diff --git a/libs/assimp/code/AssetLib/Blender/BlenderCustomData.h b/libs/assimp/code/AssetLib/Blender/BlenderCustomData.h new file mode 100644 index 0000000..f61d79a --- /dev/null +++ b/libs/assimp/code/AssetLib/Blender/BlenderCustomData.h @@ -0,0 +1,89 @@ +#pragma once + +#include "BlenderDNA.h" +#include "BlenderScene.h" +#include + +namespace Assimp { + namespace Blender { + /* CustomData.type from Blender (2.79b) */ + enum CustomDataType { + CD_AUTO_FROM_NAME = -1, + CD_MVERT = 0, +#ifdef DNA_DEPRECATED + CD_MSTICKY = 1, /* DEPRECATED */ +#endif + CD_MDEFORMVERT = 2, + CD_MEDGE = 3, + CD_MFACE = 4, + CD_MTFACE = 5, + CD_MCOL = 6, + CD_ORIGINDEX = 7, + CD_NORMAL = 8, + /* CD_POLYINDEX = 9, */ + CD_PROP_FLT = 10, + CD_PROP_INT = 11, + CD_PROP_STR = 12, + CD_ORIGSPACE = 13, /* for modifier stack face location mapping */ + CD_ORCO = 14, + CD_MTEXPOLY = 15, + CD_MLOOPUV = 16, + CD_MLOOPCOL = 17, + CD_TANGENT = 18, + CD_MDISPS = 19, + CD_PREVIEW_MCOL = 20, /* for displaying weightpaint colors */ + /* CD_ID_MCOL = 21, */ + CD_TEXTURE_MLOOPCOL = 22, + CD_CLOTH_ORCO = 23, + CD_RECAST = 24, + + /* BMESH ONLY START */ + CD_MPOLY = 25, + CD_MLOOP = 26, + CD_SHAPE_KEYINDEX = 27, + CD_SHAPEKEY = 28, + CD_BWEIGHT = 29, + CD_CREASE = 30, + CD_ORIGSPACE_MLOOP = 31, + CD_PREVIEW_MLOOPCOL = 32, + CD_BM_ELEM_PYPTR = 33, + /* BMESH ONLY END */ + + CD_PAINT_MASK = 34, + CD_GRID_PAINT_MASK = 35, + CD_MVERT_SKIN = 36, + CD_FREESTYLE_EDGE = 37, + CD_FREESTYLE_FACE = 38, + CD_MLOOPTANGENT = 39, + CD_TESSLOOPNORMAL = 40, + CD_CUSTOMLOOPNORMAL = 41, + + CD_NUMTYPES = 42 + }; + + /** + * @brief check if given cdtype is valid (ie >= 0 and < CD_NUMTYPES) + * @param[in] cdtype to check + * @return true when valid + */ + bool isValidCustomDataType(const int cdtype); + + /** + * @brief returns CustomDataLayer ptr for given cdtype and name + * @param[in] customdata CustomData to search for wanted layer + * @param[in] cdtype to search for + * @param[in] name to search for + * @return CustomDataLayer * or nullptr if not found + */ + std::shared_ptr getCustomDataLayer(const CustomData &customdata, CustomDataType cdtype, const std::string &name); + + /** + * @brief returns CustomDataLayer data ptr for given cdtype and name + * @param[in] customdata CustomData to search for wanted layer + * @param[in] cdtype to search for + * @param[in] name to search for + * @return * to struct data or nullptr if not found + */ + const ElemBase * getCustomDataLayerData(const CustomData &customdata, CustomDataType cdtype, const std::string &name); + } +} diff --git a/libs/assimp/code/AssetLib/Blender/BlenderDNA.cpp b/libs/assimp/code/AssetLib/Blender/BlenderDNA.cpp new file mode 100644 index 0000000..2910904 --- /dev/null +++ b/libs/assimp/code/AssetLib/Blender/BlenderDNA.cpp @@ -0,0 +1,351 @@ +/* +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 BlenderDNA.cpp + * @brief Implementation of the Blender `DNA`, that is its own + * serialized set of data structures. + */ + +#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER +#include "BlenderDNA.h" +#include +#include +#include + +using namespace Assimp; +using namespace Assimp::Blender; +using namespace Assimp::Formatter; + +static bool match4(StreamReaderAny &stream, const char *string) { + ai_assert(nullptr != string); + char tmp[4]; + tmp[0] = (stream).GetI1(); + tmp[1] = (stream).GetI1(); + tmp[2] = (stream).GetI1(); + tmp[3] = (stream).GetI1(); + return (tmp[0] == string[0] && tmp[1] == string[1] && tmp[2] == string[2] && tmp[3] == string[3]); +} + +struct Type { + size_t size; + std::string name; +}; + +// ------------------------------------------------------------------------------------------------ +void DNAParser::Parse() { + StreamReaderAny &stream = *db.reader.get(); + DNA &dna = db.dna; + + if (!match4(stream, "SDNA")) { + throw DeadlyImportError("BlenderDNA: Expected SDNA chunk"); + } + + // name dictionary + if (!match4(stream, "NAME")) { + throw DeadlyImportError("BlenderDNA: Expected NAME field"); + } + + std::vector names(stream.GetI4()); + for (std::string &s : names) { + while (char c = stream.GetI1()) { + s += c; + } + } + + // type dictionary + for (; stream.GetCurrentPos() & 0x3; stream.GetI1()) + ; + if (!match4(stream, "TYPE")) { + throw DeadlyImportError("BlenderDNA: Expected TYPE field"); + } + + std::vector types(stream.GetI4()); + for (Type &s : types) { + while (char c = stream.GetI1()) { + s.name += c; + } + } + + // type length dictionary + for (; stream.GetCurrentPos() & 0x3; stream.GetI1()) + ; + if (!match4(stream, "TLEN")) { + throw DeadlyImportError("BlenderDNA: Expected TLEN field"); + } + + for (Type &s : types) { + s.size = stream.GetI2(); + } + + // structures dictionary + for (; stream.GetCurrentPos() & 0x3; stream.GetI1()) + ; + if (!match4(stream, "STRC")) { + throw DeadlyImportError("BlenderDNA: Expected STRC field"); + } + + size_t end = stream.GetI4(), fields = 0; + + dna.structures.reserve(end); + for (size_t i = 0; i != end; ++i) { + + uint16_t n = stream.GetI2(); + if (n >= types.size()) { + throw DeadlyImportError("BlenderDNA: Invalid type index in structure name", n, " (there are only ", types.size(), " entries)"); + } + + // maintain separate indexes + dna.indices[types[n].name] = dna.structures.size(); + + dna.structures.push_back(Structure()); + Structure &s = dna.structures.back(); + s.name = types[n].name; + + n = stream.GetI2(); + s.fields.reserve(n); + + size_t offset = 0; + for (size_t m = 0; m < n; ++m, ++fields) { + + uint16_t j = stream.GetI2(); + if (j >= types.size()) { + throw DeadlyImportError("BlenderDNA: Invalid type index in structure field ", j, " (there are only ", types.size(), " entries)"); + } + s.fields.push_back(Field()); + Field &f = s.fields.back(); + f.offset = offset; + + f.type = types[j].name; + f.size = types[j].size; + + j = stream.GetI2(); + if (j >= names.size()) { + throw DeadlyImportError("BlenderDNA: Invalid name index in structure field ", j, " (there are only ", names.size(), " entries)"); + } + + f.name = names[j]; + f.flags = 0u; + + // pointers always specify the size of the pointee instead of their own. + // The pointer asterisk remains a property of the lookup name. + if (f.name[0] == '*') { + f.size = db.i64bit ? 8 : 4; + f.flags |= FieldFlag_Pointer; + } + + // arrays, however, specify the size of a single element so we + // need to parse the (possibly multi-dimensional) array declaration + // in order to obtain the actual size of the array in the file. + // Also we need to alter the lookup name to include no array + // brackets anymore or size fixup won't work (if our size does + // not match the size read from the DNA). + if (*f.name.rbegin() == ']') { + const std::string::size_type rb = f.name.find('['); + if (rb == std::string::npos) { + throw DeadlyImportError("BlenderDNA: Encountered invalid array declaration ", f.name); + } + + f.flags |= FieldFlag_Array; + DNA::ExtractArraySize(f.name, f.array_sizes); + f.name = f.name.substr(0, rb); + + f.size *= f.array_sizes[0] * f.array_sizes[1]; + } + + // maintain separate indexes + s.indices[f.name] = s.fields.size() - 1; + offset += f.size; + } + s.size = offset; + } + + ASSIMP_LOG_DEBUG("BlenderDNA: Got ", dna.structures.size(), " structures with totally ", fields, " fields"); + +#if ASSIMP_BUILD_BLENDER_DEBUG_DNA + dna.DumpToFile(); +#endif + + dna.AddPrimitiveStructures(); + dna.RegisterConverters(); +} + +#if ASSIMP_BUILD_BLENDER_DEBUG_DNA + +#include +// ------------------------------------------------------------------------------------------------ +void DNA ::DumpToFile() { + // we don't bother using the VFS here for this is only for debugging. + // (and all your bases are belong to us). + + std::ofstream f("dna.txt"); + if (f.fail()) { + ASSIMP_LOG_ERROR("Could not dump dna to dna.txt"); + return; + } + f << "Field format: type name offset size" + << "\n"; + f << "Structure format: name size" + << "\n"; + + for (const Structure &s : structures) { + f << s.name << " " << s.size << "\n\n"; + for (const Field &ff : s.fields) { + f << "\t" << ff.type << " " << ff.name << " " << ff.offset << " " << ff.size << "\n"; + } + f << "\n"; + } + f << std::flush; + + ASSIMP_LOG_INFO("BlenderDNA: Dumped dna to dna.txt"); +} +#endif // ASSIMP_BUILD_BLENDER_DEBUG_DNA + +// ------------------------------------------------------------------------------------------------ +/*static*/ void DNA ::ExtractArraySize( + const std::string &out, + size_t array_sizes[2]) { + array_sizes[0] = array_sizes[1] = 1; + std::string::size_type pos = out.find('['); + if (pos++ == std::string::npos) { + return; + } + array_sizes[0] = strtoul10(&out[pos]); + + pos = out.find('[', pos); + if (pos++ == std::string::npos) { + return; + } + array_sizes[1] = strtoul10(&out[pos]); +} + +// ------------------------------------------------------------------------------------------------ +std::shared_ptr DNA ::ConvertBlobToStructure( + const Structure &structure, + const FileDatabase &db) const { + std::map::const_iterator it = converters.find(structure.name); + if (it == converters.end()) { + return std::shared_ptr(); + } + + std::shared_ptr ret = (structure.*((*it).second.first))(); + (structure.*((*it).second.second))(ret, db); + + return ret; +} + +// ------------------------------------------------------------------------------------------------ +DNA::FactoryPair DNA ::GetBlobToStructureConverter( + const Structure &structure, + const FileDatabase & /*db*/ +) const { + std::map::const_iterator it = converters.find(structure.name); + return it == converters.end() ? FactoryPair() : (*it).second; +} + +// basing on http://www.blender.org/development/architecture/notes-on-sdna/ +// ------------------------------------------------------------------------------------------------ +void DNA ::AddPrimitiveStructures() { + // NOTE: these are just dummies. Their presence enforces + // Structure::Convert to be called on these + // empty structures. These converters are special + // overloads which scan the name of the structure and + // perform the required data type conversion if one + // of these special names is found in the structure + // in question. + + indices["int"] = structures.size(); + structures.push_back(Structure()); + structures.back().name = "int"; + structures.back().size = 4; + + indices["short"] = structures.size(); + structures.push_back(Structure()); + structures.back().name = "short"; + structures.back().size = 2; + + indices["char"] = structures.size(); + structures.push_back(Structure()); + structures.back().name = "char"; + structures.back().size = 1; + + indices["float"] = structures.size(); + structures.push_back(Structure()); + structures.back().name = "float"; + structures.back().size = 4; + + indices["double"] = structures.size(); + structures.push_back(Structure()); + structures.back().name = "double"; + structures.back().size = 8; + + // no long, seemingly. +} + +// ------------------------------------------------------------------------------------------------ +void SectionParser ::Next() { + stream.SetCurrentPos(current.start + current.size); + + const char tmp[] = { + (const char)stream.GetI1(), + (const char)stream.GetI1(), + (const char)stream.GetI1(), + (const char)stream.GetI1() + }; + current.id = std::string(tmp, tmp[3] ? 4 : tmp[2] ? 3 : tmp[1] ? 2 : 1); + + current.size = stream.GetI4(); + current.address.val = ptr64 ? stream.GetU8() : stream.GetU4(); + + current.dna_index = stream.GetI4(); + current.num = stream.GetI4(); + + current.start = stream.GetCurrentPos(); + if (stream.GetRemainingSizeToLimit() < current.size) { + throw DeadlyImportError("BLEND: invalid size of file block"); + } + +#ifdef ASSIMP_BUILD_BLENDER_DEBUG + ASSIMP_LOG_VERBOSE_DEBUG(current.id); +#endif +} + +#endif diff --git a/libs/assimp/code/AssetLib/Blender/BlenderDNA.h b/libs/assimp/code/AssetLib/Blender/BlenderDNA.h new file mode 100644 index 0000000..b2158f2 --- /dev/null +++ b/libs/assimp/code/AssetLib/Blender/BlenderDNA.h @@ -0,0 +1,808 @@ +/* +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 BlenderDNA.h + * @brief Blender `DNA` (file format specification embedded in + * blend file itself) loader. + */ +#ifndef INCLUDED_AI_BLEND_DNA_H +#define INCLUDED_AI_BLEND_DNA_H + +#include +#include +#include +#include +#include +#include + +// enable verbose log output. really verbose, so be careful. +#ifdef ASSIMP_BUILD_DEBUG +#define ASSIMP_BUILD_BLENDER_DEBUG +#endif + +// set this to non-zero to dump BlenderDNA stuff to dna.txt. +// you could set it on the assimp build command line too without touching it here. +// !!! please make sure this is set to 0 in the repo !!! +#ifndef ASSIMP_BUILD_BLENDER_DEBUG_DNA +#define ASSIMP_BUILD_BLENDER_DEBUG_DNA 0 +#endif + +// #define ASSIMP_BUILD_BLENDER_NO_STATS + +namespace Assimp { + +template +class StreamReader; +typedef StreamReader StreamReaderAny; + +namespace Blender { + +class FileDatabase; +struct FileBlockHead; + +template