#include "BlenderCustomData.h" #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)(void *pOut, const size_t cnt, const FileDatabase &db); /** * @brief pointer to function read memory for cnt CustomData types */ typedef uint8_t *(*PAlloc)(const size_t cnt); /** * @brief helper macro to define Structure specific read function * for ex: when used like * * IMPL_STRUCT_READ(MLoop) * * following function is implemented * * bool readMLoop(void *v, const size_t cnt, const FileDatabase &db) { * return read(db.dna["MLoop"], static_cast(v), cnt, db); * } */ #define IMPL_STRUCT_READ(ty) \ bool read##ty(void *v, const size_t cnt, const FileDatabase &db) { \ return read(db.dna[#ty], static_cast(v), cnt, db); \ } /** * @brief helper macro to define Structure specific alloc function * for ex: when used like * * IMPL_STRUCT_ALLOC(MLoop) * * following function is implemented * * void * allocMLoop(const size_t cnt) { * return new uint8_t[cnt * sizeof MLoop]; * } */ #define IMPL_STRUCT_ALLOC(ty) \ uint8_t *alloc##ty(const size_t cnt) { \ return static_cast(malloc(cnt * sizeof(ty))); \ } /** * @brief helper macro to define Structure functions */ #define IMPL_STRUCT(ty) \ IMPL_STRUCT_ALLOC(ty) \ IMPL_STRUCT_READ(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 PAlloc Alloc; ///< function to allocate n type elements CustomDataTypeDescription(PRead read, PAlloc alloc) : Read(read) , Alloc(alloc) {} }; /** * @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, &alloc##ty) /** * @brief helper macro to define CustomDataTypeDescription for UNSUPPORTED type */ #define DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION \ CustomDataTypeDescription(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.Alloc) { // allocate cnt elements and parse them from file out.reset(cdtd.Alloc(cnt), free); 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 void * 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; } } }