1#include "BlenderCustomData.h"
2#include "BlenderDNA.h"
3#include <array>
4#include <functional>
5
6namespace Assimp {
7 namespace Blender {
8 /**
9 * @brief read/convert of Structure array to memory
10 */
11 template<typename T>
12 bool read(const Structure &s, T *p, const size_t cnt, const FileDatabase &db) {
13 for (size_t i = 0; i < cnt; ++i) {
14 T read;
15 s.Convert(read, db);
16 *p = read;
17 p++;
18 }
19 return true;
20 }
21
22 /**
23 * @brief pointer to function read memory for n CustomData types
24 */
25 typedef bool (*PRead)(ElemBase *pOut, const size_t cnt, const FileDatabase &db);
26 typedef ElemBase * (*PCreate)(const size_t cnt);
27 typedef void(*PDestroy)(ElemBase *);
28
29#define IMPL_STRUCT_READ(ty) \
30 bool read##ty(ElemBase *v, const size_t cnt, const FileDatabase &db) { \
31 ty *ptr = dynamic_cast<ty*>(v); \
32 if (nullptr == ptr) { \
33 return false; \
34 } \
35 return read<ty>(db.dna[#ty], ptr, cnt, db); \
36 }
37
38#define IMPL_STRUCT_CREATE(ty) \
39 ElemBase *create##ty(const size_t cnt) { \
40 return new ty[cnt]; \
41 }
42
43#define IMPL_STRUCT_DESTROY(ty) \
44 void destroy##ty(ElemBase *pE) { \
45 ty *p = dynamic_cast<ty *>(pE); \
46 delete[]p; \
47 }
48
49 /**
50 * @brief helper macro to define Structure functions
51 */
52#define IMPL_STRUCT(ty) \
53 IMPL_STRUCT_READ(ty) \
54 IMPL_STRUCT_CREATE(ty) \
55 IMPL_STRUCT_DESTROY(ty)
56
57 // supported structures for CustomData
58 IMPL_STRUCT(MVert)
59 IMPL_STRUCT(MEdge)
60 IMPL_STRUCT(MFace)
61 IMPL_STRUCT(MTFace)
62 IMPL_STRUCT(MTexPoly)
63 IMPL_STRUCT(MLoopUV)
64 IMPL_STRUCT(MLoopCol)
65 IMPL_STRUCT(MPoly)
66 IMPL_STRUCT(MLoop)
67
68 /**
69 * @brief describes the size of data and the read function to be used for single CustomerData.type
70 */
71 struct CustomDataTypeDescription {
72 PRead Read; ///< function to read one CustomData type element
73 PCreate Create; ///< function to allocate n type elements
74 PDestroy Destroy;
75
76 CustomDataTypeDescription(PRead read, PCreate create, PDestroy destroy)
77 : Read(read)
78 , Create(create)
79 , Destroy(destroy)
80 {}
81 };
82
83
84 /**
85 * @brief helper macro to define Structure type specific CustomDataTypeDescription
86 * @note IMPL_STRUCT_READ for same ty must be used earlier to implement the typespecific read function
87 */
88#define DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(ty) \
89 CustomDataTypeDescription{&read##ty, &create##ty, &destroy##ty}
90
91 /**
92 * @brief helper macro to define CustomDataTypeDescription for UNSUPPORTED type
93 */
94#define DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION \
95 CustomDataTypeDescription{nullptr, nullptr, nullptr}
96
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 std::array<CustomDataTypeDescription, CD_NUMTYPES> customDataTypeDescriptions = { ._M_elems: {
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
115 DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
116 DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
117 DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
118 DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
119 DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
120 DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MTexPoly),
121 DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoopUV),
122 DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoopCol),
123 DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
124 DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
125
126 DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
127 DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
128 DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
129 DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
130 DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
131 DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MPoly),
132 DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoop),
133 DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
134 DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
135 DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
136
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 DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
147
148 DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
149 DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION
150 }};
151
152
153 bool isValidCustomDataType(const int cdtype) {
154 return cdtype >= 0 && cdtype < CD_NUMTYPES;
155 }
156
157 bool readCustomData(std::shared_ptr<ElemBase> &out, const int cdtype, const size_t cnt, const FileDatabase &db) {
158 if (!isValidCustomDataType(cdtype)) {
159 throw Error((Formatter::format(), "CustomData.type ", cdtype, " out of index"));
160 }
161
162 const CustomDataTypeDescription cdtd = customDataTypeDescriptions[cdtype];
163 if (cdtd.Read && cdtd.Create && cdtd.Destroy && cnt > 0) {
164 // allocate cnt elements and parse them from file
165 out.reset(p: cdtd.Create(cnt), d: cdtd.Destroy);
166 return cdtd.Read(out.get(), cnt, db);
167 }
168 return false;
169 }
170
171 std::shared_ptr<CustomDataLayer> getCustomDataLayer(const CustomData &customdata, const CustomDataType cdtype, const std::string &name) {
172 for (auto it = customdata.layers.begin(); it != customdata.layers.end(); ++it) {
173 if (it->get()->type == cdtype && name == it->get()->name) {
174 return *it;
175 }
176 }
177 return nullptr;
178 }
179
180 const ElemBase * getCustomDataLayerData(const CustomData &customdata, const CustomDataType cdtype, const std::string &name)
181 {
182 const std::shared_ptr<CustomDataLayer> pLayer = getCustomDataLayer(customdata, cdtype, name);
183 if (pLayer && pLayer->data) {
184 return pLayer->data.get();
185 }
186 return nullptr;
187 }
188 }
189}
190

source code of qt3d/src/3rdparty/assimp/src/code/Blender/BlenderCustomData.cpp