diff --git a/source/blender/blenkernel/BKE_mesh_mapping.h b/source/blender/blenkernel/BKE_mesh_mapping.h index 3c5377d7bf6..ee9e63e6975 100644 --- a/source/blender/blenkernel/BKE_mesh_mapping.h +++ b/source/blender/blenkernel/BKE_mesh_mapping.h @@ -117,6 +117,10 @@ void BKE_mesh_edge_poly_map_create( const struct MEdge *medge, const int totedge, const struct MPoly *mpoly, const int totpoly, const struct MLoop *mloop, const int totloop); +void BKE_mesh_origindex_map_create( + MeshElemMap **r_map, int **r_mem, + const int totorig, + const int *final_origindex, const int totfinal); /* smoothgroups */ int *BKE_mesh_calc_smoothgroups( diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c index cbf4b4906f5..94f29b5b1a4 100644 --- a/source/blender/blenkernel/intern/mesh_mapping.c +++ b/source/blender/blenkernel/intern/mesh_mapping.c @@ -36,6 +36,7 @@ #include "BLI_math.h" #include "BKE_mesh_mapping.h" +#include "BKE_customdata.h" #include "BLI_strict_flags.h" @@ -289,6 +290,58 @@ void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map, int **r_mem, *r_mem = indices; } +/** + * This function creates a map so the source-data (vert/edge/loop/poly) + * can loop over the destination data (using the destination arrays origindex). + * + * This has the advantage that it can operate on any data-types. + * + * \param totsource The total number of elements the that \a final_origindex points to. + * \param totfinal The size of \a final_origindex + * \param final_origindex The size of the final array. + * + * \note ``totsource`` could be ``totpoly``, + * ``totfinal`` could be ``tottessface`` and ``final_origindex`` its ORIGINDEX customdata. + * This would allow an MPoly to loop over its tessfaces. + */ +void BKE_mesh_origindex_map_create(MeshElemMap **r_map, int **r_mem, + const int totsource, + const int *final_origindex, const int totfinal) +{ + MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * (size_t)totsource, "poly-tessface map"); + int *indices = MEM_mallocN(sizeof(int) * (size_t)totfinal, "poly-tessface map mem"); + int *index_step; + int i; + + /* count face users */ + for (i = 0; i < totfinal; i++) { + if (final_origindex[i] != ORIGINDEX_NONE) { + BLI_assert(final_origindex[i] < totsource); + map[final_origindex[i]].count++; + } + } + + /* create offsets */ + index_step = indices; + for (i = 0; i < totsource; i++) { + map[i].indices = index_step; + index_step += map[i].count; + + /* re-count, using this as an index below */ + map[i].count = 0; + } + + /* assign poly-tessface users */ + for (i = 0; i < totfinal; i++) { + if (final_origindex[i] != ORIGINDEX_NONE) { + MeshElemMap *map_ele = &map[final_origindex[i]]; + map_ele->indices[map_ele->count++] = i; + } + } + + *r_map = map; + *r_mem = indices; +} /** \} */ diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 9d7bad2591e..31a344da4a1 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -56,6 +56,7 @@ #include "BKE_depsgraph.h" #include "BKE_deform.h" #include "BKE_mesh.h" +#include "BKE_mesh_mapping.h" #include "BKE_modifier.h" #include "BKE_object.h" #include "BKE_object_deform.h" @@ -2756,11 +2757,11 @@ typedef struct VPaintData { /* modify 'me->mcol' directly, since the derived mesh is drawing from this * array, otherwise we need to refresh the modifier stack */ - int use_fast_update; + bool use_fast_update; /* mpoly -> mface mapping */ - MemArena *polyfacemap_arena; - ListBase *polyfacemap; + MeshElemMap *polyfacemap; + void *polyfacemap_mem; /* loops tagged as having been painted, to apply shared vertex color * blending only to modified loops */ @@ -2772,31 +2773,19 @@ typedef struct VPaintData { static void vpaint_build_poly_facemap(struct VPaintData *vd, Mesh *me) { - MFace *mf; - PolyFaceMap *e; - int *origIndex; - int i; + const int *tessface_origindex; - vd->polyfacemap_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "vpaint tmp"); - BLI_memarena_use_calloc(vd->polyfacemap_arena); + vd->polyfacemap = NULL; + vd->polyfacemap_mem = NULL; - vd->polyfacemap = BLI_memarena_alloc(vd->polyfacemap_arena, sizeof(ListBase) * me->totpoly); + tessface_origindex = CustomData_get_layer(&me->fdata, CD_ORIGINDEX); - origIndex = CustomData_get_layer(&me->fdata, CD_ORIGINDEX); - mf = me->mface; - - if (!origIndex) + if (!tessface_origindex) return; - for (i = 0; i < me->totface; i++, mf++, origIndex++) { - if (*origIndex == ORIGINDEX_NONE) - continue; - - e = BLI_memarena_alloc(vd->polyfacemap_arena, sizeof(PolyFaceMap)); - e->facenr = i; - - BLI_addtail(&vd->polyfacemap[*origIndex], e); - } + BKE_mesh_origindex_map_create(&vd->polyfacemap, (int **)&vd->polyfacemap_mem, + me->totpoly, + tessface_origindex, me->totface); } static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const float UNUSED(mouse[2])) @@ -2868,6 +2857,15 @@ static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const fl return 1; } +BLI_INLINE int mesh_tessface_vertex_index(MFace *tessface, unsigned int v) +{ + if (tessface->v1 == v) return 0; + if (tessface->v2 == v) return 1; + if (tessface->v3 == v) return 2; + if (v && (tessface->v4 == v)) return 3; + return -1; +} + static void vpaint_paint_poly(VPaint *vp, VPaintData *vpd, Mesh *me, const unsigned int index, const float mval[2], const float brush_size_pressure, const float brush_alpha_pressure) @@ -2879,7 +2877,6 @@ static void vpaint_paint_poly(VPaint *vp, VPaintData *vpd, Mesh *me, MCol *mc; MLoop *ml; MLoopCol *mlc; - PolyFaceMap *e; unsigned int *lcol = ((unsigned int *)me->mloopcol) + mpoly->loopstart; unsigned int *lcolorig = ((unsigned int *)vp->vpaint_prev) + mpoly->loopstart; bool *mlooptag = (vpd->mlooptag) ? vpd->mlooptag + mpoly->loopstart : NULL; @@ -2942,31 +2939,28 @@ static void vpaint_paint_poly(VPaint *vp, VPaintData *vpd, Mesh *me, } if (vpd->use_fast_update) { + const MeshElemMap *map = &vpd->polyfacemap[index]; + /* update vertex colors for tessellations incrementally, * rather then regenerating the tessellation altogether */ - for (e = vpd->polyfacemap[index].first; e; e = e->next) { - mf = &me->mface[e->facenr]; - mc = &me->mcol[e->facenr * 4]; - mftag = &vpd->mfacetag[e->facenr * 4]; + for (i = 0; i < map->count; i++) { + const int index_tessface = map->indices[i]; + + mf = &me->mface[index_tessface]; + mc = &me->mcol[index_tessface * 4]; + mftag = &vpd->mfacetag[index_tessface * 4]; ml = me->mloop + mpoly->loopstart; mlc = me->mloopcol + mpoly->loopstart; + for (j = 0; j < totloop; j++, ml++, mlc++) { - if (ml->v == mf->v1) { - MESH_MLOOPCOL_TO_MCOL(mlc, mc + 0); - if (mlooptag) mftag[0] = mlooptag[j]; - } - else if (ml->v == mf->v2) { - MESH_MLOOPCOL_TO_MCOL(mlc, mc + 1); - if (mlooptag) mftag[1] = mlooptag[j]; - } - else if (ml->v == mf->v3) { - MESH_MLOOPCOL_TO_MCOL(mlc, mc + 2); - if (mlooptag) mftag[2] = mlooptag[j]; - } - else if (mf->v4 && ml->v == mf->v4) { - MESH_MLOOPCOL_TO_MCOL(mlc, mc + 3); - if (mlooptag) mftag[3] = mlooptag[j]; + /* search for the loop vertex within the tessface */ + const int fidx = mesh_tessface_vertex_index(mf, ml->v); + if (fidx != -1) { + MESH_MLOOPCOL_TO_MCOL(mlc, mc + fidx); + if (mlooptag) { + mftag[fidx] = mlooptag[j]; + } } } } @@ -3078,8 +3072,12 @@ static void vpaint_stroke_done(const bContext *C, struct PaintStroke *stroke) /* frees prev buffer */ copy_vpaint_prev(ts->vpaint, NULL, 0); - if (vpd->polyfacemap_arena) { - BLI_memarena_free(vpd->polyfacemap_arena); + if (vpd->polyfacemap) { + MEM_freeN(vpd->polyfacemap); + } + + if (vpd->polyfacemap_mem) { + MEM_freeN(vpd->polyfacemap_mem); } if (vpd->mlooptag)