[Bf-blender-cvs] [c4e4924096d] master: GPencil: Fading for build modifier.

YimingWu noreply at git.blender.org
Tue Mar 29 16:49:24 CEST 2022


Commit: c4e4924096d1dcfd971aafbbf82d848a774b57db
Author: YimingWu
Date:   Tue Mar 29 22:46:30 2022 +0800
Branches: master
https://developer.blender.org/rBc4e4924096d1dcfd971aafbbf82d848a774b57db

GPencil: Fading for build modifier.

Adds fading support for build modifier so it's not a hard cut off

Reviewed By: Antonio Vazquez (antoniov), Matias Mendiola (mendio)

Differential Revision: https://developer.blender.org/D14309

===================================================================

M	source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
M	source/blender/makesdna/DNA_gpencil_modifier_types.h
M	source/blender/makesrna/intern/rna_gpencil_modifier.c

===================================================================

diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
index 1a69a6a8a38..18ce9a12f7b 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
@@ -6,6 +6,7 @@
  */
 
 #include <stdio.h>
+#include <stdlib.h>
 
 #include "MEM_guardedalloc.h"
 
@@ -13,6 +14,7 @@
 
 #include "BLI_blenlib.h"
 #include "BLI_math.h"
+#include "BLI_sort.h"
 
 #include "BLT_translation.h"
 
@@ -25,9 +27,12 @@
 #include "DNA_screen_types.h"
 
 #include "BKE_context.h"
+#include "BKE_deform.h"
 #include "BKE_gpencil.h"
 #include "BKE_gpencil_geom.h"
 #include "BKE_gpencil_modifier.h"
+#include "BKE_lib_query.h"
+#include "BKE_modifier.h"
 #include "BKE_screen.h"
 
 #include "UI_interface.h"
@@ -99,17 +104,22 @@ static void gpf_clear_all_strokes(bGPDframe *gpf)
  * NOTE: This won't be called if all points are present/removed
  */
 static void reduce_stroke_points(bGPdata *gpd,
+                                 bGPDframe *gpf,
                                  bGPDstroke *gps,
                                  const int num_points,
                                  const eBuildGpencil_Transition transition)
 {
+  if (num_points == 0) {
+    clear_stroke(gpf, gps);
+    return;
+  }
   bGPDspoint *new_points = MEM_callocN(sizeof(bGPDspoint) * num_points, __func__);
   MDeformVert *new_dvert = NULL;
   if ((gps->dvert != NULL) && (num_points > 0)) {
     new_dvert = MEM_callocN(sizeof(MDeformVert) * num_points, __func__);
   }
 
-  /* Which end should points be removed from */
+  /* Which end should points be removed from. */
   switch (transition) {
     case GP_BUILD_TRANSITION_GROW:   /* Show in forward order =
                                       * Remove ungrown-points from end of stroke. */
@@ -131,7 +141,7 @@ static void reduce_stroke_points(bGPdata *gpd,
     }
 
     /* Hide in forward order = Remove points from start of stroke */
-    case GP_BUILD_TRANSITION_FADE: {
+    case GP_BUILD_TRANSITION_VANISH: {
       /* num_points is the number of points left after reducing.
        * We need to know how many to remove
        */
@@ -167,6 +177,57 @@ static void reduce_stroke_points(bGPdata *gpd,
   BKE_gpencil_stroke_geometry_update(gpd, gps);
 }
 
+static void fade_stroke_points(bGPDstroke *gps,
+                               const int starting_index,
+                               const int ending_index,
+                               const float starting_weight,
+                               const float ending_weight,
+                               const int target_def_nr,
+                               const eBuildGpencil_Transition transition,
+                               const float thickness_strength,
+                               const float opacity_strength)
+{
+  MDeformVert *dvert;
+
+  int range = ending_index - starting_index;
+  if (!range) {
+    range = 1;
+  }
+
+  /* Which end should points be removed from */
+  switch (transition) {
+    /* Because starting_weight and ending_weight are set in correct order before calling this
+     * function, those three modes can use the same interpolation code. */
+    case GP_BUILD_TRANSITION_GROW:
+    case GP_BUILD_TRANSITION_SHRINK:
+    case GP_BUILD_TRANSITION_VANISH: {
+      for (int i = starting_index; i <= ending_index; i++) {
+        float weight = interpf(
+            ending_weight, starting_weight, (float)(i - starting_index) / range);
+        if (target_def_nr >= 0) {
+          dvert = &gps->dvert[i];
+          MDeformWeight *dw = BKE_defvert_ensure_index(dvert, target_def_nr);
+          if (dw) {
+            dw->weight = weight;
+            CLAMP(dw->weight, 0.0f, 1.0f);
+          }
+        }
+        if (thickness_strength > 1e-5) {
+          gps->points[i].pressure *= interpf(weight, 1.0f, thickness_strength);
+        }
+        if (opacity_strength > 1e-5) {
+          gps->points[i].strength *= interpf(weight, 1.0f, opacity_strength);
+        }
+      }
+      break;
+    }
+
+    default:
+      printf("ERROR: Unknown transition %d in %s()\n", (int)transition, __func__);
+      break;
+  }
+}
+
 /* --------------------------------------------- */
 
 /* Stroke Data Table Entry - This represents one stroke being generated */
@@ -178,11 +239,26 @@ typedef struct tStrokeBuildDetails {
 
   /* Number of points - Cache for more convenient access */
   int totpoints;
+
+  /* Distance to control object, used to sort the strokes if set. */
+  float distance;
 } tStrokeBuildDetails;
 
+static int cmp_stroke_build_details(const void *ps1, const void *ps2)
+{
+  tStrokeBuildDetails *p1 = (tStrokeBuildDetails *)ps1;
+  tStrokeBuildDetails *p2 = (tStrokeBuildDetails *)ps2;
+  return p1->distance > p2->distance ? 1 : (p1->distance == p2->distance ? 0 : -1);
+}
+
 /* Sequential and additive - Show strokes one after the other. */
-static void build_sequential(
-    BuildGpencilModifierData *mmd, bGPdata *gpd, bGPDframe *gpf, float fac, bool additive)
+static void build_sequential(Object *ob,
+                             BuildGpencilModifierData *mmd,
+                             bGPdata *gpd,
+                             bGPDframe *gpf,
+                             const int target_def_nr,
+                             float fac,
+                             bool additive)
 {
   size_t tot_strokes = BLI_listbase_count(&gpf->strokes);
   size_t start_stroke;
@@ -222,6 +298,26 @@ static void build_sequential(
     cell->totpoints = gps->totpoints;
 
     totpoints += cell->totpoints;
+
+    /* Compute distance to control object if set, and build according to that order. */
+    if (mmd->object) {
+      float sv1[3], sv2[3];
+      mul_v3_m4v3(sv1, ob->obmat, &gps->points[0].x);
+      mul_v3_m4v3(sv2, ob->obmat, &gps->points[gps->totpoints - 1].x);
+      float dist_l = len_v3v3(sv1, mmd->object->loc);
+      float dist_r = len_v3v3(sv2, mmd->object->loc);
+      if (dist_r < dist_l) {
+        BKE_gpencil_stroke_flip(gps);
+        cell->distance = dist_r;
+      }
+      else {
+        cell->distance = dist_l;
+      }
+    }
+  }
+
+  if (mmd->object) {
+    qsort(table, tot_strokes, sizeof(tStrokeBuildDetails), cmp_stroke_build_details);
   }
 
   /* 2.2) Second pass - Compute the overall indices for points */
@@ -240,6 +336,17 @@ static void build_sequential(
   /* 3) Determine the global indices for points that should be visible */
   size_t first_visible = 0;
   size_t last_visible = 0;
+  /* Need signed numbers because the representation of fading offset would exceed the beginning and
+   * the end of offsets. */
+  int fade_start = 0;
+  int fade_end = 0;
+
+  bool fading_enabled = (mmd->flag & GP_BUILD_USE_FADING);
+
+  float set_fade_fac = fading_enabled ? mmd->fade_fac : 0.0f;
+  float use_fac = interpf(1 + set_fade_fac, 0, fac);
+  float use_fade_fac = use_fac - set_fade_fac;
+  CLAMP(use_fade_fac, 0.0f, 1.0f);
 
   switch (mmd->transition) {
       /* Show in forward order
@@ -247,7 +354,9 @@ static void build_sequential(
        */
     case GP_BUILD_TRANSITION_GROW:
       first_visible = 0; /* always visible */
-      last_visible = (size_t)roundf(totpoints * fac);
+      last_visible = (size_t)roundf(totpoints * use_fac);
+      fade_start = (int)roundf(totpoints * use_fade_fac);
+      fade_end = last_visible;
       break;
 
       /* Hide in reverse order
@@ -255,15 +364,19 @@ static void build_sequential(
        */
     case GP_BUILD_TRANSITION_SHRINK:
       first_visible = 0; /* always visible (until last point removed) */
-      last_visible = (size_t)(totpoints * (1.0f - fac));
+      last_visible = (size_t)(totpoints * (1.0f + set_fade_fac - use_fac));
+      fade_start = (int)roundf(totpoints * (1.0f - use_fade_fac - set_fade_fac));
+      fade_end = last_visible;
       break;
 
       /* Hide in forward order
        *  - As fac increases, the early points start getting hidden
        */
-    case GP_BUILD_TRANSITION_FADE:
-      first_visible = (size_t)(totpoints * fac);
+    case GP_BUILD_TRANSITION_VANISH:
+      first_visible = (size_t)(totpoints * use_fade_fac);
       last_visible = totpoints; /* i.e. visible until the end, unless first overlaps this */
+      fade_start = first_visible;
+      fade_end = (int)roundf(totpoints * use_fac);
       break;
   }
 
@@ -277,6 +390,30 @@ static void build_sequential(
       clear_stroke(gpf, cell->gps);
     }
     else {
+      if (fade_start != fade_end && (int)cell->start_idx < fade_end &&
+          (int)cell->end_idx > fade_start) {
+        int start_index = fade_start - cell->start_idx;
+        int end_index = cell->totpoints + fade_end - cell->end_idx - 1;
+        CLAMP(start_index, 0, cell->totpoints - 1);
+        CLAMP(end_index, 0, cell->totpoints - 1);
+        float start_weight = ratiof(fade_start, fade_end, cell->start_idx + start_index);
+        float end_weight = ratiof(fade_start, fade_end, cell->start_idx + end_index);
+        if (mmd->transition != GP_BUILD_TRANSITION_VANISH) {
+          start_weight = 1.0f - start_weight;
+          end_weight = 1.0f - end_weight;
+        }
+        fade_stroke_points(cell->gps,
+                           start_index,
+                           end_index,
+                           start_weight,
+                           end_weight,
+                           target_def_nr,
+                           mmd->transition,
+                           mmd->fade_thickness_strength,
+                           mmd->fade_opacity_strength);
+        /* Calc geometry data. */
+        BKE_gpencil_stroke_geometry_update(gpd, cell->gps);
+      }
       /* Some proportion of stroke is visible */
       if ((first_visible <= cell->start_idx) && (last_visible >= cell->end_idx)) {
         /* Do nothing - whole stroke is visible */
@@ -284,12 +421,12 @@ static void build_sequential(
       else if (first_visible > cell->start_idx) {
         /* Starts partway through this stroke */
         int num_points = cell->end_idx - first_visible;
-        reduce_stroke_points(gpd, cell->gps, num_points, mmd->transition);
+        reduce_stroke_points(gpd, gpf, cell->gps, num_points, mmd->transition);
   

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list