BlenderCustomData.cpp 8.1 KB

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