diff options
Diffstat (limited to 'source/blender/blenkernel/intern/customdata.c')
-rw-r--r-- | source/blender/blenkernel/intern/customdata.c | 627 |
1 files changed, 561 insertions, 66 deletions
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index d7cc5376e21..f0b93212766 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -44,19 +44,25 @@ #include "DNA_meshdata_types.h" #include "DNA_ID.h" +#include "BLI_utildefines.h" #include "BLI_blenlib.h" #include "BLI_linklist.h" #include "BLI_math.h" #include "BLI_mempool.h" +#include "BLI_cellalloc.h" #include "BLI_utildefines.h" #include "BKE_customdata.h" #include "BKE_customdata_file.h" #include "BKE_global.h" #include "BKE_main.h" -#include "BKE_utildefines.h" #include "BKE_multires.h" +#include "bmesh.h" + +#include <math.h> +#include <string.h> + /* number of layers to add when growing a CustomData object */ #define CUSTOMDATA_GROW 5 @@ -99,6 +105,14 @@ typedef struct LayerTypeInfo { default is assumed to be all zeros */ void (*set_default)(void *data, int count); + /* functions necassary for geometry collapse*/ + int (*equal)(void *data1, void *data2); + void (*multiply)(void *data, float fac); + void (*initminmax)(void *min, void *max); + void (*add)(void *data1, void *data2); + void (*dominmax)(void *data1, void *min, void *max); + void (*copyvalue)(void *source, void *dest); + /* a function to read data from a cdf file */ int (*read)(CDataFile *cdf, void *data, int count); @@ -125,7 +139,7 @@ static void layerCopy_mdeformvert(const void *source, void *dest, MDeformVert *dvert = (MDeformVert *)((char *)dest + i * size); if(dvert->totweight) { - MDeformWeight *dw = MEM_callocN(dvert->totweight * sizeof(*dw), + MDeformWeight *dw = BLI_cellalloc_calloc(dvert->totweight * sizeof(*dw), "layerCopy_mdeformvert dw"); memcpy(dw, dvert->dw, dvert->totweight * sizeof(*dw)); @@ -144,7 +158,7 @@ static void layerFree_mdeformvert(void *data, int count, int size) MDeformVert *dvert = (MDeformVert *)((char *)data + i * size); if(dvert->dw) { - MEM_freeN(dvert->dw); + BLI_cellalloc_free(dvert->dw); dvert->dw = NULL; dvert->totweight = 0; } @@ -153,7 +167,7 @@ static void layerFree_mdeformvert(void *data, int count, int size) static void linklist_free_simple(void *link) { - MEM_freeN(link); + BLI_cellalloc_free(link); } static void layerInterp_mdeformvert(void **sources, float *weights, @@ -186,7 +200,7 @@ static void layerInterp_mdeformvert(void **sources, float *weights, /* if this def_nr is not in the list, add it */ if(!node) { - MDeformWeight *tmp_dw = MEM_callocN(sizeof(*tmp_dw), + MDeformWeight *tmp_dw = BLI_cellalloc_calloc(sizeof(*tmp_dw), "layerInterp_mdeformvert tmp_dw"); tmp_dw->def_nr = dw->def_nr; tmp_dw->weight = dw->weight * interp_weight; @@ -197,10 +211,10 @@ static void layerInterp_mdeformvert(void **sources, float *weights, } /* now we know how many unique deform weights there are, so realloc */ - if(dvert->dw) MEM_freeN(dvert->dw); + if(dvert->dw) BLI_cellalloc_free(dvert->dw); if(totweight) { - dvert->dw = MEM_callocN(sizeof(*dvert->dw) * totweight, + dvert->dw = BLI_cellalloc_calloc(sizeof(*dvert->dw) * totweight, "layerInterp_mdeformvert dvert->dw"); dvert->totweight = totweight; @@ -331,6 +345,24 @@ static void layerDefault_tface(void *data, int count) tf[i] = default_tf; } +static void layerCopy_propFloat(const void *source, void *dest, + int count) +{ + memcpy(dest, source, sizeof(MFloatProperty)*count); +} + +static void layerCopy_propInt(const void *source, void *dest, + int count) +{ + memcpy(dest, source, sizeof(MIntProperty)*count); +} + +static void layerCopy_propString(const void *source, void *dest, + int count) +{ + memcpy(dest, source, sizeof(MStringProperty)*count); +} + static void layerCopy_origspace_face(const void *source, void *dest, int count) { const OrigSpaceFace *source_tf = (const OrigSpaceFace*)source; @@ -419,22 +451,39 @@ static void layerSwap_mdisps(void *data, const int *ci) /* happens when face changed vertex count in edit mode if it happened, just forgot displacement */ - MEM_freeN(s->disps); + BLI_cellalloc_free(s->disps); s->totdisp= (s->totdisp/corners)*nverts; - s->disps= MEM_callocN(s->totdisp*sizeof(float)*3, "mdisp swap"); + s->disps= BLI_cellalloc_calloc(s->totdisp*sizeof(float)*3, "mdisp swap"); return; } - d= MEM_callocN(sizeof(float) * 3 * s->totdisp, "mdisps swap"); + d= BLI_cellalloc_calloc(sizeof(float) * 3 * s->totdisp, "mdisps swap"); for(S = 0; S < corners; S++) memcpy(d + cornersize*S, s->disps + cornersize*ci[S], cornersize*3*sizeof(float)); - MEM_freeN(s->disps); + BLI_cellalloc_free(s->disps); s->disps= d; } } +#if 1 /* BMESH_TODO: place holder function, dont actually interp */ +static void layerInterp_mdisps(void **sources, float *UNUSED(weights), + float *UNUSED(sub_weights), int UNUSED(count), void *dest) +{ + MDisps *d = dest; + + /* happens when flipping normals of newly created mesh */ + if(!d->totdisp) { + d->totdisp = ((MDisps*)sources[0])->totdisp; + } + + if (!d->disps && d->totdisp) + d->disps = BLI_cellalloc_calloc(sizeof(float)*3*d->totdisp, "blank mdisps in layerInterp_mdisps"); +} + +#else // BMESH_TODO + static void layerInterp_mdisps(void **sources, float *UNUSED(weights), float *sub_weights, int count, void *dest) { @@ -547,6 +596,7 @@ static void layerInterp_mdisps(void **sources, float *UNUSED(weights), MEM_freeN(d->disps); d->disps = disps; } +#endif // BMESH_TODO static void layerCopy_mdisps(const void *source, void *dest, int count) { @@ -556,7 +606,7 @@ static void layerCopy_mdisps(const void *source, void *dest, int count) for(i = 0; i < count; ++i) { if(s[i].disps) { - d[i].disps = MEM_dupallocN(s[i].disps); + d[i].disps = BLI_cellalloc_dupalloc(s[i].disps); d[i].totdisp = s[i].totdisp; } else { @@ -569,6 +619,10 @@ static void layerCopy_mdisps(const void *source, void *dest, int count) static void layerValidate_mdisps(void *data, int sub_elements) { +#if 1 /*BMESH_TODO*/ + (void)data; + (void)sub_elements; +#else MDisps *disps = data; if(disps->disps) { int corners = multires_mdisp_corners(disps); @@ -576,9 +630,10 @@ static void layerValidate_mdisps(void *data, int sub_elements) if(corners != sub_elements) { MEM_freeN(disps->disps); disps->totdisp = disps->totdisp / corners * sub_elements; - disps->disps = MEM_callocN(3*disps->totdisp*sizeof(float), "layerValidate_mdisps"); + disps->disps = BLI_cellalloc_calloc(3*disps->totdisp*sizeof(float), "layerValidate_mdisps"); } } +#endif } static void layerFree_mdisps(void *data, int count, int UNUSED(size)) @@ -588,7 +643,7 @@ static void layerFree_mdisps(void *data, int count, int UNUSED(size)) for(i = 0; i < count; ++i) { if(d[i].disps) - MEM_freeN(d[i].disps); + BLI_cellalloc_free(d[i].disps); d[i].disps = NULL; d[i].totdisp = 0; } @@ -601,7 +656,7 @@ static int layerRead_mdisps(CDataFile *cdf, void *data, int count) for(i = 0; i < count; ++i) { if(!d[i].disps) - d[i].disps = MEM_callocN(sizeof(float)*3*d[i].totdisp, "mdisps read"); + d[i].disps = BLI_cellalloc_calloc(sizeof(float)*3*d[i].totdisp, "mdisps read"); if(!cdf_read_data(cdf, d[i].totdisp*3*sizeof(float), d[i].disps)) { printf("failed to read multires displacement %d/%d %d\n", i, count, d[i].totdisp); @@ -640,10 +695,83 @@ static size_t layerFilesize_mdisps(CDataFile *UNUSED(cdf), void *data, int count } /* --------- */ +static void layerCopyValue_mloopcol(void *source, void *dest) +{ + MLoopCol *m1 = source, *m2 = dest; + + m2->r = m1->r; + m2->g = m1->g; + m2->b = m1->b; + m2->a = m1->a; +} + +static int layerEqual_mloopcol(void *data1, void *data2) +{ + MLoopCol *m1 = data1, *m2 = data2; + float r, g, b, a; + + r = m1->r - m2->r; + g = m1->g - m2->g; + b = m1->b - m2->b; + a = m1->a - m2->a; + + return r*r + g*g + b*b + a*a < 0.001; +} + +static void layerMultiply_mloopcol(void *data, float fac) +{ + MLoopCol *m = data; + + m->r = (float)m->r * fac; + m->g = (float)m->g * fac; + m->b = (float)m->b * fac; + m->a = (float)m->a * fac; +} + +static void layerAdd_mloopcol(void *data1, void *data2) +{ + MLoopCol *m = data1, *m2 = data2; + + m->r += m2->r; + m->g += m2->g; + m->b += m2->b; + m->a += m2->a; +} + +static void layerDoMinMax_mloopcol(void *data, void *vmin, void *vmax) +{ + MLoopCol *m = data; + MLoopCol *min = vmin, *max = vmax; + + if (m->r < min->r) min->r = m->r; + if (m->g < min->g) min->g = m->g; + if (m->b < min->b) min->b = m->b; + if (m->a < min->a) min->a = m->a; + + if (m->r > max->r) max->r = m->r; + if (m->g > max->g) max->g = m->g; + if (m->b > max->b) max->b = m->b; + if (m->a > max->a) max->a = m->a; +} + +static void layerInitMinMax_mloopcol(void *vmin, void *vmax) +{ + MLoopCol *min = vmin, *max = vmax; + + min->r = 255; + min->g = 255; + min->b = 255; + min->a = 255; + + max->r = 0; + max->g = 0; + max->b = 0; + max->a = 0; +} static void layerDefault_mloopcol(void *data, int count) { - static MLoopCol default_mloopcol = {255,255,255,255}; + MLoopCol default_mloopcol = {255,255,255,255}; MLoopCol *mlcol = (MLoopCol*)data; int i; for(i = 0; i < count; i++) @@ -695,6 +823,56 @@ static void layerInterp_mloopcol(void **sources, float *weights, mc->g = (int)col.g; mc->b = (int)col.b; } + +static void layerCopyValue_mloopuv(void *source, void *dest) +{ + MLoopUV *luv1 = source, *luv2 = dest; + + luv2->uv[0] = luv1->uv[0]; + luv2->uv[1] = luv1->uv[1]; +} + +static int layerEqual_mloopuv(void *data1, void *data2) +{ + MLoopUV *luv1 = data1, *luv2 = data2; + float u, v; + + u = luv1->uv[0] - luv2->uv[0]; + v = luv1->uv[1] - luv2->uv[1]; + + return u*u + v*v < 0.00001; +} + +static void layerMultiply_mloopuv(void *data, float fac) +{ + MLoopUV *luv = data; + + luv->uv[0] *= fac; + luv->uv[1] *= fac; +} + +static void layerInitMinMax_mloopuv(void *vmin, void *vmax) +{ + MLoopUV *min = vmin, *max = vmax; + + INIT_MINMAX2(min->uv, max->uv); +} + +static void layerDoMinMax_mloopuv(void *data, void *vmin, void *vmax) +{ + MLoopUV *min = vmin, *max = vmax, *luv = data; + + DO_MINMAX2(luv->uv, min->uv, max->uv); +} + +static void layerAdd_mloopuv(void *data1, void *data2) +{ + MLoopUV *l1 = data1, *l2 = data2; + + l1->uv[0] += l2->uv[0]; + l1->uv[1] += l2->uv[1]; +} + static void layerInterp_mloopuv(void **sources, float *weights, float *sub_weights, int count, void *dest) { @@ -802,7 +980,48 @@ static void layerDefault_mcol(void *data, int count) mcol[i] = default_mcol; } +static void layerInterp_bweight(void **sources, float *weights, + float *UNUSED(sub_weights), int count, void *dest) +{ + float *f = dest, *src; + float **in = (float **)sources; + int i; + + if(count <= 0) return; + + *f = 0.0f; + + for(i = 0; i < count; ++i) { + float weight = weights ? weights[i] : 1.0f; + + src = in[i]; + *f += *src * weight; + } +} + +static void layerInterp_shapekey(void **sources, float *weights, + float *UNUSED(sub_weights), int count, void *dest) +{ + float *co = dest, *src; + float **in = (float **)sources; + int i; + if(count <= 0) return; + + memset(co, 0, sizeof(float)*3); + + for(i = 0; i < count; ++i) { + float weight = weights ? weights[i] : 1.0f; + + src = in[i]; + co[0] += src[0] * weight; + co[1] += src[1] * weight; + co[2] += src[2] * weight; + } +} + +/* note, these numbered comments below are copied from trunk, + * while _most_ match, some at the end need adding and are out of sync */ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { /* 0: CD_MVERT */ @@ -828,15 +1047,15 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, /* 8: CD_NORMAL */ /* 3 floats per normal vector */ - {sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, - /* 9: CD_FLAGS */ - {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, + {sizeof(float)*3, "vec3f", 1, NULL, NULL, NULL, NULL, NULL, NULL}, + /* 9: CD_POLYINDEX */ + {sizeof(int), "MIntProperty", 1, NULL, NULL, NULL, NULL, NULL, NULL}, /* 10: CD_PROP_FLT */ - {sizeof(MFloatProperty), "MFloatProperty",1,"Float",NULL,NULL,NULL,NULL}, + {sizeof(MFloatProperty), "MFloatProperty",1,"Float", layerCopy_propFloat,NULL,NULL,NULL}, /* 11: CD_PROP_INT */ - {sizeof(MIntProperty), "MIntProperty",1,"Int",NULL,NULL,NULL,NULL}, + {sizeof(MIntProperty), "MIntProperty",1,"Int",layerCopy_propInt,NULL,NULL,NULL}, /* 12: CD_PROP_STR */ - {sizeof(MStringProperty), "MStringProperty",1,"String",NULL,NULL,NULL,NULL}, + {sizeof(MStringProperty), "MStringProperty",1,"String",layerCopy_propString,NULL,NULL,NULL}, /* 13: CD_ORIGSPACE */ {sizeof(OrigSpaceFace), "OrigSpaceFace", 1, "UVTex", layerCopy_origspace_face, NULL, layerInterp_origspace_face, layerSwap_origspace_face, layerDefault_origspace_face}, @@ -845,58 +1064,80 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { /* 15: CD_MTEXPOLY */ {sizeof(MTexPoly), "MTexPoly", 1, "Face Texture", NULL, NULL, NULL, NULL, NULL}, /* 16: CD_MLOOPUV */ - {sizeof(MLoopUV), "MLoopUV", 1, "UV coord", NULL, NULL, layerInterp_mloopuv, NULL, NULL}, + {sizeof(MLoopUV), "MLoopUV", 1, "UV coord", NULL, NULL, layerInterp_mloopuv, NULL, NULL, + layerEqual_mloopuv, layerMultiply_mloopuv, layerInitMinMax_mloopuv, + layerAdd_mloopuv, layerDoMinMax_mloopuv, layerCopyValue_mloopuv}, /* 17: CD_MLOOPCOL */ - {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL, layerDefault_mloopcol}, - /* 18: CD_TANGENT */ + {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL, + layerDefault_mloopcol, layerEqual_mloopcol, layerMultiply_mloopcol, layerInitMinMax_mloopcol, + layerAdd_mloopcol, layerDoMinMax_mloopcol, layerCopyValue_mloopcol}, {sizeof(float)*4*4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, /* 19: CD_MDISPS */ {sizeof(MDisps), "MDisps", 1, NULL, layerCopy_mdisps, - layerFree_mdisps, layerInterp_mdisps, layerSwap_mdisps, NULL, layerRead_mdisps, layerWrite_mdisps, - layerFilesize_mdisps, layerValidate_mdisps}, + layerFree_mdisps, layerInterp_mdisps, layerSwap_mdisps, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + layerRead_mdisps, layerWrite_mdisps, layerFilesize_mdisps, layerValidate_mdisps}, /* 20: CD_WEIGHT_MCOL */ {sizeof(MCol)*4, "MCol", 4, "WeightCol", NULL, NULL, layerInterp_mcol, layerSwap_mcol, layerDefault_mcol}, + {sizeof(MPoly), "MPoly", 1, "NGon Face", NULL, NULL, NULL, NULL, NULL}, + {sizeof(MLoop), "MLoop", 1, "NGon Face-Vertex", NULL, NULL, NULL, NULL, NULL}, + {sizeof(float)*3, "", 0, "ClothOrco", NULL, NULL, layerInterp_shapekey}, /* 21: CD_ID_MCOL */ {sizeof(MCol)*4, "MCol", 4, "IDCol", NULL, NULL, layerInterp_mcol, layerSwap_mcol, layerDefault_mcol}, - /* 22: CD_TEXTURE_MCOL */ - {sizeof(MCol)*4, "MCol", 4, "TexturedCol", NULL, NULL, layerInterp_mcol, + {sizeof(MCol)*4, "MCol", 4, "TextureCol", NULL, NULL, layerInterp_mcol, layerSwap_mcol, layerDefault_mcol}, - /* 23: CD_CLOTH_ORCO */ - {sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, + {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, + {sizeof(float)*3, "", 0, "ShapeKey", NULL, NULL, layerInterp_shapekey}, + {sizeof(float), "", 0, "BevelWeight", NULL, NULL, layerInterp_bweight}, + {sizeof(float), "", 0, "SubSurfCrease", NULL, NULL, layerInterp_bweight}, + {sizeof(MLoopCol), "MLoopCol", 1, "WeightLoopCol", NULL, NULL, layerInterp_mloopcol, NULL, + layerDefault_mloopcol, layerEqual_mloopcol, layerMultiply_mloopcol, layerInitMinMax_mloopcol, + layerAdd_mloopcol, layerDoMinMax_mloopcol, layerCopyValue_mloopcol}, /* 24: CD_RECAST */ {sizeof(MRecast), "MRecast", 1,"Recast",NULL,NULL,NULL,NULL} }; +/* note, numbers are from trunk and need updating for bmesh */ + static const char *LAYERTYPENAMES[CD_NUMTYPES] = { - /* 0-4 */ "CDMVert", "CDMSticky", "CDMDeformVert", "CDMEdge", "CDMFace", - /* 5-9 */ "CDMTFace", "CDMCol", "CDOrigIndex", "CDNormal", "CDFlags", - /* 10-14 */ "CDMFloatProperty", "CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco", - /* 15-19 */ "CDMTexPoly", "CDMLoopUV", "CDMloopCol", "CDTangent", "CDMDisps", - /* 20-24 */"CDWeightMCol", "CDIDMCol", "CDTextureMCol", "CDClothOrco", "CDMRecast" + /* 0-4 */ "CDMVert", "CDMSticky", "CDMDeformVert", "CDMEdge", "CDMFace", "CDMTFace", + /* 5-9 */ "CDMCol", "CDOrigIndex", "CDNormal", "CDPolyIndex","CDMFloatProperty", + /* 10-14 */ "CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco", "CDMTexPoly", "CDMLoopUV", + /* 15-19 */ "CDMloopCol", "CDTangent", "CDMDisps", "CDWeightMCol", "CDMPoly", + /* 20-24 */ "CDMLoop", "CDMClothOrco", "CDMLoopCol", "CDIDCol", "CDTextureCol", + /* ?-? */ "CDShapeKeyIndex", "CDShapeKey", "CDBevelWeight", "CDSubSurfCrease", "CDMRecast" }; + const CustomDataMask CD_MASK_BAREMESH = - CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE; + CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE | CD_MASK_MLOOP | CD_MASK_MPOLY | CD_MASK_BWEIGHT; const CustomDataMask CD_MASK_MESH = CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE | CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | CD_MASK_MCOL | - CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS | CD_MASK_RECAST; + CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS | + CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MPOLY | CD_MASK_MLOOP | + CD_MASK_MTEXPOLY | CD_MASK_NORMAL | CD_MASK_MDISPS | CD_MASK_RECAST; const CustomDataMask CD_MASK_EDITMESH = - CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | - CD_MASK_MCOL|CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS | CD_MASK_RECAST; + CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | CD_MASK_MLOOPUV | + CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY | CD_MASK_SHAPE_KEYINDEX | + CD_MASK_MCOL|CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | + CD_MASK_MDISPS | CD_MASK_SHAPEKEY | CD_MASK_RECAST; const CustomDataMask CD_MASK_DERIVEDMESH = CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | - CD_MASK_MCOL | CD_MASK_ORIGINDEX | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_CLOTH_ORCO | - CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO | CD_MASK_TANGENT | CD_MASK_WEIGHT_MCOL | CD_MASK_RECAST; -const CustomDataMask CD_MASK_BMESH = - CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR; + CD_MASK_MCOL | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_CLOTH_ORCO | + CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY | CD_MASK_WEIGHT_MLOOPCOL | + CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO | CD_MASK_TANGENT | + CD_MASK_WEIGHT_MCOL | CD_MASK_NORMAL | CD_MASK_SHAPEKEY | CD_MASK_RECAST | + CD_MASK_ORIGINDEX | CD_MASK_POLYINDEX; +const CustomDataMask CD_MASK_BMESH = CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY | + CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | + CD_MASK_PROP_STR | CD_MASK_SHAPEKEY | CD_MASK_SHAPE_KEYINDEX | CD_MASK_MDISPS; const CustomDataMask CD_MASK_FACECORNERS = CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL; - static const LayerTypeInfo *layerType_getInfo(int type) { if(type < 0 || type >= CD_NUMTYPES) return NULL; @@ -917,11 +1158,28 @@ static void customData_update_offsets(CustomData *data); static CustomDataLayer *customData_add_layer__internal(CustomData *data, int type, int alloctype, void *layerdata, int totelem, const char *name); +void CustomData_update_typemap(CustomData *data) +{ + int i, lasttype = -1; + + for (i=0; i<CD_NUMTYPES; i++) { + data->typemap[i] = -1; + } + + for (i=0; i<data->totlayer; i++) { + if (data->layers[i].type != lasttype) { + data->typemap[data->layers[i].type] = i; + } + lasttype = data->layers[i].type; + } +} + void CustomData_merge(const struct CustomData *source, struct CustomData *dest, CustomDataMask mask, int alloctype, int totelem) { /*const LayerTypeInfo *typeInfo;*/ CustomDataLayer *layer, *newlayer; + void *data; int i, type, number = 0, lasttype = -1, lastactive = 0, lastrender = 0, lastclone = 0, lastmask = 0, lastflag = 0; for(i = 0; i < source->totlayer; ++i) { @@ -946,14 +1204,27 @@ void CustomData_merge(const struct CustomData *source, struct CustomData *dest, else if(!((int)mask & (int)(1 << (int)type))) continue; else if(number < CustomData_number_of_layers(dest, type)) continue; + switch (alloctype) { + case CD_ASSIGN: + case CD_REFERENCE: + case CD_DUPLICATE: + data = layer->data; + break; + default: + data = NULL; + break; + } + if((alloctype == CD_ASSIGN) && (lastflag & CD_FLAG_NOFREE)) newlayer = customData_add_layer__internal(dest, type, CD_REFERENCE, - layer->data, totelem, layer->name); + data, totelem, layer->name); else newlayer = customData_add_layer__internal(dest, type, alloctype, - layer->data, totelem, layer->name); + data, totelem, layer->name); if(newlayer) { + newlayer->uid = layer->uid; + newlayer->active = lastactive; newlayer->active_rnd = lastrender; newlayer->active_clone = lastclone; @@ -961,6 +1232,8 @@ void CustomData_merge(const struct CustomData *source, struct CustomData *dest, newlayer->flag |= lastflag & (CD_FLAG_EXTERNAL|CD_FLAG_IN_MEMORY); } } + + CustomData_update_typemap(dest); } void CustomData_copy(const struct CustomData *source, struct CustomData *dest, @@ -1025,6 +1298,7 @@ static void customData_update_offsets(CustomData *data) } data->totsize = offset; + CustomData_update_typemap(data); } int CustomData_get_layer_index(const CustomData *data, int type) @@ -1038,6 +1312,17 @@ int CustomData_get_layer_index(const CustomData *data, int type) return -1; } +int CustomData_get_layer_index_n(const struct CustomData *data, int type, int n) +{ + int i; + + for(i=0; i < data->totlayer; ++i) + if(data->layers[i].type == type) + return i + n; + + return -1; +} + int CustomData_get_named_layer_index(const CustomData *data, int type, const char *name) { int i; @@ -1051,11 +1336,12 @@ int CustomData_get_named_layer_index(const CustomData *data, int type, const cha int CustomData_get_active_layer_index(const CustomData *data, int type) { - int i; + if (!data->totlayer) + return -1; - for(i=0; i < data->totlayer; ++i) - if(data->layers[i].type == type) - return i + data->layers[i].active; + if (data->typemap[type] != -1) { + return data->typemap[type] + data->layers[data->typemap[type]].active; + } return -1; } @@ -1242,6 +1528,13 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data, int size = typeInfo->size * totelem, flag = 0, index = data->totlayer; void *newlayerdata; + /* Passing a layerdata to copy from with an alloctype that won't copy is + most likely a bug */ + BLI_assert(!layerdata || + (alloctype == CD_ASSIGN) || + (alloctype == CD_DUPLICATE) || + (alloctype == CD_REFERENCE)); + if (!typeInfo->defaultname && CustomData_has_layer(data, type)) return &data->layers[CustomData_get_layer_index(data, type)]; @@ -1254,7 +1547,7 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data, return NULL; } - if (alloctype == CD_DUPLICATE) { + if (alloctype == CD_DUPLICATE && layerdata) { if(typeInfo->copy) typeInfo->copy(layerdata, newlayerdata, totelem); else @@ -1284,6 +1577,7 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data, data->layers[index].type = type; data->layers[index].flag = flag; data->layers[index].data = newlayerdata; + if(name || (name=typeInfo->defaultname)) { BLI_strncpy(data->layers[index].name, name, 32); CustomData_set_layer_unique_name(data, index); @@ -1316,6 +1610,7 @@ void *CustomData_add_layer(CustomData *data, int type, int alloctype, layer = customData_add_layer__internal(data, type, alloctype, layerdata, totelem, typeInfo->defaultname); + CustomData_update_typemap(data); if(layer) return layer->data; @@ -1331,6 +1626,7 @@ void *CustomData_add_layer_named(CustomData *data, int type, int alloctype, layer = customData_add_layer__internal(data, type, alloctype, layerdata, totelem, name); + CustomData_update_typemap(data); if(layer) return layer->data; @@ -1369,6 +1665,7 @@ int CustomData_free_layer(CustomData *data, int type, int totelem, int index) customData_resize(data, -CUSTOMDATA_GROW); customData_update_offsets(data); + CustomData_update_typemap(data); return 1; } @@ -1469,7 +1766,7 @@ void CustomData_free_temporary(CustomData *data, int totelem) } void CustomData_set_only_copy(const struct CustomData *data, - CustomDataMask mask) + CustomDataMask mask) { int i; @@ -1478,6 +1775,16 @@ void CustomData_set_only_copy(const struct CustomData *data, data->layers[i].flag |= CD_FLAG_NOCOPY; } +void CustomData_copy_elements(int type, void *source, void *dest, int count) +{ + const LayerTypeInfo *typeInfo = layerType_getInfo(type); + + if (typeInfo->copy) + typeInfo->copy(source, dest, count); + else + memcpy(dest, source, typeInfo->size*count); +} + void CustomData_copy_data(const CustomData *source, CustomData *dest, int source_index, int dest_index, int count) { @@ -1509,7 +1816,12 @@ void CustomData_copy_data(const CustomData *source, CustomData *dest, src_offset = source_index * typeInfo->size; dest_offset = dest_index * typeInfo->size; - + + if (!src_data || !dest_data) { + printf("eek! null data in CustomData_copy_data!\n"); + continue; + } + if(typeInfo->copy) typeInfo->copy(src_data + src_offset, dest_data + dest_offset, @@ -1637,6 +1949,19 @@ void *CustomData_get(const CustomData *data, int index, int type) return (char *)data->layers[layer_index].data + offset; } +void *CustomData_get_n(const CustomData *data, int type, int index, int n) +{ + int layer_index; + int offset; + + /* get the layer index of the first layer of type */ + layer_index = data->typemap[type]; + if(layer_index < 0) return NULL; + + offset = layerType_getInfo(type)->size * index; + return (char *)data->layers[layer_index+n].data + offset; +} + void *CustomData_get_layer(const CustomData *data, int type) { /* get the layer index of the active layer of type */ @@ -1664,6 +1989,20 @@ void *CustomData_get_layer_named(const struct CustomData *data, int type, return data->layers[layer_index].data; } + +int CustomData_set_layer_name(const CustomData *data, int type, int n, const char *name) +{ + /* get the layer index of the first layer of type */ + int layer_index = CustomData_get_layer_index_n(data, type, n); + + if(layer_index < 0) return 0; + if (!name) return 0; + + strcpy(data->layers[layer_index].name, name); + + return 1; +} + void *CustomData_set_layer(const CustomData *data, int type, void *ptr) { /* get the layer index of the first layer of type */ @@ -1983,33 +2322,97 @@ void CustomData_from_em_block(const CustomData *source, CustomData *dest, /*Bmesh functions*/ /*needed to convert to/from different face reps*/ -void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *ldata) +void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *ldata, + int totloop, int totpoly) { int i; for(i=0; i < fdata->totlayer; i++){ if(fdata->layers[i].type == CD_MTFACE){ - CustomData_add_layer(pdata, CD_MTEXPOLY, CD_CALLOC, &(fdata->layers[i].name), 0); - CustomData_add_layer(ldata, CD_MLOOPUV, CD_CALLOC, &(fdata->layers[i].name), 0); + CustomData_add_layer_named(pdata, CD_MTEXPOLY, CD_CALLOC, NULL, totpoly, fdata->layers[i].name); + CustomData_add_layer_named(ldata, CD_MLOOPUV, CD_CALLOC, NULL, totloop, fdata->layers[i].name); } else if(fdata->layers[i].type == CD_MCOL) - CustomData_add_layer(ldata, CD_MLOOPCOL, CD_CALLOC, &(fdata->layers[i].name), 0); - } + CustomData_add_layer_named(ldata, CD_MLOOPCOL, CD_CALLOC, NULL, totloop, fdata->layers[i].name); + else if(fdata->layers[i].type == CD_MDISPS) + CustomData_add_layer_named(ldata, CD_MDISPS, CD_CALLOC, NULL, totloop, fdata->layers[i].name); + } } -void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *ldata, int total){ +void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *ldata, int total) +{ int i; for(i=0; i < pdata->totlayer; i++){ if(pdata->layers[i].type == CD_MTEXPOLY) - CustomData_add_layer(fdata, CD_MTFACE, CD_CALLOC, &(pdata->layers[i].name), total); + CustomData_add_layer_named(fdata, CD_MTFACE, CD_CALLOC, NULL, total, pdata->layers[i].name); } for(i=0; i < ldata->totlayer; i++){ if(ldata->layers[i].type == CD_MLOOPCOL) - CustomData_add_layer(fdata, CD_MCOL, CD_CALLOC, &(ldata->layers[i].name), total); + CustomData_add_layer_named(fdata, CD_MCOL, CD_CALLOC, NULL, total, ldata->layers[i].name); + if (ldata->layers[i].type == CD_WEIGHT_MLOOPCOL) + CustomData_add_layer_named(fdata, CD_WEIGHT_MCOL, CD_CALLOC, NULL, total, ldata->layers[i].name); } } -void CustomData_bmesh_init_pool(CustomData *data, int allocsize){ - if(data->totlayer)data->pool = BLI_mempool_create(data->totsize, allocsize, allocsize, 0); +void CustomData_bmesh_init_pool(CustomData *data, int allocsize) +{ + /* Dispose old pools before calling here to avoid leaks */ + BLI_assert(data->pool == NULL); + + /* If there are no layers, no pool is needed just yet */ + if (data->totlayer) { + data->pool = BLI_mempool_create(data->totsize, allocsize, allocsize, 1, 0); + } +} + +void CustomData_bmesh_merge(CustomData *source, CustomData *dest, + int mask, int alloctype, BMesh *bm, int type) +{ + BMHeader *h; + BMIter iter; + CustomData destold = *dest; + void *tmp; + int t; + + CustomData_merge(source, dest, mask, alloctype, 0); + CustomData_bmesh_init_pool(dest, 512); + + switch (type) { + case BM_VERT: + t = BM_VERTS_OF_MESH; break; + case BM_EDGE: + t = BM_EDGES_OF_MESH; break; + case BM_LOOP: + t = BM_LOOPS_OF_FACE; break; + case BM_FACE: + t = BM_FACES_OF_MESH; break; + default: /* should never happen */ + BLI_assert(!"invalid type given"); + t = BM_VERTS_OF_MESH; + } + + if (t != BM_LOOPS_OF_FACE) { + /*ensure all current elements follow new customdata layout*/ + BM_ITER(h, &iter, bm, t, NULL) { + CustomData_bmesh_copy_data(&destold, dest, h->data, &tmp); + CustomData_bmesh_free_block(&destold, &h->data); + h->data = tmp; + } + } else { + BMFace *f; + BMLoop *l; + BMIter liter; + + /*ensure all current elements follow new customdata layout*/ + BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) { + BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) { + CustomData_bmesh_copy_data(&destold, dest, l->head.data, &tmp); + CustomData_bmesh_free_block(&destold, &l->head.data); + l->head.data = tmp; + } + } + } + + if (destold.pool) BLI_mempool_destroy(destold.pool); } void CustomData_bmesh_free_block(CustomData *data, void **block) @@ -2029,7 +2432,9 @@ void CustomData_bmesh_free_block(CustomData *data, void **block) } } - BLI_mempool_free(data->pool, *block); + if (data->totsize) + BLI_mempool_free(data->pool, *block); + *block = NULL; } @@ -2040,7 +2445,7 @@ static void CustomData_bmesh_alloc_block(CustomData *data, void **block) CustomData_bmesh_free_block(data, block); if (data->totsize > 0) - *block = BLI_mempool_calloc(data->pool); + *block = BLI_mempool_alloc(data->pool); else *block = NULL; } @@ -2113,6 +2518,82 @@ void *CustomData_bmesh_get_n(const CustomData *data, void *block, int type, int return (char *)block + data->layers[layer_index+n].offset; } +/*gets from the layer at physical index n, note: doesn't check type.*/ +void *CustomData_bmesh_get_layer_n(const CustomData *data, void *block, int n) +{ + if(n < 0 || n >= data->totlayer) return NULL; + + return (char *)block + data->layers[n].offset; +} + +int CustomData_layer_has_math(struct CustomData *data, int layern) +{ + const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[layern].type); + + if (typeInfo->equal && typeInfo->add && typeInfo->multiply && + typeInfo->initminmax && typeInfo->dominmax) return 1; + + return 0; +} + +/*copies the "value" (e.g. mloopuv uv or mloopcol colors) from one block to + another, while not overwriting anything else (e.g. flags)*/ +void CustomData_data_copy_value(int type, void *source, void *dest) +{ + const LayerTypeInfo *typeInfo = layerType_getInfo(type); + + if(!dest) return; + + if(typeInfo->copyvalue) + typeInfo->copyvalue(source, dest); + else + memcpy(dest, source, typeInfo->size); +} + +int CustomData_data_equals(int type, void *data1, void *data2) +{ + const LayerTypeInfo *typeInfo = layerType_getInfo(type); + + if (typeInfo->equal) + return typeInfo->equal(data1, data2); + else return !memcmp(data1, data2, typeInfo->size); +} + +void CustomData_data_initminmax(int type, void *min, void *max) +{ + const LayerTypeInfo *typeInfo = layerType_getInfo(type); + + if (typeInfo->initminmax) + typeInfo->initminmax(min, max); +} + + +void CustomData_data_dominmax(int type, void *data, void *min, void *max) +{ + const LayerTypeInfo *typeInfo = layerType_getInfo(type); + + if (typeInfo->dominmax) + typeInfo->dominmax(data, min, max); +} + + +void CustomData_data_multiply(int type, void *data, float fac) +{ + const LayerTypeInfo *typeInfo = layerType_getInfo(type); + + if (typeInfo->multiply) + typeInfo->multiply(data, fac); +} + + +void CustomData_data_add(int type, void *data1, void *data2) +{ + const LayerTypeInfo *typeInfo = layerType_getInfo(type); + + if (typeInfo->add) + typeInfo->add(data1, data2); +} + void CustomData_bmesh_set(const CustomData *data, void *block, int type, void *source) { void *dest = CustomData_bmesh_get(data, block, type); @@ -2139,6 +2620,19 @@ void CustomData_bmesh_set_n(CustomData *data, void *block, int type, int n, void memcpy(dest, source, typeInfo->size); } +void CustomData_bmesh_set_layer_n(CustomData *data, void *block, int n, void *source) +{ + void *dest = CustomData_bmesh_get_layer_n(data, block, n); + const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[n].type); + + if(!dest) return; + + if(typeInfo->copy) + typeInfo->copy(source, dest, 1); + else + memcpy(dest, source, typeInfo->size); +} + void CustomData_bmesh_interp(CustomData *data, void **src_blocks, float *weights, float *sub_weights, int count, void *dest_block) { @@ -2184,6 +2678,7 @@ void CustomData_bmesh_set_default(CustomData *data, void **block) if(typeInfo->set_default) typeInfo->set_default((char*)*block + offset, 1); + else memset((char*)*block + offset, 0, typeInfo->size); } } |