123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- #include "BlenderCustomData.h"
- #include "BlenderDNA.h"
- #include <array>
- #include <functional>
- namespace Assimp {
- namespace Blender {
- /**
- * @brief read/convert of Structure array to memory
- */
- template <typename T>
- 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<ty *>(v); \
- if (nullptr == ptr) { \
- return false; \
- } \
- return read<ty>(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<ty *>(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<CustomDataTypeDescription, CD_NUMTYPES> 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<ElemBase> &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<CustomDataLayer> 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<CustomDataLayer> pLayer = getCustomDataLayer(customdata, cdtype, name);
- if (pLayer && pLayer->data) {
- return pLayer->data.get();
- }
- return nullptr;
- }
- } // namespace Blender
- } // namespace Assimp
|