diff options
Diffstat (limited to 'source/blender/blenkernel/intern/data_transfer.c')
-rw-r--r-- | source/blender/blenkernel/intern/data_transfer.c | 144 |
1 files changed, 136 insertions, 8 deletions
diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c index d41c74770f1..5ac7b928d96 100644 --- a/source/blender/blenkernel/intern/data_transfer.c +++ b/source/blender/blenkernel/intern/data_transfer.c @@ -47,6 +47,7 @@ #include "BKE_data_transfer.h" #include "BKE_deform.h" #include "BKE_DerivedMesh.h" +#include "BKE_mesh.h" #include "BKE_mesh_mapping.h" #include "BKE_mesh_remap.h" #include "BKE_object.h" @@ -79,6 +80,9 @@ CustomDataMask BKE_object_data_transfer_dttypes_to_cdmask(const int dtdata_types else if (cddata_type == CD_FAKE_UV) { cddata_mask |= CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV; } + else if (cddata_type == CD_FAKE_LNOR) { + cddata_mask |= CD_MASK_NORMAL | CD_MASK_CUSTOMLOOPNORMAL; + } } return cddata_mask; @@ -143,6 +147,10 @@ bool BKE_object_data_transfer_get_dttypes_capacity( *r_threshold = true; ret = true; break; + case DT_TYPE_LNOR: + *r_advanced_mixing = true; + ret = true; + break; case DT_TYPE_SHARP_FACE: *r_threshold = true; ret = true; @@ -217,6 +225,8 @@ int BKE_object_data_transfer_dttype_to_cdtype(const int dtdata_type) case DT_TYPE_VCOL: return CD_MLOOPCOL; + case DT_TYPE_LNOR: + return CD_FAKE_LNOR; default: BLI_assert(0); @@ -242,6 +252,105 @@ int BKE_object_data_transfer_dttype_to_srcdst_index(const int dtdata_type) /* ********** */ +/* Generic pre/post processing, only used by custom loop normals currently. */ + +static void data_transfer_dtdata_type_preprocess( + Object *UNUSED(ob_src), Object *UNUSED(ob_dst), DerivedMesh *dm_src, DerivedMesh *dm_dst, Mesh *me_dst, + const int dtdata_type, const bool dirty_nors_dst, const bool use_split_nors_src, const float split_angle_src) +{ + if (dtdata_type == DT_TYPE_LNOR) { + /* Compute custom normals into regular loop normals, which will be used for the transfer. */ + MVert *verts_dst = dm_dst ? dm_dst->getVertArray(dm_dst) : me_dst->mvert; + const int num_verts_dst = dm_dst ? dm_dst->getNumVerts(dm_dst) : me_dst->totvert; + MEdge *edges_dst = dm_dst ? dm_dst->getEdgeArray(dm_dst) : me_dst->medge; + const int num_edges_dst = dm_dst ? dm_dst->getNumEdges(dm_dst) : me_dst->totedge; + MPoly *polys_dst = dm_dst ? dm_dst->getPolyArray(dm_dst) : me_dst->mpoly; + const int num_polys_dst = dm_dst ? dm_dst->getNumPolys(dm_dst) : me_dst->totpoly; + MLoop *loops_dst = dm_dst ? dm_dst->getLoopArray(dm_dst) : me_dst->mloop; + const int num_loops_dst = dm_dst ? dm_dst->getNumLoops(dm_dst) : me_dst->totloop; + CustomData *pdata_dst = dm_dst ? dm_dst->getPolyDataLayout(dm_dst) : &me_dst->pdata; + CustomData *ldata_dst = dm_dst ? dm_dst->getLoopDataLayout(dm_dst) : &me_dst->ldata; + + const bool use_split_nors_dst = (me_dst->flag & ME_AUTOSMOOTH) != 0; + const float split_angle_dst = me_dst->smoothresh; + + dm_src->calcLoopNormals(dm_src, use_split_nors_src, split_angle_src); + + if (dm_dst) { + dm_dst->calcLoopNormals(dm_dst, use_split_nors_dst, split_angle_dst); + } + else { + float (*poly_nors_dst)[3]; + float (*loop_nors_dst)[3]; + short (*custom_nors_dst)[2] = CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL); + + /* Cache poly nors into a temp CDLayer. */ + poly_nors_dst = CustomData_get_layer(pdata_dst, CD_NORMAL); + if (dirty_nors_dst || !poly_nors_dst) { + if (!poly_nors_dst) { + poly_nors_dst = CustomData_add_layer(pdata_dst, CD_NORMAL, CD_CALLOC, NULL, num_polys_dst); + CustomData_set_layer_flag(pdata_dst, CD_NORMAL, CD_FLAG_TEMPORARY); + } + BKE_mesh_calc_normals_poly(verts_dst, num_verts_dst, loops_dst, polys_dst, + num_loops_dst, num_polys_dst, poly_nors_dst, true); + } + /* Cache loop nors into a temp CDLayer. */ + loop_nors_dst = CustomData_get_layer(ldata_dst, CD_NORMAL); + if (dirty_nors_dst || loop_nors_dst) { + if (!loop_nors_dst) { + loop_nors_dst = CustomData_add_layer(ldata_dst, CD_NORMAL, CD_CALLOC, NULL, num_loops_dst); + CustomData_set_layer_flag(ldata_dst, CD_NORMAL, CD_FLAG_TEMPORARY); + } + BKE_mesh_normals_loop_split(verts_dst, num_verts_dst, edges_dst, num_edges_dst, + loops_dst, loop_nors_dst, num_loops_dst, + polys_dst, (const float (*)[3])poly_nors_dst, num_polys_dst, + use_split_nors_dst, split_angle_dst, NULL, custom_nors_dst, NULL); + } + } + } +} + +static void data_transfer_dtdata_type_postprocess( + Object *UNUSED(ob_src), Object *UNUSED(ob_dst), DerivedMesh *UNUSED(dm_src), DerivedMesh *dm_dst, Mesh *me_dst, + const int dtdata_type, const bool changed) +{ + if (dtdata_type == DT_TYPE_LNOR) { + /* Bake edited destination loop normals into custom normals again. */ + MVert *verts_dst = dm_dst ? dm_dst->getVertArray(dm_dst) : me_dst->mvert; + const int num_verts_dst = dm_dst ? dm_dst->getNumVerts(dm_dst) : me_dst->totvert; + MEdge *edges_dst = dm_dst ? dm_dst->getEdgeArray(dm_dst) : me_dst->medge; + const int num_edges_dst = dm_dst ? dm_dst->getNumEdges(dm_dst) : me_dst->totedge; + MPoly *polys_dst = dm_dst ? dm_dst->getPolyArray(dm_dst) : me_dst->mpoly; + const int num_polys_dst = dm_dst ? dm_dst->getNumPolys(dm_dst) : me_dst->totpoly; + MLoop *loops_dst = dm_dst ? dm_dst->getLoopArray(dm_dst) : me_dst->mloop; + const int num_loops_dst = dm_dst ? dm_dst->getNumLoops(dm_dst) : me_dst->totloop; + CustomData *pdata_dst = dm_dst ? dm_dst->getPolyDataLayout(dm_dst) : &me_dst->pdata; + CustomData *ldata_dst = dm_dst ? dm_dst->getLoopDataLayout(dm_dst) : &me_dst->ldata; + + const float (*poly_nors_dst)[3] = CustomData_get_layer(pdata_dst, CD_NORMAL); + float (*loop_nors_dst)[3] = CustomData_get_layer(ldata_dst, CD_NORMAL); + short (*custom_nors_dst)[2] = CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL); + + BLI_assert(poly_nors_dst); + + if (!changed) { + return; + } + + if (!custom_nors_dst) { + custom_nors_dst = CustomData_add_layer(ldata_dst, CD_CUSTOMLOOPNORMAL, CD_CALLOC, NULL, num_loops_dst); + } + + /* Note loop_nors_dst contains our custom normals as transferred from source... */ + BKE_mesh_normals_loop_custom_set(verts_dst, num_verts_dst, edges_dst, num_edges_dst, + loops_dst, loop_nors_dst, num_loops_dst, + polys_dst, poly_nors_dst, num_polys_dst, + custom_nors_dst); + } +} + +/* ********** */ + static MeshRemapIslandsCalc data_transfer_get_loop_islands_generator(const int cddata_type) { switch (cddata_type) { @@ -690,13 +799,19 @@ static bool data_transfer_layersmapping_generate( return true; } else if (cddata_type == CD_FAKE_MDEFORMVERT) { + bool ret; + cd_src = dm_src->getVertDataLayout(dm_src); cd_dst = dm_dst ? dm_dst->getVertDataLayout(dm_dst) : &me_dst->vdata; - return data_transfer_layersmapping_vgroups(r_map, mix_mode, mix_factor, mix_weights, - num_elem_dst, use_create, use_delete, - ob_src, ob_dst, cd_src, cd_dst, dm_dst != NULL, - fromlayers, tolayers); + ret = data_transfer_layersmapping_vgroups(r_map, mix_mode, mix_factor, mix_weights, + num_elem_dst, use_create, use_delete, + ob_src, ob_dst, cd_src, cd_dst, dm_dst != NULL, + fromlayers, tolayers); + + /* Mesh stores its dvert in a specific pointer too. :( */ + me_dst->dvert = CustomData_get_layer(&me_dst->vdata, CD_MDEFORMVERT); + return ret; } else if (cddata_type == CD_FAKE_SHAPEKEY) { /* TODO: leaving shapekeys asside for now, quite specific case, since we can't access them from MVert :/ */ @@ -799,6 +914,10 @@ static bool data_transfer_layersmapping_generate( if (cddata_type == CD_FAKE_UV) { cddata_type = CD_MLOOPUV; } + else if (cddata_type == CD_FAKE_LNOR) { + /* Preprocess should have generated it, Postprocess will convert it back to CD_CUSTOMLOOPNORMAL. */ + cddata_type = CD_NORMAL; + } if (!(cddata_type & CD_FAKE)) { cd_src = dm_src->getLoopDataLayout(dm_src); @@ -957,7 +1076,7 @@ bool BKE_object_data_transfer_dm( #define DATAMAX 4 DerivedMesh *dm_src; - Mesh *me_dst; + Mesh *me_dst, *me_src; bool dirty_nors_dst = true; /* Assumed always true if not using a dm as destination. */ int i; @@ -967,7 +1086,7 @@ bool BKE_object_data_transfer_dm( MeshPairRemap geom_map[DATAMAX] = {{0}}; bool geom_map_init[DATAMAX] = {0}; - ListBase lay_map = {0}; + ListBase lay_map = {NULL}; bool changed = false; const bool use_delete = false; /* We never delete data layers from destination here. */ @@ -977,6 +1096,7 @@ bool BKE_object_data_transfer_dm( BLI_assert((ob_src != ob_dst) && (ob_src->type == OB_MESH) && (ob_dst->type == OB_MESH)); me_dst = ob_dst->data; + me_src = ob_src->data; if (dm_dst) { dirty_nors_dst = (dm_dst->dirty & DM_DIRTY_NORMALS) != 0; use_create = false; /* Never create needed custom layers on DM (modifier case). */ @@ -1016,6 +1136,10 @@ bool BKE_object_data_transfer_dm( continue; } + data_transfer_dtdata_type_preprocess(ob_src, ob_dst, dm_src, dm_dst, me_dst, + dtdata_type, dirty_nors_dst, + (me_src->flag & ME_AUTOSMOOTH) != 0, me_src->smoothresh); + cddata_type = BKE_object_data_transfer_dttype_to_cdtype(dtdata_type); fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(dtdata_type); @@ -1133,8 +1257,10 @@ bool BKE_object_data_transfer_dm( map_loop_mode, space_transform, max_distance, ray_radius, verts_dst, num_verts_dst, edges_dst, num_edges_dst, loops_dst, num_loops_dst, polys_dst, num_polys_dst, - ldata_dst, pdata_dst, me_dst->smoothresh, dirty_nors_dst, - dm_src, island_callback, islands_handling_precision, &geom_map[LDATA]); + ldata_dst, pdata_dst, + (me_dst->flag & ME_AUTOSMOOTH) != 0, me_dst->smoothresh, dirty_nors_dst, + dm_src, (me_src->flag & ME_AUTOSMOOTH) != 0, me_src->smoothresh, + island_callback, islands_handling_precision, &geom_map[LDATA]); geom_map_init[LDATA] = true; } @@ -1208,6 +1334,8 @@ bool BKE_object_data_transfer_dm( BLI_freelistN(&lay_map); } } + + data_transfer_dtdata_type_postprocess(ob_src, ob_dst, dm_src, dm_dst, me_dst, dtdata_type, changed); } for (i = 0; i < DATAMAX; i++) { |