Fix: missing clamping in single mode in Sample Index node

This commit is contained in:
Jacques Lucke 2023-01-20 14:33:06 +01:00
parent b6278c5a96
commit d79abb5d4f
1 changed files with 22 additions and 12 deletions

View File

@ -298,6 +298,7 @@ static void node_geo_exec(GeoNodeExecParams params)
const NodeGeometrySampleIndex &storage = node_storage(params.node());
const eCustomDataType data_type = eCustomDataType(storage.data_type);
const eAttrDomain domain = eAttrDomain(storage.domain);
const bool use_clamp = bool(storage.clamp);
GField value_field = get_input_attribute_field(params, data_type);
ValueOrField<int> index_value_or_field = params.extract_input<ValueOrField<int>>("Index");
@ -307,24 +308,33 @@ static void node_geo_exec(GeoNodeExecParams params)
if (index_value_or_field.is_field()) {
/* If the index is a field, the output has to be a field that still depends on the input. */
auto fn = std::make_shared<SampleIndexFunction>(
std::move(geometry), std::move(value_field), domain, bool(storage.clamp));
std::move(geometry), std::move(value_field), domain, use_clamp);
auto op = FieldOperation::Create(std::move(fn), {index_value_or_field.as_field()});
output_field = GField(std::move(op));
}
else if (const GeometryComponent *component = find_source_component(geometry, domain)) {
/* Optimization for the case when the index is a single value. Here only that one index has to
* be evaluated. */
const int index = index_value_or_field.as_value();
const IndexMask mask = IndexRange(index, 1);
bke::GeometryFieldContext geometry_context(*component, domain);
FieldEvaluator evaluator(geometry_context, &mask);
evaluator.add(value_field);
evaluator.evaluate();
const GVArray &data = evaluator.get_evaluated(0);
BUFFER_FOR_CPP_TYPE_VALUE(cpp_type, buffer);
data.get_to_uninitialized(index, buffer);
output_field = fn::make_constant_field(cpp_type, buffer);
cpp_type.destruct(buffer);
const int domain_size = component->attribute_domain_size(domain);
int index = index_value_or_field.as_value();
if (use_clamp) {
index = std::clamp(index, 0, domain_size - 1);
}
if (index >= 0 && index < domain_size) {
const IndexMask mask = IndexRange(index, 1);
bke::GeometryFieldContext geometry_context(*component, domain);
FieldEvaluator evaluator(geometry_context, &mask);
evaluator.add(value_field);
evaluator.evaluate();
const GVArray &data = evaluator.get_evaluated(0);
BUFFER_FOR_CPP_TYPE_VALUE(cpp_type, buffer);
data.get_to_uninitialized(index, buffer);
output_field = fn::make_constant_field(cpp_type, buffer);
cpp_type.destruct(buffer);
}
else {
output_field = fn::make_constant_field(cpp_type, cpp_type.default_value());
}
}
else {
/* Output default value if there is no geometry. */