Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/gpencil_modifiers')
-rw-r--r--source/blender/gpencil_modifiers/CMakeLists.txt1
-rw-r--r--source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c42
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h7
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c9
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c304
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c36
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c120
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c9
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c9
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c30
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c148
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c227
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c9
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c134
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c15
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c52
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c11
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c79
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c116
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilvertexcolor.c314
21 files changed, 1003 insertions, 670 deletions
diff --git a/source/blender/gpencil_modifiers/CMakeLists.txt b/source/blender/gpencil_modifiers/CMakeLists.txt
index 87743911add..709674e6b43 100644
--- a/source/blender/gpencil_modifiers/CMakeLists.txt
+++ b/source/blender/gpencil_modifiers/CMakeLists.txt
@@ -59,6 +59,7 @@ set(SRC
intern/MOD_gpencilthick.c
intern/MOD_gpenciltime.c
intern/MOD_gpenciltint.c
+ intern/MOD_gpencilvertexcolor.c
MOD_gpencil_modifiertypes.h
)
diff --git a/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h b/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h
index f5c064c1c07..b8e8e8fc87f 100644
--- a/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h
+++ b/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h
@@ -43,6 +43,7 @@ extern GpencilModifierTypeInfo modifierType_Gpencil_Offset;
extern GpencilModifierTypeInfo modifierType_Gpencil_Armature;
extern GpencilModifierTypeInfo modifierType_Gpencil_Time;
extern GpencilModifierTypeInfo modifierType_Gpencil_Multiply;
+extern GpencilModifierTypeInfo modifierType_Gpencil_Vertexcolor;
/* MOD_gpencil_util.c */
void gpencil_modifier_type_init(GpencilModifierTypeInfo *types[]);
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
index 6f37cedba49..1462b6f72c9 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
@@ -72,6 +72,7 @@ void gpencil_modifier_type_init(GpencilModifierTypeInfo *types[])
INIT_GP_TYPE(Armature);
INIT_GP_TYPE(Time);
INIT_GP_TYPE(Multiply);
+ INIT_GP_TYPE(Vertexcolor);
#undef INIT_GP_TYPE
}
@@ -186,44 +187,3 @@ float get_modifier_point_weight(MDeformVert *dvert, bool inverse, int def_nr)
return weight;
}
-
-/* set material when apply modifiers (used in tint and color modifier) */
-void gpencil_apply_modifier_material(
- Main *bmain, Object *ob, Material *mat, GHash *gh_color, bGPDstroke *gps, bool crt_material)
-{
- MaterialGPencilStyle *gp_style = mat->gp_style;
-
- /* look for color */
- if (crt_material) {
- Material *newmat = BLI_ghash_lookup(gh_color, mat->id.name);
- if (newmat == NULL) {
- BKE_object_material_slot_add(bmain, ob);
- newmat = BKE_material_copy(bmain, mat);
- newmat->preview = NULL;
-
- BKE_object_material_assign(bmain, ob, newmat, ob->totcol, BKE_MAT_ASSIGN_USERPREF);
-
- copy_v4_v4(newmat->gp_style->stroke_rgba, gps->runtime.tmp_stroke_rgba);
- copy_v4_v4(newmat->gp_style->fill_rgba, gps->runtime.tmp_fill_rgba);
-
- BLI_ghash_insert(gh_color, mat->id.name, newmat);
- DEG_id_tag_update(&newmat->id, ID_RECALC_COPY_ON_WRITE);
- }
- /* Reassign color index. */
- gps->mat_nr = BKE_gpencil_object_material_get_index(ob, newmat);
- }
- else {
- /* reuse existing color (but update only first time) */
- if (BLI_ghash_lookup(gh_color, mat->id.name) == NULL) {
- copy_v4_v4(gp_style->stroke_rgba, gps->runtime.tmp_stroke_rgba);
- copy_v4_v4(gp_style->fill_rgba, gps->runtime.tmp_fill_rgba);
- BLI_ghash_insert(gh_color, mat->id.name, mat);
- }
- /* update previews (icon and thumbnail) */
- if (mat->preview != NULL) {
- mat->preview->flag[ICON_SIZE_ICON] |= PRV_CHANGED;
- mat->preview->flag[ICON_SIZE_PREVIEW] |= PRV_CHANGED;
- }
- DEG_id_tag_update(&mat->id, ID_RECALC_COPY_ON_WRITE);
- }
-}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h
index 2b1f8dbc71a..fc4522bc028 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h
@@ -47,11 +47,4 @@ bool is_stroke_affected_by_modifier(struct Object *ob,
float get_modifier_point_weight(struct MDeformVert *dvert, bool inverse, int def_nr);
-void gpencil_apply_modifier_material(struct Main *bmain,
- struct Object *ob,
- struct Material *mat,
- struct GHash *gh_color,
- struct bGPDstroke *gps,
- bool crt_material);
-
#endif /* __MOD_GPENCIL_UTIL_H__ */
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c
index eceb45780cf..a8aad763422 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c
@@ -23,6 +23,7 @@
#include <stdio.h>
+#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "BLI_math.h"
@@ -116,6 +117,8 @@ static void deformStroke(GpencilModifierData *md,
}
gpencil_deform_verts(mmd, ob, gps);
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
}
static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData *md, Object *ob)
@@ -131,8 +134,8 @@ static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData
return;
}
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
/* apply armature effects on this frame
* NOTE: this assumes that we don't want armature animation on non-keyframed frames
*/
@@ -140,7 +143,7 @@ static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData
BKE_scene_graph_update_for_newframe(depsgraph, bmain);
/* compute armature effects on this frame */
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
deformStroke(md_eval, depsgraph, object_eval, gpl, gpf, gps);
}
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c
index 11ba639fa83..1fc8c19b542 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c
@@ -27,6 +27,10 @@
#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+#include "BLI_hash.h"
+#include "BLI_rand.h"
+
#include "BLI_blenlib.h"
#include "BLI_rand.h"
#include "BLI_math.h"
@@ -54,26 +58,24 @@
#include "MOD_gpencil_util.h"
#include "MOD_gpencil_modifiertypes.h"
+typedef struct tmpStrokes {
+ struct tmpStrokes *next, *prev;
+ bGPDframe *gpf;
+ bGPDstroke *gps;
+} tmpStrokes;
+
static void initData(GpencilModifierData *md)
{
ArrayGpencilModifierData *gpmd = (ArrayGpencilModifierData *)md;
gpmd->count = 2;
- gpmd->offset[0] = 1.0f;
- gpmd->offset[1] = 0.0f;
- gpmd->offset[2] = 0.0f;
- gpmd->shift[0] = 0.0f;
+ gpmd->shift[0] = 1.0f;
gpmd->shift[1] = 0.0f;
gpmd->shift[2] = 0.0f;
- gpmd->scale[0] = 1.0f;
- gpmd->scale[1] = 1.0f;
- gpmd->scale[2] = 1.0f;
- gpmd->rnd_rot = 0.5f;
- gpmd->rnd_size = 0.5f;
+ zero_v3(gpmd->offset);
+ zero_v3(gpmd->rnd_scale);
gpmd->object = NULL;
-
- /* fill random values */
- BLI_array_frand(gpmd->rnd, 20, 1);
- gpmd->rnd[0] = 1;
+ gpmd->flag |= GP_ARRAY_USE_RELATIVE;
+ gpmd->seed = 1;
}
static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
@@ -90,46 +92,24 @@ static void BKE_gpencil_instance_modifier_instance_tfm(Object *ob,
float r_offset[4][4])
{
float offset[3], rot[3], scale[3];
- int ri = mmd->rnd[0];
- float factor;
-
- offset[0] = mmd->offset[0] * elem_idx;
- offset[1] = mmd->offset[1] * elem_idx;
- offset[2] = mmd->offset[2] * elem_idx;
-
- /* rotation */
- if (mmd->flag & GP_ARRAY_RANDOM_ROT) {
- factor = mmd->rnd_rot * mmd->rnd[ri];
- mul_v3_v3fl(rot, mmd->rot, factor);
- add_v3_v3(rot, mmd->rot);
- }
- else {
- copy_v3_v3(rot, mmd->rot);
- }
+ ARRAY_SET_ITEMS(scale, 1.0f, 1.0f, 1.0f);
+ zero_v3(rot);
- /* scale */
- if (mmd->flag & GP_ARRAY_RANDOM_SIZE) {
- factor = mmd->rnd_size * mmd->rnd[ri];
- mul_v3_v3fl(scale, mmd->scale, factor);
- add_v3_v3(scale, mmd->scale);
+ if (mmd->flag & GP_ARRAY_USE_OFFSET) {
+ offset[0] = mmd->offset[0] * elem_idx;
+ offset[1] = mmd->offset[1] * elem_idx;
+ offset[2] = mmd->offset[2] * elem_idx;
}
else {
- copy_v3_v3(scale, mmd->scale);
+ zero_v3(offset);
}
- /* advance random index */
- mmd->rnd[0]++;
- if (mmd->rnd[0] > 19) {
- mmd->rnd[0] = 1;
- }
-
- /* calculate matrix */
+ /* Calculate matrix */
loc_eul_size_to_mat4(r_mat, offset, rot, scale);
-
copy_m4_m4(r_offset, r_mat);
/* offset object */
- if (mmd->object) {
+ if ((mmd->flag & GP_ARRAY_USE_OB_OFFSET) && (mmd->object)) {
float mat_offset[4][4];
float obinv[4][4];
@@ -147,140 +127,158 @@ static void BKE_gpencil_instance_modifier_instance_tfm(Object *ob,
/* array modifier - generate geometry callback (for viewport/rendering) */
static void generate_geometry(GpencilModifierData *md,
- Depsgraph *UNUSED(depsgraph),
- Object *ob,
- bGPDlayer *gpl,
- bGPDframe *gpf)
+ Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob)
{
ArrayGpencilModifierData *mmd = (ArrayGpencilModifierData *)md;
ListBase stroke_cache = {NULL, NULL};
- bGPDstroke *gps;
- int idx;
-
- /* Check which strokes we can use once, and store those results in an array
- * for quicker checking of what's valid (since string comparisons are expensive)
- */
- const int num_strokes = BLI_listbase_count(&gpf->strokes);
- int num_valid = 0;
+ /* Load the strokes to be duplicated. */
+ bGPdata *gpd = (bGPdata *)ob->data;
+ bool found = false;
+
+ /* Get bounbox for relative offset. */
+ float size[3] = {0.0f, 0.0f, 0.0f};
+ if (mmd->flag & GP_ARRAY_USE_RELATIVE) {
+ BoundBox *bb = BKE_object_boundbox_get(ob);
+ const float min[3] = {-1.0f, -1.0f, -1.0f}, max[3] = {1.0f, 1.0f, 1.0f};
+ BKE_boundbox_init_from_minmax(bb, min, max);
+ BKE_boundbox_calc_size_aabb(bb, size);
+ mul_v3_fl(size, 2.0f);
+ /* Need a minimum size (for flat drawings). */
+ CLAMP3_MIN(size, 0.01f);
+ }
- bool *valid_strokes = MEM_callocN(sizeof(bool) * num_strokes, __func__);
+ int seed = mmd->seed;
+ /* Make sure different modifiers get different seeds. */
+ seed += BLI_hash_string(ob->id.name + 2);
+ seed += BLI_hash_string(md->name);
- for (gps = gpf->strokes.first, idx = 0; gps; gps = gps->next, idx++) {
- /* Record whether this stroke can be used
- * ATTENTION: The logic here is the inverse of what's used everywhere else!
- */
- if (is_stroke_affected_by_modifier(ob,
- mmd->layername,
- mmd->materialname,
- mmd->pass_index,
- mmd->layer_pass,
- 1,
- gpl,
- gps,
- mmd->flag & GP_ARRAY_INVERT_LAYER,
- mmd->flag & GP_ARRAY_INVERT_PASS,
- mmd->flag & GP_ARRAY_INVERT_LAYERPASS,
- mmd->flag & GP_ARRAY_INVERT_MATERIAL)) {
- valid_strokes[idx] = true;
- num_valid++;
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ bGPDframe *gpf = BKE_gpencil_frame_retime_get(depsgraph, scene, ob, gpl);
+ if (gpf == NULL) {
+ continue;
+ }
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ if (is_stroke_affected_by_modifier(ob,
+ mmd->layername,
+ mmd->materialname,
+ mmd->pass_index,
+ mmd->layer_pass,
+ 1,
+ gpl,
+ gps,
+ mmd->flag & GP_ARRAY_INVERT_LAYER,
+ mmd->flag & GP_ARRAY_INVERT_PASS,
+ mmd->flag & GP_ARRAY_INVERT_LAYERPASS,
+ mmd->flag & GP_ARRAY_INVERT_MATERIAL)) {
+ tmpStrokes *tmp = MEM_callocN(sizeof(tmpStrokes), __func__);
+ tmp->gpf = gpf;
+ tmp->gps = gps;
+ BLI_addtail(&stroke_cache, tmp);
+
+ found = true;
+ }
}
}
- /* Early exit if no strokes can be copied */
- if (num_valid == 0) {
- if (G.debug & G_DEBUG) {
- printf("GP Array Mod - No strokes to be included\n");
- }
+ if (found) {
+ /* Generate new instances of all existing strokes,
+ * keeping each instance together so they maintain
+ * the correct ordering relative to each other
+ */
+ float current_offset[4][4];
+ unit_m4(current_offset);
- MEM_SAFE_FREE(valid_strokes);
- return;
- }
+ float rand_offset = BLI_hash_int_01(seed);
- /* Generate new instances of all existing strokes,
- * keeping each instance together so they maintain
- * the correct ordering relative to each other
- */
- float current_offset[4][4];
- unit_m4(current_offset);
+ for (int x = 0; x < mmd->count; x++) {
+ /* original strokes are at index = 0 */
+ if (x == 0) {
+ continue;
+ }
- for (int x = 0; x < mmd->count; x++) {
- /* original strokes are at index = 0 */
- if (x == 0) {
- continue;
- }
+ /* Compute transforms for this instance */
+ float mat[4][4];
+ float mat_offset[4][4];
+ BKE_gpencil_instance_modifier_instance_tfm(ob, mmd, x, mat, mat_offset);
- /* Compute transforms for this instance */
- float mat[4][4];
- float mat_offset[4][4];
- BKE_gpencil_instance_modifier_instance_tfm(ob, mmd, x, mat, mat_offset);
+ if ((mmd->flag & GP_ARRAY_USE_OB_OFFSET) && (mmd->object)) {
+ /* recalculate cumulative offset here */
+ mul_m4_m4m4(current_offset, current_offset, mat_offset);
+ }
+ else {
+ copy_m4_m4(current_offset, mat);
+ }
- if (mmd->object) {
- /* recalculate cumulative offset here */
- mul_m4_m4m4(current_offset, current_offset, mat_offset);
- }
- else {
- copy_m4_m4(current_offset, mat);
- }
- /* apply shift */
- madd_v3_v3fl(current_offset[3], mmd->shift, x);
-
- /* Duplicate original strokes to create this instance */
- for (gps = gpf->strokes.first, idx = 0; gps; gps = gps->next, idx++) {
- /* check if stroke can be duplicated */
- if (valid_strokes[idx]) {
- /* Calculate original stroke center (only first loop). */
- float r_min[3], r_max[3], center[3];
- if (x == 1) {
- INIT_MINMAX(r_min, r_max);
- BKE_gpencil_stroke_minmax(gps, false, r_min, r_max);
- add_v3_v3v3(center, r_min, r_max);
- mul_v3_fl(center, 0.5f);
- sub_v3_v3v3(center, center, ob->obmat[3]);
- }
+ /* Apply relative offset. */
+ if (mmd->flag & GP_ARRAY_USE_RELATIVE) {
+ float relative[3];
+ mul_v3_v3v3(relative, mmd->shift, size);
+ madd_v3_v3fl(current_offset[3], relative, x);
+ }
+ float rand[3][3];
+ for (int j = 0; j < 3; j++) {
+ uint primes[3] = {2, 3, 7};
+ double offset[3] = {0.0, 0.0, 0.0};
+ double r[3];
+ /* To ensure a nice distribution, we use halton sequence and offset using the seed. */
+ BLI_halton_3d(primes, offset, x, r);
+
+ for (int i = 0; i < 3; i++) {
+ rand[j][i] = fmodf(r[i] * 2.0 - 1.0 + rand_offset, 1.0f);
+ rand[j][i] = fmodf(sin(rand[j][i] * 12.9898 + j * 78.233) * 43758.5453, 1.0f);
+ }
+ }
+ /* Calculate Random matrix. */
+ float mat_rnd[4][4];
+ float loc[3], rot[3];
+ float scale[3] = {1.0f, 1.0f, 1.0f};
+ mul_v3_v3v3(loc, mmd->rnd_offset, rand[0]);
+ mul_v3_v3v3(rot, mmd->rnd_rot, rand[1]);
+ madd_v3_v3v3(scale, mmd->rnd_scale, rand[2]);
+
+ loc_eul_size_to_mat4(mat_rnd, loc, rot, scale);
+
+ /* Duplicate original strokes to create this instance. */
+ LISTBASE_FOREACH_BACKWARD (tmpStrokes *, iter, &stroke_cache) {
/* Duplicate stroke */
- bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps);
+ bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(iter->gps, true);
/* Move points */
- for (int i = 0; i < gps->totpoints; i++) {
+ for (int i = 0; i < iter->gps->totpoints; i++) {
bGPDspoint *pt = &gps_dst->points[i];
+ /* Apply randomness matrix. */
+ mul_m4_v3(mat_rnd, &pt->x);
+
/* Apply object local transform (Rot/Scale). */
- if (mmd->object) {
+ if ((mmd->flag & GP_ARRAY_USE_OB_OFFSET) && (mmd->object)) {
mul_m4_v3(mat, &pt->x);
}
- /* Translate to object origin. */
- float fpt[3];
- sub_v3_v3v3(fpt, &pt->x, center);
/* Global Rotate and scale. */
- mul_mat3_m4_v3(current_offset, fpt);
+ mul_mat3_m4_v3(current_offset, &pt->x);
/* Global translate. */
- add_v3_v3(fpt, center);
- add_v3_v3v3(&pt->x, fpt, current_offset[3]);
+ add_v3_v3(&pt->x, current_offset[3]);
}
- /* if replace material, use new one */
+ /* If replace material, use new one. */
if ((mmd->mat_rpl > 0) && (mmd->mat_rpl <= ob->totcol)) {
gps_dst->mat_nr = mmd->mat_rpl - 1;
}
- /* Add new stroke to cache, to be added to the frame once
- * all duplicates have been made
- */
- BLI_addtail(&stroke_cache, gps_dst);
+ /* Add new stroke. */
+ BLI_addhead(&iter->gpf->strokes, gps_dst);
+ /* Calc bounding box. */
+ BKE_gpencil_stroke_boundingbox_calc(gps_dst);
}
}
- }
- /* merge newly created stroke instances back into the main stroke list */
- if (mmd->flag & GP_ARRAY_KEEP_ONTOP) {
- BLI_movelisttolist_reverse(&gpf->strokes, &stroke_cache);
- }
- else {
- BLI_movelisttolist(&gpf->strokes, &stroke_cache);
+ /* Free temp data. */
+ LISTBASE_FOREACH_MUTABLE (tmpStrokes *, tmp, &stroke_cache) {
+ BLI_freelinkN(&stroke_cache, tmp);
+ }
}
-
- /* free temp data */
- MEM_SAFE_FREE(valid_strokes);
}
static void bakeModifier(Main *UNUSED(bmain),
@@ -288,23 +286,17 @@ static void bakeModifier(Main *UNUSED(bmain),
GpencilModifierData *md,
Object *ob)
{
-
- bGPdata *gpd = ob->data;
-
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- generate_geometry(md, depsgraph, ob, gpl, gpf);
- }
- }
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ generate_geometry(md, depsgraph, scene, ob);
}
/* -------------------------------- */
/* Generic "generateStrokes" callback */
-static void generateStrokes(
- GpencilModifierData *md, Depsgraph *depsgraph, Object *ob, bGPDlayer *gpl, bGPDframe *gpf)
+static void generateStrokes(GpencilModifierData *md, Depsgraph *depsgraph, Object *ob)
{
- generate_geometry(md, depsgraph, ob, gpl, gpf);
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ generate_geometry(md, depsgraph, scene, ob);
}
static void updateDepsgraph(GpencilModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
index e3e7168330d..7e89d8e2d6f 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
@@ -174,10 +174,8 @@ static void reduce_stroke_points(bGPDstroke *gps,
gps->dvert = new_dvert;
gps->totpoints = num_points;
- /* mark stroke as needing to have its geometry caches rebuilt */
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- gps->tot_triangles = 0;
- MEM_SAFE_FREE(gps->triangles);
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
}
/* --------------------------------------------- */
@@ -400,19 +398,15 @@ static void build_concurrent(BuildGpencilModifierData *mmd, bGPDframe *gpf, floa
}
/* --------------------------------------------- */
-
-/* Entry-point for Build Modifier */
-static void generateStrokes(GpencilModifierData *md,
- Depsgraph *depsgraph,
- Object *UNUSED(ob),
- bGPDlayer *gpl,
- bGPDframe *gpf)
+static void generate_geometry(GpencilModifierData *md,
+ Depsgraph *depsgraph,
+ bGPDlayer *gpl,
+ bGPDframe *gpf)
{
BuildGpencilModifierData *mmd = (BuildGpencilModifierData *)md;
const bool reverse = (mmd->transition != GP_BUILD_TRANSITION_GROW);
const float ctime = DEG_get_ctime(depsgraph);
- // printf("GP Build Modifier - %f\n", ctime);
/* Early exit if it's an empty frame */
if (gpf->strokes.first == NULL) {
@@ -459,7 +453,7 @@ static void generateStrokes(GpencilModifierData *md,
* By default, the upper bound is given by the "maximum length" setting
*/
float start_frame = gpf->framenum + mmd->start_delay;
- float end_frame = gpf->framenum + mmd->length;
+ float end_frame = start_frame + mmd->length;
if (gpf->next) {
/* Use the next frame or upper bound as end frame, whichever is lower/closer */
@@ -506,7 +500,6 @@ static void generateStrokes(GpencilModifierData *md,
/* Determine how far along we are between the keyframes */
float fac = (ctime - start_frame) / (end_frame - start_frame);
- // printf(" Progress on %d = %f (%f - %f)\n", gpf->framenum, fac, start_frame, end_frame);
/* Time management mode */
switch (mmd->mode) {
@@ -526,6 +519,21 @@ static void generateStrokes(GpencilModifierData *md,
}
}
+/* Entry-point for Build Modifier */
+static void generateStrokes(GpencilModifierData *md, Depsgraph *depsgraph, Object *ob)
+{
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ bGPdata *gpd = (bGPdata *)ob->data;
+
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ bGPDframe *gpf = BKE_gpencil_frame_retime_get(depsgraph, scene, ob, gpl);
+ if (gpf == NULL) {
+ continue;
+ }
+ generate_geometry(md, depsgraph, gpl, gpf);
+ }
+}
+
/* ******************************************** */
GpencilModifierTypeInfo modifierType_Gpencil_Build = {
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c
index d9869c92e06..3a930b40c8b 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c
@@ -26,7 +26,6 @@
#include "BLI_utildefines.h"
#include "BLI_blenlib.h"
-#include "BLI_ghash.h"
#include "BLI_math_color.h"
#include "BLI_math_vector.h"
@@ -35,6 +34,7 @@
#include "DNA_gpencil_types.h"
#include "DNA_gpencil_modifier_types.h"
+#include "BKE_colortools.h"
#include "BKE_gpencil.h"
#include "BKE_gpencil_modifier.h"
#include "BKE_main.h"
@@ -52,13 +52,28 @@ static void initData(GpencilModifierData *md)
ARRAY_SET_ITEMS(gpmd->hsv, 0.5f, 1.0f, 1.0f);
gpmd->layername[0] = '\0';
gpmd->materialname[0] = '\0';
- gpmd->flag |= GP_COLOR_CREATE_COLORS;
gpmd->modify_color = GP_MODIFY_COLOR_BOTH;
+
+ gpmd->curve_intensity = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ if (gpmd->curve_intensity) {
+ CurveMapping *curve = gpmd->curve_intensity;
+ BKE_curvemapping_initialize(curve);
+ }
}
static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
{
+ ColorGpencilModifierData *gmd = (ColorGpencilModifierData *)md;
+ ColorGpencilModifierData *tgmd = (ColorGpencilModifierData *)target;
+
+ if (tgmd->curve_intensity != NULL) {
+ BKE_curvemapping_free(tgmd->curve_intensity);
+ tgmd->curve_intensity = NULL;
+ }
+
BKE_gpencil_modifier_copyData_generic(md, target);
+
+ tgmd->curve_intensity = BKE_curvemapping_copy(gmd->curve_intensity);
}
/* color correction strokes */
@@ -72,6 +87,7 @@ static void deformStroke(GpencilModifierData *md,
ColorGpencilModifierData *mmd = (ColorGpencilModifierData *)md;
float hsv[3], factor[3];
+ const bool use_curve = (mmd->flag & GP_COLOR_CUSTOM_CURVE) != 0 && mmd->curve_intensity;
if (!is_stroke_affected_by_modifier(ob,
mmd->layername,
@@ -89,60 +105,76 @@ static void deformStroke(GpencilModifierData *md,
}
copy_v3_v3(factor, mmd->hsv);
- /* keep initial values unchanged, subtracting the default values. */
- factor[0] -= 0.5f;
- factor[1] -= 1.0f;
- factor[2] -= 1.0f;
+ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
- if (mmd->modify_color != GP_MODIFY_COLOR_FILL) {
- rgb_to_hsv_v(gps->runtime.tmp_stroke_rgba, hsv);
- add_v3_v3(hsv, factor);
- CLAMP3(hsv, 0.0f, 1.0f);
- hsv_to_rgb_v(hsv, gps->runtime.tmp_stroke_rgba);
+ /* Apply to Vertex Color. */
+ /* Fill */
+ if (mmd->modify_color != GP_MODIFY_COLOR_STROKE) {
+ /* If not using Vertex Color, use the material color. */
+ if ((gp_style != NULL) && (gps->vert_color_fill[3] == 0.0f) &&
+ (gp_style->fill_rgba[3] > 0.0f)) {
+ copy_v4_v4(gps->vert_color_fill, gp_style->fill_rgba);
+ gps->vert_color_fill[3] = 1.0f;
+ }
+
+ rgb_to_hsv_v(gps->vert_color_fill, hsv);
+ hsv[0] = fractf(hsv[0] + factor[0] + 0.5f);
+ hsv[1] = clamp_f(hsv[1] * factor[1], 0.0f, 1.0f);
+ hsv[2] = hsv[2] * factor[2];
+ hsv_to_rgb_v(hsv, gps->vert_color_fill);
}
- if (mmd->modify_color != GP_MODIFY_COLOR_STROKE) {
- rgb_to_hsv_v(gps->runtime.tmp_fill_rgba, hsv);
- add_v3_v3(hsv, factor);
- CLAMP3(hsv, 0.0f, 1.0f);
- hsv_to_rgb_v(hsv, gps->runtime.tmp_fill_rgba);
+ /* Stroke */
+ if (mmd->modify_color != GP_MODIFY_COLOR_FILL) {
+
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ /* If not using Vertex Color, use the material color. */
+ if ((gp_style != NULL) && (pt->vert_color[3] == 0.0f) && (gp_style->stroke_rgba[3] > 0.0f)) {
+ copy_v4_v4(pt->vert_color, gp_style->stroke_rgba);
+ pt->vert_color[3] = 1.0f;
+ }
+
+ /* Custom curve to modulate value. */
+ float factor_value[3];
+ copy_v3_v3(factor_value, factor);
+ if (use_curve) {
+ float value = (float)i / (gps->totpoints - 1);
+ float mixfac = BKE_curvemapping_evaluateF(mmd->curve_intensity, 0, value);
+ mul_v3_fl(factor_value, mixfac);
+ }
+
+ rgb_to_hsv_v(pt->vert_color, hsv);
+ hsv[0] = fractf(hsv[0] + factor_value[0] + 0.5f);
+ hsv[1] = clamp_f(hsv[1] * factor_value[1], 0.0f, 1.0f);
+ hsv[2] = hsv[2] * factor_value[2];
+ hsv_to_rgb_v(hsv, pt->vert_color);
+ }
}
}
-static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData *md, Object *ob)
+static void bakeModifier(Main *UNUSED(bmain),
+ Depsgraph *depsgraph,
+ GpencilModifierData *md,
+ Object *ob)
{
- ColorGpencilModifierData *mmd = (ColorGpencilModifierData *)md;
bGPdata *gpd = ob->data;
- GHash *gh_color = BLI_ghash_str_new("GP_Color modifier");
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
-
- Material *mat = BKE_gpencil_material(ob, gps->mat_nr + 1);
- if (mat == NULL) {
- continue;
- }
- MaterialGPencilStyle *gp_style = mat->gp_style;
- /* skip stroke if it doesn't have color info */
- if (ELEM(NULL, gp_style)) {
- continue;
- }
-
- copy_v4_v4(gps->runtime.tmp_stroke_rgba, gp_style->stroke_rgba);
- copy_v4_v4(gps->runtime.tmp_fill_rgba, gp_style->fill_rgba);
-
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
deformStroke(md, depsgraph, ob, gpl, gpf, gps);
-
- gpencil_apply_modifier_material(
- bmain, ob, mat, gh_color, gps, (bool)(mmd->flag & GP_COLOR_CREATE_COLORS));
}
}
}
- /* free hash buffers */
- if (gh_color) {
- BLI_ghash_free(gh_color, NULL, NULL);
- gh_color = NULL;
+}
+
+static void freeData(GpencilModifierData *md)
+{
+ ColorGpencilModifierData *gpmd = (ColorGpencilModifierData *)md;
+
+ if (gpmd->curve_intensity) {
+ BKE_curvemapping_free(gpmd->curve_intensity);
}
}
@@ -161,7 +193,7 @@ GpencilModifierTypeInfo modifierType_Gpencil_Color = {
/* remapTime */ NULL,
/* initData */ initData,
- /* freeData */ NULL,
+ /* freeData */ freeData,
/* isDisabled */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c
index ae51bad3ca3..41380ec4c68 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c
@@ -23,6 +23,7 @@
#include <stdio.h>
+#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "BLI_math.h"
@@ -263,6 +264,8 @@ static void deformStroke(GpencilModifierData *md,
}
gp_hook_co_apply(&tData, weight, pt);
}
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
}
/* FIXME: Ideally we be doing this on a copy of the main depsgraph
@@ -279,8 +282,8 @@ static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData
return;
}
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
/* apply hook effects on this frame
* NOTE: this assumes that we don't want hook animation on non-keyframed frames
*/
@@ -288,7 +291,7 @@ static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData
BKE_scene_graph_update_for_newframe(depsgraph, bmain);
/* compute hook effects on this frame */
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
deformStroke(md, depsgraph, ob, gpl, gpf, gps);
}
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c b/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c
index dba554fec36..d87f3a8a199 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c
@@ -23,6 +23,7 @@
#include <stdio.h>
+#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "DNA_meshdata_types.h"
@@ -108,6 +109,8 @@ static void deformStroke(GpencilModifierData *md,
}
calc_latt_deform((struct LatticeDeformData *)mmd->cache_data, &pt->x, mmd->strength * weight);
}
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
}
/* FIXME: Ideally we be doing this on a copy of the main depsgraph
@@ -125,8 +128,8 @@ static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData
return;
}
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
/* apply lattice effects on this frame
* NOTE: this assumes that we don't want lattice animation on non-keyframed frames
*/
@@ -137,7 +140,7 @@ static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData
BKE_gpencil_lattice_init(ob);
/* compute lattice effects on this frame */
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
deformStroke(md, depsgraph, ob, gpl, gpf, gps);
}
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c
index 42d45512dc5..0f9b1034352 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c
@@ -113,12 +113,7 @@ static void update_position(Object *ob, MirrorGpencilModifierData *mmd, bGPDstro
}
}
-/* Generic "generateStrokes" callback */
-static void generateStrokes(GpencilModifierData *md,
- Depsgraph *UNUSED(depsgraph),
- Object *ob,
- bGPDlayer *gpl,
- bGPDframe *gpf)
+static void generate_geometry(GpencilModifierData *md, Object *ob, bGPDlayer *gpl, bGPDframe *gpf)
{
MirrorGpencilModifierData *mmd = (MirrorGpencilModifierData *)md;
bGPDstroke *gps, *gps_new = NULL;
@@ -145,7 +140,7 @@ static void generateStrokes(GpencilModifierData *md,
mmd->flag & GP_MIRROR_INVERT_PASS,
mmd->flag & GP_MIRROR_INVERT_LAYERPASS,
mmd->flag & GP_MIRROR_INVERT_MATERIAL)) {
- gps_new = BKE_gpencil_stroke_duplicate(gps);
+ gps_new = BKE_gpencil_stroke_duplicate(gps, true);
update_position(ob, mmd, gps_new, xi);
BLI_addtail(&gpf->strokes, gps_new);
}
@@ -154,20 +149,35 @@ static void generateStrokes(GpencilModifierData *md,
}
}
+/* Generic "generateStrokes" callback */
+static void generateStrokes(GpencilModifierData *md, Depsgraph *depsgraph, Object *ob)
+{
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ bGPdata *gpd = (bGPdata *)ob->data;
+
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ bGPDframe *gpf = BKE_gpencil_frame_retime_get(depsgraph, scene, ob, gpl);
+ if (gpf == NULL) {
+ continue;
+ }
+ generate_geometry(md, ob, gpl, gpf);
+ }
+}
+
static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData *md, Object *ob)
{
Scene *scene = DEG_get_evaluated_scene(depsgraph);
bGPdata *gpd = ob->data;
int oldframe = (int)DEG_get_ctime(depsgraph);
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
/* apply mirror effects on this frame */
CFRA = gpf->framenum;
BKE_scene_graph_update_for_newframe(depsgraph, bmain);
/* compute mirror effects on this frame */
- generateStrokes(md, depsgraph, ob, gpl, gpf);
+ generate_geometry(md, ob, gpl, gpf);
}
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c
index 919dbf91862..16b0c4a5e38 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c
@@ -66,7 +66,10 @@ static void initData(GpencilModifierData *md)
MultiplyGpencilModifierData *mmd = (MultiplyGpencilModifierData *)md;
mmd->duplications = 3;
mmd->distance = 0.1f;
- mmd->split_angle = 1.0f;
+ mmd->split_angle = DEG2RADF(1.0f);
+ mmd->fading_center = 0.5f;
+ mmd->fading_thickness = 0.5f;
+ mmd->fading_opacity = 0.5f;
}
static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
@@ -74,60 +77,39 @@ static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
BKE_gpencil_modifier_copyData_generic(md, target);
}
-static void splitStroke(bGPDframe *gpf, bGPDstroke *gps, float split_angle)
-{
- bGPDspoint *pt = gps->points;
- bGPDstroke *new_gps = gps;
- int i;
- volatile float angle;
-
- if (split_angle <= FLT_EPSILON) {
- return;
- }
-
- for (i = 1; i < new_gps->totpoints - 1; i++) {
- angle = angle_v3v3v3(&pt[i - 1].x, &pt[i].x, &pt[i + 1].x);
- if (angle < split_angle) {
- if (BKE_gpencil_split_stroke(gpf, new_gps, i, &new_gps)) {
- pt = new_gps->points;
- i = 0;
- continue; /* then i == 1 again */
- }
- }
- }
-}
-
static void minter_v3_v3v3v3_ref(
- float *result, float *left, float *middle, float *right, float *stroke_normal)
+ float *result, float *prev, float *curr, float *next, float *stroke_normal)
{
- float left_arm[3], right_arm[3], inter1[3], inter2[3];
+ float vec[3], inter1[3], inter2[3];
+ ARRAY_SET_ITEMS(inter1, 0.0f, 0.0f, 0.0f);
+ ARRAY_SET_ITEMS(inter2, 0.0f, 0.0f, 0.0f);
+
float minter[3];
- if (left) {
- sub_v3_v3v3(left_arm, middle, left);
- cross_v3_v3v3(inter1, stroke_normal, left_arm);
+ if (prev) {
+ sub_v3_v3v3(vec, curr, prev);
+ cross_v3_v3v3(inter1, stroke_normal, vec);
}
- if (right) {
- sub_v3_v3v3(right_arm, right, middle);
- cross_v3_v3v3(inter2, stroke_normal, right_arm);
+ if (next) {
+ sub_v3_v3v3(vec, next, curr);
+ cross_v3_v3v3(inter2, stroke_normal, vec);
}
- if (!left) {
+ if (!prev) {
normalize_v3(inter2);
copy_v3_v3(result, inter2);
return;
}
-
- if (!right) {
+ if (!next) {
normalize_v3(inter1);
copy_v3_v3(result, inter1);
return;
}
-
interp_v3_v3v3(minter, inter1, inter2, 0.5);
normalize_v3(minter);
copy_v3_v3(result, minter);
}
-static void duplicateStroke(bGPDstroke *gps,
+static void duplicateStroke(Object *ob,
+ bGPDstroke *gps,
int count,
float dist,
float offset,
@@ -138,14 +120,15 @@ static void duplicateStroke(bGPDstroke *gps,
float fading_opacity)
{
int i;
- bGPDstroke *new_gps;
+ bGPDstroke *new_gps = NULL;
float stroke_normal[3];
- float minter[3];
bGPDspoint *pt;
- float offset_factor;
float thickness_factor;
float opacity_factor;
+ /* Apply object scale to offset distance. */
+ offset *= mat4_to_scale(ob->obmat);
+
BKE_gpencil_stroke_normal(gps, stroke_normal);
if (len_v3(stroke_normal) < FLT_EPSILON) {
add_v3_fl(stroke_normal, 1);
@@ -160,6 +143,7 @@ static void duplicateStroke(bGPDstroke *gps,
pt = gps->points;
for (int j = 0; j < gps->totpoints; j++) {
+ float minter[3];
if (j == 0) {
minter_v3_v3v3v3_ref(minter, NULL, &pt[j].x, &pt[j + 1].x, stroke_normal);
}
@@ -174,11 +158,11 @@ static void duplicateStroke(bGPDstroke *gps,
sub_v3_v3v3(&t2_array[j * 3], &pt[j].x, minter);
}
- /* This ensures the original stroke is the last one to be processed. */
+ /* This ensures the original stroke is the last one
+ * to be processed, since we duplicate its data. */
for (i = count - 1; i >= 0; i--) {
if (i != 0) {
- new_gps = BKE_gpencil_stroke_duplicate(gps);
- new_gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+ new_gps = BKE_gpencil_stroke_duplicate(gps, true);
BLI_addtail(results, new_gps);
}
else {
@@ -187,34 +171,26 @@ static void duplicateStroke(bGPDstroke *gps,
pt = new_gps->points;
- if (count == 1) {
- offset_factor = 0;
- }
- else {
- offset_factor = (float)i / (float)(count - 1);
- }
+ float offset_fac = (count == 1) ? 0.5f : (i / (float)(count - 1));
if (fading) {
- thickness_factor = (offset_factor > fading_center) ?
- (interpf(1 - fading_thickness, 1.0f, offset_factor - fading_center)) :
- (interpf(
- 1.0f, 1 - fading_thickness, offset_factor - fading_center + 1));
- opacity_factor = (offset_factor > fading_center) ?
- (interpf(1 - fading_opacity, 1.0f, offset_factor - fading_center)) :
- (interpf(1.0f, 1 - fading_opacity, offset_factor - fading_center + 1));
+ thickness_factor = interpf(1.0f - fading_thickness, 1.0f, fabsf(offset_fac - fading_center));
+ opacity_factor = interpf(1.0f - fading_opacity, 1.0f, fabsf(offset_fac - fading_center));
}
for (int j = 0; j < new_gps->totpoints; j++) {
- interp_v3_v3v3(&pt[j].x,
- &t1_array[j * 3],
- &t2_array[j * 3],
- interpf(1 + offset, offset, offset_factor));
+ float fac = interpf(1 + offset, offset, offset_fac);
+ interp_v3_v3v3(&pt[j].x, &t1_array[j * 3], &t2_array[j * 3], fac);
if (fading) {
pt[j].pressure = gps->points[j].pressure * thickness_factor;
pt[j].strength = gps->points[j].strength * opacity_factor;
}
}
}
+ /* Calc geometry data. */
+ if (new_gps != NULL) {
+ BKE_gpencil_stroke_geometry_update(new_gps);
+ }
MEM_freeN(t1_array);
MEM_freeN(t2_array);
}
@@ -224,11 +200,10 @@ static void bakeModifier(Main *UNUSED(bmain),
GpencilModifierData *md,
Object *ob)
{
-
bGPdata *gpd = ob->data;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
ListBase duplicates = {0};
MultiplyGpencilModifierData *mmd = (MultiplyGpencilModifierData *)md;
bGPDstroke *gps;
@@ -247,11 +222,9 @@ static void bakeModifier(Main *UNUSED(bmain),
mmd->flag & GP_MIRROR_INVERT_MATERIAL)) {
continue;
}
- if (mmd->flags & GP_MULTIPLY_ENABLE_ANGLE_SPLITTING) {
- splitStroke(gpf, gps, mmd->split_angle);
- }
if (mmd->duplications > 0) {
- duplicateStroke(gps,
+ duplicateStroke(ob,
+ gps,
mmd->duplications,
mmd->distance,
mmd->offset,
@@ -262,23 +235,15 @@ static void bakeModifier(Main *UNUSED(bmain),
mmd->fading_opacity);
}
}
- if (duplicates.first) {
- ((bGPDstroke *)gpf->strokes.last)->next = duplicates.first;
- ((bGPDstroke *)duplicates.first)->prev = gpf->strokes.last;
- gpf->strokes.last = duplicates.first;
+ if (!BLI_listbase_is_empty(&duplicates)) {
+ BLI_movelisttolist(&gpf->strokes, &duplicates);
}
}
}
}
/* -------------------------------- */
-
-/* Generic "generateStrokes" callback */
-static void generateStrokes(GpencilModifierData *md,
- Depsgraph *UNUSED(depsgraph),
- Object *ob,
- bGPDlayer *gpl,
- bGPDframe *gpf)
+static void generate_geometry(GpencilModifierData *md, Object *ob, bGPDlayer *gpl, bGPDframe *gpf)
{
MultiplyGpencilModifierData *mmd = (MultiplyGpencilModifierData *)md;
bGPDstroke *gps;
@@ -298,11 +263,9 @@ static void generateStrokes(GpencilModifierData *md,
mmd->flag & GP_MIRROR_INVERT_MATERIAL)) {
continue;
}
- if (mmd->flags & GP_MULTIPLY_ENABLE_ANGLE_SPLITTING) {
- splitStroke(gpf, gps, mmd->split_angle);
- }
if (mmd->duplications > 0) {
- duplicateStroke(gps,
+ duplicateStroke(ob,
+ gps,
mmd->duplications,
mmd->distance,
mmd->offset,
@@ -313,10 +276,23 @@ static void generateStrokes(GpencilModifierData *md,
mmd->fading_opacity);
}
}
- if (duplicates.first) {
- ((bGPDstroke *)gpf->strokes.last)->next = duplicates.first;
- ((bGPDstroke *)duplicates.first)->prev = gpf->strokes.last;
- gpf->strokes.last = duplicates.first;
+ if (!BLI_listbase_is_empty(&duplicates)) {
+ BLI_movelisttolist(&gpf->strokes, &duplicates);
+ }
+}
+
+/* Generic "generateStrokes" callback */
+static void generateStrokes(GpencilModifierData *md, Depsgraph *depsgraph, Object *ob)
+{
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ bGPdata *gpd = (bGPdata *)ob->data;
+
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ bGPDframe *gpf = BKE_gpencil_frame_retime_get(depsgraph, scene, ob, gpl);
+ if (gpf == NULL) {
+ continue;
+ }
+ generate_geometry(md, ob, gpl, gpf);
}
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c
index 157bd536609..9b3d37bf11f 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c
@@ -23,18 +23,23 @@
#include <stdio.h>
+#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "BLI_math_vector.h"
+#include "BLI_ghash.h"
#include "BLI_hash.h"
#include "BLI_rand.h"
+#include "MEM_guardedalloc.h"
+
#include "DNA_meshdata_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_gpencil_modifier_types.h"
+#include "BKE_colortools.h"
#include "BKE_deform.h"
#include "BKE_gpencil.h"
#include "BKE_gpencil_modifier.h"
@@ -57,13 +62,38 @@ static void initData(GpencilModifierData *md)
gpmd->layername[0] = '\0';
gpmd->materialname[0] = '\0';
gpmd->vgname[0] = '\0';
- gpmd->step = 1;
- gpmd->seed = 0;
+ gpmd->step = 4;
+ gpmd->seed = 1;
+ gpmd->curve_intensity = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ if (gpmd->curve_intensity) {
+ CurveMapping *curve = gpmd->curve_intensity;
+ BKE_curvemap_reset(curve->cm, &curve->clipr, CURVE_PRESET_BELL, CURVEMAP_SLOPE_POSITIVE);
+ BKE_curvemapping_initialize(curve);
+ }
+}
+
+static void freeData(GpencilModifierData *md)
+{
+ NoiseGpencilModifierData *gpmd = (NoiseGpencilModifierData *)md;
+
+ if (gpmd->curve_intensity) {
+ BKE_curvemapping_free(gpmd->curve_intensity);
+ }
}
static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
{
+ NoiseGpencilModifierData *gmd = (NoiseGpencilModifierData *)md;
+ NoiseGpencilModifierData *tgmd = (NoiseGpencilModifierData *)target;
+
+ if (tgmd->curve_intensity != NULL) {
+ BKE_curvemapping_free(tgmd->curve_intensity);
+ tgmd->curve_intensity = NULL;
+ }
+
BKE_gpencil_modifier_copyData_generic(md, target);
+
+ tgmd->curve_intensity = BKE_curvemapping_copy(gmd->curve_intensity);
}
static bool dependsOnTime(GpencilModifierData *md)
@@ -72,24 +102,36 @@ static bool dependsOnTime(GpencilModifierData *md)
return (mmd->flag & GP_NOISE_USE_RANDOM) != 0;
}
+static float *noise_table(int len, int seed)
+{
+ float *table = MEM_callocN(sizeof(float) * len, __func__);
+ for (int i = 0; i < len; i++) {
+ table[i] = BLI_hash_int_01(BLI_hash_int_2d(seed, i + 1));
+ }
+ return table;
+}
+
+BLI_INLINE float table_sample(float *table, float x)
+{
+ return interpf(table[(int)ceilf(x)], table[(int)floor(x)], fractf(x));
+}
+
/* aply noise effect based on stroke direction */
static void deformStroke(GpencilModifierData *md,
Depsgraph *depsgraph,
Object *ob,
bGPDlayer *gpl,
- bGPDframe *UNUSED(gpf),
+ bGPDframe *gpf,
bGPDstroke *gps)
{
NoiseGpencilModifierData *mmd = (NoiseGpencilModifierData *)md;
- bGPDspoint *pt0, *pt1;
MDeformVert *dvert = NULL;
- float shift, vran, vdir;
+ /* Noise value in range [-1..1] */
float normal[3];
float vec1[3], vec2[3];
- int sc_frame = 0;
- int stroke_seed = 0;
const int def_nr = BKE_object_defgroup_name_index(ob, mmd->vgname);
- const float unit_v3[3] = {1.0f, 1.0f, 1.0f};
+ const bool invert_group = (mmd->flag & GP_NOISE_INVERT_VGROUP) != 0;
+ const bool use_curve = (mmd->flag & GP_NOISE_CUSTOM_CURVE) != 0 && mmd->curve_intensity;
if (!is_stroke_affected_by_modifier(ob,
mmd->layername,
@@ -106,134 +148,99 @@ static void deformStroke(GpencilModifierData *md,
return;
}
- sc_frame = (int)DEG_get_ctime(depsgraph);
+ int seed = mmd->seed;
+ /* FIXME(fclem): This is really slow. We should get the stroke index in another way. */
+ int stroke_seed = BLI_findindex(&gpf->strokes, gps);
+ seed += stroke_seed;
- zero_v3(vec2);
+ /* Make sure different modifiers get different seeds. */
+ seed += BLI_hash_string(ob->id.name + 2);
+ seed += BLI_hash_string(md->name);
+
+ if (mmd->flag & GP_NOISE_USE_RANDOM) {
+ seed += ((int)DEG_get_ctime(depsgraph)) / mmd->step;
+ }
+
+ /* Sanitize as it can create out of bound reads. */
+ float noise_scale = clamp_f(mmd->noise_scale, 0.0f, 1.0f);
+
+ int len = ceilf(gps->totpoints * noise_scale) + 1;
+ float *noise_table_position = (mmd->factor > 0.0f) ? noise_table(len, seed + 2) : NULL;
+ float *noise_table_strength = (mmd->factor_strength > 0.0f) ? noise_table(len, seed + 3) : NULL;
+ float *noise_table_thickness = (mmd->factor_thickness > 0.0f) ? noise_table(len, seed) : NULL;
+ float *noise_table_uvs = (mmd->factor_uvs > 0.0f) ? noise_table(len, seed + 4) : NULL;
/* calculate stroke normal*/
if (gps->totpoints > 2) {
BKE_gpencil_stroke_normal(gps, normal);
}
else {
- copy_v3_v3(normal, unit_v3);
+ copy_v3_fl(normal, 1.0f);
}
/* move points */
for (int i = 0; i < gps->totpoints; i++) {
- if (((i == 0) || (i == gps->totpoints - 1)) && ((mmd->flag & GP_NOISE_MOVE_EXTREME) == 0)) {
- continue;
- }
-
- /* first point is special */
- if (i == 0) {
- if (gps->dvert) {
- dvert = &gps->dvert[0];
- }
- pt0 = (gps->totpoints > 1) ? &gps->points[1] : &gps->points[0];
- pt1 = &gps->points[0];
- }
- else {
- int prev_idx = i - 1;
- CLAMP_MIN(prev_idx, 0);
- if (gps->dvert) {
- dvert = &gps->dvert[prev_idx];
- }
- pt0 = &gps->points[prev_idx];
- pt1 = &gps->points[i];
- }
-
+ bGPDspoint *pt = &gps->points[i];
/* verify vertex group */
- const float weight = get_modifier_point_weight(
- dvert, (mmd->flag & GP_NOISE_INVERT_VGROUP) != 0, def_nr);
+ dvert = &gps->dvert[i];
+ float weight = get_modifier_point_weight(dvert, invert_group, def_nr);
if (weight < 0.0f) {
continue;
}
- /* initial vector (p0 -> p1) */
- if (i == 0) {
- sub_v3_v3v3(vec1, &pt0->x, &pt1->x);
- }
- else {
- sub_v3_v3v3(vec1, &pt1->x, &pt0->x);
+ if (use_curve) {
+ float value = (float)i / (gps->totpoints - 1);
+ weight *= BKE_curvemapping_evaluateF(mmd->curve_intensity, 0, value);
}
- vran = len_v3(vec1);
- /* Vector orthogonal to normal. */
- cross_v3_v3v3(vec2, vec1, normal);
- normalize_v3(vec2);
- /* Use random noise */
- if (mmd->flag & GP_NOISE_USE_RANDOM) {
- stroke_seed = BLI_hash_int_2d((sc_frame / mmd->step) + gps->totpoints, mmd->seed + 1);
- vran = BLI_hash_frand(stroke_seed);
- if (mmd->flag & GP_NOISE_FULL_STROKE) {
- vdir = BLI_hash_frand(stroke_seed + 3);
- }
- else {
- int f = (BLI_hash_frand(stroke_seed + 3) * 10.0f) + i;
- vdir = f % 2;
+
+ if (mmd->factor > 0.0f) {
+ /* Offset point randomly around the bi-normal vector. */
+ if (gps->totpoints == 1) {
+ copy_v3_fl3(vec1, 1.0f, 0.0f, 0.0f);
}
- }
- else {
- vran = 1.0f;
- if (mmd->flag & GP_NOISE_FULL_STROKE) {
- vdir = gps->totpoints % 2;
+ else if (i != gps->totpoints - 1) {
+ /* Initial vector (p1 -> p0). */
+ sub_v3_v3v3(vec1, &gps->points[i].x, &gps->points[i + 1].x);
+ /* if vec2 is zero, set to something */
+ if (len_squared_v3(vec1) < 1e-8f) {
+ copy_v3_fl3(vec1, 1.0f, 0.0f, 0.0f);
+ }
}
else {
- vdir = i % 2;
+ /* Last point reuse the penultimate normal (still stored in vec1)
+ * because the previous point is already modified. */
}
- }
+ /* Vector orthogonal to normal. */
+ cross_v3_v3v3(vec2, vec1, normal);
+ normalize_v3(vec2);
- /* if vec2 is zero, set to something */
- if (gps->totpoints < 3) {
- if ((vec2[0] == 0.0f) && (vec2[1] == 0.0f) && (vec2[2] == 0.0f)) {
- copy_v3_v3(vec2, unit_v3);
- }
+ float noise = table_sample(noise_table_position, i * noise_scale);
+ madd_v3_v3fl(&pt->x, vec2, (noise * 2.0f - 1.0f) * weight * mmd->factor * 0.1f);
}
- /* apply randomness to location of the point */
- if (mmd->flag & GP_NOISE_MOD_LOCATION) {
- /* factor is too sensitive, so need divide */
- shift = ((vran * mmd->factor) / 1000.0f) * weight;
- if (vdir > 0.5f) {
- mul_v3_fl(vec2, shift);
- }
- else {
- mul_v3_fl(vec2, shift * -1.0f);
- }
- add_v3_v3(&pt1->x, vec2);
+ if (mmd->factor_thickness > 0.0f) {
+ float noise = table_sample(noise_table_thickness, i * noise_scale);
+ pt->pressure *= max_ff(1.0f + (noise * 2.0f - 1.0f) * weight * mmd->factor_thickness, 0.0f);
+ CLAMP_MIN(pt->pressure, GPENCIL_STRENGTH_MIN);
}
- /* apply randomness to thickness */
- if (mmd->flag & GP_NOISE_MOD_THICKNESS) {
- if (vdir > 0.5f) {
- pt1->pressure -= pt1->pressure * vran * mmd->factor * weight;
- }
- else {
- pt1->pressure += pt1->pressure * vran * mmd->factor * weight;
- }
- CLAMP_MIN(pt1->pressure, GPENCIL_STRENGTH_MIN);
+ if (mmd->factor_strength > 0.0f) {
+ float noise = table_sample(noise_table_strength, i * noise_scale);
+ pt->strength *= max_ff(1.0f - noise * weight * mmd->factor_strength, 0.0f);
+ CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
}
- /* apply randomness to color strength */
- if (mmd->flag & GP_NOISE_MOD_STRENGTH) {
- if (vdir > 0.5f) {
- pt1->strength -= pt1->strength * vran * mmd->factor * weight;
- }
- else {
- pt1->strength += pt1->strength * vran * mmd->factor * weight;
- }
- CLAMP_MIN(pt1->strength, GPENCIL_STRENGTH_MIN);
- }
- /* apply randomness to uv rotation */
- if (mmd->flag & GP_NOISE_MOD_UV) {
- if (vdir > 0.5f) {
- pt1->uv_rot -= pt1->uv_rot * vran * mmd->factor * weight;
- }
- else {
- pt1->uv_rot += pt1->uv_rot * vran * mmd->factor * weight;
- }
- CLAMP(pt1->uv_rot, -M_PI_2, M_PI_2);
+ if (mmd->factor_uvs > 0.0f) {
+ float noise = table_sample(noise_table_uvs, i * noise_scale);
+ pt->uv_rot += (noise * 2.0f - 1.0f) * weight * mmd->factor_uvs * M_PI_2;
+ CLAMP(pt->uv_rot, -M_PI_2, M_PI_2);
}
}
+
+ MEM_SAFE_FREE(noise_table_position);
+ MEM_SAFE_FREE(noise_table_strength);
+ MEM_SAFE_FREE(noise_table_thickness);
+ MEM_SAFE_FREE(noise_table_uvs);
}
static void bakeModifier(struct Main *UNUSED(bmain),
@@ -243,9 +250,9 @@ static void bakeModifier(struct Main *UNUSED(bmain),
{
bGPdata *gpd = ob->data;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
deformStroke(md, depsgraph, ob, gpl, gpf, gps);
}
}
@@ -267,7 +274,7 @@ GpencilModifierTypeInfo modifierType_Gpencil_Noise = {
/* remapTime */ NULL,
/* initData */ initData,
- /* freeData */ NULL,
+ /* freeData */ freeData,
/* isDisabled */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ dependsOnTime,
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c
index 0979a2d90c9..5a9a1b68361 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c
@@ -23,6 +23,7 @@
#include <stdio.h>
+#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "BLI_math.h"
@@ -108,6 +109,8 @@ static void deformStroke(GpencilModifierData *md,
mul_m4_v3(mat, &pt->x);
}
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
}
static void bakeModifier(struct Main *UNUSED(bmain),
@@ -117,9 +120,9 @@ static void bakeModifier(struct Main *UNUSED(bmain),
{
bGPdata *gpd = ob->data;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
deformStroke(md, depsgraph, ob, gpl, gpf, gps);
}
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c
index 9647489358e..4b04e349067 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c
@@ -26,7 +26,6 @@
#include "BLI_utildefines.h"
#include "BLI_blenlib.h"
-#include "BLI_ghash.h"
#include "BLI_math_vector.h"
#include "DNA_meshdata_types.h"
@@ -35,6 +34,7 @@
#include "DNA_gpencil_types.h"
#include "DNA_gpencil_modifier_types.h"
+#include "BKE_colortools.h"
#include "BKE_deform.h"
#include "BKE_material.h"
#include "BKE_gpencil.h"
@@ -54,13 +54,27 @@ static void initData(GpencilModifierData *md)
gpmd->layername[0] = '\0';
gpmd->materialname[0] = '\0';
gpmd->vgname[0] = '\0';
- gpmd->flag |= GP_OPACITY_CREATE_COLORS;
gpmd->modify_color = GP_MODIFY_COLOR_BOTH;
+ gpmd->curve_intensity = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ if (gpmd->curve_intensity) {
+ CurveMapping *curve = gpmd->curve_intensity;
+ BKE_curvemapping_initialize(curve);
+ }
}
static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
{
+ OpacityGpencilModifierData *gmd = (OpacityGpencilModifierData *)md;
+ OpacityGpencilModifierData *tgmd = (OpacityGpencilModifierData *)target;
+
+ if (tgmd->curve_intensity != NULL) {
+ BKE_curvemapping_free(tgmd->curve_intensity);
+ tgmd->curve_intensity = NULL;
+ }
+
BKE_gpencil_modifier_copyData_generic(md, target);
+
+ tgmd->curve_intensity = BKE_curvemapping_copy(gmd->curve_intensity);
}
/* opacity strokes */
@@ -73,6 +87,7 @@ static void deformStroke(GpencilModifierData *md,
{
OpacityGpencilModifierData *mmd = (OpacityGpencilModifierData *)md;
const int def_nr = BKE_object_defgroup_name_index(ob, mmd->vgname);
+ const bool use_curve = (mmd->flag & GP_OPACITY_CUSTOM_CURVE) != 0 && mmd->curve_intensity;
if (!is_stroke_affected_by_modifier(ob,
mmd->layername,
@@ -89,98 +104,79 @@ static void deformStroke(GpencilModifierData *md,
return;
}
- if (mmd->opacity_mode == GP_OPACITY_MODE_MATERIAL) {
- if (mmd->modify_color != GP_MODIFY_COLOR_FILL) {
- gps->runtime.tmp_stroke_rgba[3] *= mmd->factor;
- /* if factor is > 1, then force opacity */
- if (mmd->factor > 1.0f) {
- gps->runtime.tmp_stroke_rgba[3] += mmd->factor - 1.0f;
- }
- CLAMP(gps->runtime.tmp_stroke_rgba[3], 0.0f, 1.0f);
- }
-
- if (mmd->modify_color != GP_MODIFY_COLOR_STROKE) {
- gps->runtime.tmp_fill_rgba[3] *= mmd->factor;
- /* if factor is > 1, then force opacity */
- if (mmd->factor > 1.0f && gps->runtime.tmp_fill_rgba[3] > 1e-5) {
- gps->runtime.tmp_fill_rgba[3] += mmd->factor - 1.0f;
- }
- CLAMP(gps->runtime.tmp_fill_rgba[3], 0.0f, 1.0f);
- }
-
- /* if opacity > 1.0, affect the strength of the stroke */
- if (mmd->factor > 1.0f) {
- for (int i = 0; i < gps->totpoints; i++) {
- bGPDspoint *pt = &gps->points[i];
- pt->strength += mmd->factor - 1.0f;
- CLAMP(pt->strength, 0.0f, 1.0f);
- }
- }
- }
- /* Apply opacity by strength */
- else {
- for (int i = 0; i < gps->totpoints; i++) {
- bGPDspoint *pt = &gps->points[i];
- MDeformVert *dvert = gps->dvert != NULL ? &gps->dvert[i] : NULL;
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ MDeformVert *dvert = gps->dvert != NULL ? &gps->dvert[i] : NULL;
+ /* Stroke using strength. */
+ if (mmd->modify_color != GP_MODIFY_COLOR_FILL) {
/* verify vertex group */
float weight = get_modifier_point_weight(
dvert, (mmd->flag & GP_OPACITY_INVERT_VGROUP) != 0, def_nr);
if (weight < 0.0f) {
continue;
}
+ /* Custom curve to modulate value. */
+ float factor_curve = mmd->factor;
+ if (use_curve) {
+ float value = (float)i / (gps->totpoints - 1);
+ factor_curve *= BKE_curvemapping_evaluateF(mmd->curve_intensity, 0, value);
+ }
+
if (def_nr < 0) {
- pt->strength += mmd->factor - 1.0f;
+ if (mmd->flag & GP_OPACITY_NORMALIZE) {
+ pt->strength = factor_curve;
+ }
+ else {
+ pt->strength += factor_curve - 1.0f;
+ }
}
else {
/* High factor values, change weight too. */
- if ((mmd->factor > 1.0f) && (weight < 1.0f)) {
- weight += mmd->factor - 1.0f;
+ if ((factor_curve > 1.0f) && (weight < 1.0f)) {
+ weight += factor_curve - 1.0f;
CLAMP(weight, 0.0f, 1.0f);
}
- pt->strength += (mmd->factor - 1) * weight;
+ if (mmd->flag & GP_OPACITY_NORMALIZE) {
+ pt->strength = factor_curve;
+ }
+ else {
+ pt->strength += (factor_curve - 1) * weight;
+ }
}
+
CLAMP(pt->strength, 0.0f, 1.0f);
}
}
+
+ /* Fill using opacity factor. */
+ if (mmd->modify_color != GP_MODIFY_COLOR_STROKE) {
+ gps->fill_opacity_fac = mmd->factor;
+ CLAMP(gps->fill_opacity_fac, 0.0f, 1.0f);
+ }
}
-static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData *md, Object *ob)
+static void bakeModifier(Main *UNUSED(bmain),
+ Depsgraph *depsgraph,
+ GpencilModifierData *md,
+ Object *ob)
{
- OpacityGpencilModifierData *mmd = (OpacityGpencilModifierData *)md;
bGPdata *gpd = ob->data;
- GHash *gh_color = BLI_ghash_str_new("GP_Opacity modifier");
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
-
- Material *mat = BKE_gpencil_material(ob, gps->mat_nr + 1);
- if (mat == NULL) {
- continue;
- }
- MaterialGPencilStyle *gp_style = mat->gp_style;
- /* skip stroke if it doesn't have color info */
- if (ELEM(NULL, gp_style)) {
- continue;
- }
-
- copy_v4_v4(gps->runtime.tmp_stroke_rgba, gp_style->stroke_rgba);
- copy_v4_v4(gps->runtime.tmp_fill_rgba, gp_style->fill_rgba);
-
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
deformStroke(md, depsgraph, ob, gpl, gpf, gps);
-
- if (mmd->opacity_mode == GP_OPACITY_MODE_MATERIAL) {
- gpencil_apply_modifier_material(
- bmain, ob, mat, gh_color, gps, (bool)(mmd->flag & GP_OPACITY_CREATE_COLORS));
- }
}
}
}
- /* free hash buffers */
- if (gh_color) {
- BLI_ghash_free(gh_color, NULL, NULL);
- gh_color = NULL;
+}
+static void freeData(GpencilModifierData *md)
+{
+ OpacityGpencilModifierData *gpmd = (OpacityGpencilModifierData *)md;
+
+ if (gpmd->curve_intensity) {
+ BKE_curvemapping_free(gpmd->curve_intensity);
}
}
@@ -199,7 +195,7 @@ GpencilModifierTypeInfo modifierType_Gpencil_Opacity = {
/* remapTime */ NULL,
/* initData */ initData,
- /* freeData */ NULL,
+ /* freeData */ freeData,
/* isDisabled */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c
index 9594fc8581e..60e26407b63 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c
@@ -23,6 +23,7 @@
#include <stdio.h>
+#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "DNA_scene_types.h"
@@ -84,21 +85,21 @@ static void deformStroke(GpencilModifierData *md,
switch (mmd->mode) {
case GP_SIMPLIFY_FIXED: {
for (int i = 0; i < mmd->step; i++) {
- BKE_gpencil_simplify_fixed(gps);
+ BKE_gpencil_stroke_simplify_fixed(gps);
}
break;
}
case GP_SIMPLIFY_ADAPTIVE: {
/* simplify stroke using Ramer-Douglas-Peucker algorithm */
- BKE_gpencil_simplify_stroke(gps, mmd->factor);
+ BKE_gpencil_stroke_simplify_adaptive(gps, mmd->factor);
break;
}
case GP_SIMPLIFY_SAMPLE: {
- BKE_gpencil_sample_stroke(gps, mmd->length, false);
+ BKE_gpencil_stroke_sample(gps, mmd->length, false);
break;
}
case GP_SIMPLIFY_MERGE: {
- BKE_gpencil_merge_distance_stroke(gpf, gps, mmd->distance, true);
+ BKE_gpencil_stroke_merge_distance(gpf, gps, mmd->distance, true);
break;
}
default:
@@ -113,9 +114,9 @@ static void bakeModifier(struct Main *UNUSED(bmain),
{
bGPdata *gpd = ob->data;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
deformStroke(md, depsgraph, ob, gpl, gpf, gps);
}
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c
index b6b5bf05a9d..896333318aa 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c
@@ -23,6 +23,7 @@
#include <stdio.h>
+#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "DNA_meshdata_types.h"
@@ -30,6 +31,7 @@
#include "DNA_gpencil_types.h"
#include "DNA_gpencil_modifier_types.h"
+#include "BKE_colortools.h"
#include "BKE_deform.h"
#include "BKE_gpencil.h"
#include "BKE_gpencil_modifier.h"
@@ -49,11 +51,27 @@ static void initData(GpencilModifierData *md)
gpmd->materialname[0] = '\0';
gpmd->vgname[0] = '\0';
gpmd->step = 1;
+
+ gpmd->curve_intensity = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ if (gpmd->curve_intensity) {
+ CurveMapping *curve = gpmd->curve_intensity;
+ BKE_curvemapping_initialize(curve);
+ }
}
static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
{
+ SmoothGpencilModifierData *gmd = (SmoothGpencilModifierData *)md;
+ SmoothGpencilModifierData *tgmd = (SmoothGpencilModifierData *)target;
+
+ if (tgmd->curve_intensity != NULL) {
+ BKE_curvemapping_free(tgmd->curve_intensity);
+ tgmd->curve_intensity = NULL;
+ }
+
BKE_gpencil_modifier_copyData_generic(md, target);
+
+ tgmd->curve_intensity = BKE_curvemapping_copy(gmd->curve_intensity);
}
/* aply smooth effect based on stroke direction */
@@ -66,6 +84,7 @@ static void deformStroke(GpencilModifierData *md,
{
SmoothGpencilModifierData *mmd = (SmoothGpencilModifierData *)md;
const int def_nr = BKE_object_defgroup_name_index(ob, mmd->vgname);
+ const bool use_curve = (mmd->flag & GP_SMOOTH_CUSTOM_CURVE) != 0 && mmd->curve_intensity;
if (!is_stroke_affected_by_modifier(ob,
mmd->layername,
@@ -89,28 +108,34 @@ static void deformStroke(GpencilModifierData *md,
MDeformVert *dvert = gps->dvert != NULL ? &gps->dvert[i] : NULL;
/* verify vertex group */
- const float weight = get_modifier_point_weight(
+ float weight = get_modifier_point_weight(
dvert, (mmd->flag & GP_SMOOTH_INVERT_VGROUP) != 0, def_nr);
if (weight < 0.0f) {
continue;
}
+ /* Custom curve to modulate value. */
+ if (use_curve) {
+ float value = (float)i / (gps->totpoints - 1);
+ weight *= BKE_curvemapping_evaluateF(mmd->curve_intensity, 0, value);
+ }
+
const float val = mmd->factor * weight;
/* perform smoothing */
if (mmd->flag & GP_SMOOTH_MOD_LOCATION) {
- BKE_gpencil_smooth_stroke(gps, i, val);
+ BKE_gpencil_stroke_smooth(gps, i, val);
}
if (mmd->flag & GP_SMOOTH_MOD_STRENGTH) {
- BKE_gpencil_smooth_stroke_strength(gps, i, val);
+ BKE_gpencil_stroke_smooth_strength(gps, i, val);
}
if ((mmd->flag & GP_SMOOTH_MOD_THICKNESS) && (val > 0.0f)) {
/* thickness need to repeat process several times */
for (int r2 = 0; r2 < r * 10; r2++) {
- BKE_gpencil_smooth_stroke_thickness(gps, i, val);
+ BKE_gpencil_stroke_smooth_thickness(gps, i, val);
}
}
if (mmd->flag & GP_SMOOTH_MOD_UV) {
- BKE_gpencil_smooth_stroke_uv(gps, i, val);
+ BKE_gpencil_stroke_smooth_uv(gps, i, val);
}
}
}
@@ -124,15 +149,24 @@ static void bakeModifier(struct Main *UNUSED(bmain),
{
bGPdata *gpd = ob->data;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
deformStroke(md, depsgraph, ob, gpl, gpf, gps);
}
}
}
}
+static void freeData(GpencilModifierData *md)
+{
+ SmoothGpencilModifierData *gpmd = (SmoothGpencilModifierData *)md;
+
+ if (gpmd->curve_intensity) {
+ BKE_curvemapping_free(gpmd->curve_intensity);
+ }
+}
+
GpencilModifierTypeInfo modifierType_Gpencil_Smooth = {
/* name */ "Smooth",
/* structName */ "SmoothGpencilModifierData",
@@ -148,7 +182,7 @@ GpencilModifierTypeInfo modifierType_Gpencil_Smooth = {
/* remapTime */ NULL,
/* initData */ initData,
- /* freeData */ NULL,
+ /* freeData */ freeData,
/* isDisabled */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c
index 89d6565d0dd..25abf0b81eb 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c
@@ -25,6 +25,7 @@
#include "MEM_guardedalloc.h"
+#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "DNA_meshdata_types.h"
@@ -84,7 +85,7 @@ static void deformStroke(GpencilModifierData *md,
return;
}
- BKE_gpencil_subdivide(gps, mmd->level, mmd->flag);
+ BKE_gpencil_stroke_subdivide(gps, mmd->level, mmd->type);
}
static void bakeModifier(struct Main *UNUSED(bmain),
@@ -94,9 +95,9 @@ static void bakeModifier(struct Main *UNUSED(bmain),
{
bGPdata *gpd = ob->data;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
deformStroke(md, depsgraph, ob, gpl, gpf, gps);
}
}
@@ -104,7 +105,7 @@ static void bakeModifier(struct Main *UNUSED(bmain),
}
GpencilModifierTypeInfo modifierType_Gpencil_Subdiv = {
- /* name */ "Subdivision",
+ /* name */ "Subdivide",
/* structName */ "SubdivGpencilModifierData",
/* structSize */ sizeof(SubdivGpencilModifierData),
/* type */ eGpencilModifierTypeType_Gpencil,
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c
index 694b932a6bf..894dff46ac2 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c
@@ -23,6 +23,8 @@
#include <stdio.h>
+#include "BLI_listbase.h"
+#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "DNA_meshdata_types.h"
@@ -45,7 +47,8 @@ static void initData(GpencilModifierData *md)
{
ThickGpencilModifierData *gpmd = (ThickGpencilModifierData *)md;
gpmd->pass_index = 0;
- gpmd->thickness = 2;
+ gpmd->thickness_fac = 1.0f;
+ gpmd->thickness = 30;
gpmd->layername[0] = '\0';
gpmd->materialname[0] = '\0';
gpmd->vgname[0] = '\0';
@@ -105,70 +108,38 @@ static void deformStroke(GpencilModifierData *md,
return;
}
- /* Check to see if we normalize the whole stroke or only certain points along it. */
- bool gps_has_affected_points = false;
- bool gps_has_unaffected_points = false;
-
- if (mmd->flag & GP_THICK_NORMALIZE) {
- for (int i = 0; i < gps->totpoints; i++) {
- MDeformVert *dvert = gps->dvert != NULL ? &gps->dvert[i] : NULL;
- const float weight = get_modifier_point_weight(
- dvert, (mmd->flag & GP_THICK_INVERT_VGROUP) != 0, def_nr);
- if (weight < 0.0f) {
- gps_has_unaffected_points = true;
- }
- else {
- gps_has_affected_points = true;
- }
-
- /* If both checks are true, we have what we need so we can stop looking. */
- if (gps_has_affected_points && gps_has_unaffected_points) {
- break;
- }
- }
- }
-
- /* If we are normalizing and all points of the stroke are affected, it's safe to reset thickness
- */
- if (mmd->flag & GP_THICK_NORMALIZE && gps_has_affected_points && !gps_has_unaffected_points) {
- gps->thickness = mmd->thickness;
- }
- /* Without this check, modifier alters the thickness of strokes which have no points in scope */
+ float stroke_thickness_inv = 1.0f / max_ii(gps->thickness, 1);
for (int i = 0; i < gps->totpoints; i++) {
bGPDspoint *pt = &gps->points[i];
MDeformVert *dvert = gps->dvert != NULL ? &gps->dvert[i] : NULL;
- float curvef = 1.0f;
/* Verify point is part of vertex group. */
- const float weight = get_modifier_point_weight(
+ float weight = get_modifier_point_weight(
dvert, (mmd->flag & GP_THICK_INVERT_VGROUP) != 0, def_nr);
if (weight < 0.0f) {
continue;
}
+ float curvef = 1.0f;
+ if ((mmd->flag & GP_THICK_CUSTOM_CURVE) && (mmd->curve_thickness)) {
+ /* Normalize value to evaluate curve. */
+ float value = (float)i / (gps->totpoints - 1);
+ curvef = BKE_curvemapping_evaluateF(mmd->curve_thickness, 0, value);
+ }
+
+ float target;
if (mmd->flag & GP_THICK_NORMALIZE) {
- if (gps_has_unaffected_points) {
- /* Clamp value for very weird situations when stroke thickness can be zero. */
- CLAMP_MIN(gps->thickness, 1);
- /* Calculate pressure value to match the width of strokes with reset thickness and 1.0
- * pressure. */
- pt->pressure = (float)mmd->thickness / (float)gps->thickness;
- }
- else {
- /* Reset point pressure values so only stroke thickness counts. */
- pt->pressure = 1.0f;
- }
+ target = mmd->thickness * stroke_thickness_inv;
+ target *= curvef;
}
else {
- if ((mmd->flag & GP_THICK_CUSTOM_CURVE) && (mmd->curve_thickness)) {
- /* Normalize value to evaluate curve. */
- float value = (float)i / (gps->totpoints - 1);
- curvef = BKE_curvemapping_evaluateF(mmd->curve_thickness, 0, value);
- }
-
- pt->pressure += mmd->thickness * weight * curvef;
- CLAMP_MIN(pt->pressure, 0.1f);
+ target = pt->pressure * mmd->thickness_fac;
+ weight *= curvef;
}
+
+ pt->pressure = interpf(target, pt->pressure, weight);
+
+ CLAMP_MIN(pt->pressure, 0.1f);
}
}
@@ -179,9 +150,9 @@ static void bakeModifier(struct Main *UNUSED(bmain),
{
bGPdata *gpd = ob->data;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
deformStroke(md, depsgraph, ob, gpl, gpf, gps);
}
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c
index 8f3956276dd..96f1f004812 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c
@@ -26,7 +26,6 @@
#include "BLI_utildefines.h"
#include "BLI_blenlib.h"
-#include "BLI_ghash.h"
#include "BLI_math_vector.h"
#include "DNA_scene_types.h"
@@ -34,6 +33,7 @@
#include "DNA_gpencil_types.h"
#include "DNA_gpencil_modifier_types.h"
+#include "BKE_colortools.h"
#include "BKE_gpencil.h"
#include "BKE_gpencil_modifier.h"
#include "BKE_material.h"
@@ -52,13 +52,28 @@ static void initData(GpencilModifierData *md)
gpmd->layername[0] = '\0';
gpmd->materialname[0] = '\0';
ARRAY_SET_ITEMS(gpmd->rgb, 1.0f, 1.0f, 1.0f);
- gpmd->flag |= GP_TINT_CREATE_COLORS;
gpmd->modify_color = GP_MODIFY_COLOR_BOTH;
+
+ gpmd->curve_intensity = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ if (gpmd->curve_intensity) {
+ CurveMapping *curve = gpmd->curve_intensity;
+ BKE_curvemapping_initialize(curve);
+ }
}
static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
{
+ TintGpencilModifierData *gmd = (TintGpencilModifierData *)md;
+ TintGpencilModifierData *tgmd = (TintGpencilModifierData *)target;
+
+ if (tgmd->curve_intensity != NULL) {
+ BKE_curvemapping_free(tgmd->curve_intensity);
+ tgmd->curve_intensity = NULL;
+ }
+
BKE_gpencil_modifier_copyData_generic(md, target);
+
+ tgmd->curve_intensity = BKE_curvemapping_copy(gmd->curve_intensity);
}
/* tint strokes */
@@ -70,6 +85,7 @@ static void deformStroke(GpencilModifierData *md,
bGPDstroke *gps)
{
TintGpencilModifierData *mmd = (TintGpencilModifierData *)md;
+ const bool use_curve = (mmd->flag & GP_TINT_CUSTOM_CURVE) != 0 && mmd->curve_intensity;
if (!is_stroke_affected_by_modifier(ob,
mmd->layername,
@@ -86,69 +102,77 @@ static void deformStroke(GpencilModifierData *md,
return;
}
- if (mmd->modify_color != GP_MODIFY_COLOR_FILL) {
- interp_v3_v3v3(
- gps->runtime.tmp_stroke_rgba, gps->runtime.tmp_stroke_rgba, mmd->rgb, mmd->factor);
- /* if factor is > 1, the alpha must be changed to get full tint */
- if (mmd->factor > 1.0f) {
- gps->runtime.tmp_stroke_rgba[3] += mmd->factor - 1.0f;
+ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
+
+ /* if factor > 1.0, affect the strength of the stroke */
+ if (mmd->factor > 1.0f) {
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ pt->strength += mmd->factor - 1.0f;
+ CLAMP(pt->strength, 0.0f, 1.0f);
}
- CLAMP4(gps->runtime.tmp_stroke_rgba, 0.0f, 1.0f);
}
+ /* Apply to Vertex Color. */
+ float mixfac = mmd->factor;
+
+ CLAMP(mixfac, 0.0, 1.0f);
+ /* Fill */
if (mmd->modify_color != GP_MODIFY_COLOR_STROKE) {
- interp_v3_v3v3(gps->runtime.tmp_fill_rgba, gps->runtime.tmp_fill_rgba, mmd->rgb, mmd->factor);
- /* if factor is > 1, the alpha must be changed to get full tint */
- if (mmd->factor > 1.0f && gps->runtime.tmp_fill_rgba[3] > 1e-5) {
- gps->runtime.tmp_fill_rgba[3] += mmd->factor - 1.0f;
+ /* If not using Vertex Color, use the material color. */
+ if ((gp_style != NULL) && (gps->vert_color_fill[3] == 0.0f) &&
+ (gp_style->fill_rgba[3] > 0.0f)) {
+ copy_v4_v4(gps->vert_color_fill, gp_style->fill_rgba);
+ gps->vert_color_fill[3] = 1.0f;
}
- CLAMP4(gps->runtime.tmp_fill_rgba, 0.0f, 1.0f);
+
+ interp_v3_v3v3(gps->vert_color_fill, gps->vert_color_fill, mmd->rgb, mixfac);
}
- /* if factor > 1.0, affect the strength of the stroke */
- if (mmd->factor > 1.0f) {
+ /* Stroke */
+ if (mmd->modify_color != GP_MODIFY_COLOR_FILL) {
for (int i = 0; i < gps->totpoints; i++) {
bGPDspoint *pt = &gps->points[i];
- pt->strength += mmd->factor - 1.0f;
- CLAMP(pt->strength, 0.0f, 1.0f);
+ /* If not using Vertex Color, use the material color. */
+ if ((gp_style != NULL) && (pt->vert_color[3] == 0.0f) && (gp_style->stroke_rgba[3] > 0.0f)) {
+ copy_v4_v4(pt->vert_color, gp_style->stroke_rgba);
+ pt->vert_color[3] = 1.0f;
+ }
+
+ /* Custom curve to modulate value. */
+ float mixvalue = mixfac;
+ if (use_curve) {
+ float value = (float)i / (gps->totpoints - 1);
+ mixvalue *= BKE_curvemapping_evaluateF(mmd->curve_intensity, 0, value);
+ }
+
+ interp_v3_v3v3(pt->vert_color, pt->vert_color, mmd->rgb, mixvalue);
}
}
}
-static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData *md, Object *ob)
+static void bakeModifier(Main *UNUSED(bmain),
+ Depsgraph *depsgraph,
+ GpencilModifierData *md,
+ Object *ob)
{
- TintGpencilModifierData *mmd = (TintGpencilModifierData *)md;
bGPdata *gpd = ob->data;
- GHash *gh_color = BLI_ghash_str_new("GP_Tint modifier");
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
-
- Material *mat = BKE_gpencil_material(ob, gps->mat_nr + 1);
- if (mat == NULL) {
- continue;
- }
- MaterialGPencilStyle *gp_style = mat->gp_style;
- /* skip stroke if it doesn't have color info */
- if (ELEM(NULL, gp_style)) {
- continue;
- }
-
- copy_v4_v4(gps->runtime.tmp_stroke_rgba, gp_style->stroke_rgba);
- copy_v4_v4(gps->runtime.tmp_fill_rgba, gp_style->fill_rgba);
-
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
deformStroke(md, depsgraph, ob, gpl, gpf, gps);
-
- gpencil_apply_modifier_material(
- bmain, ob, mat, gh_color, gps, (bool)(mmd->flag & GP_TINT_CREATE_COLORS));
}
}
}
- /* free hash buffers */
- if (gh_color) {
- BLI_ghash_free(gh_color, NULL, NULL);
- gh_color = NULL;
+}
+
+static void freeData(GpencilModifierData *md)
+{
+ TintGpencilModifierData *gpmd = (TintGpencilModifierData *)md;
+
+ if (gpmd->curve_intensity) {
+ BKE_curvemapping_free(gpmd->curve_intensity);
}
}
@@ -167,7 +191,7 @@ GpencilModifierTypeInfo modifierType_Gpencil_Tint = {
/* remapTime */ NULL,
/* initData */ initData,
- /* freeData */ NULL,
+ /* freeData */ freeData,
/* isDisabled */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilvertexcolor.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilvertexcolor.c
new file mode 100644
index 00000000000..b279d90dd4f
--- /dev/null
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilvertexcolor.c
@@ -0,0 +1,314 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2017, Blender Foundation
+ * This is a new part of Blender
+ */
+
+/** \file
+ * \ingroup modifiers
+ */
+
+#include <stdio.h>
+
+#include "BLI_utildefines.h"
+
+#include "BLI_math.h"
+#include "BLI_listbase.h"
+
+#include "DNA_meshdata_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_gpencil_modifier_types.h"
+#include "DNA_modifier_types.h"
+
+#include "BKE_action.h"
+#include "BKE_colorband.h"
+#include "BKE_colortools.h"
+#include "BKE_deform.h"
+#include "BKE_gpencil.h"
+#include "BKE_gpencil_modifier.h"
+#include "BKE_layer.h"
+#include "BKE_lib_query.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_modifier.h"
+#include "BKE_scene.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "MOD_gpencil_util.h"
+#include "MOD_gpencil_modifiertypes.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
+
+static void initData(GpencilModifierData *md)
+{
+ VertexcolorGpencilModifierData *gpmd = (VertexcolorGpencilModifierData *)md;
+ gpmd->pass_index = 0;
+ gpmd->layername[0] = '\0';
+ gpmd->materialname[0] = '\0';
+ gpmd->vgname[0] = '\0';
+ gpmd->object = NULL;
+ gpmd->radius = 1.0f;
+ gpmd->factor = 1.0f;
+
+ /* Add default color ramp. */
+ gpmd->colorband = BKE_colorband_add(false);
+ if (gpmd->colorband) {
+ BKE_colorband_init(gpmd->colorband, true);
+ CBData *ramp = gpmd->colorband->data;
+ ramp[0].r = ramp[0].g = ramp[0].b = ramp[0].a = 1.0f;
+ ramp[0].pos = 0.0f;
+ ramp[1].r = ramp[1].g = ramp[1].b = 0.0f;
+ ramp[1].a = 1.0f;
+ ramp[1].pos = 1.0f;
+
+ gpmd->colorband->tot = 2;
+ }
+
+ gpmd->curve_intensity = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ if (gpmd->curve_intensity) {
+ CurveMapping *curve = gpmd->curve_intensity;
+ BKE_curvemapping_initialize(curve);
+ }
+}
+
+static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
+{
+ VertexcolorGpencilModifierData *gmd = (VertexcolorGpencilModifierData *)md;
+ VertexcolorGpencilModifierData *tgmd = (VertexcolorGpencilModifierData *)target;
+
+ MEM_SAFE_FREE(tgmd->colorband);
+
+ if (tgmd->curve_intensity != NULL) {
+ BKE_curvemapping_free(tgmd->curve_intensity);
+ tgmd->curve_intensity = NULL;
+ }
+
+ BKE_gpencil_modifier_copyData_generic(md, target);
+
+ if (gmd->colorband) {
+ tgmd->colorband = MEM_dupallocN(gmd->colorband);
+ }
+
+ tgmd->curve_intensity = BKE_curvemapping_copy(gmd->curve_intensity);
+}
+
+/* deform stroke */
+static void deformStroke(GpencilModifierData *md,
+ Depsgraph *UNUSED(depsgraph),
+ Object *ob,
+ bGPDlayer *gpl,
+ bGPDframe *UNUSED(gpf),
+ bGPDstroke *gps)
+{
+ VertexcolorGpencilModifierData *mmd = (VertexcolorGpencilModifierData *)md;
+ if (!mmd->object) {
+ return;
+ }
+
+ const int def_nr = BKE_object_defgroup_name_index(ob, mmd->vgname);
+ const bool use_curve = (mmd->flag & GP_VERTEXCOL_CUSTOM_CURVE) != 0 && mmd->curve_intensity;
+
+ if (!is_stroke_affected_by_modifier(ob,
+ mmd->layername,
+ mmd->materialname,
+ mmd->pass_index,
+ mmd->layer_pass,
+ 1,
+ gpl,
+ gps,
+ mmd->flag & GP_VERTEXCOL_INVERT_LAYER,
+ mmd->flag & GP_VERTEXCOL_INVERT_PASS,
+ mmd->flag & GP_VERTEXCOL_INVERT_LAYERPASS,
+ mmd->flag & GP_VERTEXCOL_INVERT_MATERIAL)) {
+ return;
+ }
+ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
+
+ float coba_res[4];
+ float matrix[4][4];
+ mul_m4_m4m4(matrix, mmd->object->imat, ob->obmat);
+
+ /* loop points and apply deform */
+ bool fill_done = false;
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ MDeformVert *dvert = gps->dvert != NULL ? &gps->dvert[i] : NULL;
+
+ if (!fill_done) {
+ /* Apply to fill. */
+ if (mmd->mode != GPPAINT_MODE_STROKE) {
+
+ /* If not using Vertex Color, use the material color. */
+ if ((gp_style != NULL) && (gps->vert_color_fill[3] == 0.0f) &&
+ (gp_style->fill_rgba[3] > 0.0f)) {
+ copy_v4_v4(gps->vert_color_fill, gp_style->fill_rgba);
+ gps->vert_color_fill[3] = 1.0f;
+ }
+
+ float center[3];
+ add_v3_v3v3(center, gps->boundbox_min, gps->boundbox_max);
+ mul_v3_fl(center, 0.5f);
+ float pt_loc[3];
+ mul_v3_m4v3(pt_loc, matrix, &pt->x);
+ float dist = len_v3(pt_loc);
+ float mix_factor = clamp_f(dist / mmd->radius, 0.0f, 1.0f);
+
+ BKE_colorband_evaluate(mmd->colorband, mix_factor, coba_res);
+ interp_v3_v3v3(gps->vert_color_fill, gps->vert_color_fill, coba_res, mmd->factor);
+ gps->vert_color_fill[3] = mmd->factor;
+ /* If no stroke, cancel loop. */
+ if (mmd->mode != GPPAINT_MODE_BOTH) {
+ break;
+ }
+ }
+
+ fill_done = true;
+ }
+
+ /* Verify vertex group. */
+ if (mmd->mode != GPPAINT_MODE_FILL) {
+ float weight = get_modifier_point_weight(
+ dvert, (mmd->flag & GP_VERTEXCOL_INVERT_VGROUP) != 0, def_nr);
+ if (weight < 0.0f) {
+ continue;
+ }
+ /* Custom curve to modulate value. */
+ if (use_curve) {
+ float value = (float)i / (gps->totpoints - 1);
+ weight *= BKE_curvemapping_evaluateF(mmd->curve_intensity, 0, value);
+ }
+
+ /* Calc world position of point. */
+ float pt_loc[3];
+ mul_v3_m4v3(pt_loc, matrix, &pt->x);
+ float dist = len_v3(pt_loc);
+
+ /* If not using Vertex Color, use the material color. */
+ if ((gp_style != NULL) && (pt->vert_color[3] == 0.0f) && (gp_style->stroke_rgba[3] > 0.0f)) {
+ copy_v4_v4(pt->vert_color, gp_style->stroke_rgba);
+ pt->vert_color[3] = 1.0f;
+ }
+
+ /* Calc the factor using the distance and get mix color. */
+ float mix_factor = clamp_f(dist / mmd->radius, 0.0f, 1.0f);
+ BKE_colorband_evaluate(mmd->colorband, mix_factor, coba_res);
+
+ interp_v3_v3v3(pt->vert_color, pt->vert_color, coba_res, mmd->factor * weight * coba_res[3]);
+ }
+ }
+}
+
+/* FIXME: Ideally we be doing this on a copy of the main depsgraph
+ * (i.e. one where we don't have to worry about restoring state)
+ */
+static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData *md, Object *ob)
+{
+ VertexcolorGpencilModifierData *mmd = (VertexcolorGpencilModifierData *)md;
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ bGPdata *gpd = ob->data;
+ int oldframe = (int)DEG_get_ctime(depsgraph);
+
+ if (mmd->object == NULL) {
+ return;
+ }
+
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ /* apply effects on this frame
+ * NOTE: this assumes that we don't want animation on non-keyframed frames
+ */
+ CFRA = gpf->framenum;
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
+
+ /* compute effects on this frame */
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ deformStroke(md, depsgraph, ob, gpl, gpf, gps);
+ }
+ }
+ }
+
+ /* return frame state and DB to original state */
+ CFRA = oldframe;
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
+}
+
+static void freeData(GpencilModifierData *md)
+{
+ VertexcolorGpencilModifierData *mmd = (VertexcolorGpencilModifierData *)md;
+ if (mmd->colorband) {
+ MEM_freeN(mmd->colorband);
+ mmd->colorband = NULL;
+ }
+ if (mmd->curve_intensity) {
+ BKE_curvemapping_free(mmd->curve_intensity);
+ }
+}
+
+static bool isDisabled(GpencilModifierData *md, int UNUSED(userRenderParams))
+{
+ VertexcolorGpencilModifierData *mmd = (VertexcolorGpencilModifierData *)md;
+
+ return !mmd->object;
+}
+
+static void updateDepsgraph(GpencilModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
+{
+ VertexcolorGpencilModifierData *lmd = (VertexcolorGpencilModifierData *)md;
+ if (lmd->object != NULL) {
+ DEG_add_object_relation(ctx->node, lmd->object, DEG_OB_COMP_GEOMETRY, "Vertexcolor Modifier");
+ DEG_add_object_relation(ctx->node, lmd->object, DEG_OB_COMP_TRANSFORM, "Vertexcolor Modifier");
+ }
+ DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Vertexcolor Modifier");
+}
+
+static void foreachObjectLink(GpencilModifierData *md,
+ Object *ob,
+ ObjectWalkFunc walk,
+ void *userData)
+{
+ VertexcolorGpencilModifierData *mmd = (VertexcolorGpencilModifierData *)md;
+
+ walk(userData, ob, &mmd->object, IDWALK_CB_NOP);
+}
+
+GpencilModifierTypeInfo modifierType_Gpencil_Vertexcolor = {
+ /* name */ "Vertex Color",
+ /* structName */ "VertexcolorGpencilModifierData",
+ /* structSize */ sizeof(VertexcolorGpencilModifierData),
+ /* type */ eGpencilModifierTypeType_Gpencil,
+ /* flags */ eGpencilModifierTypeFlag_SupportsEditmode,
+
+ /* copyData */ copyData,
+
+ /* deformStroke */ deformStroke,
+ /* generateStrokes */ NULL,
+ /* bakeModifier */ bakeModifier,
+ /* remapTime */ NULL,
+
+ /* initData */ initData,
+ /* freeData */ freeData,
+ /* isDisabled */ isDisabled,
+ /* updateDepsgraph */ updateDepsgraph,
+ /* dependsOnTime */ NULL,
+ /* foreachObjectLink */ foreachObjectLink,
+ /* foreachIDLink */ NULL,
+ /* foreachTexLink */ NULL,
+};