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:
Diffstat (limited to 'source/blender/gpencil_modifiers')
-rw-r--r--source/blender/gpencil_modifiers/CMakeLists.txt1
-rw-r--r--source/blender/gpencil_modifiers/MOD_gpencil_lineart.h1
-rw-r--r--source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.c16
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.h12
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c3
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h6
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencildash.c2
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencillength.c107
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilshrinkwrap.c350
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c2
-rw-r--r--source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h28
-rw-r--r--source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c12
-rw-r--r--source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c36
-rw-r--r--source/blender/gpencil_modifiers/intern/lineart/lineart_ops.c4
15 files changed, 511 insertions, 70 deletions
diff --git a/source/blender/gpencil_modifiers/CMakeLists.txt b/source/blender/gpencil_modifiers/CMakeLists.txt
index afcd551d0af..5ee75619259 100644
--- a/source/blender/gpencil_modifiers/CMakeLists.txt
+++ b/source/blender/gpencil_modifiers/CMakeLists.txt
@@ -62,6 +62,7 @@ set(SRC
intern/MOD_gpencilnoise.c
intern/MOD_gpenciloffset.c
intern/MOD_gpencilopacity.c
+ intern/MOD_gpencilshrinkwrap.c
intern/MOD_gpencilsimplify.c
intern/MOD_gpencilsmooth.c
intern/MOD_gpencilsubdiv.c
diff --git a/source/blender/gpencil_modifiers/MOD_gpencil_lineart.h b/source/blender/gpencil_modifiers/MOD_gpencil_lineart.h
index 7d75ed5804e..95028ee959d 100644
--- a/source/blender/gpencil_modifiers/MOD_gpencil_lineart.h
+++ b/source/blender/gpencil_modifiers/MOD_gpencil_lineart.h
@@ -23,6 +23,7 @@
#include "DNA_windowmanager_types.h"
/* Operator types should be in exposed header. */
+
void OBJECT_OT_lineart_bake_strokes(struct wmOperatorType *ot);
void OBJECT_OT_lineart_bake_strokes_all(struct wmOperatorType *ot);
void OBJECT_OT_lineart_clear(struct wmOperatorType *ot);
diff --git a/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h b/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h
index d9285f44a37..56cee115760 100644
--- a/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h
+++ b/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h
@@ -48,6 +48,7 @@ extern GpencilModifierTypeInfo modifierType_Gpencil_WeightProximity;
extern GpencilModifierTypeInfo modifierType_Gpencil_WeightAngle;
extern GpencilModifierTypeInfo modifierType_Gpencil_Lineart;
extern GpencilModifierTypeInfo modifierType_Gpencil_Dash;
+extern GpencilModifierTypeInfo modifierType_Gpencil_Shrinkwrap;
/* MOD_gpencil_util.c */
void gpencil_modifier_type_init(GpencilModifierTypeInfo *types[]);
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.c b/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.c
index 2e241ea5848..fe78a7e7bcc 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.c
@@ -203,9 +203,6 @@ void gpencil_modifier_curve_panel_draw(const bContext *UNUSED(C), Panel *panel)
uiTemplateCurveMapping(layout, ptr, "curve", 0, false, false, false, false);
}
-/**
- * Draw modifier error message.
- */
void gpencil_modifier_panel_end(uiLayout *layout, PointerRNA *ptr)
{
GpencilModifierData *md = ptr->data;
@@ -232,7 +229,7 @@ PointerRNA *gpencil_modifier_panel_get_property_pointers(Panel *panel, PointerRN
UI_block_lock_clear(block);
UI_block_lock_set(block, ID_IS_LINKED((Object *)ptr->owner_id), ERROR_LIBDATA_MESSAGE);
- uiLayoutSetContextPointer(panel->layout, "modifier", ptr);
+ UI_panel_context_pointer_set(panel, "modifier", ptr);
return ptr;
}
@@ -312,7 +309,7 @@ static void gpencil_modifier_panel_header(const bContext *UNUSED(C), Panel *pane
PointerRNA *ptr = UI_panel_custom_data_get(panel);
GpencilModifierData *md = (GpencilModifierData *)ptr->data;
- uiLayoutSetContextPointer(panel->layout, "modifier", ptr);
+ UI_panel_context_pointer_set(panel, "modifier", ptr);
const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type);
bool narrow_panel = (panel->sizex < UI_UNIT_X * 9 && panel->sizex != 0);
@@ -360,9 +357,6 @@ static void gpencil_modifier_panel_header(const bContext *UNUSED(C), Panel *pane
/** \name Modifier Registration Helpers
* \{ */
-/**
- * Create a panel in the context's region
- */
PanelType *gpencil_modifier_panel_register(ARegionType *region_type,
GpencilModifierType type,
PanelDrawFn draw)
@@ -390,12 +384,6 @@ PanelType *gpencil_modifier_panel_register(ARegionType *region_type,
return panel_type;
}
-/**
- * Add a child panel to the parent.
- *
- * \note To create the panel type's idname, it appends the \a name argument to the \a parent's
- * idname.
- */
PanelType *gpencil_modifier_subpanel_register(ARegionType *region_type,
const char *name,
const char *label,
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.h b/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.h
index 782b36d47ed..2cccd6e15dd 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.h
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.h
@@ -37,15 +37,27 @@ void gpencil_modifier_masking_panel_draw(Panel *panel, bool use_material, bool u
void gpencil_modifier_curve_header_draw(const bContext *C, Panel *panel);
void gpencil_modifier_curve_panel_draw(const bContext *C, Panel *panel);
+/**
+ * Draw modifier error message.
+ */
void gpencil_modifier_panel_end(struct uiLayout *layout, PointerRNA *ptr);
struct PointerRNA *gpencil_modifier_panel_get_property_pointers(struct Panel *panel,
struct PointerRNA *r_ob_ptr);
+/**
+ * Create a panel in the context's region
+ */
PanelType *gpencil_modifier_panel_register(struct ARegionType *region_type,
GpencilModifierType type,
PanelDrawFn draw);
+/**
+ * Add a child panel to the parent.
+ *
+ * \note To create the panel type's idname, it appends the \a name argument to the \a parent's
+ * idname.
+ */
struct PanelType *gpencil_modifier_subpanel_register(struct ARegionType *region_type,
const char *name,
const char *label,
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
index 9ea146c77f2..f6a85919de4 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
@@ -67,10 +67,10 @@ void gpencil_modifier_type_init(GpencilModifierTypeInfo *types[])
INIT_GP_TYPE(WeightProximity);
INIT_GP_TYPE(Lineart);
INIT_GP_TYPE(Dash);
+ INIT_GP_TYPE(Shrinkwrap);
#undef INIT_GP_TYPE
}
-/* verify if valid layer, material and pass index */
bool is_stroke_affected_by_modifier(Object *ob,
char *mlayername,
const Material *material,
@@ -147,7 +147,6 @@ bool is_stroke_affected_by_modifier(Object *ob,
return true;
}
-/* verify if valid vertex group *and return weight */
float get_modifier_point_weight(MDeformVert *dvert, bool inverse, int def_nr)
{
float weight = 1.0f;
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h
index 2878ad4c73a..59ed11a02f3 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h
@@ -29,6 +29,9 @@ struct Object;
struct bGPDlayer;
struct bGPDstroke;
+/**
+ * Verify if valid layer, material and pass index.
+ */
bool is_stroke_affected_by_modifier(struct Object *ob,
char *mlayername,
const struct Material *material,
@@ -42,4 +45,7 @@ bool is_stroke_affected_by_modifier(struct Object *ob,
const bool inv3,
const bool inv4);
+/**
+ * Verify if valid vertex group *and return weight.
+ */
float get_modifier_point_weight(struct MDeformVert *dvert, bool inverse, int def_nr);
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencildash.c b/source/blender/gpencil_modifiers/intern/MOD_gpencildash.c
index 7d2eb4b2c75..6a4d0de5c80 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencildash.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencildash.c
@@ -313,8 +313,6 @@ static void panel_draw(const bContext *C, Panel *panel)
UI_TEMPLATE_LIST_FLAG_NONE);
uiLayout *col = uiLayoutColumn(row, false);
- uiLayoutSetContextPointer(col, "modifier", ptr);
-
uiLayout *sub = uiLayoutColumn(col, true);
uiItemO(sub, "", ICON_ADD, "GPENCIL_OT_segment_add");
uiItemO(sub, "", ICON_REMOVE, "GPENCIL_OT_segment_remove");
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/gpencil_modifiers/intern/MOD_gpencilshrinkwrap.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilshrinkwrap.c
new file mode 100644
index 00000000000..6990b41e6ce
--- /dev/null
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilshrinkwrap.c
@@ -0,0 +1,350 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2017, Blender Foundation
+ * This is a new part of Blender
+ */
+
+/** \file
+ * \ingroup modifiers
+ */
+
+#include <stdio.h>
+#include <string.h> /* For #MEMCPY_STRUCT_AFTER. */
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "BLT_translation.h"
+
+#include "DNA_defaults.h"
+#include "DNA_gpencil_modifier_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+
+#include "BKE_context.h"
+#include "BKE_deform.h"
+#include "BKE_gpencil_geom.h"
+#include "BKE_gpencil_modifier.h"
+#include "BKE_lib_query.h"
+#include "BKE_main.h"
+#include "BKE_modifier.h"
+#include "BKE_scene.h"
+#include "BKE_screen.h"
+#include "BKE_shrinkwrap.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "RNA_access.h"
+
+#include "MOD_gpencil_modifiertypes.h"
+#include "MOD_gpencil_ui_common.h"
+#include "MOD_gpencil_util.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
+
+static void initData(GpencilModifierData *md)
+{
+ ShrinkwrapGpencilModifierData *gpmd = (ShrinkwrapGpencilModifierData *)md;
+
+ BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(gpmd, modifier));
+
+ MEMCPY_STRUCT_AFTER(gpmd, DNA_struct_default_get(ShrinkwrapGpencilModifierData), modifier);
+}
+
+static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
+{
+ BKE_gpencil_modifier_copydata_generic(md, target);
+}
+
+static void deformStroke(GpencilModifierData *md,
+ Depsgraph *UNUSED(depsgraph),
+ Object *ob,
+ bGPDlayer *gpl,
+ bGPDframe *UNUSED(gpf),
+ bGPDstroke *gps)
+{
+ bGPdata *gpd = ob->data;
+ ShrinkwrapGpencilModifierData *mmd = (ShrinkwrapGpencilModifierData *)md;
+ const int def_nr = BKE_object_defgroup_name_index(ob, mmd->vgname);
+
+ if (!is_stroke_affected_by_modifier(ob,
+ mmd->layername,
+ mmd->material,
+ mmd->pass_index,
+ mmd->layer_pass,
+ 1,
+ gpl,
+ gps,
+ mmd->flag & GP_SHRINKWRAP_INVERT_LAYER,
+ mmd->flag & GP_SHRINKWRAP_INVERT_PASS,
+ mmd->flag & GP_SHRINKWRAP_INVERT_LAYERPASS,
+ mmd->flag & GP_SHRINKWRAP_INVERT_MATERIAL)) {
+ return;
+ }
+
+ if ((mmd->cache_data == NULL) || (mmd->target == ob) || (mmd->aux_target == ob)) {
+ return;
+ }
+
+ bGPDspoint *pt = gps->points;
+ float(*vert_coords)[3] = MEM_mallocN(sizeof(float[3]) * gps->totpoints, __func__);
+ int i;
+ /* Prepare array of points. */
+ for (i = 0; i < gps->totpoints; i++, pt++) {
+ copy_v3_v3(vert_coords[i], &pt->x);
+ }
+
+ shrinkwrapGpencilModifier_deform(mmd, ob, gps->dvert, def_nr, vert_coords, gps->totpoints);
+
+ /* Apply deformed coordinates. */
+ pt = gps->points;
+ for (i = 0; i < gps->totpoints; i++, pt++) {
+ copy_v3_v3(&pt->x, vert_coords[i]);
+ /* Smooth stroke. */
+ if (mmd->smooth_factor > 0.0f) {
+ for (int r = 0; r < mmd->smooth_step; r++) {
+ BKE_gpencil_stroke_smooth_point(gps, i, mmd->smooth_factor, true);
+ }
+ }
+ }
+
+ MEM_freeN(vert_coords);
+
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gpd, gps);
+}
+
+static void bakeModifier(Main *UNUSED(bmain),
+ Depsgraph *depsgraph,
+ GpencilModifierData *md,
+ Object *ob)
+{
+ ShrinkwrapGpencilModifierData *mmd = (ShrinkwrapGpencilModifierData *)md;
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ bGPdata *gpd = ob->data;
+ int oldframe = (int)DEG_get_ctime(depsgraph);
+
+ if ((mmd->target == ob) || (mmd->aux_target == ob)) {
+ return;
+ }
+
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ /* Apply shrinkwrap effects on this frame. */
+ CFRA = gpf->framenum;
+ BKE_scene_graph_update_for_newframe(depsgraph);
+
+ /* Recalculate shrinkwrap data. */
+ if (mmd->cache_data) {
+ BKE_shrinkwrap_free_tree(mmd->cache_data);
+ MEM_SAFE_FREE(mmd->cache_data);
+ }
+ Object *ob_target = DEG_get_evaluated_object(depsgraph, mmd->target);
+ Mesh *target = BKE_modifier_get_evaluated_mesh_from_evaluated_object(ob_target, false);
+ mmd->cache_data = MEM_callocN(sizeof(ShrinkwrapTreeData), __func__);
+ if (BKE_shrinkwrap_init_tree(
+ mmd->cache_data, target, mmd->shrink_type, mmd->shrink_mode, false)) {
+
+ /* Compute shrinkwrap effects on this frame. */
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ deformStroke(md, depsgraph, ob, gpl, gpf, gps);
+ }
+ }
+ /* Free data. */
+ if (mmd->cache_data) {
+ BKE_shrinkwrap_free_tree(mmd->cache_data);
+ MEM_SAFE_FREE(mmd->cache_data);
+ }
+ }
+ }
+
+ /* Return frame state and DB to original state. */
+ CFRA = oldframe;
+ BKE_scene_graph_update_for_newframe(depsgraph);
+}
+
+static void freeData(GpencilModifierData *md)
+{
+ ShrinkwrapGpencilModifierData *mmd = (ShrinkwrapGpencilModifierData *)md;
+ if (mmd->cache_data) {
+ BKE_shrinkwrap_free_tree(mmd->cache_data);
+ MEM_SAFE_FREE(mmd->cache_data);
+ }
+}
+
+static bool isDisabled(GpencilModifierData *md, int UNUSED(userRenderParams))
+{
+ ShrinkwrapGpencilModifierData *mmd = (ShrinkwrapGpencilModifierData *)md;
+
+ /* The object type check is only needed here in case we have a placeholder
+ * object assigned (because the library containing the mesh is missing).
+ *
+ * In other cases it should be impossible to have a type mismatch.
+ */
+ if (!mmd->target || mmd->target->type != OB_MESH) {
+ return true;
+ }
+ if (mmd->aux_target && mmd->aux_target->type != OB_MESH) {
+ return true;
+ }
+ return false;
+}
+
+static void updateDepsgraph(GpencilModifierData *md,
+ const ModifierUpdateDepsgraphContext *ctx,
+ const int UNUSED(mode))
+{
+ ShrinkwrapGpencilModifierData *mmd = (ShrinkwrapGpencilModifierData *)md;
+ CustomData_MeshMasks mask = {0};
+
+ if (BKE_shrinkwrap_needs_normals(mmd->shrink_type, mmd->shrink_mode)) {
+ mask.vmask |= CD_MASK_NORMAL;
+ mask.lmask |= CD_MASK_NORMAL | CD_MASK_CUSTOMLOOPNORMAL;
+ }
+
+ if (mmd->target != NULL) {
+ DEG_add_object_relation(ctx->node, mmd->target, DEG_OB_COMP_TRANSFORM, "Shrinkwrap Modifier");
+ DEG_add_object_relation(ctx->node, mmd->target, DEG_OB_COMP_GEOMETRY, "Shrinkwrap Modifier");
+ DEG_add_customdata_mask(ctx->node, mmd->target, &mask);
+ if (mmd->shrink_type == MOD_SHRINKWRAP_TARGET_PROJECT) {
+ DEG_add_special_eval_flag(ctx->node, &mmd->target->id, DAG_EVAL_NEED_SHRINKWRAP_BOUNDARY);
+ }
+ }
+ if (mmd->aux_target != NULL) {
+ DEG_add_object_relation(
+ ctx->node, mmd->aux_target, DEG_OB_COMP_TRANSFORM, "Shrinkwrap Modifier");
+ DEG_add_object_relation(
+ ctx->node, mmd->aux_target, DEG_OB_COMP_GEOMETRY, "Shrinkwrap Modifier");
+ DEG_add_customdata_mask(ctx->node, mmd->aux_target, &mask);
+ if (mmd->shrink_type == MOD_SHRINKWRAP_TARGET_PROJECT) {
+ DEG_add_special_eval_flag(
+ ctx->node, &mmd->aux_target->id, DAG_EVAL_NEED_SHRINKWRAP_BOUNDARY);
+ }
+ }
+ DEG_add_modifier_to_transform_relation(ctx->node, "Shrinkwrap Modifier");
+}
+
+static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
+{
+ ShrinkwrapGpencilModifierData *mmd = (ShrinkwrapGpencilModifierData *)md;
+
+ walk(userData, ob, (ID **)&mmd->target, IDWALK_CB_NOP);
+ walk(userData, ob, (ID **)&mmd->aux_target, IDWALK_CB_NOP);
+ walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER);
+}
+
+static void panel_draw(const bContext *UNUSED(C), Panel *panel)
+{
+ uiLayout *row, *col;
+ uiLayout *layout = panel->layout;
+ int toggles_flag = UI_ITEM_R_TOGGLE | UI_ITEM_R_FORCE_BLANK_DECORATE;
+
+ PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL);
+
+ uiLayoutSetPropSep(layout, true);
+
+ int wrap_method = RNA_enum_get(ptr, "wrap_method");
+
+ uiItemR(layout, ptr, "wrap_method", 0, NULL, ICON_NONE);
+
+ if (ELEM(wrap_method,
+ MOD_SHRINKWRAP_PROJECT,
+ MOD_SHRINKWRAP_NEAREST_SURFACE,
+ MOD_SHRINKWRAP_TARGET_PROJECT)) {
+ uiItemR(layout, ptr, "wrap_mode", 0, NULL, ICON_NONE);
+ }
+
+ if (wrap_method == MOD_SHRINKWRAP_PROJECT) {
+ uiItemR(layout, ptr, "project_limit", 0, IFACE_("Limit"), ICON_NONE);
+ uiItemR(layout, ptr, "subsurf_levels", 0, NULL, ICON_NONE);
+
+ col = uiLayoutColumn(layout, false);
+ row = uiLayoutRowWithHeading(col, true, IFACE_("Axis"));
+ uiItemR(row, ptr, "use_project_x", toggles_flag, NULL, ICON_NONE);
+ uiItemR(row, ptr, "use_project_y", toggles_flag, NULL, ICON_NONE);
+ uiItemR(row, ptr, "use_project_z", toggles_flag, NULL, ICON_NONE);
+
+ uiItemR(col, ptr, "use_negative_direction", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "use_positive_direction", 0, NULL, ICON_NONE);
+
+ uiItemR(layout, ptr, "cull_face", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ col = uiLayoutColumn(layout, false);
+ uiLayoutSetActive(col,
+ RNA_boolean_get(ptr, "use_negative_direction") &&
+ RNA_enum_get(ptr, "cull_face") != 0);
+ uiItemR(col, ptr, "use_invert_cull", 0, NULL, ICON_NONE);
+ }
+
+ uiItemR(layout, ptr, "target", 0, NULL, ICON_NONE);
+ if (wrap_method == MOD_SHRINKWRAP_PROJECT) {
+ uiItemR(layout, ptr, "auxiliary_target", 0, NULL, ICON_NONE);
+ }
+ uiItemR(layout, ptr, "offset", 0, NULL, ICON_NONE);
+
+ uiLayoutSetPropSep(layout, true);
+
+ uiItemR(layout, ptr, "smooth_factor", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "smooth_step", 0, IFACE_("Repeat"), ICON_NONE);
+
+ gpencil_modifier_panel_end(layout, ptr);
+}
+
+static void mask_panel_draw(const bContext *UNUSED(C), Panel *panel)
+{
+ gpencil_modifier_masking_panel_draw(panel, true, true);
+}
+
+static void panelRegister(ARegionType *region_type)
+{
+ PanelType *panel_type = gpencil_modifier_panel_register(
+ region_type, eGpencilModifierType_Shrinkwrap, panel_draw);
+ gpencil_modifier_subpanel_register(
+ region_type, "mask", "Influence", NULL, mask_panel_draw, panel_type);
+}
+
+GpencilModifierTypeInfo modifierType_Gpencil_Shrinkwrap = {
+ /* name */ "Shrinkwrap",
+ /* structName */ "ShrinkwrapGpencilModifierData",
+ /* structSize */ sizeof(ShrinkwrapGpencilModifierData),
+ /* type */ eGpencilModifierTypeType_Gpencil,
+ /* flags */ eGpencilModifierTypeFlag_SupportsEditmode,
+
+ /* copyData */ copyData,
+
+ /* deformStroke */ deformStroke,
+ /* generateStrokes */ NULL,
+ /* bakeModifier */ bakeModifier,
+ /* remapTime */ NULL,
+
+ /* initData */ initData,
+ /* freeData */ freeData,
+ /* isDisabled */ isDisabled,
+ /* updateDepsgraph */ updateDepsgraph,
+ /* dependsOnTime */ NULL,
+ /* foreachIDLink */ foreachIDLink,
+ /* foreachTexLink */ NULL,
+ /* panelRegister */ panelRegister,
+};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c
index b00db1ba2d2..a63cbb53645 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c
@@ -132,7 +132,7 @@ static void deformStroke(GpencilModifierData *md,
const float val = mmd->factor * weight;
/* perform smoothing */
if (mmd->flag & GP_SMOOTH_MOD_LOCATION) {
- BKE_gpencil_stroke_smooth_point(gps, i, val);
+ BKE_gpencil_stroke_smooth_point(gps, i, val, false);
}
if (mmd->flag & GP_SMOOTH_MOD_STRENGTH) {
BKE_gpencil_stroke_smooth_strength(gps, i, val);
diff --git a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
index 869f93f832e..2ef72da03fd 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
+++ b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
@@ -485,7 +485,7 @@ typedef struct LineartBoundingArea {
(((a) + DBL_TRIANGLE_LIM) >= (b) && ((a)-DBL_TRIANGLE_LIM) <= (b))
/* Notes on this function:
-
+ *
* r_ratio: The ratio on segment a1-a2. When r_ratio is very close to zero or one, it
* fixes the value to zero or one, this makes it easier to identify "on the tip" situations.
*
@@ -649,9 +649,18 @@ void MOD_lineart_destroy_render_data(struct LineartGpencilModifierData *lmd);
void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb);
void MOD_lineart_chain_split_for_fixed_occlusion(LineartRenderBuffer *rb);
+/**
+ * This function only connects two different chains. It will not do any clean up or smart chaining.
+ * So no: removing overlapping chains, removal of short isolated segments, and no loop reduction is
+ * implemented yet.
+ */
void MOD_lineart_chain_connect(LineartRenderBuffer *rb);
void MOD_lineart_chain_discard_short(LineartRenderBuffer *rb, const float threshold);
void MOD_lineart_chain_clip_at_border(LineartRenderBuffer *rb);
+/**
+ * This should always be the last stage!, see the end of
+ * #MOD_lineart_chain_split_for_fixed_occlusion().
+ */
void MOD_lineart_chain_split_angle(LineartRenderBuffer *rb, float angle_threshold_rad);
void MOD_lineart_smooth_chains(LineartRenderBuffer *rb, float tolerance);
void MOD_lineart_chain_offset_towards_camera(LineartRenderBuffer *rb,
@@ -661,6 +670,11 @@ void MOD_lineart_chain_offset_towards_camera(LineartRenderBuffer *rb,
int MOD_lineart_chain_count(const LineartEdgeChain *ec);
void MOD_lineart_chain_clear_picked_flag(LineartCache *lc);
+/**
+ * This is the entry point of all line art calculations.
+ *
+ * \return True when a change is made.
+ */
bool MOD_lineart_compute_feature_lines(struct Depsgraph *depsgraph,
struct LineartGpencilModifierData *lmd,
struct LineartCache **cached_result,
@@ -668,15 +682,24 @@ bool MOD_lineart_compute_feature_lines(struct Depsgraph *depsgraph,
struct Scene;
+/**
+ * This only gets initial "biggest" tile.
+ */
LineartBoundingArea *MOD_lineart_get_parent_bounding_area(LineartRenderBuffer *rb,
double x,
double y);
+/**
+ * Wrapper for more convenience.
+ */
LineartBoundingArea *MOD_lineart_get_bounding_area(LineartRenderBuffer *rb, double x, double y);
struct bGPDframe;
struct bGPDlayer;
+/**
+ * Wrapper for external calls.
+ */
void MOD_lineart_gpencil_generate(LineartCache *cache,
struct Depsgraph *depsgraph,
struct Object *ob,
@@ -697,6 +720,9 @@ void MOD_lineart_gpencil_generate(LineartCache *cache,
const char *vgname,
int modifier_flags);
+/**
+ * Length is in image space.
+ */
float MOD_lineart_chain_compute_length(LineartEdgeChain *ec);
void ED_operatortypes_lineart(void);
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c
index 88dcfb89c25..0deb8b1c335 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c
@@ -794,11 +794,6 @@ static LineartChainRegisterEntry *lineart_chain_get_closest_cre(LineartRenderBuf
return closest_cre;
}
-/**
- * This function only connects two different chains. It will not do any clean up or smart chaining.
- * So no: removing overlapping chains, removal of short isolated segments, and no loop reduction is
- * implemented yet.
- */
void MOD_lineart_chain_connect(LineartRenderBuffer *rb)
{
LineartEdgeChain *ec;
@@ -881,9 +876,6 @@ void MOD_lineart_chain_connect(LineartRenderBuffer *rb)
}
}
-/**
- * Length is in image space.
- */
float MOD_lineart_chain_compute_length(LineartEdgeChain *ec)
{
LineartEdgeChainItem *eci;
@@ -1072,10 +1064,6 @@ void MOD_lineart_chain_clip_at_border(LineartRenderBuffer *rb)
}
}
-/**
- * This should always be the last stage!, see the end of
- * #MOD_lineart_chain_split_for_fixed_occlusion().
- */
void MOD_lineart_chain_split_angle(LineartRenderBuffer *rb, float angle_threshold_rad)
{
LineartEdgeChain *ec, *new_ec;
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
index 88d717eb032..d9a32711833 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
@@ -502,10 +502,6 @@ static void lineart_main_occlusion_begin(LineartRenderBuffer *rb)
rb->edge_mark.last = rb->edge_mark.first;
rb->floating.last = rb->floating.first;
- /* This is needed because the occlusion function expects the camera vector to point towards the
- * camera. */
- negate_v3_db(rb->view_vector);
-
TaskPool *tp = BLI_task_pool_create(NULL, TASK_PRIORITY_HIGH);
for (i = 0; i < thread_count; i++) {
@@ -579,9 +575,7 @@ static int lineart_point_on_line_segment(double v[2], double v0[2], double v1[2]
c2 = ratiod(v0[1], v1[1], v[1]);
return (c2 >= -DBL_TRIANGLE_LIM && c2 <= 1 + DBL_TRIANGLE_LIM);
}
- else {
- return false;
- }
+ return false;
}
if (!LRT_DOUBLE_CLOSE_ENOUGH(v1[1], v0[1])) {
@@ -592,9 +586,7 @@ static int lineart_point_on_line_segment(double v[2], double v0[2], double v1[2]
c1 = ratiod(v0[0], v1[0], v[0]);
return (c1 >= -DBL_TRIANGLE_LIM && c1 <= 1 + DBL_TRIANGLE_LIM);
}
- else {
- return false;
- }
+ return false;
}
if (LRT_DOUBLE_CLOSE_ENOUGH(c1, c2) && c1 >= 0 && c1 <= 1) {
@@ -2336,9 +2328,9 @@ static bool lineart_edge_from_triangle(const LineartTriangle *tri,
* if returns true, then from/to will carry the occluded segments
* in ratio from `e->v1` to `e->v2`. The line is later cut with these two values.
*
- * TODO: (Yiming) This function uses a convoluted method that needs to be redesigned.
+ * TODO(@Yiming): This function uses a convoluted method that needs to be redesigned.
*
- * 1) The lineart_intersect_seg_seg() and lineart_point_triangle_relation() are separate calls,
+ * 1) The #lineart_intersect_seg_seg() and #lineart_point_triangle_relation() are separate calls,
* which would potentially return results that doesn't agree, especially when it's an edge
* extruding from one of the triangle's point. To get the information using one math process can
* solve this problem.
@@ -2350,7 +2342,7 @@ static bool lineart_edge_from_triangle(const LineartTriangle *tri,
* I keep this function as-is because it's still fast, and more importantly the output value
* threshold is already in tune with the cutting function in the next stage.
* While current "edge aligned" fix isn't ideal, it does solve most of the precision issue
- * especially in ortho camera mode.
+ * especially in orthographic camera mode.
*/
static bool lineart_triangle_edge_image_space_occlusion(SpinLock *UNUSED(spl),
const LineartTriangle *tri,
@@ -3010,7 +3002,7 @@ static void lineart_triangle_intersect_in_bounding_area(LineartRenderBuffer *rb,
*/
static void lineart_main_get_view_vector(LineartRenderBuffer *rb)
{
- float direction[3] = {0, 0, -1};
+ float direction[3] = {0, 0, 1};
float trans[3];
float inv[4][4];
float obmat_no_scale[4][4];
@@ -3767,9 +3759,6 @@ static bool lineart_get_edge_bounding_areas(LineartRenderBuffer *rb,
return true;
}
-/**
- * This only gets initial "biggest" tile.
- */
LineartBoundingArea *MOD_lineart_get_parent_bounding_area(LineartRenderBuffer *rb,
double x,
double y)
@@ -3841,9 +3830,6 @@ static LineartBoundingArea *lineart_get_bounding_area(LineartRenderBuffer *rb, d
return iba;
}
-/**
- * Wrapper for more convenience.
- */
LineartBoundingArea *MOD_lineart_get_bounding_area(LineartRenderBuffer *rb, double x, double y)
{
LineartBoundingArea *ba;
@@ -4149,11 +4135,6 @@ static LineartBoundingArea *lineart_bounding_area_next(LineartBoundingArea *this
return 0;
}
-/**
- * This is the entry point of all line art calculations.
- *
- * \return True when a change is made.
- */
bool MOD_lineart_compute_feature_lines(Depsgraph *depsgraph,
LineartGpencilModifierData *lmd,
LineartCache **cached_result,
@@ -4398,7 +4379,7 @@ static void lineart_gpencil_generate(LineartCache *cache,
}
}
}
- if (types & LRT_EDGE_FLAG_INTERSECTION) {
+ if (ec->type & LRT_EDGE_FLAG_INTERSECTION) {
if (mask_switches & LRT_GPENCIL_INTERSECTION_MATCH) {
if (ec->intersection_mask != intersection_mask) {
continue;
@@ -4481,9 +4462,6 @@ static void lineart_gpencil_generate(LineartCache *cache,
}
}
-/**
- * Wrapper for external calls.
- */
void MOD_lineart_gpencil_generate(LineartCache *cache,
Depsgraph *depsgraph,
Object *ob,
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_ops.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_ops.c
index b74499daf6b..c53404a87e2 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/lineart_ops.c
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_ops.c
@@ -444,7 +444,6 @@ static int lineart_gpencil_clear_strokes_all_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-/* Bake all line art modifiers on the current object. */
void OBJECT_OT_lineart_bake_strokes(wmOperatorType *ot)
{
ot->name = "Bake Line Art";
@@ -456,7 +455,6 @@ void OBJECT_OT_lineart_bake_strokes(wmOperatorType *ot)
ot->modal = lineart_gpencil_bake_strokes_commom_modal;
}
-/* Bake all lineart objects in the scene. */
void OBJECT_OT_lineart_bake_strokes_all(wmOperatorType *ot)
{
ot->name = "Bake Line Art (All)";
@@ -468,7 +466,6 @@ void OBJECT_OT_lineart_bake_strokes_all(wmOperatorType *ot)
ot->modal = lineart_gpencil_bake_strokes_commom_modal;
}
-/* clear all line art modifiers on the current object. */
void OBJECT_OT_lineart_clear(wmOperatorType *ot)
{
ot->name = "Clear Baked Line Art";
@@ -478,7 +475,6 @@ void OBJECT_OT_lineart_clear(wmOperatorType *ot)
ot->exec = lineart_gpencil_clear_strokes_exec;
}
-/* clear all lineart objects in the scene. */
void OBJECT_OT_lineart_clear_all(wmOperatorType *ot)
{
ot->name = "Clear Baked Line Art (All)";