summaryrefslogtreecommitdiff
path: root/libs/assimp/code/AssetLib/Blender/BlenderCustomData.cpp
blob: c74a6bb7536993fd5d3216fdf0c16542ebafb848 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
#include "BlenderCustomData.h"
#include "BlenderDNA.h"
#include <array>
#include <functional>

namespace Assimp {
namespace Blender {
/**
        *   @brief  read/convert of Structure array to memory
        */
template <typename T>
bool read(const Structure &s, T *p, const size_t cnt, const FileDatabase &db) {
    for (size_t i = 0; i < cnt; ++i) {
        T read;
        s.Convert(read, db);
        *p = read;
        p++;
    }
    return true;
}

/**
        *   @brief  pointer to function read memory for n CustomData types
        */
typedef bool (*PRead)(ElemBase *pOut, const size_t cnt, const FileDatabase &db);
typedef ElemBase *(*PCreate)(const size_t cnt);
typedef void (*PDestroy)(ElemBase *);

#define IMPL_STRUCT_READ(ty)                                               \
    bool read##ty(ElemBase *v, const size_t cnt, const FileDatabase &db) { \
        ty *ptr = dynamic_cast<ty *>(v);                                   \
        if (nullptr == ptr) {                                              \
            return false;                                                  \
        }                                                                  \
        return read<ty>(db.dna[#ty], ptr, cnt, db);                        \
    }

#define IMPL_STRUCT_CREATE(ty)               \
    ElemBase *create##ty(const size_t cnt) { \
        return new ty[cnt];                  \
    }

#define IMPL_STRUCT_DESTROY(ty)         \
    void destroy##ty(ElemBase *pE) {    \
        ty *p = dynamic_cast<ty *>(pE); \
        delete[] p;                     \
    }

/**
        *   @brief  helper macro to define Structure functions
        */
#define IMPL_STRUCT(ty)    \
    IMPL_STRUCT_READ(ty)   \
    IMPL_STRUCT_CREATE(ty) \
    IMPL_STRUCT_DESTROY(ty)

// supported structures for CustomData
IMPL_STRUCT(MVert)
IMPL_STRUCT(MEdge)
IMPL_STRUCT(MFace)
IMPL_STRUCT(MTFace)
IMPL_STRUCT(MTexPoly)
IMPL_STRUCT(MLoopUV)
IMPL_STRUCT(MLoopCol)
IMPL_STRUCT(MPoly)
IMPL_STRUCT(MLoop)

/**
        *   @brief  describes the size of data and the read function to be used for single CustomerData.type
        */
struct CustomDataTypeDescription {
    PRead Read; ///< function to read one CustomData type element
    PCreate Create; ///< function to allocate n type elements
    PDestroy Destroy;

    CustomDataTypeDescription(PRead read, PCreate create, PDestroy destroy) :
            Read(read), Create(create), Destroy(destroy) {}
};

/**
        *   @brief  helper macro to define Structure type specific CustomDataTypeDescription
        *   @note   IMPL_STRUCT_READ for same ty must be used earlier to implement the typespecific read function
        */
#define DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(ty) \
    CustomDataTypeDescription { &read##ty, &create##ty, &destroy##ty }

/**
        *   @brief  helper macro to define CustomDataTypeDescription for UNSUPPORTED type
        */
#define DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION \
    CustomDataTypeDescription { nullptr, nullptr, nullptr }

/**
        *   @brief  descriptors for data pointed to from CustomDataLayer.data
        *   @note   some of the CustomData uses already well defined Structures
        *           other (like CD_ORCO, ...) uses arrays of rawtypes or even arrays of Structures
        *           use a special readfunction for that cases
        */
std::array<CustomDataTypeDescription, CD_NUMTYPES> customDataTypeDescriptions = { { DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MVert),
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
        DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MEdge),
        DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MFace),
        DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MTFace),
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,

        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
        DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MTexPoly),
        DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoopUV),
        DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoopCol),
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,

        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
        DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MPoly),
        DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoop),
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,

        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,

        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
        DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION } };

bool isValidCustomDataType(const int cdtype) {
    return cdtype >= 0 && cdtype < CD_NUMTYPES;
}

bool readCustomData(std::shared_ptr<ElemBase> &out, const int cdtype, const size_t cnt, const FileDatabase &db) {
    if (!isValidCustomDataType(cdtype)) {
        throw Error("CustomData.type ", cdtype, " out of index");
    }

    const CustomDataTypeDescription cdtd = customDataTypeDescriptions[cdtype];
    if (cdtd.Read && cdtd.Create && cdtd.Destroy && cnt > 0) {
        // allocate cnt elements and parse them from file
        out.reset(cdtd.Create(cnt), cdtd.Destroy);
        return cdtd.Read(out.get(), cnt, db);
    }
    return false;
}

std::shared_ptr<CustomDataLayer> getCustomDataLayer(const CustomData &customdata, const CustomDataType cdtype, const std::string &name) {
    for (auto it = customdata.layers.begin(); it != customdata.layers.end(); ++it) {
        if (it->get()->type == cdtype && name == it->get()->name) {
            return *it;
        }
    }
    return nullptr;
}

const ElemBase *getCustomDataLayerData(const CustomData &customdata, const CustomDataType cdtype, const std::string &name) {
    const std::shared_ptr<CustomDataLayer> pLayer = getCustomDataLayer(customdata, cdtype, name);
    if (pLayer && pLayer->data) {
        return pLayer->data.get();
    }
    return nullptr;
}
} // namespace Blender
} // namespace Assimp