Cycles: svn merge -r39870:r40266 https://svn.blender.org/svnroot/bf-blender/trunk...
[blender-staging.git] / source / blender / blenkernel / intern / BME_Customdata.c
1 /*
2  * BME_customdata.c    jan 2007
3  *
4  *      Custom Data functions for Bmesh
5  *
6  * $Id$
7  *
8  * ***** BEGIN GPL LICENSE BLOCK *****
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version. The Blender
14  * Foundation also sells licenses for use in proprietary software under
15  * the Blender License.  See http://www.blender.org/BL/ for information
16  * about this.  
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * The Original Code is Copyright (C) 2004 Blender Foundation.
28  * All rights reserved.
29  *
30  * The Original Code is: all of this file.
31  *
32  * Contributor(s): Geoffrey Bantle, Brecht Van Lommel, Ben Batt
33  *
34  * ***** END GPL LICENSE BLOCK *****
35  */
36
37 /** \file blender/blenkernel/intern/BME_Customdata.c
38  *  \ingroup bke
39  */
40
41
42 #include <string.h>
43
44 #include "MEM_guardedalloc.h"
45 #include "BKE_bmeshCustomData.h"
46 #include "bmesh_private.h"
47
48 /********************* Layer type information **********************/
49 typedef struct BME_LayerTypeInfo {
50         int size;
51         const char *defaultname;
52         void (*copy)(const void *source, void *dest, int count);
53         void (*free)(void *data, int count, int size);
54         void (*interp)(void **sources, float *weights, float *sub_weights, int count, void *dest);
55         void (*set_default)(void *data, int count);
56 } BME_LayerTypeInfo;
57 const BME_LayerTypeInfo BMELAYERTYPEINFO[BME_CD_NUMTYPES] = {
58         {sizeof(BME_facetex), "TexFace", NULL, NULL, NULL, NULL},
59         {sizeof(BME_looptex), "UV", NULL, NULL, NULL, NULL},
60         {sizeof(BME_loopcol), "VCol", NULL, NULL, NULL, NULL},
61         {sizeof(BME_DeformVert), "Group", NULL, NULL, NULL, NULL}
62 };
63 static const BME_LayerTypeInfo *BME_layerType_getInfo(int type)
64 {
65         if(type < 0 || type >= CD_NUMTYPES) return NULL;
66
67         return &BMELAYERTYPEINFO[type];
68 }
69 void BME_CD_Create(BME_CustomData *data, BME_CustomDataInit *init, int initalloc)
70 {
71         int i, j, offset=0;
72         const BME_LayerTypeInfo *info;
73         
74         /*initialize data members*/
75         data->layers = NULL;
76         data->pool = NULL;
77         data->totlayer = 0;
78         data->totsize = 0;
79
80         /*first count how many layers to alloc*/
81         for(i=0; i < BME_CD_NUMTYPES; i++){
82                 info = BME_layerType_getInfo(i);
83                 data->totlayer += init->layout[i];
84                 data->totsize  += (init->layout[i] * info->size);
85         }
86         /*alloc our layers*/
87         if(data->totlayer){
88                 /*alloc memory*/
89                 data->layers = MEM_callocN(sizeof(BME_CustomDataLayer)*data->totlayer, "BMesh Custom Data Layers");
90                 data->pool = BLI_mempool_create(data->totsize, initalloc, initalloc, 0);
91                 /*initialize layer data*/
92                 for(i=0; i < BME_CD_NUMTYPES; i++){
93                         if(init->layout[i]){
94                                 info = BME_layerType_getInfo(i);
95                                 for(j=0; j < init->layout[i]; j++){
96                                         if(j==0) data->layers[j+i].active = init->active[i];
97                                         data->layers[j+i].type = i;
98                                         data->layers[j+i].offset = offset;      
99                                         strcpy(data->layers[j+i].name, &(init->nametemplate[j+i]));
100                                         offset += info->size;
101                                 }
102                         }
103                 }
104         }
105 }
106
107 void BME_CD_Free(BME_CustomData *data)
108 {
109         if(data->pool) BLI_mempool_destroy(data->pool);
110 }
111
112 /*Block level ops*/
113 void BME_CD_free_block(BME_CustomData *data, void **block)
114 {
115         const BME_LayerTypeInfo *typeInfo;
116         int i;
117
118         if(!*block) return;
119         for(i = 0; i < data->totlayer; ++i) {
120                 typeInfo = BME_layerType_getInfo(data->layers[i].type);
121                 if(typeInfo->free) {
122                         int offset = data->layers[i].offset;
123                         typeInfo->free((char*)*block + offset, 1, typeInfo->size);
124                 }
125         }
126         BLI_mempool_free(data->pool, *block);
127         *block = NULL;
128 }
129
130
131 static void BME_CD_alloc_block(BME_CustomData *data, void **block)
132 {       
133         
134         if (*block) BME_CD_free_block(data, block); //if we copy layers that have their own free functions like deformverts
135         
136         if (data->totsize > 0)
137                 *block = BLI_mempool_alloc(data->pool); 
138         else
139                 *block = NULL;
140 }
141
142 void BME_CD_copy_data(const BME_CustomData *source, BME_CustomData *dest,
143                                                         void *src_block, void **dest_block)
144 {
145         const BME_LayerTypeInfo *typeInfo;
146         int dest_i, src_i;
147
148         if (!*dest_block) /*for addXXXlist functions!*/
149                 BME_CD_alloc_block(dest, dest_block);
150         
151         /* copies a layer at a time */
152         dest_i = 0;
153         for(src_i = 0; src_i < source->totlayer; ++src_i) {
154
155                 /* find the first dest layer with type >= the source type
156                  * (this should work because layers are ordered by type)
157                  */
158                 while(dest_i < dest->totlayer
159                           && dest->layers[dest_i].type < source->layers[src_i].type)
160                         ++dest_i;
161
162                 /* if there are no more dest layers, we're done */
163                 if(dest_i >= dest->totlayer) return;
164
165                 /* if we found a matching layer, copy the data */
166                 if(dest->layers[dest_i].type == source->layers[src_i].type &&
167                         strcmp(dest->layers[dest_i].name, source->layers[src_i].name) == 0) {
168                         char *src_data = (char*)src_block + source->layers[src_i].offset;
169                         char *dest_data = (char*)*dest_block + dest->layers[dest_i].offset;
170
171                         typeInfo = BME_layerType_getInfo(source->layers[src_i].type);
172
173                         if(typeInfo->copy)
174                                 typeInfo->copy(src_data, dest_data, 1);
175                         else
176                                 memcpy(dest_data, src_data, typeInfo->size);
177
178                         /* if there are multiple source & dest layers of the same type,
179                          * we don't want to copy all source layers to the same dest, so
180                          * increment dest_i
181                          */
182                         ++dest_i;
183                 }
184         }
185 }
186 void BME_CD_set_default(BME_CustomData *data, void **block)
187 {
188         const BME_LayerTypeInfo *typeInfo;
189         int i;
190
191         if (!*block)
192                 BME_CD_alloc_block(data, block); //for addXXXlist functions...
193
194         for(i = 0; i < data->totlayer; ++i) {
195                 int offset = data->layers[i].offset;
196
197                 typeInfo = BME_layerType_getInfo(data->layers[i].type);
198
199                 if(typeInfo->set_default)
200                         typeInfo->set_default((char*)*block + offset, 1);
201         }
202 }