Blender  V2.93
MOD_normal_edit.c
Go to the documentation of this file.
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 
21 #include <string.h>
22 
23 #include "MEM_guardedalloc.h"
24 
25 #include "BLI_utildefines.h"
26 
27 #include "BLI_bitmap.h"
28 #include "BLI_math.h"
29 
30 #include "BLT_translation.h"
31 
32 #include "DNA_defaults.h"
33 #include "DNA_mesh_types.h"
34 #include "DNA_meshdata_types.h"
35 #include "DNA_object_types.h"
36 #include "DNA_screen_types.h"
37 
38 #include "BKE_context.h"
39 #include "BKE_deform.h"
40 #include "BKE_lib_id.h"
41 #include "BKE_lib_query.h"
42 #include "BKE_mesh.h"
43 #include "BKE_screen.h"
44 
45 #include "UI_interface.h"
46 #include "UI_resources.h"
47 
48 #include "RNA_access.h"
49 
50 #include "DEG_depsgraph_query.h"
51 
52 #include "MOD_ui_common.h"
53 #include "MOD_util.h"
54 
56  Object *ob,
57  Object *ob_center,
58  const float offset[3],
59  const int num_verts,
60  float (*r_cos)[3],
61  float r_size[3])
62 {
63  float min_co[3], max_co[3];
64  float diff[3];
65  bool do_diff = false;
66 
67  INIT_MINMAX(min_co, max_co);
68 
69  MVert *mv = mesh->mvert;
70  for (int i = 0; i < mesh->totvert; i++, mv++) {
71  copy_v3_v3(r_cos[i], mv->co);
72  if (r_size != NULL && ob_center == NULL) {
73  minmax_v3v3_v3(min_co, max_co, r_cos[i]);
74  }
75  }
76 
77  /* Get size (i.e. deformation of the spheroid generating normals),
78  * either from target object, or own geometry. */
79  if (r_size != NULL) {
80  if (ob_center != NULL) {
81  /* Using 'scale' as 'size' here. The input object is typically an empty
82  * who's scale is used to define an ellipsoid instead of a simple sphere. */
83 
84  /* Not we are not interested in signs here - they are even troublesome actually,
85  * due to security clamping! */
86  abs_v3_v3(r_size, ob_center->scale);
87  }
88  else {
89  /* Set size. */
90  sub_v3_v3v3(r_size, max_co, min_co);
91  }
92 
93  /* Error checks - we do not want one or more of our sizes to be null! */
94  if (is_zero_v3(r_size)) {
95  r_size[0] = r_size[1] = r_size[2] = 1.0f;
96  }
97  else {
98  CLAMP_MIN(r_size[0], FLT_EPSILON);
99  CLAMP_MIN(r_size[1], FLT_EPSILON);
100  CLAMP_MIN(r_size[2], FLT_EPSILON);
101  }
102  }
103 
104  if (ob_center != NULL) {
105  float inv_obmat[4][4];
106 
107  /* Translate our coordinates so that center of ob_center is at (0, 0, 0). */
108  /* Get ob_center (world) coordinates in ob local coordinates.
109  * No need to take into account ob_center's space here, see T44027. */
110  invert_m4_m4(inv_obmat, ob->obmat);
111  mul_v3_m4v3(diff, inv_obmat, ob_center->obmat[3]);
112  negate_v3(diff);
113 
114  do_diff = true;
115  }
116  else if (offset != NULL && !is_zero_v3(offset)) {
117  negate_v3_v3(diff, offset);
118 
119  do_diff = true;
120  }
121  /* Else, no need to change coordinates! */
122 
123  if (do_diff) {
124  int i = num_verts;
125  while (i--) {
126  add_v3_v3(r_cos[i], diff);
127  }
128  }
129 }
130 
131 /* Note this modifies nos_new in-place. */
132 static void mix_normals(const float mix_factor,
133  MDeformVert *dvert,
134  const int defgrp_index,
135  const bool use_invert_vgroup,
136  const float mix_limit,
137  const short mix_mode,
138  const int num_verts,
139  MLoop *mloop,
140  float (*nos_old)[3],
141  float (*nos_new)[3],
142  const int num_loops)
143 {
144  /* Mix with org normals... */
145  float *facs = NULL, *wfac;
146  float(*no_new)[3], (*no_old)[3];
147  int i;
148 
149  if (dvert) {
150  facs = MEM_malloc_arrayN((size_t)num_loops, sizeof(*facs), __func__);
152  dvert, defgrp_index, num_verts, mloop, num_loops, facs, use_invert_vgroup);
153  }
154 
155  for (i = num_loops, no_new = nos_new, no_old = nos_old, wfac = facs; i--;
156  no_new++, no_old++, wfac++) {
157  const float fac = facs ? *wfac * mix_factor : mix_factor;
158 
159  switch (mix_mode) {
161  add_v3_v3(*no_new, *no_old);
162  normalize_v3(*no_new);
163  break;
165  sub_v3_v3(*no_new, *no_old);
166  normalize_v3(*no_new);
167  break;
169  mul_v3_v3(*no_new, *no_old);
170  normalize_v3(*no_new);
171  break;
173  break;
174  }
175 
177  *no_new,
178  *no_old,
179  *no_new,
180  (mix_limit < (float)M_PI) ? min_ff(fac, mix_limit / angle_v3v3(*no_new, *no_old)) : fac);
181  }
182 
183  MEM_SAFE_FREE(facs);
184 }
185 
186 /* Check poly normals and new loop normals are compatible, otherwise flip polygons
187  * (and invert matching poly normals). */
188 static bool polygons_check_flip(MLoop *mloop,
189  float (*nos)[3],
190  CustomData *ldata,
191  MPoly *mpoly,
192  float (*polynors)[3],
193  const int num_polys)
194 {
195  MPoly *mp;
196  MDisps *mdisp = CustomData_get_layer(ldata, CD_MDISPS);
197  int i;
198  bool flipped = false;
199 
200  for (i = 0, mp = mpoly; i < num_polys; i++, mp++) {
201  float norsum[3] = {0.0f};
202  float(*no)[3];
203  int j;
204 
205  for (j = 0, no = &nos[mp->loopstart]; j < mp->totloop; j++, no++) {
206  add_v3_v3(norsum, *no);
207  }
208 
209  if (!normalize_v3(norsum)) {
210  continue;
211  }
212 
213  /* If average of new loop normals is opposed to polygon normal, flip polygon. */
214  if (dot_v3v3(polynors[i], norsum) < 0.0f) {
215  BKE_mesh_polygon_flip_ex(mp, mloop, ldata, nos, mdisp, true);
216  negate_v3(polynors[i]);
217  flipped = true;
218  }
219  }
220 
221  return flipped;
222 }
223 
225  const ModifierEvalContext *UNUSED(ctx),
226  Object *ob,
227  Mesh *mesh,
228  short (*clnors)[2],
229  float (*loopnors)[3],
230  float (*polynors)[3],
231  const short mix_mode,
232  const float mix_factor,
233  const float mix_limit,
234  MDeformVert *dvert,
235  const int defgrp_index,
236  const bool use_invert_vgroup,
237  MVert *mvert,
238  const int num_verts,
239  MEdge *medge,
240  const int num_edges,
241  MLoop *mloop,
242  const int num_loops,
243  MPoly *mpoly,
244  const int num_polys)
245 {
246  Object *ob_target = enmd->target;
247 
248  const bool do_polynors_fix = (enmd->flag & MOD_NORMALEDIT_NO_POLYNORS_FIX) == 0;
249  int i;
250 
251  float(*cos)[3] = MEM_malloc_arrayN((size_t)num_verts, sizeof(*cos), __func__);
252  float(*nos)[3] = MEM_malloc_arrayN((size_t)num_loops, sizeof(*nos), __func__);
253  float size[3];
254 
255  BLI_bitmap *done_verts = BLI_BITMAP_NEW((size_t)num_verts, __func__);
256 
257  generate_vert_coordinates(mesh, ob, ob_target, enmd->offset, num_verts, cos, size);
258 
290  {
291  const float a = size[0], b = size[1], c = size[2];
292  const float m2 = (b * b) / (a * a);
293  const float n2 = (c * c) / (a * a);
294 
295  MLoop *ml;
296  float(*no)[3];
297 
298  /* We reuse cos to now store the ellipsoid-normal of the verts! */
299  for (i = num_loops, ml = mloop, no = nos; i--; ml++, no++) {
300  const int vidx = ml->v;
301  float *co = cos[vidx];
302 
303  if (!BLI_BITMAP_TEST(done_verts, vidx)) {
304  const float x2 = co[0] * co[0];
305  const float y2 = co[1] * co[1];
306  const float z2 = co[2] * co[2];
307  const float a2 = x2 + (y2 / m2) + (z2 / n2);
308  const float b2 = (m2 * x2) + y2 + (m2 * z2 / n2);
309  const float c2 = (n2 * x2) + (n2 * y2 / m2) + z2;
310 
311  co[0] /= a2;
312  co[1] /= b2;
313  co[2] /= c2;
314  normalize_v3(co);
315 
316  BLI_BITMAP_ENABLE(done_verts, vidx);
317  }
318  copy_v3_v3(*no, co);
319  }
320  }
321 
322  if (loopnors) {
323  mix_normals(mix_factor,
324  dvert,
325  defgrp_index,
326  use_invert_vgroup,
327  mix_limit,
328  mix_mode,
329  num_verts,
330  mloop,
331  loopnors,
332  nos,
333  num_loops);
334  }
335 
336  if (do_polynors_fix &&
337  polygons_check_flip(mloop, nos, &mesh->ldata, mpoly, polynors, num_polys)) {
338  /* XXX TODO is this still needed? */
339  // mesh->dirty |= DM_DIRTY_TESS_CDLAYERS;
340  /* We need to recompute vertex normals! */
342  }
343 
345  num_verts,
346  medge,
347  num_edges,
348  mloop,
349  nos,
350  num_loops,
351  mpoly,
352  (const float(*)[3])polynors,
353  num_polys,
354  clnors);
355 
356  MEM_freeN(cos);
357  MEM_freeN(nos);
358  MEM_freeN(done_verts);
359 }
360 
362  const ModifierEvalContext *UNUSED(ctx),
363  Object *ob,
364  Mesh *mesh,
365  short (*clnors)[2],
366  float (*loopnors)[3],
367  float (*polynors)[3],
368  const short mix_mode,
369  const float mix_factor,
370  const float mix_limit,
371  MDeformVert *dvert,
372  const int defgrp_index,
373  const bool use_invert_vgroup,
374  MVert *mvert,
375  const int num_verts,
376  MEdge *medge,
377  const int num_edges,
378  MLoop *mloop,
379  const int num_loops,
380  MPoly *mpoly,
381  const int num_polys)
382 {
383  Object *ob_target = enmd->target;
384 
385  const bool do_polynors_fix = (enmd->flag & MOD_NORMALEDIT_NO_POLYNORS_FIX) == 0;
386  const bool use_parallel_normals = (enmd->flag & MOD_NORMALEDIT_USE_DIRECTION_PARALLEL) != 0;
387 
388  float(*nos)[3] = MEM_malloc_arrayN((size_t)num_loops, sizeof(*nos), __func__);
389 
390  float target_co[3];
391  int i;
392 
393  /* Get target's center coordinates in ob local coordinates. */
394  float mat[4][4];
395 
396  invert_m4_m4(mat, ob->obmat);
397  mul_m4_m4m4(mat, mat, ob_target->obmat);
398  copy_v3_v3(target_co, mat[3]);
399 
400  if (use_parallel_normals) {
401  float no[3];
402 
403  sub_v3_v3v3(no, target_co, enmd->offset);
404  normalize_v3(no);
405 
406  for (i = num_loops; i--;) {
407  copy_v3_v3(nos[i], no);
408  }
409  }
410  else {
411  float(*cos)[3] = MEM_malloc_arrayN((size_t)num_verts, sizeof(*cos), __func__);
412  generate_vert_coordinates(mesh, ob, ob_target, NULL, num_verts, cos, NULL);
413 
414  BLI_bitmap *done_verts = BLI_BITMAP_NEW((size_t)num_verts, __func__);
415  MLoop *ml;
416  float(*no)[3];
417 
418  /* We reuse cos to now store the 'to target' normal of the verts! */
419  for (i = num_loops, no = nos, ml = mloop; i--; no++, ml++) {
420  const int vidx = ml->v;
421  float *co = cos[vidx];
422 
423  if (!BLI_BITMAP_TEST(done_verts, vidx)) {
424  sub_v3_v3v3(co, target_co, co);
425  normalize_v3(co);
426 
427  BLI_BITMAP_ENABLE(done_verts, vidx);
428  }
429 
430  copy_v3_v3(*no, co);
431  }
432 
433  MEM_freeN(done_verts);
434  MEM_freeN(cos);
435  }
436 
437  if (loopnors) {
438  mix_normals(mix_factor,
439  dvert,
440  defgrp_index,
441  use_invert_vgroup,
442  mix_limit,
443  mix_mode,
444  num_verts,
445  mloop,
446  loopnors,
447  nos,
448  num_loops);
449  }
450 
451  if (do_polynors_fix &&
452  polygons_check_flip(mloop, nos, &mesh->ldata, mpoly, polynors, num_polys)) {
454  }
455 
457  num_verts,
458  medge,
459  num_edges,
460  mloop,
461  nos,
462  num_loops,
463  mpoly,
464  (const float(*)[3])polynors,
465  num_polys,
466  clnors);
467 
468  MEM_freeN(nos);
469 }
470 
472 {
473  if (enmd->mode == MOD_NORMALEDIT_MODE_RADIAL) {
474  return true;
475  }
476  if ((enmd->mode == MOD_NORMALEDIT_MODE_DIRECTIONAL) && enmd->target) {
477  return true;
478  }
479  return false;
480 }
481 
483 {
484  if (is_valid_target(enmd)) {
485  return true;
486  }
487  BKE_modifier_set_error(ob, (ModifierData *)enmd, "Invalid target settings");
488  return false;
489 }
490 
492  const ModifierEvalContext *ctx,
493  Object *ob,
494  Mesh *mesh)
495 {
496  const bool use_invert_vgroup = ((enmd->flag & MOD_NORMALEDIT_INVERT_VGROUP) != 0);
497  const bool use_current_clnors = !((enmd->mix_mode == MOD_NORMALEDIT_MIX_COPY) &&
498  (enmd->mix_factor == 1.0f) && (enmd->defgrp_name[0] == '\0') &&
499  (enmd->mix_limit == (float)M_PI));
500 
501  /* Do not run that modifier at all if autosmooth is disabled! */
502  if (!is_valid_target_with_error(ctx->object, enmd) || mesh->totloop == 0) {
503  return mesh;
504  }
505 
506  /* XXX TODO(Rohan Rathi):
507  * Once we fully switch to Mesh evaluation of modifiers,
508  * we can expect to get that flag from the COW copy.
509  * But for now, it is lost in the DM intermediate step,
510  * so we need to directly check orig object's data. */
511 #if 0
512  if (!(mesh->flag & ME_AUTOSMOOTH))
513 #else
514  if (!(((Mesh *)ob->data)->flag & ME_AUTOSMOOTH))
515 #endif
516  {
518  ob, (ModifierData *)enmd, "Enable 'Auto Smooth' in Object Data Properties");
519  return mesh;
520  }
521 
522  Mesh *result;
523  if (mesh->medge == ((Mesh *)ob->data)->medge) {
524  /* We need to duplicate data here, otherwise setting custom normals
525  * (which may also affect sharp edges) could
526  * modify original mesh, see T43671. */
528  }
529  else {
530  result = mesh;
531  }
532 
533  const int num_verts = result->totvert;
534  const int num_edges = result->totedge;
535  const int num_loops = result->totloop;
536  const int num_polys = result->totpoly;
537  MVert *mvert = result->mvert;
538  MEdge *medge = result->medge;
539  MLoop *mloop = result->mloop;
540  MPoly *mpoly = result->mpoly;
541 
542  int defgrp_index;
543  MDeformVert *dvert;
544 
545  float(*loopnors)[3] = NULL;
546  short(*clnors)[2] = NULL;
547 
548  float(*polynors)[3];
549 
550  CustomData *ldata = &result->ldata;
551 
552  /* Compute poly (always needed) and vert normals. */
553  CustomData *pdata = &result->pdata;
554  polynors = CustomData_get_layer(pdata, CD_NORMAL);
555  if (!polynors) {
556  polynors = CustomData_add_layer(pdata, CD_NORMAL, CD_CALLOC, NULL, num_polys);
558  }
560  NULL,
561  num_verts,
562  mloop,
563  mpoly,
564  num_loops,
565  num_polys,
566  polynors,
567  (result->runtime.cd_dirty_vert & CD_MASK_NORMAL) ? false : true);
568 
569  result->runtime.cd_dirty_vert &= ~CD_MASK_NORMAL;
570 
571  clnors = CustomData_get_layer(ldata, CD_CUSTOMLOOPNORMAL);
572  if (use_current_clnors) {
574  loopnors = MEM_malloc_arrayN((size_t)num_loops, sizeof(*loopnors), __func__);
575 
577  num_verts,
578  medge,
579  num_edges,
580  mloop,
581  loopnors,
582  num_loops,
583  mpoly,
584  (const float(*)[3])polynors,
585  num_polys,
586  true,
587  result->smoothresh,
588  NULL,
589  clnors,
590  NULL);
591  }
592 
593  if (clnors == NULL) {
594  clnors = CustomData_add_layer(ldata, CD_CUSTOMLOOPNORMAL, CD_CALLOC, NULL, num_loops);
595  }
596 
597  MOD_get_vgroup(ob, result, enmd->defgrp_name, &dvert, &defgrp_index);
598 
599  if (enmd->mode == MOD_NORMALEDIT_MODE_RADIAL) {
601  ctx,
602  ob,
603  result,
604  clnors,
605  loopnors,
606  polynors,
607  enmd->mix_mode,
608  enmd->mix_factor,
609  enmd->mix_limit,
610  dvert,
611  defgrp_index,
612  use_invert_vgroup,
613  mvert,
614  num_verts,
615  medge,
616  num_edges,
617  mloop,
618  num_loops,
619  mpoly,
620  num_polys);
621  }
622  else if (enmd->mode == MOD_NORMALEDIT_MODE_DIRECTIONAL) {
624  ctx,
625  ob,
626  result,
627  clnors,
628  loopnors,
629  polynors,
630  enmd->mix_mode,
631  enmd->mix_factor,
632  enmd->mix_limit,
633  dvert,
634  defgrp_index,
635  use_invert_vgroup,
636  mvert,
637  num_verts,
638  medge,
639  num_edges,
640  mloop,
641  num_loops,
642  mpoly,
643  num_polys);
644  }
645 
646  /* Currently Modifier stack assumes there is no poly normal data passed around... */
647  CustomData_free_layers(pdata, CD_NORMAL, num_polys);
648  MEM_SAFE_FREE(loopnors);
649 
650  result->runtime.is_original = false;
651 
652  return result;
653 }
654 
655 static void initData(ModifierData *md)
656 {
658 
659  BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(enmd, modifier));
660 
662 }
663 
664 static void requiredDataMask(Object *UNUSED(ob),
665  ModifierData *md,
666  CustomData_MeshMasks *r_cddata_masks)
667 {
669 
670  r_cddata_masks->lmask |= CD_MASK_CUSTOMLOOPNORMAL;
671 
672  /* Ask for vertexgroups if we need them. */
673  if (enmd->defgrp_name[0] != '\0') {
674  r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
675  }
676 }
677 
679 {
680  return true;
681 }
682 
683 static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
684 {
686 
687  walk(userData, ob, (ID **)&enmd->target, IDWALK_CB_NOP);
688 }
689 
690 static bool isDisabled(const struct Scene *UNUSED(scene),
691  ModifierData *md,
692  bool UNUSED(useRenderParams))
693 {
695 
696  return !is_valid_target(enmd);
697 }
698 
700 {
702  if (enmd->target) {
703  DEG_add_object_relation(ctx->node, enmd->target, DEG_OB_COMP_TRANSFORM, "NormalEdit Modifier");
704  DEG_add_modifier_to_transform_relation(ctx->node, "NormalEdit Modifier");
705  }
706 }
707 
709 {
710  return normalEditModifier_do((NormalEditModifierData *)md, ctx, ctx->object, mesh);
711 }
712 
713 static void panel_draw(const bContext *UNUSED(C), Panel *panel)
714 {
715  uiLayout *col;
716  uiLayout *layout = panel->layout;
717 
718  PointerRNA ob_ptr;
720 
721  int mode = RNA_enum_get(ptr, "mode");
722 
723  uiItemR(layout, ptr, "mode", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
724 
725  uiLayoutSetPropSep(layout, true);
726 
727  uiItemR(layout, ptr, "target", 0, NULL, ICON_NONE);
728 
729  col = uiLayoutColumn(layout, false);
731  uiItemR(col, ptr, "use_direction_parallel", 0, NULL, ICON_NONE);
732 
733  modifier_panel_end(layout, ptr);
734 }
735 
736 /* This panel could be open by default, but it isn't currently. */
737 static void mix_mode_panel_draw(const bContext *UNUSED(C), Panel *panel)
738 {
739  uiLayout *row;
740  uiLayout *layout = panel->layout;
741 
742  PointerRNA ob_ptr;
744 
745  uiLayoutSetPropSep(layout, true);
746 
747  uiItemR(layout, ptr, "mix_mode", 0, NULL, ICON_NONE);
748  uiItemR(layout, ptr, "mix_factor", 0, NULL, ICON_NONE);
749 
750  modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
751 
752  row = uiLayoutRow(layout, true);
753  uiItemR(row, ptr, "mix_limit", 0, NULL, ICON_NONE);
754  uiItemR(row,
755  ptr,
756  "no_polynors_fix",
757  0,
758  "",
759  (RNA_boolean_get(ptr, "no_polynors_fix") ? ICON_LOCKED : ICON_UNLOCKED));
760 }
761 
762 static void offset_panel_draw(const bContext *UNUSED(C), Panel *panel)
763 {
764  uiLayout *layout = panel->layout;
765 
767 
768  int mode = RNA_enum_get(ptr, "mode");
769  PointerRNA target_ptr = RNA_pointer_get(ptr, "target");
770  bool needs_object_offset = (mode == MOD_NORMALEDIT_MODE_RADIAL &&
771  RNA_pointer_is_null(&target_ptr)) ||
773  RNA_boolean_get(ptr, "use_direction_parallel"));
774 
775  uiLayoutSetPropSep(layout, true);
776 
777  uiLayoutSetActive(layout, needs_object_offset);
778  uiItemR(layout, ptr, "offset", 0, NULL, ICON_NONE);
779 }
780 
781 static void panelRegister(ARegionType *region_type)
782 {
783  PanelType *panel_type = modifier_panel_register(
784  region_type, eModifierType_NormalEdit, panel_draw);
785  modifier_subpanel_register(region_type, "mix", "Mix", NULL, mix_mode_panel_draw, panel_type);
786  modifier_subpanel_register(region_type, "offset", "Offset", NULL, offset_panel_draw, panel_type);
787 }
788 
790  /* name */ "NormalEdit",
791  /* structName */ "NormalEditModifierData",
792  /* structSize */ sizeof(NormalEditModifierData),
793  /* srna */ &RNA_NormalEditModifier,
797  /* icon */ ICON_MOD_NORMALEDIT,
798 
799  /* copyData */ BKE_modifier_copydata_generic,
800 
801  /* deformVerts */ NULL,
802  /* deformMatrices */ NULL,
803  /* deformVertsEM */ NULL,
804  /* deformMatricesEM */ NULL,
805  /* modifyMesh */ modifyMesh,
806  /* modifyHair */ NULL,
807  /* modifyGeometrySet */ NULL,
808  /* modifyVolume */ NULL,
809 
810  /* initData */ initData,
811  /* requiredDataMask */ requiredDataMask,
812  /* freeData */ NULL,
813  /* isDisabled */ isDisabled,
814  /* updateDepsgraph */ updateDepsgraph,
815  /* dependsOnTime */ NULL,
816  /* dependsOnNormals */ dependsOnNormals,
817  /* foreachIDLink */ foreachIDLink,
818  /* foreachTexLink */ NULL,
819  /* freeRuntimeData */ NULL,
820  /* panelRegister */ panelRegister,
821  /* blendWrite */ NULL,
822  /* blendRead */ NULL,
823 };
typedef float(TangentPoint)[2]
@ CD_CALLOC
void CustomData_free_layers(struct CustomData *data, int type, int totelem)
Definition: customdata.c:2716
void * CustomData_duplicate_referenced_layer(struct CustomData *data, const int type, const int totelem)
Definition: customdata.c:2788
void * CustomData_get_layer(const struct CustomData *data, int type)
void * CustomData_add_layer(struct CustomData *data, int type, eCDAllocType alloctype, void *layer, int totelem)
Definition: customdata.c:2620
void CustomData_set_layer_flag(struct CustomData *data, int type, int flag)
Definition: customdata.c:2475
support for deformation groups and hooks.
void BKE_defvert_extract_vgroup_to_loopweights(struct MDeformVert *dvert, const int defgroup, const int num_verts, struct MLoop *loops, const int num_loops, float *r_weights, const bool invert_vgroup)
Definition: deform.c:1043
@ LIB_ID_COPY_LOCALIZE
Definition: BKE_lib_id.h:145
struct ID * BKE_id_copy_ex(struct Main *bmain, const struct ID *id, struct ID **r_newid, const int flag)
@ IDWALK_CB_NOP
Definition: BKE_lib_query.h:47
void BKE_mesh_normals_loop_custom_set(const struct MVert *mverts, const int numVerts, struct MEdge *medges, const int numEdges, struct MLoop *mloops, float(*r_custom_loopnors)[3], const int numLoops, struct MPoly *mpolys, const float(*polynors)[3], const int numPolys, short(*r_clnors_data)[2])
void BKE_mesh_polygon_flip_ex(struct MPoly *mpoly, struct MLoop *mloop, struct CustomData *ldata, float(*lnors)[3], struct MDisps *mdisp, const bool use_loop_mdisp_flip)
void BKE_mesh_calc_normals(struct Mesh *me)
void BKE_mesh_normals_loop_split(const struct MVert *mverts, const int numVerts, struct MEdge *medges, const int numEdges, struct MLoop *mloops, float(*r_loopnors)[3], const int numLoops, struct MPoly *mpolys, const float(*polynors)[3], const int numPolys, const bool use_split_normals, const float split_angle, MLoopNorSpaceArray *r_lnors_spacearr, short(*clnors_data)[2], int *r_loop_to_poly)
void BKE_mesh_calc_normals_poly(struct MVert *mverts, float(*r_vertnors)[3], int numVerts, const struct MLoop *mloop, const struct MPoly *mpolys, int numLoops, int numPolys, float(*r_polyNors)[3], const bool only_face_normals)
void(* IDWalkFunc)(void *userData, struct Object *ob, struct ID **idpoin, int cb_flag)
Definition: BKE_modifier.h:120
@ eModifierTypeFlag_SupportsMapping
Definition: BKE_modifier.h:82
@ eModifierTypeFlag_EnableInEditmode
Definition: BKE_modifier.h:92
@ eModifierTypeFlag_SupportsEditmode
Definition: BKE_modifier.h:83
@ eModifierTypeFlag_AcceptsMesh
Definition: BKE_modifier.h:80
void BKE_modifier_copydata_generic(const struct ModifierData *md, struct ModifierData *md_dst, const int flag)
@ eModifierTypeType_Constructive
Definition: BKE_modifier.h:61
void BKE_modifier_set_error(const struct Object *ob, struct ModifierData *md, const char *format,...) ATTR_PRINTF_FORMAT(3
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define BLI_BITMAP_TEST(_bitmap, _index)
Definition: BLI_bitmap.h:63
#define BLI_BITMAP_ENABLE(_bitmap, _index)
Definition: BLI_bitmap.h:78
#define BLI_BITMAP_NEW(_tot, _alloc_string)
Definition: BLI_bitmap.h:50
unsigned int BLI_bitmap
Definition: BLI_bitmap.h:32
MINLINE float min_ff(float a, float b)
#define M_PI
Definition: BLI_math_base.h:38
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:262
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1278
void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:742
float angle_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
Definition: math_vector.c:443
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3])
Definition: math_vector.c:1020
MINLINE float normalize_v3(float r[3])
MINLINE void mul_v3_v3(float r[3], const float a[3])
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void negate_v3_v3(float r[3], const float a[3])
MINLINE bool is_zero_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
void interp_v3_v3v3_slerp_safe(float target[3], const float a[3], const float b[3], const float t)
Definition: math_vector.c:121
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void negate_v3(float r[3])
MINLINE void abs_v3_v3(float r[3], const float a[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
#define INIT_MINMAX(min, max)
#define UNUSED(x)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define CLAMP_MIN(a, b)
void DEG_add_object_relation(struct DepsNodeHandle *node_handle, struct Object *object, eDepsObjectComponentType component, const char *description)
void DEG_add_modifier_to_transform_relation(struct DepsNodeHandle *node_handle, const char *description)
@ DEG_OB_COMP_TRANSFORM
#define CD_MASK_NORMAL
#define CD_MASK_MDEFORMVERT
@ CD_CUSTOMLOOPNORMAL
#define CD_MASK_CUSTOMLOOPNORMAL
@ CD_FLAG_TEMPORARY
#define DNA_struct_default_get(struct_name)
Definition: DNA_defaults.h:44
@ ME_AUTOSMOOTH
struct NormalEditModifierData NormalEditModifierData
@ MOD_NORMALEDIT_MODE_RADIAL
@ MOD_NORMALEDIT_MODE_DIRECTIONAL
@ eModifierType_NormalEdit
@ MOD_NORMALEDIT_NO_POLYNORS_FIX
@ MOD_NORMALEDIT_INVERT_VGROUP
@ MOD_NORMALEDIT_USE_DIRECTION_PARALLEL
@ MOD_NORMALEDIT_MIX_COPY
@ MOD_NORMALEDIT_MIX_ADD
@ MOD_NORMALEDIT_MIX_SUB
@ MOD_NORMALEDIT_MIX_MUL
Object is a sort of wrapper for general info.
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble x2
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
static bool is_valid_target(NormalEditModifierData *enmd)
static Mesh * modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
static void generate_vert_coordinates(Mesh *mesh, Object *ob, Object *ob_center, const float offset[3], const int num_verts, float(*r_cos)[3], float r_size[3])
static void mix_mode_panel_draw(const bContext *UNUSED(C), Panel *panel)
static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
static bool is_valid_target_with_error(const Object *ob, NormalEditModifierData *enmd)
ModifierTypeInfo modifierType_NormalEdit
static bool isDisabled(const struct Scene *UNUSED(scene), ModifierData *md, bool UNUSED(useRenderParams))
static void offset_panel_draw(const bContext *UNUSED(C), Panel *panel)
static void mix_normals(const float mix_factor, MDeformVert *dvert, const int defgrp_index, const bool use_invert_vgroup, const float mix_limit, const short mix_mode, const int num_verts, MLoop *mloop, float(*nos_old)[3], float(*nos_new)[3], const int num_loops)
static void normalEditModifier_do_directional(NormalEditModifierData *enmd, const ModifierEvalContext *UNUSED(ctx), Object *ob, Mesh *mesh, short(*clnors)[2], float(*loopnors)[3], float(*polynors)[3], const short mix_mode, const float mix_factor, const float mix_limit, MDeformVert *dvert, const int defgrp_index, const bool use_invert_vgroup, MVert *mvert, const int num_verts, MEdge *medge, const int num_edges, MLoop *mloop, const int num_loops, MPoly *mpoly, const int num_polys)
static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
static bool dependsOnNormals(ModifierData *UNUSED(md))
static Mesh * normalEditModifier_do(NormalEditModifierData *enmd, const ModifierEvalContext *ctx, Object *ob, Mesh *mesh)
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
static void normalEditModifier_do_radial(NormalEditModifierData *enmd, const ModifierEvalContext *UNUSED(ctx), Object *ob, Mesh *mesh, short(*clnors)[2], float(*loopnors)[3], float(*polynors)[3], const short mix_mode, const float mix_factor, const float mix_limit, MDeformVert *dvert, const int defgrp_index, const bool use_invert_vgroup, MVert *mvert, const int num_verts, MEdge *medge, const int num_edges, MLoop *mloop, const int num_loops, MPoly *mpoly, const int num_polys)
static void initData(ModifierData *md)
static void panelRegister(ARegionType *region_type)
static void requiredDataMask(Object *UNUSED(ob), ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
static bool polygons_check_flip(MLoop *mloop, float(*nos)[3], CustomData *ldata, MPoly *mpoly, float(*polynors)[3], const int num_polys)
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void modifier_panel_end(uiLayout *layout, PointerRNA *ptr)
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
void modifier_vgroup_ui(uiLayout *layout, PointerRNA *ptr, PointerRNA *ob_ptr, const char *vgroup_prop, const char *invert_vgroup_prop, const char *text)
PanelType * modifier_subpanel_register(ARegionType *region_type, const char *name, const char *label, PanelDrawFn draw_header, PanelDrawFn draw, PanelType *parent)
void MOD_get_vgroup(Object *ob, struct Mesh *mesh, const char *name, MDeformVert **dvert, int *defgrp_index)
Definition: MOD_util.c:254
StructRNA RNA_NormalEditModifier
#define C
Definition: RandGen.cpp:39
void uiLayoutSetActive(uiLayout *layout, bool active)
@ UI_ITEM_R_EXPAND
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
Scene scene
uint col
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:48
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
static unsigned c
Definition: RandGen.cpp:97
static unsigned a[3]
Definition: RandGen.cpp:92
IMETHOD Vector diff(const Vector &a, const Vector &b, double dt=1)
INLINE Rall1d< T, V, S > cos(const Rall1d< T, V, S > &arg)
Definition: rall1d.h:319
PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6562
bool RNA_pointer_is_null(const PointerRNA *ptr)
Definition: rna_access.c:174
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6261
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
Definition: DNA_ID.h:273
unsigned int v
int64_t cd_dirty_vert
struct MEdge * medge
struct CustomData pdata ldata
struct MVert * mvert
int totvert
short flag
Mesh_Runtime runtime
int totloop
struct Object * object
Definition: BKE_modifier.h:154
struct DepsNodeHandle * node
Definition: BKE_modifier.h:147
float scale[3]
float obmat[4][4]
void * data
struct uiLayout * layout
PointerRNA * ptr
Definition: wm_files.c:3157