diff options
author | Antonio Vazquez <blendergit@gmail.com> | 2020-03-09 18:27:24 +0300 |
---|---|---|
committer | Antonio Vazquez <blendergit@gmail.com> | 2020-03-09 18:27:24 +0300 |
commit | 29f3af95272590d26f610ae828b2eeee89c82a00 (patch) | |
tree | a696a58a2561c48f7ec6166e369e22081e0a64d8 /source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c | |
parent | dcb93126876879d969a30a7865700abd072066f8 (diff) |
GPencil: Refactor of Draw Engine, Vertex Paint and all internal functions
This commit is a full refactor of the grease pencil modules including Draw Engine, Modifiers, VFX, depsgraph update, improvements in operators and conversion of Sculpt and Weight paint tools to real brushes.
Also, a huge code cleanup has been done at all levels.
Thanks to @fclem for his work and yo @pepeland and @mendio for the testing and help in the development.
Differential Revision: https://developer.blender.org/D6293
Diffstat (limited to 'source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c')
-rw-r--r-- | source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c | 227 |
1 files changed, 117 insertions, 110 deletions
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, |