Gpencil Offset Modifier - Add randomize offset options

This patch adds the Randomize options that exist in the Array modifier to the offset modifier.

Currently the patch uses
```
BLI_findindex(&gpf->strokes, gps);
```
to get the index of the current stroke for making each stroke a different seed value. This is how the noise modifier also gets the stroke seed value and it is noted there as well that this method is slow, and should be fixed in the future with another method of getting the stroke index.
Other methods were explored such as using the total number of points of the stroke, but that makes the randomize options incompatible with other modifiers before it such as Multiple Strokes, Array, Build, and Simplify.

{F9591325}

Differential Revision: https://developer.blender.org/D10171
This commit is contained in:
Cody Winchester 2021-04-29 15:39:08 +02:00 committed by Antonio Vazquez
parent 4225a18b35
commit 6a2bc40e01
Notes: blender-bot 2023-02-14 09:48:23 +01:00
Referenced by commit 16fe767d00, GPencil: Fix offset modifier performance regression
4 changed files with 111 additions and 2 deletions

View File

@ -1688,6 +1688,7 @@ void BKE_gpencil_stroke_normal(const bGPDstroke *gps, float r_normal[3])
float vec1[3];
float vec2[3];
float vec3[3];
/* initial vector (p0 -> p1) */
sub_v3_v3v3(vec1, &pt1->x, &pt0->x);
@ -1696,7 +1697,8 @@ void BKE_gpencil_stroke_normal(const bGPDstroke *gps, float r_normal[3])
sub_v3_v3v3(vec2, &pt3->x, &pt0->x);
/* vector orthogonal to polygon plane */
cross_v3_v3v3(r_normal, vec1, vec2);
cross_v3_v3v3(vec3, vec1, vec2);
cross_v3_v3v3(r_normal, vec1, vec3);
/* Normalize vector */
normalize_v3(r_normal);

View File

@ -26,7 +26,11 @@
#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
#include "BLI_math.h"
#include "BLI_hash.h"
#include "BLI_rand.h"
#include "DNA_defaults.h"
#include "DNA_gpencil_modifier_types.h"
@ -71,7 +75,7 @@ static void deformStroke(GpencilModifierData *md,
Depsgraph *UNUSED(depsgraph),
Object *ob,
bGPDlayer *gpl,
bGPDframe *UNUSED(gpf),
bGPDframe *gpf,
bGPDstroke *gps)
{
OffsetGpencilModifierData *mmd = (OffsetGpencilModifierData *)md;
@ -94,6 +98,52 @@ static void deformStroke(GpencilModifierData *md,
mmd->flag & GP_OFFSET_INVERT_MATERIAL)) {
return;
}
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);
float rand[3][3];
float rand_offset = BLI_hash_int_01(seed);
/* Get stroke index for random offset. */
int rnd_index = 0;
LISTBASE_FOREACH (bGPDstroke *, o_gps, &gpf->strokes) {
if (o_gps == gps) {
break;
}
rnd_index += 1;
}
for (int j = 0; j < 3; j++) {
const 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, rnd_index, r);
if ((mmd->flag & GP_OFFSET_UNIFORM_RANDOM_SCALE) && j == 2) {
float rand_value;
rand_value = fmodf(r[0] * 2.0 - 1.0 + rand_offset, 1.0f);
rand_value = fmodf(sin(rand_value * 12.9898 + j * 78.233) * 43758.5453, 1.0f);
copy_v3_fl(rand[j], rand_value);
}
else {
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 rnd_loc[3], rnd_rot[3];
float rnd_scale[3] = {1.0f, 1.0f, 1.0f};
mul_v3_v3v3(rnd_loc, mmd->rnd_offset, rand[0]);
mul_v3_v3v3(rnd_rot, mmd->rnd_rot, rand[1]);
madd_v3_v3v3(rnd_scale, mmd->rnd_scale, rand[2]);
loc_eul_size_to_mat4(mat_rnd, rnd_loc, rnd_rot, rnd_scale);
bGPdata *gpd = ob->data;
for (int i = 0; i < gps->totpoints; i++) {
@ -106,6 +156,9 @@ static void deformStroke(GpencilModifierData *md,
if (weight < 0.0f) {
continue;
}
/* Apply randomness matrix. */
mul_m4_v3(mat_rnd, &pt->x);
/* Calculate matrix. */
mul_v3_v3fl(loc, mmd->loc, weight);
mul_v3_v3fl(rot, mmd->rot, weight);
@ -161,6 +214,21 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
gpencil_modifier_panel_end(layout, ptr);
}
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);
uiItemR(layout, ptr, "random_offset", 0, IFACE_("Offset"), ICON_NONE);
uiItemR(layout, ptr, "random_rotation", 0, IFACE_("Rotation"), ICON_NONE);
uiItemR(layout, ptr, "random_scale", 0, IFACE_("Scale"), ICON_NONE);
uiItemR(layout, ptr, "use_uniform_random_scale", 0, NULL, ICON_NONE);
uiItemR(layout, ptr, "seed", 0, NULL, ICON_NONE);
}
static void mask_panel_draw(const bContext *UNUSED(C), Panel *panel)
{
gpencil_modifier_masking_panel_draw(panel, true, true);
@ -170,6 +238,8 @@ static void panelRegister(ARegionType *region_type)
{
PanelType *panel_type = gpencil_modifier_panel_register(
region_type, eGpencilModifierType_Offset, panel_draw);
gpencil_modifier_subpanel_register(
region_type, "randomize", "Randomize", NULL, random_panel_draw, panel_type);
gpencil_modifier_subpanel_register(
region_type, "mask", "Influence", NULL, mask_panel_draw, panel_type);
}

View File

@ -630,6 +630,14 @@ typedef struct OffsetGpencilModifierData {
float loc[3];
float rot[3];
float scale[3];
/** Random Offset. */
float rnd_offset[3];
/** Random Rotation. */
float rnd_rot[3];
/** Random Scales. */
float rnd_scale[3];
/** (first element is the index) random values. */
int seed;
/** Custom index for passes. */
int layer_pass;
} OffsetGpencilModifierData;
@ -640,6 +648,7 @@ typedef enum eOffsetGpencil_Flag {
GP_OFFSET_INVERT_VGROUP = (1 << 2),
GP_OFFSET_INVERT_LAYERPASS = (1 << 3),
GP_OFFSET_INVERT_MATERIAL = (1 << 4),
GP_OFFSET_UNIFORM_RANDOM_SCALE = (1 << 5),
} eOffsetGpencil_Flag;
typedef struct SmoothGpencilModifierData {

View File

@ -1290,6 +1290,34 @@ static void rna_def_modifier_gpenciloffset(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Scale", "Values for changes in scale");
RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT);
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "random_offset", PROP_FLOAT, PROP_XYZ);
RNA_def_property_float_sdna(prop, NULL, "rnd_offset");
RNA_def_property_ui_text(prop, "Random Offset", "Value for changes in location");
RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT);
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "random_rotation", PROP_FLOAT, PROP_EULER);
RNA_def_property_float_sdna(prop, NULL, "rnd_rot");
RNA_def_property_ui_text(prop, "Random Rotation", "Value for changes in rotation");
RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT);
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "random_scale", PROP_FLOAT, PROP_XYZ);
RNA_def_property_float_sdna(prop, NULL, "rnd_scale");
RNA_def_property_ui_text(prop, "Scale", "Value for changes in scale");
RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT);
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_uniform_random_scale", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_OFFSET_UNIFORM_RANDOM_SCALE);
RNA_def_property_ui_text(
prop, "Uniform Scale", "Use the same random seed for each scale axis for a uniform scale");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
}
static void rna_def_modifier_gpenciltint(BlenderRNA *brna)