svn merge ^/trunk/blender -r40368:40370
authorCampbell Barton <ideasman42@gmail.com>
Thu, 22 Sep 2011 16:17:27 +0000 (16:17 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Thu, 22 Sep 2011 16:17:27 +0000 (16:17 +0000)
1  2 
source/blender/editors/sculpt_paint/paint_utils.c
source/blender/editors/sculpt_paint/paint_vertex.c

index bed482e6a5824c07ae753f53a586f84ad59c0530,d332dc6ec0d84a79d77fba61dded5e13513b5f62..9e929ba7070dd9eebd4d28b3661e87fc373e587e
@@@ -1,5 -1,5 +1,5 @@@
  /*
-  * $Id:
+  * $Id$
   *
   * ***** BEGIN GPL LICENSE BLOCK *****
   *
@@@ -180,9 -180,9 +180,9 @@@ static void imapaint_tri_weights(Objec
  void imapaint_pick_uv(Scene *scene, Object *ob, unsigned int faceindex, const int xy[2], float uv[2])
  {
        DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
 -      const int *index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
 -      MTFace *tface = dm->getFaceDataArray(dm, CD_MTFACE), *tf;
 -      int numfaces = dm->getNumFaces(dm), a, findex;
 +      const int *index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
 +      MTFace *tface = dm->getTessFaceDataArray(dm, CD_MTFACE), *tf;
 +      int numfaces = dm->getNumTessFaces(dm), a, findex;
        float p[2], w[3], absw, minabsw;
        MFace mf;
        MVert mv[4];
                findex= index ? index[a]: a;
  
                if(findex == faceindex) {
 -                      dm->getFace(dm, a, &mf);
 +                      dm->getTessFace(dm, a, &mf);
  
                        dm->getVert(dm, mf.v1, &mv[0]);
                        dm->getVert(dm, mf.v2, &mv[1]);
index 48c53dcef0ce4ce83f42827ba34a57a1eb8e15c2,9ae7278ebc0460f81582fa278fda020989f64f5b..901772247fe6d1518b1c9a5987efcf8974e41765
@@@ -45,7 -45,6 +45,7 @@@
  
  #include "BLI_blenlib.h"
  #include "BLI_math.h"
 +#include "BLI_memarena.h"
  #include "BLI_utildefines.h"
  #include "BLI_ghash.h"
  
@@@ -200,7 -199,7 +200,7 @@@ unsigned int vpaint_get_current_col(VPa
        return rgba_to_mcol(brush->rgb[0], brush->rgb[1], brush->rgb[2], 1.0f);
  }
  
 -static void do_shared_vertexcol(Mesh *me)
 +static void do_shared_vertex_tesscol(Mesh *me)
  {
        /* if no mcol: do not do */
        /* if tface: only the involved faces, otherwise all */
        MEM_freeN(scolmain);
  }
  
 +void do_shared_vertexcol(Mesh *me)
 +{
 +      MLoop *ml = me->mloop;
 +      MLoopCol *lcol = me->mloopcol;
 +      MTexPoly *mtp = me->mtpoly;
 +      MPoly *mp = me->mpoly;
 +      float (*scol)[5];
 +      int i;
 +
 +      /* if no mloopcol: do not do */
 +      /* if mtexpoly: only the involved faces, otherwise all */
 +
 +      if(me->mloopcol==0 || me->totvert==0 || me->totpoly==0) return;
 +
 +      scol = MEM_callocN(sizeof(float)*me->totvert*5, "scol");
 +
 +      for (i=0; i<me->totloop; i++, ml++, lcol++) {
 +              if (i >= mp->loopstart + mp->totloop) {
 +                      mp++;
 +                      if (mtp) mtp++;
 +              }
 +
 +              if (mtp && !(mtp->mode & TF_SHAREDCOL))
 +                      continue;
 +
 +              scol[ml->v][0] += lcol->r;
 +              scol[ml->v][1] += lcol->g;
 +              scol[ml->v][2] += lcol->b;
 +              scol[ml->v][3] += lcol->a;
 +              scol[ml->v][4] += 1.0;
 +      }
 +      
 +      for (i=0; i<me->totvert; i++) {
 +              if (!scol[i][4]) continue;
 +
 +              scol[i][0] /= scol[i][4];
 +              scol[i][1] /= scol[i][4];
 +              scol[i][2] /= scol[i][4];
 +              scol[i][3] /= scol[i][4];
 +      }
 +      
 +      ml = me->mloop;
 +      lcol = me->mloopcol;
 +      for (i=0; i<me->totloop; i++, ml++, lcol++) {
 +              if (!scol[ml->v][4]) continue;
 +
 +              lcol->r = scol[ml->v][0];
 +              lcol->g = scol[ml->v][1];
 +              lcol->b = scol[ml->v][2];
 +              lcol->a = scol[ml->v][3];
 +      }
 +
 +      MEM_freeN(scol);
 +
 +      do_shared_vertex_tesscol(me);
 +}
 +
  static void make_vertexcol(Object *ob)        /* single ob */
  {
        Mesh *me;
        if(!ob || ob->id.lib) return;
        me= get_mesh(ob);
        if(me==NULL) return;
 -      if(me->edit_mesh) return;
 +      if(me->edit_btmesh) return;
  
        /* copies from shadedisplist to mcol */
 -      if(!me->mcol) {
 -              CustomData_add_layer(&me->fdata, CD_MCOL, CD_CALLOC, NULL, me->totface);
 -              mesh_update_customdata_pointers(me);
 -      }
 +      if(!me->mcol)
 +              CustomData_add_layer(&me->fdata, CD_MCOL, CD_DEFAULT, NULL, me->totface);
 +      if (!me->mloopcol)
 +              CustomData_add_layer(&me->ldata, CD_MLOOPCOL, CD_DEFAULT, NULL, me->totloop);
 +      
 +      mesh_update_customdata_pointers(me);
  
        //if(shade)
        //      shadeMeshMCol(scene, ob, me);
@@@ -386,7 -326,7 +386,7 @@@ static void wpaint_mirror_vgroup_ensure
        *vgroup_mirror= -1;
  }
  
 -static void copy_vpaint_prev(VPaint *vp, unsigned int *mcol, int tot)
 +static void copy_vpaint_prev(VPaint *vp, unsigned int *lcol, int tot)
  {
        if(vp->vpaint_prev) {
                MEM_freeN(vp->vpaint_prev);
        }
        vp->tot= tot;   
        
 -      if(mcol==NULL || tot==0) return;
 +      if(lcol==NULL || tot==0) return;
        
 -      vp->vpaint_prev= MEM_mallocN(4*sizeof(int)*tot, "vpaint_prev");
 -      memcpy(vp->vpaint_prev, mcol, 4*sizeof(int)*tot);
 +      vp->vpaint_prev= MEM_mallocN(sizeof(int)*tot, "vpaint_prev");
 +      memcpy(vp->vpaint_prev, lcol, sizeof(int)*tot);
        
  }
  
@@@ -420,11 -360,9 +420,11 @@@ static void copy_wpaint_prev (VPaint *w
  void vpaint_fill(Object *ob, unsigned int paintcol)
  {
        Mesh *me;
 -      MFace *mf;
 +      MFace *mf;
 +      MPoly *mp;
 +      MLoopCol *lcol;
        unsigned int *mcol;
 -      int i, selected;
 +      int i, j, selected;
  
        me= get_mesh(ob);
        if(me==NULL || me->totface==0) return;
                        mcol[3] = paintcol;
                }
        }
 +
 +      mp = me->mpoly;
 +      lcol = me->mloopcol;
 +      for (i=0; i<me->totpoly; i++, mp++) {
 +              if (!(!selected || mp->flag & ME_FACE_SEL))
 +                      continue;
 +
 +              lcol = me->mloopcol + mp->loopstart;
 +              for (j=0; j<mp->totloop; j++, lcol++) {
 +                      *(int*)lcol = paintcol;
 +              }
 +      }
        
        DAG_id_tag_update(&me->id, 0);
  }
@@@ -529,7 -455,7 +529,7 @@@ void wpaint_fill(VPaint *wp, Object *ob
                                                dw->weight= paintweight;
                                                
                                                if(me->editflag & ME_EDIT_MIRROR_X) {   /* x mirror painting */
 -                                                      int j= mesh_get_x_mirror_vert(ob, faceverts[i]);
 +                                                      int j= -1; //BMESH_TODO mesh_get_x_mirror_vert(ob, faceverts[i]);
                                                        if(j>=0) {
                                                                /* copy, not paint again */
                                                                if(vgroup_mirror != -1) {
@@@ -965,7 -891,6 +965,7 @@@ static void wpaint_blend(VPaint *wp, MD
  
  /* sets wp->weight to the closest weight value to vertex */
  /* note: we cant sample frontbuf, weight colors are interpolated too unpredictable */
 +#if 0// BMESH_TODO
  static int weight_sample_invoke(bContext *C, wmOperator *op, wmEvent *event)
  {
        ViewContext vc;
                return OPERATOR_CANCELLED;
        }
  }
 +#endif
  
  void PAINT_OT_weight_sample(wmOperatorType *ot)
  {
        ot->idname= "PAINT_OT_weight_sample";
  
        /* api callbacks */
 +#if 0 // BMESH_TODO
        ot->invoke= weight_sample_invoke;
 +#endif
        ot->poll= weight_paint_mode_poll;
  
        /* flags */
  }
  
  /* samples cursor location, and gives menu with vertex groups to activate */
 +#if 0 // BMESH_TODO
  static EnumPropertyItem *weight_paint_sample_enum_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
  {
        if (C) {
  
        return DummyRNA_NULL_items;
  }
 +#endif
  
  static int weight_sample_group_exec(bContext *C, wmOperator *op)
  {
@@@ -1152,13 -1072,12 +1152,13 @@@ void PAINT_OT_weight_sample_group(wmOpe
  
        /* keyingset to use (dynamic enum) */
        prop= RNA_def_enum(ot->srna, "group", DummyRNA_DEFAULT_items, 0, "Keying Set", "The Keying Set to use");
 +#if 0 // BMESH_TODO
        RNA_def_enum_funcs(prop, weight_paint_sample_enum_itemf);
 +#endif
        ot->prop= prop;
  }
  
  
 -#if 0 /* UNUSED */
  static void do_weight_paint_auto_normalize(MDeformVert *dvert, 
                                           int paint_nr, char *map)
  {
                }
        }
  }
 -#endif
  
  /* the active group should be involved in auto normalize */
  static void do_weight_paint_auto_normalize_all_groups(MDeformVert *dvert, char *map, char do_auto_normalize)
@@@ -1256,12 -1176,13 +1256,13 @@@ static char *gen_lock_flags(Object* ob
        if(is_locked){
                return lock_flags;
        }
-       // don't forget to free it if it is unneeded
        MEM_freeN(lock_flags);
        return NULL;
  }
  
- static int has_locked_group_selected(int defbase_tot, char *defbase_sel, char *lock_flags) {
+ static int has_locked_group_selected(int defbase_tot, char *defbase_sel, char *lock_flags)
+ {
        int i;
        for(i = 0; i < defbase_tot; i++) {
                if(defbase_sel[i] && lock_flags[i]) {
  
  
  #if 0 /* UNUSED */
- static int has_unselected_unlocked_bone_group(int defbase_tot, char *defbase_sel, int selected, char *lock_flags, char *vgroup_validmap) {
+ static int has_unselected_unlocked_bone_group(int defbase_tot, char *defbase_sel, int selected, char *lock_flags, char *vgroup_validmap)
+ {
        int i;
        if(defbase_tot == selected) {
                return FALSE;
  #endif
  
  
- static void multipaint_selection(MDeformVert *dvert, float change, char *defbase_sel, int defbase_tot) {
+ static void multipaint_selection(MDeformVert *dvert, float change, char *defbase_sel, int defbase_tot)
+ {
        int i;
        MDeformWeight *dw;
        float val;
-       // make sure they are all at most 1 after the change
+       /* make sure they are all at most 1 after the change */
        for(i = 0; i < defbase_tot; i++) {
                if(defbase_sel[i]) {
                        dw = defvert_find_index(dvert, i);
                        if(dw && dw->weight) {
                                val = dw->weight * change;
                                if(val > 1) {
-                                       /*  TODO: when the change is reduced, you need to recheck the earlier values to make sure they are not 0 (precision error) */
+                                       /* TODO: when the change is reduced, you need to recheck
+                                        * the earlier values to make sure they are not 0
+                                        * (precision error) */
                                        change = 1.0f/dw->weight;
                                }
-                               // the value should never reach zero while multi-painting if it was nonzero beforehand
+                               /* the value should never reach zero while multi-painting if it
+                                * was nonzero beforehand */
                                if(val <= 0) {
                                        return;
                                }
                        }
                }
        }
-       // apply the valid change
+       /* apply the valid change */
        for(i = 0; i < defbase_tot; i++) {
                if(defbase_sel[i]) {
                        dw = defvert_find_index(dvert, i);
        }
  }
  
- // move all change onto valid, unchanged groups.  If there is change left over, then return it.
- // assumes there are valid groups to shift weight onto
- static float redistribute_change(MDeformVert *ndv, char *change_status, int changeme, int changeto, const char *vgroup_validmap, float totchange, float total_valid, char do_auto_normalize) {
+ /* move all change onto valid, unchanged groups.  If there is change left over,
+  * then return it.
+  * assumes there are valid groups to shift weight onto */
+ static float redistribute_change(MDeformVert *ndv, char *change_status, int changeme, int changeto, float totchange, float total_valid, char do_auto_normalize)
+ {
        float was_change;
        float change;
        float oldval;
        MDeformWeight *ndw;
        int i;
        do {
-               // assume there is no change until you see one
+               /* assume there is no change until you see one */
                was_change = FALSE;
-               // change each group by the same amount each time
+               /* change each group by the same amount each time */
                change = totchange/total_valid;
                for(i = 0; i < ndv->totweight && total_valid && totchange; i++) {
                        ndw = (ndv->dw+i);
-                       // change only the groups with a valid status
+                       /* change only the groups with a valid status */
                        if(change_status[ndw->def_nr] == changeme) {
                                oldval = ndw->weight;
-                               // if auto normalize is active, don't worry about upper bounds
+                               /* if auto normalize is active, don't worry about upper bounds */
                                if(do_auto_normalize == FALSE && ndw->weight + change > 1) {
                                        totchange -= 1-ndw->weight;
                                        ndw->weight = 1;
-                                       // stop the changes to this group
+                                       /* stop the changes to this group */
                                        change_status[ndw->def_nr] = changeto;
                                        total_valid--;
-                               } else if(ndw->weight + change < 0) { // check the lower bound
+                               }
+                               else if(ndw->weight + change < 0) { /* check the lower bound */
                                        totchange -= ndw->weight;
                                        ndw->weight = 0;
                                        change_status[ndw->def_nr] = changeto;
                                        total_valid--;
-                               } else {// a perfectly valid change occurred to ndw->weight
+                               }
+                               else {/* a perfectly valid change occurred to ndw->weight */
                                        totchange -= change;
                                        ndw->weight += change;
                                }
-                               // see if there was a change
+                               /* see if there was a change */
                                if(oldval != ndw->weight) {
                                        was_change = TRUE;
                                }
                        }
                }
-       // don't go again if there was no change, if there is no valid group, or there is no change left
-       }while(was_change && total_valid && totchange);
-       // left overs
-       (void)vgroup_validmap;
+               /* don't go again if there was no change, if there is no valid group,
+                * or there is no change left */
+       } while(was_change && total_valid && totchange);
+       /* left overs */
        return totchange;
  }
  
- // observe the changes made to the weights of groups.
// make sure all locked groups on the vertex have the same deformation
- // by moving the changes made to groups onto other unlocked groups
+ /* observe the changes made to the weights of groups.
 * make sure all locked groups on the vertex have the same deformation
+  * by moving the changes made to groups onto other unlocked groups */
  static void enforce_locks(MDeformVert *odv, MDeformVert *ndv, int defbase_tot,
                            const char *lock_flags, const char *vgroup_validmap, char do_auto_normalize)
  {
        if(!lock_flags || !has_locked_group(ndv, lock_flags)) {
                return;
        }
-       // record if a group was changed, unlocked and not changed, or locked
+       /* record if a group was changed, unlocked and not changed, or locked */
        change_status = MEM_callocN(sizeof(char)*defbase_tot, "unlocked_unchanged");
  
        for(i = 0; i < defbase_tot; i++) {
                ndw = defvert_find_index(ndv, i);
                odw = defvert_find_index(odv, i);
-               // the weights are zero, so we can assume a lot
+               /* the weights are zero, so we can assume a lot */
                if(!ndw || !odw) {
                        if (!lock_flags[i] && vgroup_validmap[i]){
                                defvert_verify_index(odv, i);
                                defvert_verify_index(ndv, i);
                                total_valid++;
-                               change_status[i] = 1; // can be altered while redistributing
+                               change_status[i] = 1; /* can be altered while redistributing */
                        }
                        continue;
                }
-               // locked groups should not be changed
+               /* locked groups should not be changed */
                if(lock_flags[i]) {
                        ndw->weight = odw->weight;
                }
-               else if(ndw->weight != odw->weight) { // changed groups are handled here
+               else if(ndw->weight != odw->weight) { /* changed groups are handled here */
                        totchange += ndw->weight - odw->weight;
-                       change_status[i] = 2; // was altered already
+                       change_status[i] = 2; /* was altered already */
                        total_changed++;
                        if(ndw->weight == 0) {
                                new_weight_has_zero = TRUE;
                        else if(designatedw == -1){
                                designatedw = i;
                        }
-               } // unchanged, unlocked bone groups are handled here
+               } /* unchanged, unlocked bone groups are handled here */
                else if (vgroup_validmap[i]){
                        totchange_allowed += ndw->weight;
                        total_valid++;
-                       change_status[i] = 1; // can be altered while redistributing
+                       change_status[i] = 1; /* can be altered while redistributing */
                }
        }
-       // if there was any change, redistribute it
+       /* if there was any change, redistribute it */
        if(total_changed) {
-               // auto normalize will allow weights to temporarily go above 1 in redistribution
+               /* auto normalize will allow weights to temporarily go above 1 in redistribution */
                if(vgroup_validmap && total_changed < 0 && total_valid) {
                        totchange_allowed = total_valid;
                }
-               // there needs to be change allowed, or you should not bother
+               /* there needs to be change allowed, or you should not bother */
                if(totchange_allowed) {
-                       // the way you modify the unlocked+unchanged groups is different depending
-                       // on whether or not you are painting the weight(s) up or down
+                       /* the way you modify the unlocked+unchanged groups is different depending
+                        * on whether or not you are painting the weight(s) up or down */
                        if(totchange < 0) {
                                totchange_allowed = total_valid - totchange_allowed;
                        }
                        }
                        left_over = 0;
                        if(fabsf(totchange_allowed) < fabsf(totchange)) {
-                               // this amount goes back onto the changed, unlocked weights
+                               /* this amount goes back onto the changed, unlocked weights */
                                left_over = fabsf(fabsf(totchange) - fabsf(totchange_allowed));
                                if(totchange > 0) {
                                        left_over *= -1;
                                }
                        }
                        else {
-                               // all of the change will be permitted
+                               /* all of the change will be permitted */
                                totchange_allowed = -totchange;
                        }
-                       // move the weight evenly between the allowed groups, move excess back onto the used groups based on the change
-                       totchange_allowed = redistribute_change(ndv, change_status, 1, -1, vgroup_validmap, totchange_allowed, total_valid, do_auto_normalize);
+                       /* move the weight evenly between the allowed groups, move excess back onto the used groups based on the change */
+                       totchange_allowed = redistribute_change(ndv, change_status, 1, -1, totchange_allowed, total_valid, do_auto_normalize);
                        left_over += totchange_allowed;
                        if(left_over) {
-                               // more than one nonzero weights were changed with the same ratio, so keep them changed that way!
+                               /* more than one nonzero weights were changed with the same ratio, so keep them changed that way! */
                                if(total_changed > 1 && !new_weight_has_zero && designatedw >= 0) {
-                                       // this dw is special, it is used as a base to determine how to change the others
+                                       /* this dw is special, it is used as a base to determine how to change the others */
                                        ndw = defvert_find_index(ndv, designatedw);
                                        odw = defvert_find_index(odv, designatedw);
                                        storedw = ndw->weight;
                                                }
                                        }
                                }
-                               // a weight was changed to zero, only one weight was changed, or designatedw is still -1
-                               // put weight back as evenly as possible
+                               /* a weight was changed to zero, only one weight was changed,
+                                * or designatedw is still -1 put weight back as evenly as possible */
                                else {
-                                       redistribute_change(ndv, change_status, 2, -2, vgroup_validmap, left_over, total_changed, do_auto_normalize);
+                                       redistribute_change(ndv, change_status, 2, -2, left_over, total_changed, do_auto_normalize);
                                }
                        }
                }
                else {
-                       // reset the weights
+                       /* reset the weights */
                        for(i = 0; i < ndv->totweight; i++) {
                                ndv->dw[i].weight = odv->dw[i].weight;
                        }
        MEM_freeN(change_status);
  }
  
- // multi-paint's initial, potential change is computed here based on the user's stroke
- static float get_mp_change(MDeformVert *odv, char *defbase_sel, float brush_change) {
+ /* multi-paint's initial, potential change is computed here based on the user's stroke */
+ static float get_mp_change(MDeformVert *odv, char *defbase_sel, float brush_change)
+ {
        float selwsum = 0.0f;
        int i;
        MDeformWeight *dw;
        return 0.0f;
  }
  
- // change the weights back to the wv's weights
- // it assumes you already have the correct pointer index
- static void reset_to_prev(MDeformVert *wv, MDeformVert *dv) {
+ /* change the weights back to the wv's weights
+  * it assumes you already have the correct pointer index */
+ static void reset_to_prev(MDeformVert *wv, MDeformVert *dv)
+ {
        int i;
        MDeformWeight *d;
        MDeformWeight *w;
        }
  }
  
- static void clamp_weights(MDeformVert *dvert) {
+ static void clamp_weights(MDeformVert *dvert)
+ {
        int i;
        for (i = 0; i < dvert->totweight; i++) {
                CLAMP((dvert->dw+i)->weight, 0.0f, 1.0f);
@@@ -1579,7 -1512,10 +1592,10 @@@ static int apply_mp_locks_normalize(Mes
        dv_test.totweight = dv->totweight;
        /* do not multi-paint if a locked group is selected or the active group is locked
         * !lock_flags[dw->def_nr] helps if nothing is selected, but active group is locked */
-       if((wpi->lock_flags == NULL) || (wpi->lock_flags[dw->def_nr] == FALSE && has_locked_group_selected(wpi->defbase_tot, wpi->defbase_sel, wpi->lock_flags) == FALSE)) {
+       if(             (wpi->lock_flags == NULL) ||
+               ((wpi->lock_flags[dw->def_nr] == FALSE) &&
+                has_locked_group_selected(wpi->defbase_tot, wpi->defbase_sel, wpi->lock_flags) == FALSE))
+       {
                if(wpi->do_multipaint && wpi->defbase_tot_sel > 1) {
                        if(change && change!=1) {
                                multipaint_selection(dv, change, wpi->defbase_sel, wpi->defbase_tot);
  
  /* within the current dvert index, get the dw that is selected and has a weight
   * above 0, this helps multi-paint */
- static int get_first_selected_nonzero_weight(MDeformVert *dvert, char *defbase_sel) {
+ static int get_first_selected_nonzero_weight(MDeformVert *dvert, char *defbase_sel)
+ {
        int i;
        MDeformWeight *dw;
        for(i=0; i< dvert->totweight; i++) {
@@@ -1660,7 -1597,9 +1677,9 @@@ static void do_weight_paint_vertex( /* 
  
        /* If there are no locks or multipaint,
         * then there is no need to run the more complicated checks */
-       if((wpi->do_multipaint == FALSE || wpi->defbase_tot_sel <= 1) && (wpi->lock_flags == NULL || has_locked_group(&me->dvert[index], wpi->lock_flags) == FALSE)) {
+       if(             (wpi->do_multipaint == FALSE || wpi->defbase_tot_sel <= 1) &&
+               (wpi->lock_flags == NULL || has_locked_group(&me->dvert[index], wpi->lock_flags) == FALSE))
+       {
                wpaint_blend(wp, dw, uw, alpha, paintweight, wpi->do_flip, FALSE);
                do_weight_paint_auto_normalize_all_groups(me->dvert+index, wpi->vgroup_validmap, wpi->do_auto_normalize);
  
                neww = dw->weight;
                dw->weight = oldw;
                
-               // setup multi-paint
+               /* setup multi-paint */
                if(wpi->defbase_tot_sel > 1 && wpi->do_multipaint) {
                        dv.dw= MEM_dupallocN((me->dvert+index)->dw);
                        dv.flag = me->dvert[index].flag;
@@@ -1800,7 -1739,7 +1819,7 @@@ static int set_wpaint(bContext *C, wmOp
                paint_init(&wp->paint, PAINT_CURSOR_WEIGHT_PAINT);
                paint_cursor_start(C, weight_paint_poll);
                
 -              mesh_octree_table(ob, NULL, NULL, 's');
 +              //BMESH_TODO mesh_octree_table(ob, NULL, NULL, 's');
                
                /* verify if active weight group is also active bone */
                par= modifiers_isDeformedByArmature(ob);
                }
        }
        else {
 -              mesh_octree_table(NULL, NULL, NULL, 'e');
 -              mesh_mirrtopo_table(NULL, 'e');
 +              //BMESH_TODO mesh_octree_table(NULL, NULL, NULL, 'e');
 +              //BMESH_TODO mesh_mirrtopo_table(NULL, 'e');
        }
        
        WM_event_add_notifier(C, NC_SCENE|ND_MODE, scene);
@@@ -1935,13 -1874,6 +1954,13 @@@ static int wpaint_stroke_test_start(bCo
        me= get_mesh(ob);
        if(me==NULL || me->totface==0) return OPERATOR_PASS_THROUGH;
        
 +      /*we can't assume mfaces have a correct origindex layer that indices to mpolys.
 +        so instead we have to regenerate the tesselation faces altogether.*/
 +      me->totface = mesh_recalcTesselation(&me->fdata, &me->ldata, &me->pdata, 
 +              me->mvert, me->totface, me->totloop, me->totpoly, 1, 0);
 +      mesh_update_customdata_pointers(me);
 +      makeDerivedMesh(scene, ob, NULL, CD_MASK_BAREMESH, 0);
 +
        /* if nothing was added yet, we make dverts and a vertex deform group */
        if (!me->dvert) {
                ED_vgroup_data_create(&me->id);
@@@ -2036,8 -1968,8 +2055,8 @@@ static void wpaint_stroke_update_step(b
  
        /* cannot paint if there is no stroke data */
        if (wpd == NULL) {
-               // XXX: force a redraw here, since even though we can't paint, 
-               // at least view won't freeze until stroke ends
+               /* XXX: force a redraw here, since even though we can't paint,
+                * at least view won't freeze until stroke ends */
                ED_region_tag_redraw(CTX_wm_region(C));
                return;
        }
  
        /* which faces are involved */
        if(wp->flag & VP_AREA) {
-               // Ugly hack, to avoid drawing vertex index when getting the face index buffer - campbell
+               /* Ugly hack, to avoid drawing vertex index when getting the face index buffer - campbell */
                me->editflag &= ~ME_EDIT_VERT_SEL;
                totindex= sample_backbuf_area(vc, indexar, me->totface, mval[0], mval[1], brush_size(brush));
                me->editflag |= use_vert_sel ? ME_EDIT_VERT_SEL : 0;
                        
        if(wp->flag & VP_COLINDEX) {
                for(index=0; index<totindex; index++) {
 -                      if(indexar[index] && indexar[index]<=me->totface) {
 -                              MFace *mface= ((MFace *)me->mface) + (indexar[index]-1);
 +                      if(indexar[index] && indexar[index]<=me->totpoly) {
 +                              MPoly *mpoly= ((MPoly *)me->mpoly) + (indexar[index]-1);
                                                
 -                              if(mface->mat_nr!=ob->actcol-1) {
 +                              if(mpoly->mat_nr!=ob->actcol-1) {
                                        indexar[index]= 0;
                                }
                        }
                }
        }
                        
 -      if((me->editflag & ME_EDIT_PAINT_MASK) && me->mface) {
 +      if((me->editflag & ME_EDIT_PAINT_MASK) && me->mpoly) {
                for(index=0; index<totindex; index++) {
 -                      if(indexar[index] && indexar[index]<=me->totface) {
 -                              MFace *mface= ((MFace *)me->mface) + (indexar[index]-1);
 +                      if(indexar[index] && indexar[index]<=me->totpoly) {
 +                              MPoly *mpoly= ((MPoly *)me->mpoly) + (indexar[index]-1);
                                                
 -                              if((mface->flag & ME_FACE_SEL)==0) {
 +                              if((mpoly->flag & ME_FACE_SEL)==0) {
                                        indexar[index]= 0;
                                }
                        }                                       
                paintweight= ts->vgroup_weight;
                        
        for(index=0; index<totindex; index++) {
 -              if(indexar[index] && indexar[index]<=me->totface) {
 -                      MFace *mface= me->mface + (indexar[index]-1);
 +              if(indexar[index] && indexar[index]<=me->totpoly) {
 +                      MPoly *mpoly= me->mpoly + (indexar[index]-1);
 +                      MLoop *ml = me->mloop + mpoly->loopstart;
 +                      int i;
  
                        if(use_vert_sel) {
 -                              me->dvert[mface->v1].flag = (me->mvert[mface->v1].flag & SELECT);
 -                              me->dvert[mface->v2].flag = (me->mvert[mface->v2].flag & SELECT);
 -                              me->dvert[mface->v3].flag = (me->mvert[mface->v3].flag & SELECT);
 -                              if(mface->v4) me->dvert[mface->v4].flag = (me->mvert[mface->v4].flag & SELECT);
 +                              for (i=0; i<mpoly->totloop; i++, ml++) {
 +                                      me->dvert[ml->v].flag = (me->mvert[ml->v].flag & SELECT);
 +                              }
                        }
                        else {
 -                              me->dvert[mface->v1].flag= 1;
 -                              me->dvert[mface->v2].flag= 1;
 -                              me->dvert[mface->v3].flag= 1;
 -                              if(mface->v4) me->dvert[mface->v4].flag= 1;
 +                              for (i=0; i<mpoly->totloop; i++, ml++) {
 +                                      me->dvert[ml->v].flag = 1;
 +                              }
                        }
                                        
                        if(brush->vertexpaint_tool==VP_BLUR) {
                                else
                                        dw_func= defvert_verify_index;
                                                
 -                              dw= dw_func(me->dvert+mface->v1, ob->actdef-1);
 -                              if(dw) {paintweight+= dw->weight; totw++;}
 -                              dw= dw_func(me->dvert+mface->v2, ob->actdef-1);
 -                              if(dw) {paintweight+= dw->weight; totw++;}
 -                              dw= dw_func(me->dvert+mface->v3, ob->actdef-1);
 -                              if(dw) {paintweight+= dw->weight; totw++;}
 -                              if(mface->v4) {
 -                                      dw= dw_func(me->dvert+mface->v4, ob->actdef-1);
 -                                      if(dw) {paintweight+= dw->weight; totw++;}
 +                              ml = me->mloop + mpoly->loopstart;
 +                              for (i=0; i<mpoly->totloop; i++, ml++) {
 +                                      dw = dw_func(me->dvert+ml->v, ob->actdef-1);
 +                                      if (dw) {
 +                                              paintweight += dw->weight;
 +                                              totw++;
 +                                      }
                                }
                        }
                }
                paintweight/= (float)totw;
                        
        for(index=0; index<totindex; index++) {
 -                              
 -              if(indexar[index] && indexar[index]<=me->totface) {
 -                      MFace *mf= me->mface + (indexar[index]-1);
 -                      unsigned int fidx= mf->v4 ? 3:2;;
 -                      do {
 -                              int vidx= *(&mf->v1 + fidx);
 -
 -                              if(me->dvert[vidx].flag) {
 +              if(indexar[index] && indexar[index]<=me->totpoly) {
 +                      MPoly *mpoly= me->mpoly + (indexar[index]-1);
 +                      MLoop *ml=me->mloop+mpoly->loopstart;
 +                      int i;
 +
 +                      for (i=0; i<mpoly->totloop; i++, ml++) {
 +                              unsigned int vidx= ml->v;
 +                              if (me->dvert[vidx].flag) {
                                        alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*vidx, mval, pressure);
 -                                      if(alpha) {
 +                                      if(alpha != 0.0f) {
                                                do_weight_paint_vertex(wp, ob, &wpi, vidx, alpha, paintweight);
                                        }
                                        me->dvert[vidx].flag= 0;
                                }
 -                      } while (fidx--);
 +                      }
                }
        }
  
@@@ -2284,7 -2218,7 +2303,7 @@@ static int weight_paint_set_exec(bConte
        Object *obact = CTX_data_active_object(C);
  
        wpaint_fill(scene->toolsettings->wpaint, obact, scene->toolsettings->vgroup_weight);
-       ED_region_tag_redraw(CTX_wm_region(C)); // XXX - should redraw all 3D views
+       ED_region_tag_redraw(CTX_wm_region(C)); /* XXX - should redraw all 3D views */
        return OPERATOR_FINISHED;
  }
  
@@@ -2319,7 -2253,7 +2338,7 @@@ static int set_vpaint(bContext *C, wmOp
                return OPERATOR_PASS_THROUGH;
        }
        
 -      if(me && me->mcol==NULL) make_vertexcol(ob);
 +      if(me && me->mloopcol==NULL) make_vertexcol(ob);
        
        /* toggle: end vpaint */
        if(ob->mode & OB_MODE_VERTEX_PAINT) {
@@@ -2387,60 -2321,14 +2406,60 @@@ For future
  
  */
  
 +typedef struct polyfacemap_e {
 +      struct polyfacemap_e *next, *prev;
 +      int facenr;
 +} polyfacemap_e;
 +
  typedef struct VPaintData {
        ViewContext vc;
        unsigned int paintcol;
        int *indexar;
        float *vertexcosnos;
        float vpimat[3][3];
 +      
 +      /*mpoly -> mface mapping*/
 +      MemArena *arena;
 +      ListBase *polyfacemap;
  } VPaintData;
  
 +static void vpaint_build_poly_facemap(struct VPaintData *vd, Mesh *me,
 +                                    Object *ob, Scene *scene)
 +{
 +      MFace *mf;
 +      polyfacemap_e *e;
 +      int *origIndex;
 +      int i;
 +
 +      vd->arena = BLI_memarena_new(1<<13, "vpaint tmp");
 +      BLI_memarena_use_calloc(vd->arena);
 +
 +      vd->polyfacemap = BLI_memarena_alloc(vd->arena, sizeof(ListBase)*me->totpoly);
 +
 +      /*we can't assume mfaces have a correct origindex layer that indices to mpolys.
 +        so instead we have to regenerate the tesselation faces altogether.*/
 +      me->totface = mesh_recalcTesselation(&me->fdata, &me->ldata, &me->pdata, 
 +              me->mvert, me->totface, me->totloop, me->totpoly, 1, 0);
 +      mesh_update_customdata_pointers(me);
 +      makeDerivedMesh(scene, ob, NULL, CD_MASK_BAREMESH, 0);
 +
 +      origIndex = CustomData_get_layer(&me->fdata, CD_ORIGINDEX);
 +      mf = me->mface;
 +
 +      if (!origIndex)
 +              return;
 +
 +      for (i=0; i<me->totface; i++, mf++, origIndex++) {
 +              if (*origIndex == ORIGINDEX_NONE)
 +                      continue;
 +
 +              e = BLI_memarena_alloc(vd->arena, sizeof(polyfacemap_e));
 +              e->facenr = i;
 +              
 +              BLI_addtail(&vd->polyfacemap[*origIndex], e);
 +      }
 +}
 +
  static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, wmEvent *UNUSED(event))
  {
        ToolSettings *ts= CTX_data_tool_settings(C);
        VPaint *vp= ts->vpaint;
        struct VPaintData *vpd;
        Object *ob= CTX_data_active_object(C);
 +      Scene *scene = CTX_data_scene(C);
        Mesh *me;
        float mat[4][4], imat[4][4];
  
        /* context checks could be a poll() */
        me= get_mesh(ob);
 -      if(me==NULL || me->totface==0) return OPERATOR_PASS_THROUGH;
 +      if(me==NULL || me->totpoly==0)
 +              return OPERATOR_PASS_THROUGH;
        
 -      if(me->mcol==NULL) make_vertexcol(ob);
 -      if(me->mcol==NULL) return OPERATOR_CANCELLED;
 +      if(me->mloopcol==NULL)
 +              make_vertexcol(ob);
 +      if(me->mloopcol==NULL)
 +              return OPERATOR_CANCELLED;
        
        /* make mode data storage */
        vpd= MEM_callocN(sizeof(struct VPaintData), "VPaintData");
        vpd->vertexcosnos= mesh_get_mapped_verts_nors(vpd->vc.scene, ob);
        vpd->indexar= get_indexarray(me);
        vpd->paintcol= vpaint_get_current_col(vp);
 +      vpaint_build_poly_facemap(vpd, me, ob, scene);
        
        /* for filtering */
 -      copy_vpaint_prev(vp, (unsigned int *)me->mcol, me->totface);
 +      copy_vpaint_prev(vp, (unsigned int *)me->mloopcol, me->totloop);
        
        /* some old cruft to sort out later */
        mul_m4_m4m4(mat, ob->obmat, vpd->vc.rv3d->viewmat);
        return 1;
  }
  
 +#if 0
  static void vpaint_paint_face(VPaint *vp, VPaintData *vpd, Object *ob, int index, const float mval[2], float pressure, int UNUSED(flip))
  {
        ViewContext *vc = &vpd->vc;
                        vpaint_blend(vp, mcol+i, mcolorig+i, vpd->paintcol, (int)(alpha*255.0f));
        }
  }
 +#endif
  
  static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
  {
        Brush *brush = paint_brush(&vp->paint);
        ViewContext *vc= &vpd->vc;
        Object *ob= vc->obact;
 +      polyfacemap_e *e;
        Mesh *me= ob->data;
        float mat[4][4];
        int *indexar= vpd->indexar;
                        
        /* which faces are involved */
        if(vp->flag & VP_AREA) {
 -              totindex= sample_backbuf_area(vc, indexar, me->totface, mval[0], mval[1], brush_size(brush));
 +              totindex= sample_backbuf_area(vc, indexar, me->totpoly, mval[0], mval[1], brush_size(brush));
        }
        else {
                indexar[0]= view3d_sample_backbuf(vc, mval[0], mval[1]);
                        
        swap_m4m4(vc->rv3d->persmat, mat);
                        
 -      for(index=0; index<totindex; index++) {                         
 -              if(indexar[index] && indexar[index]<=me->totface)
 -                      vpaint_paint_face(vp, vpd, ob, indexar[index]-1, mval, pressure, flip);
 +      if(vp->flag & VP_COLINDEX) {
 +              for(index=0; index<totindex; index++) {
 +                      if(indexar[index] && indexar[index]<=me->totpoly) {
 +                              MPoly *mpoly= ((MPoly *)me->mpoly) + (indexar[index]-1);
 +                                              
 +                              if(mpoly->mat_nr!=ob->actcol-1) {
 +                                      indexar[index]= 0;
 +                              }
 +                      }                                       
 +              }
        }
 +
 +      if((me->editflag & ME_EDIT_PAINT_MASK) && me->mpoly) {
 +              for(index=0; index<totindex; index++) {
 +                      if(indexar[index] && indexar[index]<=me->totpoly) {
 +                              MPoly *mpoly= ((MPoly *)me->mpoly) + (indexar[index]-1);
                                                
 +                              if((mpoly->flag & ME_FACE_SEL)==0)
 +                                      indexar[index]= 0;
 +                      }                                       
 +              }
 +      }
 +      
        swap_m4m4(vc->rv3d->persmat, mat);
  
        /* was disabled because it is slow, but necessary for blur */
        if(brush->vertexpaint_tool == VP_BLUR)
                do_shared_vertexcol(me);
                        
 -      ED_region_tag_redraw(vc->ar);
 +      for(index=0; index<totindex; index++) {
 +                              
 +              if(indexar[index] && indexar[index]<=me->totpoly) {
 +                      MPoly *mpoly= ((MPoly *)me->mpoly) + (indexar[index]-1);
 +                      MFace *mf;
 +                      MCol *mc;
 +                      MLoop *ml;
 +                      MLoopCol *mlc;
 +                      unsigned int *lcol = ((unsigned int*)me->mloopcol) + mpoly->loopstart;
 +                      unsigned int *lcolorig = ((unsigned int*)vp->vpaint_prev) + mpoly->loopstart;
 +                      float alpha;
 +                      int i, j;
 +                                      
 +                      if(brush->vertexpaint_tool==VP_BLUR) {
 +                              unsigned int blend[5] = {0};
 +                              char *col;
 +
 +                              for (j=0; j<mpoly->totloop; j += 2) {
 +                                      col = (char*)(lcol + j);
 +                                      blend[0] += col[0];
 +                                      blend[1] += col[1];
 +                                      blend[2] += col[2];
 +                                      blend[3] += col[3];
 +                              }
 +
 +                              blend[0] /= mpoly->totloop;
 +                              blend[1] /= mpoly->totloop;
 +                              blend[2] /= mpoly->totloop;
 +                              blend[3] /= mpoly->totloop;
 +                              col = (char*)(blend + 4);
 +                              col[0] = blend[0];
 +                              col[1] = blend[1];
 +                              col[2] = blend[2];
 +                              col[3] = blend[3];
 +
 +                              vpd->paintcol = *((unsigned int*)col);
 +                      }
 +
 +                      ml = me->mloop + mpoly->loopstart;
 +                      for (i=0; i<mpoly->totloop; i++, ml++) {
 +                              alpha= calc_vp_alpha_dl(vp, vc, vpd->vpimat, 
 +                                         vpd->vertexcosnos+6*ml->v, mval, pressure);
 +                              if(alpha > 0.0f) vpaint_blend(vp, lcol+i, lcolorig+i, vpd->paintcol, (int)(alpha*255.0f));
 +                      }
 +      
 +                      #ifdef CPYCOL
 +                      #undef CPYCOL
 +                      #endif
 +                      #define CPYCOL(c, l) (c)->a = (l)->a, (c)->r = (l)->r, (c)->g = (l)->g, (c)->b = (l)->b
 +
 +                      /*update vertex colors for tesselations incrementally,
 +                        rather then regenerating the tesselation altogether.*/
 +                      for (e=vpd->polyfacemap[(indexar[index]-1)].first; e; e=e->next) {
 +                              mf = me->mface + e->facenr;
 +                              mc = me->mcol + e->facenr*4;
 +                              
 +                              ml = me->mloop + mpoly->loopstart;
 +                              mlc = me->mloopcol + mpoly->loopstart;
 +                              for (j=0; j<mpoly->totloop; j++, ml++, mlc++) {
 +                                      if (ml->v == mf->v1)
 +                                              CPYCOL(mc, mlc);
 +                                      else if (ml->v == mf->v2)
 +                                              CPYCOL(mc+1, mlc);
 +                                      else if (ml->v == mf->v3)
 +                                              CPYCOL(mc+2, mlc);
 +                                      else if (mf->v4 && ml->v == mf->v4)
 +                                              CPYCOL(mc+3, mlc);
 +
 +                              }
 +                      }
 +                      #undef CPYCOL
 +              }
 +      }
 +              
 +      swap_m4m4(vc->rv3d->persmat, mat);
                        
 +      do_shared_vertexcol(me);
 +
 +      ED_region_tag_redraw(vc->ar);           
        DAG_id_tag_update(ob->data, 0);
  }
  
@@@ -2681,8 -2466,7 +2700,8 @@@ static void vpaint_stroke_done(bContex
        
        /* frees prev buffer */
        copy_vpaint_prev(ts->vpaint, NULL, 0);
 -      
 +      BLI_memarena_free(vpd->arena);
 +
        MEM_freeN(vpd);
  }