Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/modifiers/intern/MOD_mirror.c')
-rw-r--r--source/blender/modifiers/intern/MOD_mirror.c373
1 files changed, 184 insertions, 189 deletions
diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c
index f551f0f5e7a..2825053050e 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,193 @@ 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;
- 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, 0);
- if(flip_map == NULL)
- do_vgroup_mirr= 0;
+ float tolerance_sq;
+ DerivedMesh *cddm, *origdm;
+ bDeformGroup *def, *defb;
+ 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, b, 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);
- }
- }
-
- 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);
+
+ 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;
- dm->getFace(dm, i, &inMF);
+ 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);
+ }
- DM_copy_face_data(dm, result, i, numFaces, 1);
- *mf = inMF;
- 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;
- mf->v1 = indexMap[inMF.v1][0];
- mf->v2 = indexMap[inMF.v2][0];
- mf->v3 = indexMap[inMF.v3][0];
- mf->v4 = indexMap[inMF.v4][0];
+ mp->loopstart += dm->numLoopData;
+ }
+
+ /*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_recalc_tesselation(cddm, 1);
+
+ /*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);
- 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];
+ for (i=0; i<dm->numVertData; i++, dvert++) {
+ for(j = 0; j < dvert->totweight; ++j) {
+ char tmpname[32];
+
+ if(dvert->dw[j].def_nr < 0 ||
+ dvert->dw[j].def_nr >= vector_size)
+ continue;
+
+ def = vector_def[dvert->dw[j].def_nr];
+ strcpy(tmpname, def->name);
+ vertgroup_flip_name(tmpname,0);
+
+ for(b = 0, defb = ob->defbase.first; defb;
+ defb = defb->next, b++)
+ {
+ if(!strcmp(defb->name, tmpname))
+ {
+ dvert->dw[j].def_nr = b;
+ break;
}
}
}
-
- /* 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++;
}
}
-
- if (flip_map) MEM_freeN(flip_map);
-
- MEM_freeN(indexMap);
-
- CDDM_lower_num_verts(result, numVerts);
- CDDM_lower_num_edges(result, numEdges);
- CDDM_lower_num_faces(result, numFaces);
-
- return result;
+
+ 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 +306,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 +321,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);
}