Compare commits
22 Commits
temp-geome
...
lineart-fn
Author | SHA1 | Date | |
---|---|---|---|
3dfda41c46 | |||
fad1d746c8 | |||
27f38bae5e | |||
5fe915d141 | |||
089ea73abf | |||
0203b35272 | |||
9870984c79 | |||
59e82df127 | |||
e3e8227b19 | |||
4e84a49218 | |||
f9568c4c1f | |||
02d1a1bfcc | |||
fc6a6d3a28 | |||
fe9ab6281d | |||
862f86e3b3 | |||
e6d1424f21 | |||
7c979ad568 | |||
e06e13a56e | |||
4cdb056036 | |||
13861121b1 | |||
62ca6d46d3 | |||
c224ca3689 |
@@ -294,6 +294,20 @@ bool BKE_gpencil_has_geometry_modifiers(struct Object *ob);
|
|||||||
bool BKE_gpencil_has_time_modifiers(struct Object *ob);
|
bool BKE_gpencil_has_time_modifiers(struct Object *ob);
|
||||||
bool BKE_gpencil_has_transform_modifiers(struct Object *ob);
|
bool BKE_gpencil_has_transform_modifiers(struct Object *ob);
|
||||||
|
|
||||||
|
typedef struct GpencilLineartLimitInfo {
|
||||||
|
char min_level;
|
||||||
|
char max_level;
|
||||||
|
short edge_types;
|
||||||
|
} GpencilLineartLimitInfo;
|
||||||
|
|
||||||
|
void BKE_gpencil_get_lineart_modifier_limits(struct Object *ob,
|
||||||
|
struct GpencilLineartLimitInfo *info);
|
||||||
|
|
||||||
|
void BKE_gpencil_set_lineart_modifier_limits(struct GpencilModifierData *md,
|
||||||
|
struct GpencilLineartLimitInfo *info,
|
||||||
|
bool is_first_lineart);
|
||||||
|
bool BKE_gpencil_is_first_lineart_in_stack(struct Object *ob, struct GpencilModifierData *md);
|
||||||
|
|
||||||
void BKE_gpencil_lattice_init(struct Object *ob);
|
void BKE_gpencil_lattice_init(struct Object *ob);
|
||||||
void BKE_gpencil_lattice_clear(struct Object *ob);
|
void BKE_gpencil_lattice_clear(struct Object *ob);
|
||||||
|
|
||||||
|
@@ -55,6 +55,7 @@
|
|||||||
#include "DEG_depsgraph.h"
|
#include "DEG_depsgraph.h"
|
||||||
#include "DEG_depsgraph_query.h"
|
#include "DEG_depsgraph_query.h"
|
||||||
|
|
||||||
|
#include "MOD_gpencil_lineart.h"
|
||||||
#include "MOD_gpencil_modifiertypes.h"
|
#include "MOD_gpencil_modifiertypes.h"
|
||||||
|
|
||||||
#include "BLO_read_write.h"
|
#include "BLO_read_write.h"
|
||||||
@@ -202,6 +203,58 @@ bool BKE_gpencil_has_transform_modifiers(Object *ob)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BKE_gpencil_get_lineart_modifier_limits(Object *ob, struct GpencilLineartLimitInfo *info)
|
||||||
|
{
|
||||||
|
bool is_first = true;
|
||||||
|
LISTBASE_FOREACH (GpencilModifierData *, md, &ob->greasepencil_modifiers) {
|
||||||
|
if (md->type == eGpencilModifierType_Lineart) {
|
||||||
|
LineartGpencilModifierData *lmd = (LineartGpencilModifierData *)md;
|
||||||
|
if (is_first || (lmd->flags & LRT_GPENCIL_USE_CACHE)) {
|
||||||
|
info->min_level = MIN2(info->min_level, lmd->level_start);
|
||||||
|
info->max_level = MAX2(info->max_level,
|
||||||
|
(lmd->use_multiple_levels ? lmd->level_end : lmd->level_start));
|
||||||
|
info->edge_types |= lmd->edge_types;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BKE_gpencil_set_lineart_modifier_limits(GpencilModifierData *md,
|
||||||
|
struct GpencilLineartLimitInfo *info,
|
||||||
|
bool is_first_lineart)
|
||||||
|
{
|
||||||
|
BLI_assert(md->type == eGpencilModifierType_Lineart);
|
||||||
|
LineartGpencilModifierData *lmd = (LineartGpencilModifierData *)md;
|
||||||
|
if (is_first_lineart || lmd->flags & LRT_GPENCIL_USE_CACHE) {
|
||||||
|
lmd->level_start_override = info->min_level;
|
||||||
|
lmd->level_end_override = info->max_level;
|
||||||
|
lmd->edge_types_override = info->edge_types;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lmd->level_start_override = lmd->level_start;
|
||||||
|
lmd->level_end_override = lmd->level_end;
|
||||||
|
lmd->edge_types_override = lmd->edge_types;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BKE_gpencil_is_first_lineart_in_stack(Object *ob, GpencilModifierData *md)
|
||||||
|
{
|
||||||
|
if (md->type != eGpencilModifierType_Lineart) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
LISTBASE_FOREACH (GpencilModifierData *, gmd, &ob->greasepencil_modifiers) {
|
||||||
|
if (gmd->type == eGpencilModifierType_Lineart) {
|
||||||
|
if (gmd == md) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false; /* Unlikely. */
|
||||||
|
}
|
||||||
|
|
||||||
/* apply time modifiers */
|
/* apply time modifiers */
|
||||||
static int gpencil_time_modifier(
|
static int gpencil_time_modifier(
|
||||||
Depsgraph *depsgraph, Scene *scene, Object *ob, bGPDlayer *gpl, int cfra, bool is_render)
|
Depsgraph *depsgraph, Scene *scene, Object *ob, bGPDlayer *gpl, int cfra, bool is_render)
|
||||||
@@ -771,6 +824,9 @@ void BKE_gpencil_modifiers_calc(Depsgraph *depsgraph, Scene *scene, Object *ob)
|
|||||||
BKE_gpencil_lattice_init(ob);
|
BKE_gpencil_lattice_init(ob);
|
||||||
|
|
||||||
const bool time_remap = BKE_gpencil_has_time_modifiers(ob);
|
const bool time_remap = BKE_gpencil_has_time_modifiers(ob);
|
||||||
|
bool is_first_lineart = true;
|
||||||
|
GpencilLineartLimitInfo info = {0};
|
||||||
|
BKE_gpencil_get_lineart_modifier_limits(ob, &info);
|
||||||
|
|
||||||
LISTBASE_FOREACH (GpencilModifierData *, md, &ob->greasepencil_modifiers) {
|
LISTBASE_FOREACH (GpencilModifierData *, md, &ob->greasepencil_modifiers) {
|
||||||
|
|
||||||
@@ -781,6 +837,11 @@ void BKE_gpencil_modifiers_calc(Depsgraph *depsgraph, Scene *scene, Object *ob)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (md->type == eGpencilModifierType_Lineart) {
|
||||||
|
BKE_gpencil_set_lineart_modifier_limits(md, &info, is_first_lineart);
|
||||||
|
is_first_lineart = false;
|
||||||
|
}
|
||||||
|
|
||||||
/* Apply geometry modifiers (add new geometry). */
|
/* Apply geometry modifiers (add new geometry). */
|
||||||
if (mti && mti->generateStrokes) {
|
if (mti && mti->generateStrokes) {
|
||||||
mti->generateStrokes(md, depsgraph, ob);
|
mti->generateStrokes(md, depsgraph, ob);
|
||||||
@@ -806,6 +867,8 @@ void BKE_gpencil_modifiers_calc(Depsgraph *depsgraph, Scene *scene, Object *ob)
|
|||||||
|
|
||||||
/* Clear any lattice data. */
|
/* Clear any lattice data. */
|
||||||
BKE_gpencil_lattice_clear(ob);
|
BKE_gpencil_lattice_clear(ob);
|
||||||
|
|
||||||
|
MOD_lineart_clear_cache(&gpd->runtime.lineart_cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BKE_gpencil_modifier_blend_write(BlendWriter *writer, ListBase *modbase)
|
void BKE_gpencil_modifier_blend_write(BlendWriter *writer, ListBase *modbase)
|
||||||
|
@@ -29,3 +29,7 @@ void OBJECT_OT_lineart_clear(struct wmOperatorType *ot);
|
|||||||
void OBJECT_OT_lineart_clear_all(struct wmOperatorType *ot);
|
void OBJECT_OT_lineart_clear_all(struct wmOperatorType *ot);
|
||||||
|
|
||||||
void WM_operatortypes_lineart(void);
|
void WM_operatortypes_lineart(void);
|
||||||
|
|
||||||
|
struct LineartCache;
|
||||||
|
|
||||||
|
void MOD_lineart_clear_cache(struct LineartCache **lc);
|
||||||
|
@@ -38,6 +38,7 @@
|
|||||||
#include "DNA_scene_types.h"
|
#include "DNA_scene_types.h"
|
||||||
#include "DNA_screen_types.h"
|
#include "DNA_screen_types.h"
|
||||||
|
|
||||||
|
#include "MOD_gpencil_lineart.h"
|
||||||
#include "lineart/MOD_lineart.h"
|
#include "lineart/MOD_lineart.h"
|
||||||
|
|
||||||
#include "BKE_collection.h"
|
#include "BKE_collection.h"
|
||||||
@@ -88,7 +89,7 @@ static void generate_strokes_actual(
|
|||||||
}
|
}
|
||||||
|
|
||||||
MOD_lineart_gpencil_generate(
|
MOD_lineart_gpencil_generate(
|
||||||
lmd->render_buffer,
|
lmd->cache,
|
||||||
depsgraph,
|
depsgraph,
|
||||||
ob,
|
ob,
|
||||||
gpl,
|
gpl,
|
||||||
@@ -156,11 +157,31 @@ static void generateStrokes(GpencilModifierData *md, Depsgraph *depsgraph, Objec
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MOD_lineart_compute_feature_lines(depsgraph, lmd);
|
LineartCache *local_lc = gpd->runtime.lineart_cache;
|
||||||
|
if (!gpd->runtime.lineart_cache) {
|
||||||
|
MOD_lineart_compute_feature_lines(depsgraph, lmd, &gpd->runtime.lineart_cache);
|
||||||
|
MOD_lineart_destroy_render_data(lmd);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!(lmd->flags & LRT_GPENCIL_USE_CACHE)) {
|
||||||
|
MOD_lineart_compute_feature_lines(depsgraph, lmd, &local_lc);
|
||||||
|
MOD_lineart_destroy_render_data(lmd);
|
||||||
|
}
|
||||||
|
MOD_lineart_chain_clear_picked_flag(local_lc);
|
||||||
|
lmd->cache = local_lc;
|
||||||
|
}
|
||||||
|
|
||||||
generate_strokes_actual(md, depsgraph, ob, gpl, gpf);
|
generate_strokes_actual(md, depsgraph, ob, gpl, gpf);
|
||||||
|
|
||||||
MOD_lineart_destroy_render_data(lmd);
|
if (!(lmd->flags & LRT_GPENCIL_USE_CACHE)) {
|
||||||
|
/* Clear local cache. */
|
||||||
|
if (local_lc != gpd->runtime.lineart_cache) {
|
||||||
|
MOD_lineart_clear_cache(&local_lc);
|
||||||
|
}
|
||||||
|
/* Restore the original cache pointer so the modifiers below still have access to the "global"
|
||||||
|
* cache. */
|
||||||
|
lmd->cache = gpd->runtime.lineart_cache;
|
||||||
|
}
|
||||||
|
|
||||||
WM_main_add_notifier(NA_EDITED | NC_GPENCIL, NULL);
|
WM_main_add_notifier(NA_EDITED | NC_GPENCIL, NULL);
|
||||||
}
|
}
|
||||||
@@ -182,11 +203,12 @@ static void bakeModifier(Main *UNUSED(bmain),
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MOD_lineart_compute_feature_lines(depsgraph, lmd);
|
if (!gpd->runtime.lineart_cache) {
|
||||||
|
MOD_lineart_compute_feature_lines(depsgraph, lmd, &gpd->runtime.lineart_cache);
|
||||||
|
MOD_lineart_destroy_render_data(lmd);
|
||||||
|
}
|
||||||
|
|
||||||
generate_strokes_actual(md, depsgraph, ob, gpl, gpf);
|
generate_strokes_actual(md, depsgraph, ob, gpl, gpf);
|
||||||
|
|
||||||
MOD_lineart_destroy_render_data(lmd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isDisabled(GpencilModifierData *md, int UNUSED(userRenderParams))
|
static bool isDisabled(GpencilModifierData *md, int UNUSED(userRenderParams))
|
||||||
@@ -258,10 +280,16 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
|
|||||||
|
|
||||||
const int source_type = RNA_enum_get(ptr, "source_type");
|
const int source_type = RNA_enum_get(ptr, "source_type");
|
||||||
const bool is_baked = RNA_boolean_get(ptr, "is_baked");
|
const bool is_baked = RNA_boolean_get(ptr, "is_baked");
|
||||||
|
const bool use_cache = RNA_boolean_get(ptr, "use_cached_result");
|
||||||
|
const bool is_first = BKE_gpencil_is_first_lineart_in_stack(ob_ptr.data, ptr->data);
|
||||||
|
|
||||||
uiLayoutSetPropSep(layout, true);
|
uiLayoutSetPropSep(layout, true);
|
||||||
uiLayoutSetEnabled(layout, !is_baked);
|
uiLayoutSetEnabled(layout, !is_baked);
|
||||||
|
|
||||||
|
if (!BKE_gpencil_is_first_lineart_in_stack(ob_ptr.data, ptr->data)) {
|
||||||
|
uiItemR(layout, ptr, "use_cached_result", 0, NULL, ICON_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
uiItemR(layout, ptr, "source_type", 0, NULL, ICON_NONE);
|
uiItemR(layout, ptr, "source_type", 0, NULL, ICON_NONE);
|
||||||
|
|
||||||
if (source_type == LRT_SOURCE_OBJECT) {
|
if (source_type == LRT_SOURCE_OBJECT) {
|
||||||
@@ -280,12 +308,17 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
|
|||||||
uiItemR(col, ptr, "use_material", 0, IFACE_("Material Borders"), ICON_NONE);
|
uiItemR(col, ptr, "use_material", 0, IFACE_("Material Borders"), ICON_NONE);
|
||||||
uiItemR(col, ptr, "use_edge_mark", 0, IFACE_("Edge Marks"), ICON_NONE);
|
uiItemR(col, ptr, "use_edge_mark", 0, IFACE_("Edge Marks"), ICON_NONE);
|
||||||
uiItemR(col, ptr, "use_intersection", 0, IFACE_("Intersections"), ICON_NONE);
|
uiItemR(col, ptr, "use_intersection", 0, IFACE_("Intersections"), ICON_NONE);
|
||||||
uiItemR(col, ptr, "use_crease", 0, IFACE_("Crease"), ICON_NONE);
|
|
||||||
uiLayout *sub = uiLayoutRow(col, true);
|
|
||||||
uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_crease"));
|
|
||||||
uiLayoutSetPropSep(sub, true);
|
|
||||||
|
|
||||||
uiItemR(sub, ptr, "crease_threshold", UI_ITEM_R_SLIDER, " ", ICON_NONE);
|
uiLayout *sub = uiLayoutRowWithHeading(col, false, IFACE_("Crease"));
|
||||||
|
uiItemR(sub, ptr, "use_crease", 0, "", ICON_NONE);
|
||||||
|
uiLayout *entry = uiLayoutRow(sub, false);
|
||||||
|
uiLayoutSetActive(entry, RNA_boolean_get(ptr, "use_crease") || is_first);
|
||||||
|
if (use_cache && !is_first) {
|
||||||
|
uiItemL(entry, IFACE_("Angle Cached"), ICON_INFO);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
uiItemR(entry, ptr, "crease_threshold", UI_ITEM_R_SLIDER, " ", ICON_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
uiItemPointerR(layout, ptr, "target_layer", &obj_data_ptr, "layers", NULL, ICON_GREASEPENCIL);
|
uiItemPointerR(layout, ptr, "target_layer", &obj_data_ptr, "layers", NULL, ICON_GREASEPENCIL);
|
||||||
|
|
||||||
@@ -308,14 +341,33 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
|
|||||||
NULL,
|
NULL,
|
||||||
material_valid ? ICON_SHADING_TEXTURE : ICON_ERROR);
|
material_valid ? ICON_SHADING_TEXTURE : ICON_ERROR);
|
||||||
|
|
||||||
uiItemR(layout, ptr, "use_remove_doubles", 0, NULL, ICON_NONE);
|
|
||||||
uiItemR(layout, ptr, "use_edge_overlap", 0, IFACE_("Overlapping Edges As Contour"), ICON_NONE);
|
|
||||||
uiItemR(layout, ptr, "use_object_instances", 0, NULL, ICON_NONE);
|
|
||||||
uiItemR(layout, ptr, "use_clip_plane_boundaries", 0, NULL, ICON_NONE);
|
|
||||||
|
|
||||||
gpencil_modifier_panel_end(layout, ptr);
|
gpencil_modifier_panel_end(layout, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void options_panel_draw(const bContext *UNUSED(C), Panel *panel)
|
||||||
|
{
|
||||||
|
uiLayout *layout = panel->layout;
|
||||||
|
PointerRNA ob_ptr;
|
||||||
|
PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, &ob_ptr);
|
||||||
|
|
||||||
|
const bool is_baked = RNA_boolean_get(ptr, "is_baked");
|
||||||
|
const bool use_cache = RNA_boolean_get(ptr, "use_cached_result");
|
||||||
|
const bool is_first = BKE_gpencil_is_first_lineart_in_stack(ob_ptr.data, ptr->data);
|
||||||
|
|
||||||
|
uiLayoutSetPropSep(layout, true);
|
||||||
|
uiLayoutSetEnabled(layout, !is_baked);
|
||||||
|
|
||||||
|
if (!use_cache || is_first) {
|
||||||
|
uiItemR(layout, ptr, "use_remove_doubles", 0, NULL, ICON_NONE);
|
||||||
|
uiItemR(layout, ptr, "use_edge_overlap", 0, IFACE_("Overlapping Edges As Contour"), ICON_NONE);
|
||||||
|
uiItemR(layout, ptr, "use_object_instances", 0, NULL, ICON_NONE);
|
||||||
|
uiItemR(layout, ptr, "use_clip_plane_boundaries", 0, NULL, ICON_NONE);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
uiItemL(layout, "Cached with the first line art modifier.", ICON_INFO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void style_panel_draw(const bContext *UNUSED(C), Panel *panel)
|
static void style_panel_draw(const bContext *UNUSED(C), Panel *panel)
|
||||||
{
|
{
|
||||||
uiLayout *layout = panel->layout;
|
uiLayout *layout = panel->layout;
|
||||||
@@ -395,22 +447,30 @@ static void transparency_panel_draw(const bContext *UNUSED(C), Panel *panel)
|
|||||||
|
|
||||||
static void chaining_panel_draw(const bContext *UNUSED(C), Panel *panel)
|
static void chaining_panel_draw(const bContext *UNUSED(C), Panel *panel)
|
||||||
{
|
{
|
||||||
PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL);
|
PointerRNA ob_ptr;
|
||||||
|
PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, &ob_ptr);
|
||||||
|
|
||||||
uiLayout *layout = panel->layout;
|
uiLayout *layout = panel->layout;
|
||||||
|
|
||||||
const bool is_baked = RNA_boolean_get(ptr, "is_baked");
|
const bool is_baked = RNA_boolean_get(ptr, "is_baked");
|
||||||
|
const bool use_cache = RNA_boolean_get(ptr, "use_cached_result");
|
||||||
|
const bool is_first = BKE_gpencil_is_first_lineart_in_stack(ob_ptr.data, ptr->data);
|
||||||
|
|
||||||
uiLayoutSetPropSep(layout, true);
|
uiLayoutSetPropSep(layout, true);
|
||||||
uiLayoutSetEnabled(layout, !is_baked);
|
uiLayoutSetEnabled(layout, !is_baked);
|
||||||
|
|
||||||
uiLayout *col = uiLayoutColumnWithHeading(layout, true, IFACE_("Chain"));
|
if (!use_cache || is_first) {
|
||||||
uiItemR(col, ptr, "use_fuzzy_intersections", 0, NULL, ICON_NONE);
|
uiLayout *col = uiLayoutColumnWithHeading(layout, true, IFACE_("Chain"));
|
||||||
uiItemR(col, ptr, "use_fuzzy_all", 0, NULL, ICON_NONE);
|
uiItemR(col, ptr, "use_fuzzy_intersections", 0, NULL, ICON_NONE);
|
||||||
|
uiItemR(col, ptr, "use_fuzzy_all", 0, NULL, ICON_NONE);
|
||||||
|
|
||||||
uiItemR(layout, ptr, "chaining_image_threshold", 0, NULL, ICON_NONE);
|
uiItemR(layout, ptr, "chaining_image_threshold", 0, NULL, ICON_NONE);
|
||||||
|
|
||||||
uiItemR(layout, ptr, "split_angle", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
|
uiItemR(layout, ptr, "split_angle", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
uiItemL(layout, "Cached with the first line art modifier.", ICON_INFO);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vgroup_panel_draw(const bContext *UNUSED(C), Panel *panel)
|
static void vgroup_panel_draw(const bContext *UNUSED(C), Panel *panel)
|
||||||
@@ -421,22 +481,30 @@ static void vgroup_panel_draw(const bContext *UNUSED(C), Panel *panel)
|
|||||||
uiLayout *layout = panel->layout;
|
uiLayout *layout = panel->layout;
|
||||||
|
|
||||||
const bool is_baked = RNA_boolean_get(ptr, "is_baked");
|
const bool is_baked = RNA_boolean_get(ptr, "is_baked");
|
||||||
|
const bool use_cache = RNA_boolean_get(ptr, "use_cached_result");
|
||||||
|
const bool is_first = BKE_gpencil_is_first_lineart_in_stack(ob_ptr.data, ptr->data);
|
||||||
|
|
||||||
uiLayoutSetPropSep(layout, true);
|
uiLayoutSetPropSep(layout, true);
|
||||||
uiLayoutSetEnabled(layout, !is_baked);
|
uiLayoutSetEnabled(layout, !is_baked);
|
||||||
|
|
||||||
uiLayout *col = uiLayoutColumn(layout, true);
|
if (!use_cache || is_first) {
|
||||||
|
uiLayout *col = uiLayoutColumn(layout, true);
|
||||||
|
|
||||||
uiLayout *row = uiLayoutRow(col, true);
|
uiLayout *row = uiLayoutRow(col, true);
|
||||||
uiItemR(row, ptr, "source_vertex_group", 0, IFACE_("Filter Source"), ICON_GROUP_VERTEX);
|
|
||||||
uiItemR(row, ptr, "invert_source_vertex_group", UI_ITEM_R_TOGGLE, "", ICON_ARROW_LEFTRIGHT);
|
|
||||||
|
|
||||||
uiItemR(col, ptr, "use_output_vertex_group_match_by_name", 0, NULL, ICON_NONE);
|
uiItemR(row, ptr, "source_vertex_group", 0, IFACE_("Filter Source"), ICON_GROUP_VERTEX);
|
||||||
|
uiItemR(row, ptr, "invert_source_vertex_group", UI_ITEM_R_TOGGLE, "", ICON_ARROW_LEFTRIGHT);
|
||||||
|
|
||||||
const bool match_output = RNA_boolean_get(ptr, "use_output_vertex_group_match_by_name");
|
uiItemR(col, ptr, "use_output_vertex_group_match_by_name", 0, NULL, ICON_NONE);
|
||||||
if (!match_output) {
|
|
||||||
uiItemPointerR(
|
const bool match_output = RNA_boolean_get(ptr, "use_output_vertex_group_match_by_name");
|
||||||
col, ptr, "vertex_group", &ob_ptr, "vertex_groups", IFACE_("Target"), ICON_NONE);
|
if (!match_output) {
|
||||||
|
uiItemPointerR(
|
||||||
|
col, ptr, "vertex_group", &ob_ptr, "vertex_groups", IFACE_("Target"), ICON_NONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
uiItemL(layout, "Cached with the first line art modifier.", ICON_INFO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -473,6 +541,8 @@ static void panelRegister(ARegionType *region_type)
|
|||||||
PanelType *panel_type = gpencil_modifier_panel_register(
|
PanelType *panel_type = gpencil_modifier_panel_register(
|
||||||
region_type, eGpencilModifierType_Lineart, panel_draw);
|
region_type, eGpencilModifierType_Lineart, panel_draw);
|
||||||
|
|
||||||
|
gpencil_modifier_subpanel_register(
|
||||||
|
region_type, "options", "Options", NULL, options_panel_draw, panel_type);
|
||||||
gpencil_modifier_subpanel_register(
|
gpencil_modifier_subpanel_register(
|
||||||
region_type, "style", "Style", NULL, style_panel_draw, panel_type);
|
region_type, "style", "Style", NULL, style_panel_draw, panel_type);
|
||||||
PanelType *occlusion_panel = gpencil_modifier_subpanel_register(
|
PanelType *occlusion_panel = gpencil_modifier_subpanel_register(
|
||||||
|
@@ -250,6 +250,10 @@ typedef struct LineartRenderBuffer {
|
|||||||
ListBase wasted_cuts;
|
ListBase wasted_cuts;
|
||||||
SpinLock lock_cuts;
|
SpinLock lock_cuts;
|
||||||
|
|
||||||
|
/* This is just a pointer to LineartCache::chain_data_pool, which acts as a cache for line
|
||||||
|
* chains. */
|
||||||
|
LineartStaticMemPool *chain_data_pool;
|
||||||
|
|
||||||
/* Render status */
|
/* Render status */
|
||||||
double view_vector[3];
|
double view_vector[3];
|
||||||
|
|
||||||
@@ -309,6 +313,18 @@ typedef struct LineartRenderBuffer {
|
|||||||
|
|
||||||
} LineartRenderBuffer;
|
} LineartRenderBuffer;
|
||||||
|
|
||||||
|
typedef struct LineartCache {
|
||||||
|
/** Separate memory pool for chain data, this goes to the cache, so when we free the main pool,
|
||||||
|
* chains will still be available. */
|
||||||
|
LineartStaticMemPool chain_data_pool;
|
||||||
|
|
||||||
|
/** A copy of rb->chains so we have that data available after rb has been destroyed. */
|
||||||
|
ListBase chains;
|
||||||
|
|
||||||
|
/** Cache only contains edge types specified in this variable. */
|
||||||
|
char rb_edge_types;
|
||||||
|
} LineartCache;
|
||||||
|
|
||||||
#define DBL_TRIANGLE_LIM 1e-8
|
#define DBL_TRIANGLE_LIM 1e-8
|
||||||
#define DBL_EDGE_LIM 1e-9
|
#define DBL_EDGE_LIM 1e-9
|
||||||
|
|
||||||
@@ -563,10 +579,11 @@ void MOD_lineart_chain_discard_short(LineartRenderBuffer *rb, const float thresh
|
|||||||
void MOD_lineart_chain_split_angle(LineartRenderBuffer *rb, float angle_threshold_rad);
|
void MOD_lineart_chain_split_angle(LineartRenderBuffer *rb, float angle_threshold_rad);
|
||||||
|
|
||||||
int MOD_lineart_chain_count(const LineartEdgeChain *ec);
|
int MOD_lineart_chain_count(const LineartEdgeChain *ec);
|
||||||
void MOD_lineart_chain_clear_picked_flag(struct LineartRenderBuffer *rb);
|
void MOD_lineart_chain_clear_picked_flag(LineartCache *lc);
|
||||||
|
|
||||||
bool MOD_lineart_compute_feature_lines(struct Depsgraph *depsgraph,
|
bool MOD_lineart_compute_feature_lines(struct Depsgraph *depsgraph,
|
||||||
struct LineartGpencilModifierData *lmd);
|
struct LineartGpencilModifierData *lmd,
|
||||||
|
LineartCache **cached_result);
|
||||||
|
|
||||||
struct Scene;
|
struct Scene;
|
||||||
|
|
||||||
@@ -579,7 +596,7 @@ LineartBoundingArea *MOD_lineart_get_bounding_area(LineartRenderBuffer *rb, doub
|
|||||||
struct bGPDlayer;
|
struct bGPDlayer;
|
||||||
struct bGPDframe;
|
struct bGPDframe;
|
||||||
|
|
||||||
void MOD_lineart_gpencil_generate(LineartRenderBuffer *rb,
|
void MOD_lineart_gpencil_generate(LineartCache *cache,
|
||||||
struct Depsgraph *depsgraph,
|
struct Depsgraph *depsgraph,
|
||||||
struct Object *ob,
|
struct Object *ob,
|
||||||
struct bGPDlayer *gpl,
|
struct bGPDlayer *gpl,
|
||||||
|
@@ -74,7 +74,7 @@ static LineartEdge *lineart_line_get_connected(LineartBoundingArea *ba,
|
|||||||
static LineartEdgeChain *lineart_chain_create(LineartRenderBuffer *rb)
|
static LineartEdgeChain *lineart_chain_create(LineartRenderBuffer *rb)
|
||||||
{
|
{
|
||||||
LineartEdgeChain *ec;
|
LineartEdgeChain *ec;
|
||||||
ec = lineart_mem_acquire(&rb->render_data_pool, sizeof(LineartEdgeChain));
|
ec = lineart_mem_acquire(rb->chain_data_pool, sizeof(LineartEdgeChain));
|
||||||
|
|
||||||
BLI_addtail(&rb->chains, ec);
|
BLI_addtail(&rb->chains, ec);
|
||||||
|
|
||||||
@@ -119,7 +119,7 @@ static LineartEdgeChainItem *lineart_chain_append_point(LineartRenderBuffer *rb,
|
|||||||
return old_rlci;
|
return old_rlci;
|
||||||
}
|
}
|
||||||
|
|
||||||
eci = lineart_mem_acquire(&rb->render_data_pool, sizeof(LineartEdgeChainItem));
|
eci = lineart_mem_acquire(rb->chain_data_pool, sizeof(LineartEdgeChainItem));
|
||||||
|
|
||||||
copy_v2_v2(eci->pos, fbcoord);
|
copy_v2_v2(eci->pos, fbcoord);
|
||||||
copy_v3_v3(eci->gpos, gpos);
|
copy_v3_v3(eci->gpos, gpos);
|
||||||
@@ -149,7 +149,7 @@ static LineartEdgeChainItem *lineart_chain_prepend_point(LineartRenderBuffer *rb
|
|||||||
return ec->chain.first;
|
return ec->chain.first;
|
||||||
}
|
}
|
||||||
|
|
||||||
eci = lineart_mem_acquire(&rb->render_data_pool, sizeof(LineartEdgeChainItem));
|
eci = lineart_mem_acquire(rb->chain_data_pool, sizeof(LineartEdgeChainItem));
|
||||||
|
|
||||||
copy_v2_v2(eci->pos, fbcoord);
|
copy_v2_v2(eci->pos, fbcoord);
|
||||||
copy_v3_v3(eci->gpos, gpos);
|
copy_v3_v3(eci->gpos, gpos);
|
||||||
@@ -889,12 +889,12 @@ int MOD_lineart_chain_count(const LineartEdgeChain *ec)
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MOD_lineart_chain_clear_picked_flag(LineartRenderBuffer *rb)
|
void MOD_lineart_chain_clear_picked_flag(LineartCache *lc)
|
||||||
{
|
{
|
||||||
if (rb == NULL) {
|
if (lc == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LISTBASE_FOREACH (LineartEdgeChain *, ec, &rb->chains) {
|
LISTBASE_FOREACH (LineartEdgeChain *, ec, &lc->chains) {
|
||||||
ec->picked = 0;
|
ec->picked = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -21,6 +21,7 @@
|
|||||||
* \ingroup editors
|
* \ingroup editors
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "MOD_gpencil_lineart.h"
|
||||||
#include "MOD_lineart.h"
|
#include "MOD_lineart.h"
|
||||||
|
|
||||||
#include "BLI_linklist.h"
|
#include "BLI_linklist.h"
|
||||||
@@ -42,6 +43,7 @@
|
|||||||
#include "BKE_gpencil_modifier.h"
|
#include "BKE_gpencil_modifier.h"
|
||||||
#include "BKE_material.h"
|
#include "BKE_material.h"
|
||||||
#include "BKE_mesh.h"
|
#include "BKE_mesh.h"
|
||||||
|
#include "BKE_pointcache.h"
|
||||||
#include "BKE_scene.h"
|
#include "BKE_scene.h"
|
||||||
#include "DEG_depsgraph_query.h"
|
#include "DEG_depsgraph_query.h"
|
||||||
#include "DNA_camera_types.h"
|
#include "DNA_camera_types.h"
|
||||||
@@ -107,6 +109,8 @@ static bool lineart_triangle_edge_image_space_occlusion(SpinLock *spl,
|
|||||||
|
|
||||||
static void lineart_add_edge_to_list(LineartRenderBuffer *rb, LineartEdge *e);
|
static void lineart_add_edge_to_list(LineartRenderBuffer *rb, LineartEdge *e);
|
||||||
|
|
||||||
|
static LineartCache *lineart_init_cache(void);
|
||||||
|
|
||||||
static void lineart_discard_segment(LineartRenderBuffer *rb, LineartEdgeSegment *es)
|
static void lineart_discard_segment(LineartRenderBuffer *rb, LineartEdgeSegment *es)
|
||||||
{
|
{
|
||||||
BLI_spin_lock(&rb->lock_cuts);
|
BLI_spin_lock(&rb->lock_cuts);
|
||||||
@@ -2771,13 +2775,13 @@ static void lineart_destroy_render_data(LineartRenderBuffer *rb)
|
|||||||
|
|
||||||
void MOD_lineart_destroy_render_data(LineartGpencilModifierData *lmd)
|
void MOD_lineart_destroy_render_data(LineartGpencilModifierData *lmd)
|
||||||
{
|
{
|
||||||
LineartRenderBuffer *rb = lmd->render_buffer;
|
LineartRenderBuffer *rb = lmd->render_buffer_ptr;
|
||||||
|
|
||||||
lineart_destroy_render_data(rb);
|
lineart_destroy_render_data(rb);
|
||||||
|
|
||||||
if (rb) {
|
if (rb) {
|
||||||
MEM_freeN(rb);
|
MEM_freeN(rb);
|
||||||
lmd->render_buffer = NULL;
|
lmd->render_buffer_ptr = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (G.debug_value == 4000) {
|
if (G.debug_value == 4000) {
|
||||||
@@ -2785,14 +2789,33 @@ void MOD_lineart_destroy_render_data(LineartGpencilModifierData *lmd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static LineartCache *lineart_init_cache()
|
||||||
|
{
|
||||||
|
LineartCache *lc = MEM_callocN(sizeof(LineartCache), "Lineart Cache");
|
||||||
|
return lc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MOD_lineart_clear_cache(struct LineartCache **lc)
|
||||||
|
{
|
||||||
|
if (!(*lc)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lineart_mem_destroy(&((*lc)->chain_data_pool));
|
||||||
|
MEM_freeN(*lc);
|
||||||
|
(*lc) = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static LineartRenderBuffer *lineart_create_render_buffer(Scene *scene,
|
static LineartRenderBuffer *lineart_create_render_buffer(Scene *scene,
|
||||||
LineartGpencilModifierData *lmd)
|
LineartGpencilModifierData *lmd,
|
||||||
|
LineartCache *lc)
|
||||||
{
|
{
|
||||||
LineartRenderBuffer *rb = MEM_callocN(sizeof(LineartRenderBuffer), "Line Art render buffer");
|
LineartRenderBuffer *rb = MEM_callocN(sizeof(LineartRenderBuffer), "Line Art render buffer");
|
||||||
|
|
||||||
lmd->render_buffer = rb;
|
lmd->cache = lc;
|
||||||
|
lmd->render_buffer_ptr = rb;
|
||||||
|
lc->rb_edge_types = lmd->edge_types_override;
|
||||||
|
|
||||||
if (!scene || !scene->camera) {
|
if (!scene || !scene->camera || !lc) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
Camera *c = scene->camera->data;
|
Camera *c = scene->camera->data;
|
||||||
@@ -2835,11 +2858,15 @@ static LineartRenderBuffer *lineart_create_render_buffer(Scene *scene,
|
|||||||
/* See lineart_edge_from_triangle() for how this option may impact performance. */
|
/* See lineart_edge_from_triangle() for how this option may impact performance. */
|
||||||
rb->allow_overlapping_edges = (lmd->calculation_flags & LRT_ALLOW_OVERLAPPING_EDGES) != 0;
|
rb->allow_overlapping_edges = (lmd->calculation_flags & LRT_ALLOW_OVERLAPPING_EDGES) != 0;
|
||||||
|
|
||||||
rb->use_contour = (lmd->edge_types & LRT_EDGE_FLAG_CONTOUR) != 0;
|
int16_t edge_types = lmd->edge_types_override;
|
||||||
rb->use_crease = (lmd->edge_types & LRT_EDGE_FLAG_CREASE) != 0;
|
|
||||||
rb->use_material = (lmd->edge_types & LRT_EDGE_FLAG_MATERIAL) != 0;
|
rb->use_contour = (edge_types & LRT_EDGE_FLAG_CONTOUR) != 0;
|
||||||
rb->use_edge_marks = (lmd->edge_types & LRT_EDGE_FLAG_EDGE_MARK) != 0;
|
rb->use_crease = (edge_types & LRT_EDGE_FLAG_CREASE) != 0;
|
||||||
rb->use_intersections = (lmd->edge_types & LRT_EDGE_FLAG_INTERSECTION) != 0;
|
rb->use_material = (edge_types & LRT_EDGE_FLAG_MATERIAL) != 0;
|
||||||
|
rb->use_edge_marks = (edge_types & LRT_EDGE_FLAG_EDGE_MARK) != 0;
|
||||||
|
rb->use_intersections = (edge_types & LRT_EDGE_FLAG_INTERSECTION) != 0;
|
||||||
|
|
||||||
|
rb->chain_data_pool = &lc->chain_data_pool;
|
||||||
|
|
||||||
BLI_spin_init(&rb->lock_task);
|
BLI_spin_init(&rb->lock_task);
|
||||||
BLI_spin_init(&rb->lock_cuts);
|
BLI_spin_init(&rb->lock_cuts);
|
||||||
@@ -3818,7 +3845,9 @@ static LineartBoundingArea *lineart_bounding_area_next(LineartBoundingArea *this
|
|||||||
*
|
*
|
||||||
* \return True when a change is made.
|
* \return True when a change is made.
|
||||||
*/
|
*/
|
||||||
bool MOD_lineart_compute_feature_lines(Depsgraph *depsgraph, LineartGpencilModifierData *lmd)
|
bool MOD_lineart_compute_feature_lines(Depsgraph *depsgraph,
|
||||||
|
LineartGpencilModifierData *lmd,
|
||||||
|
LineartCache **cached_result)
|
||||||
{
|
{
|
||||||
LineartRenderBuffer *rb;
|
LineartRenderBuffer *rb;
|
||||||
Scene *scene = DEG_get_evaluated_scene(depsgraph);
|
Scene *scene = DEG_get_evaluated_scene(depsgraph);
|
||||||
@@ -3836,7 +3865,10 @@ bool MOD_lineart_compute_feature_lines(Depsgraph *depsgraph, LineartGpencilModif
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
rb = lineart_create_render_buffer(scene, lmd);
|
LineartCache *lc = lineart_init_cache();
|
||||||
|
(*cached_result) = lc;
|
||||||
|
|
||||||
|
rb = lineart_create_render_buffer(scene, lmd, lc);
|
||||||
|
|
||||||
/* Triangle thread testing data size varies depending on the thread count.
|
/* Triangle thread testing data size varies depending on the thread count.
|
||||||
* See definition of LineartTriangleThread for details. */
|
* See definition of LineartTriangleThread for details. */
|
||||||
@@ -3844,7 +3876,9 @@ bool MOD_lineart_compute_feature_lines(Depsgraph *depsgraph, LineartGpencilModif
|
|||||||
|
|
||||||
/* This is used to limit calculation to a certain level to save time, lines who have higher
|
/* This is used to limit calculation to a certain level to save time, lines who have higher
|
||||||
* occlusion levels will get ignored. */
|
* occlusion levels will get ignored. */
|
||||||
rb->max_occlusion_level = MAX2(lmd->level_start, lmd->level_end);
|
rb->max_occlusion_level = (lmd->flags & LRT_GPENCIL_USE_CACHE) ?
|
||||||
|
lmd->level_end_override :
|
||||||
|
(lmd->use_multiple_levels ? lmd->level_end : lmd->level_start);
|
||||||
|
|
||||||
/* FIXME(Yiming): See definition of int #LineartRenderBuffer::_source_type for detailed. */
|
/* FIXME(Yiming): See definition of int #LineartRenderBuffer::_source_type for detailed. */
|
||||||
rb->_source_type = lmd->source_type;
|
rb->_source_type = lmd->source_type;
|
||||||
@@ -3907,13 +3941,8 @@ bool MOD_lineart_compute_feature_lines(Depsgraph *depsgraph, LineartGpencilModif
|
|||||||
|
|
||||||
/* Then we connect chains based on the _proximity_ of their end points in image space, here's
|
/* Then we connect chains based on the _proximity_ of their end points in image space, here's
|
||||||
* the place threshold value gets involved. */
|
* the place threshold value gets involved. */
|
||||||
|
|
||||||
/* do_geometry_space = true. */
|
|
||||||
MOD_lineart_chain_connect(rb);
|
MOD_lineart_chain_connect(rb);
|
||||||
|
|
||||||
/* After chaining, we need to clear flags so we don't confuse GPencil generation calls. */
|
|
||||||
MOD_lineart_chain_clear_picked_flag(rb);
|
|
||||||
|
|
||||||
float *t_image = &lmd->chaining_image_threshold;
|
float *t_image = &lmd->chaining_image_threshold;
|
||||||
/* This configuration ensures there won't be accidental lost of short unchained segments. */
|
/* This configuration ensures there won't be accidental lost of short unchained segments. */
|
||||||
MOD_lineart_chain_discard_short(rb, MIN2(*t_image, 0.001f) - FLT_EPSILON);
|
MOD_lineart_chain_discard_short(rb, MIN2(*t_image, 0.001f) - FLT_EPSILON);
|
||||||
@@ -3921,6 +3950,12 @@ bool MOD_lineart_compute_feature_lines(Depsgraph *depsgraph, LineartGpencilModif
|
|||||||
if (rb->angle_splitting_threshold > FLT_EPSILON) {
|
if (rb->angle_splitting_threshold > FLT_EPSILON) {
|
||||||
MOD_lineart_chain_split_angle(rb, rb->angle_splitting_threshold);
|
MOD_lineart_chain_split_angle(rb, rb->angle_splitting_threshold);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Finally transfer the result list into cache. */
|
||||||
|
memcpy(&lc->chains, &rb->chains, sizeof(ListBase));
|
||||||
|
|
||||||
|
/* At last, we need to clear flags so we don't confuse GPencil generation calls. */
|
||||||
|
MOD_lineart_chain_clear_picked_flag(lc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (G.debug_value == 4000) {
|
if (G.debug_value == 4000) {
|
||||||
@@ -3944,7 +3979,7 @@ static int lineart_rb_edge_types(LineartRenderBuffer *rb)
|
|||||||
return types;
|
return types;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lineart_gpencil_generate(LineartRenderBuffer *rb,
|
static void lineart_gpencil_generate(LineartCache *cache,
|
||||||
Depsgraph *depsgraph,
|
Depsgraph *depsgraph,
|
||||||
Object *gpencil_object,
|
Object *gpencil_object,
|
||||||
float (*gp_obmat_inverse)[4],
|
float (*gp_obmat_inverse)[4],
|
||||||
@@ -3964,9 +3999,9 @@ static void lineart_gpencil_generate(LineartRenderBuffer *rb,
|
|||||||
const char *vgname,
|
const char *vgname,
|
||||||
int modifier_flags)
|
int modifier_flags)
|
||||||
{
|
{
|
||||||
if (rb == NULL) {
|
if (cache == NULL) {
|
||||||
if (G.debug_value == 4000) {
|
if (G.debug_value == 4000) {
|
||||||
printf("NULL Lineart rb!\n");
|
printf("NULL Lineart cache!\n");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -3990,11 +4025,11 @@ static void lineart_gpencil_generate(LineartRenderBuffer *rb,
|
|||||||
float mat[4][4];
|
float mat[4][4];
|
||||||
unit_m4(mat);
|
unit_m4(mat);
|
||||||
|
|
||||||
int enabled_types = lineart_rb_edge_types(rb);
|
int enabled_types = cache->rb_edge_types;
|
||||||
bool invert_input = modifier_flags & LRT_GPENCIL_INVERT_SOURCE_VGROUP;
|
bool invert_input = modifier_flags & LRT_GPENCIL_INVERT_SOURCE_VGROUP;
|
||||||
bool match_output = modifier_flags & LRT_GPENCIL_MATCH_OUTPUT_VGROUP;
|
bool match_output = modifier_flags & LRT_GPENCIL_MATCH_OUTPUT_VGROUP;
|
||||||
|
|
||||||
LISTBASE_FOREACH (LineartEdgeChain *, ec, &rb->chains) {
|
LISTBASE_FOREACH (LineartEdgeChain *, ec, &cache->chains) {
|
||||||
|
|
||||||
if (ec->picked) {
|
if (ec->picked) {
|
||||||
continue;
|
continue;
|
||||||
@@ -4108,7 +4143,7 @@ static void lineart_gpencil_generate(LineartRenderBuffer *rb,
|
|||||||
/**
|
/**
|
||||||
* Wrapper for external calls.
|
* Wrapper for external calls.
|
||||||
*/
|
*/
|
||||||
void MOD_lineart_gpencil_generate(LineartRenderBuffer *rb,
|
void MOD_lineart_gpencil_generate(LineartCache *cache,
|
||||||
Depsgraph *depsgraph,
|
Depsgraph *depsgraph,
|
||||||
Object *ob,
|
Object *ob,
|
||||||
bGPDlayer *gpl,
|
bGPDlayer *gpl,
|
||||||
@@ -4156,7 +4191,7 @@ void MOD_lineart_gpencil_generate(LineartRenderBuffer *rb,
|
|||||||
}
|
}
|
||||||
float gp_obmat_inverse[4][4];
|
float gp_obmat_inverse[4][4];
|
||||||
invert_m4_m4(gp_obmat_inverse, ob->obmat);
|
invert_m4_m4(gp_obmat_inverse, ob->obmat);
|
||||||
lineart_gpencil_generate(rb,
|
lineart_gpencil_generate(cache,
|
||||||
depsgraph,
|
depsgraph,
|
||||||
ob,
|
ob,
|
||||||
gp_obmat_inverse,
|
gp_obmat_inverse,
|
||||||
|
@@ -88,7 +88,12 @@ static void clear_strokes(Object *ob, GpencilModifierData *md, int frame)
|
|||||||
BKE_gpencil_layer_frame_delete(gpl, gpf);
|
BKE_gpencil_layer_frame_delete(gpl, gpf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool bake_strokes(Object *ob, Depsgraph *dg, GpencilModifierData *md, int frame)
|
static bool bake_strokes(Object *ob,
|
||||||
|
Depsgraph *dg,
|
||||||
|
LineartCache **lc,
|
||||||
|
GpencilModifierData *md,
|
||||||
|
int frame,
|
||||||
|
bool is_first)
|
||||||
{
|
{
|
||||||
/* Modifier data sanity check. */
|
/* Modifier data sanity check. */
|
||||||
if (lineart_mod_is_disabled(md)) {
|
if (lineart_mod_is_disabled(md)) {
|
||||||
@@ -111,11 +116,22 @@ static bool bake_strokes(Object *ob, Depsgraph *dg, GpencilModifierData *md, int
|
|||||||
/* No greasepencil frame created or found. */
|
/* No greasepencil frame created or found. */
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
LineartCache *local_lc = *lc;
|
||||||
MOD_lineart_compute_feature_lines(dg, lmd);
|
if (!(*lc)) {
|
||||||
|
MOD_lineart_compute_feature_lines(dg, lmd, lc);
|
||||||
|
MOD_lineart_destroy_render_data(lmd);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (is_first || (!(lmd->flags & LRT_GPENCIL_USE_CACHE))) {
|
||||||
|
MOD_lineart_compute_feature_lines(dg, lmd, &local_lc);
|
||||||
|
MOD_lineart_destroy_render_data(lmd);
|
||||||
|
}
|
||||||
|
MOD_lineart_chain_clear_picked_flag(local_lc);
|
||||||
|
lmd->cache = local_lc;
|
||||||
|
}
|
||||||
|
|
||||||
MOD_lineart_gpencil_generate(
|
MOD_lineart_gpencil_generate(
|
||||||
lmd->render_buffer,
|
lmd->cache,
|
||||||
dg,
|
dg,
|
||||||
ob,
|
ob,
|
||||||
gpl,
|
gpl,
|
||||||
@@ -135,7 +151,15 @@ static bool bake_strokes(Object *ob, Depsgraph *dg, GpencilModifierData *md, int
|
|||||||
lmd->vgname,
|
lmd->vgname,
|
||||||
lmd->flags);
|
lmd->flags);
|
||||||
|
|
||||||
MOD_lineart_destroy_render_data(lmd);
|
if (!(lmd->flags & LRT_GPENCIL_USE_CACHE)) {
|
||||||
|
/* Clear local cache. */
|
||||||
|
if (!is_first) {
|
||||||
|
MOD_lineart_clear_cache(&local_lc);
|
||||||
|
}
|
||||||
|
/* Restore the original cache pointer so the modifiers below still have access to the
|
||||||
|
* "global" cache. */
|
||||||
|
lmd->cache = gpd->runtime.lineart_cache;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -174,14 +198,22 @@ static bool lineart_gpencil_bake_single_target(LineartBakeJob *bj, Object *ob, i
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GpencilLineartLimitInfo info = {0};
|
||||||
|
BKE_gpencil_get_lineart_modifier_limits(ob, &info);
|
||||||
|
|
||||||
|
LineartCache *lc = NULL;
|
||||||
|
bool is_first = true;
|
||||||
LISTBASE_FOREACH (GpencilModifierData *, md, &ob->greasepencil_modifiers) {
|
LISTBASE_FOREACH (GpencilModifierData *, md, &ob->greasepencil_modifiers) {
|
||||||
if (md->type != eGpencilModifierType_Lineart) {
|
if (md->type != eGpencilModifierType_Lineart) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (bake_strokes(ob, bj->dg, md, frame)) {
|
BKE_gpencil_set_lineart_modifier_limits(md, &info, is_first);
|
||||||
|
if (bake_strokes(ob, bj->dg, &lc, md, frame, is_first)) {
|
||||||
touched = true;
|
touched = true;
|
||||||
|
is_first = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
MOD_lineart_clear_cache(&lc);
|
||||||
|
|
||||||
return touched;
|
return touched;
|
||||||
}
|
}
|
||||||
|
@@ -878,6 +878,7 @@ typedef enum eLineArtGPencilModifierFlags {
|
|||||||
LRT_GPENCIL_MATCH_OUTPUT_VGROUP = (1 << 1),
|
LRT_GPENCIL_MATCH_OUTPUT_VGROUP = (1 << 1),
|
||||||
LRT_GPENCIL_BINARY_WEIGHTS = (1 << 2) /* Deprecated, this is removed for lack of use case. */,
|
LRT_GPENCIL_BINARY_WEIGHTS = (1 << 2) /* Deprecated, this is removed for lack of use case. */,
|
||||||
LRT_GPENCIL_IS_BAKED = (1 << 3),
|
LRT_GPENCIL_IS_BAKED = (1 << 3),
|
||||||
|
LRT_GPENCIL_USE_CACHE = (1 << 4),
|
||||||
} eLineArtGPencilModifierFlags;
|
} eLineArtGPencilModifierFlags;
|
||||||
|
|
||||||
typedef enum eLineartGpencilTransparencyFlags {
|
typedef enum eLineartGpencilTransparencyFlags {
|
||||||
@@ -886,6 +887,8 @@ typedef enum eLineartGpencilTransparencyFlags {
|
|||||||
LRT_GPENCIL_TRANSPARENCY_MATCH = (1 << 1),
|
LRT_GPENCIL_TRANSPARENCY_MATCH = (1 << 1),
|
||||||
} eLineartGpencilTransparencyFlags;
|
} eLineartGpencilTransparencyFlags;
|
||||||
|
|
||||||
|
struct LineartCache;
|
||||||
|
|
||||||
typedef struct LineartGpencilModifierData {
|
typedef struct LineartGpencilModifierData {
|
||||||
GpencilModifierData modifier;
|
GpencilModifierData modifier;
|
||||||
|
|
||||||
@@ -925,16 +928,24 @@ typedef struct LineartGpencilModifierData {
|
|||||||
/* CPU mode */
|
/* CPU mode */
|
||||||
float chaining_image_threshold;
|
float chaining_image_threshold;
|
||||||
|
|
||||||
int _pad;
|
|
||||||
|
|
||||||
/* Ported from SceneLineArt flags. */
|
/* Ported from SceneLineArt flags. */
|
||||||
int calculation_flags;
|
int calculation_flags;
|
||||||
|
|
||||||
/* Additional Switches. */
|
/* Additional Switches. */
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
/* Runtime only. */
|
/* Runtime data. */
|
||||||
void *render_buffer;
|
|
||||||
|
/* Because we can potentially only compute features lines once per modifier stack (Use Cache), we
|
||||||
|
* need to have these override values to ensure that we have the data we need is computed and
|
||||||
|
* stored in the cache. */
|
||||||
|
char level_start_override;
|
||||||
|
char level_end_override;
|
||||||
|
short edge_types_override;
|
||||||
|
|
||||||
|
struct LineartCache *cache;
|
||||||
|
/* Keep a pointer to the render buffer so we can call destroy from ModifierData. */
|
||||||
|
struct LineartRenderBuffer *render_buffer_ptr;
|
||||||
|
|
||||||
} LineartGpencilModifierData;
|
} LineartGpencilModifierData;
|
||||||
|
|
||||||
|
@@ -629,6 +629,7 @@ typedef struct bGPdata_Runtime {
|
|||||||
/** Brush pointer */
|
/** Brush pointer */
|
||||||
Brush *sbuffer_brush;
|
Brush *sbuffer_brush;
|
||||||
struct GpencilBatchCache *gpencil_cache;
|
struct GpencilBatchCache *gpencil_cache;
|
||||||
|
struct LineartCache *lineart_cache;
|
||||||
} bGPdata_Runtime;
|
} bGPdata_Runtime;
|
||||||
|
|
||||||
/* grid configuration */
|
/* grid configuration */
|
||||||
|
@@ -2930,6 +2930,14 @@ static void rna_def_modifier_gpencillineart(BlenderRNA *brna)
|
|||||||
RNA_def_property_ui_text(prop, "Is Baked", "This modifier has baked data");
|
RNA_def_property_ui_text(prop, "Is Baked", "This modifier has baked data");
|
||||||
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
|
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "use_cached_result", PROP_BOOLEAN, PROP_NONE);
|
||||||
|
RNA_def_property_boolean_sdna(prop, NULL, "flags", LRT_GPENCIL_USE_CACHE);
|
||||||
|
RNA_def_property_ui_text(prop,
|
||||||
|
"Use Cached Result",
|
||||||
|
"Use cached line art data from the first line art modifier in the "
|
||||||
|
"stack. Certain settings will be unavailable when using cached data.");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "thickness", PROP_INT, PROP_NONE);
|
prop = RNA_def_property(srna, "thickness", PROP_INT, PROP_NONE);
|
||||||
RNA_def_property_ui_text(prop, "Thickness", "The thickness for the generated strokes");
|
RNA_def_property_ui_text(prop, "Thickness", "The thickness for the generated strokes");
|
||||||
RNA_def_property_ui_range(prop, 1, 100, 1, 1);
|
RNA_def_property_ui_range(prop, 1, 100, 1, 1);
|
||||||
|
Submodule source/tools updated: 2afbb8ec47...01f51a0e55
Reference in New Issue
Block a user