bmesh minor refactor
[blender.git] / source / blender / modifiers / intern / MOD_edgesplit.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software  Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2005 by the Blender Foundation.
19  * All rights reserved.
20  *
21  * Contributor(s): Daniel Dunbar
22  *                 Ton Roosendaal,
23  *                 Ben Batt,
24  *                 Brecht Van Lommel,
25  *                 Campbell Barton
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  *
29  */
30
31 /** \file blender/modifiers/intern/MOD_edgesplit.c
32  *  \ingroup modifiers
33  */
34
35
36 /* EdgeSplit modifier: Splits edges in the mesh according to sharpness flag
37  * or edge angle (can be used to achieve autosmoothing) */
38
39 #include "BLI_utildefines.h"
40 #include "BLI_math.h"
41
42 #include "MEM_guardedalloc.h"
43
44 #include "BKE_cdderivedmesh.h"
45 #include "BKE_modifier.h"
46 #include "BKE_tessmesh.h"
47 #include "BKE_mesh.h"
48
49 #include "DNA_object_types.h"
50
51 /* EdgeSplit */
52 /* EdgeSplit modifier: Splits edges in the mesh according to sharpness flag
53  * or edge angle (can be used to achieve autosmoothing)
54  *
55  * note: this code is very close to MOD_bevel.c
56  */
57
58 #define EDGE_MARK       1
59
60 static DerivedMesh *doEdgeSplit(DerivedMesh *dm, EdgeSplitModifierData *emd, Object *ob)
61 {
62         DerivedMesh *result;
63         BMesh *bm;
64         BMEditMesh *em;
65         BMIter iter;
66         BMEdge *e;
67         float threshold = cos((emd->split_angle + 0.00001) * M_PI / 180.0);
68
69         em = DM_to_editbmesh(ob, dm, NULL, FALSE);
70         bm = em->bm;
71
72         BM_mesh_normals_update(bm);     
73         BMO_push(bm, NULL);
74         
75         if (emd->flags & MOD_EDGESPLIT_FROMANGLE) {
76                 BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
77                         /* check for 1 edge having 2 face users */
78                         BMLoop *l1, *l2;
79                         if ( (l1= e->l) &&
80                              (l2= e->l->radial_next) != l1)
81                         {
82                                 if (dot_v3v3(l1->f->no, l2->f->no) < threshold) {
83                                         BMO_elem_flag_set(bm, e, EDGE_MARK);
84                                 }
85                         }
86                 }
87         }
88         
89         if (emd->flags & MOD_EDGESPLIT_FROMFLAG) {
90                 BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
91                         if (BM_elem_flag_test(e, BM_ELEM_SHARP))
92                                 BMO_elem_flag_set(bm, e, EDGE_MARK);
93                 }
94         }
95         
96         BMO_op_callf(bm, "edgesplit edges=%fe", EDGE_MARK);
97         
98         BMO_pop(bm);
99
100         BLI_assert(em->looptris == NULL);
101         result = CDDM_from_BMEditMesh(em, NULL, TRUE, FALSE);
102         BMEdit_Free(em);
103         MEM_freeN(em);
104         
105         return result;
106 }
107
108 static void initData(ModifierData *md)
109 {
110         EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
111
112         /* default to 30-degree split angle, sharpness from both angle & flag
113         */
114         emd->split_angle = 30;
115         emd->flags = MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG;
116 }
117
118 static void copyData(ModifierData *md, ModifierData *target)
119 {
120         EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
121         EdgeSplitModifierData *temd = (EdgeSplitModifierData*) target;
122
123         temd->split_angle = emd->split_angle;
124         temd->flags = emd->flags;
125 }
126
127 static DerivedMesh *edgesplitModifier_do(EdgeSplitModifierData *emd,
128                                          Object *ob, DerivedMesh *dm)
129 {
130         if(!(emd->flags & (MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG)))
131                 return dm;
132
133         return doEdgeSplit(dm, emd, ob);
134 }
135
136 static DerivedMesh *applyModifier(
137                 ModifierData *md, Object *ob, DerivedMesh *derivedData,
138                 int UNUSED(useRenderParams), int UNUSED(isFinalCalc))
139 {
140         DerivedMesh *result;
141         EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
142
143         result = edgesplitModifier_do(emd, ob, derivedData);
144
145         if(result != derivedData)
146                 CDDM_calc_normals(result);
147
148         return result;
149 }
150
151 static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob,
152                                                 struct BMEditMesh *UNUSED(editData),
153                                                 DerivedMesh *derivedData)
154 {
155         return applyModifier(md, ob, derivedData, 0, 1);
156 }
157
158
159 ModifierTypeInfo modifierType_EdgeSplit = {
160         /* name */              "EdgeSplit",
161         /* structName */        "EdgeSplitModifierData",
162         /* structSize */        sizeof(EdgeSplitModifierData),
163         /* type */              eModifierTypeType_Constructive,
164         /* flags */             eModifierTypeFlag_AcceptsMesh
165                                                         | eModifierTypeFlag_AcceptsCVs
166                                                         | eModifierTypeFlag_SupportsMapping
167                                                         | eModifierTypeFlag_SupportsEditmode
168                                                         | eModifierTypeFlag_EnableInEditmode,
169
170         /* copyData */          copyData,
171         /* deformVerts */       NULL,
172         /* deformMatrices */    NULL,
173         /* deformVertsEM */     NULL,
174         /* deformMatricesEM */  NULL,
175         /* applyModifier */     applyModifier,
176         /* applyModifierEM */   applyModifierEM,
177         /* initData */          initData,
178         /* requiredDataMask */  NULL,
179         /* freeData */          NULL,
180         /* isDisabled */        NULL,
181         /* updateDepgraph */    NULL,
182         /* dependsOnTime */     NULL,
183         /* dependsOnNormals */  NULL,
184         /* foreachObjectLink */ NULL,
185         /* foreachIDLink */     NULL,
186         /* foreachTexLink */    NULL,
187 };