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