svn merge -r41287:41310 ^/trunk/blender note, mirror modifier had slow, per vertex...
authorCampbell Barton <ideasman42@gmail.com>
Thu, 27 Oct 2011 09:42:03 +0000 (09:42 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Thu, 27 Oct 2011 09:42:03 +0000 (09:42 +0000)
15 files changed:
1  2 
source/blender/blenkernel/intern/blender.c
source/blender/blenkernel/intern/curve.c
source/blender/blenkernel/intern/deform.c
source/blender/blenkernel/intern/key.c
source/blender/blenkernel/intern/library.c
source/blender/blenkernel/intern/mesh.c
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/particle.c
source/blender/blenkernel/intern/particle_system.c
source/blender/blenloader/intern/readfile.c
source/blender/editors/gpencil/gpencil_paint.c
source/blender/editors/object/object_vgroup.c
source/blender/editors/space_view3d/view3d_buttons.c
source/blender/makesrna/intern/rna_scene.c
source/blender/modifiers/intern/MOD_mirror.c

  #include "DNA_key_types.h"
  #include "DNA_meshdata_types.h"
  #include "DNA_ipo_types.h"
 +#include "DNA_customdata_types.h"
  
 +#include "BLI_utildefines.h"
  #include "BLI_blenlib.h"
+ #include "BLI_bpath.h"
  #include "BLI_editVert.h"
  #include "BLI_math.h"
  #include "BLI_edgehash.h"
@@@ -563,55 -242,21 +564,50 @@@ Mesh *copy_mesh(Mesh *me
        return men;
  }
  
- static void make_local_tface(Main *bmain, Mesh *me)
 +BMesh *BKE_mesh_to_bmesh(Mesh *me, Object *ob)
 +{
 +      BMesh *bm;
 +      int allocsize[4] = {512,512,2048,512};
 +
 +      bm = BM_Make_Mesh(ob, allocsize);
 +
 +      BMO_CallOpf(bm, "mesh_to_bmesh mesh=%p object=%p set_shapekey=%i", me, ob, 1);
 +
 +      return bm;
 +}
 +
+ static void expand_local_mesh(Mesh *me)
  {
-       MTFace *tface;
-       MTexPoly *txface;
-       Image *ima;
-       int a, i;
-       
-       for(i=0; i<me->pdata.totlayer; i++) {
-               if(me->pdata.layers[i].type == CD_MTEXPOLY) {
-                       txface= (MTexPoly*)me->fdata.layers[i].data;
-                       
-                       for(a=0; a<me->totpoly; a++, txface++) {
-                               /* special case: ima always local immediately */
-                               if(txface->tpage) {
-                                       ima= txface->tpage;
-                                       if(ima->id.lib) {
-                                               ima->id.lib= 0;
-                                               ima->id.flag= LIB_LOCAL;
-                                               new_id(0, (ID *)ima, 0);
+       id_lib_extern((ID *)me->texcomesh);
+       if(me->mtface) {
 -              MTFace *tface;
+               int a, i;
++              for(i=0; i<me->pdata.totlayer; i++) {
++                      if(me->pdata.layers[i].type == CD_MTEXPOLY) {
++                              MTexPoly *txface= (MTexPoly*)me->fdata.layers[i].data;
++
++                              for(a=0; a<me->totpoly; a++, txface++) {
++                                      /* special case: ima always local immediately */
++                                      if(txface->tpage) {
++                                              if(txface->tpage) {
++                                                      id_lib_extern((ID *)txface->tpage);
++                                              }
 +                                      }
 +                              }
 +                      }
 +              }
-       }
 +
-       for(i=0; i<me->fdata.totlayer; i++) {
-               if(me->fdata.layers[i].type == CD_MTFACE) {
-                       tface= (MTFace*)me->fdata.layers[i].data;
-                       
-                       for(a=0; a<me->totface; a++, tface++) {
-                               /* special case: ima always local immediately */
-                               if(tface->tpage) {
-                                       ima= tface->tpage;
-                                       if(ima->id.lib) {
-                                               ima->id.lib= NULL;
-                                               ima->id.flag= LIB_LOCAL;
-                                               new_id(&bmain->image, (ID *)ima, NULL);
+               for(i=0; i<me->fdata.totlayer; i++) {
+                       if(me->fdata.layers[i].type == CD_MTFACE) {
 -                              tface= (MTFace*)me->fdata.layers[i].data;
++                              MTFace *tface= (MTFace*)me->fdata.layers[i].data;
+                               for(a=0; a<me->totface; a++, tface++) {
++                                      /* special case: ima always local immediately */
+                                       if(tface->tpage) {
 -                                              id_lib_extern((ID *)tface->tpage);
++                                              if(tface->tpage) {
++                                                      id_lib_extern((ID *)tface->tpage);
++                                              }
                                        }
                                }
                        }
@@@ -646,11 -281,8 +632,11 @@@ void make_local_mesh(Mesh *me
  
        if(me->id.lib==NULL) return;
        if(me->id.us==1) {
 -              id_clear_lib_data(bmain, &me->id);
 +              me->id.lib= NULL;
 +              me->id.flag= LIB_LOCAL;
 +
 +              new_id(&bmain->mesh, (ID *)me, NULL);
-               expand_local_mesh(bmain, me);
+               expand_local_mesh(me);
                return;
        }
  
                }
        }
  
 -      if(is_local && is_lib == FALSE) {
 -              id_clear_lib_data(bmain, &me->id);
 +      if(local && lib==0) {
 +              me->id.lib= NULL;
 +              me->id.flag= LIB_LOCAL;
 +
 +              new_id(&bmain->mesh, (ID *)me, NULL);
-               expand_local_mesh(bmain, me);
+               expand_local_mesh(me);
        }
 -      else if(is_local && is_lib) {
 -              char *bpath_user_data[2]= {bmain->name, me->id.lib->filepath};
 +      else if(local && lib) {
                Mesh *men= copy_mesh(me);
                men->id.us= 0;
  
@@@ -53,8 -53,7 +53,9 @@@
  #include "BLI_rand.h"
  #include "BLI_threads.h"
  #include "BLI_linklist.h"
+ #include "BLI_bpath.h"
 +#include "BLI_cellalloc.h"
 +#include "BLI_math.h"
  
  #include "BKE_anim.h"
  #include "BKE_animsys.h"
@@@ -3630,16 -3627,19 +3629,18 @@@ void make_local_particlesettings(Partic
                }
        }
        
-       if(local && lib==0) {
-               part->id.lib= 0;
-               part->id.flag= LIB_LOCAL;
-               new_id(&bmain->particle, (ID *)part, 0);
+       if(is_local && is_lib==FALSE) {
+               id_clear_lib_data(bmain, &part->id);
                expand_local_particlesettings(part);
        }
-       else if(local && lib) {
+       else if(is_local && is_lib) {
+               char *bpath_user_data[2]= {bmain->name, part->id.lib->filepath};
                ParticleSettings *partn= psys_copy_settings(part);
 -
                partn->id.us= 0;
-               
+               /* Remap paths of new ID using old library as base. */
+               bpath_traverse_id(bmain, &partn->id, bpath_relocate_visitor, 0, bpath_user_data);
                /* do objects */
                for(ob= bmain->object.first; ob; ob= ob->id.next) {
                        ParticleSystem *psys;
@@@ -1560,15 -1557,12 +1560,15 @@@ static void dvert_mirror_op(MDeformVer
  
  void ED_vgroup_mirror(Object *ob, const short mirror_weights, const short flip_vgroups)
  {
- #define VGROUP_MIRR_OP dvert_mirror_op(dvert, dvert_mirr, sel, sel_mirr, flip_map, mirror_weights, flip_vgroups)
+ #define VGROUP_MIRR_OP dvert_mirror_op(dvert, dvert_mirr, sel, sel_mirr, flip_map, flip_map_len, mirror_weights, flip_vgroups)
  
 +#if 0
        EditVert *eve, *eve_mirr;
 +#endif
 +
        MDeformVert *dvert, *dvert_mirr;
        short sel, sel_mirr;
-       int     *flip_map;
+       int     *flip_map, flip_map_len;
  
        if(mirror_weights==0 && flip_vgroups==0)
                return;
@@@ -93,193 -95,195 +93,176 @@@ static void updateDepgraph(ModifierDat
        }
  }
  
 -static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
 +
 +/* Mirror */
 +#define VERT_NEW      1
 +
 +DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
                Object *ob,
                DerivedMesh *dm,
 -              int initFlags,
 +              int UNUSED(initFlags),
                int axis)
  {
 -      int i;
 -      float tolerance = mmd->tolerance;
 -      DerivedMesh *result;
 -      int numVerts, numEdges, numFaces;
 -      int maxVerts = dm->getNumVerts(dm);
 -      int maxEdges = dm->getNumEdges(dm);
 -      int maxFaces = dm->getNumFaces(dm);
 -      int *flip_map= NULL, flip_map_len= 0;
 -      int do_vgroup_mirr= (mmd->flag & MOD_MIR_VGROUP);
 -      int (*indexMap)[2];
 -      float mtx[4][4], imtx[4][4];
 -
 -      numVerts = numEdges = numFaces = 0;
 -
 -      indexMap = MEM_mallocN(sizeof(*indexMap) * maxVerts, "indexmap");
 -
 -      result = CDDM_from_template(dm, maxVerts * 2, maxEdges * 2, maxFaces * 2);
 -
 -
 -      if (do_vgroup_mirr) {
 -              flip_map= defgroup_flip_map(ob, &flip_map_len, FALSE);
 -              if(flip_map == NULL)
 -                      do_vgroup_mirr= 0;
 +      float tolerance_sq;
 +      DerivedMesh *cddm, *origdm;
 +      bDeformGroup *def, *defb;
 +      bDeformGroup **vector_def = NULL;
 +      MVert *mv, *ov;
 +      MEdge *me;
 +      MLoop *ml;
 +      MPoly *mp;
 +      float mtx[4][4];
 +      int i, j, *vtargetmap = NULL;
 +      BLI_array_declare(vtargetmap);
 +      int vector_size=0, a, b, totshape;
 +
 +      tolerance_sq = mmd->tolerance * mmd->tolerance;
 +      
 +      origdm = dm;
 +      if (!CDDM_Check(dm))
 +              dm = CDDM_copy(dm, 0);
 +      
 +      if (mmd->flag & MOD_MIR_VGROUP) {
 +              /* calculate the number of deformedGroups */
 +              for(vector_size = 0, def = ob->defbase.first; def;
 +                      def = def->next, vector_size++);
 +
 +              /* load the deformedGroups for fast access */
 +              vector_def =
 +                      (bDeformGroup **)MEM_mallocN(sizeof(bDeformGroup*) * vector_size,
 +                                                                               "group_index");
 +              for(a = 0, def = ob->defbase.first; def; def = def->next, a++) {
 +                      vector_def[a] = def;
 +              }
        }
  
 +      /*mtx is the mirror transformation*/
 +      unit_m4(mtx);
 +      mtx[axis][axis] = -1.0;
 +
        if (mmd->mirror_ob) {
 -              float obinv[4][4];
 -              
 -              invert_m4_m4(obinv, mmd->mirror_ob->obmat);
 -              mul_m4_m4m4(mtx, ob->obmat, obinv);
 -              invert_m4_m4(imtx, mtx);
 +              float tmp[4][4];
 +              float itmp[4][4];
 +
 +              /*tmp is a transform from coords relative to the object's own origin, to
 +                coords relative to the mirror object origin*/
 +              invert_m4_m4(tmp, mmd->mirror_ob->obmat);
 +              mul_m4_m4m4(tmp, ob->obmat, tmp);
 +
 +              /*itmp is the reverse transform back to origin-relative coordiantes*/
 +              invert_m4_m4(itmp, tmp);
 +
 +              /*combine matrices to get a single matrix that translates coordinates into
 +                mirror-object-relative space, does the mirror, and translates back to
 +                origin-relative space*/
 +              mul_m4_m4m4(mtx, tmp, mtx);
 +              mul_m4_m4m4(mtx, mtx, itmp);
        }
 -
 -      for(i = 0; i < maxVerts; i++) {
 -              MVert inMV;
 -              MVert *mv = CDDM_get_vert(result, numVerts);
 -              int isShared;
 -              float co[3];
 -              
 -              dm->getVert(dm, i, &inMV);
 -              
 -              copy_v3_v3(co, inMV.co);
 -              
 -              if (mmd->mirror_ob) {
 -                      mul_m4_v3(mtx, co);
 +      
 +      cddm = CDDM_from_template(dm, dm->numVertData*2, dm->numEdgeData*2, 0, dm->numLoopData*2, dm->numPolyData*2);
 +      
 +      /*copy customdata to original geometry*/
 +      CustomData_copy_data(&dm->vertData, &cddm->vertData, 0, 0, dm->numVertData);
 +      CustomData_copy_data(&dm->edgeData, &cddm->edgeData, 0, 0, dm->numEdgeData);
 +      CustomData_copy_data(&dm->loopData, &cddm->loopData, 0, 0, dm->numLoopData);
 +      CustomData_copy_data(&dm->polyData, &cddm->polyData, 0, 0, dm->numPolyData);
 +
 +      /*copy customdata to new geometry*/
 +      CustomData_copy_data(&dm->vertData, &cddm->vertData, 0, dm->numVertData, dm->numVertData);
 +      CustomData_copy_data(&dm->edgeData, &cddm->edgeData, 0, dm->numEdgeData, dm->numEdgeData);
 +      CustomData_copy_data(&dm->polyData, &cddm->polyData, 0, dm->numPolyData, dm->numPolyData);
 +      
 +      /*mirror vertex coordinates*/
 +      ov = CDDM_get_verts(cddm);
 +      mv = ov + dm->numVertData;
 +      for (i=0; i<dm->numVertData; i++, mv++, ov++) {
 +              mul_m4_v3(mtx, mv->co);
 +              /*compare location of the original and mirrored vertex, to see if they
 +                should be mapped for merging*/
 +              if (len_squared_v3v3(ov->co, mv->co) < tolerance_sq) {
 +                      BLI_array_append(vtargetmap, i+dm->numVertData);
                }
 -              
 -              if(mmd->flag & MOD_MIR_NO_MERGE)
 -                      isShared = 0;
 -              else
 -                      isShared = ABS(co[axis])<=tolerance;
 -              
 -              /* Because the topology result (# of vertices) must be the same if
 -              * the mesh data is overridden by vertex cos, have to calc sharedness
 -              * based on original coordinates. This is why we test before copy.
 -              */
 -              DM_copy_vert_data(dm, result, i, numVerts, 1);
 -              *mv = inMV;
 -              numVerts++;
 -              
 -              indexMap[i][0] = numVerts - 1;
 -              indexMap[i][1] = !isShared;
 -              //
 -              if(isShared ) {
 -                      co[axis] = 0;
 -                      if (mmd->mirror_ob) {
 -                              mul_m4_v3(imtx, co);
 -                      }
 -                      copy_v3_v3(mv->co, co);
 -                      
 -                      mv->flag |= ME_VERT_MERGED;
 -              } else {
 -                      MVert *mv2 = CDDM_get_vert(result, numVerts);
 -                      
 -                      DM_copy_vert_data(dm, result, i, numVerts, 1);
 -                      *mv2 = *mv;
 -                      
 -                      co[axis] = -co[axis];
 -                      if (mmd->mirror_ob) {
 -                              mul_m4_v3(imtx, co);
 -                      }
 -                      copy_v3_v3(mv2->co, co);
 -                      
 -                      if (do_vgroup_mirr) {
 -                              MDeformVert *dvert= DM_get_vert_data(result, numVerts, CD_MDEFORMVERT);
 -                              if(dvert) {
 -                                      defvert_flip(dvert, flip_map, flip_map_len);
 -                              }
 -                      }
 -
 -                      numVerts++;
 +              else {
 +                      BLI_array_append(vtargetmap, -1);
                }
        }
 -
 -      for(i = 0; i < maxEdges; i++) {
 -              MEdge inMED;
 -              MEdge *med = CDDM_get_edge(result, numEdges);
 -              
 -              dm->getEdge(dm, i, &inMED);
 -              
 -              DM_copy_edge_data(dm, result, i, numEdges, 1);
 -              *med = inMED;
 -              numEdges++;
 -              
 -              med->v1 = indexMap[inMED.v1][0];
 -              med->v2 = indexMap[inMED.v2][0];
 -              if(initFlags)
 -                      med->flag |= ME_EDGEDRAW | ME_EDGERENDER;
 -              
 -              if(indexMap[inMED.v1][1] || indexMap[inMED.v2][1]) {
 -                      MEdge *med2 = CDDM_get_edge(result, numEdges);
 -                      
 -                      DM_copy_edge_data(dm, result, i, numEdges, 1);
 -                      *med2 = *med;
 -                      numEdges++;
 -                      
 -                      med2->v1 += indexMap[inMED.v1][1];
 -                      med2->v2 += indexMap[inMED.v2][1];
 +      
 +      /*handle shape keys*/
 +      totshape = CustomData_number_of_layers(&cddm->vertData, CD_SHAPEKEY);
 +      for (a=0; a<totshape; a++) {
 +              float (*cos)[3] = CustomData_get_layer_n(&cddm->vertData, CD_SHAPEKEY, a);
 +              for (i=dm->numVertData; i<cddm->numVertData; i++) {
 +                      mul_m4_v3(mtx, cos[i]);
                }
        }
 -
 -      for(i = 0; i < maxFaces; i++) {
 -              MFace inMF;
 -              MFace *mf = CDDM_get_face(result, numFaces);
 -              
 -              dm->getFace(dm, i, &inMF);
 -              
 -              DM_copy_face_data(dm, result, i, numFaces, 1);
 -              *mf = inMF;
 -              numFaces++;
 +      
 +      for (i=0; i<dm->numVertData; i++) {
 +              BLI_array_append(vtargetmap, -1);
 +      }
 +      
 +      /*adjust mirrored edge vertex indices*/
 +      me = CDDM_get_edges(cddm) + dm->numEdgeData;
 +      for (i=0; i<dm->numEdgeData; i++, me++) {
 +              me->v1 += dm->numVertData;
 +              me->v2 += dm->numVertData;
 +      }
 +      
 +      /*adjust mirrored poly loopstart indices, and reverse loop order (normals)*/    
 +      mp = CDDM_get_polys(cddm) + dm->numPolyData;
 +      ml = CDDM_get_loops(cddm);
 +      for (i=0; i<dm->numPolyData; i++, mp++) {
 +              MLoop *ml2;
 +              int e;
                
 -              mf->v1 = indexMap[inMF.v1][0];
 -              mf->v2 = indexMap[inMF.v2][0];
 -              mf->v3 = indexMap[inMF.v3][0];
 -              mf->v4 = indexMap[inMF.v4][0];
 +              for (j=0; j<mp->totloop; j++) {
 +                      CustomData_copy_data(&dm->loopData, &cddm->loopData, mp->loopstart+j,
 +                                                               mp->loopstart+dm->numLoopData+mp->totloop-j-1, 1);
 +              }
                
 -              if(indexMap[inMF.v1][1]
 -                               || indexMap[inMF.v2][1]
 -                               || indexMap[inMF.v3][1]
 -                               || (mf->v4 && indexMap[inMF.v4][1])) {
 -                      MFace *mf2 = CDDM_get_face(result, numFaces);
 -                      static int corner_indices[4] = {2, 1, 0, 3};
 -                      
 -                      DM_copy_face_data(dm, result, i, numFaces, 1);
 -                      *mf2 = *mf;
 -                      
 -                      mf2->v1 += indexMap[inMF.v1][1];
 -                      mf2->v2 += indexMap[inMF.v2][1];
 -                      mf2->v3 += indexMap[inMF.v3][1];
 -                      if(inMF.v4) mf2->v4 += indexMap[inMF.v4][1];
 -                      
 -                      /* mirror UVs if enabled */
 -                      if(mmd->flag & (MOD_MIR_MIRROR_U | MOD_MIR_MIRROR_V)) {
 -                              MTFace *tf = result->getFaceData(result, numFaces, CD_MTFACE);
 -                              if(tf) {
 -                                      int j;
 -                                      for(j = 0; j < 4; ++j) {
 -                                              if(mmd->flag & MOD_MIR_MIRROR_U)
 -                                                      tf->uv[j][0] = 1.0f - tf->uv[j][0];
 -                                              if(mmd->flag & MOD_MIR_MIRROR_V)
 -                                                      tf->uv[j][1] = 1.0f - tf->uv[j][1];
 -                                      }
 -                              }
 -                      }
 -                      
 -                      /* Flip face normal */
 -                      SWAP(int, mf2->v1, mf2->v3);
 -                      DM_swap_face_data(result, numFaces, corner_indices);
 -                      
 -                      test_index_face(mf2, &result->faceData, numFaces, inMF.v4?4:3);
 -                      numFaces++;
 +              ml2 = ml + mp->loopstart + dm->numLoopData;
 +              e = ml2[0].e;
 +              for (j=0; j<mp->totloop-1; j++) {
 +                      ml2[j].e = ml2[j+1].e;
                }
 +              ml2[mp->totloop-1].e = e;
 +              
 +              mp->loopstart += dm->numLoopData;
        }
  
 -      if (flip_map) MEM_freeN(flip_map);
 -
 -      MEM_freeN(indexMap);
 +      /*adjust mirrored loop vertex and edge indices*/        
 +      ml = CDDM_get_loops(cddm) + dm->numLoopData;
 +      for (i=0; i<dm->numLoopData; i++, ml++) {
 +              ml->v += dm->numVertData;
 +              ml->e += dm->numEdgeData;
 +      }
  
 -      CDDM_lower_num_verts(result, numVerts);
 -      CDDM_lower_num_edges(result, numEdges);
 -      CDDM_lower_num_faces(result, numFaces);
 +      CDDM_recalc_tesselation(cddm, 1);
 +      
 +      /*handle vgroup stuff*/
 +      if ((mmd->flag & MOD_MIR_VGROUP) && CustomData_has_layer(&cddm->vertData, CD_MDEFORMVERT)) {
 +              MDeformVert *dvert = CustomData_get_layer(&cddm->vertData, CD_MDEFORMVERT);
++              int *flip_map= NULL, flip_map_len= 0;
 -      return result;
++              flip_map= defgroup_flip_map(ob, &flip_map_len, FALSE);
 +              
 +              for (i=0; i<dm->numVertData; i++, dvert++) {
-                       for(j = 0; j < dvert->totweight; ++j) {
-                               char tmpname[32];
-                               if(dvert->dw[j].def_nr < 0 ||
-                                  dvert->dw[j].def_nr >= vector_size)
-                                       continue;
-                               def = vector_def[dvert->dw[j].def_nr];
-                               strcpy(tmpname, def->name);
-                               vertgroup_flip_name(tmpname,0);
-                               for(b = 0, defb = ob->defbase.first; defb;
-                                       defb = defb->next, b++)
-                               {
-                                       if(!strcmp(defb->name, tmpname))
-                                       {
-                                               dvert->dw[j].def_nr = b;
-                                               break;
-                                       }
-                               }
-                       }
++                      defvert_flip(dvert, flip_map, flip_map_len);
 +              }
 +      }
 +      
 +      if (!(mmd->flag & MOD_MIR_NO_MERGE))
 +              cddm = CDDM_merge_verts(cddm, vtargetmap);
 +      
 +      BLI_array_free(vtargetmap);
 +      
 +      if (vector_def) MEM_freeN(vector_def);
 +      
 +      if (dm != origdm) {
 +              dm->needsFree = 1;
 +              dm->release(dm);
 +      }
 +      
 +      return cddm;
  }
  
  static DerivedMesh *mirrorModifier__doMirror(MirrorModifierData *mmd,