diff options
Diffstat (limited to 'source/blender/gpencil_modifiers')
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)"; |