diff options
author | Cody Winchester <CodyWinch> | 2021-12-13 19:14:32 +0300 |
---|---|---|
committer | Antonio Vazquez <blendergit@gmail.com> | 2021-12-13 19:14:44 +0300 |
commit | a90c3564676649aa4a0b74112c852a75de6d3521 (patch) | |
tree | e52f0845e3fd097a3b5a3663417fd13fbf35c4a2 /source | |
parent | 459af75d1ed586f08cd43e2aec7a3b270e809132 (diff) |
GPencil: Add randomize options to Length modifier
This patch adds a randomize factor for the start/end lengths in the Length modifier.
Reviewed By: #grease_pencil, antoniov, pepeland, HooglyBoogly
Differential Revision: https://developer.blender.org/D12928
Diffstat (limited to 'source')
4 files changed, 153 insertions, 5 deletions
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencillength.c b/source/blender/gpencil_modifiers/intern/MOD_gpencillength.c index 80b60547e92..af0067e06aa 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencillength.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencillength.c @@ -23,8 +23,10 @@ #include <stdio.h> +#include "BLI_hash.h" #include "BLI_listbase.h" #include "BLI_math.h" +#include "BLI_rand.h" #include "BLI_utildefines.h" #include "BLT_translation.h" @@ -56,6 +58,7 @@ #include "MOD_gpencil_util.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" static void initData(GpencilModifierData *md) { @@ -71,6 +74,20 @@ static void copyData(const GpencilModifierData *md, GpencilModifierData *target) BKE_gpencil_modifier_copydata_generic(md, target); } +static float *noise_table(int len, int offset, 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 + offset + 1)); + } + return table; +} + +BLI_INLINE float table_sample(float *table, float x) +{ + return interpf(table[(int)ceilf(x)], table[(int)floor(x)], fractf(x)); +} + static bool gpencil_modify_stroke(bGPDstroke *gps, const float length, const float overshoot_fac, @@ -104,9 +121,15 @@ static bool gpencil_modify_stroke(bGPDstroke *gps, return changed; } -static void applyLength(LengthGpencilModifierData *lmd, bGPdata *gpd, bGPDstroke *gps) +static void applyLength(GpencilModifierData *md, + Depsgraph *depsgraph, + bGPdata *gpd, + bGPDframe *gpf, + bGPDstroke *gps, + Object *ob) { bool changed = false; + LengthGpencilModifierData *lmd = (LengthGpencilModifierData *)md; const float len = (lmd->mode == GP_LENGTH_ABSOLUTE) ? 1.0f : BKE_gpencil_stroke_length(gps, true); const int totpoints = gps->totpoints; @@ -120,11 +143,48 @@ static void applyLength(LengthGpencilModifierData *lmd, bGPdata *gpd, bGPDstroke int first_mode = 1; float second_fac = lmd->end_fac; int second_mode = 2; + + float rand[2] = {0.0f, 0.0f}; + if (lmd->rand_start_fac != 0.0 || lmd->rand_end_fac != 0.0) { + int seed = lmd->seed; + + /* Make sure different modifiers get different seeds. */ + seed += BLI_hash_string(ob->id.name + 2); + seed += BLI_hash_string(md->name); + + if (lmd->flag & GP_LENGTH_USE_RANDOM) { + seed += ((int)DEG_get_ctime(depsgraph)) / lmd->step; + } + + float rand_offset = BLI_hash_int_01(seed); + + /* Get stroke index for random offset. */ + int rnd_index = BLI_findindex(&gpf->strokes, gps); + const uint primes[2] = {2, 3}; + double offset[2] = {0.0f, 0.0f}; + double r[2]; + + float *noise_table_length = noise_table(4, (int)floor(lmd->rand_offset), seed + 2); + + /* To ensure a nice distribution, we use halton sequence and offset using the seed. */ + BLI_halton_2d(primes, offset, rnd_index, r); + for (int j = 0; j < 2; j++) { + float noise = table_sample(noise_table_length, j * 2 + fractf(lmd->rand_offset)); + + rand[j] = fmodf(r[j] + rand_offset, 1.0f); + rand[j] = fabs(fmodf(sin(rand[j] * 12.9898f + j * 78.233f) * 43758.5453f, 1.0f) + noise); + } + + MEM_SAFE_FREE(noise_table_length); + + first_fac = first_fac + rand[0] * lmd->rand_start_fac; + second_fac = second_fac + rand[1] * lmd->rand_end_fac; + } + if (first_fac < 0) { SWAP(float, first_fac, second_fac); SWAP(int, first_mode, second_mode); } - const int first_extra_point_count = ceil(first_fac * lmd->point_density); const int second_extra_point_count = ceil(second_fac * lmd->point_density); @@ -161,10 +221,10 @@ static void applyLength(LengthGpencilModifierData *lmd, bGPdata *gpd, bGPDstroke } static void deformStroke(GpencilModifierData *md, - Depsgraph *UNUSED(depsgraph), + Depsgraph *depsgraph, Object *ob, bGPDlayer *gpl, - bGPDframe *UNUSED(gpf), + bGPDframe *gpf, bGPDstroke *gps) { bGPdata *gpd = ob->data; @@ -187,7 +247,7 @@ static void deformStroke(GpencilModifierData *md, /* Don't affect cyclic strokes as they have no start/end. */ return; } - applyLength(lmd, gpd, gps); + applyLength(md, depsgraph, gpd, gpf, gps, ob); } static void bakeModifier(Main *UNUSED(bmain), @@ -214,6 +274,39 @@ static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); } +static void random_header_draw(const bContext *UNUSED(C), Panel *panel) +{ + uiLayout *layout = panel->layout; + + PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL); + + uiItemR(layout, ptr, "use_random", 0, IFACE_("Randomize"), ICON_NONE); +} + +static void random_panel_draw(const bContext *UNUSED(C), Panel *panel) +{ + uiLayout *layout = panel->layout; + + PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL); + + uiLayoutSetPropSep(layout, true); + + uiLayoutSetActive(layout, RNA_boolean_get(ptr, "use_random")); + + uiItemR(layout, ptr, "step", 0, NULL, ICON_NONE); +} + +static void offset_panel_draw(const bContext *UNUSED(C), Panel *panel) +{ + uiLayout *layout = panel->layout; + PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL); + uiLayoutSetPropSep(layout, true); + uiItemR(layout, ptr, "random_start_factor", 0, IFACE_("Random Offset Start"), ICON_NONE); + uiItemR(layout, ptr, "random_end_factor", 0, IFACE_("Random Offset End"), ICON_NONE); + uiItemR(layout, ptr, "random_offset", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "seed", 0, NULL, ICON_NONE); +} + static void panel_draw(const bContext *UNUSED(C), Panel *panel) { uiLayout *layout = panel->layout; @@ -277,6 +370,10 @@ static void panelRegister(ARegionType *region_type) region_type, eGpencilModifierType_Length, panel_draw); gpencil_modifier_subpanel_register( region_type, "curvature", "", curvature_header_draw, curvature_panel_draw, panel_type); + PanelType *offset_panel = gpencil_modifier_subpanel_register( + region_type, "offset", "Random Offsets", NULL, offset_panel_draw, panel_type); + gpencil_modifier_subpanel_register( + region_type, "randomize", "", random_header_draw, random_panel_draw, offset_panel); gpencil_modifier_subpanel_register( region_type, "mask", "Influence", NULL, mask_panel_draw, panel_type); } diff --git a/source/blender/makesdna/DNA_gpencil_modifier_defaults.h b/source/blender/makesdna/DNA_gpencil_modifier_defaults.h index e0947085694..88eb164c2b4 100644 --- a/source/blender/makesdna/DNA_gpencil_modifier_defaults.h +++ b/source/blender/makesdna/DNA_gpencil_modifier_defaults.h @@ -333,6 +333,11 @@ .point_density = 30.0f,\ .segment_influence = 0.0f,\ .max_angle = DEG2RAD(170.0f),\ + .rand_start_fac = 0.0f,\ + .rand_end_fac = 0.0f,\ + .rand_offset = 0.0f,\ + .seed = 0,\ + .step = 4,\ } #define _DNA_DEFAULT_DashGpencilModifierData \ diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h index f7964e1f2fa..0f69a256f56 100644 --- a/source/blender/makesdna/DNA_gpencil_modifier_types.h +++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h @@ -492,10 +492,17 @@ typedef struct LengthGpencilModifierData { int layer_pass; /** Length. */ float start_fac, end_fac; + /** Random length factors. */ + float rand_start_fac, rand_end_fac, rand_offset; /** Overshoot trajectory factor. */ float overshoot_fac; + /** (first element is the index) random values. */ + int seed; + /** How many frames before recalculate randoms. */ + int step; /** Modifier mode. */ int mode; + char _pad[4]; /* Curvature parameters. */ float point_density; float segment_influence; @@ -509,6 +516,7 @@ typedef enum eLengthGpencil_Flag { GP_LENGTH_INVERT_MATERIAL = (1 << 3), GP_LENGTH_USE_CURVATURE = (1 << 4), GP_LENGTH_INVERT_CURVATURE = (1 << 5), + GP_LENGTH_USE_RANDOM = (1 << 6), } eLengthGpencil_Flag; typedef enum eLengthGpencil_Type { diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c index 72401b460be..7ca77e1c290 100644 --- a/source/blender/makesrna/intern/rna_gpencil_modifier.c +++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c @@ -3488,6 +3488,44 @@ static void rna_def_modifier_gpencillength(BlenderRNA *brna) RNA_def_property_ui_text(prop, "End Factor", "Absolute added length to the end of each stroke"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "random_start_factor", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "rand_start_fac"); + RNA_def_property_ui_range(prop, -10.0f, 10.0f, 0.1, 1); + RNA_def_property_ui_text(prop, + "Random Start Factor", + "Size of random length added to the start of each stroke"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "random_end_factor", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "rand_end_fac"); + RNA_def_property_ui_range(prop, -10.0f, 10.0f, 0.1, 1); + RNA_def_property_ui_text( + prop, "Random End Factor", "Size of random length added to the end of each stroke"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "random_offset", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "rand_offset"); + RNA_def_property_ui_range(prop, 0.0f, 100.0f, 0.1, 3); + RNA_def_property_ui_text( + prop, "Random Noise Offset", "Smoothly offset each stroke's random value"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "use_random", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LENGTH_USE_RANDOM); + RNA_def_property_ui_text(prop, "Random", "Use random values over time"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "seed", PROP_INT, PROP_UNSIGNED); + RNA_def_property_ui_text(prop, "Seed", "Random seed"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "step", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "step"); + RNA_def_property_range(prop, 1, 100); + RNA_def_property_ui_text( + prop, "Step", "Number of frames before recalculate random values again"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "overshoot_factor", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "overshoot_fac"); RNA_def_property_range(prop, 0.0f, 1.0f); |