diff options
Diffstat (limited to 'source/blender/blenkernel/intern/customdata.c')
-rw-r--r-- | source/blender/blenkernel/intern/customdata.c | 108 |
1 files changed, 99 insertions, 9 deletions
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index ecd809304cd..a12d5434b30 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -61,6 +61,8 @@ #include "BKE_mesh_remap.h" #include "BKE_multires.h" +#include "data_transfer_intern.h" + #include "bmesh.h" #include <math.h> @@ -305,13 +307,16 @@ static void layerInterp_normal( const void **sources, const float *weights, const float *UNUSED(sub_weights), int count, void *dest) { + /* Note: This is linear interpolation, which is not optimal for vectors. + * Unfortunately, spherical interpolation of more than two values is hairy, so for now it will do... */ float no[3] = {0.0f}; while (count--) { madd_v3_v3fl(no, (const float *)sources[count], weights[count]); } - copy_v3_v3((float *)dest, no); + /* Weighted sum of normalized vectors will **not** be normalized, even if weights are. */ + normalize_v3_v3((float *)dest, no); } static void layerCopyValue_normal(const void *source, void *dest, const int mixmode, const float mixfactor) @@ -904,6 +909,7 @@ static void layerInterp_mloopuv( const float *sub_weights, int count, void *dest) { float uv[2]; + int flag = 0; int i; zero_v2(uv); @@ -911,9 +917,12 @@ static void layerInterp_mloopuv( if (sub_weights) { const float *sub_weight = sub_weights; for (i = 0; i < count; i++) { - float weight = weights ? weights[i] : 1.0f; + float weight = (weights ? weights[i] : 1.0f) * (*sub_weight); const MLoopUV *src = sources[i]; - madd_v2_v2fl(uv, src->uv, (*sub_weight) * weight); + madd_v2_v2fl(uv, src->uv, weight); + if (weight > 0.0f) { + flag |= src->flag; + } sub_weight++; } } @@ -922,11 +931,15 @@ static void layerInterp_mloopuv( float weight = weights ? weights[i] : 1; const MLoopUV *src = sources[i]; madd_v2_v2fl(uv, src->uv, weight); + if (weight > 0.0f) { + flag |= src->flag; + } } } /* delay writing to the destination incase dest is in sources */ copy_v2_v2(((MLoopUV *)dest)->uv, uv); + ((MLoopUV *)dest)->flag = flag; } /* origspace is almost exact copy of mloopuv's, keep in sync */ @@ -1297,7 +1310,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { /* 35: CD_GRID_PAINT_MASK */ {sizeof(GridPaintMask), "GridPaintMask", 1, NULL, layerCopy_grid_paint_mask, layerFree_grid_paint_mask, NULL, NULL, NULL}, - /* 36: CD_SKIN_NODE */ + /* 36: CD_MVERT_SKIN */ {sizeof(MVertSkin), "MVertSkin", 1, NULL, NULL, NULL, layerInterp_mvert_skin, NULL, layerDefault_mvert_skin}, /* 37: CD_FREESTYLE_EDGE */ @@ -1312,7 +1325,6 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { {sizeof(short[2]), "vec2s", 1, NULL, NULL, 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", @@ -1361,9 +1373,16 @@ const CustomDataMask CD_MASK_BMESH = CD_MASK_CREASE | CD_MASK_BWEIGHT | CD_MASK_RECAST | CD_MASK_PAINT_MASK | CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN | CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE | CD_MASK_CUSTOMLOOPNORMAL; -const CustomDataMask CD_MASK_FACECORNERS = /* XXX Not used anywhere! */ - CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV | - CD_MASK_MLOOPCOL | CD_MASK_NORMAL | CD_MASK_MLOOPTANGENT; +/** + * cover values copied by #BKE_mesh_loops_to_tessdata + */ +const CustomDataMask CD_MASK_FACECORNERS = + CD_MASK_MTFACE | CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV | + CD_MASK_MCOL | CD_MASK_MLOOPCOL | + CD_MASK_PREVIEW_MCOL | CD_MASK_PREVIEW_MLOOPCOL | + CD_MASK_ORIGSPACE | CD_MASK_ORIGSPACE_MLOOP | + CD_MASK_TESSLOOPNORMAL | CD_MASK_NORMAL | + CD_MASK_TANGENT | CD_MASK_MLOOPTANGENT; const CustomDataMask CD_MASK_EVERYTHING = CD_MASK_MVERT | CD_MASK_MDEFORMVERT | CD_MASK_MEDGE | CD_MASK_MFACE | CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_ORIGINDEX | CD_MASK_NORMAL /* | CD_MASK_POLYINDEX */ | CD_MASK_PROP_FLT | @@ -2314,7 +2333,14 @@ void CustomData_interp(const CustomData *source, CustomData *dest, if (count > SOURCE_BUF_SIZE) MEM_freeN((void *)sources); } -void CustomData_swap(struct CustomData *data, int index, const int *corner_indices) +/** + * Swap data inside each item, for all layers. + * This only applies to item types that may store several sub-item data (e.g. corner data [UVs, VCol, ...] of + * tessellated faces). + * + * \param corner_indices A mapping 'new_index -> old_index' of sub-item data. + */ +void CustomData_swap_corners(struct CustomData *data, int index, const int *corner_indices) { const LayerTypeInfo *typeInfo; int i; @@ -2330,6 +2356,35 @@ void CustomData_swap(struct CustomData *data, int index, const int *corner_indic } } +/** + * Swap two items of given custom data, in all available layers. + */ +void CustomData_swap(struct CustomData *data, const int index_a, const int index_b) +{ + int i; + char buff_static[256]; + + if (index_a == index_b) { + return; + } + + for (i = 0; i < data->totlayer; ++i) { + const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[i].type); + const size_t size = typeInfo->size; + const size_t offset_a = size * index_a; + const size_t offset_b = size * index_b; + + void *buff = size <= sizeof(buff_static) ? buff_static : MEM_mallocN(size, __func__); + memcpy(buff, POINTER_OFFSET(data->layers[i].data, offset_a), size); + memcpy(POINTER_OFFSET(data->layers[i].data, offset_a), POINTER_OFFSET(data->layers[i].data, offset_b), size); + memcpy(POINTER_OFFSET(data->layers[i].data, offset_b), buff, size); + + if (buff != buff_static) { + MEM_freeN(buff); + } + } +} + void *CustomData_get(const CustomData *data, int index, int type) { int offset; @@ -3522,6 +3577,7 @@ void CustomData_external_read(CustomData *data, ID *id, CustomDataMask mask, int cdf = cdf_create(CDF_TYPE_MESH); if (!cdf_read_open(cdf, filename)) { + cdf_free(cdf); fprintf(stderr, "Failed to read %s layer from %s.\n", layerType_getName(layer->type), filename); return; } @@ -3612,6 +3668,7 @@ void CustomData_external_write(CustomData *data, ID *id, CustomDataMask mask, in if (!cdf_write_open(cdf, filename)) { fprintf(stderr, "Failed to open %s for writing.\n", filename); + cdf_free(cdf); return; } @@ -3638,6 +3695,7 @@ void CustomData_external_write(CustomData *data, ID *id, CustomDataMask mask, in if (i != data->totlayer) { fprintf(stderr, "Failed to write data to %s.\n", filename); + cdf_write_close(cdf); cdf_free(cdf); return; } @@ -3905,6 +3963,38 @@ static void customdata_data_transfer_interp_generic( MEM_freeN(tmp_dst); } +/* Normals are special, we need to take care of source & destination spaces... */ +void customdata_data_transfer_interp_normal_normals( + const CustomDataTransferLayerMap *laymap, void *data_dst, + const void **sources, const float *weights, const int count, + const float mix_factor) +{ + const int data_type = laymap->data_type; + const int mix_mode = laymap->mix_mode; + + SpaceTransform *space_transform = laymap->interp_data; + + const LayerTypeInfo *type_info = layerType_getInfo(data_type); + cd_interp interp_cd = type_info->interp; + + float tmp_dst[3]; + + BLI_assert(data_type == CD_NORMAL); + + if (!sources) { + /* Not supported here, abort. */ + return; + } + + interp_cd(sources, weights, NULL, count, tmp_dst); + if (space_transform) { + /* tmp_dst is in source space so far, bring it back in destination space. */ + BLI_space_transform_invert_normal(space_transform, tmp_dst); + } + + CustomData_data_mix_value(data_type, tmp_dst, data_dst, mix_mode, mix_factor); +} + void CustomData_data_transfer(const MeshPairRemap *me_remap, const CustomDataTransferLayerMap *laymap) { MeshPairRemapItem *mapit = me_remap->items; |