Blender  V3.3
MOD_gpencilenvelope.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2017 Blender Foundation. */
3 
8 #include <stdio.h>
9 
10 #include "BLI_listbase.h"
11 #include "BLI_math_geom.h"
12 #include "BLI_math_vector.h"
13 #include "BLI_utildefines.h"
14 
15 #include "BLT_translation.h"
16 
17 #include "DNA_defaults.h"
19 #include "DNA_gpencil_types.h"
20 #include "DNA_meshdata_types.h"
21 #include "DNA_object_types.h"
22 #include "DNA_scene_types.h"
23 #include "DNA_screen_types.h"
24 
25 #include "BKE_context.h"
26 #include "BKE_deform.h"
27 #include "BKE_gpencil.h"
28 #include "BKE_gpencil_geom.h"
29 #include "BKE_gpencil_modifier.h"
30 #include "BKE_lib_query.h"
31 #include "BKE_modifier.h"
32 #include "BKE_screen.h"
33 
34 #include "DEG_depsgraph.h"
35 #include "DEG_depsgraph_build.h"
36 #include "DEG_depsgraph_query.h"
37 
38 #include "UI_interface.h"
39 #include "UI_resources.h"
40 
41 #include "RNA_access.h"
42 
44 #include "MOD_gpencil_ui_common.h"
45 #include "MOD_gpencil_util.h"
46 
47 #include "MEM_guardedalloc.h"
48 
49 static void initData(GpencilModifierData *md)
50 {
52 
53  BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(gpmd, modifier));
54 
56 }
57 
58 static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
59 {
61 }
62 
63 static float calc_min_radius_v3v3(float p1[3], float p2[3], float dir[3])
64 {
65  /* Use plane-conic-intersections to choose the maximal radius.
66  * The conic is defined in 4D as f({x,y,z,t}) = x*x + y*y + z*z - t*t = 0
67  * Then a plane is defined parametrically as
68  * {p}(u, v) = {p1,0}*u + {p2,0}*(1-u) + {dir,1}*v with 0 <= u <= 1 and v >= 0
69  * Now compute the intersection point with the smallest t.
70  * To do so, compute the parameters u, v such that f(p(u, v)) = 0 and v is minimal.
71  * This can be done analytically and the solution is:
72  * u = -dot(p2,dir) / dot(p1-p2, dir) +/- sqrt((dot(p2,dir) / dot(p1-p2, dir))^2 -
73  * (2*dot(p1-p2,p2)*dot(p2,dir)-dot(p2,p2)*dot(p1-p2,dir))/(dot(p1-p2,dir)*dot(p1-p2,p1-p2)));
74  * v = ({p1}u + {p2}*(1-u))^2 / (2*(dot(p1,dir)*u + dot(p2,dir)*(1-u)));
75  */
76  float diff[3];
77  float p1_dir = dot_v3v3(p1, dir);
78  float p2_dir = dot_v3v3(p2, dir);
79  float p2_sqr = len_squared_v3(p2);
80  float diff_dir = p1_dir - p2_dir;
81  float u = 0.5f;
82  if (diff_dir != 0.0f) {
83  float p = p2_dir / diff_dir;
84  sub_v3_v3v3(diff, p1, p2);
85  float diff_sqr = len_squared_v3(diff);
86  float diff_p2 = dot_v3v3(diff, p2);
87  float q = (2 * diff_p2 * p2_dir - p2_sqr * diff_dir) / (diff_dir * diff_sqr);
88  if (p * p - q >= 0) {
89  u = -p - sqrtf(p * p - q) * copysign(1.0f, p);
90  CLAMP(u, 0.0f, 1.0f);
91  }
92  else {
93  u = 0.5f - copysign(0.5f, p);
94  }
95  }
96  else {
97  float p1_sqr = len_squared_v3(p1);
98  u = p1_sqr < p2_sqr ? 1.0f : 0.0f;
99  }
100  float p[3];
101  interp_v3_v3v3(p, p2, p1, u);
102  /* v is the determined minimal radius. In case p1 and p2 are the same, there is a
103  * simple proof for the following formula using the geometric mean theorem and Thales theorem. */
104  float v = len_squared_v3(p) / (2 * interpf(p1_dir, p2_dir, u));
105  if (v < 0 || !isfinite(v)) {
106  /* No limit to the radius from this segment. */
107  return 1e16f;
108  }
109  return v;
110 }
111 
112 static float calc_radius_limit(
113  bGPDstroke *gps, bGPDspoint *points, float dir[3], int spread, const int i)
114 {
115  const bool is_cyclic = (gps->flag & GP_STROKE_CYCLIC) != 0;
116  bGPDspoint *pt = &points[i];
117 
118  /* NOTE this part is the second performance critical part. Improvements are welcome. */
119  float radius_limit = 1e16f;
120  float p1[3], p2[3];
121  if (is_cyclic) {
122  if (gps->totpoints / 2 < spread) {
123  spread = gps->totpoints / 2;
124  }
125  const int start = i + gps->totpoints;
126  for (int j = -spread; j <= spread; j++) {
127  j += (j == 0);
128  const int i1 = (start + j) % gps->totpoints;
129  const int i2 = (start + j + (j > 0) - (j < 0)) % gps->totpoints;
130  sub_v3_v3v3(p1, &points[i1].x, &pt->x);
131  sub_v3_v3v3(p2, &points[i2].x, &pt->x);
132  float r = calc_min_radius_v3v3(p1, p2, dir);
133  radius_limit = min_ff(radius_limit, r);
134  }
135  }
136  else {
137  const int start = max_ii(-spread, 1 - i);
138  const int end = min_ii(spread, gps->totpoints - 2 - i);
139  for (int j = start; j <= end; j++) {
140  if (j == 0) {
141  continue;
142  }
143  const int i1 = i + j;
144  const int i2 = i + j + (j > 0) - (j < 0);
145  sub_v3_v3v3(p1, &points[i1].x, &pt->x);
146  sub_v3_v3v3(p2, &points[i2].x, &pt->x);
147  float r = calc_min_radius_v3v3(p1, p2, dir);
148  radius_limit = min_ff(radius_limit, r);
149  }
150  }
151  return radius_limit;
152 }
153 
155  int spread,
156  const int def_nr,
157  const bool invert_vg,
158  const float thickness,
159  const float pixfactor)
160 {
161  const bool is_cyclic = (gps->flag & GP_STROKE_CYCLIC) != 0;
162  if (is_cyclic) {
163  const int half = gps->totpoints / 2;
164  spread = abs(((spread + half) % gps->totpoints) - half);
165  }
166  else {
167  spread = min_ii(spread, gps->totpoints - 1);
168  }
169 
170  const int spread_left = (spread + 2) / 2;
171  const int spread_right = (spread + 1) / 2;
172 
173  /* Copy the point data. Only need positions, but extracting them
174  * is probably just as expensive as a full copy. */
175  bGPDspoint *old_points = (bGPDspoint *)MEM_dupallocN(gps->points);
176 
177  /* Deform the stroke to match the envelope shape. */
178  for (int i = 0; i < gps->totpoints; i++) {
179  MDeformVert *dvert = gps->dvert != NULL ? &gps->dvert[i] : NULL;
180 
181  /* Verify in vertex group. */
182  float weight = get_modifier_point_weight(dvert, invert_vg, def_nr);
183  if (weight < 0.0f) {
184  continue;
185  }
186 
187  int index1 = i - spread_left;
188  int index2 = i + spread_right;
189  CLAMP(index1, 0, gps->totpoints - 1);
190  CLAMP(index2, 0, gps->totpoints - 1);
191 
192  bGPDspoint *point = &gps->points[i];
193  point->pressure *= interpf(thickness, 1.0f, weight);
194 
195  float closest[3];
196  float closest2[3];
197  copy_v3_v3(closest2, &point->x);
198  float dist = 0.0f;
199  float dist2 = 0.0f;
200  /* Create plane from point and neighbors and intersect that with the line. */
201  float v1[3], v2[3], plane_no[3];
202  sub_v3_v3v3(
203  v1,
204  &old_points[is_cyclic ? (i - 1 + gps->totpoints) % gps->totpoints : max_ii(0, i - 1)].x,
205  &old_points[i].x);
206  sub_v3_v3v3(
207  v2,
208  &old_points[is_cyclic ? (i + 1) % gps->totpoints : min_ii(gps->totpoints - 1, i + 1)].x,
209  &old_points[i].x);
210  normalize_v3(v1);
211  normalize_v3(v2);
212  sub_v3_v3v3(plane_no, v1, v2);
213  if (normalize_v3(plane_no) == 0.0f) {
214  continue;
215  }
216  /* Now find the intersections with the plane. */
217  /* NOTE this part is the first performance critical part. Improvements are welcome. */
218  float tmp_closest[3];
219  for (int j = -spread_right; j <= spread_left; j++) {
220  const int i1 = is_cyclic ? (i + j - spread_left + gps->totpoints) % gps->totpoints :
221  max_ii(0, i + j - spread_left);
222  const int i2 = is_cyclic ? (i + j + spread_right) % gps->totpoints :
223  min_ii(gps->totpoints - 1, i + j + spread_right);
224 #if 0
225  bool side = dot_v3v3(&old_points[i1].x, plane_no) < dot_v3v3(plane_no, &old_points[i2].x);
226  if (side) {
227  continue;
228  }
229 #endif
230  float lambda = line_plane_factor_v3(
231  &point->x, plane_no, &old_points[i1].x, &old_points[i2].x);
232  if (lambda <= 0.0f || lambda >= 1.0f) {
233  continue;
234  }
235  interp_v3_v3v3(tmp_closest, &old_points[i1].x, &old_points[i2].x, lambda);
236 
237  float dir[3];
238  sub_v3_v3v3(dir, tmp_closest, &point->x);
239  float d = len_v3(dir);
240  /* Use a formula to find the diameter of the circle that would touch the line. */
241  float cos_angle = fabsf(dot_v3v3(plane_no, &old_points[i1].x) -
242  dot_v3v3(plane_no, &old_points[i2].x)) /
243  len_v3v3(&old_points[i1].x, &old_points[i2].x);
244  d *= 2 * cos_angle / (1 + cos_angle);
245  float to_closest[3];
246  sub_v3_v3v3(to_closest, closest, &point->x);
247  if (dist == 0.0f) {
248  dist = d;
249  copy_v3_v3(closest, tmp_closest);
250  }
251  else if (dot_v3v3(to_closest, dir) >= 0) {
252  if (d > dist) {
253  dist = d;
254  copy_v3_v3(closest, tmp_closest);
255  }
256  }
257  else {
258  if (d > dist2) {
259  dist2 = d;
260  copy_v3_v3(closest2, tmp_closest);
261  }
262  }
263  }
264  if (dist == 0.0f) {
265  copy_v3_v3(closest, &point->x);
266  }
267  if (dist2 == 0.0f) {
268  copy_v3_v3(closest2, &point->x);
269  }
270  dist = dist + dist2;
271 
272  if (dist < FLT_EPSILON) {
273  continue;
274  }
275 
276  float use_dist = dist;
277 
278  /* Apply radius limiting to not cross existing lines. */
279  float dir[3], new_center[3];
280  interp_v3_v3v3(new_center, closest2, closest, 0.5f);
281  sub_v3_v3v3(dir, new_center, &point->x);
282  if (normalize_v3(dir) != 0.0f && (is_cyclic || (i > 0 && i < gps->totpoints - 1))) {
283  const float max_radius = calc_radius_limit(gps, old_points, dir, spread, i);
284  use_dist = min_ff(use_dist, 2 * max_radius);
285  }
286 
287  float fac = use_dist * weight;
288  point->pressure += fac * pixfactor;
289  interp_v3_v3v3(&point->x, &point->x, new_center, fac / len_v3v3(closest, closest2));
290  }
291 
292  MEM_freeN(old_points);
293 }
294 
300  Object *ob,
301  bGPDlayer *gpl,
302  bGPDframe *UNUSED(gpf),
303  bGPDstroke *gps)
304 {
306  if (mmd->mode != GP_ENVELOPE_DEFORM) {
307  return;
308  }
309  const int def_nr = BKE_object_defgroup_name_index(ob, mmd->vgname);
310 
312  mmd->layername,
313  mmd->material,
314  mmd->pass_index,
315  mmd->layer_pass,
316  3,
317  gpl,
318  gps,
323  return;
324  }
325 
326  if (mmd->spread <= 0) {
327  return;
328  }
329 
330  bGPdata *gpd = (bGPdata *)ob->data;
331  const float pixfactor = 1000.0f / ((gps->thickness + gpl->line_change) * gpd->pixfactor);
333  mmd->spread,
334  def_nr,
335  (mmd->flag & GP_ENVELOPE_INVERT_VGROUP) != 0,
336  mmd->thickness,
337  pixfactor);
338 }
339 
340 static void add_stroke(Object *ob,
341  bGPDstroke *gps,
342  const int point_index,
343  const int connection_index,
344  const int size2,
345  const int size1,
346  const int mat_nr,
347  const float thickness,
348  const float strength,
349  ListBase *results)
350 {
351  const int size = size1 + size2;
352  bGPdata *gpd = ob->data;
353  bGPDstroke *gps_dst = BKE_gpencil_stroke_new(mat_nr, size, gps->thickness);
354  gps_dst->runtime.gps_orig = gps->runtime.gps_orig;
355 
356  memcpy(&gps_dst->points[0], &gps->points[connection_index], size1 * sizeof(bGPDspoint));
357  memcpy(&gps_dst->points[size1], &gps->points[point_index], size2 * sizeof(bGPDspoint));
358 
359  for (int i = 0; i < size; i++) {
360  gps_dst->points[i].pressure *= thickness;
361  gps_dst->points[i].strength *= strength;
362  }
363 
364  if (gps->dvert != NULL) {
365  gps_dst->dvert = MEM_malloc_arrayN(size, sizeof(MDeformVert), __func__);
366  BKE_defvert_array_copy(&gps_dst->dvert[0], &gps->dvert[connection_index], size1);
367  BKE_defvert_array_copy(&gps_dst->dvert[size1], &gps->dvert[point_index], size2);
368  }
369 
370  BLI_addtail(results, gps_dst);
371 
372  /* Calc geometry data. */
374 }
375 
376 static void add_stroke_cyclic(Object *ob,
377  bGPDstroke *gps,
378  const int point_index,
379  const int connection_index,
380  const int size,
381  const int mat_nr,
382  const float thickness,
383  const float strength,
384  ListBase *results)
385 {
386  bGPdata *gpd = ob->data;
387  bGPDstroke *gps_dst = BKE_gpencil_stroke_new(mat_nr, size * 2, gps->thickness);
388  gps_dst->runtime.gps_orig = gps->runtime.gps_orig;
389 
390  if (gps->dvert != NULL) {
391  gps_dst->dvert = MEM_malloc_arrayN(size * 2, sizeof(MDeformVert), __func__);
392  }
393 
394  for (int i = 0; i < size; i++) {
395  int a = (connection_index + i) % gps->totpoints;
396  int b = (point_index + i) % gps->totpoints;
397 
398  gps_dst->points[i] = gps->points[a];
399  bGPDspoint *pt_dst = &gps_dst->points[i];
400  bGPDspoint *pt_orig = &gps->points[a];
401  pt_dst->runtime.pt_orig = pt_orig->runtime.pt_orig;
402  pt_dst->runtime.idx_orig = pt_orig->runtime.idx_orig;
403 
404  gps_dst->points[size + i] = gps->points[b];
405  pt_dst = &gps_dst->points[size + i];
406  pt_orig = &gps->points[b];
407  pt_dst->runtime.pt_orig = pt_orig->runtime.pt_orig;
408  pt_dst->runtime.idx_orig = pt_orig->runtime.idx_orig;
409 
410  if (gps->dvert != NULL) {
411  BKE_defvert_array_copy(&gps_dst->dvert[i], &gps->dvert[a], 1);
412  BKE_defvert_array_copy(&gps_dst->dvert[size + i], &gps->dvert[b], 1);
413  }
414  }
415  for (int i = 0; i < size * 2; i++) {
416  gps_dst->points[i].pressure *= thickness;
417  gps_dst->points[i].strength *= strength;
418  memset(&gps_dst->points[i].runtime, 0, sizeof(bGPDspoint_Runtime));
419  }
420 
421  BLI_addtail(results, gps_dst);
422 
423  /* Calc geometry data. */
425 }
426 
427 static void add_stroke_simple(Object *ob,
428  bGPDstroke *gps,
429  const int point_index,
430  const int connection_index,
431  const int mat_nr,
432  const float thickness,
433  const float strength,
434  ListBase *results)
435 {
436  bGPdata *gpd = ob->data;
437  bGPDstroke *gps_dst = BKE_gpencil_stroke_new(mat_nr, 2, gps->thickness);
438  gps_dst->runtime.gps_orig = gps->runtime.gps_orig;
439 
440  gps_dst->points[0] = gps->points[connection_index];
441  gps_dst->points[0].pressure *= thickness;
442  gps_dst->points[0].strength *= strength;
443  bGPDspoint *pt_dst = &gps_dst->points[0];
444  bGPDspoint *pt_orig = &gps->points[connection_index];
445  pt_dst->runtime.pt_orig = pt_orig->runtime.pt_orig;
446  pt_dst->runtime.idx_orig = pt_orig->runtime.idx_orig;
447 
448  gps_dst->points[1] = gps->points[point_index];
449  gps_dst->points[1].pressure *= thickness;
450  gps_dst->points[1].strength *= strength;
451  pt_dst = &gps_dst->points[1];
452  pt_orig = &gps->points[point_index];
453  pt_dst->runtime.pt_orig = pt_orig->runtime.pt_orig;
454  pt_dst->runtime.idx_orig = pt_orig->runtime.idx_orig;
455 
456  if (gps->dvert != NULL) {
457  gps_dst->dvert = MEM_malloc_arrayN(2, sizeof(MDeformVert), __func__);
458  BKE_defvert_array_copy(&gps_dst->dvert[0], &gps->dvert[connection_index], 1);
459  BKE_defvert_array_copy(&gps_dst->dvert[1], &gps->dvert[point_index], 1);
460  }
461 
462  BLI_addtail(results, gps_dst);
463 
464  /* Calc geometry data. */
466 }
467 
469 {
471  ListBase duplicates = {0};
474  mmd->layername,
475  mmd->material,
476  mmd->pass_index,
477  mmd->layer_pass,
478  3,
479  gpl,
480  gps,
485  continue;
486  }
487 
488  const int mat_nr = mmd->mat_nr < 0 ? gps->mat_nr : min_ii(mmd->mat_nr, ob->totcol - 1);
489  if (mmd->mode == GP_ENVELOPE_FILLS) {
490  const int skip = min_ii(mmd->skip, min_ii(mmd->spread / 2, gps->totpoints - 2));
491  if (gps->flag & GP_STROKE_CYCLIC) {
492  for (int i = 0; i < gps->totpoints; i++) {
493  const int connection_index = (i + mmd->spread - skip) % gps->totpoints;
495  gps,
496  i,
497  connection_index,
498  2 + skip,
499  mat_nr,
500  mmd->thickness,
501  mmd->strength,
502  &duplicates);
503  i += mmd->skip;
504  }
505  }
506  else {
507  for (int i = -mmd->spread + skip; i < gps->totpoints - 1; i++) {
508  const int point_index = max_ii(0, i);
509  const int connection_index = min_ii(i + mmd->spread + 1, gps->totpoints - 1);
510  const int size1 = min_ii(2 + skip,
511  min_ii(point_index + 1, gps->totpoints - point_index));
512  const int size2 = min_ii(
513  2 + skip, min_ii(connection_index + 1, gps->totpoints - connection_index));
514  add_stroke(ob,
515  gps,
516  point_index,
517  connection_index + 1 - size2,
518  size1,
519  size2,
520  mat_nr,
521  mmd->thickness,
522  mmd->strength,
523  &duplicates);
524  i += mmd->skip;
525  }
526  }
527  BLI_remlink(&gpf->strokes, gps);
529  }
530  else {
532  if (gps->flag & GP_STROKE_CYCLIC) {
533  for (int i = 0; i < gps->totpoints; i++) {
534  const int connection_index = (i + 1 + mmd->spread) % gps->totpoints;
536  ob, gps, i, connection_index, mat_nr, mmd->thickness, mmd->strength, &duplicates);
537  i += mmd->skip;
538  }
539  }
540  else {
541  for (int i = -mmd->spread; i < gps->totpoints - 1; i++) {
542  const int connection_index = min_ii(i + 1 + mmd->spread, gps->totpoints - 1);
544  gps,
545  max_ii(0, i),
546  connection_index,
547  mat_nr,
548  mmd->thickness,
549  mmd->strength,
550  &duplicates);
551  i += mmd->skip;
552  }
553  }
554  }
555  }
556  if (!BLI_listbase_is_empty(&duplicates)) {
557  /* Add strokes to the start of the stroke list to ensure the new lines are drawn underneath the
558  * original line. */
559  BLI_movelisttolist_reverse(&gpf->strokes, &duplicates);
560  }
561 }
562 
567 {
569  if (mmd->mode == GP_ENVELOPE_DEFORM || mmd->spread <= 0) {
570  return;
571  }
573  bGPdata *gpd = (bGPdata *)ob->data;
574 
575  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
577  if (gpf == NULL) {
578  continue;
579  }
580  generate_geometry(md, ob, gpl, gpf);
581  }
582 }
583 
584 static void bakeModifier(struct Main *UNUSED(bmain),
587  Object *ob)
588 {
590  if (mmd->mode == GP_ENVELOPE_DEFORM) {
592  }
593  else {
594  bGPdata *gpd = ob->data;
595 
596  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
597  LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
598  generate_geometry(md, ob, gpl, gpf);
599  }
600  }
601  }
602 }
603 
604 static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
605 {
607 
608  walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER);
609 }
610 
611 static void panel_draw(const bContext *UNUSED(C), Panel *panel)
612 {
613  uiLayout *layout = panel->layout;
614 
616 
617  uiLayoutSetPropSep(layout, true);
618 
619  uiItemR(layout, ptr, "mode", 0, NULL, ICON_NONE);
620 
621  uiItemR(layout, ptr, "spread", 0, NULL, ICON_NONE);
622  uiItemR(layout, ptr, "thickness", 0, NULL, ICON_NONE);
623 
624  const int mode = RNA_enum_get(ptr, "mode");
625  if (mode != GP_ENVELOPE_DEFORM) {
626  uiItemR(layout, ptr, "strength", 0, NULL, ICON_NONE);
627  uiItemR(layout, ptr, "mat_nr", 0, NULL, ICON_NONE);
628  uiItemR(layout, ptr, "skip", 0, NULL, ICON_NONE);
629  }
630 
632 }
633 
634 static void mask_panel_draw(const bContext *UNUSED(C), Panel *panel)
635 {
636  gpencil_modifier_masking_panel_draw(panel, true, true);
637 }
638 
639 static void panelRegister(ARegionType *region_type)
640 {
644  region_type, "mask", "Influence", NULL, mask_panel_draw, panel_type);
645 }
646 
648  /* name */ N_("Envelope"),
649  /* structName */ "EnvelopeGpencilModifierData",
650  /* structSize */ sizeof(EnvelopeGpencilModifierData),
653 
654  /* copyData */ copyData,
655 
656  /* deformStroke */ deformStroke,
657  /* generateStrokes */ generateStrokes,
658  /* bakeModifier */ bakeModifier,
659  /* remapTime */ NULL,
660 
661  /* initData */ initData,
662  /* freeData */ NULL,
663  /* isDisabled */ NULL,
664  /* updateDepsgraph */ NULL,
665  /* dependsOnTime */ NULL,
666  /* foreachIDLink */ foreachIDLink,
667  /* foreachTexLink */ NULL,
668  /* panelRegister */ panelRegister,
669 };
support for deformation groups and hooks.
int BKE_object_defgroup_name_index(const struct Object *ob, const char *name)
void BKE_defvert_array_copy(struct MDeformVert *dst, const struct MDeformVert *src, int totvert)
struct bGPDstroke * BKE_gpencil_stroke_new(int mat_idx, int totpoints, short thickness)
Definition: gpencil.c:756
void BKE_gpencil_free_stroke(struct bGPDstroke *gps)
Definition: gpencil.c:391
void BKE_gpencil_stroke_geometry_update(struct bGPdata *gpd, struct bGPDstroke *gps)
void BKE_gpencil_modifier_copydata_generic(const struct GpencilModifierData *md_src, struct GpencilModifierData *md_dst)
@ eGpencilModifierTypeFlag_SupportsEditmode
struct bGPDframe * BKE_gpencil_frame_retime_get(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, struct bGPDlayer *gpl)
@ eGpencilModifierTypeType_Gpencil
@ IDWALK_CB_USER
Definition: BKE_lib_query.h:73
void(* IDWalkFunc)(void *userData, struct Object *ob, struct ID **idpoin, int cb_flag)
Definition: BKE_modifier.h:107
#define BLI_assert(a)
Definition: BLI_assert.h:46
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
Definition: BLI_listbase.h:354
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:100
void void void void BLI_movelisttolist_reverse(struct ListBase *dst, struct ListBase *src) ATTR_NONNULL(1
MINLINE int min_ii(int a, int b)
MINLINE float min_ff(float a, float b)
MINLINE int max_ii(int a, int b)
MINLINE float interpf(float a, float b, float t)
float line_plane_factor_v3(const float plane_co[3], const float plane_no[3], const float l1[3], const float l2[3])
Definition: math_geom.c:3279
MINLINE float len_squared_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float normalize_v3(float r[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 float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
Definition: math_vector.c:29
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
#define UNUSED(x)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
struct Scene * DEG_get_evaluated_scene(const struct Depsgraph *graph)
#define DNA_struct_default_get(struct_name)
Definition: DNA_defaults.h:29
struct EnvelopeGpencilModifierData EnvelopeGpencilModifierData
@ GP_ENVELOPE_INVERT_LAYERPASS
@ GP_ENVELOPE_INVERT_LAYER
@ GP_ENVELOPE_INVERT_VGROUP
@ GP_ENVELOPE_INVERT_MATERIAL
@ eGpencilModifierType_Envelope
@ GP_STROKE_CYCLIC
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 GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_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 i1
_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 v1
Read Guarded memory(de)allocation.
PointerRNA * gpencil_modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void gpencil_modifier_masking_panel_draw(Panel *panel, bool use_material, bool use_vertex)
void gpencil_modifier_panel_end(uiLayout *layout, PointerRNA *ptr)
PanelType * gpencil_modifier_subpanel_register(ARegionType *region_type, const char *name, const char *label, PanelDrawFn draw_header, PanelDrawFn draw, PanelType *parent)
PanelType * gpencil_modifier_panel_register(ARegionType *region_type, GpencilModifierType type, PanelDrawFn draw)
float get_modifier_point_weight(MDeformVert *dvert, bool inverse, int def_nr)
void generic_bake_deform_stroke(Depsgraph *depsgraph, GpencilModifierData *md, Object *ob, const bool retime, gpBakeCb bake_cb)
bool is_stroke_affected_by_modifier(Object *ob, char *mlayername, Material *material, const int mpassindex, const int gpl_passindex, const int minpoints, bGPDlayer *gpl, bGPDstroke *gps, const bool inv1, const bool inv2, const bool inv3, const bool inv4)
static void apply_stroke_envelope(bGPDstroke *gps, int spread, const int def_nr, const bool invert_vg, const float thickness, const float pixfactor)
static void deformStroke(GpencilModifierData *md, Depsgraph *UNUSED(depsgraph), Object *ob, bGPDlayer *gpl, bGPDframe *UNUSED(gpf), bGPDstroke *gps)
static void add_stroke_simple(Object *ob, bGPDstroke *gps, const int point_index, const int connection_index, const int mat_nr, const float thickness, const float strength, ListBase *results)
GpencilModifierTypeInfo modifierType_Gpencil_Envelope
static void bakeModifier(struct Main *UNUSED(bmain), Depsgraph *depsgraph, GpencilModifierData *md, Object *ob)
static void add_stroke_cyclic(Object *ob, bGPDstroke *gps, const int point_index, const int connection_index, const int size, const int mat_nr, const float thickness, const float strength, ListBase *results)
static void mask_panel_draw(const bContext *UNUSED(C), Panel *panel)
static float calc_radius_limit(bGPDstroke *gps, bGPDspoint *points, float dir[3], int spread, const int i)
static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
static float calc_min_radius_v3v3(float p1[3], float p2[3], float dir[3])
static void generate_geometry(GpencilModifierData *md, Object *ob, bGPDlayer *gpl, bGPDframe *gpf)
static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
static void panelRegister(ARegionType *region_type)
static void initData(GpencilModifierData *md)
static void generateStrokes(GpencilModifierData *md, Depsgraph *depsgraph, Object *ob)
static void add_stroke(Object *ob, bGPDstroke *gps, const int point_index, const int connection_index, const int size2, const int size1, const int mat_nr, const float thickness, const float strength, ListBase *results)
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position CLAMP
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a point
#define C
Definition: RandGen.cpp:25
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
bool closest(btVector3 &v)
Definition: half.h:41
Scene scene
const Depsgraph * depsgraph
static bool is_cyclic(const Nurb *nu)
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:34
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:28
#define fabsf(x)
Definition: metal/compat.h:219
#define sqrtf(x)
Definition: metal/compat.h:243
bool isfinite(uchar)
Definition: scene/image.cpp:31
static unsigned a[3]
Definition: RandGen.cpp:78
IMETHOD Vector diff(const Vector &a, const Vector &b, double dt=1)
T abs(const T &a)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5004
Definition: DNA_ID.h:368
Definition: BKE_main.h:121
void * data
struct uiLayout * layout
ListBase strokes
ListBase frames
struct bGPDspoint * pt_orig
bGPDspoint_Runtime runtime
struct bGPDstroke * gps_orig
bGPDspoint * points
bGPDstroke_Runtime runtime
struct MDeformVert * dvert
ListBase layers
#define N_(msgid)
PointerRNA * ptr
Definition: wm_files.c:3480