Merged with trunk (-r43609:43611): updated modifier preview.
authorBastien Montagne <montagne29@wanadoo.fr>
Sun, 22 Jan 2012 20:05:26 +0000 (20:05 +0000)
committerBastien Montagne <montagne29@wanadoo.fr>
Sun, 22 Jan 2012 20:05:26 +0000 (20:05 +0000)
Noted preview code for DynamicPaint is currently disabled, will see if I can re-enable it…

1  2 
source/blender/blenkernel/BKE_DerivedMesh.h
source/blender/blenkernel/BKE_modifier.h
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/dynamicpaint.c
source/blender/editors/space_view3d/drawmesh.c
source/blender/editors/space_view3d/drawobject.c
source/blender/modifiers/intern/MOD_weightvgedit.c
source/blender/modifiers/intern/MOD_weightvgmix.c
source/blender/modifiers/intern/MOD_weightvgproximity.c

@@@ -1018,151 -753,90 +1017,210 @@@ static unsigned char *calc_weightpaint_
        return wtcol_v;
  }
  
- static void add_weight_mcol_dm(Object *ob, DerivedMesh *dm, int const draw_flag)
+ /* return an array of vertex weight colors from given weights, caller must free.
+  *
+  * note that we could save some memory and allocate RGB only but then we'd need to
+  * re-arrange the colors when copying to the face since MCol has odd ordering,
+  * so leave this as is - campbell */
+ static unsigned char *calc_colors_from_weights_array(const int num, float *weights)
+ {
+       unsigned char *wtcol_v = MEM_mallocN(sizeof(unsigned char) * num * 4, "weightmap_v");
+       unsigned char *wc = wtcol_v;
+       int i;
+       for (i = 0; i < num; i++, wc += 4, weights++)
+               weightpaint_color((unsigned char *) wc, NULL, *weights);
+       return wtcol_v;
+ }
+ void DM_update_weight_mcol(Object *ob, DerivedMesh *dm, int const draw_flag,
+                            float *weights, int num, const int *indices)
  {
        ColorBand *coba= stored_cb;     /* warning, not a local var */
-       unsigned char *wtcol_v = calc_weightpaint_vert_array(ob, draw_flag, coba);
-       unsigned char *wtcol_f;
-       unsigned char(*wtcol_l)[4] = NULL;
-       BLI_array_declare(wtcol_l);
 -      MFace *mf = dm->getFaceArray(dm);
 -      int numFaces = dm->getNumFaces(dm);
 -      int numVerts = dm->getNumVerts(dm);
+       unsigned char *wtcol_v;
 -      unsigned char *wtcol_f = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL);
 -      int i;
++      unsigned char *wtcol_f = dm->getTessFaceDataArray(dm, CD_WEIGHT_MCOL);
++      unsigned char(*wtcol_l)[4] = CustomData_get_layer(dm->getLoopDataLayout(dm), CD_WEIGHT_MLOOPCOL);
 +      MFace *mf = dm->getTessFaceArray(dm);
 +      MLoop *mloop = dm->getLoopArray(dm), *ml;
 +      MPoly *mp = dm->getPolyArray(dm);
-       int i, j, totface=dm->getNumTessFaces(dm), totloop;
-       int *origIndex = dm->getVertDataArray(dm, CD_ORIGINDEX);
-       unsigned char *wtcol_f_step;
++      int numFaces = dm->getNumTessFaces(dm);
++      int numVerts = dm->getNumVerts(dm);
++      int totloop;
++      int i, j;
+       /* If no CD_WEIGHT_MCOL existed yet, add a new one! */
+       if (!wtcol_f)
+               wtcol_f = CustomData_add_layer(&dm->faceData, CD_WEIGHT_MCOL, CD_CALLOC, NULL, numFaces);
+       if (wtcol_f) {
+               unsigned char *wtcol_f_step = wtcol_f;
+               /* Weights are given by caller. */
+               if (weights) {
+                       float *w = weights;
+                       /* If indices is not NULL, it means we do not have weights for all vertices,
+                        * so we must create them (and set them to zero)... */
+                       if(indices) {
+                               w = MEM_callocN(sizeof(float)*numVerts, "Temp weight array DM_update_weight_mcol");
+                               i = num;
+                               while(i--)
+                                       w[indices[i]] = weights[i];
+                       }
+                       /* Convert float weights to colors. */
+                       wtcol_v = calc_colors_from_weights_array(numVerts, w);
+                       if(indices)
+                               MEM_freeN(w);
+               }
  
-       wtcol_f = MEM_mallocN(sizeof (unsigned char) * totface*4*4, "weightmap_f");
-       wtcol_f_step = wtcol_f;
+               /* No weights given, take them from active vgroup(s). */
+               else
+                       wtcol_v = calc_weightpaint_vert_array(ob, dm, draw_flag, coba);
  
-       /*first add colors to the tesselation faces*/
-       for (i=0; i<totface; i++, mf++, wtcol_f_step += (4 * 4)) {
-               /*origindex being NULL means we're operating on original mesh data*/
+               /* Now copy colors in all face verts. */
++              /*first add colors to the tesselation faces*/
+               for (i = 0; i < numFaces; i++, mf++, wtcol_f_step += (4 * 4)) {
++                      /*origindex being NULL means we're operating on original mesh data*/
  #if 0
-               unsigned int fidx= mf->v4 ? 3:2;
+                       unsigned int fidx= mf->v4 ? 3:2;
  
  #else /* better zero out triangles 4th component. else valgrind complains when the buffer's copied */
-               unsigned int fidx;
-               if (mf->v4) {
-                       fidx = 3;
-               }
-               else {
-                       fidx = 2;
-                       *(int *)(&wtcol_f_step[3 * 4]) = 0;
-               }
+                       unsigned int fidx;
+                       if (mf->v4) {
+                               fidx = 3;
+                       }
+                       else {
+                               fidx = 2;
+                               *(int *)(&wtcol_f_step[3 * 4]) = 0;
+                       }
  #endif
  
-               do {
-                       copy_v4_v4_char((char *)&wtcol_f_step[fidx * 4],
-                                       (char *)&wtcol_v[4 * (*(&mf->v1 + fidx))]);
-               } while (fidx--);
-       }
-       CustomData_add_layer(&dm->faceData, CD_WEIGHT_MCOL, CD_ASSIGN, wtcol_f, totface);
+                       do {
+                               copy_v4_v4_char((char *)&wtcol_f_step[fidx * 4],
 -                                                      (char *)&wtcol_v[4 * (*(&mf->v1 + fidx))]);
++                                              (char *)&wtcol_v[4 * (*(&mf->v1 + fidx))]);
+                       } while (fidx--);
+               }
 +
-       /*now add to loops, so the data can be passed through the modifier stack*/
-       totloop = 0;
-       for (i=0; i<dm->numPolyData; i++, mp++) {
-               ml = mloop + mp->loopstart;
++              /*now add to loops, so the data can be passed through the modifier stack*/
++              /* If no CD_WEIGHT_MLOOPCOL existed yet, we have to add a new one! */
++              if (!wtcol_l) {
++                      BLI_array_declare(wtcol_l);
++                      totloop = 0;
++                      for (i=0; i<dm->numPolyData; i++, mp++) {
++                              ml = mloop + mp->loopstart;
++
++                              for (j=0; j<mp->totloop; j++, ml++, totloop++) {
++                                      BLI_array_growone(wtcol_l);
++                                      copy_v4_v4_char((char *)&wtcol_l[totloop],
++                                                      (char *)&wtcol_v[4 * ml->v]);
++                              }
++                      }
++                      CustomData_add_layer(&dm->loopData, CD_WEIGHT_MLOOPCOL, CD_ASSIGN, wtcol_l, totloop);
++              }
++              else {
++                      totloop = 0;
++                      for (i=0; i < dm->numPolyData; i++, mp++) {
++                              ml = mloop + mp->loopstart;
 +
-               for (j=0; j<mp->totloop; j++, ml++, totloop++) {
-                       BLI_array_growone(wtcol_l);
-                       copy_v4_v4_char((char *)&wtcol_l[totloop],
-                                       (char *)&wtcol_v[4 * (origIndex ? origIndex[ml->v] : ml->v)]);
++                              for (j=0; j < mp->totloop; j++, ml++, totloop++) {
++                                      copy_v4_v4_char((char *)&wtcol_l[totloop],
++                                                      (char *)&wtcol_v[4 * ml->v]);
++                              }
++                      }
 +              }
+               MEM_freeN(wtcol_v);
        }
-       MEM_freeN(wtcol_v);
-       CustomData_add_layer(&dm->loopData, CD_WEIGHT_MLOOPCOL, CD_ASSIGN, wtcol_l, totloop);
  }
  
 +
 +static void shapekey_layers_to_keyblocks(DerivedMesh *dm, Mesh *me, int actshape_uid)
 +{
 +      KeyBlock *kb;
 +      int i, j, tot;
 +      
 +      if (!me->key)
 +              return; 
 +      
 +      tot = CustomData_number_of_layers(&dm->vertData, CD_SHAPEKEY);
 +      for (i=0; i<tot; i++) {
 +              CustomDataLayer *layer = &dm->vertData.layers[CustomData_get_layer_index_n(&dm->vertData, CD_SHAPEKEY, i)];
 +              float (*cos)[3], (*kbcos)[3];
 +              
 +              for (kb=me->key->block.first; kb; kb=kb->next) {
 +                      if (kb->uid == layer->uid)
 +                              break;
 +              }
 +              
 +              if (!kb) {
 +                      kb = add_keyblock(me->key, layer->name);
 +                      kb->uid = layer->uid;
 +              }
 +              
 +              if (kb->data)
 +                      MEM_freeN(kb->data);
 +              
 +              cos = CustomData_get_layer_n(&dm->vertData, CD_SHAPEKEY, i);
 +              kb->totelem = dm->numVertData;
 +
 +              kb->data = kbcos = MEM_mallocN(sizeof(float)*3*kb->totelem, "kbcos DerivedMesh.c");
 +              if (kb->uid == actshape_uid) {
 +                      MVert *mvert = dm->getVertArray(dm);
 +                      
 +                      for (j=0; j<dm->numVertData; j++, kbcos++, mvert++) {
 +                              copy_v3_v3(*kbcos, mvert->co);
 +                      }
 +              } else {
 +                      for (j=0; j<kb->totelem; j++, cos++, kbcos++) {
 +                              copy_v3_v3(*kbcos, *cos);
 +                      }
 +              }
 +      }
 +      
 +      for (kb=me->key->block.first; kb; kb=kb->next) {
 +              if (kb->totelem != dm->numVertData) {
 +                      if (kb->data)
 +                              MEM_freeN(kb->data);
 +                      
 +                      kb->totelem = dm->numVertData;
 +                      kb->data = MEM_callocN(sizeof(float)*3*kb->totelem, "kb->data derivedmesh.c");
 +                      fprintf(stderr, "%s: lost a shapekey layer! (bmesh internal error)\n", __func__);
 +              }
 +      }
 +}
 +
 +static void add_shapekey_layers(DerivedMesh *dm, Mesh *me, Object *UNUSED(ob))
 +{
 +      KeyBlock *kb;
 +      Key *key = me->key;
 +      int a, b;
 +      
 +      if (!me->key)
 +              return;
 +      
 +      if (dm->numVertData != me->totvert) {
 +              printf("error in add_shapekey_layers: dm isn't the same size as me\n");
 +              return;
 +      }
 +              
 +      for (a=0, kb=key->block.first; kb; kb=kb->next, a++) {
 +              float (*cos)[3] = CustomData_add_layer_named(&dm->vertData, CD_SHAPEKEY, CD_CALLOC, NULL, dm->numVertData, kb->name);
 +              int ci = CustomData_get_layer_index_n(&dm->vertData, CD_SHAPEKEY, a);
 +              
 +              dm->vertData.layers[ci].uid = kb->uid;
 +              if (kb->totelem != dm->numVertData) {
 +                      printf("error in add_shapekey_layers: totelem and totvert don't match");
 +                      continue;
 +              }
 +              
 +              for (b=0; b<kb->totelem; b++, cos++) {
 +                      copy_v3_v3((float *)cos, ((float*)kb->data)+b*3);
 +              }
 +      }
 +}
 +
  /* new value for useDeform -1  (hack for the gameengine):
   * - apply only the modifier stack of the object, skipping the virtual modifiers,
   * - don't apply the key
  static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos)[3],
                                                                DerivedMesh **deform_r, DerivedMesh **final_r,
                                                                int useRenderParams, int useDeform,
 -                                                              int needMapping, CustomDataMask dataMask, int index, int useCache)
 +                                                              int needMapping, CustomDataMask dataMask, 
 +                                                              int index, int useCache, int build_shapekey_layers)
  {
        Mesh *me = ob->data;
-       ModifierData *firstmd, *md;
+       ModifierData *firstmd, *md, *previewmd = NULL;
        LinkNode *datamasks, *curr;
        CustomDataMask mask, nextmask, append_mask = 0;
        float (*deformedVerts)[3] = NULL;
  
                                        range_vn_i(DM_get_vert_data_layer(dm, CD_ORIGINDEX), dm->numVertData, 0);
                                        range_vn_i(DM_get_edge_data_layer(dm, CD_ORIGINDEX), dm->numEdgeData, 0);
 -                                      range_vn_i(DM_get_face_data_layer(dm, CD_ORIGINDEX), dm->numFaceData, 0);
 +                                      range_vn_i(DM_get_poly_data_layer(dm, CD_ORIGINDEX), dm->numPolyData, 0);
                                }
-                               if((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT))
-                                       add_weight_mcol_dm(ob, dm, draw_flag);
 +
++/*                            if((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT))*/
++/*                                    add_weight_mcol_dm(ob, dm, draw_flag);*/
 +
                        }
  
                        
                CDDM_apply_vert_coords(finaldm, deformedVerts);
                CDDM_calc_normals(finaldm);
  
-               if((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT))
-                       add_weight_mcol_dm(ob, finaldm, draw_flag);
+ #if 0 /* For later nice mod preview! */
+               /* In case we need modified weights in CD_WEIGHT_MCOL, we have to re-compute it. */
+               if(do_final_wmcol)
+                       DM_update_weight_mcol(ob, finaldm, draw_flag, NULL, 0, NULL);
+ #endif
        } else if(dm) {
                finaldm = dm;
+ #if 0 /* For later nice mod preview! */
+               /* In case we need modified weights in CD_WEIGHT_MCOL, we have to re-compute it. */
+               if(do_final_wmcol)
+                       DM_update_weight_mcol(ob, finaldm, draw_flag, NULL, 0, NULL);
+ #endif
        } else {
 -              finaldm = CDDM_from_mesh(me, ob);
 +              int recalc_normals= 0;
  
 +              finaldm = CDDM_from_mesh(me, ob);
 +              
 +              if(build_shapekey_layers) {
 +                      add_shapekey_layers(finaldm, me, ob);
 +                      recalc_normals= 1;
 +              }
 +              
                if(deformedVerts) {
                        CDDM_apply_vert_coords(finaldm, deformedVerts);
-               if(recalc_normals)
 +                      recalc_normals= 1;
 +              }
 +
++              if(recalc_normals) {
                        CDDM_calc_normals(finaldm);
-               
-               if((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT))
-                       add_weight_mcol_dm(ob, finaldm, draw_flag);
+               }
+               /* In this case, we should never have weight-modifying modifiers in stack... */
+               if(do_init_wmcol)
+                       DM_update_weight_mcol(ob, finaldm, draw_flag, NULL, 0, NULL);
        }
  
        /* add an orco layer if needed */
@@@ -1706,29 -1705,11 +1704,12 @@@ static struct DerivedMesh *dynamicPaint
                                                int defgrp_index = defgroup_name_index(ob, surface->output_name);
                                                MDeformVert *dvert = result->getVertDataArray(result, CD_MDEFORMVERT);
                                                float *weight = (float*)sData->type_data;
 +
                                                /* viewport preview */
 -                                              if (surface->flags & MOD_DPAINT_PREVIEW) {
 -                                                      /* Save preview results to weight layer, to be
 +                                              if (0 && surface->flags & MOD_DPAINT_PREVIEW) {
 +                                                      /* Save preview results to weight layer to be
                                                        *   able to share same drawing methods */
-                                                       int i;
-                                                       MLoopCol *col = CustomData_get_layer(&dm->loopData, CD_WEIGHT_MLOOPCOL);
-                                                       if (!col) col = CustomData_add_layer(&dm->loopData, CD_WEIGHT_MLOOPCOL, CD_CALLOC, NULL, totloop);
-                                                       if (col) {
-                                                               printf("doint weight preview\n");
-                                                               #pragma omp parallel for schedule(static)
-                                                               for (i=0; i<totloop; i++) {
-                                                                       float temp_color[3];
-                                                                       weight_to_rgb(temp_color, weight[mloop[i].v]);
-                                                                       col[i].a = 255;
-                                                                       col[i].r = FTOCHAR(temp_color[2]);
-                                                                       col[i].g = FTOCHAR(temp_color[1]);
-                                                                       col[i].b = FTOCHAR(temp_color[0]);
-                                                               }
-                                                               pmd->canvas->flags |= MOD_DPAINT_PREVIEW_READY;
-                                                       }
+                                                       DM_update_weight_mcol(ob, result, 0, weight, 0, NULL);
                                                }
  
                                                /* apply weights into a vertex group, if doesnt exists add a new layer */
@@@ -3158,20 -3086,10 +3156,10 @@@ static void draw_mesh_fancy(Scene *scen
        if(!dm)
                return;
  
-       /* check to draw dynamic paint colors */
-       if ((md = modifiers_findByType(ob, eModifierType_DynamicPaint)))
-       {
-               /* check if target has an active dpaint modifier        */
-               if(md && (md->mode & eModifierMode_Realtime))                                   
-               {
-                       DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
-                       /* if canvas is ready to preview vertex colors */
-                       if (pmd->canvas && pmd->canvas->flags & MOD_DPAINT_PREVIEW_READY &&
-                               DM_get_poly_data_layer(dm, CD_WEIGHT_MCOL)) {
-                               draw_flags |= DRAW_DYNAMIC_PAINT_PREVIEW;
-                       }
-               }
-       }
+       /* Check to draw dynamic paint colors (or weights from WeightVG modifiers).
+        * Note: Last "preview-active" modifier in stack will win! */
 -      if(DM_get_face_data_layer(dm, CD_WEIGHT_MCOL) && modifiers_isPreview(ob))
++      if(DM_get_poly_data_layer(dm, CD_WEIGHT_MCOL) && modifiers_isPreview(ob))
+               draw_flags |= DRAW_MODIFIERS_PREVIEW;
  
        /* Unwanted combination */
        if (draw_flags & DRAW_FACE_SELECT) {