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.c349
1 files changed, 349 insertions, 0 deletions
diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c
new file mode 100644
index 00000000000..442202655ee
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_mirror.c
@@ -0,0 +1,349 @@
+/*
+* $Id$
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+
+#include "DNA_meshdata_types.h"
+
+#include "BLI_math.h"
+
+#include "BKE_cdderivedmesh.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_deform.h"
+#include "BKE_utildefines.h"
+
+#include "MEM_guardedalloc.h"
+#include "depsgraph_private.h"
+
+static void initData(ModifierData *md)
+{
+ MirrorModifierData *mmd = (MirrorModifierData*) md;
+
+ mmd->flag |= (MOD_MIR_AXIS_X | MOD_MIR_VGROUP);
+ mmd->tolerance = 0.001;
+ mmd->mirror_ob = NULL;
+}
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ MirrorModifierData *mmd = (MirrorModifierData*) md;
+ MirrorModifierData *tmmd = (MirrorModifierData*) target;
+
+ tmmd->axis = mmd->axis;
+ tmmd->flag = mmd->flag;
+ tmmd->tolerance = mmd->tolerance;
+ tmmd->mirror_ob = mmd->mirror_ob;;
+}
+
+static void foreachObjectLink(
+ ModifierData *md, Object *ob,
+ void (*walk)(void *userData, Object *ob, Object **obpoin),
+ void *userData)
+{
+ MirrorModifierData *mmd = (MirrorModifierData*) md;
+
+ walk(userData, ob, &mmd->mirror_ob);
+}
+
+static void updateDepgraph(ModifierData *md, DagForest *forest, struct Scene *scene,
+ Object *ob, DagNode *obNode)
+{
+ MirrorModifierData *mmd = (MirrorModifierData*) md;
+
+ if(mmd->mirror_ob) {
+ DagNode *latNode = dag_get_node(forest, mmd->mirror_ob);
+
+ dag_add_relation(forest, latNode, obNode,
+ DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Mirror Modifier");
+ }
+}
+
+static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
+ Object *ob,
+ DerivedMesh *dm,
+ int 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;
+ }
+
+ 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);
+ }
+
+ 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);
+ }
+ 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++;
+ }
+ }
+
+ 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];
+ }
+ }
+
+ 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++;
+
+ mf->v1 = indexMap[inMF.v1][0];
+ mf->v2 = indexMap[inMF.v2][0];
+ mf->v3 = indexMap[inMF.v3][0];
+ mf->v4 = indexMap[inMF.v4][0];
+
+ 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++;
+ }
+ }
+
+ 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;
+}
+
+static DerivedMesh *mirrorModifier__doMirror(MirrorModifierData *mmd,
+ Object *ob, DerivedMesh *dm,
+ int initFlags)
+{
+ DerivedMesh *result = dm;
+
+ /* check which axes have been toggled and mirror accordingly */
+ if(mmd->flag & MOD_MIR_AXIS_X) {
+ result = doMirrorOnAxis(mmd, ob, result, initFlags, 0);
+ }
+ if(mmd->flag & MOD_MIR_AXIS_Y) {
+ DerivedMesh *tmp = result;
+ result = doMirrorOnAxis(mmd, ob, result, initFlags, 1);
+ if(tmp != dm) tmp->release(tmp); /* free intermediate results */
+ }
+ if(mmd->flag & MOD_MIR_AXIS_Z) {
+ DerivedMesh *tmp = result;
+ result = doMirrorOnAxis(mmd, ob, result, initFlags, 2);
+ if(tmp != dm) tmp->release(tmp); /* free intermediate results */
+ }
+
+ return result;
+}
+
+static DerivedMesh *applyModifier(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ int useRenderParams, int isFinalCalc)
+{
+ DerivedMesh *result;
+ MirrorModifierData *mmd = (MirrorModifierData*) md;
+
+ result = mirrorModifier__doMirror(mmd, ob, derivedData, 0);
+
+ if(result != derivedData)
+ CDDM_calc_normals(result);
+
+ return result;
+}
+
+static DerivedMesh *applyModifierEM(
+ ModifierData *md, Object *ob, struct EditMesh *editData,
+ DerivedMesh *derivedData)
+{
+ return applyModifier(md, ob, derivedData, 0, 1);
+}
+
+
+ModifierTypeInfo modifierType_Mirror = {
+ /* name */ "Mirror",
+ /* structName */ "MirrorModifierData",
+ /* structSize */ sizeof(MirrorModifierData),
+ /* type */ eModifierTypeType_Constructive,
+ /* flags */ eModifierTypeFlag_AcceptsMesh
+ | eModifierTypeFlag_SupportsMapping
+ | eModifierTypeFlag_SupportsEditmode
+ | eModifierTypeFlag_EnableInEditmode
+ | eModifierTypeFlag_AcceptsCVs,
+
+ /* copyData */ copyData,
+ /* deformVerts */ 0,
+ /* deformVertsEM */ 0,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ applyModifier,
+ /* applyModifierEM */ applyModifierEM,
+ /* initData */ initData,
+ /* requiredDataMask */ 0,
+ /* freeData */ 0,
+ /* isDisabled */ 0,
+ /* updateDepgraph */ updateDepgraph,
+ /* dependsOnTime */ 0,
+ /* foreachObjectLink */ foreachObjectLink,
+ /* foreachIDLink */ 0,
+};