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:
authorAntonio Vazquez <blendergit@gmail.com>2020-03-09 18:27:24 +0300
committerAntonio Vazquez <blendergit@gmail.com>2020-03-09 18:27:24 +0300
commit29f3af95272590d26f610ae828b2eeee89c82a00 (patch)
treea696a58a2561c48f7ec6166e369e22081e0a64d8 /source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c
parentdcb93126876879d969a30a7865700abd072066f8 (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_gpencilarray.c')
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c304
1 files changed, 148 insertions, 156 deletions
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)