LEFT | RIGHT |
1 /* | 1 /* |
2 * $Id$ | 2 * ***** BEGIN GPL LICENSE BLOCK ***** |
3 * | 3 * |
4 * ***** BEGIN GPL LICENSE BLOCK ***** | 4 * This program is free software; you can redistribute it and/or |
5 * | 5 * modify it under the terms of the GNU General Public License |
6 * This program is free software; you can redistribute it and/or | 6 * as published by the Free Software Foundation; either version 2 |
7 * modify it under the terms of the GNU General Public License | 7 * of the License, or (at your option) any later version. |
8 * as published by the Free Software Foundation; either version 2 | 8 * |
9 * of the License, or (at your option) any later version. | 9 * This program is distributed in the hope that it will be useful, |
10 * | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 * This program is distributed in the hope that it will be useful, | 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 * GNU General Public License for more details. |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 13 * |
14 * GNU General Public License for more details. | 14 * You should have received a copy of the GNU General Public License |
15 * | 15 * along with this program; if not, write to the Free Software Foundation, |
16 * You should have received a copy of the GNU General Public License | 16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
17 * along with this program; if not, write to the Free Software Foundation, | 17 * |
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 18 * The Original Code is Copyright (C) 2006 Blender Foundation. |
19 * | 19 * All rights reserved. |
20 * The Original Code is Copyright (C) 2006 Blender Foundation. | 20 * |
21 * All rights reserved. | 21 * The Original Code is: all of this file. |
22 * | 22 * |
23 * The Original Code is: all of this file. | 23 * Contributor(s): Ben Batt <benbatt@gmail.com> |
24 * | 24 * |
25 * Contributor(s): Ben Batt <benbatt@gmail.com> | 25 * ***** END GPL LICENSE BLOCK ***** |
26 * | 26 * |
27 * ***** END GPL LICENSE BLOCK ***** | 27 * Implementation of CustomData. |
28 * | 28 * |
29 * Implementation of CustomData. | 29 * BKE_customdata.h contains the function prototypes for this file. |
30 * | 30 * |
31 * BKE_customdata.h contains the function prototypes for this file. | 31 */ |
32 * | |
33 */ | |
34 | 32 |
35 /** \file blender/blenkernel/intern/customdata.c | 33 /** \file blender/blenkernel/intern/customdata.c |
36 * \ingroup bke | 34 * \ingroup bke |
37 */ | 35 */ |
38 · | 36 · |
39 | 37 |
40 #include <math.h> | 38 #include <math.h> |
41 #include <string.h> | 39 #include <string.h> |
42 #include <assert.h> | 40 #include <assert.h> |
43 | 41 |
44 #include "MEM_guardedalloc.h" | 42 #include "MEM_guardedalloc.h" |
45 | 43 |
46 #include "DNA_meshdata_types.h" | 44 #include "DNA_meshdata_types.h" |
47 #include "DNA_ID.h" | 45 #include "DNA_ID.h" |
48 | 46 |
49 #include "BLI_blenlib.h" | 47 #include "BLI_utildefines.h" |
| 48 #include "BLI_string.h" |
50 #include "BLI_path_util.h" | 49 #include "BLI_path_util.h" |
51 #include "BLI_linklist.h" | |
52 #include "BLI_math.h" | 50 #include "BLI_math.h" |
53 #include "BLI_mempool.h" | 51 #include "BLI_mempool.h" |
54 #include "BLI_utildefines.h" | 52 #include "BLI_utildefines.h" |
| 53 #include "BLI_alloca.h" |
| 54 |
| 55 #include "BLF_translation.h" |
55 | 56 |
56 #include "BKE_customdata.h" | 57 #include "BKE_customdata.h" |
57 #include "BKE_customdata_file.h" | 58 #include "BKE_customdata_file.h" |
58 #include "BKE_global.h" | 59 #include "BKE_global.h" |
59 #include "BKE_main.h" | 60 #include "BKE_main.h" |
60 #include "BKE_utildefines.h" | |
61 #include "BKE_multires.h" | 61 #include "BKE_multires.h" |
| 62 |
| 63 #include "bmesh.h" |
| 64 |
| 65 #include <math.h> |
| 66 #include <string.h> |
62 | 67 |
63 /* number of layers to add when growing a CustomData object */ | 68 /* number of layers to add when growing a CustomData object */ |
64 #define CUSTOMDATA_GROW 5 | 69 #define CUSTOMDATA_GROW 5 |
| 70 |
| 71 /* ensure typemap size is ok */ |
| 72 BLI_STATIC_ASSERT(sizeof(((CustomData *)NULL)->typemap) / |
| 73 sizeof(((CustomData *)NULL)->typemap[0]) == CD_NUMTYPES, |
| 74 "size mismatch"); |
| 75 |
65 | 76 |
66 /********************* Layer type information **********************/ | 77 /********************* Layer type information **********************/ |
67 typedef struct LayerTypeInfo { | 78 typedef struct LayerTypeInfo { |
68 int size; /* the memory size of one element of this layer's dat
a */ | 79 int size; /* the memory size of one element of this layer's dat
a */ |
69 » const char *structname; /* name of the struct used, for file writing */ | 80 |
70 » int structnum; /* number of structs per element, for file writing */ | 81 » /** name of the struct used, for file writing */ |
71 » const char *defaultname; /* default layer name */ | 82 » const char *structname; |
72 | 83 » /** number of structs per element, for file writing */ |
73 » /* a function to copy count elements of this layer's data | 84 » int structnum; |
| 85 |
| 86 » /** |
| 87 » * default layer name. |
| 88 » * note! when NULL this is a way to ensure there is only ever one item |
| 89 » * see: CustomData_layertype_is_singleton() */ |
| 90 » const char *defaultname; |
| 91 |
| 92 » /** |
| 93 » * a function to copy count elements of this layer's data |
74 * (deep copy if appropriate) | 94 * (deep copy if appropriate) |
75 * if NULL, memcpy is used | 95 * if NULL, memcpy is used |
76 */ | 96 */ |
77 void (*copy)(const void *source, void *dest, int count); | 97 void (*copy)(const void *source, void *dest, int count); |
78 | 98 |
79 » /* a function to free any dynamically allocated components of this | 99 » /** |
| 100 » * a function to free any dynamically allocated components of this |
80 * layer's data (note the data pointer itself should not be freed) | 101 * layer's data (note the data pointer itself should not be freed) |
81 * size should be the size of one element of this layer's data (e.g. | 102 * size should be the size of one element of this layer's data (e.g. |
82 * LayerTypeInfo.size) | 103 * LayerTypeInfo.size) |
83 */ | 104 */ |
84 void (*free)(void *data, int count, int size); | 105 void (*free)(void *data, int count, int size); |
85 | 106 |
86 » /* a function to interpolate between count source elements of this | 107 » /** |
| 108 » * a function to interpolate between count source elements of this |
87 * layer's data and store the result in dest | 109 * layer's data and store the result in dest |
88 * if weights == NULL or sub_weights == NULL, they should default to 1 | 110 * if weights == NULL or sub_weights == NULL, they should default to 1 |
89 * | 111 * |
90 * weights gives the weight for each element in sources | 112 * weights gives the weight for each element in sources |
91 * sub_weights gives the sub-element weights for each element in sources | 113 * sub_weights gives the sub-element weights for each element in sources |
92 * (there should be (sub element count)^2 weights per element) | 114 * (there should be (sub element count)^2 weights per element) |
93 * count gives the number of elements in sources | 115 * count gives the number of elements in sources |
| 116 * |
| 117 * \note in some cases \a dest pointer is in \a sources |
| 118 * so all functions have to take this into account and delay |
| 119 * applying changes while reading from sources. |
| 120 * See bug [#32395] - Campbell. |
94 */ | 121 */ |
95 » void (*interp)(void **sources, float *weights, float *sub_weights, | 122 » void (*interp)(void **sources, const float *weights, const float *sub_we
ights, |
96 » » » » int count, void *dest); | 123 » int count, void *dest); |
97 | 124 |
98 » /* a function to swap the data in corners of the element */ | 125 » /** a function to swap the data in corners of the element */ |
99 void (*swap)(void *data, const int *corner_indices); | 126 void (*swap)(void *data, const int *corner_indices); |
100 | 127 |
101 » /* a function to set a layer's data to default values. if NULL, the | 128 » /** |
102 » default is assumed to be all zeros */ | 129 » * a function to set a layer's data to default values. if NULL, the |
| 130 » * default is assumed to be all zeros */ |
103 void (*set_default)(void *data, int count); | 131 void (*set_default)(void *data, int count); |
104 | 132 |
105 » /* a function to read data from a cdf file */ | 133 » /** functions necessary for geometry collapse */ |
| 134 » bool (*equal)(void *data1, void *data2); |
| 135 » void (*multiply)(void *data, float fac); |
| 136 » void (*initminmax)(void *min, void *max); |
| 137 » void (*add)(void *data1, void *data2); |
| 138 » void (*dominmax)(void *data1, void *min, void *max); |
| 139 » void (*copyvalue)(void *source, void *dest); |
| 140 |
| 141 » /** a function to read data from a cdf file */ |
106 int (*read)(CDataFile *cdf, void *data, int count); | 142 int (*read)(CDataFile *cdf, void *data, int count); |
107 | 143 |
108 » /* a function to write data to a cdf file */ | 144 » /** a function to write data to a cdf file */ |
109 int (*write)(CDataFile *cdf, void *data, int count); | 145 int (*write)(CDataFile *cdf, void *data, int count); |
110 | 146 |
111 » /* a function to determine file size */ | 147 » /** a function to determine file size */ |
112 size_t (*filesize)(CDataFile *cdf, void *data, int count); | 148 size_t (*filesize)(CDataFile *cdf, void *data, int count); |
113 | |
114 /* a function to validate layer contents depending on | |
115 * sub-elements count | |
116 */ | |
117 void (*validate)(void *source, int sub_elements); | |
118 } LayerTypeInfo; | 149 } LayerTypeInfo; |
119 | 150 |
120 static void layerCopy_mdeformvert(const void *source, void *dest, | 151 static void layerCopy_mdeformvert(const void *source, void *dest, |
121 » » » » » » » » int count) | 152 int count) |
122 { | 153 { |
123 int i, size = sizeof(MDeformVert); | 154 int i, size = sizeof(MDeformVert); |
124 | 155 |
125 memcpy(dest, source, count * size); | 156 memcpy(dest, source, count * size); |
126 | 157 |
127 » for(i = 0; i < count; ++i) { | 158 » for (i = 0; i < count; ++i) { |
128 MDeformVert *dvert = (MDeformVert *)((char *)dest + i * size); | 159 MDeformVert *dvert = (MDeformVert *)((char *)dest + i * size); |
129 | 160 |
130 » » if(dvert->totweight) { | 161 » » if (dvert->totweight) { |
131 » » » MDeformWeight *dw = MEM_callocN(dvert->totweight * sizeo
f(*dw), | 162 » » » MDeformWeight *dw = MEM_mallocN(dvert->totweight * sizeo
f(*dw), |
132 » » » » » » » » » »
» "layerCopy_mdeformvert dw"); | 163 » » » "layerCopy_mdeformvert d
w"); |
133 | 164 |
134 memcpy(dw, dvert->dw, dvert->totweight * sizeof(*dw)); | 165 memcpy(dw, dvert->dw, dvert->totweight * sizeof(*dw)); |
135 dvert->dw = dw; | 166 dvert->dw = dw; |
136 } | 167 } |
137 else | 168 else |
138 dvert->dw = NULL; | 169 dvert->dw = NULL; |
139 } | 170 } |
140 } | 171 } |
141 | 172 |
142 static void layerFree_mdeformvert(void *data, int count, int size) | 173 static void layerFree_mdeformvert(void *data, int count, int size) |
143 { | 174 { |
144 int i; | 175 int i; |
145 | 176 |
146 » for(i = 0; i < count; ++i) { | 177 » for (i = 0; i < count; ++i) { |
147 MDeformVert *dvert = (MDeformVert *)((char *)data + i * size); | 178 MDeformVert *dvert = (MDeformVert *)((char *)data + i * size); |
148 | 179 |
149 » » if(dvert->dw) { | 180 » » if (dvert->dw) { |
150 MEM_freeN(dvert->dw); | 181 MEM_freeN(dvert->dw); |
151 dvert->dw = NULL; | 182 dvert->dw = NULL; |
152 dvert->totweight = 0; | 183 dvert->totweight = 0; |
153 } | 184 } |
154 } | 185 } |
155 } | 186 } |
156 | 187 |
157 static void linklist_free_simple(void *link) | 188 /* copy just zeros in this case */ |
158 { | 189 static void layerCopy_bmesh_elem_py_ptr(const void *UNUSED(source), void *dest, |
159 » MEM_freeN(link); | 190 int count) |
160 } | 191 { |
161 | 192 » int i, size = sizeof(void *); |
162 static void layerInterp_mdeformvert(void **sources, float *weights, | 193 |
163 » » » » » » » » » float *U
NUSED(sub_weights), int count, void *dest) | 194 » for (i = 0; i < count; ++i) { |
164 { | 195 » » void **ptr = (void **)((char *)dest + i * size); |
| 196 » » *ptr = NULL; |
| 197 » } |
| 198 } |
| 199 |
| 200 #ifndef WITH_PYTHON |
| 201 void bpy_bm_generic_invalidate(struct BPy_BMGeneric *UNUSED(self)) |
| 202 { |
| 203 » /* dummy */ |
| 204 } |
| 205 #endif |
| 206 |
| 207 static void layerFree_bmesh_elem_py_ptr(void *data, int count, int size) |
| 208 { |
| 209 » int i; |
| 210 |
| 211 » for (i = 0; i < count; ++i) { |
| 212 » » void **ptr = (void *)((char *)data + i * size); |
| 213 » » if (*ptr) { |
| 214 » » » bpy_bm_generic_invalidate(*ptr); |
| 215 » » } |
| 216 » } |
| 217 } |
| 218 |
| 219 static void layerInterp_mdeformvert(void **sources, const float *weights, |
| 220 const float *UNUSED(sub_weights), int count,
void *dest) |
| 221 { |
| 222 » /* a single linked list of MDeformWeight's |
| 223 » * use this to avoid double allocs (which LinkNode would do) */ |
| 224 » struct MDeformWeight_Link { |
| 225 » » struct MDeformWeight_Link *next; |
| 226 » » MDeformWeight dw; |
| 227 » }; |
| 228 |
165 MDeformVert *dvert = dest; | 229 MDeformVert *dvert = dest; |
166 » LinkNode *dest_dw = NULL; /* a list of lists of MDeformWeight pointers *
/ | 230 » struct MDeformWeight_Link *dest_dwlink = NULL; |
167 » LinkNode *node; | 231 » struct MDeformWeight_Link *node; |
168 int i, j, totweight; | 232 int i, j, totweight; |
169 | 233 |
170 » if(count <= 0) return; | 234 » if (count <= 0) return; |
171 | 235 |
172 /* build a list of unique def_nrs for dest */ | 236 /* build a list of unique def_nrs for dest */ |
173 totweight = 0; | 237 totweight = 0; |
174 » for(i = 0; i < count; ++i) { | 238 » for (i = 0; i < count; ++i) { |
175 MDeformVert *source = sources[i]; | 239 MDeformVert *source = sources[i]; |
176 float interp_weight = weights ? weights[i] : 1.0f; | 240 float interp_weight = weights ? weights[i] : 1.0f; |
177 | 241 |
178 » » for(j = 0; j < source->totweight; ++j) { | 242 » » for (j = 0; j < source->totweight; ++j) { |
179 MDeformWeight *dw = &source->dw[j]; | 243 MDeformWeight *dw = &source->dw[j]; |
180 | 244 » » » float weight = dw->weight * interp_weight; |
181 » » » for(node = dest_dw; node; node = node->next) { | 245 |
182 » » » » MDeformWeight *tmp_dw = (MDeformWeight *)node->l
ink; | 246 » » » if (weight == 0.0f) |
183 | 247 » » » » continue; |
184 » » » » if(tmp_dw->def_nr == dw->def_nr) { | 248 |
185 » » » » » tmp_dw->weight += dw->weight * interp_we
ight; | 249 » » » for (node = dest_dwlink; node; node = node->next) { |
| 250 » » » » MDeformWeight *tmp_dw = &node->dw; |
| 251 |
| 252 » » » » if (tmp_dw->def_nr == dw->def_nr) { |
| 253 » » » » » tmp_dw->weight += weight; |
186 break; | 254 break; |
187 } | 255 } |
188 } | 256 } |
189 | 257 |
190 /* if this def_nr is not in the list, add it */ | 258 /* if this def_nr is not in the list, add it */ |
191 » » » if(!node) { | 259 » » » if (!node) { |
192 » » » » MDeformWeight *tmp_dw = MEM_callocN(sizeof(*tmp_
dw), | 260 » » » » struct MDeformWeight_Link *tmp_dwlink = alloca(s
izeof(*tmp_dwlink)); |
193 » » » » » » » » » »
» "layerInterp_mdeformvert tmp_dw"); | 261 » » » » tmp_dwlink->dw.def_nr = dw->def_nr; |
194 » » » » tmp_dw->def_nr = dw->def_nr; | 262 » » » » tmp_dwlink->dw.weight = weight; |
195 » » » » tmp_dw->weight = dw->weight * interp_weight; | 263 |
196 » » » » BLI_linklist_prepend(&dest_dw, tmp_dw); | 264 » » » » /* inline linklist */ |
| 265 » » » » tmp_dwlink->next = dest_dwlink; |
| 266 » » » » dest_dwlink = tmp_dwlink; |
| 267 |
197 totweight++; | 268 totweight++; |
198 } | 269 } |
199 } | 270 } |
200 } | 271 } |
201 | 272 |
| 273 /* delay writing to the destination incase dest is in sources */ |
| 274 |
202 /* now we know how many unique deform weights there are, so realloc */ | 275 /* now we know how many unique deform weights there are, so realloc */ |
203 » if(dvert->dw) MEM_freeN(dvert->dw); | 276 » if (dvert->dw && (dvert->totweight == totweight)) { |
204 | 277 » » /* pass (fastpath if we don't need to realloc) */ |
205 » if(totweight) { | 278 » } |
206 » » dvert->dw = MEM_callocN(sizeof(*dvert->dw) * totweight, | 279 » else { |
207 » » » » » » » » "layerInterp_mde
formvert dvert->dw"); | 280 » » if (dvert->dw) { |
| 281 » » » MEM_freeN(dvert->dw); |
| 282 » » } |
| 283 |
| 284 » » if (totweight) { |
| 285 » » » dvert->dw = MEM_mallocN(sizeof(*dvert->dw) * totweight,
__func__); |
| 286 » » } |
| 287 » } |
| 288 |
| 289 » if (totweight) { |
208 dvert->totweight = totweight; | 290 dvert->totweight = totweight; |
209 | 291 » » for (i = 0, node = dest_dwlink; node; node = node->next, i++) { |
210 » » for(i = 0, node = dest_dw; node; node = node->next, ++i) | 292 » » » dvert->dw[i] = node->dw; |
211 » » » dvert->dw[i] = *((MDeformWeight *)node->link); | 293 » » } |
212 » } | 294 » } |
213 » else | 295 » else { |
214 memset(dvert, 0, sizeof(*dvert)); | 296 memset(dvert, 0, sizeof(*dvert)); |
215 | 297 » } |
216 » BLI_linklist_free(dest_dw, linklist_free_simple); | 298 } |
217 } | 299 |
218 | 300 static void layerCopy_tface(const void *source, void *dest, int count) |
219 | 301 { |
220 static void layerInterp_msticky(void **sources, float *weights, | 302 » const MTFace *source_tf = (const MTFace *)source; |
221 » » » » » » » » float *UNUSED(su
b_weights), int count, void *dest) | 303 » MTFace *dest_tf = (MTFace *)dest; |
222 { | |
223 » float co[2], w; | |
224 » MSticky *mst; | |
225 int i; | 304 int i; |
226 | 305 |
227 » co[0] = co[1] = 0.0f; | 306 » for (i = 0; i < count; ++i) |
228 » for(i = 0; i < count; i++) { | |
229 » » w = weights ? weights[i] : 1.0f; | |
230 » » mst = (MSticky*)sources[i]; | |
231 | |
232 » » co[0] += w*mst->co[0]; | |
233 » » co[1] += w*mst->co[1]; | |
234 » } | |
235 | |
236 » mst = (MSticky*)dest; | |
237 » mst->co[0] = co[0]; | |
238 » mst->co[1] = co[1]; | |
239 } | |
240 | |
241 | |
242 static void layerCopy_tface(const void *source, void *dest, int count) | |
243 { | |
244 » const MTFace *source_tf = (const MTFace*)source; | |
245 » MTFace *dest_tf = (MTFace*)dest; | |
246 » int i; | |
247 | |
248 » for(i = 0; i < count; ++i) | |
249 dest_tf[i] = source_tf[i]; | 307 dest_tf[i] = source_tf[i]; |
250 } | 308 } |
251 | 309 |
252 static void layerInterp_tface(void **sources, float *weights, | 310 static void layerInterp_tface(void **sources, const float *weights, |
253 » » » » » » » float *sub_weights, in
t count, void *dest) | 311 const float *sub_weights, int count, void *dest) |
254 { | 312 { |
255 MTFace *tf = dest; | 313 MTFace *tf = dest; |
256 int i, j, k; | 314 int i, j, k; |
257 » float uv[4][2]; | 315 » float uv[4][2] = {{0.0f}}; |
258 » float *sub_weight; | 316 » const float *sub_weight; |
259 | 317 |
260 » if(count <= 0) return; | 318 » if (count <= 0) return; |
261 | |
262 » memset(uv, 0, sizeof(uv)); | |
263 | 319 |
264 sub_weight = sub_weights; | 320 sub_weight = sub_weights; |
265 » for(i = 0; i < count; ++i) { | 321 » for (i = 0; i < count; ++i) { |
266 float weight = weights ? weights[i] : 1; | 322 float weight = weights ? weights[i] : 1; |
267 MTFace *src = sources[i]; | 323 MTFace *src = sources[i]; |
268 | 324 |
269 » » for(j = 0; j < 4; ++j) { | 325 » » for (j = 0; j < 4; ++j) { |
270 » » » if(sub_weights) { | |
271 » » » » for(k = 0; k < 4; ++k, ++sub_weight) { | |
272 » » » » » float w = (*sub_weight) * weight; | |
273 » » » » » float *tmp_uv = src->uv[k]; | |
274 | |
275 » » » » » uv[j][0] += tmp_uv[0] * w; | |
276 » » » » » uv[j][1] += tmp_uv[1] * w; | |
277 » » » » } | |
278 » » » } else { | |
279 » » » » uv[j][0] += src->uv[j][0] * weight; | |
280 » » » » uv[j][1] += src->uv[j][1] * weight; | |
281 » » » } | |
282 » » } | |
283 » } | |
284 | |
285 » *tf = *(MTFace *)sources[0]; | |
286 » for(j = 0; j < 4; ++j) { | |
287 » » tf->uv[j][0] = uv[j][0]; | |
288 » » tf->uv[j][1] = uv[j][1]; | |
289 » } | |
290 } | |
291 | |
292 static void layerSwap_tface(void *data, const int *corner_indices) | |
293 { | |
294 » MTFace *tf = data; | |
295 » float uv[4][2]; | |
296 » static const short pin_flags[4] = | |
297 » » { TF_PIN1, TF_PIN2, TF_PIN3, TF_PIN4 }; | |
298 » static const char sel_flags[4] = | |
299 » » { TF_SEL1, TF_SEL2, TF_SEL3, TF_SEL4 }; | |
300 » short unwrap = tf->unwrap & ~(TF_PIN1 | TF_PIN2 | TF_PIN3 | TF_PIN4); | |
301 » char flag = tf->flag & ~(TF_SEL1 | TF_SEL2 | TF_SEL3 | TF_SEL4); | |
302 » int j; | |
303 | |
304 » for(j = 0; j < 4; ++j) { | |
305 » » int source_index = corner_indices[j]; | |
306 | |
307 » » uv[j][0] = tf->uv[source_index][0]; | |
308 » » uv[j][1] = tf->uv[source_index][1]; | |
309 | |
310 » » // swap pinning flags around | |
311 » » if(tf->unwrap & pin_flags[source_index]) { | |
312 » » » unwrap |= pin_flags[j]; | |
313 » » } | |
314 | |
315 » » // swap selection flags around | |
316 » » if(tf->flag & sel_flags[source_index]) { | |
317 » » » flag |= sel_flags[j]; | |
318 » » } | |
319 » } | |
320 | |
321 » memcpy(tf->uv, uv, sizeof(tf->uv)); | |
322 » tf->unwrap = unwrap; | |
323 » tf->flag = flag; | |
324 } | |
325 | |
326 static void layerDefault_tface(void *data, int count) | 326 static void layerDefault_tface(void *data, int count) |
327 { | 327 { |
328 static MTFace default_tf = {{{0, 0}, {1, 0}, {1, 1}, {0, 1}}, NULL, | 328 static MTFace default_tf = {{{0, 0}, {1, 0}, {1, 1}, {0, 1}}, NULL, |
329 » » » » » » » 0, 0, TF_DYNAMIC|TF_C
ONVERTED, 0, 0}; | 329 » » » » » » » 0, 0, TF_DYNAMIC, 0,
0}; |
330 MTFace *tf = (MTFace*)data; | 330 MTFace *tf = (MTFace*)data; |
331 int i; | 331 int i; |
332 | 332 |
333 for(i = 0; i < count; i++) | |
334 tf[i] = default_tf; | |
335 } | |
336 | |
337 static void layerCopy_origspace_face(const void *source, void *dest, int count) | |
338 { | |
339 const OrigSpaceFace *source_tf = (const OrigSpaceFace*)source; | |
340 OrigSpaceFace *dest_tf = (OrigSpaceFace*)dest; | |
341 int i; | |
342 | |
343 for(i = 0; i < count; ++i) | |
344 dest_tf[i] = source_tf[i]; | |
345 } | |
346 | |
347 static void layerInterp_origspace_face(void **sources, float *weights, | |
348 float *sub_weights, in
t count, void *dest) | |
349 { | |
350 OrigSpaceFace *osf = dest; | |
351 int i, j, k; | |
352 float uv[4][2]; | |
353 float *sub_weight; | |
354 | |
355 if(count <= 0) return; | |
356 | |
357 memset(uv, 0, sizeof(uv)); | |
358 | |
359 sub_weight = sub_weights; | |
360 for(i = 0; i < count; ++i) { | |
361 float weight = weights ? weights[i] : 1; | |
362 OrigSpaceFace *src = sources[i]; | |
363 | |
364 for(j = 0; j < 4; ++j) { | |
365 if(sub_weights) { | |
366 for(k = 0; k < 4; ++k, ++sub_weight) { | |
367 float w = (*sub_weight) * weight; | |
368 float *tmp_uv = src->uv[k]; | |
369 | |
370 uv[j][0] += tmp_uv[0] * w; | |
371 uv[j][1] += tmp_uv[1] * w; | |
372 } | |
373 } else { | |
374 uv[j][0] += src->uv[j][0] * weight; | |
375 uv[j][1] += src->uv[j][1] * weight; | |
376 } | |
377 } | |
378 } | |
379 | |
380 *osf = *(OrigSpaceFace *)sources[0]; | |
381 for(j = 0; j < 4; ++j) { | |
382 osf->uv[j][0] = uv[j][0]; | |
383 osf->uv[j][1] = uv[j][1]; | |
384 } | |
385 } | |
386 | |
387 static void layerSwap_origspace_face(void *data, const int *corner_indices) | |
388 { | |
389 OrigSpaceFace *osf = data; | |
390 float uv[4][2]; | |
391 int j; | |
392 | |
393 for(j = 0; j < 4; ++j) { | |
394 uv[j][0] = osf->uv[corner_indices[j]][0]; | |
395 uv[j][1] = osf->uv[corner_indices[j]][1]; | |
396 } | |
397 memcpy(osf->uv, uv, sizeof(osf->uv)); | |
398 } | |
399 | |
400 static void layerDefault_origspace_face(void *data, int count) | |
401 { | |
402 static OrigSpaceFace default_osf = {{{0, 0}, {1, 0}, {1, 1}, {0, 1}}}; | |
403 OrigSpaceFace *osf = (OrigSpaceFace*)data; | |
404 int i; | |
405 | |
406 for(i = 0; i < count; i++) | |
407 osf[i] = default_osf; | |
408 } | |
409 | |
410 static void layerSwap_mdisps(void *data, const int *ci) | |
411 { | |
412 MDisps *s = data; | |
413 float (*d)[3] = NULL; | |
414 int corners, cornersize, S; | |
415 | |
416 if(s->disps) { | |
417 int nverts= (ci[1] == 3) ? 4 : 3; /* silly way to know vertex co
unt of face */ | |
418 corners= multires_mdisp_corners(s); | |
419 cornersize= s->totdisp/corners; | |
420 | |
421 if(corners!=nverts) { | |
422 /* happens when face changed vertex count in edit mode | |
423 if it happened, just forgot displacement */ | |
424 | |
425 MEM_freeN(s->disps); | |
426 s->totdisp= (s->totdisp/corners)*nverts; | |
427 s->disps= MEM_callocN(s->totdisp*sizeof(float)*3, "mdisp
swap"); | |
428 return; | |
429 } | |
430 | |
431 d= MEM_callocN(sizeof(float) * 3 * s->totdisp, "mdisps swap"); | |
432 | |
433 for(S = 0; S < corners; S++) | |
434 memcpy(d + cornersize*S, s->disps + cornersize*ci[S], co
rnersize*3*sizeof(float)); | |
435 ················ | |
436 MEM_freeN(s->disps); | |
437 s->disps= d; | |
438 } | |
439 } | |
440 | |
441 static void layerInterp_mdisps(void **sources, float *UNUSED(weights), | |
442 float *sub_weights, int count, void *dest) | |
443 { | |
444 MDisps *d = dest; | |
445 MDisps *s = NULL; | |
446 int st, stl; | |
447 int i, x, y; | |
448 int side, S, dst_corners, src_corners; | |
449 float crn_weight[4][2]; | |
450 float (*sw)[4] = (void*)sub_weights; | |
451 float (*disps)[3], (*out)[3]; | |
452 | |
453 /* happens when flipping normals of newly created mesh */ | |
454 if(!d->totdisp) | |
455 return; | |
456 | |
457 s = sources[0]; | |
458 dst_corners = multires_mdisp_corners(d); | |
459 src_corners = multires_mdisp_corners(s); | |
460 | |
461 if(sub_weights && count == 2 && src_corners == 3) { | |
462 src_corners = multires_mdisp_corners(sources[1]); | |
463 | |
464 /* special case -- converting two triangles to quad */ | |
465 if(src_corners == 3 && dst_corners == 4) { | |
466 MDisps tris[2]; | |
467 int vindex[4] = {0}; | |
468 | |
469 for(i = 0; i < 2; i++) | |
470 for(y = 0; y < 4; y++) | |
471 for(x = 0; x < 4; x++) | |
472 if(sw[x+i*4][y]) | |
473 vindex[x] = y; | |
474 | |
475 for(i = 0; i < 2; i++) { | |
476 float sw_m4[4][4] = {{0}}; | |
477 int a = 7 & ~(1 << vindex[i*2] | 1 << vindex[i*2
+1]); | |
478 | |
479 sw_m4[0][vindex[i*2+1]] = 1; | |
480 sw_m4[1][vindex[i*2]] = 1; | |
481 | |
482 for(x = 0; x < 3; x++) | |
483 if(a & (1 << x)) | |
484 sw_m4[2][x] = 1; | |
485 | |
486 tris[i] = *((MDisps*)sources[i]); | |
487 tris[i].disps = MEM_dupallocN(tris[i].disps); | |
488 layerInterp_mdisps(&sources[i], NULL, (float*)sw
_m4, 1, &tris[i]); | |
489 } | |
490 | |
491 mdisp_join_tris(d, &tris[0], &tris[1]); | |
492 | |
493 for(i = 0; i < 2; i++) | |
494 MEM_freeN(tris[i].disps); | |
495 | |
496 return; | |
497 } | |
498 } | |
499 | |
500 /* For now, some restrictions on the input */ | |
501 if(count != 1 || !sub_weights) { | |
502 for(i = 0; i < d->totdisp; ++i) | |
503 zero_v3(d->disps[i]); | |
504 | |
505 return; | |
506 } | |
507 | |
508 /* Initialize the destination */ | |
509 disps = MEM_callocN(3*d->totdisp*sizeof(float), "iterp disps"); | |
510 | |
511 side = sqrt(d->totdisp / dst_corners); | |
512 st = (side<<1)-1; | |
513 stl = st - 1; | |
514 | |
515 sw= (void*)sub_weights; | |
516 for(i = 0; i < 4; ++i) { | |
517 crn_weight[i][0] = 0 * sw[i][0] + stl * sw[i][1] + stl * sw[i][2
] + 0 * sw[i][3]; | |
518 crn_weight[i][1] = 0 * sw[i][0] + 0 * sw[i][1] + stl * sw[i][2]
+ stl * sw[i][3]; | |
519 } | |
520 | |
521 multires_mdisp_smooth_bounds(s); | |
522 | |
523 out = disps; | |
524 for(S = 0; S < dst_corners; S++) { | |
525 float base[2], axis_x[2], axis_y[2]; | |
526 | |
527 mdisp_apply_weight(S, dst_corners, 0, 0, st, crn_weight, &base[0
], &base[1]); | |
528 mdisp_apply_weight(S, dst_corners, side-1, 0, st, crn_weight, &a
xis_x[0], &axis_x[1]); | |
529 mdisp_apply_weight(S, dst_corners, 0, side-1, st, crn_weight, &a
xis_y[0], &axis_y[1]); | |
530 | |
531 sub_v2_v2(axis_x, base); | |
532 sub_v2_v2(axis_y, base); | |
533 normalize_v2(axis_x); | |
534 normalize_v2(axis_y); | |
535 | |
536 for(y = 0; y < side; ++y) { | |
537 for(x = 0; x < side; ++x, ++out) { | |
538 int crn; | |
539 float face_u, face_v, crn_u, crn_v; | |
540 | |
541 mdisp_apply_weight(S, dst_corners, x, y, st, crn
_weight, &face_u, &face_v); | |
542 crn = mdisp_rot_face_to_quad_crn(src_corners, st
, face_u, face_v, &crn_u, &crn_v); | |
543 | |
544 old_mdisps_bilinear((*out), &s->disps[crn*side*s
ide], side, crn_u, crn_v); | |
545 mdisp_flip_disp(crn, dst_corners, axis_x, axis_y
, *out); | |
546 } | |
547 } | |
548 } | |
549 | |
550 MEM_freeN(d->disps); | |
551 d->disps = disps; | |
552 } | |
553 | |
554 static void layerCopy_mdisps(const void *source, void *dest, int count) | |
555 { | |
556 int i; | |
557 const MDisps *s = source; | |
558 MDisps *d = dest; | |
559 | |
560 for(i = 0; i < count; ++i) { | |
561 if(s[i].disps) { | |
562 d[i].disps = MEM_dupallocN(s[i].disps); | |
563 d[i].totdisp = s[i].totdisp; | |
564 } | |
565 else { | |
566 d[i].disps = NULL; | |
567 d[i].totdisp = 0; | |
568 } | |
569 ················ | |
570 } | |
571 } | |
572 | |
573 static void layerValidate_mdisps(void *data, int sub_elements) | |
574 { | |
575 MDisps *disps = data; | |
576 if(disps->disps) { | |
577 int corners = multires_mdisp_corners(disps); | |
578 | |
579 if(corners != sub_elements) { | |
580 MEM_freeN(disps->disps); | |
581 disps->totdisp = disps->totdisp / corners * sub_elements
; | |
582 disps->disps = MEM_callocN(3*disps->totdisp*sizeof(float
), "layerValidate_mdisps"); | |
583 } | |
584 } | |
585 } | |
586 | |
587 static void layerFree_mdisps(void *data, int count, int UNUSED(size)) | |
588 { | |
589 int i; | |
590 MDisps *d = data; | |
591 | |
592 for(i = 0; i < count; ++i) { | |
593 if(d[i].disps) | |
594 MEM_freeN(d[i].disps); | |
595 d[i].disps = NULL; | |
596 d[i].totdisp = 0; | |
597 } | |
598 } | |
599 | |
600 static int layerRead_mdisps(CDataFile *cdf, void *data, int count) | |
601 { | |
602 MDisps *d = data; | |
603 int i; | |
604 | |
605 for(i = 0; i < count; ++i) { | |
606 if(!d[i].disps) | |
607 d[i].disps = MEM_callocN(sizeof(float)*3*d[i].totdisp, "
mdisps read"); | |
608 | |
609 if(!cdf_read_data(cdf, d[i].totdisp*3*sizeof(float), d[i].disps)
) { | |
610 printf("failed to read multires displacement %d/%d %d\n"
, i, count, d[i].totdisp); | |
611 return 0; | |
612 } | |
613 } | |
614 | |
615 return 1; | |
616 } | |
617 | |
618 static int layerWrite_mdisps(CDataFile *cdf, void *data, int count) | |
619 { | |
620 MDisps *d = data; | |
621 int i; | |
622 | |
623 for(i = 0; i < count; ++i) { | |
624 if(!cdf_write_data(cdf, d[i].totdisp*3*sizeof(float), d[i].disps
)) { | |
625 printf("failed to write multires displacement %d/%d %d\n
", i, count, d[i].totdisp); | |
626 return 0; | |
627 } | |
628 } | |
629 | |
630 return 1; | |
631 } | |
632 | |
633 static size_t layerFilesize_mdisps(CDataFile *UNUSED(cdf), void *data, int count
) | |
634 { | |
635 MDisps *d = data; | |
636 size_t size = 0; | |
637 int i; | |
638 | |
639 for(i = 0; i < count; ++i) | |
640 size += d[i].totdisp*3*sizeof(float); | |
641 | |
642 return size; | |
643 } | |
644 | |
645 /* --------- */ | |
646 | |
647 static void layerDefault_mloopcol(void *data, int count) | |
648 { | |
649 static MLoopCol default_mloopcol = {255,255,255,255}; | |
650 MLoopCol *mlcol = (MLoopCol*)data; | |
651 int i; | |
652 for(i = 0; i < count; i++) | |
653 mlcol[i] = default_mloopcol; | |
654 | |
655 } | |
656 | |
657 static void layerInterp_mloopcol(void **sources, float *weights, | |
658 float *sub_weights, int count, void *dest) | |
659 { | |
660 MLoopCol *mc = dest; | |
661 int i; | |
662 float *sub_weight; | |
663 struct { | |
664 float a; | |
665 float r; | |
666 float g; | |
667 float b; | |
668 } col; | |
669 col.a = col.r = col.g = col.b = 0; | |
670 | |
671 sub_weight = sub_weights; | |
672 for(i = 0; i < count; ++i){ | |
673 float weight = weights ? weights[i] : 1; | |
674 MLoopCol *src = sources[i]; | |
675 if(sub_weights){ | |
676 col.a += src->a * (*sub_weight) * weight; | |
677 col.r += src->r * (*sub_weight) * weight; | |
678 col.g += src->g * (*sub_weight) * weight; | |
679 col.b += src->b * (*sub_weight) * weight; | |
680 sub_weight++;··········· | |
681 } else { | |
682 col.a += src->a * weight; | |
683 col.r += src->r * weight; | |
684 col.g += src->g * weight; | |
685 col.b += src->b * weight; | |
686 } | |
687 } | |
688 ········ | |
689 /* Subdivide smooth or fractal can cause problems without clamping | |
690 * although weights should also not cause this situation */ | |
691 CLAMP(col.a, 0.0f, 255.0f); | |
692 CLAMP(col.r, 0.0f, 255.0f); | |
693 CLAMP(col.g, 0.0f, 255.0f); | |
694 CLAMP(col.b, 0.0f, 255.0f); | |
695 ········ | |
696 mc->a = (int)col.a; | |
697 mc->r = (int)col.r; | |
698 mc->g = (int)col.g; | |
699 mc->b = (int)col.b; | |
700 } | |
701 static void layerInterp_mloopuv(void **sources, float *weights, | |
702 float *sub_weights, int count, void *dest) | |
703 { | |
704 MLoopUV *mluv = dest; | |
705 int i; | |
706 float *sub_weight; | |
707 struct { | |
708 float u; | |
709 float v; | |
710 }uv; | |
711 uv.u = uv.v = 0.0; | |
712 | |
713 sub_weight = sub_weights; | |
714 for(i = 0; i < count; ++i){ | |
715 float weight = weights ? weights[i] : 1; | |
716 MLoopUV *src = sources[i]; | |
717 if(sub_weights){ | |
718 uv.u += src->uv[0] * (*sub_weight) * weight; | |
719 uv.v += src->uv[1] * (*sub_weight) * weight; | |
720 sub_weight++;··········· | |
721 } else { | |
722 uv.u += src->uv[0] * weight; | |
723 uv.v += src->uv[1] * weight; | |
724 } | |
725 } | |
726 mluv->uv[0] = uv.u; | |
727 mluv->uv[1] = uv.v; | |
728 } | |
729 | |
730 static void layerInterp_mcol(void **sources, float *weights, | |
731 float *sub_weights, int
count, void *dest) | |
732 { | |
733 MCol *mc = dest; | |
734 int i, j, k; | |
735 struct { | |
736 float a; | |
737 float r; | |
738 float g; | |
739 float b; | |
740 } col[4]; | |
741 float *sub_weight; | |
742 | |
743 if(count <= 0) return; | |
744 | |
745 memset(col, 0, sizeof(col)); | |
746 ········ | |
747 sub_weight = sub_weights; | |
748 for(i = 0; i < count; ++i) { | |
749 float weight = weights ? weights[i] : 1; | |
750 | |
751 for(j = 0; j < 4; ++j) { | |
752 if(sub_weights) { | |
753 MCol *src = sources[i]; | |
754 for(k = 0; k < 4; ++k, ++sub_weight, ++src) { | |
755 col[j].a += src->a * (*sub_weight) * wei
ght; | |
756 col[j].r += src->r * (*sub_weight) * wei
ght; | |
757 col[j].g += src->g * (*sub_weight) * wei
ght; | |
758 col[j].b += src->b * (*sub_weight) * wei
ght; | |
759 } | |
760 } else { | |
761 MCol *src = sources[i]; | |
762 col[j].a += src[j].a * weight; | |
763 col[j].r += src[j].r * weight; | |
764 col[j].g += src[j].g * weight; | |
765 col[j].b += src[j].b * weight; | |
766 } | |
767 } | |
768 } | |
769 | |
770 for(j = 0; j < 4; ++j) { | |
771 ················ | |
772 /* Subdivide smooth or fractal can cause problems without clampi
ng | |
773 * although weights should also not cause this situation */ | |
774 CLAMP(col[j].a, 0.0f, 255.0f); | |
775 CLAMP(col[j].r, 0.0f, 255.0f); | |
776 CLAMP(col[j].g, 0.0f, 255.0f); | |
777 CLAMP(col[j].b, 0.0f, 255.0f); | |
778 ················ | |
779 mc[j].a = (int)col[j].a; | |
780 mc[j].r = (int)col[j].r; | |
781 mc[j].g = (int)col[j].g; | |
782 mc[j].b = (int)col[j].b; | |
783 } | |
784 } | |
785 | |
786 static void layerSwap_mcol(void *data, const int *corner_indices) | |
787 { | |
788 MCol *mcol = data; | |
789 MCol col[4]; | |
790 int j; | |
791 | |
792 for(j = 0; j < 4; ++j) | |
793 col[j] = mcol[corner_indices[j]]; | |
794 | |
795 memcpy(mcol, col, sizeof(col)); | |
796 } | |
797 | |
798 static void layerDefault_mcol(void *data, int count) | |
799 { | |
800 static MCol default_mcol = {255, 255, 255, 255}; | |
801 MCol *mcol = (MCol*)data; | |
802 int i; | |
803 | |
804 for(i = 0; i < 4*count; i++) | |
805 mcol[i] = default_mcol; | |
806 } | |
807 | |
808 | |
809 | |
810 static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { | |
811 /* 0: CD_MVERT */ | |
812 {sizeof(MVert), "MVert", 1, NULL, NULL, NULL, NULL, NULL, NULL}, | |
813 /* 1: CD_MSTICKY */ | |
814 {sizeof(MSticky), "MSticky", 1, NULL, NULL, NULL, layerInterp_msticky, N
ULL, | |
815 NULL}, | |
816 /* 2: CD_MDEFORMVERT */ | |
817 {sizeof(MDeformVert), "MDeformVert", 1, NULL, layerCopy_mdeformvert, | |
818 layerFree_mdeformvert, layerInterp_mdeformvert, NULL, NULL}, | |
819 /* 3: CD_MEDGE */ | |
820 {sizeof(MEdge), "MEdge", 1, NULL, NULL, NULL, NULL, NULL, NULL}, | |
821 /* 4: CD_MFACE */ | |
822 {sizeof(MFace), "MFace", 1, NULL, NULL, NULL, NULL, NULL, NULL}, | |
823 /* 5: CD_MTFACE */ | |
824 {sizeof(MTFace), "MTFace", 1, "UVTex", layerCopy_tface, NULL, | |
825 layerInterp_tface, layerSwap_tface, layerDefault_tface}, | |
826 /* 6: CD_MCOL */ | |
827 /* 4 MCol structs per face */ | |
828 {sizeof(MCol)*4, "MCol", 4, "Col", NULL, NULL, layerInterp_mcol, | |
829 layerSwap_mcol, layerDefault_mcol}, | |
830 /* 7: CD_ORIGINDEX */ | |
831 {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, | |
832 /* 8: CD_NORMAL */ | |
833 /* 3 floats per normal vector */ | |
834 {sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, | |
835 /* 9: CD_FLAGS */ | |
836 {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, | |
837 /* 10: CD_PROP_FLT */ | |
838 {sizeof(MFloatProperty), "MFloatProperty",1,"Float",NULL,NULL,NULL,NULL}
, | |
839 /* 11: CD_PROP_INT */ | |
840 {sizeof(MIntProperty), "MIntProperty",1,"Int",NULL,NULL,NULL,NULL}, | |
841 /* 12: CD_PROP_STR */ | |
842 {sizeof(MStringProperty), "MStringProperty",1,"String",NULL,NULL,NULL,NU
LL}, | |
843 /* 13: CD_ORIGSPACE */ | |
844 {sizeof(OrigSpaceFace), "OrigSpaceFace", 1, "UVTex", layerCopy_origspace
_face, NULL, | |
845 layerInterp_origspace_face, layerSwap_origspace_face, layerDefault_orig
space_face}, | |
846 /* 14: CD_ORCO */ | |
847 {sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, | |
848 /* 15: CD_MTEXPOLY */ | |
849 {sizeof(MTexPoly), "MTexPoly", 1, "Face Texture", NULL, NULL, NULL, NULL
, NULL}, | |
850 /* 16: CD_MLOOPUV */ | |
851 {sizeof(MLoopUV), "MLoopUV", 1, "UV coord", NULL, NULL, layerInterp_mloo
puv, NULL, NULL}, | |
852 /* 17: CD_MLOOPCOL */ | |
853 {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopco
l, NULL, layerDefault_mloopcol}, | |
854 /* 18: CD_TANGENT */ | |
855 {sizeof(float)*4*4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, | |
856 /* 19: CD_MDISPS */ | |
857 {sizeof(MDisps), "MDisps", 1, NULL, layerCopy_mdisps, | |
858 layerFree_mdisps, layerInterp_mdisps, layerSwap_mdisps, NULL, layerRead
_mdisps, layerWrite_mdisps, | |
859 layerFilesize_mdisps, layerValidate_mdisps}, | |
860 /* 20: CD_WEIGHT_MCOL */ | |
861 {sizeof(MCol)*4, "MCol", 4, "WeightCol", NULL, NULL, layerInterp_mcol, | |
862 layerSwap_mcol, layerDefault_mcol}, | |
863 /* 21: CD_ID_MCOL */ | |
864 {sizeof(MCol)*4, "MCol", 4, "IDCol", NULL, NULL, layerInterp_mcol, | |
865 layerSwap_mcol, layerDefault_mcol}, | |
866 /* 22: CD_TEXTURE_MCOL */ | |
867 {sizeof(MCol)*4, "MCol", 4, "TexturedCol", NULL, NULL, layerInterp_mcol, | |
868 layerSwap_mcol, layerDefault_mcol}, | |
869 /* 23: CD_CLOTH_ORCO */ | |
870 {sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, | |
871 /* 24: CD_RECAST */ | |
872 {sizeof(MRecast), "MRecast", 1,"Recast",NULL,NULL,NULL,NULL} | |
873 }; | |
874 | |
875 static const char *LAYERTYPENAMES[CD_NUMTYPES] = { | |
876 /* 0-4 */ "CDMVert", "CDMSticky", "CDMDeformVert", "CDMEdge", "CDMFace
", | |
877 /* 5-9 */ "CDMTFace", "CDMCol", "CDOrigIndex", "CDNormal", "CDFlags", | |
878 /* 10-14 */ "CDMFloatProperty", "CDMIntProperty","CDMStringProperty", "C
DOrigSpace", "CDOrco", | |
879 /* 15-19 */ "CDMTexPoly", "CDMLoopUV", "CDMloopCol", "CDTangent", "CDMDi
sps", | |
880 /* 20-24 */"CDWeightMCol", "CDIDMCol", "CDTextureMCol", "CDClothOrco", "
CDMRecast" | |
881 }; | |
882 | |
883 const CustomDataMask CD_MASK_BAREMESH = | |
884 CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE; | |
885 const CustomDataMask CD_MASK_MESH = | |
886 CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE | | |
887 CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | CD_MASK_MCOL | | |
888 CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS
| CD_MASK_RECAST; | |
889 const CustomDataMask CD_MASK_EDITMESH = | |
890 CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | | |
891 CD_MASK_MCOL|CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD
_MASK_MDISPS | CD_MASK_RECAST; | |
892 const CustomDataMask CD_MASK_DERIVEDMESH = | |
893 CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | | |
894 CD_MASK_MCOL | CD_MASK_ORIGINDEX | CD_MASK_PROP_FLT | CD_MASK_PROP_INT |
CD_MASK_CLOTH_ORCO | | |
895 CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO | CD_MASK_TANGENT |
CD_MASK_WEIGHT_MCOL | CD_MASK_RECAST; | |
896 const CustomDataMask CD_MASK_BMESH =· | |
897 CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_
INT | CD_MASK_PROP_STR; | |
898 const CustomDataMask CD_MASK_FACECORNERS = | |
899 CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV | | |
900 CD_MASK_MLOOPCOL; | |
901 | |
902 | |
903 static const LayerTypeInfo *layerType_getInfo(int type) | |
904 { | |
905 if(type < 0 || type >= CD_NUMTYPES) return NULL; | |
906 | |
907 return &LAYERTYPEINFO[type]; | |
908 } | |
909 | |
910 static const char *layerType_getName(int type) | |
911 { | |
912 if(type < 0 || type >= CD_NUMTYPES) return NULL; | |
913 | |
914 return LAYERTYPENAMES[type]; | |
915 } | |
916 | |
917 /********************* CustomData functions *********************/ | |
918 static void customData_update_offsets(CustomData *data); | |
919 | |
920 static CustomDataLayer *customData_add_layer__internal(CustomData *data, | |
921 int type, int alloctype, void *layerdata, int totelem, const char *name)
; | |
922 | |
923 void CustomData_merge(const struct CustomData *source, struct CustomData *dest, | |
924 CustomDataMask mask, int alloctype, in
t totelem) | |
925 { | |
926 /*const LayerTypeInfo *typeInfo;*/ | |
927 CustomDataLayer *layer, *newlayer; | |
928 int i, type, number = 0, lasttype = -1, lastactive = 0, lastrender = 0,
lastclone = 0, lastmask = 0, lastflag = 0; | |
929 | |
930 for(i = 0; i < source->totlayer; ++i) { | |
931 layer = &source->layers[i]; | |
932 /*typeInfo = layerType_getInfo(layer->type);*/ /*UNUSED*/ | |
933 | |
934 type = layer->type; | |
935 | |
936 if (type != lasttype) { | |
937 number = 0; | |
938 lastactive = layer->active; | |
939 lastrender = layer->active_rnd; | |
940 lastclone = layer->active_clone; | |
941 lastmask = layer->active_mask; | |
942 lasttype = type; | |
943 lastflag = layer->flag; | |
944 } | |
945 else | |
946 number++; | |
947 | |
948 if(lastflag & CD_FLAG_NOCOPY) continue; | |
949 else if(!((int)mask & (int)(1 << (int)type))) continue; | |
950 else if(number < CustomData_number_of_layers(dest, type)) contin
ue; | |
951 | |
952 if((alloctype == CD_ASSIGN) && (lastflag & CD_FLAG_NOFREE)) | |
953 newlayer = customData_add_layer__internal(dest, type, CD
_REFERENCE, | |
954 layer->data, totelem, layer->name); | |
955 else | |
956 newlayer = customData_add_layer__internal(dest, type, al
loctype, | |
957 layer->data, totelem, layer->name); | |
958 ················ | |
959 if(newlayer) { | |
960 newlayer->active = lastactive; | |
961 newlayer->active_rnd = lastrender; | |
962 newlayer->active_clone = lastclone; | |
963 newlayer->active_mask = lastmask; | |
964 newlayer->flag |= lastflag & (CD_FLAG_EXTERNAL|CD_FLAG_I
N_MEMORY); | |
965 } | |
966 } | |
967 } | |
968 | |
969 void CustomData_copy(const struct CustomData *source, struct CustomData *dest, | |
970 CustomDataMask mask, int alloctype, int
totelem) | |
971 { | |
972 memset(dest, 0, sizeof(*dest)); | |
973 | |
974 if(source->external) | |
975 dest->external= MEM_dupallocN(source->external); | |
976 | |
977 CustomData_merge(source, dest, mask, alloctype, totelem); | |
978 } | |
979 | |
980 static void customData_free_layer__internal(CustomDataLayer *layer, int totelem) | |
981 { | |
982 const LayerTypeInfo *typeInfo; | |
983 | |
984 if(!(layer->flag & CD_FLAG_NOFREE) && layer->data) { | |
985 typeInfo = layerType_getInfo(layer->type); | |
986 | |
987 if(typeInfo->free) | |
988 typeInfo->free(layer->data, totelem, typeInfo->size); | |
989 | |
990 if(layer->data) | |
991 MEM_freeN(layer->data); | |
992 } | |
993 } | |
994 | |
995 static void CustomData_external_free(CustomData *data) | |
996 { | |
997 if(data->external) { | |
998 MEM_freeN(data->external); | |
999 data->external= NULL; | |
1000 } | |
1001 } | |
1002 | |
1003 void CustomData_free(CustomData *data, int totelem) | |
1004 { | |
1005 int i; | |
1006 | |
1007 for(i = 0; i < data->totlayer; ++i) | |
1008 customData_free_layer__internal(&data->layers[i], totelem); | |
1009 | |
1010 if(data->layers) | |
1011 MEM_freeN(data->layers); | |
1012 ········ | |
1013 CustomData_external_free(data); | |
1014 ········ | |
1015 memset(data, 0, sizeof(*data)); | |
1016 } | |
1017 | |
1018 static void customData_update_offsets(CustomData *data) | |
1019 { | |
1020 const LayerTypeInfo *typeInfo; | |
1021 int i, offset = 0; | |
1022 | |
1023 for(i = 0; i < data->totlayer; ++i) { | |
1024 typeInfo = layerType_getInfo(data->layers[i].type); | |
1025 | |
1026 data->layers[i].offset = offset; | |
1027 offset += typeInfo->size; | |
1028 } | |
1029 | |
1030 data->totsize = offset; | |
1031 } | |
1032 | |
1033 int CustomData_get_layer_index(const CustomData *data, int type) | |
1034 { | |
1035 int i;· | |
1036 | |
1037 for(i=0; i < data->totlayer; ++i) | |
1038 if(data->layers[i].type == type) | |
1039 return i; | |
1040 | |
1041 return -1; | |
1042 } | |
1043 | |
1044 int CustomData_get_named_layer_index(const CustomData *data, int type, const cha
r *name) | |
1045 { | |
1046 int i; | |
1047 | |
1048 for(i=0; i < data->totlayer; ++i) | |
1049 if(data->layers[i].type == type && strcmp(data->layers[i].name,
name)==0) | |
1050 return i; | |
1051 | |
1052 return -1; | |
1053 } | |
1054 | |
1055 int CustomData_get_active_layer_index(const CustomData *data, int type) | |
1056 { | |
1057 int i; | |
1058 | |
1059 for(i=0; i < data->totlayer; ++i) | |
1060 if(data->layers[i].type == type) | |
1061 return i + data->layers[i].active; | |
1062 | |
1063 return -1; | |
1064 } | |
1065 | |
1066 int CustomData_get_render_layer_index(const CustomData *data, int type) | |
1067 { | |
1068 int i; | |
1069 | |
1070 for(i=0; i < data->totlayer; ++i) | |
1071 if(data->layers[i].type == type) | |
1072 return i + data->layers[i].active_rnd; | |
1073 | |
1074 return -1; | |
1075 } | |
1076 | |
1077 int CustomData_get_clone_layer_index(const CustomData *data, int type) | |
1078 { | |
1079 int i; | |
1080 | |
1081 for(i=0; i < data->totlayer; ++i) | |
1082 if(data->layers[i].type == type) | |
1083 return i + data->layers[i].active_clone; | |
1084 | |
1085 return -1; | |
1086 } | |
1087 | |
1088 int CustomData_get_stencil_layer_index(const CustomData *data, int type) | |
1089 { | |
1090 int i; | |
1091 | |
1092 for(i=0; i < data->totlayer; ++i) | |
1093 if(data->layers[i].type == type) | |
1094 return i + data->layers[i].active_mask; | |
1095 | |
1096 return -1; | |
1097 } | |
1098 | |
1099 int CustomData_get_active_layer(const CustomData *data, int type) | |
1100 { | |
1101 int i; | |
1102 | |
1103 for(i=0; i < data->totlayer; ++i) | |
1104 if(data->layers[i].type == type) | |
1105 return data->layers[i].active; | |
1106 | |
1107 return -1; | |
1108 } | |
1109 | |
1110 int CustomData_get_render_layer(const CustomData *data, int type) | |
1111 { | |
1112 int i; | |
1113 | |
1114 for(i=0; i < data->totlayer; ++i) | |
1115 if(data->layers[i].type == type) | |
1116 return data->layers[i].active_rnd; | |
1117 | |
1118 return -1; | |
1119 } | |
1120 | |
1121 int CustomData_get_clone_layer(const CustomData *data, int type) | |
1122 { | |
1123 int i; | |
1124 | |
1125 for(i=0; i < data->totlayer; ++i) | |
1126 if(data->layers[i].type == type) | |
1127 return data->layers[i].active_clone; | |
1128 | |
1129 return -1; | |
1130 } | |
1131 | |
1132 int CustomData_get_stencil_layer(const CustomData *data, int type) | |
1133 { | |
1134 int i; | |
1135 | |
1136 for(i=0; i < data->totlayer; ++i) | |
1137 if(data->layers[i].type == type) | |
1138 return data->layers[i].active_mask; | |
1139 | |
1140 return -1; | |
1141 } | |
1142 | |
1143 void CustomData_set_layer_active(CustomData *data, int type, int n) | |
1144 { | |
1145 int i; | |
1146 | |
1147 for(i=0; i < data->totlayer; ++i) | |
1148 if(data->layers[i].type == type) | |
1149 data->layers[i].active = n; | |
1150 } | |
1151 | |
1152 void CustomData_set_layer_render(CustomData *data, int type, int n) | |
1153 { | |
1154 int i; | |
1155 | |
1156 for(i=0; i < data->totlayer; ++i) | |
1157 if(data->layers[i].type == type) | |
1158 data->layers[i].active_rnd = n; | |
1159 } | |
1160 | |
1161 void CustomData_set_layer_clone(CustomData *data, int type, int n) | |
1162 { | |
1163 int i; | |
1164 | |
1165 for(i=0; i < data->totlayer; ++i) | |
1166 if(data->layers[i].type == type) | |
1167 data->layers[i].active_clone = n; | |
1168 } | |
1169 | |
1170 void CustomData_set_layer_stencil(CustomData *data, int type, int n) | |
1171 { | |
1172 int i; | |
1173 | |
1174 for(i=0; i < data->totlayer; ++i) | |
1175 if(data->layers[i].type == type) | |
1176 data->layers[i].active_mask = n; | |
1177 } | |
1178 | |
1179 /* for using with an index from CustomData_get_active_layer_index and CustomData
_get_render_layer_index */ | |
1180 void CustomData_set_layer_active_index(CustomData *data, int type, int n) | |
1181 { | |
1182 int i; | |
1183 | |
1184 for(i=0; i < data->totlayer; ++i) | |
1185 if(data->layers[i].type == type) | |
1186 data->layers[i].active = n-i; | |
1187 } | |
1188 | |
1189 void CustomData_set_layer_render_index(CustomData *data, int type, int n) | |
1190 { | |
1191 int i; | |
1192 | |
1193 for(i=0; i < data->totlayer; ++i) | |
1194 if(data->layers[i].type == type) | |
1195 data->layers[i].active_rnd = n-i; | |
1196 } | |
1197 | |
1198 void CustomData_set_layer_clone_index(CustomData *data, int type, int n) | |
1199 { | |
1200 int i; | |
1201 | |
1202 for(i=0; i < data->totlayer; ++i) | |
1203 if(data->layers[i].type == type) | |
1204 data->layers[i].active_clone = n-i; | |
1205 } | |
1206 | |
1207 void CustomData_set_layer_stencil_index(CustomData *data, int type, int n) | |
1208 { | |
1209 int i; | |
1210 | |
1211 for(i=0; i < data->totlayer; ++i) | |
1212 if(data->layers[i].type == type) | |
1213 data->layers[i].active_mask = n-i; | |
1214 } | |
1215 | |
1216 void CustomData_set_layer_flag(struct CustomData *data, int type, int flag) | |
1217 { | |
1218 int i; | |
1219 | |
1220 for(i=0; i < data->totlayer; ++i) | |
1221 if(data->layers[i].type == type) | |
1222 data->layers[i].flag |= flag; | |
1223 } | |
1224 | |
1225 static int customData_resize(CustomData *data, int amount) | |
1226 { | |
1227 CustomDataLayer *tmp = MEM_callocN(sizeof(*tmp)*(data->maxlayer + amount
), | |
1228 "Cust
omData->layers"); | |
1229 if(!tmp) return 0; | |
1230 | |
1231 data->maxlayer += amount; | |
1232 if (data->layers) { | |
1233 memcpy(tmp, data->layers, sizeof(*tmp) * data->totlayer); | |
1234 MEM_freeN(data->layers); | |
1235 } | |
1236 data->layers = tmp; | |
1237 | |
1238 return 1; | |
1239 } | |
1240 | |
1241 static CustomDataLayer *customData_add_layer__internal(CustomData *data, | |
1242 int type, int alloctype, void *layerdata, int totelem, const char *name) | |
1243 { | |
1244 const LayerTypeInfo *typeInfo= layerType_getInfo(type); | |
1245 int size = typeInfo->size * totelem, flag = 0, index = data->totlayer; | |
1246 void *newlayerdata; | |
1247 | |
1248 if (!typeInfo->defaultname && CustomData_has_layer(data, type)) | |
1249 return &data->layers[CustomData_get_layer_index(data, type)]; | |
1250 | |
1251 if((alloctype == CD_ASSIGN) || (alloctype == CD_REFERENCE)) { | |
1252 newlayerdata = layerdata; | |
1253 } | |
1254 else { | |
1255 newlayerdata = MEM_callocN(size, layerType_getName(type)); | |
1256 if(!newlayerdata) | |
1257 return NULL; | |
1258 } | |
1259 | |
1260 if (alloctype == CD_DUPLICATE) { | |
1261 if(typeInfo->copy) | |
1262 typeInfo->copy(layerdata, newlayerdata, totelem); | |
1263 else | |
1264 memcpy(newlayerdata, layerdata, size); | |
1265 } | |
1266 else if (alloctype == CD_DEFAULT) { | |
1267 if(typeInfo->set_default) | |
1268 typeInfo->set_default((char*)newlayerdata, totelem); | |
1269 } | |
1270 else if (alloctype == CD_REFERENCE) | |
1271 flag |= CD_FLAG_NOFREE; | |
1272 | |
1273 if(index >= data->maxlayer) { | |
1274 if(!customData_resize(data, CUSTOMDATA_GROW)) { | |
1275 if(newlayerdata != layerdata) | |
1276 MEM_freeN(newlayerdata); | |
1277 return NULL; | |
1278 } | |
1279 } | |
1280 ········ | |
1281 data->totlayer++; | |
1282 | |
1283 /* keep layers ordered by type */ | |
1284 for( ; index > 0 && data->layers[index - 1].type > type; --index) | |
1285 data->layers[index] = data->layers[index - 1]; | |
1286 | |
1287 data->layers[index].type = type; | |
1288 data->layers[index].flag = flag; | |
1289 data->layers[index].data = newlayerdata; | |
1290 if(name || (name=typeInfo->defaultname)) { | |
1291 BLI_strncpy(data->layers[index].name, name, 32); | |
1292 CustomData_set_layer_unique_name(data, index); | |
1293 } | |
1294 else | |
1295 data->layers[index].name[0] = '\0'; | |
1296 | |
1297 if(index > 0 && data->layers[index-1].type == type) { | |
1298 data->layers[index].active = data->layers[index-1].active; | |
1299 data->layers[index].active_rnd = data->layers[index-1].active_rn
d; | |
1300 data->layers[index].active_clone = data->layers[index-1].active_
clone; | |
1301 data->layers[index].active_mask = data->layers[index-1].active_m
ask; | |
1302 } else { | |
1303 data->layers[index].active = 0; | |
1304 data->layers[index].active_rnd = 0; | |
1305 data->layers[index].active_clone = 0; | |
1306 data->layers[index].active_mask = 0; | |
1307 } | |
1308 ········ | |
1309 customData_update_offsets(data); | |
1310 | |
1311 return &data->layers[index]; | |
1312 } | |
1313 | |
1314 void *CustomData_add_layer(CustomData *data, int type, int alloctype, | |
1315 void *layerdata, int totelem) | |
1316 { | |
1317 CustomDataLayer *layer; | |
1318 const LayerTypeInfo *typeInfo= layerType_getInfo(type); | |
1319 ········ | |
1320 layer = customData_add_layer__internal(data, type, alloctype, layerdata, | |
1321
totelem, typeInfo->defaultname); | |
1322 | |
1323 if(layer) | |
1324 return layer->data; | |
1325 | |
1326 return NULL; | |
1327 } | |
1328 | |
1329 /*same as above but accepts a name*/ | |
1330 void *CustomData_add_layer_named(CustomData *data, int type, int alloctype, | |
1331 void *layerdata, int totelem,
const char *name) | |
1332 { | |
1333 CustomDataLayer *layer; | |
1334 ········ | |
1335 layer = customData_add_layer__internal(data, type, alloctype, layerdata, | |
1336
totelem, name); | |
1337 | |
1338 if(layer) | |
1339 return layer->data; | |
1340 | |
1341 return NULL; | |
1342 } | |
1343 | |
1344 | |
1345 int CustomData_free_layer(CustomData *data, int type, int totelem, int index) | |
1346 { | |
1347 int i; | |
1348 ········ | |
1349 if (index < 0) return 0; | |
1350 | |
1351 customData_free_layer__internal(&data->layers[index], totelem); | |
1352 | |
1353 for (i=index+1; i < data->totlayer; ++i) | |
1354 data->layers[i-1] = data->layers[i]; | |
1355 | |
1356 data->totlayer--; | |
1357 | |
1358 /* if layer was last of type in array, set new active layer */ | |
1359 if ((index >= data->totlayer) || (data->layers[index].type != type)) { | |
1360 i = CustomData_get_layer_index(data, type); | |
1361 ················ | |
1362 if (i >= 0) | |
1363 for (; i < data->totlayer && data->layers[i].type == typ
e; i++) { | |
1364 data->layers[i].active--; | |
1365 data->layers[i].active_rnd--; | |
1366 data->layers[i].active_clone--; | |
1367 data->layers[i].active_mask--; | |
1368 } | |
1369 } | |
1370 | |
1371 if (data->totlayer <= data->maxlayer-CUSTOMDATA_GROW) | |
1372 customData_resize(data, -CUSTOMDATA_GROW); | |
1373 | |
1374 customData_update_offsets(data); | |
1375 | |
1376 return 1; | |
1377 } | |
1378 | |
1379 int CustomData_free_layer_active(CustomData *data, int type, int totelem) | |
1380 { | |
1381 int index = 0; | |
1382 index = CustomData_get_active_layer_index(data, type); | |
1383 if (index < 0) return 0; | |
1384 return CustomData_free_layer(data, type, totelem, index); | |
1385 } | |
1386 | |
1387 | |
1388 void CustomData_free_layers(CustomData *data, int type, int totelem) | |
1389 { | |
1390 while (CustomData_has_layer(data, type)) | |
1391 CustomData_free_layer_active(data, type, totelem); | |
1392 } | |
1393 | |
1394 int CustomData_has_layer(const CustomData *data, int type) | |
1395 { | |
1396 return (CustomData_get_layer_index(data, type) != -1); | |
1397 } | |
1398 | |
1399 int CustomData_number_of_layers(const CustomData *data, int type) | |
1400 { | |
1401 int i, number = 0; | |
1402 | |
1403 for(i = 0; i < data->totlayer; i++) | |
1404 if(data->layers[i].type == type) | |
1405 number++; | |
1406 ········ | |
1407 return number; | |
1408 } | |
1409 | |
1410 void *CustomData_duplicate_referenced_layer(struct CustomData *data, int type) | |
1411 { | |
1412 CustomDataLayer *layer; | |
1413 int layer_index; | |
1414 | |
1415 /* get the layer index of the first layer of type */ | |
1416 layer_index = CustomData_get_active_layer_index(data, type); | |
1417 if(layer_index < 0) return NULL; | |
1418 | |
1419 layer = &data->layers[layer_index]; | |
1420 | |
1421 if (layer->flag & CD_FLAG_NOFREE) { | |
1422 layer->data = MEM_dupallocN(layer->data); | |
1423 layer->flag &= ~CD_FLAG_NOFREE; | |
1424 } | |
1425 | |
1426 return layer->data; | |
1427 } | |
1428 | |
1429 void *CustomData_duplicate_referenced_layer_named(struct CustomData *data, | |
1430
int type, const char *name) | |
1431 { | |
1432 CustomDataLayer *layer; | |
1433 int layer_index; | |
1434 | |
1435 /* get the layer index of the desired layer */ | |
1436 layer_index = CustomData_get_named_layer_index(data, type, name); | |
1437 if(layer_index < 0) return NULL; | |
1438 | |
1439 layer = &data->layers[layer_index]; | |
1440 | |
1441 if (layer->flag & CD_FLAG_NOFREE) { | |
1442 layer->data = MEM_dupallocN(layer->data); | |
1443 layer->flag &= ~CD_FLAG_NOFREE; | |
1444 } | |
1445 | |
1446 return layer->data; | |
1447 } | |
1448 | |
1449 void CustomData_free_temporary(CustomData *data, int totelem) | |
1450 { | |
1451 CustomDataLayer *layer; | |
1452 int i, j; | |
1453 | |
1454 for(i = 0, j = 0; i < data->totlayer; ++i) { | |
1455 layer = &data->layers[i]; | |
1456 | |
1457 if (i != j) | |
1458 data->layers[j] = data->layers[i]; | |
1459 | |
1460 if ((layer->flag & CD_FLAG_TEMPORARY) == CD_FLAG_TEMPORARY) | |
1461 customData_free_layer__internal(layer, totelem); | |
1462 else | |
1463 j++; | |
1464 } | |
1465 | |
1466 data->totlayer = j; | |
1467 | |
1468 if(data->totlayer <= data->maxlayer-CUSTOMDATA_GROW) | |
1469 customData_resize(data, -CUSTOMDATA_GROW); | |
1470 | |
1471 customData_update_offsets(data); | |
1472 } | |
1473 | |
1474 void CustomData_set_only_copy(const struct CustomData *data, | |
1475 CustomDataMask mask) | |
1476 { | |
1477 int i; | |
1478 | |
1479 for(i = 0; i < data->totlayer; ++i) | |
1480 if(!((int)mask & (int)(1 << (int)data->layers[i].type))) | |
1481 data->layers[i].flag |= CD_FLAG_NOCOPY; | |
1482 } | |
1483 | |
1484 void CustomData_copy_data(const CustomData *source, CustomData *dest, | |
1485 int source_index, int dest_ind
ex, int count) | |
1486 { | |
1487 const LayerTypeInfo *typeInfo; | |
1488 int src_i, dest_i; | |
1489 int src_offset; | |
1490 int dest_offset; | |
1491 | |
1492 /* copies a layer at a time */ | |
1493 dest_i = 0; | |
1494 for(src_i = 0; src_i < source->totlayer; ++src_i) { | |
1495 | |
1496 /* find the first dest layer with type >= the source type | |
1497 * (this should work because layers are ordered by type) | |
1498 */ | |
1499 while(dest_i < dest->totlayer | |
1500 && dest->layers[dest_i].type < source->layers[src_i].t
ype) | |
1501 ++dest_i; | |
1502 | |
1503 /* if there are no more dest layers, we're done */ | |
1504 if(dest_i >= dest->totlayer) return; | |
1505 | |
1506 /* if we found a matching layer, copy the data */ | |
1507 if(dest->layers[dest_i].type == source->layers[src_i].type) { | |
1508 char *src_data = source->layers[src_i].data; | |
1509 char *dest_data = dest->layers[dest_i].data; | |
1510 | |
1511 typeInfo = layerType_getInfo(source->layers[src_i].type)
; | |
1512 | |
1513 src_offset = source_index * typeInfo->size; | |
1514 dest_offset = dest_index * typeInfo->size; | |
1515 | |
1516 if(typeInfo->copy) | |
1517 typeInfo->copy(src_data + src_offset, | |
1518 dest_data + dest
_offset, | |
1519 count); | |
1520 else | |
1521 memcpy(dest_data + dest_offset, | |
1522 src_data + src_offset, | |
1523 count * typeInfo->size); | |
1524 | |
1525 /* if there are multiple source & dest layers of the sam
e type, | |
1526 * we don't want to copy all source layers to the same d
est, so | |
1527 * increment dest_i | |
1528 */ | |
1529 ++dest_i; | |
1530 } | |
1531 } | |
1532 } | |
1533 | |
1534 void CustomData_free_elem(CustomData *data, int index, int count) | |
1535 { | |
1536 int i; | |
1537 const LayerTypeInfo *typeInfo; | |
1538 | |
1539 for(i = 0; i < data->totlayer; ++i) { | |
1540 if(!(data->layers[i].flag & CD_FLAG_NOFREE)) { | |
1541 typeInfo = layerType_getInfo(data->layers[i].type); | |
1542 | |
1543 if(typeInfo->free) { | |
1544 int offset = typeInfo->size * index; | |
1545 | |
1546 typeInfo->free((char *)data->layers[i].data + of
fset, | |
1547 count, typeInfo->size
); | |
1548 } | |
1549 } | |
1550 } | |
1551 } | |
1552 | |
1553 #define SOURCE_BUF_SIZE 100 | |
1554 | |
1555 void CustomData_interp(const CustomData *source, CustomData *dest, | |
1556 int *src_indices, float *weights, flo
at *sub_weights, | |
1557 int count, int dest_index) | |
1558 { | |
1559 int src_i, dest_i; | |
1560 int dest_offset; | |
1561 int j; | |
1562 void *source_buf[SOURCE_BUF_SIZE]; | |
1563 void **sources = source_buf; | |
1564 | |
1565 /* slow fallback in case we're interpolating a ridiculous number of | |
1566 * elements | |
1567 */ | |
1568 if(count > SOURCE_BUF_SIZE) | |
1569 sources = MEM_callocN(sizeof(*sources) * count, | |
1570 "CustomData_interp sou
rces"); | |
1571 | |
1572 /* interpolates a layer at a time */ | |
1573 dest_i = 0; | |
1574 for(src_i = 0; src_i < source->totlayer; ++src_i) { | |
1575 const LayerTypeInfo *typeInfo= layerType_getInfo(source->layers[
src_i].type); | |
1576 if(!typeInfo->interp) continue; | |
1577 | |
1578 /* find the first dest layer with type >= the source type | |
1579 * (this should work because layers are ordered by type) | |
1580 */ | |
1581 while(dest_i < dest->totlayer | |
1582 && dest->layers[dest_i].type < source->layers[src_i].t
ype) | |
1583 ++dest_i; | |
1584 | |
1585 /* if there are no more dest layers, we're done */ | |
1586 if(dest_i >= dest->totlayer) return; | |
1587 | |
1588 /* if we found a matching layer, copy the data */ | |
1589 if(dest->layers[dest_i].type == source->layers[src_i].type) { | |
1590 void *src_data = source->layers[src_i].data; | |
1591 | |
1592 for(j = 0; j < count; ++j) | |
1593 sources[j] = (char *)src_data | |
1594 + typeInfo->size * src_
indices[j]; | |
1595 | |
1596 dest_offset = dest_index * typeInfo->size; | |
1597 | |
1598 typeInfo->interp(sources, weights, sub_weights, count, | |
1599 (char *)dest->layers[dest_i].
data + dest_offset); | |
1600 | |
1601 /* if there are multiple source & dest layers of the sam
e type, | |
1602 * we don't want to copy all source layers to the same d
est, so | |
1603 * increment dest_i | |
1604 */ | |
1605 ++dest_i; | |
1606 } | |
1607 } | |
1608 | |
1609 if(count > SOURCE_BUF_SIZE) MEM_freeN(sources); | |
1610 } | |
1611 | |
1612 void CustomData_swap(struct CustomData *data, int index, const int *corner_indic
es) | |
1613 { | |
1614 const LayerTypeInfo *typeInfo; | |
1615 int i; | |
1616 | |
1617 for(i = 0; i < data->totlayer; ++i) { | |
1618 typeInfo = layerType_getInfo(data->layers[i].type); | |
1619 | |
1620 if(typeInfo->swap) { | |
1621 int offset = typeInfo->size * index; | |
1622 | |
1623 typeInfo->swap((char *)data->layers[i].data + offset, co
rner_indices); | |
1624 } | |
1625 } | |
1626 } | |
1627 | |
1628 void *CustomData_get(const CustomData *data, int index, int type) | |
1629 { | |
1630 int offset; | |
1631 int layer_index; | |
1632 ········ | |
1633 /* get the layer index of the active layer of type */ | |
1634 layer_index = CustomData_get_active_layer_index(data, type); | |
1635 if(layer_index < 0) return NULL; | |
1636 | |
1637 /* get the offset of the desired element */ | |
1638 offset = layerType_getInfo(type)->size * index; | |
1639 | |
1640 return (char *)data->layers[layer_index].data + offset; | |
1641 } | |
1642 | |
1643 void *CustomData_get_layer(const CustomData *data, int type) | |
1644 { | |
1645 /* get the layer index of the active layer of type */ | |
1646 int layer_index = CustomData_get_active_layer_index(data, type); | |
1647 if(layer_index < 0) return NULL; | |
1648 | |
1649 return data->layers[layer_index].data; | |
1650 } | |
1651 | |
1652 void *CustomData_get_layer_n(const CustomData *data, int type, int n) | |
1653 { | |
1654 /* get the layer index of the active layer of type */ | |
1655 int layer_index = CustomData_get_layer_index(data, type); | |
1656 if(layer_index < 0) return NULL; | |
1657 | |
1658 return data->layers[layer_index+n].data; | |
1659 } | |
1660 | |
1661 void *CustomData_get_layer_named(const struct CustomData *data, int type, | |
1662 const char *nam
e) | |
1663 { | |
1664 int layer_index = CustomData_get_named_layer_index(data, type, name); | |
1665 if(layer_index < 0) return NULL; | |
1666 | |
1667 return data->layers[layer_index].data; | |
1668 } | |
1669 | |
1670 void *CustomData_set_layer(const CustomData *data, int type, void *ptr) | |
1671 { | |
1672 /* get the layer index of the first layer of type */ | |
1673 int layer_index = CustomData_get_active_layer_index(data, type); | |
1674 | |
1675 if(layer_index < 0) return NULL; | |
1676 | |
1677 data->layers[layer_index].data = ptr; | |
1678 | |
1679 return ptr; | |
1680 } | |
1681 | |
1682 void *CustomData_set_layer_n(const struct CustomData *data, int type, int n, voi
d *ptr) | |
1683 { | |
1684 /* get the layer index of the first layer of type */ | |
1685 int layer_index = CustomData_get_layer_index(data, type); | |
1686 if(layer_index < 0) return NULL; | |
1687 | |
1688 data->layers[layer_index+n].data = ptr; | |
1689 | |
1690 return ptr; | |
1691 } | |
1692 | |
1693 void CustomData_set(const CustomData *data, int index, int type, void *source) | |
1694 { | |
1695 void *dest = CustomData_get(data, index, type); | |
1696 const LayerTypeInfo *typeInfo = layerType_getInfo(type); | |
1697 | |
1698 if(!dest) return; | |
1699 | |
1700 if(typeInfo->copy) | |
1701 typeInfo->copy(source, dest, 1); | |
1702 else | |
1703 memcpy(dest, source, typeInfo->size); | |
1704 } | |
1705 | |
1706 /* EditMesh functions */ | |
1707 | |
1708 void CustomData_em_free_block(CustomData *data, void **block) | |
1709 { | |
1710 const LayerTypeInfo *typeInfo; | |
1711 int i; | |
1712 | |
1713 if(!*block) return; | |
1714 | |
1715 for(i = 0; i < data->totlayer; ++i) { | |
1716 if(!(data->layers[i].flag & CD_FLAG_NOFREE)) { | |
1717 typeInfo = layerType_getInfo(data->layers[i].type); | |
1718 | |
1719 if(typeInfo->free) { | |
1720 int offset = data->layers[i].offset; | |
1721 typeInfo->free((char*)*block + offset, 1, typeIn
fo->size); | |
1722 } | |
1723 } | |
1724 } | |
1725 | |
1726 MEM_freeN(*block); | |
1727 *block = NULL; | |
1728 } | |
1729 | |
1730 static void CustomData_em_alloc_block(CustomData *data, void **block) | |
1731 { | |
1732 /* TODO: optimize free/alloc */ | |
1733 | |
1734 if (*block) | |
1735 CustomData_em_free_block(data, block); | |
1736 | |
1737 if (data->totsize > 0) | |
1738 *block = MEM_callocN(data->totsize, "CustomData EM block"); | |
1739 else | |
1740 *block = NULL; | |
1741 } | |
1742 | |
1743 void CustomData_em_copy_data(const CustomData *source, CustomData *dest, | |
1744 void *src_block, void **
dest_block) | |
1745 { | |
1746 const LayerTypeInfo *typeInfo; | |
1747 int dest_i, src_i; | |
1748 | |
1749 if (!*dest_block) | |
1750 CustomData_em_alloc_block(dest, dest_block); | |
1751 ········ | |
1752 /* copies a layer at a time */ | |
1753 dest_i = 0; | |
1754 for(src_i = 0; src_i < source->totlayer; ++src_i) { | |
1755 | |
1756 /* find the first dest layer with type >= the source type | |
1757 * (this should work because layers are ordered by type) | |
1758 */ | |
1759 while(dest_i < dest->totlayer | |
1760 && dest->layers[dest_i].type < source->layers[src_i].t
ype) | |
1761 ++dest_i; | |
1762 | |
1763 /* if there are no more dest layers, we're done */ | |
1764 if(dest_i >= dest->totlayer) return; | |
1765 | |
1766 /* if we found a matching layer, copy the data */ | |
1767 if(dest->layers[dest_i].type == source->layers[src_i].type && | |
1768 strcmp(dest->layers[dest_i].name, source->layers[src_i].
name) == 0) { | |
1769 char *src_data = (char*)src_block + source->layers[src_i
].offset; | |
1770 char *dest_data = (char*)*dest_block + dest->layers[dest
_i].offset; | |
1771 | |
1772 typeInfo = layerType_getInfo(source->layers[src_i].type)
; | |
1773 | |
1774 if(typeInfo->copy) | |
1775 typeInfo->copy(src_data, dest_data, 1); | |
1776 else | |
1777 memcpy(dest_data, src_data, typeInfo->size); | |
1778 | |
1779 /* if there are multiple source & dest layers of the sam
e type, | |
1780 * we don't want to copy all source layers to the same d
est, so | |
1781 * increment dest_i | |
1782 */ | |
1783 ++dest_i; | |
1784 } | |
1785 } | |
1786 } | |
1787 | |
1788 void CustomData_em_validate_data(CustomData *data, void *block, int sub_elements
) | |
1789 { | |
1790 int i; | |
1791 for(i = 0; i < data->totlayer; i++) { | |
1792 const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[i
].type); | |
1793 char *leayer_data = (char*)block + data->layers[i].offset; | |
1794 | |
1795 if(typeInfo->validate) | |
1796 typeInfo->validate(leayer_data, sub_elements); | |
1797 } | |
1798 } | |
1799 | |
1800 void *CustomData_em_get(const CustomData *data, void *block, int type) | |
1801 { | |
1802 int layer_index; | |
1803 ········ | |
1804 /* get the layer index of the first layer of type */ | |
1805 layer_index = CustomData_get_active_layer_index(data, type); | |
1806 if(layer_index < 0) return NULL; | |
1807 | |
1808 return (char *)block + data->layers[layer_index].offset; | |
1809 } | |
1810 | |
1811 void *CustomData_em_get_n(const CustomData *data, void *block, int type, int n) | |
1812 { | |
1813 int layer_index; | |
1814 ········ | |
1815 /* get the layer index of the first layer of type */ | |
1816 layer_index = CustomData_get_layer_index(data, type); | |
1817 if(layer_index < 0) return NULL; | |
1818 | |
1819 return (char *)block + data->layers[layer_index+n].offset; | |
1820 } | |
1821 | |
1822 void CustomData_em_set(CustomData *data, void *block, int type, void *source) | |
1823 { | |
1824 void *dest = CustomData_em_get(data, block, type); | |
1825 const LayerTypeInfo *typeInfo = layerType_getInfo(type); | |
1826 | |
1827 if(!dest) return; | |
1828 | |
1829 if(typeInfo->copy) | |
1830 typeInfo->copy(source, dest, 1); | |
1831 else | |
1832 memcpy(dest, source, typeInfo->size); | |
1833 } | |
1834 | |
1835 void CustomData_em_set_n(CustomData *data, void *block, int type, int n, void *s
ource) | |
1836 { | |
1837 void *dest = CustomData_em_get_n(data, block, type, n); | |
1838 const LayerTypeInfo *typeInfo = layerType_getInfo(type); | |
1839 | |
1840 if(!dest) return; | |
1841 | |
1842 if(typeInfo->copy) | |
1843 typeInfo->copy(source, dest, 1); | |
1844 else | |
1845 memcpy(dest, source, typeInfo->size); | |
1846 } | |
1847 | |
1848 void CustomData_em_interp(CustomData *data, void **src_blocks, float *weights, | |
1849 float *sub_weights, int count,
void *dest_block) | |
1850 { | |
1851 int i, j; | |
1852 void *source_buf[SOURCE_BUF_SIZE]; | |
1853 void **sources = source_buf; | |
1854 | |
1855 /* slow fallback in case we're interpolating a ridiculous number of | |
1856 * elements | |
1857 */ | |
1858 if(count > SOURCE_BUF_SIZE) | |
1859 sources = MEM_callocN(sizeof(*sources) * count, | |
1860 "CustomData_interp sou
rces"); | |
1861 | |
1862 /* interpolates a layer at a time */ | |
1863 for(i = 0; i < data->totlayer; ++i) { | |
1864 CustomDataLayer *layer = &data->layers[i]; | |
1865 const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type); | |
1866 | |
1867 if(typeInfo->interp) { | |
1868 for(j = 0; j < count; ++j) | |
1869 sources[j] = (char *)src_blocks[j] + layer->offs
et; | |
1870 | |
1871 typeInfo->interp(sources, weights, sub_weights, count, | |
1872 (char *)dest_block + l
ayer->offset); | |
1873 } | |
1874 } | |
1875 | |
1876 if(count > SOURCE_BUF_SIZE) MEM_freeN(sources); | |
1877 } | |
1878 | |
1879 void CustomData_em_set_default(CustomData *data, void **block) | |
1880 { | |
1881 const LayerTypeInfo *typeInfo; | |
1882 int i; | |
1883 | |
1884 if (!*block) | |
1885 CustomData_em_alloc_block(data, block); | |
1886 | |
1887 for(i = 0; i < data->totlayer; ++i) { | |
1888 int offset = data->layers[i].offset; | |
1889 | |
1890 typeInfo = layerType_getInfo(data->layers[i].type); | |
1891 | |
1892 if(typeInfo->set_default) | |
1893 typeInfo->set_default((char*)*block + offset, 1); | |
1894 } | |
1895 } | |
1896 | |
1897 void CustomData_to_em_block(const CustomData *source, CustomData *dest, | |
1898 int src_index, void **de
st_block) | |
1899 { | |
1900 const LayerTypeInfo *typeInfo; | |
1901 int dest_i, src_i, src_offset; | |
1902 | |
1903 if (!*dest_block) | |
1904 CustomData_em_alloc_block(dest, dest_block); | |
1905 ········ | |
1906 /* copies a layer at a time */ | |
1907 dest_i = 0; | |
1908 for(src_i = 0; src_i < source->totlayer; ++src_i) { | |
1909 | |
1910 /* find the first dest layer with type >= the source type | |
1911 * (this should work because layers are ordered by type) | |
1912 */ | |
1913 while(dest_i < dest->totlayer | |
1914 && dest->layers[dest_i].type < source->layers[src_i].t
ype) | |
1915 ++dest_i; | |
1916 | |
1917 /* if there are no more dest layers, we're done */ | |
1918 if(dest_i >= dest->totlayer) return; | |
1919 | |
1920 /* if we found a matching layer, copy the data */ | |
1921 if(dest->layers[dest_i].type == source->layers[src_i].type) { | |
1922 int offset = dest->layers[dest_i].offset; | |
1923 char *src_data = source->layers[src_i].data; | |
1924 char *dest_data = (char*)*dest_block + offset; | |
1925 | |
1926 typeInfo = layerType_getInfo(dest->layers[dest_i].type); | |
1927 src_offset = src_index * typeInfo->size; | |
1928 | |
1929 if(typeInfo->copy) | |
1930 typeInfo->copy(src_data + src_offset, dest_data,
1); | |
1931 else | |
1932 memcpy(dest_data, src_data + src_offset, typeInf
o->size); | |
1933 | |
1934 /* if there are multiple source & dest layers of the sam
e type, | |
1935 * we don't want to copy all source layers to the same d
est, so | |
1936 * increment dest_i | |
1937 */ | |
1938 ++dest_i; | |
1939 } | |
1940 } | |
1941 } | |
1942 | |
1943 void CustomData_from_em_block(const CustomData *source, CustomData *dest, | |
1944 void *src_block, int d
est_index) | |
1945 { | |
1946 const LayerTypeInfo *typeInfo; | |
1947 int dest_i, src_i, dest_offset; | |
1948 | |
1949 /* copies a layer at a time */ | |
1950 dest_i = 0; | |
1951 for(src_i = 0; src_i < source->totlayer; ++src_i) { | |
1952 | |
1953 /* find the first dest layer with type >= the source type | |
1954 * (this should work because layers are ordered by type) | |
1955 */ | |
1956 while(dest_i < dest->totlayer | |
1957 && dest->layers[dest_i].type < source->layers[src_i].t
ype) | |
1958 ++dest_i; | |
1959 | |
1960 /* if there are no more dest layers, we're done */ | |
1961 if(dest_i >= dest->totlayer) return; | |
1962 | |
1963 /* if we found a matching layer, copy the data */ | |
1964 if(dest->layers[dest_i].type == source->layers[src_i].type) { | |
1965 int offset = source->layers[src_i].offset; | |
1966 char *src_data = (char*)src_block + offset; | |
1967 char *dest_data = dest->layers[dest_i].data; | |
1968 | |
1969 typeInfo = layerType_getInfo(dest->layers[dest_i].type); | |
1970 dest_offset = dest_index * typeInfo->size; | |
1971 | |
1972 if(typeInfo->copy) | |
1973 typeInfo->copy(src_data, dest_data + dest_offset
, 1); | |
1974 else | |
1975 memcpy(dest_data + dest_offset, src_data, typeIn
fo->size); | |
1976 | |
1977 /* if there are multiple source & dest layers of the sam
e type, | |
1978 * we don't want to copy all source layers to the same d
est, so | |
1979 * increment dest_i | |
1980 */ | |
1981 ++dest_i; | |
1982 } | |
1983 } | |
1984 | |
1985 } | |
1986 | |
1987 /*Bmesh functions*/ | |
1988 /*needed to convert to/from different face reps*/ | |
1989 void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *l
data) | |
1990 { | |
1991 int i; | |
1992 for(i=0; i < fdata->totlayer; i++){ | |
1993 if(fdata->layers[i].type == CD_MTFACE){ | |
1994 CustomData_add_layer(pdata, CD_MTEXPOLY, CD_CALLOC, &(fd
ata->layers[i].name), 0); | |
1995 CustomData_add_layer(ldata, CD_MLOOPUV, CD_CALLOC, &(fda
ta->layers[i].name), 0); | |
1996 } | |
1997 else if(fdata->layers[i].type == CD_MCOL) | |
1998 CustomData_add_layer(ldata, CD_MLOOPCOL, CD_CALLOC, &(fd
ata->layers[i].name), 0); | |
1999 }··············· | |
2000 } | |
2001 void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData
*ldata, int total){ | |
2002 int i; | |
2003 for(i=0; i < pdata->totlayer; i++){ | |
2004 if(pdata->layers[i].type == CD_MTEXPOLY) | |
2005 CustomData_add_layer(fdata, CD_MTFACE, CD_CALLOC, &(pdat
a->layers[i].name), total); | |
2006 } | |
2007 for(i=0; i < ldata->totlayer; i++){ | |
2008 if(ldata->layers[i].type == CD_MLOOPCOL) | |
2009 CustomData_add_layer(fdata, CD_MCOL, CD_CALLOC, &(ldata-
>layers[i].name), total); | |
2010 } | |
2011 } | |
2012 | |
2013 | |
2014 void CustomData_bmesh_init_pool(CustomData *data, int allocsize){ | |
2015 if(data->totlayer)data->pool = BLI_mempool_create(data->totsize, allocsi
ze, allocsize, 0); | |
2016 } | |
2017 | |
2018 void CustomData_bmesh_free_block(CustomData *data, void **block) | |
2019 { | |
2020 const LayerTypeInfo *typeInfo; | |
2021 int i; | |
2022 | |
2023 if(!*block) return; | |
2024 for(i = 0; i < data->totlayer; ++i) { | |
2025 if(!(data->layers[i].flag & CD_FLAG_NOFREE)) { | |
2026 typeInfo = layerType_getInfo(data->layers[i].type); | |
2027 | |
2028 if(typeInfo->free) { | |
2029 int offset = data->layers[i].offset; | |
2030 typeInfo->free((char*)*block + offset, 1, typeIn
fo->size); | |
2031 } | |
2032 } | |
2033 } | |
2034 | |
2035 BLI_mempool_free(data->pool, *block); | |
2036 *block = NULL; | |
2037 } | |
2038 | |
2039 static void CustomData_bmesh_alloc_block(CustomData *data, void **block) | |
2040 { | |
2041 | |
2042 if (*block) | |
2043 CustomData_bmesh_free_block(data, block); | |
2044 | |
2045 if (data->totsize > 0) | |
2046 *block = BLI_mempool_calloc(data->pool); | |
2047 else | |
2048 *block = NULL; | |
2049 } | |
2050 | |
2051 void CustomData_bmesh_copy_data(const CustomData *source, CustomData *dest, | |
2052 void *src_block, void **
dest_block) | |
2053 { | |
2054 const LayerTypeInfo *typeInfo; | |
2055 int dest_i, src_i; | |
2056 | |
2057 if (!*dest_block) | |
2058 CustomData_bmesh_alloc_block(dest, dest_block); | |
2059 ········ | |
2060 /* copies a layer at a time */ | |
2061 dest_i = 0; | |
2062 for(src_i = 0; src_i < source->totlayer; ++src_i) { | |
2063 | |
2064 /* find the first dest layer with type >= the source type | |
2065 * (this should work because layers are ordered by type) | |
2066 */ | |
2067 while(dest_i < dest->totlayer | |
2068 && dest->layers[dest_i].type < source->layers[src_i].t
ype) | |
2069 ++dest_i; | |
2070 | |
2071 /* if there are no more dest layers, we're done */ | |
2072 if(dest_i >= dest->totlayer) return; | |
2073 | |
2074 /* if we found a matching layer, copy the data */ | |
2075 if(dest->layers[dest_i].type == source->layers[src_i].type && | |
2076 strcmp(dest->layers[dest_i].name, source->layers[src_i].
name) == 0) { | |
2077 char *src_data = (char*)src_block + source->layers[src_i
].offset; | |
2078 char *dest_data = (char*)*dest_block + dest->layers[dest
_i].offset; | |
2079 | |
2080 typeInfo = layerType_getInfo(source->layers[src_i].type)
; | |
2081 | |
2082 if(typeInfo->copy) | |
2083 typeInfo->copy(src_data, dest_data, 1); | |
2084 else | |
2085 memcpy(dest_data, src_data, typeInfo->size); | |
2086 | |
2087 /* if there are multiple source & dest layers of the sam
e type, | |
2088 * we don't want to copy all source layers to the same d
est, so | |
2089 * increment dest_i | |
2090 */ | |
2091 ++dest_i; | |
2092 } | |
2093 } | |
2094 } | |
2095 | |
2096 /*Bmesh Custom Data Functions. Should replace editmesh ones with these as well,
due to more effecient memory alloc*/ | |
2097 void *CustomData_bmesh_get(const CustomData *data, void *block, int type) | |
2098 { | |
2099 int layer_index; | |
2100 ········ | |
2101 /* get the layer index of the first layer of type */ | |
2102 layer_index = CustomData_get_active_layer_index(data, type); | |
2103 if(layer_index < 0) return NULL; | |
2104 | |
2105 return (char *)block + data->layers[layer_index].offset; | |
2106 } | |
2107 | |
2108 void *CustomData_bmesh_get_n(const CustomData *data, void *block, int type, int
n) | |
2109 { | |
2110 int layer_index; | |
2111 ········ | |
2112 /* get the layer index of the first layer of type */ | |
2113 layer_index = CustomData_get_layer_index(data, type); | |
2114 if(layer_index < 0) return NULL; | |
2115 | |
2116 return (char *)block + data->layers[layer_index+n].offset; | |
2117 } | |
2118 | |
2119 void CustomData_bmesh_set(const CustomData *data, void *block, int type, void *s
ource) | |
2120 { | |
2121 void *dest = CustomData_bmesh_get(data, block, type); | |
2122 const LayerTypeInfo *typeInfo = layerType_getInfo(type); | |
2123 | |
2124 if(!dest) return; | |
2125 | |
2126 if(typeInfo->copy) | |
2127 typeInfo->copy(source, dest, 1); | |
2128 else | |
2129 memcpy(dest, source, typeInfo->size); | |
2130 } | |
2131 | |
2132 void CustomData_bmesh_set_n(CustomData *data, void *block, int type, int n, void
*source) | |
2133 { | |
2134 void *dest = CustomData_bmesh_get_n(data, block, type, n); | |
2135 const LayerTypeInfo *typeInfo = layerType_getInfo(type); | |
2136 | |
2137 if(!dest) return; | |
2138 | |
2139 if(typeInfo->copy) | |
2140 typeInfo->copy(source, dest, 1); | |
2141 else | |
2142 memcpy(dest, source, typeInfo->size); | |
2143 } | |
2144 | |
2145 void CustomData_bmesh_interp(CustomData *data, void **src_blocks, float *weights
, | |
2146 float *sub_weights, int count,
void *dest_block) | |
2147 { | |
2148 int i, j; | |
2149 void *source_buf[SOURCE_BUF_SIZE]; | |
2150 void **sources = source_buf; | |
2151 | |
2152 /* slow fallback in case we're interpolating a ridiculous number of | |
2153 * elements | |
2154 */ | |
2155 if(count > SOURCE_BUF_SIZE) | |
2156 sources = MEM_callocN(sizeof(*sources) * count, | |
2157 "CustomData_interp sou
rces"); | |
2158 | |
2159 /* interpolates a layer at a time */ | |
2160 for(i = 0; i < data->totlayer; ++i) { | |
2161 CustomDataLayer *layer = &data->layers[i]; | |
2162 const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type); | |
2163 if(typeInfo->interp) { | |
2164 for(j = 0; j < count; ++j) | |
2165 sources[j] = (char *)src_blocks[j] + layer->offs
et; | |
2166 | |
2167 typeInfo->interp(sources, weights, sub_weights, count, | |
2168 (char *)dest_block + l
ayer->offset); | |
2169 } | |
2170 } | |
2171 | |
2172 if(count > SOURCE_BUF_SIZE) MEM_freeN(sources); | |
2173 } | |
2174 | |
2175 void CustomData_bmesh_set_default(CustomData *data, void **block) | |
2176 { | |
2177 const LayerTypeInfo *typeInfo; | |
2178 int i; | |
2179 | |
2180 if (!*block) | |
2181 CustomData_bmesh_alloc_block(data, block); | |
2182 | |
2183 for(i = 0; i < data->totlayer; ++i) { | |
2184 int offset = data->layers[i].offset; | |
2185 | |
2186 typeInfo = layerType_getInfo(data->layers[i].type); | |
2187 | |
2188 if(typeInfo->set_default) | |
2189 typeInfo->set_default((char*)*block + offset, 1); | |
2190 } | |
2191 } | |
2192 | |
2193 void CustomData_to_bmesh_block(const CustomData *source, CustomData *dest, | |
2194 int src_index, void **de
st_block) | |
2195 { | |
2196 const LayerTypeInfo *typeInfo; | |
2197 int dest_i, src_i, src_offset; | |
2198 | |
2199 if (!*dest_block) | |
2200 CustomData_bmesh_alloc_block(dest, dest_block); | |
2201 ········ | |
2202 /* copies a layer at a time */ | |
2203 dest_i = 0; | |
2204 for(src_i = 0; src_i < source->totlayer; ++src_i) { | |
2205 | |
2206 /* find the first dest layer with type >= the source type | |
2207 * (this should work because layers are ordered by type) | |
2208 */ | |
2209 while(dest_i < dest->totlayer | |
2210 && dest->layers[dest_i].type < source->layers[src_i].t
ype) | |
2211 ++dest_i; | |
2212 | |
2213 /* if there are no more dest layers, we're done */ | |
2214 if(dest_i >= dest->totlayer) return; | |
2215 | |
2216 /* if we found a matching layer, copy the data */ | |
2217 if(dest->layers[dest_i].type == source->layers[src_i].type) { | |
2218 int offset = dest->layers[dest_i].offset; | |
2219 char *src_data = source->layers[src_i].data; | |
2220 char *dest_data = (char*)*dest_block + offset; | |
2221 | |
2222 typeInfo = layerType_getInfo(dest->layers[dest_i].type); | |
2223 src_offset = src_index * typeInfo->size; | |
2224 | |
2225 if(typeInfo->copy) | |
2226 typeInfo->copy(src_data + src_offset, dest_data,
1); | |
2227 else | |
2228 memcpy(dest_data, src_data + src_offset, typeInf
o->size); | |
2229 | |
2230 /* if there are multiple source & dest layers of the sam
e type, | |
2231 * we don't want to copy all source layers to the same d
est, so | |
2232 * increment dest_i | |
2233 */ | |
2234 ++dest_i; | |
2235 } | |
2236 } | |
2237 } | |
2238 | |
2239 void CustomData_from_bmesh_block(const CustomData *source, CustomData *dest, | |
2240 void *src_block, int d
est_index) | |
2241 { | |
2242 const LayerTypeInfo *typeInfo; | |
2243 int dest_i, src_i, dest_offset; | |
2244 | |
2245 /* copies a layer at a time */ | |
2246 dest_i = 0; | |
2247 for(src_i = 0; src_i < source->totlayer; ++src_i) { | |
2248 | |
2249 /* find the first dest layer with type >= the source type | |
2250 * (this should work because layers are ordered by type) | |
2251 */ | |
2252 while(dest_i < dest->totlayer | |
2253 && dest->layers[dest_i].type < source->layers[src_i].t
ype) | |
2254 ++dest_i; | |
2255 | |
2256 /* if there are no more dest layers, we're done */ | |
2257 if(dest_i >= dest->totlayer) return; | |
2258 | |
2259 /* if we found a matching layer, copy the data */ | |
2260 if(dest->layers[dest_i].type == source->layers[src_i].type) { | |
2261 int offset = source->layers[src_i].offset; | |
2262 char *src_data = (char*)src_block + offset; | |
2263 char *dest_data = dest->layers[dest_i].data; | |
2264 | |
2265 typeInfo = layerType_getInfo(dest->layers[dest_i].type); | |
2266 dest_offset = dest_index * typeInfo->size; | |
2267 | |
2268 if(typeInfo->copy) | |
2269 typeInfo->copy(src_data, dest_data + dest_offset
, 1); | |
2270 else | |
2271 memcpy(dest_data + dest_offset, src_data, typeIn
fo->size); | |
2272 | |
2273 /* if there are multiple source & dest layers of the sam
e type, | |
2274 * we don't want to copy all source layers to the same d
est, so | |
2275 * increment dest_i | |
2276 */ | |
2277 ++dest_i; | |
2278 } | |
2279 } | |
2280 | |
2281 } | |
2282 | |
2283 void CustomData_file_write_info(int type, const char **structname, int *structnu
m) | |
2284 { | |
2285 const LayerTypeInfo *typeInfo = layerType_getInfo(type); | |
2286 | |
2287 *structname = typeInfo->structname; | |
2288 *structnum = typeInfo->structnum; | |
2289 } | |
2290 | |
2291 int CustomData_sizeof(int type) | |
2292 { | |
2293 const LayerTypeInfo *typeInfo = layerType_getInfo(type); | |
2294 | |
2295 return typeInfo->size; | |
2296 } | |
2297 | |
2298 const char *CustomData_layertype_name(int type) | |
2299 { | |
2300 return layerType_getName(type); | |
2301 } | |
2302 | |
2303 static int CustomData_is_property_layer(int type) | |
2304 { | |
2305 if((type == CD_PROP_FLT) || (type == CD_PROP_INT) || (type == CD_PROP_ST
R)) | |
2306 return 1; | |
2307 return 0; | |
2308 } | |
2309 | |
2310 static int cd_layer_find_dupe(CustomData *data, const char *name, int type, int
index) | |
2311 { | |
2312 int i; | |
2313 /* see if there is a duplicate */ | |
2314 for(i=0; i<data->totlayer; i++) { | |
2315 if(i != index) { | |
2316 CustomDataLayer *layer= &data->layers[i]; | |
2317 ························ | |
2318 if(CustomData_is_property_layer(type)) { | |
2319 if(CustomData_is_property_layer(layer->type) &&
strcmp(layer->name, name)==0) { | |
2320 return 1; | |
2321 } | |
2322 } | |
2323 else{ | |
2324 if(i!=index && layer->type==type && strcmp(layer
->name, name)==0) { | |
2325 return 1; | |
2326 } | |
2327 } | |
2328 } | |
2329 } | |
2330 ········ | |
2331 return 0; | |
2332 } | |
2333 | |
2334 static int customdata_unique_check(void *arg, const char *name) | |
2335 { | |
2336 struct {CustomData *data; int type; int index;} *data_arg= arg; | |
2337 return cd_layer_find_dupe(data_arg->data, name, data_arg->type, data_arg
->index); | |
2338 } | |
2339 | |
2340 void CustomData_set_layer_unique_name(CustomData *data, int index) | |
2341 {······· | |
2342 CustomDataLayer *nlayer= &data->layers[index]; | |
2343 const LayerTypeInfo *typeInfo= layerType_getInfo(nlayer->type); | |
2344 | |
2345 struct {CustomData *data; int type; int index;} data_arg; | |
2346 data_arg.data= data; | |
2347 data_arg.type= nlayer->type; | |
2348 data_arg.index= index; | |
2349 | |
2350 if (!typeInfo->defaultname) | |
2351 return; | |
2352 ········ | |
2353 BLI_uniquename_cb(customdata_unique_check, &data_arg, typeInfo->defaultn
ame, '.', nlayer->name, sizeof(nlayer->name)); | |
2354 } | |
2355 | |
2356 int CustomData_verify_versions(struct CustomData *data, int index) | |
2357 { | |
2358 const LayerTypeInfo *typeInfo; | |
2359 CustomDataLayer *layer = &data->layers[index]; | |
2360 int i, keeplayer = 1; | |
2361 | |
2362 if (layer->type >= CD_NUMTYPES) { | |
2363 keeplayer = 0; /* unknown layer type from future version */ | |
2364 } | |
2365 else { | |
2366 typeInfo = layerType_getInfo(layer->type); | |
2367 | |
2368 if (!typeInfo->defaultname && (index > 0) && | |
2369 data->layers[index-1].type == layer->type) | |
2370 keeplayer = 0; /* multiple layers of which we only suppo
rt one */ | |
2371 } | |
2372 | |
2373 if (!keeplayer) { | |
2374 for (i=index+1; i < data->totlayer; ++i) | |
2375 data->layers[i-1] = data->layers[i]; | |
2376 data->totlayer--; | |
2377 } | |
2378 | |
2379 return keeplayer; | |
2380 } | |
2381 | |
2382 /****************************** External Files *******************************/ | |
2383 | |
2384 static void customdata_external_filename(char filename[FILE_MAX], ID *id, Custom
DataExternal *external) | |
2385 { | |
2386 char *path = (id->lib)? id->lib->filepath: G.main->name; | |
2387 | |
2388 BLI_strncpy(filename, external->filename, FILE_MAX); | |
2389 BLI_path_abs(filename, path); | |
2390 } | |
2391 | |
2392 void CustomData_external_reload(CustomData *data, ID *UNUSED(id), CustomDataMask
mask, int totelem) | |
2393 { | |
2394 CustomDataLayer *layer; | |
2395 const LayerTypeInfo *typeInfo; | |
2396 int i; | |
2397 | |
2398 for(i=0; i<data->totlayer; i++) { | |
2399 layer = &data->layers[i]; | |
2400 typeInfo = layerType_getInfo(layer->type); | |
2401 | |
2402 if(!(mask & (1<<layer->type))); | |
2403 else if((layer->flag & CD_FLAG_EXTERNAL) && (layer->flag & CD_FL
AG_IN_MEMORY)) { | |
2404 if(typeInfo->free) | |
2405 typeInfo->free(layer->data, totelem, typeInfo->s
ize); | |
2406 layer->flag &= ~CD_FLAG_IN_MEMORY; | |
2407 } | |
2408 } | |
2409 } | |
2410 | |
2411 void CustomData_external_read(CustomData *data, ID *id, CustomDataMask mask, int
totelem) | |
2412 { | |
2413 CustomDataExternal *external= data->external; | |
2414 CustomDataLayer *layer; | |
2415 CDataFile *cdf; | |
2416 CDataFileLayer *blay; | |
2417 char filename[FILE_MAX]; | |
2418 const LayerTypeInfo *typeInfo; | |
2419 int i, update = 0; | |
2420 | |
2421 if(!external) | |
2422 return; | |
2423 ········ | |
2424 for(i=0; i<data->totlayer; i++) { | |
2425 layer = &data->layers[i]; | |
2426 typeInfo = layerType_getInfo(layer->type); | |
2427 | |
2428 if(!(mask & (1<<layer->type))); | |
2429 else if(layer->flag & CD_FLAG_IN_MEMORY); | |
2430 else if((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->read) | |
2431 update= 1; | |
2432 } | |
2433 | |
2434 if(!update) | |
2435 return; | |
2436 | |
2437 customdata_external_filename(filename, id, external); | |
2438 | |
2439 cdf= cdf_create(CDF_TYPE_MESH); | |
2440 if(!cdf_read_open(cdf, filename)) { | |
2441 fprintf(stderr, "Failed to read %s layer from %s.\n", layerType_
getName(layer->type), filename); | |
2442 return; | |
2443 } | |
2444 | |
2445 for(i=0; i<data->totlayer; i++) { | |
2446 layer = &data->layers[i]; | |
2447 typeInfo = layerType_getInfo(layer->type); | |
2448 | |
2449 if(!(mask & (1<<layer->type))); | |
2450 else if(layer->flag & CD_FLAG_IN_MEMORY); | |
2451 else if((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->read) { | |
2452 blay= cdf_layer_find(cdf, layer->type, layer->name); | |
2453 | |
2454 if(blay) { | |
2455 if(cdf_read_layer(cdf, blay)) { | |
2456 if(typeInfo->read(cdf, layer->data, tote
lem)); | |
2457 else break; | |
2458 layer->flag |= CD_FLAG_IN_MEMORY; | |
2459 } | |
2460 else | |
2461 break; | |
2462 } | |
2463 } | |
2464 } | |
2465 | |
2466 cdf_read_close(cdf); | |
2467 cdf_free(cdf); | |
2468 } | |
2469 | |
2470 void CustomData_external_write(CustomData *data, ID *id, CustomDataMask mask, in
t totelem, int free) | |
2471 { | |
2472 CustomDataExternal *external= data->external; | |
2473 CustomDataLayer *layer; | |
2474 CDataFile *cdf; | |
2475 CDataFileLayer *blay; | |
2476 const LayerTypeInfo *typeInfo; | |
2477 int i, update = 0; | |
2478 char filename[FILE_MAX]; | |
2479 | |
2480 if(!external) | |
2481 return; | |
2482 | |
2483 /* test if there is anything to write */ | |
2484 for(i=0; i<data->totlayer; i++) { | |
2485 layer = &data->layers[i]; | |
2486 typeInfo = layerType_getInfo(layer->type); | |
2487 | |
2488 if(!(mask & (1<<layer->type))); | |
2489 else if((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write) | |
2490 update= 1; | |
2491 } | |
2492 | |
2493 if(!update) | |
2494 return; | |
2495 | |
2496 /* make sure data is read before we try to write */ | |
2497 CustomData_external_read(data, id, mask, totelem); | |
2498 customdata_external_filename(filename, id, external); | |
2499 | |
2500 cdf= cdf_create(CDF_TYPE_MESH); | |
2501 | |
2502 for(i=0; i<data->totlayer; i++) { | |
2503 layer = &data->layers[i]; | |
2504 typeInfo = layerType_getInfo(layer->type); | |
2505 | |
2506 if((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->filesize) { | |
2507 if(layer->flag & CD_FLAG_IN_MEMORY) { | |
2508 cdf_layer_add(cdf, layer->type, layer->name, | |
2509 typeInfo->filesize(cdf, layer->data, tot
elem)); | |
2510 } | |
2511 else { | |
2512 cdf_free(cdf); | |
2513 return; /* read failed for a layer! */ | |
2514 } | |
2515 } | |
2516 } | |
2517 | |
2518 if(!cdf_write_open(cdf, filename)) { | |
2519 fprintf(stderr, "Failed to open %s for writing.\n", filename); | |
2520 return; | |
2521 } | |
2522 | |
2523 for(i=0; i<data->totlayer; i++) { | |
2524 layer = &data->layers[i]; | |
2525 typeInfo = layerType_getInfo(layer->type); | |
2526 | |
2527 if((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write) { | |
2528 blay= cdf_layer_find(cdf, layer->type, layer->name); | |
2529 | |
2530 if(cdf_write_layer(cdf, blay)) { | |
2531 if(typeInfo->write(cdf, layer->data, totelem)); | |
2532 else break; | |
2533 } | |
2534 else | |
2535 break; | |
2536 } | |
2537 } | |
2538 | |
2539 if(i != data->totlayer) { | |
2540 fprintf(stderr, "Failed to write data to %s.\n", filename); | |
2541 cdf_free(cdf); | |
2542 return; | |
2543 } | |
2544 | |
2545 for(i=0; i<data->totlayer; i++) { | |
2546 layer = &data->layers[i]; | |
2547 typeInfo = layerType_getInfo(layer->type); | |
2548 | |
2549 if((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write) { | |
2550 if(free) { | |
2551 if(typeInfo->free) | |
2552 typeInfo->free(layer->data, totelem, typ
eInfo->size); | |
2553 layer->flag &= ~CD_FLAG_IN_MEMORY; | |
2554 } | |
2555 } | |
2556 } | |
2557 | |
2558 cdf_write_close(cdf); | |
2559 cdf_free(cdf); | |
2560 } | |
2561 | |
2562 void CustomData_external_add(CustomData *data, ID *UNUSED(id), int type, int UNU
SED(totelem), const char *filename) | |
2563 { | |
2564 CustomDataExternal *external= data->external; | |
2565 CustomDataLayer *layer; | |
2566 int layer_index; | |
2567 | |
2568 layer_index = CustomData_get_active_layer_index(data, type); | |
2569 if(layer_index < 0) return; | |
2570 | |
2571 layer = &data->layers[layer_index]; | |
2572 | |
2573 if(layer->flag & CD_FLAG_EXTERNAL) | |
2574 return; | |
2575 | |
2576 if(!external) { | |
2577 external= MEM_callocN(sizeof(CustomDataExternal), "CustomDataExt
ernal"); | |
2578 data->external= external; | |
2579 } | |
2580 BLI_strncpy(external->filename, filename, sizeof(external->filename)); | |
2581 | |
2582 layer->flag |= CD_FLAG_EXTERNAL|CD_FLAG_IN_MEMORY; | |
2583 } | |
2584 | |
2585 void CustomData_external_remove(CustomData *data, ID *id, int type, int totelem) | |
2586 { | |
2587 CustomDataExternal *external= data->external; | |
2588 CustomDataLayer *layer; | |
2589 //char filename[FILE_MAX]; | |
2590 int layer_index; // i, remove_file; | |
2591 | |
2592 layer_index = CustomData_get_active_layer_index(data, type); | |
2593 if(layer_index < 0) return; | |
2594 | |
2595 layer = &data->layers[layer_index]; | |
2596 | |
2597 if(!external) | |
2598 return; | |
2599 | |
2600 if(layer->flag & CD_FLAG_EXTERNAL) { | |
2601 if(!(layer->flag & CD_FLAG_IN_MEMORY)) | |
2602 CustomData_external_read(data, id, (1<<layer->type), tot
elem); | |
2603 | |
2604 layer->flag &= ~CD_FLAG_EXTERNAL; | |
2605 | |
2606 #if 0 | |
2607 remove_file= 1; | |
2608 for(i=0; i<data->totlayer; i++) | |
2609 if(data->layers[i].flag & CD_FLAG_EXTERNAL) | |
2610 remove_file= 0; | |
2611 | |
2612 if(remove_file) { | |
2613 customdata_external_filename(filename, id, external); | |
2614 cdf_remove(filename); | |
2615 CustomData_external_free(data); | |
2616 } | |
2617 #endif | |
2618 } | |
2619 } | |
2620 | |
2621 int CustomData_external_test(CustomData *data, int type) | |
2622 { | |
2623 CustomDataLayer *layer; | |
2624 int layer_index; | |
2625 | |
2626 layer_index = CustomData_get_active_layer_index(data, type); | |
2627 if(layer_index < 0) return 0; | |
2628 | |
2629 layer = &data->layers[layer_index]; | |
2630 return (layer->flag & CD_FLAG_EXTERNAL); | |
2631 } | |
2632 | |
2633 #if 0 | |
2634 void CustomData_external_remove_object(CustomData *data, ID *id) | |
2635 { | |
2636 CustomDataExternal *external= data->external; | |
2637 char filename[FILE_MAX]; | |
2638 | |
2639 if(!external) | |
2640 return; | |
2641 | |
2642 customdata_external_filename(filename, id, external); | |
2643 cdf_remove(filename); | |
2644 CustomData_external_free(data); | |
2645 } | |
2646 #endif | |
2647 | |
LEFT | RIGHT |