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... :/
This commit is contained in:
parent
a88ae6fa70
commit
8172712841
Notes:
blender-bot
2023-02-14 08:31:12 +01:00
Referenced by issue #46508, data_transfer modifier has no effect when called "in a dependency chain"
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue