Blender  V2.59
BME_Customdata.c
Go to the documentation of this file.
00001 /*
00002  * BME_customdata.c    jan 2007
00003  *
00004  *      Custom Data functions for Bmesh
00005  *
00006  * $Id: BME_Customdata.c 35247 2011-02-27 20:40:57Z jesterking $
00007  *
00008  * ***** BEGIN GPL LICENSE BLOCK *****
00009  *
00010  * This program is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU General Public License
00012  * as published by the Free Software Foundation; either version 2
00013  * of the License, or (at your option) any later version. The Blender
00014  * Foundation also sells licenses for use in proprietary software under
00015  * the Blender License.  See http://www.blender.org/BL/ for information
00016  * about this.  
00017  *
00018  * This program is distributed in the hope that it will be useful,
00019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021  * GNU General Public License for more details.
00022  *
00023  * You should have received a copy of the GNU General Public License
00024  * along with this program; if not, write to the Free Software Foundation,
00025  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00026  *
00027  * The Original Code is Copyright (C) 2004 Blender Foundation.
00028  * All rights reserved.
00029  *
00030  * The Original Code is: all of this file.
00031  *
00032  * Contributor(s): Geoffrey Bantle, Brecht Van Lommel, Ben Batt
00033  *
00034  * ***** END GPL LICENSE BLOCK *****
00035  */
00036 
00042 #include <string.h>
00043 
00044 #include "MEM_guardedalloc.h"
00045 #include "BKE_bmeshCustomData.h"
00046 #include "bmesh_private.h"
00047 
00048 /********************* Layer type information **********************/
00049 typedef struct BME_LayerTypeInfo {
00050         int size;
00051         const char *defaultname;
00052         void (*copy)(const void *source, void *dest, int count);
00053         void (*free)(void *data, int count, int size);
00054         void (*interp)(void **sources, float *weights, float *sub_weights, int count, void *dest);
00055         void (*set_default)(void *data, int count);
00056 } BME_LayerTypeInfo;
00057 const BME_LayerTypeInfo BMELAYERTYPEINFO[BME_CD_NUMTYPES] = {
00058         {sizeof(BME_facetex), "TexFace", NULL, NULL, NULL, NULL},
00059         {sizeof(BME_looptex), "UV", NULL, NULL, NULL, NULL},
00060         {sizeof(BME_loopcol), "VCol", NULL, NULL, NULL, NULL},
00061         {sizeof(BME_DeformVert), "Group", NULL, NULL, NULL, NULL}
00062 };
00063 static const BME_LayerTypeInfo *BME_layerType_getInfo(int type)
00064 {
00065         if(type < 0 || type >= CD_NUMTYPES) return NULL;
00066 
00067         return &BMELAYERTYPEINFO[type];
00068 }
00069 void BME_CD_Create(BME_CustomData *data, BME_CustomDataInit *init, int initalloc)
00070 {
00071         int i, j, offset=0;
00072         const BME_LayerTypeInfo *info;
00073         
00074         /*initialize data members*/
00075         data->layers = NULL;
00076         data->pool = NULL;
00077         data->totlayer = 0;
00078         data->totsize = 0;
00079 
00080         /*first count how many layers to alloc*/
00081         for(i=0; i < BME_CD_NUMTYPES; i++){
00082                 info = BME_layerType_getInfo(i);
00083                 data->totlayer += init->layout[i];
00084                 data->totsize  += (init->layout[i] * info->size);
00085         }
00086         /*alloc our layers*/
00087         if(data->totlayer){
00088                 /*alloc memory*/
00089                 data->layers = MEM_callocN(sizeof(BME_CustomDataLayer)*data->totlayer, "BMesh Custom Data Layers");
00090                 data->pool = BLI_mempool_create(data->totsize, initalloc, initalloc, 0);
00091                 /*initialize layer data*/
00092                 for(i=0; i < BME_CD_NUMTYPES; i++){
00093                         if(init->layout[i]){
00094                                 info = BME_layerType_getInfo(i);
00095                                 for(j=0; j < init->layout[i]; j++){
00096                                         if(j==0) data->layers[j+i].active = init->active[i];
00097                                         data->layers[j+i].type = i;
00098                                         data->layers[j+i].offset = offset;      
00099                                         strcpy(data->layers[j+i].name, &(init->nametemplate[j+i]));
00100                                         offset += info->size;
00101                                 }
00102                         }
00103                 }
00104         }
00105 }
00106 
00107 void BME_CD_Free(BME_CustomData *data)
00108 {
00109         if(data->pool) BLI_mempool_destroy(data->pool);
00110 }
00111 
00112 /*Block level ops*/
00113 void BME_CD_free_block(BME_CustomData *data, void **block)
00114 {
00115         const BME_LayerTypeInfo *typeInfo;
00116         int i;
00117 
00118         if(!*block) return;
00119         for(i = 0; i < data->totlayer; ++i) {
00120                 typeInfo = BME_layerType_getInfo(data->layers[i].type);
00121                 if(typeInfo->free) {
00122                         int offset = data->layers[i].offset;
00123                         typeInfo->free((char*)*block + offset, 1, typeInfo->size);
00124                 }
00125         }
00126         BLI_mempool_free(data->pool, *block);
00127         *block = NULL;
00128 }
00129 
00130 
00131 static void BME_CD_alloc_block(BME_CustomData *data, void **block)
00132 {       
00133         
00134         if (*block) BME_CD_free_block(data, block); //if we copy layers that have their own free functions like deformverts
00135         
00136         if (data->totsize > 0)
00137                 *block = BLI_mempool_alloc(data->pool); 
00138         else
00139                 *block = NULL;
00140 }
00141 
00142 void BME_CD_copy_data(const BME_CustomData *source, BME_CustomData *dest,
00143                                                         void *src_block, void **dest_block)
00144 {
00145         const BME_LayerTypeInfo *typeInfo;
00146         int dest_i, src_i;
00147 
00148         if (!*dest_block) /*for addXXXlist functions!*/
00149                 BME_CD_alloc_block(dest, dest_block);
00150         
00151         /* copies a layer at a time */
00152         dest_i = 0;
00153         for(src_i = 0; src_i < source->totlayer; ++src_i) {
00154 
00155                 /* find the first dest layer with type >= the source type
00156                  * (this should work because layers are ordered by type)
00157                  */
00158                 while(dest_i < dest->totlayer
00159                           && dest->layers[dest_i].type < source->layers[src_i].type)
00160                         ++dest_i;
00161 
00162                 /* if there are no more dest layers, we're done */
00163                 if(dest_i >= dest->totlayer) return;
00164 
00165                 /* if we found a matching layer, copy the data */
00166                 if(dest->layers[dest_i].type == source->layers[src_i].type &&
00167                         strcmp(dest->layers[dest_i].name, source->layers[src_i].name) == 0) {
00168                         char *src_data = (char*)src_block + source->layers[src_i].offset;
00169                         char *dest_data = (char*)*dest_block + dest->layers[dest_i].offset;
00170 
00171                         typeInfo = BME_layerType_getInfo(source->layers[src_i].type);
00172 
00173                         if(typeInfo->copy)
00174                                 typeInfo->copy(src_data, dest_data, 1);
00175                         else
00176                                 memcpy(dest_data, src_data, typeInfo->size);
00177 
00178                         /* if there are multiple source & dest layers of the same type,
00179                          * we don't want to copy all source layers to the same dest, so
00180                          * increment dest_i
00181                          */
00182                         ++dest_i;
00183                 }
00184         }
00185 }
00186 void BME_CD_set_default(BME_CustomData *data, void **block)
00187 {
00188         const BME_LayerTypeInfo *typeInfo;
00189         int i;
00190 
00191         if (!*block)
00192                 BME_CD_alloc_block(data, block); //for addXXXlist functions...
00193 
00194         for(i = 0; i < data->totlayer; ++i) {
00195                 int offset = data->layers[i].offset;
00196 
00197                 typeInfo = BME_layerType_getInfo(data->layers[i].type);
00198 
00199                 if(typeInfo->set_default)
00200                         typeInfo->set_default((char*)*block + offset, 1);
00201         }
00202 }