Merge branch 'master' into blender2.8
[blender.git] / source / blender / modifiers / intern / MOD_solidify.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): Campbell Barton
22  *                 Shinsuke Irie
23  *                 Martin Felke
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  *
27  */
28
29 /** \file blender/modifiers/intern/MOD_solidify.c
30  *  \ingroup modifiers
31  */
32
33 #include "DNA_mesh_types.h"
34 #include "DNA_meshdata_types.h"
35
36 #include "MEM_guardedalloc.h"
37
38 #include "BLI_utildefines.h"
39 #include "BLI_utildefines_stack.h"
40 #include "BLI_bitmap.h"
41 #include "BLI_math.h"
42
43 #include "BKE_cdderivedmesh.h"
44 #include "BKE_mesh.h"
45 #include "BKE_particle.h"
46 #include "BKE_deform.h"
47
48 #include "MOD_modifiertypes.h"
49 #include "MOD_util.h"
50
51 #ifdef __GNUC__
52 #  pragma GCC diagnostic error "-Wsign-conversion"
53 #endif
54
55 /* skip shell thickness for non-manifold edges, see [#35710] */
56 #define USE_NONMANIFOLD_WORKAROUND
57
58 /* *** derived mesh high quality normal calculation function  *** */
59 /* could be exposed for other functions to use */
60
61 typedef struct EdgeFaceRef {
62         int f1; /* init as -1 */
63         int f2;
64 } EdgeFaceRef;
65
66 BLI_INLINE bool edgeref_is_init(const EdgeFaceRef *edge_ref)
67 {
68         return !((edge_ref->f1 == 0) && (edge_ref->f2 == 0));
69 }
70
71 /**
72  * \param dm  Mesh to calculate normals for.
73  * \param face_nors  Precalculated face normals.
74  * \param r_vert_nors  Return vert normals.
75  */
76 static void mesh_calc_hq_normal(Mesh *mesh, float (*face_nors)[3], float (*r_vert_nors)[3])
77 {
78         int i, numVerts, numEdges, numFaces;
79         MPoly *mpoly, *mp;
80         MLoop *mloop, *ml;
81         MEdge *medge, *ed;
82         MVert *mvert, *mv;
83
84         numVerts = mesh->totvert;
85         numEdges = mesh->totedge;
86         numFaces = mesh->totface;
87         mpoly = mesh->mpoly;
88         medge = mesh->medge;
89         mvert = mesh->mvert;
90         mloop = mesh->mloop;
91
92         /* we don't want to overwrite any referenced layers */
93
94         /* Doesn't work here! */
95 #if 0
96         mv = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, numVerts);
97         cddm->mvert = mv;
98 #endif
99
100         mv = mvert;
101         mp = mpoly;
102
103         {
104                 EdgeFaceRef *edge_ref_array = MEM_calloc_arrayN((size_t)numEdges, sizeof(EdgeFaceRef), "Edge Connectivity");
105                 EdgeFaceRef *edge_ref;
106                 float edge_normal[3];
107
108                 /* Add an edge reference if it's not there, pointing back to the face index. */
109                 for (i = 0; i < numFaces; i++, mp++) {
110                         int j;
111
112                         ml = mloop + mp->loopstart;
113
114                         for (j = 0; j < mp->totloop; j++, ml++) {
115                                 /* --- add edge ref to face --- */
116                                 edge_ref = &edge_ref_array[ml->e];
117                                 if (!edgeref_is_init(edge_ref)) {
118                                         edge_ref->f1 =  i;
119                                         edge_ref->f2 = -1;
120                                 }
121                                 else if ((edge_ref->f1 != -1) && (edge_ref->f2 == -1)) {
122                                         edge_ref->f2 = i;
123                                 }
124                                 else {
125                                         /* 3+ faces using an edge, we can't handle this usefully */
126                                         edge_ref->f1 = edge_ref->f2 = -1;
127 #ifdef USE_NONMANIFOLD_WORKAROUND
128                                         medge[ml->e].flag |= ME_EDGE_TMP_TAG;
129 #endif
130                                 }
131                                 /* --- done --- */
132                         }
133                 }
134
135                 for (i = 0, ed = medge, edge_ref = edge_ref_array; i < numEdges; i++, ed++, edge_ref++) {
136                         /* Get the edge vert indices, and edge value (the face indices that use it) */
137
138                         if (edgeref_is_init(edge_ref) && (edge_ref->f1 != -1)) {
139                                 if (edge_ref->f2 != -1) {
140                                         /* We have 2 faces using this edge, calculate the edges normal
141                                          * using the angle between the 2 faces as a weighting */
142 #if 0
143                                         add_v3_v3v3(edge_normal, face_nors[edge_ref->f1], face_nors[edge_ref->f2]);
144                                         normalize_v3_length(
145                                                 edge_normal,
146                                                 angle_normalized_v3v3(face_nors[edge_ref->f1], face_nors[edge_ref->f2]));
147 #else
148                                         mid_v3_v3v3_angle_weighted(edge_normal, face_nors[edge_ref->f1], face_nors[edge_ref->f2]);
149 #endif
150                                 }
151                                 else {
152                                         /* only one face attached to that edge */
153                                         /* an edge without another attached- the weight on this is undefined */
154                                         copy_v3_v3(edge_normal, face_nors[edge_ref->f1]);
155                                 }
156                                 add_v3_v3(r_vert_nors[ed->v1], edge_normal);
157                                 add_v3_v3(r_vert_nors[ed->v2], edge_normal);
158                         }
159                 }
160                 MEM_freeN(edge_ref_array);
161         }
162
163         /* normalize vertex normals and assign */
164         for (i = 0; i < numVerts; i++, mv++) {
165                 if (normalize_v3(r_vert_nors[i]) == 0.0f) {
166                         normal_short_to_float_v3(r_vert_nors[i], mv->no);
167                 }
168         }
169 }
170
171 static void initData(ModifierData *md)
172 {
173         SolidifyModifierData *smd = (SolidifyModifierData *) md;
174         smd->offset = 0.01f;
175         smd->offset_fac = -1.0f;
176         smd->flag = MOD_SOLIDIFY_RIM;
177 }
178
179 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
180 {
181         SolidifyModifierData *smd = (SolidifyModifierData *) md;
182         CustomDataMask dataMask = 0;
183
184         /* ask for vertexgroups if we need them */
185         if (smd->defgrp_name[0]) dataMask |= CD_MASK_MDEFORMVERT;
186
187         return dataMask;
188 }
189
190 /* specific function for solidify - define locally */
191 BLI_INLINE void madd_v3v3short_fl(float r[3], const short a[3], const float f)
192 {
193         r[0] += (float)a[0] * f;
194         r[1] += (float)a[1] * f;
195         r[2] += (float)a[2] * f;
196 }
197
198 static Mesh *applyModifier(
199         ModifierData *md, const ModifierEvalContext *ctx,
200         Mesh *mesh)
201 {
202         Mesh *result;
203         const SolidifyModifierData *smd = (SolidifyModifierData *) md;
204
205         MVert *mv, *mvert, *orig_mvert;
206         MEdge *ed, *medge, *orig_medge;
207         MLoop *ml, *mloop, *orig_mloop;
208         MPoly *mp, *mpoly, *orig_mpoly;
209         const unsigned int numVerts = (unsigned int)mesh->totvert;
210         const unsigned int numEdges = (unsigned int)mesh->totedge;
211         const unsigned int numFaces = (unsigned int)mesh->totpoly;
212         const unsigned int numLoops = (unsigned int)mesh->totloop;
213         unsigned int newLoops = 0, newFaces = 0, newEdges = 0, newVerts = 0, rimVerts = 0;
214
215         /* only use material offsets if we have 2 or more materials  */
216         const short mat_nr_max = ctx->object->totcol > 1 ? ctx->object->totcol - 1 : 0;
217         const short mat_ofs = mat_nr_max ? smd->mat_ofs : 0;
218         const short mat_ofs_rim = mat_nr_max ? smd->mat_ofs_rim : 0;
219
220         /* use for edges */
221         /* over-alloc new_vert_arr, old_vert_arr */
222         unsigned int *new_vert_arr = NULL;
223         STACK_DECLARE(new_vert_arr);
224
225         unsigned int *new_edge_arr = NULL;
226         STACK_DECLARE(new_edge_arr);
227
228         unsigned int *old_vert_arr = MEM_calloc_arrayN(numVerts, sizeof(*old_vert_arr), "old_vert_arr in solidify");
229
230         unsigned int *edge_users = NULL;
231         char *edge_order = NULL;
232
233         float (*vert_nors)[3] = NULL;
234         float (*face_nors)[3] = NULL;
235
236         const bool need_face_normals = (smd->flag & MOD_SOLIDIFY_NORMAL_CALC) || (smd->flag & MOD_SOLIDIFY_EVEN);
237
238         const float ofs_orig = -(((-smd->offset_fac + 1.0f) * 0.5f) * smd->offset);
239         const float ofs_new  = smd->offset + ofs_orig;
240         const float offset_fac_vg = smd->offset_fac_vg;
241         const float offset_fac_vg_inv = 1.0f - smd->offset_fac_vg;
242         const bool do_flip = (smd->flag & MOD_SOLIDIFY_FLIP) != 0;
243         const bool do_clamp = (smd->offset_clamp != 0.0f);
244         const bool do_shell = ((smd->flag & MOD_SOLIDIFY_RIM) && (smd->flag & MOD_SOLIDIFY_NOSHELL)) == 0;
245
246         /* weights */
247         MDeformVert *dvert;
248         const bool defgrp_invert = (smd->flag & MOD_SOLIDIFY_VGROUP_INV) != 0;
249         int defgrp_index;
250
251         /* array size is doubled in case of using a shell */
252         const unsigned int stride = do_shell ? 2 : 1;
253
254         modifier_get_vgroup_mesh(ctx->object, mesh, smd->defgrp_name, &dvert, &defgrp_index);
255
256         orig_mvert = mesh->mvert;
257         orig_medge = mesh->medge;
258         orig_mloop = mesh->mloop;
259         orig_mpoly = mesh->mpoly;
260
261         if (need_face_normals) {
262                 /* calculate only face normals */
263                 face_nors = MEM_malloc_arrayN(numFaces, sizeof(*face_nors), __func__);
264                 BKE_mesh_calc_normals_poly(
265                             orig_mvert, NULL, (int)numVerts,
266                             orig_mloop, orig_mpoly,
267                             (int)numLoops, (int)numFaces,
268                             face_nors, true);
269         }
270
271         STACK_INIT(new_vert_arr, numVerts * 2);
272         STACK_INIT(new_edge_arr, numEdges * 2);
273
274         if (smd->flag & MOD_SOLIDIFY_RIM) {
275                 BLI_bitmap *orig_mvert_tag = BLI_BITMAP_NEW(numVerts, __func__);
276                 unsigned int eidx;
277                 unsigned int i;
278
279 #define INVALID_UNUSED ((unsigned int)-1)
280 #define INVALID_PAIR ((unsigned int)-2)
281
282                 new_vert_arr = MEM_malloc_arrayN(numVerts, 2 * sizeof(*new_vert_arr), __func__);
283                 new_edge_arr = MEM_malloc_arrayN(((numEdges * 2) + numVerts), sizeof(*new_edge_arr), __func__);
284
285                 edge_users = MEM_malloc_arrayN(numEdges, sizeof(*edge_users), "solid_mod edges");
286                 edge_order = MEM_malloc_arrayN(numEdges, sizeof(*edge_order), "solid_mod eorder");
287
288
289                 /* save doing 2 loops here... */
290 #if 0
291                 copy_vn_i(edge_users, numEdges, INVALID_UNUSED);
292 #endif
293
294                 for (eidx = 0, ed = orig_medge; eidx < numEdges; eidx++, ed++) {
295                         edge_users[eidx] = INVALID_UNUSED;
296                 }
297
298                 for (i = 0, mp = orig_mpoly; i < numFaces; i++, mp++) {
299                         MLoop *ml_prev;
300                         int j;
301
302                         ml = orig_mloop + mp->loopstart;
303                         ml_prev = ml + (mp->totloop - 1);
304
305                         for (j = 0; j < mp->totloop; j++, ml++) {
306                                 /* add edge user */
307                                 eidx = ml_prev->e;
308                                 if (edge_users[eidx] == INVALID_UNUSED) {
309                                         ed = orig_medge + eidx;
310                                         BLI_assert(ELEM(ml_prev->v,    ed->v1, ed->v2) &&
311                                                    ELEM(ml->v, ed->v1, ed->v2));
312                                         edge_users[eidx] = (ml_prev->v > ml->v) == (ed->v1 < ed->v2) ? i : (i + numFaces);
313                                         edge_order[eidx] = j;
314                                 }
315                                 else {
316                                         edge_users[eidx] = INVALID_PAIR;
317                                 }
318                                 ml_prev = ml;
319                         }
320                 }
321
322                 for (eidx = 0, ed = orig_medge; eidx < numEdges; eidx++, ed++) {
323                         if (!ELEM(edge_users[eidx], INVALID_UNUSED, INVALID_PAIR)) {
324                                 BLI_BITMAP_ENABLE(orig_mvert_tag, ed->v1);
325                                 BLI_BITMAP_ENABLE(orig_mvert_tag, ed->v2);
326                                 STACK_PUSH(new_edge_arr, eidx);
327                                 newFaces++;
328                                 newLoops += 4;
329                         }
330                 }
331
332                 for (i = 0; i < numVerts; i++) {
333                         if (BLI_BITMAP_TEST(orig_mvert_tag, i)) {
334                                 old_vert_arr[i] = STACK_SIZE(new_vert_arr);
335                                 STACK_PUSH(new_vert_arr, i);
336                                 rimVerts++;
337                         }
338                         else {
339                                 old_vert_arr[i] = INVALID_UNUSED;
340                         }
341                 }
342
343                 MEM_freeN(orig_mvert_tag);
344         }
345
346         if (do_shell == false) {
347                 /* only add rim vertices */
348                 newVerts = rimVerts;
349                 /* each extruded face needs an opposite edge */
350                 newEdges = newFaces;
351         }
352         else {
353                 /* (stride == 2) in this case, so no need to add newVerts/newEdges */
354                 BLI_assert(newVerts == 0);
355                 BLI_assert(newEdges == 0);
356         }
357
358         if (smd->flag & MOD_SOLIDIFY_NORMAL_CALC) {
359                 vert_nors = MEM_calloc_arrayN(numVerts, 3 * sizeof(float), "mod_solid_vno_hq");
360                 mesh_calc_hq_normal(mesh, face_nors, vert_nors);
361         }
362
363         result = BKE_mesh_from_template(mesh,
364                                         (int)((numVerts * stride) + newVerts),
365                                         (int)((numEdges * stride) + newEdges + rimVerts), 0,
366                                         (int)((numLoops * stride) + newLoops),
367                                         (int)((numFaces * stride) + newFaces));
368
369         mpoly = result->mpoly;
370         mloop = result->mloop;
371         medge = result->medge;
372         mvert = result->mvert;
373
374         if (do_shell) {
375                 CustomData_copy_data(&mesh->vdata, &result->vdata, 0, 0, (int)numVerts);
376                 CustomData_copy_data(&mesh->vdata, &result->vdata, 0, (int)numVerts, (int)numVerts);
377
378                 CustomData_copy_data(&mesh->edata, &result->edata, 0, 0, (int)numEdges);
379                 CustomData_copy_data(&mesh->edata, &result->edata, 0, (int)numEdges, (int)numEdges);
380
381                 CustomData_copy_data(&mesh->ldata, &result->ldata, 0, 0, (int)numLoops);
382                 CustomData_copy_data(&mesh->ldata, &result->ldata, 0, (int)numLoops, (int)numLoops);
383
384                 CustomData_copy_data(&mesh->pdata, &result->pdata, 0, 0, (int)numFaces);
385                 CustomData_copy_data(&mesh->pdata, &result->pdata, 0, (int)numFaces, (int)numFaces);
386         }
387         else {
388                 int i, j;
389                 CustomData_copy_data(&mesh->vdata, &result->vdata, 0, 0, (int)numVerts);
390                 for (i = 0, j = (int)numVerts; i < numVerts; i++) {
391                         if (old_vert_arr[i] != INVALID_UNUSED) {
392                                 CustomData_copy_data(&mesh->vdata, &result->vdata, i, j, 1);
393                                 j++;
394                         }
395                 }
396
397                 CustomData_copy_data(&mesh->edata, &result->edata, 0, 0, (int)numEdges);
398
399                 for (i = 0, j = (int)numEdges; i < numEdges; i++) {
400                         if (!ELEM(edge_users[i], INVALID_UNUSED, INVALID_PAIR)) {
401                                 MEdge *ed_src, *ed_dst;
402                                 CustomData_copy_data(&mesh->edata, &result->edata, i, j, 1);
403
404                                 ed_src = &medge[i];
405                                 ed_dst = &medge[j];
406                                 ed_dst->v1 = old_vert_arr[ed_src->v1] + numVerts;
407                                 ed_dst->v2 = old_vert_arr[ed_src->v2] + numVerts;
408                                 j++;
409                         }
410                 }
411
412                 /* will be created later */
413                 CustomData_copy_data(&mesh->ldata, &result->ldata, 0, 0, (int)numLoops);
414                 CustomData_copy_data(&mesh->pdata, &result->pdata, 0, 0, (int)numFaces);
415         }
416
417 #undef INVALID_UNUSED
418 #undef INVALID_PAIR
419
420
421         /* initializes: (i_end, do_shell_align, mv)  */
422 #define INIT_VERT_ARRAY_OFFSETS(test) \
423         if (((ofs_new >= ofs_orig) == do_flip) == test) { \
424                 i_end = numVerts; \
425                 do_shell_align = true; \
426                 mv = mvert; \
427         } \
428         else { \
429                 if (do_shell) { \
430                         i_end = numVerts; \
431                         do_shell_align = true; \
432                 } \
433                 else { \
434                         i_end = newVerts ; \
435                         do_shell_align = false; \
436                 } \
437                 mv = &mvert[numVerts]; \
438         } (void)0
439
440
441         /* flip normals */
442
443         if (do_shell) {
444                 unsigned int i;
445
446                 mp = mpoly + numFaces;
447                 for (i = 0; i < mesh->totpoly; i++, mp++) {
448                         const int loop_end = mp->totloop - 1;
449                         MLoop *ml2;
450                         unsigned int e;
451                         int j;
452
453                         /* reverses the loop direction (MLoop.v as well as custom-data)
454                          * MLoop.e also needs to be corrected too, done in a separate loop below. */
455                         ml2 = mloop + mp->loopstart + mesh->totloop;
456 #if 0
457                         for (j = 0; j < mp->totloop; j++) {
458                                 CustomData_copy_data(&mesh->ldata, &result->ldata, mp->loopstart + j,
459                                                      mp->loopstart + (loop_end - j) + mesh->totloop, 1);
460                         }
461 #else
462                         /* slightly more involved, keep the first vertex the same for the copy,
463                          * ensures the diagonals in the new face match the original. */
464                         j = 0;
465                         for (int j_prev = loop_end; j < mp->totloop; j_prev = j++) {
466                                 CustomData_copy_data(&mesh->ldata, &result->ldata, mp->loopstart + j,
467                                                      mp->loopstart + (loop_end - j_prev) + mesh->totloop, 1);
468                         }
469 #endif
470
471                         if (mat_ofs) {
472                                 mp->mat_nr += mat_ofs;
473                                 CLAMP(mp->mat_nr, 0, mat_nr_max);
474                         }
475
476                         e = ml2[0].e;
477                         for (j = 0; j < loop_end; j++) {
478                                 ml2[j].e = ml2[j + 1].e;
479                         }
480                         ml2[loop_end].e = e;
481
482                         mp->loopstart += mesh->totloop;
483
484                         for (j = 0; j < mp->totloop; j++) {
485                                 ml2[j].e += numEdges;
486                                 ml2[j].v += numVerts;
487                         }
488                 }
489
490                 for (i = 0, ed = medge + numEdges; i < numEdges; i++, ed++) {
491                         ed->v1 += numVerts;
492                         ed->v2 += numVerts;
493                 }
494         }
495
496         /* note, copied vertex layers don't have flipped normals yet. do this after applying offset */
497         if ((smd->flag & MOD_SOLIDIFY_EVEN) == 0) {
498                 /* no even thickness, very simple */
499                 float scalar_short;
500                 float scalar_short_vgroup;
501
502                 /* for clamping */
503                 float *vert_lens = NULL;
504                 const float offset    = fabsf(smd->offset) * smd->offset_clamp;
505                 const float offset_sq = offset * offset;
506
507                 if (do_clamp) {
508                         unsigned int i;
509
510                         vert_lens = MEM_malloc_arrayN(numVerts, sizeof(float), "vert_lens");
511                         copy_vn_fl(vert_lens, (int)numVerts, FLT_MAX);
512                         for (i = 0; i < numEdges; i++) {
513                                 const float ed_len_sq = len_squared_v3v3(mvert[medge[i].v1].co, mvert[medge[i].v2].co);
514                                 vert_lens[medge[i].v1] = min_ff(vert_lens[medge[i].v1], ed_len_sq);
515                                 vert_lens[medge[i].v2] = min_ff(vert_lens[medge[i].v2], ed_len_sq);
516                         }
517                 }
518
519                 if (ofs_new != 0.0f) {
520                         unsigned int i_orig, i_end;
521                         bool do_shell_align;
522
523                         scalar_short = scalar_short_vgroup = ofs_new / 32767.0f;
524
525                         INIT_VERT_ARRAY_OFFSETS(false);
526
527                         for (i_orig = 0; i_orig < i_end; i_orig++, mv++) {
528                                 const unsigned int i = do_shell_align ? i_orig : new_vert_arr[i_orig];
529                                 if (dvert) {
530                                         MDeformVert *dv = &dvert[i];
531                                         if (defgrp_invert) scalar_short_vgroup = 1.0f - defvert_find_weight(dv, defgrp_index);
532                                         else scalar_short_vgroup = defvert_find_weight(dv, defgrp_index);
533                                         scalar_short_vgroup = (offset_fac_vg + (scalar_short_vgroup * offset_fac_vg_inv)) * scalar_short;
534                                 }
535                                 if (do_clamp) {
536                                         /* always reset becaise we may have set before */
537                                         if (dvert == NULL) {
538                                                 scalar_short_vgroup = scalar_short;
539                                         }
540                                         if (vert_lens[i] < offset_sq) {
541                                                 float scalar = sqrtf(vert_lens[i]) / offset;
542                                                 scalar_short_vgroup *= scalar;
543                                         }
544                                 }
545                                 madd_v3v3short_fl(mv->co, mv->no, scalar_short_vgroup);
546                         }
547                 }
548
549                 if (ofs_orig != 0.0f) {
550                         unsigned int i_orig, i_end;
551                         bool do_shell_align;
552
553                         scalar_short = scalar_short_vgroup = ofs_orig / 32767.0f;
554
555                         /* as above but swapped */
556                         INIT_VERT_ARRAY_OFFSETS(true);
557
558                         for (i_orig = 0; i_orig < i_end; i_orig++, mv++) {
559                                 const unsigned int i = do_shell_align ? i_orig : new_vert_arr[i_orig];
560                                 if (dvert) {
561                                         MDeformVert *dv = &dvert[i];
562                                         if (defgrp_invert) scalar_short_vgroup = 1.0f - defvert_find_weight(dv, defgrp_index);
563                                         else scalar_short_vgroup = defvert_find_weight(dv, defgrp_index);
564                                         scalar_short_vgroup = (offset_fac_vg + (scalar_short_vgroup * offset_fac_vg_inv)) * scalar_short;
565                                 }
566                                 if (do_clamp) {
567                                         /* always reset becaise we may have set before */
568                                         if (dvert == NULL) {
569                                                 scalar_short_vgroup = scalar_short;
570                                         }
571                                         if (vert_lens[i] < offset_sq) {
572                                                 float scalar = sqrtf(vert_lens[i]) / offset;
573                                                 scalar_short_vgroup *= scalar;
574                                         }
575                                 }
576                                 madd_v3v3short_fl(mv->co, mv->no, scalar_short_vgroup);
577                         }
578                 }
579
580                 if (do_clamp) {
581                         MEM_freeN(vert_lens);
582                 }
583         }
584         else {
585 #ifdef USE_NONMANIFOLD_WORKAROUND
586                 const bool check_non_manifold = (smd->flag & MOD_SOLIDIFY_NORMAL_CALC) != 0;
587 #endif
588                 /* same as EM_solidify() in editmesh_lib.c */
589                 float *vert_angles = MEM_calloc_arrayN(numVerts, 2 * sizeof(float), "mod_solid_pair"); /* 2 in 1 */
590                 float *vert_accum = vert_angles + numVerts;
591                 unsigned int vidx;
592                 unsigned int i;
593
594                 if (vert_nors == NULL) {
595                         vert_nors = MEM_malloc_arrayN(numVerts, 3 * sizeof(float), "mod_solid_vno");
596                         for (i = 0, mv = mvert; i < numVerts; i++, mv++) {
597                                 normal_short_to_float_v3(vert_nors[i], mv->no);
598                         }
599                 }
600
601                 for (i = 0, mp = mpoly; i < numFaces; i++, mp++) {
602                         /* #BKE_mesh_calc_poly_angles logic is inlined here */
603                         float nor_prev[3];
604                         float nor_next[3];
605
606                         int i_curr = mp->totloop - 1;
607                         int i_next = 0;
608
609                         ml = &mloop[mp->loopstart];
610
611                         sub_v3_v3v3(nor_prev, mvert[ml[i_curr - 1].v].co, mvert[ml[i_curr].v].co);
612                         normalize_v3(nor_prev);
613
614                         while (i_next < mp->totloop) {
615                                 float angle;
616                                 sub_v3_v3v3(nor_next, mvert[ml[i_curr].v].co, mvert[ml[i_next].v].co);
617                                 normalize_v3(nor_next);
618                                 angle = angle_normalized_v3v3(nor_prev, nor_next);
619
620
621                                 /* --- not related to angle calc --- */
622                                 if (angle < FLT_EPSILON) {
623                                         angle = FLT_EPSILON;
624                                 }
625
626                                 vidx = ml[i_curr].v;
627                                 vert_accum[vidx] += angle;
628
629 #ifdef USE_NONMANIFOLD_WORKAROUND
630                                 /* skip 3+ face user edges */
631                                 if ((check_non_manifold == false) ||
632                                     LIKELY(((orig_medge[ml[i_curr].e].flag & ME_EDGE_TMP_TAG) == 0) &&
633                                            ((orig_medge[ml[i_next].e].flag & ME_EDGE_TMP_TAG) == 0)))
634                                 {
635                                         vert_angles[vidx] += shell_v3v3_normalized_to_dist(vert_nors[vidx], face_nors[i]) * angle;
636                                 }
637                                 else {
638                                         vert_angles[vidx] += angle;
639                                 }
640 #else
641                                 vert_angles[vidx] += shell_v3v3_normalized_to_dist(vert_nors[vidx], face_nors[i]) * angle;
642 #endif
643                                 /* --- end non-angle-calc section --- */
644
645
646                                 /* step */
647                                 copy_v3_v3(nor_prev, nor_next);
648                                 i_curr = i_next;
649                                 i_next++;
650                         }
651                 }
652
653                 /* vertex group support */
654                 if (dvert) {
655                         MDeformVert *dv = dvert;
656                         float scalar;
657
658                         if (defgrp_invert) {
659                                 for (i = 0; i < numVerts; i++, dv++) {
660                                         scalar = 1.0f - defvert_find_weight(dv, defgrp_index);
661                                         scalar = offset_fac_vg + (scalar * offset_fac_vg_inv);
662                                         vert_angles[i] *= scalar;
663                                 }
664                         }
665                         else {
666                                 for (i = 0; i < numVerts; i++, dv++) {
667                                         scalar = defvert_find_weight(dv, defgrp_index);
668                                         scalar = offset_fac_vg + (scalar * offset_fac_vg_inv);
669                                         vert_angles[i] *= scalar;
670                                 }
671                         }
672                 }
673
674                 if (do_clamp) {
675                         float *vert_lens_sq = MEM_malloc_arrayN(numVerts, sizeof(float), "vert_lens");
676                         const float offset    = fabsf(smd->offset) * smd->offset_clamp;
677                         const float offset_sq = offset * offset;
678                         copy_vn_fl(vert_lens_sq, (int)numVerts, FLT_MAX);
679                         for (i = 0; i < numEdges; i++) {
680                                 const float ed_len = len_squared_v3v3(mvert[medge[i].v1].co, mvert[medge[i].v2].co);
681                                 vert_lens_sq[medge[i].v1] = min_ff(vert_lens_sq[medge[i].v1], ed_len);
682                                 vert_lens_sq[medge[i].v2] = min_ff(vert_lens_sq[medge[i].v2], ed_len);
683                         }
684                         for (i = 0; i < numVerts; i++) {
685                                 if (vert_lens_sq[i] < offset_sq) {
686                                         float scalar = sqrtf(vert_lens_sq[i]) / offset;
687                                         vert_angles[i] *= scalar;
688                                 }
689                         }
690                         MEM_freeN(vert_lens_sq);
691                 }
692
693                 if (ofs_new != 0.0f) {
694                         unsigned int i_orig, i_end;
695                         bool do_shell_align;
696
697                         INIT_VERT_ARRAY_OFFSETS(false);
698
699                         for (i_orig = 0; i_orig < i_end; i_orig++, mv++) {
700                                 const unsigned int i_other = do_shell_align ? i_orig : new_vert_arr[i_orig];
701                                 if (vert_accum[i_other]) { /* zero if unselected */
702                                         madd_v3_v3fl(mv->co, vert_nors[i_other], ofs_new * (vert_angles[i_other] / vert_accum[i_other]));
703                                 }
704                         }
705                 }
706
707                 if (ofs_orig != 0.0f) {
708                         unsigned int i_orig, i_end;
709                         bool do_shell_align;
710
711                         /* same as above but swapped, intentional use of 'ofs_new' */
712                         INIT_VERT_ARRAY_OFFSETS(true);
713
714                         for (i_orig = 0; i_orig < i_end; i_orig++, mv++) {
715                                 const unsigned int i_other = do_shell_align ? i_orig : new_vert_arr[i_orig];
716                                 if (vert_accum[i_other]) { /* zero if unselected */
717                                         madd_v3_v3fl(mv->co, vert_nors[i_other], ofs_orig * (vert_angles[i_other] / vert_accum[i_other]));
718                                 }
719                         }
720                 }
721
722                 MEM_freeN(vert_angles);
723         }
724
725         if (vert_nors)
726                 MEM_freeN(vert_nors);
727
728         /* must recalculate normals with vgroups since they can displace unevenly [#26888] */
729         if ((mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) || (smd->flag & MOD_SOLIDIFY_RIM) || dvert) {
730                 result->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
731         }
732         else if (do_shell) {
733                 unsigned int i;
734                 /* flip vertex normals for copied verts */
735                 mv = mvert + numVerts;
736                 for (i = 0; i < numVerts; i++, mv++) {
737                         negate_v3_short(mv->no);
738                 }
739         }
740
741         if (smd->flag & MOD_SOLIDIFY_RIM) {
742                 unsigned int i;
743
744                 /* bugger, need to re-calculate the normals for the new edge faces.
745                  * This could be done in many ways, but probably the quickest way
746                  * is to calculate the average normals for side faces only.
747                  * Then blend them with the normals of the edge verts.
748                  *
749                  * at the moment its easiest to allocate an entire array for every vertex,
750                  * even though we only need edge verts - campbell
751                  */
752
753 #define SOLIDIFY_SIDE_NORMALS
754
755 #ifdef SOLIDIFY_SIDE_NORMALS
756                 /* Note that, due to the code setting cd_dirty_vert a few lines above,
757                  * do_side_normals is always false. - Sybren */
758                 const bool do_side_normals = !(result->runtime.cd_dirty_vert & CD_MASK_NORMAL);
759                 /* annoying to allocate these since we only need the edge verts, */
760                 float (*edge_vert_nos)[3] = do_side_normals ? MEM_calloc_arrayN(numVerts, 3 * sizeof(float), __func__) : NULL;
761                 float nor[3];
762 #endif
763                 const unsigned char crease_rim = smd->crease_rim * 255.0f;
764                 const unsigned char crease_outer = smd->crease_outer * 255.0f;
765                 const unsigned char crease_inner = smd->crease_inner * 255.0f;
766
767                 int *origindex_edge;
768                 int *orig_ed;
769                 unsigned int j;
770
771                 if (crease_rim || crease_outer || crease_inner) {
772                         result->cd_flag |= ME_CDFLAG_EDGE_CREASE;
773                 }
774
775                 /* add faces & edges */
776                 origindex_edge = CustomData_get_layer(&result->edata, CD_ORIGINDEX);
777                 BLI_assert(origindex_edge != NULL);
778                 ed = &medge[(numEdges * stride) + newEdges];  /* start after copied edges */
779                 orig_ed = &origindex_edge[(numEdges * stride) + newEdges];
780                 for (i = 0; i < rimVerts; i++, ed++, orig_ed++) {
781                         ed->v1 = new_vert_arr[i];
782                         ed->v2 = (do_shell ? new_vert_arr[i] : i) + numVerts;
783                         ed->flag |= ME_EDGEDRAW;
784
785                         *orig_ed = ORIGINDEX_NONE;
786
787                         if (crease_rim) {
788                                 ed->crease = crease_rim;
789                         }
790                 }
791
792                 /* faces */
793                 mp = mpoly + (numFaces * stride);
794                 ml = mloop + (numLoops * stride);
795                 j = 0;
796                 for (i = 0; i < newFaces; i++, mp++) {
797                         unsigned int eidx = new_edge_arr[i];
798                         unsigned int fidx = edge_users[eidx];
799                         int k1, k2;
800                         bool flip;
801
802                         if (fidx >= numFaces) {
803                                 fidx -= numFaces;
804                                 flip = true;
805                         }
806                         else {
807                                 flip = false;
808                         }
809
810                         ed = medge + eidx;
811
812                         /* copy most of the face settings */
813                         CustomData_copy_data(&mesh->pdata, &result->pdata, (int)fidx, (int)((numFaces * stride) + i), 1);
814                         mp->loopstart = (int)(j + (numLoops * stride));
815                         mp->flag = mpoly[fidx].flag;
816
817                         /* notice we use 'mp->totloop' which is later overwritten,
818                          * we could lookup the original face but theres no point since this is a copy
819                          * and will have the same value, just take care when changing order of assignment */
820                         k1 = mpoly[fidx].loopstart + (((edge_order[eidx] - 1) + mp->totloop) % mp->totloop);  /* prev loop */
821                         k2 = mpoly[fidx].loopstart +   (edge_order[eidx]);
822
823                         mp->totloop = 4;
824
825                         CustomData_copy_data(&mesh->ldata, &result->ldata, k2, (int)((numLoops * stride) + j + 0), 1);
826                         CustomData_copy_data(&mesh->ldata, &result->ldata, k1, (int)((numLoops * stride) + j + 1), 1);
827                         CustomData_copy_data(&mesh->ldata, &result->ldata, k1, (int)((numLoops * stride) + j + 2), 1);
828                         CustomData_copy_data(&mesh->ldata, &result->ldata, k2, (int)((numLoops * stride) + j + 3), 1);
829
830                         if (flip == false) {
831                                 ml[j].v = ed->v1;
832                                 ml[j++].e = eidx;
833
834                                 ml[j].v = ed->v2;
835                                 ml[j++].e = (numEdges * stride) + old_vert_arr[ed->v2] + newEdges;
836
837                                 ml[j].v = (do_shell ? ed->v2 : old_vert_arr[ed->v2]) + numVerts;
838                                 ml[j++].e = (do_shell ? eidx : i) + numEdges;
839
840                                 ml[j].v = (do_shell ? ed->v1 : old_vert_arr[ed->v1]) + numVerts;
841                                 ml[j++].e = (numEdges * stride) + old_vert_arr[ed->v1] + newEdges;
842                         }
843                         else {
844                                 ml[j].v = ed->v2;
845                                 ml[j++].e = eidx;
846
847                                 ml[j].v = ed->v1;
848                                 ml[j++].e = (numEdges * stride) + old_vert_arr[ed->v1] + newEdges;
849
850                                 ml[j].v = (do_shell ? ed->v1 : old_vert_arr[ed->v1]) + numVerts;
851                                 ml[j++].e = (do_shell ? eidx : i) + numEdges;
852
853                                 ml[j].v = (do_shell ? ed->v2 : old_vert_arr[ed->v2]) + numVerts;
854                                 ml[j++].e = (numEdges * stride) + old_vert_arr[ed->v2] + newEdges;
855                         }
856
857                         origindex_edge[ml[j - 3].e] = ORIGINDEX_NONE;
858                         origindex_edge[ml[j - 1].e] = ORIGINDEX_NONE;
859
860                         /* use the next material index if option enabled */
861                         if (mat_ofs_rim) {
862                                 mp->mat_nr += mat_ofs_rim;
863                                 CLAMP(mp->mat_nr, 0, mat_nr_max);
864                         }
865                         if (crease_outer) {
866                                 /* crease += crease_outer; without wrapping */
867                                 char *cr = &(ed->crease);
868                                 int tcr = *cr + crease_outer;
869                                 *cr = tcr > 255 ? 255 : tcr;
870                         }
871
872                         if (crease_inner) {
873                                 /* crease += crease_inner; without wrapping */
874                                 char *cr = &(medge[numEdges + (do_shell ? eidx : i)].crease);
875                                 int tcr = *cr + crease_inner;
876                                 *cr = tcr > 255 ? 255 : tcr;
877                         }
878
879 #ifdef SOLIDIFY_SIDE_NORMALS
880                         if (do_side_normals) {
881                                 normal_quad_v3(nor,
882                                                mvert[ml[j - 4].v].co,
883                                                mvert[ml[j - 3].v].co,
884                                                mvert[ml[j - 2].v].co,
885                                                mvert[ml[j - 1].v].co);
886
887                                 add_v3_v3(edge_vert_nos[ed->v1], nor);
888                                 add_v3_v3(edge_vert_nos[ed->v2], nor);
889                         }
890 #endif
891                 }
892
893 #ifdef SOLIDIFY_SIDE_NORMALS
894                 if (do_side_normals) {
895                         const MEdge *ed_orig = medge;
896                         ed = medge + (numEdges * stride);
897                         for (i = 0; i < rimVerts; i++, ed++, ed_orig++) {
898                                 float nor_cpy[3];
899                                 short *nor_short;
900                                 int k;
901
902                                 /* note, only the first vertex (lower half of the index) is calculated */
903                                 BLI_assert(ed->v1 < numVerts);
904                                 normalize_v3_v3(nor_cpy, edge_vert_nos[ed_orig->v1]);
905
906                                 for (k = 0; k < 2; k++) { /* loop over both verts of the edge */
907                                         nor_short = mvert[*(&ed->v1 + k)].no;
908                                         normal_short_to_float_v3(nor, nor_short);
909                                         add_v3_v3(nor, nor_cpy);
910                                         normalize_v3(nor);
911                                         normal_float_to_short_v3(nor_short, nor);
912                                 }
913                         }
914
915                         MEM_freeN(edge_vert_nos);
916                 }
917 #endif
918
919                 MEM_freeN(new_vert_arr);
920                 MEM_freeN(new_edge_arr);
921
922                 MEM_freeN(edge_users);
923                 MEM_freeN(edge_order);
924         }
925
926         if (old_vert_arr)
927                 MEM_freeN(old_vert_arr);
928
929         if (face_nors)
930                 MEM_freeN(face_nors);
931
932         if (numFaces == 0 && numEdges != 0) {
933                 modifier_setError(md, "Faces needed for useful output");
934         }
935
936         return result;
937 }
938
939 #undef SOLIDIFY_SIDE_NORMALS
940
941 static bool dependsOnNormals(ModifierData *UNUSED(md))
942 {
943         /* even when we calculate our own normals,
944          * the vertex normals are used as a fallback */
945         return true;
946 }
947
948 ModifierTypeInfo modifierType_Solidify = {
949         /* name */              "Solidify",
950         /* structName */        "SolidifyModifierData",
951         /* structSize */        sizeof(SolidifyModifierData),
952         /* type */              eModifierTypeType_Constructive,
953
954         /* flags */             eModifierTypeFlag_AcceptsMesh |
955                                 eModifierTypeFlag_AcceptsCVs |
956                                 eModifierTypeFlag_SupportsMapping |
957                                 eModifierTypeFlag_SupportsEditmode |
958                                 eModifierTypeFlag_EnableInEditmode,
959
960         /* copyData */          modifier_copyData_generic,
961
962         /* deformVerts_DM */    NULL,
963         /* deformMatrices_DM */ NULL,
964         /* deformVertsEM_DM */  NULL,
965         /* deformMatricesEM_DM*/NULL,
966         /* applyModifier_DM */  NULL,
967         /* applyModifierEM_DM */NULL,
968
969         /* deformVerts */       NULL,
970         /* deformMatrices */    NULL,
971         /* deformVertsEM */     NULL,
972         /* deformMatricesEM */  NULL,
973         /* applyModifier */     applyModifier,
974         /* applyModifierEM */   NULL,
975
976         /* initData */          initData,
977         /* requiredDataMask */  requiredDataMask,
978         /* freeData */          NULL,
979         /* isDisabled */        NULL,
980         /* updateDepsgraph */   NULL,
981         /* dependsOnTime */     NULL,
982         /* dependsOnNormals */  dependsOnNormals,
983         /* foreachObjectLink */ NULL,
984         /* foreachIDLink */     NULL,
985         /* foreachTexLink */    NULL,
986 };