From 80123efc5fc258ef8b27efba67d6ad2a0efb7edd Mon Sep 17 00:00:00 2001 From: Antonioya Date: Thu, 1 Aug 2019 17:54:51 +0200 Subject: Fix T67939: GPencil Noise modifier wrong random calculation There were several problems in the old random calculation: * Different result in the viewport and render. * Noise "pop" in some frames. * Random number was calculated every time the file was opened, so get different results. Now, instead to calculate the random numbers when n number of frames changed, the random values are calculated using a unique seed by stroke. Also, a new Seed parameter has been added and this adds more control in the noise generated. This value can be animated and get more variations. Differential Revision: http://developer.blender.org/D5393 --- .../gpencil_modifiers/intern/MOD_gpencilnoise.c | 74 +++------------------- .../blender/makesdna/DNA_gpencil_modifier_types.h | 10 +-- .../blender/makesrna/intern/rna_gpencil_modifier.c | 4 ++ 3 files changed, 16 insertions(+), 72 deletions(-) (limited to 'source') diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c index e0139eac6b2..e891b6dea12 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c @@ -26,10 +26,9 @@ #include "BLI_utildefines.h" #include "BLI_math_vector.h" +#include "BLI_hash.h" #include "BLI_rand.h" -#include "PIL_time.h" - #include "DNA_meshdata_types.h" #include "DNA_scene_types.h" #include "DNA_object_types.h" @@ -58,20 +57,7 @@ static void initData(GpencilModifierData *md) gpmd->layername[0] = '\0'; gpmd->vgname[0] = '\0'; gpmd->step = 1; - gpmd->scene_frame = -999999; - gpmd->gp_frame = -999999; - - gpmd->vrand1 = 1.0; - gpmd->vrand2 = 1.0; -} - -static void freeData(GpencilModifierData *md) -{ - NoiseGpencilModifierData *mmd = (NoiseGpencilModifierData *)md; - - if (mmd->rng != NULL) { - BLI_rng_free(mmd->rng); - } + gpmd->seed = 0; } static void copyData(const GpencilModifierData *md, GpencilModifierData *target) @@ -85,21 +71,6 @@ static bool dependsOnTime(GpencilModifierData *md) return (mmd->flag & GP_NOISE_USE_RANDOM) != 0; } -/* Get the lower number of frame for all layers. */ -static int get_lower_frame(bGPdata *gpd) -{ - int init = 99999; - for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { - if (gpl->frames.first) { - bGPDframe *gpf = gpl->frames.first; - if (gpf->framenum < init) { - init = gpf->framenum; - } - } - } - return init; -} - /* aply noise effect based on stroke direction */ static void deformStroke( GpencilModifierData *md, Depsgraph *depsgraph, Object *ob, bGPDlayer *gpl, bGPDstroke *gps) @@ -111,26 +82,10 @@ static void deformStroke( float normal[3]; float vec1[3], vec2[3]; int sc_frame = 0; - int sc_diff = 0; + int stroke_seed = 0; const int def_nr = defgroup_name_index(ob, mmd->vgname); const float unit_v3[3] = {1.0f, 1.0f, 1.0f}; - Object *object_eval = DEG_get_evaluated_object(depsgraph, ob); - GpencilModifierData *md_eval = BKE_gpencil_modifiers_findByName(object_eval, md->name); - NoiseGpencilModifierData *mmd_eval = (NoiseGpencilModifierData *)md_eval; - bGPdata *gpd = (bGPdata *)ob->data; - - /* Random generator, only init once. (it uses eval to get same value in render) */ - if (mmd_eval->rng == NULL) { - uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX); - rng_seed ^= POINTER_AS_UINT(mmd); - mmd_eval->rng = BLI_rng_new(rng_seed); - mmd->rng = mmd_eval->rng; - /* Get lower frame number */ - mmd_eval->scene_frame = get_lower_frame(gpd); - mmd->scene_frame = mmd_eval->scene_frame; - } - if (!is_stroke_affected_by_modifier(ob, mmd->layername, mmd->pass_index, @@ -200,22 +155,14 @@ static void deformStroke( normalize_v3(vec2); /* Use random noise */ if (mmd->flag & GP_NOISE_USE_RANDOM) { - sc_diff = abs(sc_frame - mmd->scene_frame) % mmd->step; - /* Only recalc if the gp frame change or is a step. */ - if ((mmd->gp_frame != sc_frame) && (sc_diff == 0)) { - vran = mmd->vrand1 = BLI_rng_get_float(mmd->rng); - vdir = mmd->vrand2 = BLI_rng_get_float(mmd->rng); - mmd->gp_frame = sc_frame; + 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 { - vran = mmd->vrand1; - if (mmd->flag & GP_NOISE_FULL_STROKE) { - vdir = mmd->vrand2; - } - else { - int f = (mmd->vrand2 * 10.0f) + i; - vdir = f % 2; - } + int f = (BLI_hash_frand(stroke_seed + 3) * 10.0f) + i; + vdir = f % 2; } } else { @@ -226,7 +173,6 @@ static void deformStroke( else { vdir = i % 2; } - mmd->gp_frame = -999999; } /* if vec2 is zero, set to something */ @@ -314,7 +260,7 @@ GpencilModifierTypeInfo modifierType_Gpencil_Noise = { /* remapTime */ NULL, /* initData */ initData, - /* freeData */ freeData, + /* freeData */ NULL, /* isDisabled */ NULL, /* updateDepsgraph */ NULL, /* dependsOnTime */ dependsOnTime, diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h index c2a9d3cf296..47347753f42 100644 --- a/source/blender/makesdna/DNA_gpencil_modifier_types.h +++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h @@ -90,16 +90,10 @@ typedef struct NoiseGpencilModifierData { float factor; /** How many frames before recalculate randoms. */ int step; - /** Last gp frame used. */ - int gp_frame; - /** First scene frame used. */ - int scene_frame; - /** Random values. */ - float vrand1, vrand2; - struct RNG *rng; /** Custom index for passes. */ int layer_pass; - char _pad[4]; + /** Random seed */ + int seed; } NoiseGpencilModifierData; typedef enum eNoiseGpencil_Flag { diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c index 2b89225d34d..754c443e7e6 100644 --- a/source/blender/makesrna/intern/rna_gpencil_modifier.c +++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c @@ -377,6 +377,10 @@ static void rna_def_modifier_gpencilnoise(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Random", "Use random values"); 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, "use_edit_position", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_NOISE_MOD_LOCATION); RNA_def_property_ui_text( -- cgit v1.2.3