Mesh API: Add BKE_mesh_origindex_map_create

This API function lets original data loop over its derived data,
Use for vertex paint, replacing custom function.
This commit is contained in:
Campbell Barton 2013-12-12 17:11:27 +11:00
parent e23f77b935
commit ab127c12d4
3 changed files with 100 additions and 45 deletions

View File

@ -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(

View File

@ -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;
}
/** \} */

View File

@ -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)