Cleanup: move some geometry field inputs to more correct header

This commit is contained in:
Jacques Lucke 2024-02-01 12:43:35 +01:00
parent c9ad858d9d
commit 7042db684f
16 changed files with 189 additions and 195 deletions

View File

@ -422,6 +422,47 @@ class CurveLengthFieldInput final : public CurvesFieldInput {
std::optional<AttrDomain> preferred_domain(const bke::CurvesGeometry &curves) const final;
};
class EvaluateAtIndexInput final : public bke::GeometryFieldInput {
private:
fn::Field<int> index_field_;
fn::GField value_field_;
AttrDomain value_field_domain_;
public:
EvaluateAtIndexInput(fn::Field<int> index_field,
fn::GField value_field,
AttrDomain value_field_domain);
GVArray get_varray_for_context(const bke::GeometryFieldContext &context,
const IndexMask &mask) const final;
std::optional<AttrDomain> preferred_domain(const GeometryComponent & /*component*/) const final
{
return value_field_domain_;
}
};
void copy_with_checked_indices(const GVArray &src,
const VArray<int> &indices,
const IndexMask &mask,
GMutableSpan dst);
class EvaluateOnDomainInput final : public bke::GeometryFieldInput {
private:
fn::GField src_field_;
AttrDomain src_domain_;
public:
EvaluateOnDomainInput(fn::GField field, AttrDomain domain);
GVArray get_varray_for_context(const bke::GeometryFieldContext &context,
const IndexMask & /*mask*/) const final;
void for_each_field_input_recursive(FunctionRef<void(const FieldInput &)> fn) const override;
std::optional<AttrDomain> preferred_domain(
const GeometryComponent & /*component*/) const override;
};
bool try_capture_field_on_geometry(MutableAttributeAccessor attributes,
const fn::FieldContext &field_context,
const AttributeIDRef &attribute_id,

View File

@ -594,6 +594,132 @@ std::optional<AttrDomain> NamedLayerSelectionFieldInput::preferred_domain(
return AttrDomain::Layer;
}
template<typename T>
void copy_with_checked_indices(const VArray<T> &src,
const VArray<int> &indices,
const IndexMask &mask,
MutableSpan<T> dst)
{
const IndexRange src_range = src.index_range();
devirtualize_varray2(src, indices, [&](const auto src, const auto indices) {
mask.foreach_index(GrainSize(4096), [&](const int i) {
const int index = indices[i];
if (src_range.contains(index)) {
dst[i] = src[index];
}
else {
dst[i] = {};
}
});
});
}
void copy_with_checked_indices(const GVArray &src,
const VArray<int> &indices,
const IndexMask &mask,
GMutableSpan dst)
{
bke::attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
using T = decltype(dummy);
copy_with_checked_indices(src.typed<T>(), indices, mask, dst.typed<T>());
});
}
EvaluateAtIndexInput::EvaluateAtIndexInput(fn::Field<int> index_field,
fn::GField value_field,
AttrDomain value_field_domain)
: bke::GeometryFieldInput(value_field.cpp_type(), "Evaluate at Index"),
index_field_(std::move(index_field)),
value_field_(std::move(value_field)),
value_field_domain_(value_field_domain)
{
}
GVArray EvaluateAtIndexInput::get_varray_for_context(const bke::GeometryFieldContext &context,
const IndexMask &mask) const
{
const std::optional<AttributeAccessor> attributes = context.attributes();
if (!attributes) {
return {};
}
const bke::GeometryFieldContext value_context{context, value_field_domain_};
fn::FieldEvaluator value_evaluator{value_context, attributes->domain_size(value_field_domain_)};
value_evaluator.add(value_field_);
value_evaluator.evaluate();
const GVArray &values = value_evaluator.get_evaluated(0);
fn::FieldEvaluator index_evaluator{context, &mask};
index_evaluator.add(index_field_);
index_evaluator.evaluate();
const VArray<int> indices = index_evaluator.get_evaluated<int>(0);
GArray<> dst_array(values.type(), mask.min_array_size());
copy_with_checked_indices(values, indices, mask, dst_array);
return GVArray::ForGArray(std::move(dst_array));
}
EvaluateOnDomainInput::EvaluateOnDomainInput(fn::GField field, AttrDomain domain)
: bke::GeometryFieldInput(field.cpp_type(), "Evaluate on Domain"),
src_field_(std::move(field)),
src_domain_(domain)
{
}
GVArray EvaluateOnDomainInput::get_varray_for_context(const bke::GeometryFieldContext &context,
const IndexMask & /*mask*/) const
{
const AttrDomain dst_domain = context.domain();
const int dst_domain_size = context.attributes()->domain_size(dst_domain);
const CPPType &cpp_type = src_field_.cpp_type();
if (context.type() == GeometryComponent::Type::GreasePencil &&
(src_domain_ == AttrDomain::Layer) != (dst_domain == AttrDomain::Layer))
{
/* Evaluate field just for the current layer. */
if (src_domain_ == AttrDomain::Layer) {
const bke::GeometryFieldContext src_domain_context{context, AttrDomain::Layer};
const int layer_index = context.grease_pencil_layer_index();
const IndexMask single_layer_mask = IndexRange(layer_index, 1);
fn::FieldEvaluator value_evaluator{src_domain_context, &single_layer_mask};
value_evaluator.add(src_field_);
value_evaluator.evaluate();
const GVArray &values = value_evaluator.get_evaluated(0);
BUFFER_FOR_CPP_TYPE_VALUE(cpp_type, value);
BLI_SCOPED_DEFER([&]() { cpp_type.destruct(value); });
values.get_to_uninitialized(layer_index, value);
return GVArray::ForSingle(cpp_type, dst_domain_size, value);
}
/* We don't adapt from curve to layer domain currently. */
return GVArray::ForSingleDefault(cpp_type, dst_domain_size);
}
const bke::AttributeAccessor attributes = *context.attributes();
const bke::GeometryFieldContext other_domain_context{context, src_domain_};
const int64_t src_domain_size = attributes.domain_size(src_domain_);
GArray<> values(cpp_type, src_domain_size);
fn::FieldEvaluator value_evaluator{other_domain_context, src_domain_size};
value_evaluator.add_with_destination(src_field_, values.as_mutable_span());
value_evaluator.evaluate();
return attributes.adapt_domain(GVArray::ForGArray(std::move(values)), src_domain_, dst_domain);
}
void EvaluateOnDomainInput::for_each_field_input_recursive(
FunctionRef<void(const FieldInput &)> fn) const
{
src_field_.node().for_each_field_input_recursive(fn);
}
std::optional<AttrDomain> EvaluateOnDomainInput::preferred_domain(
const GeometryComponent & /*component*/) const
{
return src_domain_;
}
} // namespace blender::bke
/* -------------------------------------------------------------------- */

View File

@ -61,45 +61,6 @@ void get_closest_in_bvhtree(BVHTreeFromMesh &tree_data,
int apply_offset_in_cyclic_range(IndexRange range, int start_index, int offset);
class EvaluateAtIndexInput final : public bke::GeometryFieldInput {
private:
Field<int> index_field_;
GField value_field_;
AttrDomain value_field_domain_;
public:
EvaluateAtIndexInput(Field<int> index_field, GField value_field, AttrDomain value_field_domain);
GVArray get_varray_for_context(const bke::GeometryFieldContext &context,
const IndexMask &mask) const final;
std::optional<AttrDomain> preferred_domain(const GeometryComponent & /*component*/) const final
{
return value_field_domain_;
}
};
class EvaluateOnDomainInput final : public bke::GeometryFieldInput {
private:
GField src_field_;
AttrDomain src_domain_;
public:
EvaluateOnDomainInput(GField field, AttrDomain domain);
GVArray get_varray_for_context(const bke::GeometryFieldContext &context,
const IndexMask & /*mask*/) const final;
void for_each_field_input_recursive(FunctionRef<void(const FieldInput &)> fn) const override;
std::optional<AttrDomain> preferred_domain(
const GeometryComponent & /*component*/) const override;
};
void copy_with_checked_indices(const GVArray &src,
const VArray<int> &indices,
const IndexMask &mask,
GMutableSpan dst);
void mix_baked_data_item(eNodeSocketDatatype socket_type,
void *prev,
const void *next,

View File

@ -100,12 +100,12 @@ static void node_geo_exec(GeoNodeExecParams params)
if (params.output_is_required("Curve Index")) {
params.set_output(
"Curve Index",
Field<int>(std::make_shared<EvaluateAtIndexInput>(
Field<int>(std::make_shared<bke::EvaluateAtIndexInput>(
point_index, Field<int>(std::make_shared<CurveOfPointInput>()), AttrDomain::Point)));
}
if (params.output_is_required("Index in Curve")) {
params.set_output("Index in Curve",
Field<int>(std::make_shared<EvaluateAtIndexInput>(
Field<int>(std::make_shared<bke::EvaluateAtIndexInput>(
point_index,
Field<int>(std::make_shared<PointIndexInCurveInput>()),
AttrDomain::Point)));

View File

@ -223,7 +223,7 @@ static void node_geo_exec(GeoNodeExecParams params)
const Field<int> curve_index = params.extract_input<Field<int>>("Curve Index");
if (params.output_is_required("Total")) {
params.set_output("Total",
Field<int>(std::make_shared<EvaluateAtIndexInput>(
Field<int>(std::make_shared<bke::EvaluateAtIndexInput>(
curve_index,
Field<int>(std::make_shared<CurvePointCountInput>()),
AttrDomain::Curve)));

View File

@ -17,44 +17,6 @@
#include "NOD_socket_search_link.hh"
namespace blender::nodes {
EvaluateAtIndexInput::EvaluateAtIndexInput(Field<int> index_field,
GField value_field,
AttrDomain value_field_domain)
: bke::GeometryFieldInput(value_field.cpp_type(), "Evaluate at Index"),
index_field_(std::move(index_field)),
value_field_(std::move(value_field)),
value_field_domain_(value_field_domain)
{
}
GVArray EvaluateAtIndexInput::get_varray_for_context(const bke::GeometryFieldContext &context,
const IndexMask &mask) const
{
const std::optional<AttributeAccessor> attributes = context.attributes();
if (!attributes) {
return {};
}
const bke::GeometryFieldContext value_context{context, value_field_domain_};
FieldEvaluator value_evaluator{value_context, attributes->domain_size(value_field_domain_)};
value_evaluator.add(value_field_);
value_evaluator.evaluate();
const GVArray &values = value_evaluator.get_evaluated(0);
FieldEvaluator index_evaluator{context, &mask};
index_evaluator.add(index_field_);
index_evaluator.evaluate();
const VArray<int> indices = index_evaluator.get_evaluated<int>(0);
GArray<> dst_array(values.type(), mask.min_array_size());
copy_with_checked_indices(values, indices, mask, dst_array);
return GVArray::ForGArray(std::move(dst_array));
}
} // namespace blender::nodes
namespace blender::nodes::node_geo_evaluate_at_index_cc {
static void node_declare(NodeDeclarationBuilder &b)
@ -109,7 +71,7 @@ static void node_geo_exec(GeoNodeExecParams params)
const bNode &node = params.node();
const AttrDomain domain = AttrDomain(node.custom1);
GField output_field{std::make_shared<EvaluateAtIndexInput>(
GField output_field{std::make_shared<bke::EvaluateAtIndexInput>(
params.extract_input<Field<int>>("Index"), params.extract_input<GField>("Value"), domain)};
params.set_output<GField>("Value", std::move(output_field));
}

View File

@ -19,71 +19,6 @@
#include "NOD_socket_search_link.hh"
namespace blender::nodes {
EvaluateOnDomainInput::EvaluateOnDomainInput(GField field, AttrDomain domain)
: bke::GeometryFieldInput(field.cpp_type(), "Evaluate on Domain"),
src_field_(std::move(field)),
src_domain_(domain)
{
}
GVArray EvaluateOnDomainInput::get_varray_for_context(const bke::GeometryFieldContext &context,
const IndexMask & /*mask*/) const
{
const AttrDomain dst_domain = context.domain();
const int dst_domain_size = context.attributes()->domain_size(dst_domain);
const CPPType &cpp_type = src_field_.cpp_type();
if (context.type() == GeometryComponent::Type::GreasePencil &&
(src_domain_ == AttrDomain::Layer) != (dst_domain == AttrDomain::Layer))
{
/* Evaluate field just for the current layer. */
if (src_domain_ == AttrDomain::Layer) {
const bke::GeometryFieldContext src_domain_context{context, AttrDomain::Layer};
const int layer_index = context.grease_pencil_layer_index();
const IndexMask single_layer_mask = IndexRange(layer_index, 1);
FieldEvaluator value_evaluator{src_domain_context, &single_layer_mask};
value_evaluator.add(src_field_);
value_evaluator.evaluate();
const GVArray &values = value_evaluator.get_evaluated(0);
BUFFER_FOR_CPP_TYPE_VALUE(cpp_type, value);
BLI_SCOPED_DEFER([&]() { cpp_type.destruct(value); });
values.get_to_uninitialized(layer_index, value);
return GVArray::ForSingle(cpp_type, dst_domain_size, value);
}
/* We don't adapt from curve to layer domain currently. */
return GVArray::ForSingleDefault(cpp_type, dst_domain_size);
}
const bke::AttributeAccessor attributes = *context.attributes();
const bke::GeometryFieldContext other_domain_context{context, src_domain_};
const int64_t src_domain_size = attributes.domain_size(src_domain_);
GArray<> values(cpp_type, src_domain_size);
FieldEvaluator value_evaluator{other_domain_context, src_domain_size};
value_evaluator.add_with_destination(src_field_, values.as_mutable_span());
value_evaluator.evaluate();
return attributes.adapt_domain(GVArray::ForGArray(std::move(values)), src_domain_, dst_domain);
}
void EvaluateOnDomainInput::for_each_field_input_recursive(
FunctionRef<void(const FieldInput &)> fn) const
{
src_field_.node().for_each_field_input_recursive(fn);
}
std::optional<AttrDomain> EvaluateOnDomainInput::preferred_domain(
const GeometryComponent & /*component*/) const
{
return src_domain_;
}
} // namespace blender::nodes
namespace blender::nodes::node_geo_evaluate_on_domain_cc {
static void node_declare(NodeDeclarationBuilder &b)
@ -130,7 +65,7 @@ static void node_geo_exec(GeoNodeExecParams params)
const AttrDomain domain = AttrDomain(node.custom1);
GField src_field = params.extract_input<GField>("Value");
GField dst_field{std::make_shared<EvaluateOnDomainInput>(std::move(src_field), domain)};
GField dst_field{std::make_shared<bke::EvaluateOnDomainInput>(std::move(src_field), domain)};
params.set_output<GField>("Value", std::move(dst_field));
}

View File

@ -173,7 +173,7 @@ static void node_geo_exec(GeoNodeExecParams params)
const Field<int> edge_index = params.extract_input<Field<int>>("Edge Index");
if (params.output_is_required("Total")) {
params.set_output("Total",
Field<int>(std::make_shared<EvaluateAtIndexInput>(
Field<int>(std::make_shared<bke::EvaluateAtIndexInput>(
edge_index,
Field<int>(std::make_shared<CornersOfEdgeCountInput>()),
AttrDomain::Edge)));

View File

@ -175,7 +175,7 @@ static void node_geo_exec(GeoNodeExecParams params)
const Field<int> face_index = params.extract_input<Field<int>>("Face Index");
if (params.output_is_required("Total")) {
params.set_output("Total",
Field<int>(std::make_shared<EvaluateAtIndexInput>(
Field<int>(std::make_shared<bke::EvaluateAtIndexInput>(
face_index,
Field<int>(std::make_shared<CornersOfFaceCountInput>()),
AttrDomain::Face)));

View File

@ -181,7 +181,7 @@ static void node_geo_exec(GeoNodeExecParams params)
const Field<int> vert_index = params.extract_input<Field<int>>("Vertex Index");
if (params.output_is_required("Total")) {
params.set_output("Total",
Field<int>(std::make_shared<EvaluateAtIndexInput>(
Field<int>(std::make_shared<bke::EvaluateAtIndexInput>(
vert_index,
Field<int>(std::make_shared<CornersOfVertCountInput>()),
AttrDomain::Point)));

View File

@ -103,14 +103,14 @@ static void node_geo_exec(GeoNodeExecParams params)
const Field<int> corner_index = params.extract_input<Field<int>>("Corner Index");
if (params.output_is_required("Next Edge Index")) {
params.set_output("Next Edge Index",
Field<int>(std::make_shared<EvaluateAtIndexInput>(
Field<int>(std::make_shared<bke::EvaluateAtIndexInput>(
corner_index,
Field<int>(std::make_shared<CornerNextEdgeFieldInput>()),
AttrDomain::Corner)));
}
if (params.output_is_required("Previous Edge Index")) {
params.set_output("Previous Edge Index",
Field<int>(std::make_shared<EvaluateAtIndexInput>(
Field<int>(std::make_shared<bke::EvaluateAtIndexInput>(
corner_index,
Field<int>(std::make_shared<CornerPreviousEdgeFieldInput>()),
AttrDomain::Corner)));

View File

@ -186,7 +186,7 @@ static void node_geo_exec(GeoNodeExecParams params)
const Field<int> vert_index = params.extract_input<Field<int>>("Vertex Index");
if (params.output_is_required("Total")) {
params.set_output("Total",
Field<int>(std::make_shared<EvaluateAtIndexInput>(
Field<int>(std::make_shared<bke::EvaluateAtIndexInput>(
vert_index,
Field<int>(std::make_shared<EdgesOfVertCountInput>()),
AttrDomain::Point)));

View File

@ -93,14 +93,14 @@ static void node_geo_exec(GeoNodeExecParams params)
const Field<int> corner_index = params.extract_input<Field<int>>("Corner Index");
if (params.output_is_required("Face Index")) {
params.set_output("Face Index",
Field<int>(std::make_shared<EvaluateAtIndexInput>(
Field<int>(std::make_shared<bke::EvaluateAtIndexInput>(
corner_index,
Field<int>(std::make_shared<CornerFaceIndexInput>()),
AttrDomain::Corner)));
}
if (params.output_is_required("Index in Face")) {
params.set_output("Index in Face",
Field<int>(std::make_shared<EvaluateAtIndexInput>(
Field<int>(std::make_shared<bke::EvaluateAtIndexInput>(
corner_index,
Field<int>(std::make_shared<CornerIndexInFaceInput>()),
AttrDomain::Corner)));

View File

@ -56,7 +56,7 @@ class CornerVertFieldInput final : public bke::MeshFieldInput {
static void node_geo_exec(GeoNodeExecParams params)
{
params.set_output("Vertex Index",
Field<int>(std::make_shared<EvaluateAtIndexInput>(
Field<int>(std::make_shared<bke::EvaluateAtIndexInput>(
params.extract_input<Field<int>>("Corner Index"),
Field<int>(std::make_shared<CornerVertFieldInput>()),
AttrDomain::Corner)));

View File

@ -15,37 +15,6 @@
namespace blender::nodes {
template<typename T>
void copy_with_checked_indices(const VArray<T> &src,
const VArray<int> &indices,
const IndexMask &mask,
MutableSpan<T> dst)
{
const IndexRange src_range = src.index_range();
devirtualize_varray2(src, indices, [&](const auto src, const auto indices) {
mask.foreach_index(GrainSize(4096), [&](const int i) {
const int index = indices[i];
if (src_range.contains(index)) {
dst[i] = src[index];
}
else {
dst[i] = {};
}
});
});
}
void copy_with_checked_indices(const GVArray &src,
const VArray<int> &indices,
const IndexMask &mask,
GMutableSpan dst)
{
bke::attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
using T = decltype(dummy);
copy_with_checked_indices(src.typed<T>(), indices, mask, dst.typed<T>());
});
}
} // namespace blender::nodes
namespace blender::nodes::node_geo_sample_index_cc {
@ -220,7 +189,7 @@ class SampleIndexFunction : public mf::MultiFunction {
});
}
else {
copy_with_checked_indices(*src_data_, indices, mask, dst);
bke::copy_with_checked_indices(*src_data_, indices, mask, dst);
}
}
};

View File

@ -57,13 +57,13 @@ static void set_curve_normal(bke::CurvesGeometry &curves,
fn::make_constant_field<int8_t>(mode));
if (mode == NORMAL_MODE_FREE) {
bke::try_capture_field_on_geometry(
curves.attributes_for_write(),
point_context,
"custom_normal",
AttrDomain::Point,
Field<bool>(std::make_shared<EvaluateOnDomainInput>(selection_field, AttrDomain::Curve)),
custom_normal);
bke::try_capture_field_on_geometry(curves.attributes_for_write(),
point_context,
"custom_normal",
AttrDomain::Point,
Field<bool>(std::make_shared<bke::EvaluateOnDomainInput>(
selection_field, AttrDomain::Curve)),
custom_normal);
}
curves.tag_normals_changed();