GPv3: Resample Curve node

Reviewed as part of !113581.
This commit is contained in:
Dalai Felinto
2023-10-06 18:32:15 +02:00
parent 87e03b3f97
commit 3f13471d65
4 changed files with 96 additions and 13 deletions

View File

@@ -26,6 +26,7 @@ struct ResampleCurvesOutputAttributeIDs {
* \note The values provided by the #count_field are clamped to 1 or greater.
*/
CurvesGeometry resample_to_count(const CurvesGeometry &src_curves,
const fn::FieldContext &field_context,
const fn::Field<bool> &selection_field,
const fn::Field<int> &count_field,
const ResampleCurvesOutputAttributeIDs &output_ids = {});
@@ -36,6 +37,7 @@ CurvesGeometry resample_to_count(const CurvesGeometry &src_curves,
* The accuracy will depend on the curve's resolution parameter.
*/
CurvesGeometry resample_to_length(const CurvesGeometry &src_curves,
const fn::FieldContext &field_context,
const fn::Field<bool> &selection_field,
const fn::Field<float> &segment_length_field,
const ResampleCurvesOutputAttributeIDs &output_ids = {});
@@ -44,6 +46,7 @@ CurvesGeometry resample_to_length(const CurvesGeometry &src_curves,
* Evaluate each selected curve to its implicit evaluated points.
*/
CurvesGeometry resample_to_evaluated(const CurvesGeometry &src_curves,
const fn::FieldContext &field_context,
const fn::Field<bool> &selection_field,
const ResampleCurvesOutputAttributeIDs &output_ids = {});

View File

@@ -246,6 +246,7 @@ static void normalize_curve_point_data(const IndexMaskSegment curve_selection,
}
static CurvesGeometry resample_to_uniform(const CurvesGeometry &src_curves,
const fn::FieldContext &field_context,
const fn::Field<bool> &selection_field,
const fn::Field<int> &count_field,
const ResampleCurvesOutputAttributeIDs &output_ids)
@@ -262,7 +263,6 @@ static CurvesGeometry resample_to_uniform(const CurvesGeometry &src_curves,
CurvesGeometry dst_curves = bke::curves::copy_only_curve_domain(src_curves);
MutableSpan<int> dst_offsets = dst_curves.offsets_for_write();
const bke::CurvesFieldContext field_context{src_curves, ATTR_DOMAIN_CURVE};
fn::FieldEvaluator evaluator{field_context, src_curves.curves_num()};
evaluator.set_selection(selection_field);
evaluator.add_with_destination(count_field, dst_offsets.drop_back(1));
@@ -395,24 +395,33 @@ static CurvesGeometry resample_to_uniform(const CurvesGeometry &src_curves,
}
CurvesGeometry resample_to_count(const CurvesGeometry &src_curves,
const fn::FieldContext &field_context,
const fn::Field<bool> &selection_field,
const fn::Field<int> &count_field,
const ResampleCurvesOutputAttributeIDs &output_ids)
{
return resample_to_uniform(
src_curves, selection_field, get_count_input_max_one(count_field), output_ids);
return resample_to_uniform(src_curves,
field_context,
selection_field,
get_count_input_max_one(count_field),
output_ids);
}
CurvesGeometry resample_to_length(const CurvesGeometry &src_curves,
const fn::FieldContext &field_context,
const fn::Field<bool> &selection_field,
const fn::Field<float> &segment_length_field,
const ResampleCurvesOutputAttributeIDs &output_ids)
{
return resample_to_uniform(
src_curves, selection_field, get_count_input_from_length(segment_length_field), output_ids);
return resample_to_uniform(src_curves,
field_context,
selection_field,
get_count_input_from_length(segment_length_field),
output_ids);
}
CurvesGeometry resample_to_evaluated(const CurvesGeometry &src_curves,
const fn::FieldContext &field_context,
const fn::Field<bool> &selection_field,
const ResampleCurvesOutputAttributeIDs &output_ids)
{
@@ -423,7 +432,6 @@ CurvesGeometry resample_to_evaluated(const CurvesGeometry &src_curves,
const OffsetIndices src_evaluated_points_by_curve = src_curves.evaluated_points_by_curve();
const Span<float3> evaluated_positions = src_curves.evaluated_positions();
const bke::CurvesFieldContext field_context{src_curves, ATTR_DOMAIN_CURVE};
fn::FieldEvaluator evaluator{field_context, src_curves.curves_num()};
evaluator.set_selection(selection_field);
evaluator.evaluate();

View File

@@ -5,6 +5,7 @@
#include "GEO_resample_curves.hh"
#include "BKE_curves.hh"
#include "BKE_grease_pencil.hh"
#include "UI_interface.hh"
#include "UI_resources.hh"
@@ -19,7 +20,8 @@ NODE_STORAGE_FUNCS(NodeGeometryCurveResample)
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::Bool>("Selection").default_value(true).field_on_all().hide_value();
b.add_input<decl::Int>("Count").default_value(10).min(1).max(100000).field_on_all();
b.add_input<decl::Float>("Length")
@@ -72,12 +74,31 @@ static void node_geo_exec(GeoNodeExecParams params)
geometry_set.modify_geometry_sets([&](GeometrySet &geometry) {
if (const Curves *src_curves_id = geometry.get_curves()) {
const bke::CurvesGeometry &src_curves = src_curves_id->geometry.wrap();
const bke::CurvesFieldContext field_context{src_curves, ATTR_DOMAIN_CURVE};
bke::CurvesGeometry dst_curves = geometry::resample_to_count(
src_curves, selection, count);
src_curves, field_context, selection, count);
Curves *dst_curves_id = bke::curves_new_nomain(std::move(dst_curves));
bke::curves_copy_parameters(*src_curves_id, *dst_curves_id);
geometry.replace_curves(dst_curves_id);
}
if (geometry_set.has_grease_pencil()) {
using namespace blender::bke::greasepencil;
GreasePencil &grease_pencil = *geometry_set.get_grease_pencil_for_write();
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();
const bke::GreasePencilLayerFieldContext field_context(
grease_pencil, ATTR_DOMAIN_CURVE, layer_index);
bke::CurvesGeometry dst_curves = geometry::resample_to_count(
src_curves, field_context, selection, count);
drawing->strokes_for_write() = std::move(dst_curves);
drawing->tag_positions_changed();
}
}
});
break;
}
@@ -86,12 +107,31 @@ static void node_geo_exec(GeoNodeExecParams params)
geometry_set.modify_geometry_sets([&](GeometrySet &geometry) {
if (const Curves *src_curves_id = geometry.get_curves()) {
const bke::CurvesGeometry &src_curves = src_curves_id->geometry.wrap();
const bke::CurvesFieldContext field_context{src_curves, ATTR_DOMAIN_CURVE};
bke::CurvesGeometry dst_curves = geometry::resample_to_length(
src_curves, selection, length);
src_curves, field_context, selection, length);
Curves *dst_curves_id = bke::curves_new_nomain(std::move(dst_curves));
bke::curves_copy_parameters(*src_curves_id, *dst_curves_id);
geometry.replace_curves(dst_curves_id);
}
if (geometry_set.has_grease_pencil()) {
using namespace blender::bke::greasepencil;
GreasePencil &grease_pencil = *geometry_set.get_grease_pencil_for_write();
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();
const bke::GreasePencilLayerFieldContext field_context(
grease_pencil, ATTR_DOMAIN_CURVE, layer_index);
bke::CurvesGeometry dst_curves = geometry::resample_to_length(
src_curves, field_context, selection, length);
drawing->strokes_for_write() = std::move(dst_curves);
drawing->tag_positions_changed();
}
}
});
break;
}
@@ -99,11 +139,31 @@ static void node_geo_exec(GeoNodeExecParams params)
geometry_set.modify_geometry_sets([&](GeometrySet &geometry) {
if (const Curves *src_curves_id = geometry.get_curves()) {
const bke::CurvesGeometry &src_curves = src_curves_id->geometry.wrap();
bke::CurvesGeometry dst_curves = geometry::resample_to_evaluated(src_curves, selection);
const bke::CurvesFieldContext field_context{src_curves, ATTR_DOMAIN_CURVE};
bke::CurvesGeometry dst_curves = geometry::resample_to_evaluated(
src_curves, field_context, selection);
Curves *dst_curves_id = bke::curves_new_nomain(std::move(dst_curves));
bke::curves_copy_parameters(*src_curves_id, *dst_curves_id);
geometry.replace_curves(dst_curves_id);
}
if (geometry_set.has_grease_pencil()) {
using namespace blender::bke::greasepencil;
GreasePencil &grease_pencil = *geometry_set.get_grease_pencil_for_write();
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();
const bke::GreasePencilLayerFieldContext field_context(
grease_pencil, ATTR_DOMAIN_CURVE, layer_index);
bke::CurvesGeometry dst_curves = geometry::resample_to_evaluated(
src_curves, field_context, selection);
drawing->strokes_for_write() = std::move(dst_curves);
drawing->tag_topology_changed();
}
}
});
break;
}

View File

@@ -157,9 +157,15 @@ static void node_geo_exec(GeoNodeExecParams params)
geometry_set.modify_geometry_sets([&](GeometrySet &geometry) {
if (const Curves *src_curves_id = geometry.get_curves()) {
const bke::CurvesGeometry &src_curves = src_curves_id->geometry.wrap();
const bke::CurvesFieldContext field_context{src_curves, ATTR_DOMAIN_CURVE};
bke::CurvesGeometry dst_curves = geometry::resample_to_count(
src_curves, fn::make_constant_field<bool>(true), count, resample_attributes);
src_curves,
field_context,
fn::make_constant_field<bool>(true),
count,
resample_attributes);
PointCloud *pointcloud = pointcloud_from_curves(std::move(dst_curves),
resample_attributes.tangent_id,
resample_attributes.normal_id,
rotation_anonymous_id.get());
@@ -174,8 +180,13 @@ static void node_geo_exec(GeoNodeExecParams params)
geometry_set.modify_geometry_sets([&](GeometrySet &geometry) {
if (const Curves *src_curves_id = geometry.get_curves()) {
const bke::CurvesGeometry &src_curves = src_curves_id->geometry.wrap();
const bke::CurvesFieldContext field_context{src_curves, ATTR_DOMAIN_CURVE};
bke::CurvesGeometry dst_curves = geometry::resample_to_length(
src_curves, fn::make_constant_field<bool>(true), length, resample_attributes);
src_curves,
field_context,
fn::make_constant_field<bool>(true),
length,
resample_attributes);
PointCloud *pointcloud = pointcloud_from_curves(std::move(dst_curves),
resample_attributes.tangent_id,
resample_attributes.normal_id,
@@ -190,8 +201,9 @@ static void node_geo_exec(GeoNodeExecParams params)
geometry_set.modify_geometry_sets([&](GeometrySet &geometry) {
if (const Curves *src_curves_id = geometry.get_curves()) {
const bke::CurvesGeometry &src_curves = src_curves_id->geometry.wrap();
const bke::CurvesFieldContext field_context{src_curves, ATTR_DOMAIN_CURVE};
bke::CurvesGeometry dst_curves = geometry::resample_to_evaluated(
src_curves, fn::make_constant_field<bool>(true), resample_attributes);
src_curves, field_context, fn::make_constant_field<bool>(true), resample_attributes);
PointCloud *pointcloud = pointcloud_from_curves(std::move(dst_curves),
resample_attributes.tangent_id,
resample_attributes.normal_id,