ClangFormat: apply to source, most of intern
[blender.git] / source / blender / blenkernel / intern / editmesh.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  * The Original Code is Copyright (C) 2005 Blender Foundation.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup bke
22  */
23
24 #include "MEM_guardedalloc.h"
25
26 #include "DNA_listBase.h"
27 #include "DNA_object_types.h"
28 #include "DNA_mesh_types.h"
29
30 #include "BLI_math.h"
31
32 #include "BKE_editmesh.h"
33 #include "BKE_cdderivedmesh.h"
34 #include "BKE_library.h"
35
36 BMEditMesh *BKE_editmesh_create(BMesh *bm, const bool do_tessellate)
37 {
38   BMEditMesh *em = MEM_callocN(sizeof(BMEditMesh), __func__);
39
40   em->bm = bm;
41   if (do_tessellate) {
42     BKE_editmesh_tessface_calc(em);
43   }
44
45   return em;
46 }
47
48 BMEditMesh *BKE_editmesh_copy(BMEditMesh *em)
49 {
50   BMEditMesh *em_copy = MEM_callocN(sizeof(BMEditMesh), __func__);
51   *em_copy = *em;
52
53   em_copy->mesh_eval_cage = em_copy->mesh_eval_final = NULL;
54
55   em_copy->derivedVertColor = NULL;
56   em_copy->derivedVertColorLen = 0;
57   em_copy->derivedFaceColor = NULL;
58   em_copy->derivedFaceColorLen = 0;
59
60   em_copy->bm = BM_mesh_copy(em->bm);
61
62   /* The tessellation is NOT calculated on the copy here,
63    * because currently all the callers of this function use
64    * it to make a backup copy of the BMEditMesh to restore
65    * it in the case of errors in an operation. For perf
66    * reasons, in that case it makes more sense to do the
67    * tessellation only when/if that copy ends up getting
68    * used.*/
69   em_copy->looptris = NULL;
70
71   return em_copy;
72 }
73
74 /**
75  * \brief Return the BMEditMesh for a given object
76  *
77  * \note this function assumes this is a mesh object,
78  * don't add NULL data check here. caller must do that
79  */
80 BMEditMesh *BKE_editmesh_from_object(Object *ob)
81 {
82   BLI_assert(ob->type == OB_MESH);
83   /* sanity check */
84 #if 0 /* disable in mutlti-object edit. */
85 #  ifndef NDEBUG
86   if (((Mesh *)ob->data)->edit_mesh) {
87     BLI_assert(((Mesh *)ob->data)->edit_mesh->ob == ob);
88   }
89 #  endif
90 #endif
91   return ((Mesh *)ob->data)->edit_mesh;
92 }
93
94 static void editmesh_tessface_calc_intern(BMEditMesh *em)
95 {
96   /* allocating space before calculating the tessellation */
97
98   BMesh *bm = em->bm;
99
100   /* this assumes all faces can be scan-filled, which isn't always true,
101    * worst case we over alloc a little which is acceptable */
102   const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop);
103   const int looptris_tot_prev_alloc = em->looptris ?
104                                           (MEM_allocN_len(em->looptris) / sizeof(*em->looptris)) :
105                                           0;
106
107   BMLoop *(*looptris)[3];
108
109   /* this means no reallocs for quad dominant models, for */
110   if ((em->looptris != NULL) &&
111       /* (*em->tottri >= looptris_tot)) */
112       /* check against alloc'd size incase we over alloc'd a little */
113       ((looptris_tot_prev_alloc >= looptris_tot) &&
114        (looptris_tot_prev_alloc <= looptris_tot * 2))) {
115     looptris = em->looptris;
116   }
117   else {
118     if (em->looptris)
119       MEM_freeN(em->looptris);
120     looptris = MEM_mallocN(sizeof(*looptris) * looptris_tot, __func__);
121   }
122
123   em->looptris = looptris;
124
125   /* after allocating the em->looptris, we're ready to tessellate */
126   BM_mesh_calc_tessellation(em->bm, em->looptris, &em->tottri);
127 }
128
129 void BKE_editmesh_tessface_calc(BMEditMesh *em)
130 {
131   editmesh_tessface_calc_intern(em);
132
133   /* commented because editbmesh_build_data() ensures we get tessfaces */
134 #if 0
135   if (em->mesh_eval_final && em->mesh_eval_final == em->mesh_eval_cage) {
136     BKE_mesh_runtime_looptri_ensure(em->mesh_eval_final);
137   }
138   else if (em->mesh_eval_final) {
139     BKE_mesh_runtime_looptri_ensure(em->mesh_eval_final);
140     BKE_mesh_runtime_looptri_ensure(em->mesh_eval_cage);
141   }
142 #endif
143 }
144
145 void BKE_editmesh_free_derivedmesh(BMEditMesh *em)
146 {
147   if (em->mesh_eval_cage) {
148     BKE_id_free(NULL, em->mesh_eval_cage);
149   }
150   if (em->mesh_eval_final && em->mesh_eval_final != em->mesh_eval_cage) {
151     BKE_id_free(NULL, em->mesh_eval_final);
152   }
153   em->mesh_eval_cage = em->mesh_eval_final = NULL;
154 }
155
156 /*does not free the BMEditMesh struct itself*/
157 void BKE_editmesh_free(BMEditMesh *em)
158 {
159   BKE_editmesh_free_derivedmesh(em);
160
161   BKE_editmesh_color_free(em);
162
163   if (em->looptris)
164     MEM_freeN(em->looptris);
165
166   if (em->bm)
167     BM_mesh_free(em->bm);
168 }
169
170 void BKE_editmesh_color_free(BMEditMesh *em)
171 {
172   if (em->derivedVertColor)
173     MEM_freeN(em->derivedVertColor);
174   if (em->derivedFaceColor)
175     MEM_freeN(em->derivedFaceColor);
176   em->derivedVertColor = NULL;
177   em->derivedFaceColor = NULL;
178
179   em->derivedVertColorLen = 0;
180   em->derivedFaceColorLen = 0;
181 }
182
183 void BKE_editmesh_color_ensure(BMEditMesh *em, const char htype)
184 {
185   switch (htype) {
186     case BM_VERT:
187       if (em->derivedVertColorLen != em->bm->totvert) {
188         BKE_editmesh_color_free(em);
189         em->derivedVertColor = MEM_mallocN(sizeof(*em->derivedVertColor) * em->bm->totvert,
190                                            __func__);
191         em->derivedVertColorLen = em->bm->totvert;
192       }
193       break;
194     case BM_FACE:
195       if (em->derivedFaceColorLen != em->bm->totface) {
196         BKE_editmesh_color_free(em);
197         em->derivedFaceColor = MEM_mallocN(sizeof(*em->derivedFaceColor) * em->bm->totface,
198                                            __func__);
199         em->derivedFaceColorLen = em->bm->totface;
200       }
201       break;
202     default:
203       BLI_assert(0);
204       break;
205   }
206 }
207
208 float (*BKE_editmesh_vertexCos_get_orco(BMEditMesh *em, int *r_numVerts))[3]
209 {
210   BMIter iter;
211   BMVert *eve;
212   float(*orco)[3];
213   int i;
214
215   orco = MEM_mallocN(em->bm->totvert * sizeof(*orco), __func__);
216
217   BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
218     copy_v3_v3(orco[i], eve->co);
219   }
220
221   *r_numVerts = em->bm->totvert;
222
223   return orco;
224 }
225
226 void BKE_editmesh_lnorspace_update(BMEditMesh *em)
227 {
228   BMesh *bm = em->bm;
229
230   /* We need to create clnors data if none exist yet, otherwise there is no way to edit them.
231    * Similar code to MESH_OT_customdata_custom_splitnormals_add operator, we want to keep same shading
232    * in case we were using autosmooth so far...
233    * Note: there is a problem here, which is that if someone starts a normal editing operation on previously
234    * autosmooth-ed mesh, and cancel that operation, generated clnors data remain, with related sharp edges
235    * (and hence autosmooth is 'lost').
236    * Not sure how critical this is, and how to fix that issue? */
237   if (!CustomData_has_layer(&bm->ldata, CD_CUSTOMLOOPNORMAL)) {
238     Mesh *me = em->ob->data;
239     if (me->flag & ME_AUTOSMOOTH) {
240       BM_edges_sharp_from_angle_set(bm, me->smoothresh);
241     }
242   }
243
244   BM_lnorspace_update(bm);
245 }