Blender V2.61 - r43446

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