Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Goudey <h.goudey@me.com>2022-07-20 02:50:27 +0300
committerHans Goudey <h.goudey@me.com>2022-07-20 02:50:27 +0300
commit2551cf908732bab2865654571164d74e8bbad47e (patch)
tree3f526721dce7aa3e0304decd2fa1c23d65e64c87 /source/blender/nodes/geometry
parent5d6e4822d85bf4db099e2810555af17962929e49 (diff)
Curves: Port fillet node to the new data-block
This commit ports the fillet curves node to the new curves data-block, and moves the fillet node implementation to the geometry module to help separate the implementation from the node. The changes are similar to the subdivide node or resample node. I've resused common utilities where it makes sense, though some things like the iteration over attributes can be generalized further. The node is now multi-threaded per-curve and inside each curve, and some buffers are reused per curve to avoid many allocations. The code is more explicit now, and though there is more boilerplate to pass around many spans, the more complex logic should be more readable. Differential Revision: https://developer.blender.org/D15346
Diffstat (limited to 'source/blender/nodes/geometry')
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc600
1 files changed, 37 insertions, 563 deletions
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc
index dd8471d2dac..ab1f8269c39 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc
@@ -1,17 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
-#include "BLI_task.hh"
-
#include "UI_interface.h"
#include "UI_resources.h"
-#include "DNA_node_types.h"
+#include "GEO_fillet_curves.hh"
#include "node_geometry_util.hh"
-#include "BKE_curves.hh"
-#include "BKE_spline.hh"
-
namespace blender::nodes::node_geo_curve_fillet_cc {
NODE_STORAGE_FUNCS(NodeGeometryCurveFillet)
@@ -45,574 +40,18 @@ static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeGeometryCurveFillet *data = MEM_cnew<NodeGeometryCurveFillet>(__func__);
-
data->mode = GEO_NODE_CURVE_FILLET_BEZIER;
node->storage = data;
}
-struct FilletParam {
- GeometryNodeCurveFilletMode mode;
-
- /* Number of points to be added. */
- VArray<int> counts;
-
- /* Radii for fillet arc at all vertices. */
- VArray<float> radii;
-
- /* Whether or not fillets are allowed to overlap. */
- bool limit_radius;
-};
-
-/* A data structure used to store fillet data about all vertices to be filleted. */
-struct FilletData {
- Span<float3> positions;
- Array<float3> directions, axes;
- Array<float> radii, angles;
- Array<int> counts;
-};
-
static void node_update(bNodeTree *ntree, bNode *node)
{
const NodeGeometryCurveFillet &storage = node_storage(*node);
const GeometryNodeCurveFilletMode mode = (GeometryNodeCurveFilletMode)storage.mode;
-
bNodeSocket *poly_socket = ((bNodeSocket *)node->inputs.first)->next;
-
nodeSetSocketAvailability(ntree, poly_socket, mode == GEO_NODE_CURVE_FILLET_POLY);
}
-/* Function to get the center of a fillet. */
-static float3 get_center(const float3 vec_pos2prev,
- const float3 pos,
- const float3 axis,
- const float angle)
-{
- float3 vec_pos2center;
- rotate_normalized_v3_v3v3fl(vec_pos2center, vec_pos2prev, axis, M_PI_2 - angle / 2.0f);
- vec_pos2center *= 1.0f / sinf(angle / 2.0f);
-
- return vec_pos2center + pos;
-}
-
-/* Function to get the center of the fillet using fillet data */
-static float3 get_center(const float3 vec_pos2prev, const FilletData &fd, const int index)
-{
- const float angle = fd.angles[index];
- const float3 axis = fd.axes[index];
- const float3 pos = fd.positions[index];
-
- return get_center(vec_pos2prev, pos, axis, angle);
-}
-
-/* Calculate the direction vectors from each vertex to their previous vertex. */
-static Array<float3> calculate_directions(const Span<float3> positions)
-{
- const int num = positions.size();
- Array<float3> directions(num);
-
- for (const int i : IndexRange(num - 1)) {
- directions[i] = math::normalize(positions[i + 1] - positions[i]);
- }
- directions[num - 1] = math::normalize(positions[0] - positions[num - 1]);
-
- return directions;
-}
-
-/* Calculate the axes around which the fillet is built. */
-static Array<float3> calculate_axes(const Span<float3> directions)
-{
- const int num = directions.size();
- Array<float3> axes(num);
-
- axes[0] = math::normalize(math::cross(-directions[num - 1], directions[0]));
- for (const int i : IndexRange(1, num - 1)) {
- axes[i] = math::normalize(math::cross(-directions[i - 1], directions[i]));
- }
-
- return axes;
-}
-
-/* Calculate the angle of the arc formed by the fillet. */
-static Array<float> calculate_angles(const Span<float3> directions)
-{
- const int num = directions.size();
- Array<float> angles(num);
-
- angles[0] = M_PI - angle_v3v3(-directions[num - 1], directions[0]);
- for (const int i : IndexRange(1, num - 1)) {
- angles[i] = M_PI - angle_v3v3(-directions[i - 1], directions[i]);
- }
-
- return angles;
-}
-
-/* Calculate the segment count in each filleted arc. */
-static Array<int> calculate_counts(const FilletParam &fillet_param,
- const int num,
- const int spline_offset,
- const bool cyclic)
-{
- Array<int> counts(num, 1);
- if (fillet_param.mode == GEO_NODE_CURVE_FILLET_POLY) {
- for (const int i : IndexRange(num)) {
- counts[i] = fillet_param.counts[spline_offset + i];
- }
- }
- if (!cyclic) {
- counts[0] = counts[num - 1] = 0;
- }
-
- return counts;
-}
-
-/* Calculate the radii for the vertices to be filleted. */
-static Array<float> calculate_radii(const FilletParam &fillet_param,
- const int num,
- const int spline_offset)
-{
- Array<float> radii(num, 0.0f);
- if (fillet_param.limit_radius) {
- for (const int i : IndexRange(num)) {
- radii[i] = std::max(fillet_param.radii[spline_offset + i], 0.0f);
- }
- }
- else {
- for (const int i : IndexRange(num)) {
- radii[i] = fillet_param.radii[spline_offset + i];
- }
- }
-
- return radii;
-}
-
-/* Calculate the number of vertices added per vertex on the source spline. */
-static int calculate_point_counts(MutableSpan<int> point_counts,
- const Span<float> radii,
- const Span<int> counts)
-{
- int added_count = 0;
- for (const int i : IndexRange(point_counts.size())) {
- /* Calculate number of points to be added for the vertex. */
- if (radii[i] != 0.0f) {
- added_count += counts[i];
- point_counts[i] = counts[i] + 1;
- }
- }
-
- return added_count;
-}
-
-static FilletData calculate_fillet_data(const Spline &spline,
- const FilletParam &fillet_param,
- int &added_count,
- MutableSpan<int> point_counts,
- const int spline_offset)
-{
- const int num = spline.size();
-
- FilletData fd;
- fd.directions = calculate_directions(spline.positions());
- fd.positions = spline.positions();
- fd.axes = calculate_axes(fd.directions);
- fd.angles = calculate_angles(fd.directions);
- fd.counts = calculate_counts(fillet_param, num, spline_offset, spline.is_cyclic());
- fd.radii = calculate_radii(fillet_param, num, spline_offset);
-
- added_count = calculate_point_counts(point_counts, fd.radii, fd.counts);
-
- return fd;
-}
-
-/* Limit the radius based on angle and radii to prevent overlapping. */
-static void limit_radii(FilletData &fd, const bool cyclic)
-{
- MutableSpan<float> radii(fd.radii);
- Span<float> angles(fd.angles);
- Span<float3> positions(fd.positions);
-
- const int num = radii.size();
- const int fillet_count = cyclic ? num : num - 2;
- const int start = cyclic ? 0 : 1;
- Array<float> max_radii(num, FLT_MAX);
-
- if (cyclic) {
- /* Calculate lengths between adjacent control points. */
- const float len_prev = math::distance(positions[0], positions[num - 1]);
- const float len_next = math::distance(positions[0], positions[1]);
-
- /* Calculate tangent lengths of fillets in control points. */
- const float tan_len = radii[0] * tan(angles[0] / 2.0f);
- const float tan_len_prev = radii[num - 1] * tan(angles[num - 1] / 2.0f);
- const float tan_len_next = radii[1] * tan(angles[1] / 2.0f);
-
- float factor_prev = 1.0f, factor_next = 1.0f;
- if (tan_len + tan_len_prev > len_prev) {
- factor_prev = len_prev / (tan_len + tan_len_prev);
- }
- if (tan_len + tan_len_next > len_next) {
- factor_next = len_next / (tan_len + tan_len_next);
- }
-
- /* Scale max radii by calculated factors. */
- max_radii[0] = radii[0] * std::min(factor_next, factor_prev);
- max_radii[1] = radii[1] * factor_next;
- max_radii[num - 1] = radii[num - 1] * factor_prev;
- }
-
- /* Initialize max_radii to largest possible radii. */
- float prev_dist = math::distance(positions[1], positions[0]);
- for (const int i : IndexRange(1, num - 2)) {
- const float temp_dist = math::distance(positions[i], positions[i + 1]);
- max_radii[i] = std::min(prev_dist, temp_dist) / tan(angles[i] / 2.0f);
- prev_dist = temp_dist;
- }
-
- /* Max radii calculations for each index. */
- for (const int i : IndexRange(start, fillet_count - 1)) {
- const float len_next = math::distance(positions[i], positions[i + 1]);
- const float tan_len = radii[i] * tan(angles[i] / 2.0f);
- const float tan_len_next = radii[i + 1] * tan(angles[i + 1] / 2.0f);
-
- /* Scale down radii if too large for segment. */
- float factor = 1.0f;
- if (tan_len + tan_len_next > len_next) {
- factor = len_next / (tan_len + tan_len_next);
- }
- max_radii[i] = std::min(max_radii[i], radii[i] * factor);
- max_radii[i + 1] = std::min(max_radii[i + 1], radii[i + 1] * factor);
- }
-
- /* Assign the max_radii to the fillet data's radii. */
- for (const int i : IndexRange(num)) {
- radii[i] = std::min(radii[i], max_radii[i]);
- }
-}
-
-/*
- * Create a mapping from each vertex in the destination spline to that of the source spline.
- * Used for copying the data from the source spline.
- */
-static Array<int> create_dst_to_src_map(const Span<int> point_counts, const int total_points)
-{
- Array<int> map(total_points);
- MutableSpan<int> map_span{map};
- int index = 0;
-
- for (const int i : point_counts.index_range()) {
- map_span.slice(index, point_counts[i]).fill(i);
- index += point_counts[i];
- }
-
- BLI_assert(index == total_points);
-
- return map;
-}
-
-template<typename T>
-static void copy_attribute_by_mapping(const Span<T> src,
- MutableSpan<T> dst,
- const Span<int> mapping)
-{
- for (const int i : dst.index_range()) {
- dst[i] = src[mapping[i]];
- }
-}
-
-/* Copy radii and tilts from source spline to destination. Positions are handled later in update
- * positions methods. */
-static void copy_common_attributes_by_mapping(const Spline &src,
- Spline &dst,
- const Span<int> mapping)
-{
- copy_attribute_by_mapping(src.radii(), dst.radii(), mapping);
- copy_attribute_by_mapping(src.tilts(), dst.tilts(), mapping);
-
- src.attributes.foreach_attribute(
- [&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) {
- std::optional<GSpan> src_attribute = src.attributes.get_for_read(attribute_id);
- if (dst.attributes.create(attribute_id, meta_data.data_type)) {
- std::optional<GMutableSpan> dst_attribute = dst.attributes.get_for_write(attribute_id);
- if (dst_attribute) {
- attribute_math::convert_to_static_type(dst_attribute->type(), [&](auto dummy) {
- using T = decltype(dummy);
- copy_attribute_by_mapping(
- src_attribute->typed<T>(), dst_attribute->typed<T>(), mapping);
- });
- return true;
- }
- }
- BLI_assert_unreachable();
- return false;
- },
- ATTR_DOMAIN_POINT);
-}
-
-/* Update the vertex positions and handle positions of a Bezier spline based on fillet data. */
-static void update_bezier_positions(const FilletData &fd,
- BezierSpline &dst_spline,
- const BezierSpline &src_spline,
- const Span<int> point_counts)
-{
- Span<float> radii(fd.radii);
- Span<float> angles(fd.angles);
- Span<float3> axes(fd.axes);
- Span<float3> positions(fd.positions);
- Span<float3> directions(fd.directions);
-
- const int num = radii.size();
-
- int i_dst = 0;
- for (const int i_src : IndexRange(num)) {
- const int count = point_counts[i_src];
-
- /* Skip if the point count for the vertex is 1. */
- if (count == 1) {
- dst_spline.positions()[i_dst] = src_spline.positions()[i_src];
- dst_spline.handle_types_left()[i_dst] = src_spline.handle_types_left()[i_src];
- dst_spline.handle_types_right()[i_dst] = src_spline.handle_types_right()[i_src];
- dst_spline.handle_positions_left()[i_dst] = src_spline.handle_positions_left()[i_src];
- dst_spline.handle_positions_right()[i_dst] = src_spline.handle_positions_right()[i_src];
- i_dst++;
- continue;
- }
-
- /* Calculate the angle to be formed between any 2 adjacent vertices within the fillet. */
- const float segment_angle = angles[i_src] / (count - 1);
- /* Calculate the handle length for each added vertex. Equation: L = 4R/3 * tan(A/4) */
- const float handle_length = 4.0f * radii[i_src] / 3.0f * tan(segment_angle / 4.0f);
- /* Calculate the distance by which each vertex should be displaced from their initial position.
- */
- const float displacement = radii[i_src] * tan(angles[i_src] / 2.0f);
-
- /* Position the end points of the arc and their handles. */
- const int end_i = i_dst + count - 1;
- const float3 prev_dir = i_src == 0 ? -directions[num - 1] : -directions[i_src - 1];
- const float3 next_dir = directions[i_src];
- dst_spline.positions()[i_dst] = positions[i_src] + displacement * prev_dir;
- dst_spline.positions()[end_i] = positions[i_src] + displacement * next_dir;
- dst_spline.handle_positions_right()[i_dst] = dst_spline.positions()[i_dst] -
- handle_length * prev_dir;
- dst_spline.handle_positions_left()[end_i] = dst_spline.positions()[end_i] -
- handle_length * next_dir;
- dst_spline.handle_types_right()[i_dst] = dst_spline.handle_types_left()[end_i] =
- BEZIER_HANDLE_ALIGN;
- dst_spline.handle_types_left()[i_dst] = dst_spline.handle_types_right()[end_i] =
- BEZIER_HANDLE_VECTOR;
- dst_spline.mark_cache_invalid();
-
- /* Calculate the center of the radius to be formed. */
- const float3 center = get_center(dst_spline.positions()[i_dst] - positions[i_src], fd, i_src);
- /* Calculate the vector of the radius formed by the first vertex. */
- float3 radius_vec = dst_spline.positions()[i_dst] - center;
- float radius;
- radius_vec = math::normalize_and_get_length(radius_vec, radius);
-
- dst_spline.handle_types_right().slice(1, count - 2).fill(BEZIER_HANDLE_ALIGN);
- dst_spline.handle_types_left().slice(1, count - 2).fill(BEZIER_HANDLE_ALIGN);
-
- /* For each of the vertices in between the end points. */
- for (const int j : IndexRange(1, count - 2)) {
- int index = i_dst + j;
- /* Rotate the radius by the segment angle and determine its tangent (used for getting handle
- * directions). */
- float3 new_radius_vec, tangent_vec;
- rotate_normalized_v3_v3v3fl(new_radius_vec, radius_vec, -axes[i_src], segment_angle);
- rotate_normalized_v3_v3v3fl(tangent_vec, new_radius_vec, axes[i_src], M_PI_2);
- radius_vec = new_radius_vec;
- tangent_vec *= handle_length;
-
- /* Adjust the positions of the respective vertex and its handles. */
- dst_spline.positions()[index] = center + new_radius_vec * radius;
- dst_spline.handle_positions_left()[index] = dst_spline.positions()[index] + tangent_vec;
- dst_spline.handle_positions_right()[index] = dst_spline.positions()[index] - tangent_vec;
- }
-
- i_dst += count;
- }
-}
-
-/* Update the vertex positions of a Poly spline based on fillet data. */
-static void update_poly_positions(const FilletData &fd,
- Spline &dst_spline,
- const Spline &src_spline,
- const Span<int> point_counts)
-{
- Span<float> radii(fd.radii);
- Span<float> angles(fd.angles);
- Span<float3> axes(fd.axes);
- Span<float3> positions(fd.positions);
- Span<float3> directions(fd.directions);
-
- const int num = radii.size();
-
- int i_dst = 0;
- for (const int i_src : IndexRange(num)) {
- const int count = point_counts[i_src];
-
- /* Skip if the point count for the vertex is 1. */
- if (count == 1) {
- dst_spline.positions()[i_dst] = src_spline.positions()[i_src];
- i_dst++;
- continue;
- }
-
- const float segment_angle = angles[i_src] / (count - 1);
- const float displacement = radii[i_src] * tan(angles[i_src] / 2.0f);
-
- /* Position the end points of the arc. */
- const int end_i = i_dst + count - 1;
- const float3 prev_dir = i_src == 0 ? -directions[num - 1] : -directions[i_src - 1];
- const float3 next_dir = directions[i_src];
- dst_spline.positions()[i_dst] = positions[i_src] + displacement * prev_dir;
- dst_spline.positions()[end_i] = positions[i_src] + displacement * next_dir;
-
- /* Calculate the center of the radius to be formed. */
- const float3 center = get_center(dst_spline.positions()[i_dst] - positions[i_src], fd, i_src);
- /* Calculate the vector of the radius formed by the first vertex. */
- float3 radius_vec = dst_spline.positions()[i_dst] - center;
-
- for (const int j : IndexRange(1, count - 2)) {
- /* Rotate the radius by the segment angle */
- float3 new_radius_vec;
- rotate_normalized_v3_v3v3fl(new_radius_vec, radius_vec, -axes[i_src], segment_angle);
- radius_vec = new_radius_vec;
-
- dst_spline.positions()[i_dst + j] = center + new_radius_vec;
- }
-
- i_dst += count;
- }
-}
-
-static SplinePtr fillet_spline(const Spline &spline,
- const FilletParam &fillet_param,
- const int spline_offset)
-{
- const int num = spline.size();
- const bool cyclic = spline.is_cyclic();
-
- if (num < 3) {
- return spline.copy();
- }
-
- /* Initialize the point_counts with 1s (at least one vertex on dst for each vertex on src). */
- Array<int> point_counts(num, 1);
-
- int added_count = 0;
- /* Update point_counts array and added_count. */
- FilletData fd = calculate_fillet_data(
- spline, fillet_param, added_count, point_counts, spline_offset);
- if (fillet_param.limit_radius) {
- limit_radii(fd, cyclic);
- }
-
- const int total_points = added_count + num;
- const Array<int> dst_to_src = create_dst_to_src_map(point_counts, total_points);
- SplinePtr dst_spline_ptr = spline.copy_only_settings();
- (*dst_spline_ptr).resize(total_points);
- copy_common_attributes_by_mapping(spline, *dst_spline_ptr, dst_to_src);
-
- switch (spline.type()) {
- case CURVE_TYPE_BEZIER: {
- const BezierSpline &src_spline = static_cast<const BezierSpline &>(spline);
- BezierSpline &dst_spline = static_cast<BezierSpline &>(*dst_spline_ptr);
- if (fillet_param.mode == GEO_NODE_CURVE_FILLET_POLY) {
- dst_spline.handle_types_left().fill(BEZIER_HANDLE_VECTOR);
- dst_spline.handle_types_right().fill(BEZIER_HANDLE_VECTOR);
- update_poly_positions(fd, dst_spline, src_spline, point_counts);
- }
- else {
- update_bezier_positions(fd, dst_spline, src_spline, point_counts);
- }
- break;
- }
- case CURVE_TYPE_POLY: {
- update_poly_positions(fd, *dst_spline_ptr, spline, point_counts);
- break;
- }
- case CURVE_TYPE_NURBS: {
- const NURBSpline &src_spline = static_cast<const NURBSpline &>(spline);
- NURBSpline &dst_spline = static_cast<NURBSpline &>(*dst_spline_ptr);
- copy_attribute_by_mapping(src_spline.weights(), dst_spline.weights(), dst_to_src);
- update_poly_positions(fd, dst_spline, src_spline, point_counts);
- break;
- }
- case CURVE_TYPE_CATMULL_ROM: {
- BLI_assert_unreachable();
- break;
- }
- }
-
- return dst_spline_ptr;
-}
-
-static std::unique_ptr<CurveEval> fillet_curve(const CurveEval &input_curve,
- const FilletParam &fillet_param)
-{
- Span<SplinePtr> input_splines = input_curve.splines();
-
- std::unique_ptr<CurveEval> output_curve = std::make_unique<CurveEval>();
- const int splines_num = input_splines.size();
- output_curve->resize(splines_num);
- MutableSpan<SplinePtr> output_splines = output_curve->splines();
- Array<int> spline_offsets = input_curve.control_point_offsets();
-
- threading::parallel_for(input_splines.index_range(), 128, [&](IndexRange range) {
- for (const int i : range) {
- output_splines[i] = fillet_spline(*input_splines[i], fillet_param, spline_offsets[i]);
- }
- });
- output_curve->attributes = input_curve.attributes;
-
- return output_curve;
-}
-
-static void calculate_curve_fillet(GeometrySet &geometry_set,
- const GeometryNodeCurveFilletMode mode,
- const Field<float> &radius_field,
- const std::optional<Field<int>> &count_field,
- const bool limit_radius)
-{
- if (!geometry_set.has_curves()) {
- return;
- }
-
- FilletParam fillet_param;
- fillet_param.mode = mode;
-
- CurveComponent &component = geometry_set.get_component_for_write<CurveComponent>();
- GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_POINT};
- const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_POINT);
- fn::FieldEvaluator field_evaluator{field_context, domain_size};
-
- field_evaluator.add(radius_field);
-
- if (mode == GEO_NODE_CURVE_FILLET_POLY) {
- field_evaluator.add(*count_field);
- }
-
- field_evaluator.evaluate();
-
- fillet_param.radii = field_evaluator.get_evaluated<float>(0);
- if (fillet_param.radii.is_single() && fillet_param.radii.get_internal_single() < 0.0f) {
- return;
- }
-
- if (mode == GEO_NODE_CURVE_FILLET_POLY) {
- fillet_param.counts = field_evaluator.get_evaluated<int>(1);
- }
-
- fillet_param.limit_radius = limit_radius;
-
- const Curves &src_curves_id = *geometry_set.get_curves_for_read();
- const std::unique_ptr<CurveEval> input_curve = curves_to_curve_eval(*component.get_for_read());
- std::unique_ptr<CurveEval> output_curve = fillet_curve(*input_curve, fillet_param);
-
- Curves *dst_curves_id = curve_eval_to_curves(*output_curve);
- bke::curves_copy_parameters(src_curves_id, *dst_curves_id);
- geometry_set.replace_curves(dst_curves_id);
-}
-
static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Curve");
@@ -629,7 +68,42 @@ static void node_geo_exec(GeoNodeExecParams params)
}
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
- calculate_curve_fillet(geometry_set, mode, radius_field, count_field, limit_radius);
+ if (!geometry_set.has_curves()) {
+ return;
+ }
+
+ const CurveComponent &component = *geometry_set.get_component_for_read<CurveComponent>();
+ const Curves &curves_id = *component.get_for_read();
+ const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry);
+ GeometryComponentFieldContext context{component, 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);
+ 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);
+ 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;
+ }
+ }
});
params.set_output("Curve", std::move(geometry_set));