Changeset View
Changeset View
Standalone View
Standalone View
source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc
| Show First 20 Lines • Show All 170 Lines • ▼ Show 20 Lines | static std::unique_ptr<CurveEval> resample_curve(const CurveComponent *component, | ||||
| const SampleModeParam &mode_param) | const SampleModeParam &mode_param) | ||||
| { | { | ||||
| const CurveEval *input_curve = component->get_for_read(); | const CurveEval *input_curve = component->get_for_read(); | ||||
| GeometryComponentFieldContext field_context{*component, ATTR_DOMAIN_CURVE}; | GeometryComponentFieldContext field_context{*component, ATTR_DOMAIN_CURVE}; | ||||
| const int domain_size = component->attribute_domain_size(ATTR_DOMAIN_CURVE); | const int domain_size = component->attribute_domain_size(ATTR_DOMAIN_CURVE); | ||||
| Span<SplinePtr> input_splines = input_curve->splines(); | Span<SplinePtr> input_splines = input_curve->splines(); | ||||
| /* Some splines (e.g. NURBS with only one point) might have no evaluated points. In that case, | |||||
| * they cannot be resampled at all. Keep track of the indices of "good" splines to allow removing | |||||
| * the others from the result. */ | |||||
| Vector<int64_t> result_spline_indices; | |||||
| result_spline_indices.reserve(domain_size); | |||||
| for (const int64_t i : input_splines.index_range()) { | |||||
| if (input_splines[i]->evaluated_points_size() > 0) { | |||||
| result_spline_indices.append(i); | |||||
| } | |||||
| } | |||||
| const IndexMask result_mask(result_spline_indices); | |||||
| std::unique_ptr<CurveEval> output_curve = std::make_unique<CurveEval>(); | std::unique_ptr<CurveEval> output_curve = std::make_unique<CurveEval>(); | ||||
| output_curve->resize(input_splines.size()); | output_curve->resize(result_mask.size()); | ||||
| MutableSpan<SplinePtr> output_splines = output_curve->splines(); | MutableSpan<SplinePtr> output_splines = output_curve->splines(); | ||||
| if (mode_param.mode == GEO_NODE_CURVE_RESAMPLE_COUNT) { | if (mode_param.mode == GEO_NODE_CURVE_RESAMPLE_COUNT) { | ||||
| fn::FieldEvaluator evaluator{field_context, domain_size}; | fn::FieldEvaluator evaluator{field_context, domain_size}; | ||||
| evaluator.add(*mode_param.count); | evaluator.add(*mode_param.count); | ||||
| evaluator.evaluate(); | evaluator.evaluate(); | ||||
| const VArray<int> &cuts = evaluator.get_evaluated<int>(0); | const VArray<int> &cuts = evaluator.get_evaluated<int>(0); | ||||
| threading::parallel_for(input_splines.index_range(), 128, [&](IndexRange range) { | threading::parallel_for(result_mask.index_range(), 128, [&](IndexRange range) { | ||||
| for (const int i : range) { | for (const int i : range) { | ||||
| BLI_assert(mode_param.count); | BLI_assert(mode_param.count); | ||||
| output_splines[i] = resample_spline(*input_splines[i], std::max(cuts[i], 1)); | output_splines[i] = resample_spline(*input_splines[result_mask[i]], std::max(cuts[i], 1)); | ||||
| } | } | ||||
| }); | }); | ||||
| } | } | ||||
| else if (mode_param.mode == GEO_NODE_CURVE_RESAMPLE_LENGTH) { | else if (mode_param.mode == GEO_NODE_CURVE_RESAMPLE_LENGTH) { | ||||
| fn::FieldEvaluator evaluator{field_context, domain_size}; | fn::FieldEvaluator evaluator{field_context, domain_size}; | ||||
| evaluator.add(*mode_param.length); | evaluator.add(*mode_param.length); | ||||
| evaluator.evaluate(); | evaluator.evaluate(); | ||||
| const VArray<float> &lengths = evaluator.get_evaluated<float>(0); | const VArray<float> &lengths = evaluator.get_evaluated<float>(0); | ||||
| threading::parallel_for(input_splines.index_range(), 128, [&](IndexRange range) { | threading::parallel_for(result_mask.index_range(), 128, [&](IndexRange range) { | ||||
| for (const int i : range) { | for (const int i : range) { | ||||
| const Spline &src = *input_splines[result_mask[i]]; | |||||
| /* Don't allow asymptotic count increase for low resolution values. */ | /* Don't allow asymptotic count increase for low resolution values. */ | ||||
| const float divide_length = std::max(lengths[i], 0.0001f); | const float divide_length = std::max(lengths[i], 0.0001f); | ||||
| const float spline_length = input_splines[i]->length(); | const float spline_length = src.length(); | ||||
| const int count = std::max(int(spline_length / divide_length) + 1, 1); | const int count = std::max(int(spline_length / divide_length) + 1, 1); | ||||
| output_splines[i] = resample_spline(*input_splines[i], count); | output_splines[i] = resample_spline(src, count); | ||||
| } | } | ||||
| }); | }); | ||||
| } | } | ||||
| else if (mode_param.mode == GEO_NODE_CURVE_RESAMPLE_EVALUATED) { | else if (mode_param.mode == GEO_NODE_CURVE_RESAMPLE_EVALUATED) { | ||||
| threading::parallel_for(input_splines.index_range(), 128, [&](IndexRange range) { | threading::parallel_for(result_mask.index_range(), 128, [&](IndexRange range) { | ||||
| for (const int i : range) { | for (const int i : range) { | ||||
| output_splines[i] = resample_spline_evaluated(*input_splines[i]); | output_splines[i] = resample_spline_evaluated(*input_splines[result_mask[i]]); | ||||
| } | } | ||||
| }); | }); | ||||
| } | } | ||||
| if (result_mask.size() == domain_size) { | |||||
| output_curve->attributes = input_curve->attributes; | output_curve->attributes = input_curve->attributes; | ||||
| } | |||||
| else { | |||||
| copy_all_attributes_with_mask(input_curve->attributes, output_curve->attributes, result_mask); | |||||
| } | |||||
| return output_curve; | return output_curve; | ||||
| } | } | ||||
| static void geometry_set_curve_resample(GeometrySet &geometry_set, | static void geometry_set_curve_resample(GeometrySet &geometry_set, | ||||
| const SampleModeParam &mode_param) | const SampleModeParam &mode_param) | ||||
| { | { | ||||
| if (!geometry_set.has_curve()) { | if (!geometry_set.has_curve()) { | ||||
| ▲ Show 20 Lines • Show All 53 Lines • Show Last 20 Lines | |||||