BlenderCustomData.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. #include "BlenderCustomData.h"
  2. #include "BlenderDNA.h"
  3. #include <array>
  4. #include <functional>
  5. namespace Assimp {
  6. namespace Blender {
  7. /**
  8. * @brief read/convert of Structure array to memory
  9. */
  10. template<typename T>
  11. bool read(const Structure &s, T *p, const size_t cnt, const FileDatabase &db) {
  12. for (size_t i = 0; i < cnt; ++i) {
  13. T read;
  14. s.Convert(read, db);
  15. *p = read;
  16. p++;
  17. }
  18. return true;
  19. }
  20. /**
  21. * @brief pointer to function read memory for n CustomData types
  22. */
  23. typedef bool (*PRead)(ElemBase *pOut, const size_t cnt, const FileDatabase &db);
  24. typedef ElemBase * (*PCreate)(const size_t cnt);
  25. typedef void(*PDestroy)(ElemBase *);
  26. #define IMPL_STRUCT_READ(ty) \
  27. bool read##ty(ElemBase *v, const size_t cnt, const FileDatabase &db) { \
  28. return read<ty>(db.dna[#ty], dynamic_cast<ty *>(v), cnt, db); \
  29. }
  30. #define IMPL_STRUCT_CREATE(ty) \
  31. ElemBase *create##ty(const size_t cnt) { \
  32. return new ty[cnt]; \
  33. }
  34. #define IMPL_STRUCT_DESTROY(ty) \
  35. void destroy##ty(ElemBase *pE) { \
  36. ty *p = dynamic_cast<ty *>(pE); \
  37. delete[]p; \
  38. }
  39. /**
  40. * @brief helper macro to define Structure functions
  41. */
  42. #define IMPL_STRUCT(ty) \
  43. IMPL_STRUCT_READ(ty) \
  44. IMPL_STRUCT_CREATE(ty) \
  45. IMPL_STRUCT_DESTROY(ty)
  46. // supported structures for CustomData
  47. IMPL_STRUCT(MVert)
  48. IMPL_STRUCT(MEdge)
  49. IMPL_STRUCT(MFace)
  50. IMPL_STRUCT(MTFace)
  51. IMPL_STRUCT(MTexPoly)
  52. IMPL_STRUCT(MLoopUV)
  53. IMPL_STRUCT(MLoopCol)
  54. IMPL_STRUCT(MPoly)
  55. IMPL_STRUCT(MLoop)
  56. /**
  57. * @brief describes the size of data and the read function to be used for single CustomerData.type
  58. */
  59. struct CustomDataTypeDescription {
  60. PRead Read; ///< function to read one CustomData type element
  61. PCreate Create; ///< function to allocate n type elements
  62. PDestroy Destroy;
  63. CustomDataTypeDescription(PRead read, PCreate create, PDestroy destroy)
  64. : Read(read)
  65. , Create(create)
  66. , Destroy(destroy)
  67. {}
  68. };
  69. /**
  70. * @brief helper macro to define Structure type specific CustomDataTypeDescription
  71. * @note IMPL_STRUCT_READ for same ty must be used earlier to implement the typespecific read function
  72. */
  73. #define DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(ty) \
  74. CustomDataTypeDescription{&read##ty, &create##ty, &destroy##ty}
  75. /**
  76. * @brief helper macro to define CustomDataTypeDescription for UNSUPPORTED type
  77. */
  78. #define DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION \
  79. CustomDataTypeDescription{nullptr, nullptr, nullptr}
  80. /**
  81. * @brief descriptors for data pointed to from CustomDataLayer.data
  82. * @note some of the CustomData uses already well defined Structures
  83. * other (like CD_ORCO, ...) uses arrays of rawtypes or even arrays of Structures
  84. * use a special readfunction for that cases
  85. */
  86. std::array<CustomDataTypeDescription, CD_NUMTYPES> customDataTypeDescriptions = { {
  87. DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MVert),
  88. DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
  89. DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
  90. DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MEdge),
  91. DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MFace),
  92. DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MTFace),
  93. DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
  94. DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
  95. DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
  96. DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
  97. DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
  98. DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
  99. DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
  100. DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
  101. DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
  102. DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MTexPoly),
  103. DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoopUV),
  104. DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoopCol),
  105. DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
  106. DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
  107. DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
  108. DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
  109. DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
  110. DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
  111. DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
  112. DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MPoly),
  113. DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoop),
  114. DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
  115. DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
  116. DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
  117. DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
  118. DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
  119. DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
  120. DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
  121. DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
  122. DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
  123. DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
  124. DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
  125. DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
  126. DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
  127. DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
  128. DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION
  129. }};
  130. bool isValidCustomDataType(const int cdtype) {
  131. return cdtype >= 0 && cdtype < CD_NUMTYPES;
  132. }
  133. bool readCustomData(std::shared_ptr<ElemBase> &out, const int cdtype, const size_t cnt, const FileDatabase &db) {
  134. if (!isValidCustomDataType(cdtype)) {
  135. throw Error((Formatter::format(), "CustomData.type ", cdtype, " out of index"));
  136. }
  137. const CustomDataTypeDescription cdtd = customDataTypeDescriptions[cdtype];
  138. if (cdtd.Read && cdtd.Create && cdtd.Destroy && cnt > 0) {
  139. // allocate cnt elements and parse them from file
  140. out.reset(cdtd.Create(cnt), cdtd.Destroy);
  141. return cdtd.Read(out.get(), cnt, db);
  142. }
  143. return false;
  144. }
  145. std::shared_ptr<CustomDataLayer> getCustomDataLayer(const CustomData &customdata, const CustomDataType cdtype, const std::string &name) {
  146. for (auto it = customdata.layers.begin(); it != customdata.layers.end(); ++it) {
  147. if (it->get()->type == cdtype && name == it->get()->name) {
  148. return *it;
  149. }
  150. }
  151. return nullptr;
  152. }
  153. const ElemBase * getCustomDataLayerData(const CustomData &customdata, const CustomDataType cdtype, const std::string &name)
  154. {
  155. const std::shared_ptr<CustomDataLayer> pLayer = getCustomDataLayer(customdata, cdtype, name);
  156. if (pLayer && pLayer->data) {
  157. return pLayer->data.get();
  158. }
  159. return nullptr;
  160. }
  161. }
  162. }