BlenderCustomData.cpp 8.2 KB

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