svn merge ^/trunk/blender -r42957:42967
authorCampbell Barton <ideasman42@gmail.com>
Thu, 29 Dec 2011 06:44:51 +0000 (06:44 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Thu, 29 Dec 2011 06:44:51 +0000 (06:44 +0000)
1  2 
source/blender/modifiers/intern/MOD_mirror.c

@@@ -93,176 -94,195 +93,171 @@@ static void updateDepgraph(ModifierDat
        }
  }
  
- /* Mirror */
- #define VERT_NEW      1
  static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
-               Object *ob,
-               DerivedMesh *dm,
-               int UNUSED(initFlags),
-               int axis)
+                                    Object *ob,
+                                    DerivedMesh *dm,
+                                    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);
 -      unsigned 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;
 +      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, 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);
 -              mult_m4_m4m4(mtx, obinv, ob->obmat);
 -              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);
 +              mult_m4_m4m4(tmp, tmp, ob->obmat);
 +
 +              /*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*/
 +              mult_m4_m4m4(mtx, mtx, tmp);
 +              mult_m4_m4m4(mtx, itmp, mtx);
        }
 -
 -      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);
 -              }
 -              
 -              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;
 -
 -              indexMap[i][0] = numVerts;
 -              indexMap[i][1] = !isShared;
 -
 -              numVerts++;
 -
 -              if(isShared ) {
 -                      co[axis] = 0.0f;
 -                      if (mmd->mirror_ob) {
 -                              mul_m4_v3(imtx, co);
 -                      }
 -                      copy_v3_v3(mv->co, co);
 -                      
 -                      mv->flag |= ME_VERT_MERGED;
 +      
 +      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);
                }
                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++;
 +                      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(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(unsigned 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);
 +      
 +      /*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++) {
 +                      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,