Blender V2.61 - r43446

MOD_mirror.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software  Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2005 by the Blender Foundation.
00019  * All rights reserved.
00020  *
00021  * Contributor(s): Daniel Dunbar
00022  *                 Ton Roosendaal,
00023  *                 Ben Batt,
00024  *                 Brecht Van Lommel,
00025  *                 Campbell Barton
00026  *
00027  * ***** END GPL LICENSE BLOCK *****
00028  *
00029  */
00030 
00036 #include "DNA_meshdata_types.h"
00037 #include "DNA_object_types.h"
00038 
00039 #include "BLI_math.h"
00040 #include "BLI_utildefines.h"
00041 
00042 #include "BKE_cdderivedmesh.h"
00043 #include "BKE_mesh.h"
00044 #include "BKE_modifier.h"
00045 #include "BKE_deform.h"
00046 
00047 
00048 #include "MEM_guardedalloc.h"
00049 #include "depsgraph_private.h"
00050 
00051 #include "MOD_util.h"
00052 
00053 static void initData(ModifierData *md)
00054 {
00055     MirrorModifierData *mmd = (MirrorModifierData*) md;
00056 
00057     mmd->flag |= (MOD_MIR_AXIS_X | MOD_MIR_VGROUP);
00058     mmd->tolerance = 0.001;
00059     mmd->mirror_ob = NULL;
00060 }
00061 
00062 static void copyData(ModifierData *md, ModifierData *target)
00063 {
00064     MirrorModifierData *mmd = (MirrorModifierData*) md;
00065     MirrorModifierData *tmmd = (MirrorModifierData*) target;
00066 
00067     tmmd->flag = mmd->flag;
00068     tmmd->tolerance = mmd->tolerance;
00069     tmmd->mirror_ob = mmd->mirror_ob;
00070 }
00071 
00072 static void foreachObjectLink(
00073                          ModifierData *md, Object *ob,
00074       void (*walk)(void *userData, Object *ob, Object **obpoin),
00075          void *userData)
00076 {
00077     MirrorModifierData *mmd = (MirrorModifierData*) md;
00078 
00079     walk(userData, ob, &mmd->mirror_ob);
00080 }
00081 
00082 static void updateDepgraph(ModifierData *md, DagForest *forest,
00083                         struct Scene *UNUSED(scene),
00084                         Object *UNUSED(ob),
00085                         DagNode *obNode)
00086 {
00087     MirrorModifierData *mmd = (MirrorModifierData*) md;
00088 
00089     if(mmd->mirror_ob) {
00090         DagNode *latNode = dag_get_node(forest, mmd->mirror_ob);
00091 
00092         dag_add_relation(forest, latNode, obNode,
00093                          DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Mirror Modifier");
00094     }
00095 }
00096 
00097 static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
00098                                    Object *ob,
00099                                    DerivedMesh *dm,
00100                                    int axis)
00101 {
00102     int i;
00103     float tolerance = mmd->tolerance;
00104     DerivedMesh *result;
00105     int numVerts, numEdges, numFaces;
00106     int maxVerts = dm->getNumVerts(dm);
00107     int maxEdges = dm->getNumEdges(dm);
00108     int maxFaces = dm->getNumFaces(dm);
00109     int *flip_map= NULL, flip_map_len= 0;
00110     int do_vgroup_mirr= (mmd->flag & MOD_MIR_VGROUP);
00111     unsigned int (*indexMap)[2];
00112     float mtx[4][4], imtx[4][4];
00113 
00114     numVerts = numEdges = numFaces = 0;
00115 
00116     indexMap = MEM_mallocN(sizeof(*indexMap) * maxVerts, "indexmap");
00117 
00118     result = CDDM_from_template(dm, maxVerts * 2, maxEdges * 2, maxFaces * 2);
00119 
00120 
00121     if (do_vgroup_mirr) {
00122         flip_map= defgroup_flip_map(ob, &flip_map_len, FALSE);
00123         if(flip_map == NULL)
00124             do_vgroup_mirr= 0;
00125     }
00126 
00127     if (mmd->mirror_ob) {
00128         float obinv[4][4];
00129         
00130         invert_m4_m4(obinv, mmd->mirror_ob->obmat);
00131         mult_m4_m4m4(mtx, obinv, ob->obmat);
00132         invert_m4_m4(imtx, mtx);
00133     }
00134 
00135     for(i = 0; i < maxVerts; i++) {
00136         MVert inMV;
00137         MVert *mv = CDDM_get_vert(result, numVerts);
00138         int isShared;
00139         float co[3];
00140         
00141         dm->getVert(dm, i, &inMV);
00142         
00143         copy_v3_v3(co, inMV.co);
00144         
00145         if (mmd->mirror_ob) {
00146             mul_m4_v3(mtx, co);
00147         }
00148         
00149         if(mmd->flag & MOD_MIR_NO_MERGE)
00150             isShared = 0;
00151         else
00152             isShared = ABS(co[axis])<=tolerance;
00153         
00154         /* Because the topology result (# of vertices) must be the same if
00155          * the mesh data is overridden by vertex cos, have to calc sharedness
00156          * based on original coordinates. This is why we test before copy.
00157          */
00158         DM_copy_vert_data(dm, result, i, numVerts, 1);
00159         *mv = inMV;
00160 
00161         indexMap[i][0] = numVerts;
00162         indexMap[i][1] = !isShared;
00163 
00164         numVerts++;
00165 
00166         if(isShared ) {
00167             co[axis] = 0.0f;
00168             if (mmd->mirror_ob) {
00169                 mul_m4_v3(imtx, co);
00170             }
00171             copy_v3_v3(mv->co, co);
00172             
00173             mv->flag |= ME_VERT_MERGED;
00174         }
00175         else {
00176             MVert *mv2 = CDDM_get_vert(result, numVerts);
00177             
00178             DM_copy_vert_data(dm, result, i, numVerts, 1);
00179             *mv2 = *mv;
00180             
00181             co[axis] = -co[axis];
00182             if (mmd->mirror_ob) {
00183                 mul_m4_v3(imtx, co);
00184             }
00185             copy_v3_v3(mv2->co, co);
00186             
00187             if (do_vgroup_mirr) {
00188                 MDeformVert *dvert= DM_get_vert_data(result, numVerts, CD_MDEFORMVERT);
00189                 if(dvert) {
00190                     defvert_flip(dvert, flip_map, flip_map_len);
00191                 }
00192             }
00193 
00194             numVerts++;
00195         }
00196     }
00197 
00198     for(i = 0; i < maxEdges; i++) {
00199         MEdge inMED;
00200         MEdge *med = CDDM_get_edge(result, numEdges);
00201         
00202         dm->getEdge(dm, i, &inMED);
00203         
00204         DM_copy_edge_data(dm, result, i, numEdges, 1);
00205         *med = inMED;
00206         numEdges++;
00207         
00208         med->v1 = indexMap[inMED.v1][0];
00209         med->v2 = indexMap[inMED.v2][0];
00210         
00211         if(indexMap[inMED.v1][1] || indexMap[inMED.v2][1]) {
00212             MEdge *med2 = CDDM_get_edge(result, numEdges);
00213             
00214             DM_copy_edge_data(dm, result, i, numEdges, 1);
00215             *med2 = *med;
00216             numEdges++;
00217             
00218             med2->v1 += indexMap[inMED.v1][1];
00219             med2->v2 += indexMap[inMED.v2][1];
00220         }
00221     }
00222 
00223     for(i = 0; i < maxFaces; i++) {
00224         MFace inMF;
00225         MFace *mf = CDDM_get_face(result, numFaces);
00226         
00227         dm->getFace(dm, i, &inMF);
00228         
00229         DM_copy_face_data(dm, result, i, numFaces, 1);
00230         *mf = inMF;
00231         numFaces++;
00232         
00233         mf->v1 = indexMap[inMF.v1][0];
00234         mf->v2 = indexMap[inMF.v2][0];
00235         mf->v3 = indexMap[inMF.v3][0];
00236         mf->v4 = indexMap[inMF.v4][0];
00237         
00238         if ( indexMap[inMF.v1][1] ||
00239              indexMap[inMF.v2][1] ||
00240              indexMap[inMF.v3][1] ||
00241              (mf->v4 && indexMap[inMF.v4][1]))
00242         {
00243             MFace *mf2 = CDDM_get_face(result, numFaces);
00244             static int corner_indices[4] = {2, 1, 0, 3};
00245             
00246             DM_copy_face_data(dm, result, i, numFaces, 1);
00247             *mf2 = *mf;
00248             
00249             mf2->v1 += indexMap[inMF.v1][1];
00250             mf2->v2 += indexMap[inMF.v2][1];
00251             mf2->v3 += indexMap[inMF.v3][1];
00252             if(inMF.v4) mf2->v4 += indexMap[inMF.v4][1];
00253             
00254             /* mirror UVs if enabled */
00255             if(mmd->flag & (MOD_MIR_MIRROR_U | MOD_MIR_MIRROR_V)) {
00256                 MTFace *tf = result->getFaceData(result, numFaces, CD_MTFACE);
00257                 if(tf) {
00258                     int j;
00259                     for(j = 0; j < 4; ++j) {
00260                         if(mmd->flag & MOD_MIR_MIRROR_U)
00261                             tf->uv[j][0] = 1.0f - tf->uv[j][0];
00262                         if(mmd->flag & MOD_MIR_MIRROR_V)
00263                             tf->uv[j][1] = 1.0f - tf->uv[j][1];
00264                     }
00265                 }
00266             }
00267             
00268             /* Flip face normal */
00269             SWAP(unsigned int, mf2->v1, mf2->v3);
00270             DM_swap_face_data(result, numFaces, corner_indices);
00271             
00272             test_index_face(mf2, &result->faceData, numFaces, inMF.v4?4:3);
00273             numFaces++;
00274         }
00275     }
00276 
00277     if (flip_map) MEM_freeN(flip_map);
00278 
00279     MEM_freeN(indexMap);
00280 
00281     CDDM_lower_num_verts(result, numVerts);
00282     CDDM_lower_num_edges(result, numEdges);
00283     CDDM_lower_num_faces(result, numFaces);
00284 
00285     return result;
00286 }
00287 
00288 static DerivedMesh *mirrorModifier__doMirror(MirrorModifierData *mmd,
00289                         Object *ob, DerivedMesh *dm)
00290 {
00291     DerivedMesh *result = dm;
00292 
00293     /* check which axes have been toggled and mirror accordingly */
00294     if(mmd->flag & MOD_MIR_AXIS_X) {
00295         result = doMirrorOnAxis(mmd, ob, result, 0);
00296     }
00297     if(mmd->flag & MOD_MIR_AXIS_Y) {
00298         DerivedMesh *tmp = result;
00299         result = doMirrorOnAxis(mmd, ob, result, 1);
00300         if(tmp != dm) tmp->release(tmp); /* free intermediate results */
00301     }
00302     if(mmd->flag & MOD_MIR_AXIS_Z) {
00303         DerivedMesh *tmp = result;
00304         result = doMirrorOnAxis(mmd, ob, result, 2);
00305         if(tmp != dm) tmp->release(tmp); /* free intermediate results */
00306     }
00307 
00308     return result;
00309 }
00310 
00311 static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
00312                         DerivedMesh *derivedData,
00313                         int UNUSED(useRenderParams),
00314                         int UNUSED(isFinalCalc))
00315 {
00316     DerivedMesh *result;
00317     MirrorModifierData *mmd = (MirrorModifierData*) md;
00318 
00319     result = mirrorModifier__doMirror(mmd, ob, derivedData);
00320 
00321     if(result != derivedData)
00322         CDDM_calc_normals(result);
00323     
00324     return result;
00325 }
00326 
00327 static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob,
00328                         struct EditMesh *UNUSED(editData),
00329                         DerivedMesh *derivedData)
00330 {
00331     return applyModifier(md, ob, derivedData, 0, 1);
00332 }
00333 
00334 
00335 ModifierTypeInfo modifierType_Mirror = {
00336     /* name */              "Mirror",
00337     /* structName */        "MirrorModifierData",
00338     /* structSize */        sizeof(MirrorModifierData),
00339     /* type */              eModifierTypeType_Constructive,
00340     /* flags */             eModifierTypeFlag_AcceptsMesh
00341                             | eModifierTypeFlag_SupportsMapping
00342                             | eModifierTypeFlag_SupportsEditmode
00343                             | eModifierTypeFlag_EnableInEditmode
00344                             | eModifierTypeFlag_AcceptsCVs,
00345 
00346     /* copyData */          copyData,
00347     /* deformVerts */       NULL,
00348     /* deformMatrices */    NULL,
00349     /* deformVertsEM */     NULL,
00350     /* deformMatricesEM */  NULL,
00351     /* applyModifier */     applyModifier,
00352     /* applyModifierEM */   applyModifierEM,
00353     /* initData */          initData,
00354     /* requiredDataMask */  NULL,
00355     /* freeData */          NULL,
00356     /* isDisabled */        NULL,
00357     /* updateDepgraph */    updateDepgraph,
00358     /* dependsOnTime */     NULL,
00359     /* dependsOnNormals */  NULL,
00360     /* foreachObjectLink */ foreachObjectLink,
00361     /* foreachIDLink */     NULL,
00362     /* foreachTexLink */    NULL,
00363 };