diff options
Diffstat (limited to 'source/blender/modifiers/intern/MOD_mirror.c')
-rw-r--r-- | source/blender/modifiers/intern/MOD_mirror.c | 360 |
1 files changed, 169 insertions, 191 deletions
diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c index 2e744337b97..d3d5babb41e 100644 --- a/source/blender/modifiers/intern/MOD_mirror.c +++ b/source/blender/modifiers/intern/MOD_mirror.c @@ -28,27 +28,26 @@ * */ -/** \file blender/modifiers/intern/MOD_mirror.c - * \ingroup modifiers - */ - - #include "DNA_meshdata_types.h" #include "DNA_object_types.h" +#include "MEM_guardedalloc.h" + #include "BLI_math.h" -#include "BLI_utildefines.h" +#include "BLI_smallhash.h" +#include "BLI_array.h" #include "BKE_cdderivedmesh.h" #include "BKE_mesh.h" #include "BKE_modifier.h" #include "BKE_deform.h" +#include "BKE_utildefines.h" +#include "BKE_tessmesh.h" - -#include "MEM_guardedalloc.h" #include "depsgraph_private.h" -#include "MOD_util.h" +/*from MOD_array.c*/ +void vertgroup_flip_name (char *name, int strip_number); static void initData(ModifierData *md) { @@ -76,14 +75,13 @@ static void foreachObjectLink( void *userData) { MirrorModifierData *mmd = (MirrorModifierData*) md; - - walk(userData, ob, &mmd->mirror_ob); + + if (mmd->mirror_ob) + walk(userData, ob, &mmd->mirror_ob); } -static void updateDepgraph(ModifierData *md, DagForest *forest, - struct Scene *UNUSED(scene), - Object *UNUSED(ob), - DagNode *obNode) +static void updateDepgraph(ModifierData *md, DagForest *forest, struct Scene *UNUSED(scene), + Object *UNUSED(ob), DagNode *obNode) { MirrorModifierData *mmd = (MirrorModifierData*) md; @@ -95,195 +93,176 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, } } -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; + 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); - 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); + + /*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, @@ -310,10 +289,9 @@ static DerivedMesh *mirrorModifier__doMirror(MirrorModifierData *mmd, return result; } -static DerivedMesh *applyModifier(ModifierData *md, Object *ob, - DerivedMesh *derivedData, - int UNUSED(useRenderParams), - int UNUSED(isFinalCalc)) +static DerivedMesh *applyModifier( + ModifierData *md, Object *ob, DerivedMesh *derivedData, + int UNUSED(useRenderParams), int UNUSED(isFinalCalc)) { DerivedMesh *result; MirrorModifierData *mmd = (MirrorModifierData*) md; @@ -326,9 +304,9 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, return result; } -static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob, - struct EditMesh *UNUSED(editData), - DerivedMesh *derivedData) +static DerivedMesh *applyModifierEM( + ModifierData *md, Object *ob, struct BMEditMesh *UNUSED(editData), + DerivedMesh *derivedData) { return applyModifier(md, ob, derivedData, 0, 1); } |