GPv3: Add Catmull-Clark option in subdivide modifier
This adds the "Catmull-Clark" option to the subdivide modifier. Since this option is creating 2^n segments, the "Simple" method was adjusted to do the same. This is now consistent with the old GPv2 modifier. Pull Request: https://projects.blender.org/blender/blender/pulls/117382
This commit is contained in:
@@ -2554,18 +2554,19 @@ typedef enum GreasePencilOpacityModifierFlag {
|
||||
typedef struct GreasePencilSubdivModifierData {
|
||||
ModifierData modifier;
|
||||
GreasePencilModifierInfluenceData influence;
|
||||
/** `GreasePencilSubdivModifierFlag`. */
|
||||
int flag;
|
||||
/** Number of subdivisions. */
|
||||
/** #GreasePencilSubdivideType. */
|
||||
int type;
|
||||
/** Level of subdivisions, will generate 2^level segments. */
|
||||
int level;
|
||||
|
||||
char _pad[8];
|
||||
void *_pad1;
|
||||
} GreasePencilSubdivModifierData;
|
||||
|
||||
typedef enum GreasePencilSubdivModifierFlag {
|
||||
MOD_GREASE_PENCIL_SUBDIV_OPEN_INFLUENCE_PANEL = (1 << 0),
|
||||
} GreasePencilSubdivModifierFlag;
|
||||
typedef enum GreasePencilSubdivideType {
|
||||
MOD_GREASE_PENCIL_SUBDIV_CATMULL = 0,
|
||||
MOD_GREASE_PENCIL_SUBDIV_SIMPLE = 1,
|
||||
} GreasePencilSubdivideType;
|
||||
|
||||
typedef struct GreasePencilColorModifierData {
|
||||
ModifierData modifier;
|
||||
|
||||
@@ -7776,6 +7776,12 @@ static void rna_def_modifier_grease_pencil_subdiv(BlenderRNA *brna)
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
static const EnumPropertyItem subdivision_type_items[] = {
|
||||
{MOD_GREASE_PENCIL_SUBDIV_CATMULL, "CATMULL_CLARK", 0, "Catmull-Clark", ""},
|
||||
{MOD_GREASE_PENCIL_SUBDIV_SIMPLE, "SIMPLE", 0, "Simple", ""},
|
||||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
|
||||
srna = RNA_def_struct(brna, "GreasePencilSubdivModifier", "Modifier");
|
||||
RNA_def_struct_ui_text(srna, "Subdivision Modifier", "Subdivide Stroke modifier");
|
||||
RNA_def_struct_sdna(srna, "GreasePencilSubdivModifierData");
|
||||
@@ -7793,11 +7799,16 @@ static void rna_def_modifier_grease_pencil_subdiv(BlenderRNA *brna)
|
||||
|
||||
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_range(prop, 0, 16);
|
||||
RNA_def_property_ui_range(prop, 0, 6, 1, 0);
|
||||
RNA_def_property_ui_text(prop, "Level", "Level of subdivision");
|
||||
|
||||
prop = RNA_def_property(srna, "subdivision_type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, nullptr, "type");
|
||||
RNA_def_property_enum_items(prop, subdivision_type_items);
|
||||
RNA_def_property_ui_text(prop, "Subdivision Type", "Select type of subdivision algorithm");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
RNA_define_lib_overridable(false);
|
||||
|
||||
@@ -80,15 +80,40 @@ static void blend_read(BlendDataReader *reader, ModifierData *md)
|
||||
static void subdivide_drawing(ModifierData &md, Object &ob, bke::greasepencil::Drawing &drawing)
|
||||
{
|
||||
GreasePencilSubdivModifierData &mmd = reinterpret_cast<GreasePencilSubdivModifierData &>(md);
|
||||
const bool use_catmull_clark = mmd.type == MOD_GREASE_PENCIL_SUBDIV_CATMULL;
|
||||
|
||||
IndexMaskMemory memory;
|
||||
const IndexMask strokes = modifier::greasepencil::get_filtered_stroke_mask(
|
||||
&ob, drawing.strokes_for_write(), mmd.influence, memory);
|
||||
|
||||
const VArray<int> cuts = VArray<int>::ForSingle(mmd.level, drawing.strokes().points_num());
|
||||
if (use_catmull_clark) {
|
||||
bke::CurvesGeometry subdivided_curves = drawing.strokes();
|
||||
for ([[maybe_unused]] const int level_i : IndexRange(mmd.level)) {
|
||||
VArray<int> one_cut = VArray<int>::ForSingle(1, subdivided_curves.points_num());
|
||||
subdivided_curves = geometry::subdivide_curves(
|
||||
subdivided_curves, strokes, std::move(one_cut), {});
|
||||
|
||||
offset_indices::OffsetIndices<int> points_by_curve = subdivided_curves.points_by_curve();
|
||||
MutableSpan<float3> positions = subdivided_curves.positions_for_write();
|
||||
threading::parallel_for(subdivided_curves.curves_range(), 1024, [&](const IndexRange range) {
|
||||
for (const int curve_i : range) {
|
||||
const IndexRange points = points_by_curve[curve_i];
|
||||
for (const int point_i : points.drop_front(1).drop_back(1)) {
|
||||
positions[point_i] = math::interpolate(
|
||||
positions[point_i],
|
||||
math::interpolate(positions[point_i - 1], positions[point_i + 1], 0.5f),
|
||||
0.5f);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
drawing.strokes_for_write() = subdivided_curves;
|
||||
}
|
||||
else {
|
||||
VArray<int> cuts = VArray<int>::ForSingle(math::pow(mmd.level,2), drawing.strokes().points_num());
|
||||
drawing.strokes_for_write() = geometry::subdivide_curves(drawing.strokes(), strokes, cuts, {});
|
||||
}
|
||||
|
||||
drawing.strokes_for_write() = geometry::subdivide_curves(
|
||||
drawing.strokes(), strokes, std::move(cuts), {});
|
||||
drawing.tag_topology_changed();
|
||||
}
|
||||
|
||||
@@ -131,6 +156,7 @@ static void panel_draw(const bContext *C, Panel *panel)
|
||||
|
||||
uiLayoutSetPropSep(layout, true);
|
||||
|
||||
uiItemR(layout, ptr, "subdivision_type", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||
uiItemR(layout, ptr, "level", UI_ITEM_NONE, IFACE_("Subdivisions"), ICON_NONE);
|
||||
|
||||
if (uiLayout *influence_panel = uiLayoutPanel(
|
||||
|
||||
Reference in New Issue
Block a user