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>2021-12-13 19:09:22 +0300
committerAntonio Vazquez <blendergit@gmail.com>2021-12-13 19:09:22 +0300
commit459af75d1ed586f08cd43e2aec7a3b270e809132 (patch)
treec7dbbe0be774f5a6fc2fb89630b2a00dd2adf0e5 /source/blender/gpencil_modifiers
parent49802af7cd920d83f2c1805f4047d91842c76311 (diff)
GPencil: New Shrinkwrap modifier
his new modifier is equals to the existing mesh modifier but adapted to grease pencil. The underlying functions used to calculate the shrink are the same used in meshes. {F11794101} Reviewed By: pepeland, HooglyBoogly Differential Revision: https://developer.blender.org/D13192
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_modifiertypes.h1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilshrinkwrap.c350
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c2
5 files changed, 354 insertions, 1 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_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_util.c b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
index d3088c68af5..f6a85919de4 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
@@ -67,6 +67,7 @@ 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
}
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);