e39698e142ec62f3d4920f8390717819c50e99d2
[blender.git] / source / blender / modifiers / intern / MOD_triangulate.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software  Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16
17 /** \file
18  * \ingroup modifiers
19  */
20
21 #include "MEM_guardedalloc.h"
22
23 #include "BLI_utildefines.h"
24
25 #include "DNA_mesh_types.h"
26 #include "DNA_meshdata_types.h"
27 #include "DNA_object_types.h"
28
29 #include "BKE_modifier.h"
30 #include "BKE_mesh.h"
31
32 #include "bmesh.h"
33 #include "bmesh_tools.h"
34
35 #include "MOD_modifiertypes.h"
36
37 static Mesh *triangulate_mesh(Mesh *mesh, const int quad_method, const int ngon_method, const int flag)
38 {
39         Mesh *result;
40         BMesh *bm;
41         int total_edges, i;
42         MEdge *me;
43         CustomData_MeshMasks cddata_masks = {.vmask = CD_MASK_ORIGINDEX, .emask = CD_MASK_ORIGINDEX, .pmask = CD_MASK_ORIGINDEX};
44
45         bool keep_clnors = (flag & MOD_TRIANGULATE_KEEP_CUSTOMLOOP_NORMALS) != 0;
46
47         if (keep_clnors) {
48                 BKE_mesh_calc_normals_split(mesh);
49                 /* We need that one to 'survive' to/from BMesh conversions. */
50                 CustomData_clear_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
51                 cddata_masks.lmask |= CD_MASK_NORMAL;
52         }
53
54         bm = BKE_mesh_to_bmesh_ex(
55                 mesh,
56                 &((struct BMeshCreateParams){0}),
57                 &((struct BMeshFromMeshParams){
58                     .calc_face_normal = true,
59                     .cd_mask_extra = cddata_masks,
60                 }));
61
62         BM_mesh_triangulate(bm, quad_method, ngon_method, false, NULL, NULL, NULL);
63
64         result = BKE_mesh_from_bmesh_for_eval_nomain(bm, &cddata_masks);
65         BM_mesh_free(bm);
66
67
68         if (keep_clnors) {
69                 float (*lnors)[3] = CustomData_get_layer(&result->ldata, CD_NORMAL);
70                 BLI_assert(lnors != NULL);
71
72                 BKE_mesh_set_custom_normals(result, lnors);
73
74                 /* Do some cleanup, we do not want those temp data to stay around. */
75                 CustomData_set_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
76                 CustomData_set_layer_flag(&result->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
77         }
78
79         total_edges = result->totedge;
80         me = result->medge;
81
82         /* force drawing of all edges (seems to be omitted in CDDM_from_bmesh) */
83         for (i = 0; i < total_edges; i++, me++) {
84                 me->flag |= ME_EDGEDRAW | ME_EDGERENDER;
85         }
86
87         result->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
88
89         return result;
90 }
91
92
93 static void initData(ModifierData *md)
94 {
95         TriangulateModifierData *tmd = (TriangulateModifierData *)md;
96
97         /* Enable in editmode by default */
98         md->mode |= eModifierMode_Editmode;
99         tmd->quad_method = MOD_TRIANGULATE_QUAD_SHORTEDGE;
100         tmd->ngon_method = MOD_TRIANGULATE_NGON_BEAUTY;
101 }
102
103 static Mesh *applyModifier(
104         ModifierData *md,
105         const ModifierEvalContext *UNUSED(ctx),
106         Mesh *mesh)
107 {
108         TriangulateModifierData *tmd = (TriangulateModifierData *)md;
109         Mesh *result;
110         if (!(result = triangulate_mesh(mesh, tmd->quad_method, tmd->ngon_method, tmd->flag))) {
111                 return mesh;
112         }
113
114         return result;
115 }
116
117 ModifierTypeInfo modifierType_Triangulate = {
118         /* name */              "Triangulate",
119         /* structName */        "TriangulateModifierData",
120         /* structSize */        sizeof(TriangulateModifierData),
121         /* type */              eModifierTypeType_Constructive,
122         /* flags */             eModifierTypeFlag_AcceptsMesh |
123                                 eModifierTypeFlag_SupportsEditmode |
124                                 eModifierTypeFlag_SupportsMapping |
125                                 eModifierTypeFlag_EnableInEditmode |
126                                 eModifierTypeFlag_AcceptsCVs,
127
128         /* copyData */          modifier_copyData_generic,
129
130         /* deformVerts_DM */    NULL,
131         /* deformMatrices_DM */ NULL,
132         /* deformVertsEM_DM */  NULL,
133         /* deformMatricesEM_DM*/NULL,
134         /* applyModifier_DM */  NULL,
135
136         /* deformVerts */       NULL,
137         /* deformMatrices */    NULL,
138         /* deformVertsEM */     NULL,
139         /* deformMatricesEM */  NULL,
140         /* applyModifier */     applyModifier,
141
142         /* initData */          initData,
143         /* requiredDataMask */  NULL, //requiredDataMask,
144         /* freeData */          NULL,
145         /* isDisabled */        NULL,
146         /* updateDepsgraph */   NULL,
147         /* dependsOnTime */     NULL,
148         /* dependsOnNormals */  NULL,
149         /* foreachObjectLink */ NULL,
150         /* foreachIDLink */     NULL,
151         /* freeRuntimeData */   NULL,
152 };