GPv3: Fillet Curve node

Part of #113602.

Pull Request: https://projects.blender.org/blender/blender/pulls/113850
This commit is contained in:
Dalai Felinto 2023-10-17 18:30:38 +02:00 committed by Hans Goudey
parent e1fd7a8a7b
commit f54d5df2fc
1 changed files with 85 additions and 39 deletions

View File

@ -17,7 +17,8 @@ NODE_STORAGE_FUNCS(NodeGeometryCurveFillet)
static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>("Curve").supported_type(GeometryComponent::Type::Curve);
b.add_input<decl::Geometry>("Curve").supported_type(
{GeometryComponent::Type::Curve, GeometryComponent::Type::GreasePencil});
b.add_input<decl::Int>("Count").default_value(1).min(1).max(1000).field_on_all().make_available(
[](bNode &node) { node_storage(node).mode = GEO_NODE_CURVE_FILLET_POLY; });
b.add_input<decl::Float>("Radius")
@ -51,6 +52,71 @@ static void node_update(bNodeTree *ntree, bNode *node)
bke::nodeSetSocketAvailability(ntree, poly_socket, mode == GEO_NODE_CURVE_FILLET_POLY);
}
static bke::CurvesGeometry fillet_curve(const bke::CurvesGeometry &src_curves,
const GeometryNodeCurveFilletMode mode,
const fn::FieldContext &field_context,
const std::optional<Field<int>> &count_field,
const Field<float> &radius_field,
const bool limit_radius,
const AnonymousAttributePropagationInfo &propagation_info)
{
fn::FieldEvaluator evaluator{field_context, src_curves.points_num()};
evaluator.add(radius_field);
switch (mode) {
case GEO_NODE_CURVE_FILLET_BEZIER: {
evaluator.evaluate();
return geometry::fillet_curves_bezier(src_curves,
src_curves.curves_range(),
evaluator.get_evaluated<float>(0),
limit_radius,
propagation_info);
}
case GEO_NODE_CURVE_FILLET_POLY: {
evaluator.add(*count_field);
evaluator.evaluate();
return geometry::fillet_curves_poly(src_curves,
src_curves.curves_range(),
evaluator.get_evaluated<float>(0),
evaluator.get_evaluated<int>(1),
limit_radius,
propagation_info);
}
}
return bke::CurvesGeometry();
}
static void fillet_grease_pencil(GreasePencil &grease_pencil,
const GeometryNodeCurveFilletMode mode,
const std::optional<Field<int>> &count_field,
const Field<float> &radius_field,
const bool limit_radius,
const AnonymousAttributePropagationInfo &propagation_info)
{
using namespace blender::bke::greasepencil;
for (const int layer_index : grease_pencil.layers().index_range()) {
Drawing *drawing = get_eval_grease_pencil_layer_drawing_for_write(grease_pencil, layer_index);
if (drawing == nullptr) {
continue;
}
const bke::CurvesGeometry &src_curves = drawing->strokes();
if (src_curves.points_num() == 0) {
continue;
}
const bke::GreasePencilLayerFieldContext field_context(
grease_pencil, ATTR_DOMAIN_CURVE, layer_index);
bke::CurvesGeometry dst_curves = fillet_curve(src_curves,
mode,
field_context,
count_field,
radius_field,
limit_radius,
propagation_info);
drawing->strokes_for_write() = std::move(dst_curves);
drawing->tag_topology_changed();
}
}
static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Curve");
@ -70,45 +136,25 @@ static void node_geo_exec(GeoNodeExecParams params)
"Curve");
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
if (!geometry_set.has_curves()) {
return;
if (geometry_set.has_curves()) {
const Curves &curves_id = *geometry_set.get_curves();
const bke::CurvesGeometry &src_curves = curves_id.geometry.wrap();
const bke::CurvesFieldContext field_context{src_curves, ATTR_DOMAIN_POINT};
const bke::CurvesGeometry &dst_curves = fillet_curve(src_curves,
mode,
field_context,
count_field,
radius_field,
limit_radius,
propagation_info);
Curves *dst_curves_id = bke::curves_new_nomain(std::move(dst_curves));
bke::curves_copy_parameters(curves_id, *dst_curves_id);
geometry_set.replace_curves(dst_curves_id);
}
const Curves &curves_id = *geometry_set.get_curves();
const bke::CurvesGeometry &curves = curves_id.geometry.wrap();
const bke::CurvesFieldContext context{curves, ATTR_DOMAIN_POINT};
fn::FieldEvaluator evaluator{context, curves.points_num()};
evaluator.add(radius_field);
switch (mode) {
case GEO_NODE_CURVE_FILLET_BEZIER: {
evaluator.evaluate();
bke::CurvesGeometry dst_curves = geometry::fillet_curves_bezier(
curves,
curves.curves_range(),
evaluator.get_evaluated<float>(0),
limit_radius,
propagation_info);
Curves *dst_curves_id = bke::curves_new_nomain(std::move(dst_curves));
bke::curves_copy_parameters(curves_id, *dst_curves_id);
geometry_set.replace_curves(dst_curves_id);
break;
}
case GEO_NODE_CURVE_FILLET_POLY: {
evaluator.add(*count_field);
evaluator.evaluate();
bke::CurvesGeometry dst_curves = geometry::fillet_curves_poly(
curves,
curves.curves_range(),
evaluator.get_evaluated<float>(0),
evaluator.get_evaluated<int>(1),
limit_radius,
propagation_info);
Curves *dst_curves_id = bke::curves_new_nomain(std::move(dst_curves));
bke::curves_copy_parameters(curves_id, *dst_curves_id);
geometry_set.replace_curves(dst_curves_id);
break;
}
if (geometry_set.has_grease_pencil()) {
GreasePencil &grease_pencil = *geometry_set.get_grease_pencil_for_write();
fillet_grease_pencil(
grease_pencil, mode, count_field, radius_field, limit_radius, propagation_info);
}
});