Blender V2.61 - r43446
|
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 };