diff options
author | Bastien Montagne <montagne29@wanadoo.fr> | 2015-10-16 22:28:22 +0300 |
---|---|---|
committer | Bastien Montagne <montagne29@wanadoo.fr> | 2015-10-16 22:56:42 +0300 |
commit | 8172712841975014e28219da91a41c7c5b074d5a (patch) | |
tree | 876c6683bab9c6d2759293baf317dd41805d0733 /source/blender | |
parent | a88ae6fa708ff099410c035e022eacbc62d87bea (diff) |
Fix T46508: data_transfer of normals fails in case objects are transformed.
The final stage of the process (copying/interpolating new dst cddata from src cddata)
was simply broken in normal case, where we need to convert from source to destination
object space.
This patch is a bit verbose, but I cannot see how to avoid it really.
To think this code is in master since over 6 months and it only gets reported now... :/
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/BKE_customdata.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/customdata.c | 34 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/data_transfer.c | 70 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/data_transfer_intern.h | 8 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/deform.c | 6 |
5 files changed, 88 insertions, 32 deletions
diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index 3e784752f10..a7c5c210061 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -472,6 +472,8 @@ typedef struct CustomDataTransferLayerMap { size_t data_offset; /* Offset of actual data we transfer (in element contained in data_src/dst). */ uint64_t data_flag; /* For bitflag transfer, flag(s) to affect in transfered data. */ + void *interp_data; /* Opaque pointer, to be used by specific interp callback (e.g. transformspace for normals). */ + cd_datatransfer_interp interp; } CustomDataTransferLayerMap; diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index f14feee0b2a..7149b24161f 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> @@ -3913,6 +3915,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; diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c index 28aaec84859..43d23e92901 100644 --- a/source/blender/blenkernel/intern/data_transfer.c +++ b/source/blender/blenkernel/intern/data_transfer.c @@ -428,7 +428,7 @@ void data_transfer_layersmapping_add_item( ListBase *r_map, const int cddata_type, const int mix_mode, const float mix_factor, const float *mix_weights, const void *data_src, void *data_dst, const int data_src_n, const int data_dst_n, const size_t elem_size, const size_t data_size, const size_t data_offset, const uint64_t data_flag, - cd_datatransfer_interp interp) + cd_datatransfer_interp interp, void *interp_data) { CustomDataTransferLayerMap *item = MEM_mallocN(sizeof(*item), __func__); @@ -450,17 +450,18 @@ void data_transfer_layersmapping_add_item( item->data_flag = data_flag; item->interp = interp; + item->interp_data = interp_data; BLI_addtail(r_map, item); } static void data_transfer_layersmapping_add_item_cd( ListBase *r_map, const int cddata_type, const int mix_mode, const float mix_factor, const float *mix_weights, - void *data_src, void *data_dst) + void *data_src, void *data_dst, cd_datatransfer_interp interp, void *interp_data) { data_transfer_layersmapping_add_item( r_map, cddata_type, mix_mode, mix_factor, mix_weights, data_src, data_dst, - 0, 0, 0, 0, 0, 0, NULL); + 0, 0, 0, 0, 0, 0, interp, interp_data); } /* Note: All those layer mapping handlers return false *only* if they were given invalid parameters. @@ -473,7 +474,8 @@ static bool data_transfer_layersmapping_cdlayers_multisrc_to_dst( ListBase *r_map, const int cddata_type, const int mix_mode, const float mix_factor, const float *mix_weights, const int num_elem_dst, const bool use_create, const bool use_delete, CustomData *cd_src, CustomData *cd_dst, const bool use_dupref_dst, - const int tolayers, bool *use_layers_src, const int num_layers_src) + const int tolayers, bool *use_layers_src, const int num_layers_src, + cd_datatransfer_interp interp, void *interp_data) { void *data_src, *data_dst = NULL; int idx_src = num_layers_src; @@ -527,7 +529,7 @@ static bool data_transfer_layersmapping_cdlayers_multisrc_to_dst( data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_src); } data_transfer_layersmapping_add_item_cd(r_map, cddata_type, mix_mode, mix_factor, mix_weights, - data_src, data_dst); + data_src, data_dst, interp, interp_data); } } break; @@ -571,7 +573,7 @@ static bool data_transfer_layersmapping_cdlayers_multisrc_to_dst( data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_dst); } data_transfer_layersmapping_add_item_cd(r_map, cddata_type, mix_mode, mix_factor, mix_weights, - data_src, data_dst); + data_src, data_dst, interp, interp_data); } } @@ -599,7 +601,8 @@ static bool data_transfer_layersmapping_cdlayers( ListBase *r_map, const int cddata_type, const int mix_mode, const float mix_factor, const float *mix_weights, const int num_elem_dst, const bool use_create, const bool use_delete, CustomData *cd_src, CustomData *cd_dst, const bool use_dupref_dst, - const int fromlayers, const int tolayers) + const int fromlayers, const int tolayers, + cd_datatransfer_interp interp, void *interp_data) { int idx_src, idx_dst; void *data_src, *data_dst = NULL; @@ -626,7 +629,7 @@ static bool data_transfer_layersmapping_cdlayers( if (r_map) { data_transfer_layersmapping_add_item_cd(r_map, cddata_type, mix_mode, mix_factor, mix_weights, - data_src, data_dst); + data_src, data_dst, interp, interp_data); } } else if (fromlayers == DT_LAYERS_ACTIVE_SRC || fromlayers >= 0) { @@ -719,7 +722,7 @@ static bool data_transfer_layersmapping_cdlayers( if (r_map) { data_transfer_layersmapping_add_item_cd( - r_map, cddata_type, mix_mode, mix_factor, mix_weights, data_src, data_dst); + r_map, cddata_type, mix_mode, mix_factor, mix_weights, data_src, data_dst, interp, interp_data); } } else if (fromlayers == DT_LAYERS_ALL_SRC) { @@ -734,7 +737,8 @@ static bool data_transfer_layersmapping_cdlayers( ret = data_transfer_layersmapping_cdlayers_multisrc_to_dst( r_map, cddata_type, mix_mode, mix_factor, mix_weights, num_elem_dst, use_create, use_delete, cd_src, cd_dst, use_dupref_dst, - tolayers, use_layers_src, num_src); + tolayers, use_layers_src, num_src, + interp, interp_data); if (use_layers_src) { MEM_freeN(use_layers_src); @@ -751,10 +755,14 @@ static bool data_transfer_layersmapping_cdlayers( static bool data_transfer_layersmapping_generate( ListBase *r_map, Object *ob_src, Object *ob_dst, DerivedMesh *dm_src, DerivedMesh *dm_dst, Mesh *me_dst, const int elem_type, int cddata_type, int mix_mode, float mix_factor, const float *mix_weights, - const int num_elem_dst, const bool use_create, const bool use_delete, const int fromlayers, const int tolayers) + const int num_elem_dst, const bool use_create, const bool use_delete, const int fromlayers, const int tolayers, + SpaceTransform *space_transform) { CustomData *cd_src, *cd_dst; + cd_datatransfer_interp interp = NULL; + void *interp_data = NULL; + if (elem_type == ME_VERT) { if (!(cddata_type & CD_FAKE)) { cd_src = dm_src->getVertDataLayout(dm_src); @@ -763,7 +771,8 @@ static bool data_transfer_layersmapping_generate( if (!data_transfer_layersmapping_cdlayers(r_map, cddata_type, mix_mode, mix_factor, mix_weights, num_elem_dst, use_create, use_delete, cd_src, cd_dst, dm_dst != NULL, - fromlayers, tolayers)) + fromlayers, tolayers, + interp, interp_data)) { /* We handle specific source selection cases here. */ return false; @@ -795,7 +804,7 @@ static bool data_transfer_layersmapping_generate( dm_src->getNumVerts(dm_src), dm_dst ? dm_dst->getNumVerts(dm_dst) : me_dst->totvert, elem_size, data_size, data_offset, data_flag, - data_transfer_interp_char); + data_transfer_interp_char, interp_data); } return true; } @@ -827,7 +836,8 @@ static bool data_transfer_layersmapping_generate( if (!data_transfer_layersmapping_cdlayers(r_map, cddata_type, mix_mode, mix_factor, mix_weights, num_elem_dst, use_create, use_delete, cd_src, cd_dst, dm_dst != NULL, - fromlayers, tolayers)) + fromlayers, tolayers, + interp, interp_data)) { /* We handle specific source selection cases here. */ return false; @@ -859,7 +869,7 @@ static bool data_transfer_layersmapping_generate( dm_src->getNumEdges(dm_src), dm_dst ? dm_dst->getNumEdges(dm_dst) : me_dst->totedge, elem_size, data_size, data_offset, data_flag, - data_transfer_interp_char); + data_transfer_interp_char, interp_data); } return true; } @@ -888,7 +898,7 @@ static bool data_transfer_layersmapping_generate( dm_src->getNumEdges(dm_src), dm_dst ? dm_dst->getNumEdges(dm_dst) : me_dst->totedge, elem_size, data_size, data_offset, data_flag, - data_transfer_interp_char); + data_transfer_interp_char, interp_data); } return true; } @@ -904,7 +914,7 @@ static bool data_transfer_layersmapping_generate( dm_dst ? dm_dst->getEdgeArray(dm_dst) : me_dst->medge, dm_src->getNumEdges(dm_src), dm_dst ? dm_dst->getNumEdges(dm_dst) : me_dst->totedge, - elem_size, data_size, data_offset, data_flag, NULL); + elem_size, data_size, data_offset, data_flag, NULL, interp_data); return true; } else { @@ -918,6 +928,8 @@ static bool data_transfer_layersmapping_generate( else if (cddata_type == CD_FAKE_LNOR) { /* Preprocess should have generated it, Postprocess will convert it back to CD_CUSTOMLOOPNORMAL. */ cddata_type = CD_NORMAL; + interp_data = space_transform; + interp = customdata_data_transfer_interp_normal_normals; } if (!(cddata_type & CD_FAKE)) { @@ -927,7 +939,8 @@ static bool data_transfer_layersmapping_generate( if (!data_transfer_layersmapping_cdlayers( r_map, cddata_type, mix_mode, mix_factor, mix_weights, num_elem_dst, use_create, use_delete, cd_src, cd_dst, dm_dst != NULL, - fromlayers, tolayers)) + fromlayers, tolayers, + interp, interp_data)) { /* We handle specific source selection cases here. */ return false; @@ -950,7 +963,8 @@ static bool data_transfer_layersmapping_generate( if (!data_transfer_layersmapping_cdlayers( r_map, cddata_type, mix_mode, mix_factor, mix_weights, num_elem_dst, use_create, use_delete, cd_src, cd_dst, dm_dst != NULL, - fromlayers, tolayers)) + fromlayers, tolayers, + interp, interp_data)) { /* We handle specific source selection cases here. */ return false; @@ -969,7 +983,7 @@ static bool data_transfer_layersmapping_generate( dm_dst ? dm_dst->getPolyArray(dm_dst) : me_dst->mpoly, dm_src->getNumPolys(dm_src), dm_dst ? dm_dst->getNumPolys(dm_dst) : me_dst->totpoly, - elem_size, data_size, data_offset, data_flag, NULL); + elem_size, data_size, data_offset, data_flag, NULL, interp_data); return true; } else { @@ -1035,28 +1049,28 @@ void BKE_object_data_transfer_layout( data_transfer_layersmapping_generate( NULL, ob_src, ob_dst, dm_src, NULL, me_dst, ME_VERT, cddata_type, 0, 0.0f, NULL, - num_elem_dst, use_create, use_delete, fromlayers, tolayers); + num_elem_dst, use_create, use_delete, fromlayers, tolayers, NULL); } if (DT_DATATYPE_IS_EDGE(dtdata_type)) { const int num_elem_dst = me_dst->totedge; data_transfer_layersmapping_generate( NULL, ob_src, ob_dst, dm_src, NULL, me_dst, ME_EDGE, cddata_type, 0, 0.0f, NULL, - num_elem_dst, use_create, use_delete, fromlayers, tolayers); + num_elem_dst, use_create, use_delete, fromlayers, tolayers, NULL); } if (DT_DATATYPE_IS_LOOP(dtdata_type)) { const int num_elem_dst = me_dst->totloop; data_transfer_layersmapping_generate( NULL, ob_src, ob_dst, dm_src, NULL, me_dst, ME_LOOP, cddata_type, 0, 0.0f, NULL, - num_elem_dst, use_create, use_delete, fromlayers, tolayers); + num_elem_dst, use_create, use_delete, fromlayers, tolayers, NULL); } if (DT_DATATYPE_IS_POLY(dtdata_type)) { const int num_elem_dst = me_dst->totpoly; data_transfer_layersmapping_generate( NULL, ob_src, ob_dst, dm_src, NULL, me_dst, ME_POLY, cddata_type, 0, 0.0f, NULL, - num_elem_dst, use_create, use_delete, fromlayers, tolayers); + num_elem_dst, use_create, use_delete, fromlayers, tolayers, NULL); } } } @@ -1198,7 +1212,7 @@ bool BKE_object_data_transfer_dm( if (data_transfer_layersmapping_generate( &lay_map, ob_src, ob_dst, dm_src, dm_dst, me_dst, ME_VERT, cddata_type, mix_mode, mix_factor, weights[VDATA], - num_verts_dst, use_create, use_delete, fromlayers, tolayers)) + num_verts_dst, use_create, use_delete, fromlayers, tolayers, space_transform)) { CustomDataTransferLayerMap *lay_mapit; @@ -1249,7 +1263,7 @@ bool BKE_object_data_transfer_dm( if (data_transfer_layersmapping_generate( &lay_map, ob_src, ob_dst, dm_src, dm_dst, me_dst, ME_EDGE, cddata_type, mix_mode, mix_factor, weights[EDATA], - num_edges_dst, use_create, use_delete, fromlayers, tolayers)) + num_edges_dst, use_create, use_delete, fromlayers, tolayers, space_transform)) { CustomDataTransferLayerMap *lay_mapit; @@ -1312,7 +1326,7 @@ bool BKE_object_data_transfer_dm( if (data_transfer_layersmapping_generate( &lay_map, ob_src, ob_dst, dm_src, dm_dst, me_dst, ME_LOOP, cddata_type, mix_mode, mix_factor, weights[LDATA], - num_loops_dst, use_create, use_delete, fromlayers, tolayers)) + num_loops_dst, use_create, use_delete, fromlayers, tolayers, space_transform)) { CustomDataTransferLayerMap *lay_mapit; @@ -1367,7 +1381,7 @@ bool BKE_object_data_transfer_dm( if (data_transfer_layersmapping_generate( &lay_map, ob_src, ob_dst, dm_src, dm_dst, me_dst, ME_POLY, cddata_type, mix_mode, mix_factor, weights[PDATA], - num_polys_dst, use_create, use_delete, fromlayers, tolayers)) + num_polys_dst, use_create, use_delete, fromlayers, tolayers, space_transform)) { CustomDataTransferLayerMap *lay_mapit; diff --git a/source/blender/blenkernel/intern/data_transfer_intern.h b/source/blender/blenkernel/intern/data_transfer_intern.h index 501b749b464..352eedc6ec2 100644 --- a/source/blender/blenkernel/intern/data_transfer_intern.h +++ b/source/blender/blenkernel/intern/data_transfer_intern.h @@ -45,7 +45,7 @@ void data_transfer_layersmapping_add_item( const float mix_factor, const float *mix_weights, const void *data_src, void *data_dst, const int data_src_n, const int data_dst_n, const size_t elem_size, const size_t data_size, const size_t data_offset, const uint64_t data_flag, - cd_datatransfer_interp interp); + cd_datatransfer_interp interp, void *interp_data); /* Type-specific. */ @@ -55,4 +55,10 @@ bool data_transfer_layersmapping_vgroups( struct Object *ob_src, struct Object *ob_dst, struct CustomData *cd_src, struct CustomData *cd_dst, const bool use_dupref_dst, const int fromlayers, const int tolayers); +/* Defined in customdata.c */ +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); + #endif /* __DATA_TRANSFER_INTERN_H__ */ diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index 6670c3359d7..f904369ae97 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -1163,7 +1163,7 @@ static bool data_transfer_layersmapping_vgroups_multisrc_to_dst( } data_transfer_layersmapping_add_item(r_map, CD_FAKE_MDEFORMVERT, mix_mode, mix_factor, mix_weights, data_src, data_dst, idx_src, idx_src, - elem_size, 0, 0, 0, vgroups_datatransfer_interp); + elem_size, 0, 0, 0, vgroups_datatransfer_interp, NULL); } } break; @@ -1211,7 +1211,7 @@ static bool data_transfer_layersmapping_vgroups_multisrc_to_dst( data_transfer_layersmapping_add_item( r_map, CD_FAKE_MDEFORMVERT, mix_mode, mix_factor, mix_weights, data_src, data_dst, idx_src, idx_dst, - elem_size, 0, 0, 0, vgroups_datatransfer_interp); + elem_size, 0, 0, 0, vgroups_datatransfer_interp, NULL); } } break; @@ -1317,7 +1317,7 @@ bool data_transfer_layersmapping_vgroups( data_transfer_layersmapping_add_item(r_map, CD_FAKE_MDEFORMVERT, mix_mode, mix_factor, mix_weights, data_src, data_dst, idx_src, idx_dst, - elem_size, 0, 0, 0, vgroups_datatransfer_interp); + elem_size, 0, 0, 0, vgroups_datatransfer_interp, NULL); } } else { |