GPv3: Subdivide Modifier

This ports the Subdivide modifier from GPv2.

Pull Request: https://projects.blender.org/blender/blender/pulls/117056
This commit is contained in:
YimingWu
2024-01-18 13:02:53 +01:00
committed by Falk David
parent 03c1cc4310
commit 4d387843e9
9 changed files with 278 additions and 1 deletions
@@ -73,7 +73,7 @@ class OBJECT_MT_modifier_add(ModifierAddMenu, Menu):
layout.separator()
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE', 'GREASEPENCIL'}:
layout.menu("OBJECT_MT_modifier_add_edit")
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'VOLUME'}:
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'VOLUME', 'GREASEPENCIL'}:
layout.menu("OBJECT_MT_modifier_add_generate")
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE', 'VOLUME'}:
layout.menu("OBJECT_MT_modifier_add_deform")
@@ -149,6 +149,8 @@ class OBJECT_MT_modifier_add_generate(ModifierAddMenu, Menu):
self.operator_modifier_add(layout, 'WELD')
if ob_type == 'MESH':
self.operator_modifier_add(layout, 'WIREFRAME')
if ob_type == 'GREASEPENCIL':
self.operator_modifier_add(layout, 'GREASEPENCIL_SUBDIV')
layout.template_modifier_asset_menu_items(catalog_path=self.bl_label)
@@ -808,4 +808,9 @@
.hardness_factor = 1.0f, \
}
#define _DNA_DEFAULT_GreasePencilSubdivModifierData \
{ \
.level = 1, \
}
/* clang-format off */
@@ -94,6 +94,7 @@ typedef enum ModifierType {
eModifierType_VolumeDisplace = 59,
eModifierType_VolumeToMesh = 60,
eModifierType_GreasePencilOpacity = 61,
eModifierType_GreasePencilSubdiv = 62,
NUM_MODIFIER_TYPES,
} ModifierType;
@@ -2547,3 +2548,19 @@ typedef enum GreasePencilOpacityModifierFlag {
/* Set the opacity for every point in a stroke, otherwise multiply existing opacity. */
MOD_GREASE_PENCIL_OPACITY_USE_UNIFORM_OPACITY = (1 << 2),
} GreasePencilOpacityModifierFlag;
typedef struct GreasePencilSubdivModifierData {
ModifierData modifier;
GreasePencilModifierInfluenceData influence;
/** `GreasePencilSubdivModifierFlag`. */
int flag;
/** Number of subdivisions. */
int level;
char _pad[8];
void *_pad1;
} GreasePencilSubdivModifierData;
typedef enum GreasePencilSubdivModifierFlag {
MOD_GREASE_PENCIL_SUBDIV_OPEN_INFLUENCE_PANEL = (1 << 0),
} GreasePencilSubdivModifierFlag;
@@ -292,6 +292,7 @@ SDNA_DEFAULT_DECL_STRUCT(WeightVGMixModifierData);
SDNA_DEFAULT_DECL_STRUCT(WeightVGProximityModifierData);
SDNA_DEFAULT_DECL_STRUCT(WeldModifierData);
SDNA_DEFAULT_DECL_STRUCT(WireframeModifierData);
SDNA_DEFAULT_DECL_STRUCT(GreasePencilSubdivModifierData);
/* DNA_gpencil_modifier_defaults.h */
SDNA_DEFAULT_DECL_STRUCT(ArmatureGpencilModifierData);
@@ -537,6 +538,7 @@ const void *DNA_default_table[SDNA_TYPE_MAX] = {
SDNA_DEFAULT_DECL(WeightVGProximityModifierData),
SDNA_DEFAULT_DECL(WeldModifierData),
SDNA_DEFAULT_DECL(WireframeModifierData),
SDNA_DEFAULT_DECL(GreasePencilSubdivModifierData),
/* DNA_gpencil_modifier_defaults.h */
SDNA_DEFAULT_DECL(ArmatureGpencilModifierData),
@@ -12,6 +12,7 @@
#include "DNA_armature_types.h"
#include "DNA_cachefile_types.h"
#include "DNA_gpencil_modifier_types.h"
#include "DNA_mesh_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_force_types.h"
@@ -200,6 +201,11 @@ const EnumPropertyItem rna_enum_object_modifier_type_items[] = {
ICON_MOD_WIREFRAME,
"Wireframe",
"Convert faces into thickened edges"},
{eModifierType_GreasePencilSubdiv,
"GREASEPENCIL_SUBDIV",
ICON_GREASEPENCIL,
"Subdivide strokes",
"Grease Pencil subdivide modifier"},
RNA_ENUM_ITEM_HEADING(N_("Deform"), nullptr),
{eModifierType_Armature,
@@ -1796,6 +1802,8 @@ static void rna_GreasePencilModifier_material_set(PointerRNA *ptr,
RNA_MOD_GREASE_PENCIL_MATERIAL_FILTER_SET(GreasePencilOpacity);
RNA_MOD_GREASE_PENCIL_VERTEX_GROUP_SET(GreasePencilOpacity);
RNA_MOD_GREASE_PENCIL_MATERIAL_FILTER_SET(GreasePencilSubdiv);
RNA_MOD_GREASE_PENCIL_VERTEX_GROUP_SET(GreasePencilSubdiv);
static void rna_GreasePencilOpacityModifier_opacity_factor_range(
PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
@@ -7730,6 +7738,40 @@ static void rna_def_modifier_grease_pencil_opacity(BlenderRNA *brna)
prop, nullptr, "flag", MOD_GREASE_PENCIL_OPACITY_USE_UNIFORM_OPACITY);
RNA_def_property_ui_text(
prop, "Uniform Opacity", "Replace the stroke opacity instead of modulating each point");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
RNA_define_lib_overridable(false);
}
static void rna_def_modifier_grease_pencil_subdiv(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "GreasePencilSubdivModifier", "Modifier");
RNA_def_struct_ui_text(srna, "Subdivision Modifier", "Subdivide Stroke modifier");
RNA_def_struct_sdna(srna, "GreasePencilSubdivModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_SUBSURF);
rna_def_modifier_grease_pencil_layer_filter(srna);
rna_def_modifier_grease_pencil_material_filter(
srna, "rna_GreasePencilSubdivModifier_material_filter_set");
rna_def_modifier_grease_pencil_vertex_group(
srna, "rna_GreasePencilSubdivModifier_vertex_group_name_set");
rna_def_modifier_grease_pencil_custom_curve(srna);
rna_def_modifier_panel_open_prop(srna, "open_influence_panel", 0);
RNA_define_lib_overridable(true);
prop = RNA_def_property(srna, "level", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, nullptr, "level");
/* Since the new subdiv algorithm uses linear cut count, we set the limits as 2^n the old value
* to get the same range as before. */
RNA_def_property_range(prop, 0, 65536);
RNA_def_property_ui_range(prop, 0, 32, 1, 0);
RNA_def_property_ui_text(prop, "Level", "Number of subdivisions");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
RNA_define_lib_overridable(false);
@@ -7896,6 +7938,7 @@ void RNA_def_modifier(BlenderRNA *brna)
rna_def_modifier_volume_displace(brna);
rna_def_modifier_volume_to_mesh(brna);
rna_def_modifier_grease_pencil_opacity(brna);
rna_def_modifier_grease_pencil_subdiv(brna);
}
#endif
+1
View File
@@ -45,6 +45,7 @@ set(SRC
intern/MOD_explode.cc
intern/MOD_fluid.cc
intern/MOD_grease_pencil_opacity.cc
intern/MOD_grease_pencil_subdiv.cc
intern/MOD_grease_pencil_util.cc
intern/MOD_hook.cc
intern/MOD_laplaciandeform.cc
@@ -74,6 +74,7 @@ extern ModifierTypeInfo modifierType_MeshToVolume;
extern ModifierTypeInfo modifierType_VolumeDisplace;
extern ModifierTypeInfo modifierType_VolumeToMesh;
extern ModifierTypeInfo modifierType_GreasePencilOpacity;
extern ModifierTypeInfo modifierType_GreasePencilSubdiv;
/* MOD_util.cc */
@@ -0,0 +1,205 @@
/* SPDX-FileCopyrightText: 2005 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup modifiers
*/
#include "BLI_array.hh"
#include "BLI_index_mask.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_task.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
#include "BLO_read_write.hh"
#include "DNA_defaults.h"
#include "DNA_modifier_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "BKE_context.hh"
#include "BKE_curves.hh"
#include "BKE_geometry_set.hh"
#include "BKE_grease_pencil.hh"
#include "BKE_lib_query.h"
#include "BKE_modifier.hh"
#include "BKE_screen.hh"
#include "GEO_subdivide_curves.hh"
#include "UI_interface.hh"
#include "UI_resources.hh"
#include "ED_grease_pencil.hh"
#include "MOD_grease_pencil_util.hh"
#include "MOD_modifiertypes.hh"
#include "MOD_ui_common.hh"
#include "RNA_prototypes.h"
#include "DEG_depsgraph.hh"
#include "DEG_depsgraph_query.hh"
namespace blender {
static void init_data(ModifierData *md)
{
GreasePencilSubdivModifierData *gpmd = reinterpret_cast<GreasePencilSubdivModifierData *>(md);
BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(gpmd, modifier));
MEMCPY_STRUCT_AFTER(gpmd, DNA_struct_default_get(GreasePencilSubdivModifierData), modifier);
modifier::greasepencil::init_influence_data(&gpmd->influence, true);
}
static void free_data(ModifierData *md)
{
GreasePencilSubdivModifierData *mmd = reinterpret_cast<GreasePencilSubdivModifierData *>(md);
modifier::greasepencil::free_influence_data(&mmd->influence);
}
static void copy_data(const ModifierData *md, ModifierData *target, int flag)
{
const GreasePencilSubdivModifierData *gmd =
reinterpret_cast<const GreasePencilSubdivModifierData *>(md);
GreasePencilSubdivModifierData *tgmd = reinterpret_cast<GreasePencilSubdivModifierData *>(
target);
BKE_modifier_copydata_generic(md, target, flag);
modifier::greasepencil::copy_influence_data(&gmd->influence, &tgmd->influence, flag);
}
static void blend_write(BlendWriter *writer, const ID * /*id_owner*/, const ModifierData *md)
{
const GreasePencilSubdivModifierData *mmd =
reinterpret_cast<const GreasePencilSubdivModifierData *>(md);
BLO_write_struct(writer, GreasePencilSubdivModifierData, mmd);
modifier::greasepencil::write_influence_data(writer, &mmd->influence);
}
static void blend_read(BlendDataReader *reader, ModifierData *md)
{
GreasePencilSubdivModifierData *mmd = reinterpret_cast<GreasePencilSubdivModifierData *>(md);
modifier::greasepencil::read_influence_data(reader, &mmd->influence);
}
static void deform_drawing(ModifierData &md,
Depsgraph * /*depsgraph*/,
Object &ob,
bke::greasepencil::Drawing &drawing)
{
GreasePencilSubdivModifierData &mmd = reinterpret_cast<GreasePencilSubdivModifierData &>(md);
IndexMaskMemory memory;
const IndexMask strokes = modifier::greasepencil::get_filtered_stroke_mask(
&ob, drawing.strokes_for_write(), mmd.influence, memory);
VArray<int> cuts = VArray<int>::ForSingle(mmd.level, drawing.strokes().points_num());
drawing.strokes_for_write() = geometry::subdivide_curves(
drawing.strokes(), strokes, std::move(cuts), {});
drawing.tag_topology_changed();
}
static void modify_geometry_set(ModifierData *md,
const ModifierEvalContext *ctx,
bke::GeometrySet *geometry_set)
{
GreasePencilSubdivModifierData *mmd = reinterpret_cast<GreasePencilSubdivModifierData *>(md);
if (mmd->level < 1 || !geometry_set->has_grease_pencil()) {
return;
}
GreasePencil &grease_pencil = *geometry_set->get_grease_pencil_for_write();
const int current_frame = DEG_get_evaluated_scene(ctx->depsgraph)->r.cfra;
IndexMaskMemory mask_memory;
const IndexMask layer_mask = modifier::greasepencil::get_filtered_layer_mask(
grease_pencil, mmd->influence, mask_memory);
const Vector<bke::greasepencil::Drawing *> drawings =
modifier::greasepencil::get_drawings_for_write(grease_pencil, layer_mask, current_frame);
threading::parallel_for_each(drawings, [&](bke::greasepencil::Drawing *drawing) {
deform_drawing(*md, ctx->depsgraph, *ctx->object, *drawing);
});
}
static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
{
GreasePencilSubdivModifierData *mmd = reinterpret_cast<GreasePencilSubdivModifierData *>(md);
modifier::greasepencil::foreach_influence_ID_link(&mmd->influence, ob, walk, user_data);
}
static void panel_draw(const bContext *C, Panel *panel)
{
uiLayout *layout = panel->layout;
PointerRNA *ptr = modifier_panel_get_property_pointers(panel, nullptr);
uiLayoutSetPropSep(layout, true);
uiItemR(layout, ptr, "level", UI_ITEM_NONE, IFACE_("Subdivisions"), ICON_NONE);
if (uiLayout *influence_panel = uiLayoutPanel(
C, layout, "Influence", ptr, "open_influence_panel"))
{
modifier::greasepencil::draw_layer_filter_settings(C, influence_panel, ptr);
modifier::greasepencil::draw_material_filter_settings(C, influence_panel, ptr);
modifier::greasepencil::draw_vertex_group_settings(C, influence_panel, ptr);
}
modifier_panel_end(layout, ptr);
}
static void panel_register(ARegionType *region_type)
{
modifier_panel_register(region_type, eModifierType_GreasePencilSubdiv, panel_draw);
}
} // namespace blender
ModifierTypeInfo modifierType_GreasePencilSubdiv = {
/*idname*/ "GreasePencilSubdivModifier",
/*name*/ N_("Subdivide"),
/*struct_name*/ "GreasePencilSubdivModifierData",
/*struct_size*/ sizeof(GreasePencilSubdivModifierData),
/*srna*/ &RNA_GreasePencilSubdivModifier,
/*type*/ ModifierTypeType::Constructive,
/*flags*/
(eModifierTypeFlag_AcceptsGreasePencil | eModifierTypeFlag_SupportsEditmode |
eModifierTypeFlag_EnableInEditmode),
/*icon*/ ICON_MOD_SUBSURF,
/*copy_data*/ blender::copy_data,
/*deform_verts*/ nullptr,
/*deform_matrices*/ nullptr,
/*deform_verts_EM*/ nullptr,
/*deform_matrices_EM*/ nullptr,
/*modify_mesh*/ nullptr,
/*modify_geometry_set*/ blender::modify_geometry_set,
/*init_data*/ blender::init_data,
/*required_data_mask*/ nullptr,
/*free_data*/ blender::free_data,
/*is_disabled*/ nullptr,
/*update_depsgraph*/ nullptr,
/*depends_on_time*/ nullptr,
/*depends_on_normals*/ nullptr,
/*foreach_ID_link*/ blender::foreach_ID_link,
/*foreach_tex_link*/ nullptr,
/*free_runtime_data*/ nullptr,
/*panel_register*/ blender::panel_register,
/*blend_write*/ blender::blend_write,
/*blend_read*/ blender::blend_read,
};
@@ -271,5 +271,6 @@ void modifier_type_init(ModifierTypeInfo *types[])
INIT_TYPE(VolumeToMesh);
INIT_TYPE(Nodes);
INIT_TYPE(GreasePencilOpacity);
INIT_TYPE(GreasePencilSubdiv);
#undef INIT_TYPE
}