#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) { \ return read(db.dna[#ty], dynamic_cast(v), 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((Formatter::format(), "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; } } }