2
0

BlenderCustomData.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  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), Create(create), Destroy(destroy) {}
  69. };
  70. /**
  71. * @brief helper macro to define Structure type specific CustomDataTypeDescription
  72. * @note IMPL_STRUCT_READ for same ty must be used earlier to implement the typespecific read function
  73. */
  74. #define DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(ty) \
  75. CustomDataTypeDescription { &read##ty, &create##ty, &destroy##ty }
  76. /**
  77. * @brief helper macro to define CustomDataTypeDescription for UNSUPPORTED type
  78. */
  79. #define DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION \
  80. CustomDataTypeDescription { nullptr, nullptr, nullptr }
  81. /**
  82. * @brief descriptors for data pointed to from CustomDataLayer.data
  83. * @note some of the CustomData uses already well defined Structures
  84. * other (like CD_ORCO, ...) uses arrays of rawtypes or even arrays of Structures
  85. * use a special readfunction for that cases
  86. */
  87. std::array<CustomDataTypeDescription, CD_NUMTYPES> customDataTypeDescriptions = { { 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. bool isValidCustomDataType(const int cdtype) {
  130. return cdtype >= 0 && cdtype < CD_NUMTYPES;
  131. }
  132. bool readCustomData(std::shared_ptr<ElemBase> &out, const int cdtype, const size_t cnt, const FileDatabase &db) {
  133. if (!isValidCustomDataType(cdtype)) {
  134. throw Error((Formatter::format(), "CustomData.type ", cdtype, " out of index"));
  135. }
  136. const CustomDataTypeDescription cdtd = customDataTypeDescriptions[cdtype];
  137. if (cdtd.Read && cdtd.Create && cdtd.Destroy && cnt > 0) {
  138. // allocate cnt elements and parse them from file
  139. out.reset(cdtd.Create(cnt), cdtd.Destroy);
  140. return cdtd.Read(out.get(), cnt, db);
  141. }
  142. return false;
  143. }
  144. std::shared_ptr<CustomDataLayer> getCustomDataLayer(const CustomData &customdata, const CustomDataType cdtype, const std::string &name) {
  145. for (auto it = customdata.layers.begin(); it != customdata.layers.end(); ++it) {
  146. if (it->get()->type == cdtype && name == it->get()->name) {
  147. return *it;
  148. }
  149. }
  150. return nullptr;
  151. }
  152. const ElemBase *getCustomDataLayerData(const CustomData &customdata, const CustomDataType cdtype, const std::string &name) {
  153. const std::shared_ptr<CustomDataLayer> pLayer = getCustomDataLayer(customdata, cdtype, name);
  154. if (pLayer && pLayer->data) {
  155. return pLayer->data.get();
  156. }
  157. return nullptr;
  158. }
  159. } // namespace Blender
  160. } // namespace Assimp