Geometry Nodes: simplify using selection when evaluating fields
We often had to use two `FieldEvaluator` instances to first evaluate the selection and then the remaining fields. Now both can be done with a single `FieldEvaluator`. This results in less boilerplate code in many cases. Performance is not affected by this change. In a separate patch we could improve performance by reusing evaluated sub-fields that are used by the selection and the other fields. Differential Revision: https://developer.blender.org/D13571
This commit is contained in:
parent
b44a500988
commit
8e2c9f2dd3
Notes:
blender-bot
2023-02-14 08:28:46 +01:00
Referenced by commit 367b484841
, Fix T94166: set handle position node crashed after refactor
Referenced by issue #94166, Geometry Nodes: set handle position node crashed in lastest 3.1 alpha version
|
@ -313,6 +313,9 @@ class FieldEvaluator : NonMovable, NonCopyable {
|
|||
Vector<OutputPointerInfo> output_pointer_infos_;
|
||||
bool is_evaluated_ = false;
|
||||
|
||||
Field<bool> selection_field_;
|
||||
IndexMask selection_mask_;
|
||||
|
||||
public:
|
||||
/** Takes #mask by pointer because the mask has to live longer than the evaluator. */
|
||||
FieldEvaluator(const FieldContext &context, const IndexMask *mask)
|
||||
|
@ -332,6 +335,18 @@ class FieldEvaluator : NonMovable, NonCopyable {
|
|||
BLI_assert(is_evaluated_);
|
||||
}
|
||||
|
||||
/**
|
||||
* The selection field is evaluated first to determine which indices of the other fields should
|
||||
* be evaluated. Calling this method multiple times will just replace the previously set
|
||||
* selection field. Only the elements selected by both this selection and the selection provided
|
||||
* in the constructor are calculated. If no selection field is set, it is assumed that all
|
||||
* indices passed to the constructor are selected.
|
||||
*/
|
||||
void set_selection(Field<bool> selection)
|
||||
{
|
||||
selection_field_ = std::move(selection);
|
||||
}
|
||||
|
||||
/**
|
||||
* \param field: Field to add to the evaluator.
|
||||
* \param dst: Mutable virtual array that the evaluated result for this field is be written into.
|
||||
|
@ -403,6 +418,8 @@ class FieldEvaluator : NonMovable, NonCopyable {
|
|||
return this->get_evaluated(field_index).typed<T>();
|
||||
}
|
||||
|
||||
IndexMask get_evaluated_selection_as_mask();
|
||||
|
||||
/**
|
||||
* Retrieve the output of an evaluated boolean field and convert it to a mask, which can be used
|
||||
* to avoid calculations for unnecessary elements later on. The evaluator will own the indices in
|
||||
|
|
|
@ -624,7 +624,7 @@ FieldInput::FieldInput(const CPPType &type, std::string debug_name)
|
|||
* FieldEvaluator.
|
||||
*/
|
||||
|
||||
static Vector<int64_t> indices_from_selection(const VArray<bool> &selection)
|
||||
static Vector<int64_t> indices_from_selection(IndexMask mask, const VArray<bool> &selection)
|
||||
{
|
||||
/* If the selection is just a single value, it's best to avoid calling this
|
||||
* function when constructing an IndexMask and use an IndexRange instead. */
|
||||
|
@ -633,14 +633,14 @@ static Vector<int64_t> indices_from_selection(const VArray<bool> &selection)
|
|||
Vector<int64_t> indices;
|
||||
if (selection.is_span()) {
|
||||
Span<bool> span = selection.get_internal_span();
|
||||
for (const int64_t i : span.index_range()) {
|
||||
for (const int64_t i : mask) {
|
||||
if (span[i]) {
|
||||
indices.append(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (const int i : selection.index_range()) {
|
||||
for (const int i : mask) {
|
||||
if (selection[i]) {
|
||||
indices.append(i);
|
||||
}
|
||||
|
@ -681,14 +681,36 @@ int FieldEvaluator::add(GField field)
|
|||
return field_index;
|
||||
}
|
||||
|
||||
static IndexMask evaluate_selection(const Field<bool> &selection_field,
|
||||
const FieldContext &context,
|
||||
IndexMask full_mask,
|
||||
ResourceScope &scope)
|
||||
{
|
||||
if (selection_field) {
|
||||
VArray<bool> selection =
|
||||
evaluate_fields(scope, {selection_field}, full_mask, context)[0].typed<bool>();
|
||||
if (selection.is_single()) {
|
||||
if (selection.get_internal_single()) {
|
||||
return full_mask;
|
||||
}
|
||||
return IndexRange(0);
|
||||
}
|
||||
return scope.add_value(indices_from_selection(full_mask, selection)).as_span();
|
||||
}
|
||||
return full_mask;
|
||||
}
|
||||
|
||||
void FieldEvaluator::evaluate()
|
||||
{
|
||||
BLI_assert_msg(!is_evaluated_, "Cannot evaluate fields twice.");
|
||||
|
||||
selection_mask_ = evaluate_selection(selection_field_, context_, mask_, scope_);
|
||||
|
||||
Array<GFieldRef> fields(fields_to_evaluate_.size());
|
||||
for (const int i : fields_to_evaluate_.index_range()) {
|
||||
fields[i] = fields_to_evaluate_[i];
|
||||
}
|
||||
evaluated_varrays_ = evaluate_fields(scope_, fields, mask_, context_, dst_varrays_);
|
||||
evaluated_varrays_ = evaluate_fields(scope_, fields, selection_mask_, context_, dst_varrays_);
|
||||
BLI_assert(fields_to_evaluate_.size() == evaluated_varrays_.size());
|
||||
for (const int i : fields_to_evaluate_.index_range()) {
|
||||
OutputPointerInfo &info = output_pointer_infos_[i];
|
||||
|
@ -710,7 +732,13 @@ IndexMask FieldEvaluator::get_evaluated_as_mask(const int field_index)
|
|||
return IndexRange(0);
|
||||
}
|
||||
|
||||
return scope_.add_value(indices_from_selection(varray)).as_span();
|
||||
return scope_.add_value(indices_from_selection(mask_, varray)).as_span();
|
||||
}
|
||||
|
||||
IndexMask FieldEvaluator::get_evaluated_selection_as_mask()
|
||||
{
|
||||
BLI_assert(is_evaluated_);
|
||||
return selection_mask_;
|
||||
}
|
||||
|
||||
} // namespace blender::fn
|
||||
|
|
|
@ -399,16 +399,12 @@ static Array<float> calc_full_density_factors_with_selection(const MeshComponent
|
|||
GeometryComponentFieldContext field_context{component, attribute_domain};
|
||||
const int domain_size = component.attribute_domain_size(attribute_domain);
|
||||
|
||||
fn::FieldEvaluator selection_evaluator{field_context, domain_size};
|
||||
selection_evaluator.add(selection_field);
|
||||
selection_evaluator.evaluate();
|
||||
const IndexMask selection_mask = selection_evaluator.get_evaluated_as_mask(0);
|
||||
|
||||
Array<float> densities(domain_size, 0.0f);
|
||||
|
||||
fn::FieldEvaluator density_evaluator{field_context, &selection_mask};
|
||||
density_evaluator.add_with_destination(density_field, densities.as_mutable_span());
|
||||
density_evaluator.evaluate();
|
||||
fn::FieldEvaluator evaluator{field_context, domain_size};
|
||||
evaluator.set_selection(selection_field);
|
||||
evaluator.add_with_destination(density_field, densities.as_mutable_span());
|
||||
evaluator.evaluate();
|
||||
return densities;
|
||||
}
|
||||
|
||||
|
|
|
@ -65,12 +65,24 @@ static void add_instances_from_component(
|
|||
const AttributeDomain domain = ATTR_DOMAIN_POINT;
|
||||
const int domain_size = src_component.attribute_domain_size(domain);
|
||||
|
||||
VArray<bool> pick_instance;
|
||||
VArray<int> indices;
|
||||
VArray<float3> rotations;
|
||||
VArray<float3> scales;
|
||||
|
||||
GeometryComponentFieldContext field_context{src_component, domain};
|
||||
const Field<bool> selection_field = params.get_input<Field<bool>>("Selection");
|
||||
fn::FieldEvaluator selection_evaluator{field_context, domain_size};
|
||||
selection_evaluator.add(selection_field);
|
||||
selection_evaluator.evaluate();
|
||||
const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0);
|
||||
fn::FieldEvaluator evaluator{field_context, domain_size};
|
||||
evaluator.set_selection(selection_field);
|
||||
/* The evaluator could use the component's stable IDs as a destination directly, but only the
|
||||
* selected indices should be copied. */
|
||||
evaluator.add(params.get_input<Field<bool>>("Pick Instance"), &pick_instance);
|
||||
evaluator.add(params.get_input<Field<int>>("Instance Index"), &indices);
|
||||
evaluator.add(params.get_input<Field<float3>>("Rotation"), &rotations);
|
||||
evaluator.add(params.get_input<Field<float3>>("Scale"), &scales);
|
||||
evaluator.evaluate();
|
||||
|
||||
const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
|
||||
|
||||
/* The initial size of the component might be non-zero when this function is called for multiple
|
||||
* component types. */
|
||||
|
@ -83,19 +95,6 @@ static void add_instances_from_component(
|
|||
MutableSpan<float4x4> dst_transforms = dst_component.instance_transforms().slice(start_len,
|
||||
select_len);
|
||||
|
||||
FieldEvaluator field_evaluator{field_context, domain_size};
|
||||
VArray<bool> pick_instance;
|
||||
VArray<int> indices;
|
||||
VArray<float3> rotations;
|
||||
VArray<float3> scales;
|
||||
/* The evaluator could use the component's stable IDs as a destination directly, but only the
|
||||
* selected indices should be copied. */
|
||||
field_evaluator.add(params.get_input<Field<bool>>("Pick Instance"), &pick_instance);
|
||||
field_evaluator.add(params.get_input<Field<int>>("Instance Index"), &indices);
|
||||
field_evaluator.add(params.get_input<Field<float3>>("Rotation"), &rotations);
|
||||
field_evaluator.add(params.get_input<Field<float3>>("Scale"), &scales);
|
||||
field_evaluator.evaluate();
|
||||
|
||||
VArray<float3> positions = src_component.attribute_get_for_read<float3>(
|
||||
"position", domain, {0, 0, 0});
|
||||
|
||||
|
|
|
@ -56,10 +56,12 @@ static void convert_instances_to_points(GeometrySet &geometry_set,
|
|||
GeometryComponentFieldContext field_context{instances, ATTR_DOMAIN_INSTANCE};
|
||||
const int domain_size = instances.attribute_domain_size(ATTR_DOMAIN_INSTANCE);
|
||||
|
||||
fn::FieldEvaluator selection_evaluator{field_context, domain_size};
|
||||
selection_evaluator.add(std::move(selection_field));
|
||||
selection_evaluator.evaluate();
|
||||
const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0);
|
||||
fn::FieldEvaluator evaluator{field_context, domain_size};
|
||||
evaluator.set_selection(std::move(selection_field));
|
||||
evaluator.add(std::move(position_field));
|
||||
evaluator.add(std::move(radius_field));
|
||||
evaluator.evaluate();
|
||||
const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
|
||||
if (selection.is_empty()) {
|
||||
return;
|
||||
}
|
||||
|
@ -69,10 +71,6 @@ static void convert_instances_to_points(GeometrySet &geometry_set,
|
|||
|
||||
PointCloudComponent &points = geometry_set.get_component_for_write<PointCloudComponent>();
|
||||
|
||||
fn::FieldEvaluator evaluator{field_context, &selection};
|
||||
evaluator.add(std::move(position_field));
|
||||
evaluator.add(std::move(radius_field));
|
||||
evaluator.evaluate();
|
||||
const VArray<float3> &positions = evaluator.get_evaluated<float3>(0);
|
||||
copy_attribute_to_points(positions, selection, {(float3 *)pointcloud->co, pointcloud->totpoint});
|
||||
const VArray<float> &radii = evaluator.get_evaluated<float>(1);
|
||||
|
|
|
@ -83,10 +83,15 @@ static void geometry_set_mesh_to_points(GeometrySet &geometry_set,
|
|||
geometry_set.keep_only({GEO_COMPONENT_TYPE_INSTANCES});
|
||||
return;
|
||||
}
|
||||
fn::FieldEvaluator selection_evaluator{field_context, domain_size};
|
||||
selection_evaluator.add(selection_field);
|
||||
selection_evaluator.evaluate();
|
||||
const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0);
|
||||
fn::FieldEvaluator evaluator{field_context, domain_size};
|
||||
evaluator.set_selection(selection_field);
|
||||
/* Evaluating directly into the point cloud doesn't work because we are not using the full
|
||||
* "min_array_size" array but compressing the selected elements into the final array with no
|
||||
* gaps. */
|
||||
evaluator.add(position_field);
|
||||
evaluator.add(radius_field);
|
||||
evaluator.evaluate();
|
||||
const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
|
||||
|
||||
PointCloud *pointcloud = BKE_pointcloud_new_nomain(selection.size());
|
||||
uninitialized_fill_n(pointcloud->radius, pointcloud->totpoint, 0.05f);
|
||||
|
@ -94,13 +99,6 @@ static void geometry_set_mesh_to_points(GeometrySet &geometry_set,
|
|||
PointCloudComponent &point_component =
|
||||
geometry_set.get_component_for_write<PointCloudComponent>();
|
||||
|
||||
/* Evaluating directly into the point cloud doesn't work because we are not using the full
|
||||
* "min_array_size" array but compressing the selected elements into the final array with no
|
||||
* gaps. */
|
||||
fn::FieldEvaluator evaluator{field_context, &selection};
|
||||
evaluator.add(position_field);
|
||||
evaluator.add(radius_field);
|
||||
evaluator.evaluate();
|
||||
copy_attribute_to_points(evaluator.get_evaluated<float3>(0),
|
||||
selection,
|
||||
{(float3 *)pointcloud->co, pointcloud->totpoint});
|
||||
|
|
|
@ -35,19 +35,17 @@ static void rotate_instances(GeoNodeExecParams ¶ms, InstancesComponent &inst
|
|||
GeometryComponentFieldContext field_context{instances_component, ATTR_DOMAIN_INSTANCE};
|
||||
const int domain_size = instances_component.instances_amount();
|
||||
|
||||
fn::FieldEvaluator selection_evaluator{field_context, domain_size};
|
||||
selection_evaluator.add(params.extract_input<Field<bool>>("Selection"));
|
||||
selection_evaluator.evaluate();
|
||||
const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0);
|
||||
fn::FieldEvaluator evaluator{field_context, domain_size};
|
||||
evaluator.set_selection(params.extract_input<Field<bool>>("Selection"));
|
||||
evaluator.add(params.extract_input<Field<float3>>("Rotation"));
|
||||
evaluator.add(params.extract_input<Field<float3>>("Pivot Point"));
|
||||
evaluator.add(params.extract_input<Field<bool>>("Local Space"));
|
||||
evaluator.evaluate();
|
||||
|
||||
fn::FieldEvaluator transforms_evaluator{field_context, &selection};
|
||||
transforms_evaluator.add(params.extract_input<Field<float3>>("Rotation"));
|
||||
transforms_evaluator.add(params.extract_input<Field<float3>>("Pivot Point"));
|
||||
transforms_evaluator.add(params.extract_input<Field<bool>>("Local Space"));
|
||||
transforms_evaluator.evaluate();
|
||||
const VArray<float3> &rotations = transforms_evaluator.get_evaluated<float3>(0);
|
||||
const VArray<float3> &pivots = transforms_evaluator.get_evaluated<float3>(1);
|
||||
const VArray<bool> &local_spaces = transforms_evaluator.get_evaluated<bool>(2);
|
||||
const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
|
||||
const VArray<float3> &rotations = evaluator.get_evaluated<float3>(0);
|
||||
const VArray<float3> &pivots = evaluator.get_evaluated<float3>(1);
|
||||
const VArray<bool> &local_spaces = evaluator.get_evaluated<bool>(2);
|
||||
|
||||
MutableSpan<float4x4> instance_transforms = instances_component.instance_transforms();
|
||||
|
||||
|
|
|
@ -37,19 +37,17 @@ static void scale_instances(GeoNodeExecParams ¶ms, InstancesComponent &insta
|
|||
{
|
||||
GeometryComponentFieldContext field_context{instances_component, ATTR_DOMAIN_INSTANCE};
|
||||
|
||||
fn::FieldEvaluator selection_evaluator{field_context, instances_component.instances_amount()};
|
||||
selection_evaluator.add(params.extract_input<Field<bool>>("Selection"));
|
||||
selection_evaluator.evaluate();
|
||||
const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0);
|
||||
fn::FieldEvaluator evaluator{field_context, instances_component.instances_amount()};
|
||||
evaluator.set_selection(params.extract_input<Field<bool>>("Selection"));
|
||||
evaluator.add(params.extract_input<Field<float3>>("Scale"));
|
||||
evaluator.add(params.extract_input<Field<float3>>("Center"));
|
||||
evaluator.add(params.extract_input<Field<bool>>("Local Space"));
|
||||
evaluator.evaluate();
|
||||
|
||||
fn::FieldEvaluator transforms_evaluator{field_context, &selection};
|
||||
transforms_evaluator.add(params.extract_input<Field<float3>>("Scale"));
|
||||
transforms_evaluator.add(params.extract_input<Field<float3>>("Center"));
|
||||
transforms_evaluator.add(params.extract_input<Field<bool>>("Local Space"));
|
||||
transforms_evaluator.evaluate();
|
||||
const VArray<float3> &scales = transforms_evaluator.get_evaluated<float3>(0);
|
||||
const VArray<float3> &pivots = transforms_evaluator.get_evaluated<float3>(1);
|
||||
const VArray<bool> &local_spaces = transforms_evaluator.get_evaluated<bool>(2);
|
||||
const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
|
||||
const VArray<float3> &scales = evaluator.get_evaluated<float3>(0);
|
||||
const VArray<float3> &pivots = evaluator.get_evaluated<float3>(1);
|
||||
const VArray<bool> &local_spaces = evaluator.get_evaluated<bool>(2);
|
||||
|
||||
MutableSpan<float4x4> instance_transforms = instances_component.instance_transforms();
|
||||
|
||||
|
|
|
@ -60,10 +60,12 @@ static void set_position_in_component(const GeometryNodeCurveHandleMode mode,
|
|||
return;
|
||||
}
|
||||
|
||||
fn::FieldEvaluator selection_evaluator{field_context, domain_size};
|
||||
selection_evaluator.add(selection_field);
|
||||
selection_evaluator.evaluate();
|
||||
const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0);
|
||||
fn::FieldEvaluator evaluator{field_context, domain_size};
|
||||
evaluator.set_selection(selection_field);
|
||||
evaluator.add(position_field);
|
||||
evaluator.add(offset_field);
|
||||
evaluator.evaluate();
|
||||
const IndexMask selection = evaluator.get_evaluated_as_mask(0);
|
||||
|
||||
CurveComponent *curve_component = static_cast<CurveComponent *>(&component);
|
||||
CurveEval *curve = curve_component->get_for_write();
|
||||
|
@ -113,13 +115,8 @@ static void set_position_in_component(const GeometryNodeCurveHandleMode mode,
|
|||
}
|
||||
}
|
||||
|
||||
fn::FieldEvaluator position_evaluator{field_context, &selection};
|
||||
position_evaluator.add(position_field);
|
||||
position_evaluator.add(offset_field);
|
||||
position_evaluator.evaluate();
|
||||
|
||||
const VArray<float3> &positions_input = position_evaluator.get_evaluated<float3>(0);
|
||||
const VArray<float3> &offsets_input = position_evaluator.get_evaluated<float3>(1);
|
||||
const VArray<float3> &positions_input = evaluator.get_evaluated<float3>(0);
|
||||
const VArray<float3> &offsets_input = evaluator.get_evaluated<float3>(1);
|
||||
|
||||
OutputAttribute_Typed<float3> positions = component.attribute_try_get_for_output<float3>(
|
||||
side, ATTR_DOMAIN_POINT, {0, 0, 0});
|
||||
|
|
|
@ -40,16 +40,14 @@ static void set_radius_in_component(GeometryComponent &component,
|
|||
return;
|
||||
}
|
||||
|
||||
fn::FieldEvaluator selection_evaluator{field_context, domain_size};
|
||||
selection_evaluator.add(selection_field);
|
||||
selection_evaluator.evaluate();
|
||||
const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0);
|
||||
|
||||
OutputAttribute_Typed<float> radii = component.attribute_try_get_for_output_only<float>(
|
||||
"radius", ATTR_DOMAIN_POINT);
|
||||
fn::FieldEvaluator radii_evaluator{field_context, &selection};
|
||||
radii_evaluator.add_with_destination(radius_field, radii.varray());
|
||||
radii_evaluator.evaluate();
|
||||
|
||||
fn::FieldEvaluator evaluator{field_context, domain_size};
|
||||
evaluator.set_selection(selection_field);
|
||||
evaluator.add_with_destination(radius_field, radii.varray());
|
||||
evaluator.evaluate();
|
||||
|
||||
radii.save();
|
||||
}
|
||||
|
||||
|
|
|
@ -36,16 +36,14 @@ static void set_tilt_in_component(GeometryComponent &component,
|
|||
return;
|
||||
}
|
||||
|
||||
fn::FieldEvaluator selection_evaluator{field_context, domain_size};
|
||||
selection_evaluator.add(selection_field);
|
||||
selection_evaluator.evaluate();
|
||||
const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0);
|
||||
|
||||
OutputAttribute_Typed<float> tilts = component.attribute_try_get_for_output_only<float>(
|
||||
"tilt", ATTR_DOMAIN_POINT);
|
||||
fn::FieldEvaluator tilt_evaluator{field_context, &selection};
|
||||
tilt_evaluator.add_with_destination(tilt_field, tilts.varray());
|
||||
tilt_evaluator.evaluate();
|
||||
|
||||
fn::FieldEvaluator evaluator{field_context, domain_size};
|
||||
evaluator.set_selection(selection_field);
|
||||
evaluator.add_with_destination(tilt_field, tilts.varray());
|
||||
evaluator.evaluate();
|
||||
|
||||
tilts.save();
|
||||
}
|
||||
|
||||
|
|
|
@ -36,26 +36,24 @@ static void set_id_in_component(GeometryComponent &component,
|
|||
return;
|
||||
}
|
||||
|
||||
fn::FieldEvaluator selection_evaluator{field_context, domain_size};
|
||||
selection_evaluator.add(selection_field);
|
||||
selection_evaluator.evaluate();
|
||||
const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0);
|
||||
fn::FieldEvaluator evaluator{field_context, domain_size};
|
||||
evaluator.set_selection(selection_field);
|
||||
|
||||
/* Since adding the ID attribute can change the result of the field evaluation (the random value
|
||||
* node uses the index if the ID is unavailable), make sure that it isn't added before evaluating
|
||||
* the field. However, as an optimization, use a faster code path when it already exists. */
|
||||
fn::FieldEvaluator id_evaluator{field_context, &selection};
|
||||
if (component.attribute_exists("id")) {
|
||||
OutputAttribute_Typed<int> id_attribute = component.attribute_try_get_for_output_only<int>(
|
||||
"id", ATTR_DOMAIN_POINT);
|
||||
id_evaluator.add_with_destination(id_field, id_attribute.varray());
|
||||
id_evaluator.evaluate();
|
||||
evaluator.add_with_destination(id_field, id_attribute.varray());
|
||||
evaluator.evaluate();
|
||||
id_attribute.save();
|
||||
}
|
||||
else {
|
||||
id_evaluator.add(id_field);
|
||||
id_evaluator.evaluate();
|
||||
const VArray<int> &result_ids = id_evaluator.get_evaluated<int>(0);
|
||||
evaluator.add(id_field);
|
||||
evaluator.evaluate();
|
||||
const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
|
||||
const VArray<int> &result_ids = evaluator.get_evaluated<int>(0);
|
||||
OutputAttribute_Typed<int> id_attribute = component.attribute_try_get_for_output_only<int>(
|
||||
"id", ATTR_DOMAIN_POINT);
|
||||
result_ids.materialize(selection, id_attribute.as_span());
|
||||
|
|
|
@ -36,16 +36,13 @@ static void set_material_index_in_component(GeometryComponent &component,
|
|||
return;
|
||||
}
|
||||
|
||||
fn::FieldEvaluator selection_evaluator{field_context, domain_size};
|
||||
selection_evaluator.add(selection_field);
|
||||
selection_evaluator.evaluate();
|
||||
const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0);
|
||||
|
||||
OutputAttribute_Typed<int> indices = component.attribute_try_get_for_output_only<int>(
|
||||
"material_index", ATTR_DOMAIN_FACE);
|
||||
fn::FieldEvaluator material_evaluator{field_context, &selection};
|
||||
material_evaluator.add_with_destination(index_field, indices.varray());
|
||||
material_evaluator.evaluate();
|
||||
|
||||
fn::FieldEvaluator evaluator{field_context, domain_size};
|
||||
evaluator.set_selection(selection_field);
|
||||
evaluator.add_with_destination(index_field, indices.varray());
|
||||
evaluator.evaluate();
|
||||
indices.save();
|
||||
}
|
||||
|
||||
|
|
|
@ -40,16 +40,14 @@ static void set_radius_in_component(GeometryComponent &component,
|
|||
return;
|
||||
}
|
||||
|
||||
fn::FieldEvaluator selection_evaluator{field_context, domain_size};
|
||||
selection_evaluator.add(selection_field);
|
||||
selection_evaluator.evaluate();
|
||||
const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0);
|
||||
|
||||
OutputAttribute_Typed<float> radii = component.attribute_try_get_for_output_only<float>(
|
||||
"radius", ATTR_DOMAIN_POINT);
|
||||
fn::FieldEvaluator radii_evaluator{field_context, &selection};
|
||||
radii_evaluator.add_with_destination(radius_field, radii.varray());
|
||||
radii_evaluator.evaluate();
|
||||
|
||||
fn::FieldEvaluator evaluator{field_context, domain_size};
|
||||
evaluator.set_selection(selection_field);
|
||||
evaluator.add_with_destination(radius_field, radii.varray());
|
||||
evaluator.evaluate();
|
||||
|
||||
radii.save();
|
||||
}
|
||||
|
||||
|
|
|
@ -119,18 +119,15 @@ static void set_position_in_component(GeometryComponent &component,
|
|||
return;
|
||||
}
|
||||
|
||||
fn::FieldEvaluator selection_evaluator{field_context, domain_size};
|
||||
selection_evaluator.add(selection_field);
|
||||
selection_evaluator.evaluate();
|
||||
const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0);
|
||||
fn::FieldEvaluator evaluator{field_context, domain_size};
|
||||
evaluator.set_selection(selection_field);
|
||||
evaluator.add(position_field);
|
||||
evaluator.add(offset_field);
|
||||
evaluator.evaluate();
|
||||
|
||||
fn::FieldEvaluator position_evaluator{field_context, &selection};
|
||||
position_evaluator.add(position_field);
|
||||
position_evaluator.add(offset_field);
|
||||
position_evaluator.evaluate();
|
||||
|
||||
const VArray<float3> &positions_input = position_evaluator.get_evaluated<float3>(0);
|
||||
const VArray<float3> &offsets_input = position_evaluator.get_evaluated<float3>(1);
|
||||
const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
|
||||
const VArray<float3> &positions_input = evaluator.get_evaluated<float3>(0);
|
||||
const VArray<float3> &offsets_input = evaluator.get_evaluated<float3>(1);
|
||||
set_computed_position_and_offset(component, positions_input, offsets_input, domain, selection);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,16 +36,14 @@ static void set_smooth_in_component(GeometryComponent &component,
|
|||
return;
|
||||
}
|
||||
|
||||
fn::FieldEvaluator selection_evaluator{field_context, domain_size};
|
||||
selection_evaluator.add(selection_field);
|
||||
selection_evaluator.evaluate();
|
||||
const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0);
|
||||
|
||||
OutputAttribute_Typed<bool> shades = component.attribute_try_get_for_output_only<bool>(
|
||||
"shade_smooth", ATTR_DOMAIN_FACE);
|
||||
fn::FieldEvaluator shade_evaluator{field_context, &selection};
|
||||
shade_evaluator.add_with_destination(shade_field, shades.varray());
|
||||
shade_evaluator.evaluate();
|
||||
|
||||
fn::FieldEvaluator evaluator{field_context, domain_size};
|
||||
evaluator.set_selection(selection_field);
|
||||
evaluator.add_with_destination(shade_field, shades.varray());
|
||||
evaluator.evaluate();
|
||||
|
||||
shades.save();
|
||||
}
|
||||
|
||||
|
|
|
@ -36,16 +36,14 @@ static void set_cyclic_in_component(GeometryComponent &component,
|
|||
return;
|
||||
}
|
||||
|
||||
fn::FieldEvaluator selection_evaluator{field_context, domain_size};
|
||||
selection_evaluator.add(selection_field);
|
||||
selection_evaluator.evaluate();
|
||||
const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0);
|
||||
|
||||
OutputAttribute_Typed<bool> cyclics = component.attribute_try_get_for_output_only<bool>(
|
||||
"cyclic", ATTR_DOMAIN_CURVE);
|
||||
fn::FieldEvaluator cyclic_evaluator{field_context, &selection};
|
||||
cyclic_evaluator.add_with_destination(cyclic_field, cyclics.varray());
|
||||
cyclic_evaluator.evaluate();
|
||||
|
||||
fn::FieldEvaluator evaluator{field_context, domain_size};
|
||||
evaluator.set_selection(selection_field);
|
||||
evaluator.add_with_destination(cyclic_field, cyclics.varray());
|
||||
evaluator.evaluate();
|
||||
|
||||
cyclics.save();
|
||||
}
|
||||
|
||||
|
|
|
@ -38,16 +38,14 @@ static void set_resolution_in_component(GeometryComponent &component,
|
|||
return;
|
||||
}
|
||||
|
||||
fn::FieldEvaluator selection_evaluator{field_context, domain_size};
|
||||
selection_evaluator.add(selection_field);
|
||||
selection_evaluator.evaluate();
|
||||
const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0);
|
||||
|
||||
OutputAttribute_Typed<int> resolutions = component.attribute_try_get_for_output_only<int>(
|
||||
"resolution", ATTR_DOMAIN_CURVE);
|
||||
fn::FieldEvaluator resolution_evaluator{field_context, &selection};
|
||||
resolution_evaluator.add_with_destination(resolution_field, resolutions.varray());
|
||||
resolution_evaluator.evaluate();
|
||||
|
||||
fn::FieldEvaluator evaluator{field_context, domain_size};
|
||||
evaluator.set_selection(selection_field);
|
||||
evaluator.add_with_destination(resolution_field, resolutions.varray());
|
||||
evaluator.evaluate();
|
||||
|
||||
resolutions.save();
|
||||
}
|
||||
|
||||
|
|
|
@ -33,17 +33,15 @@ static void translate_instances(GeoNodeExecParams ¶ms, InstancesComponent &i
|
|||
{
|
||||
GeometryComponentFieldContext field_context{instances_component, ATTR_DOMAIN_INSTANCE};
|
||||
|
||||
fn::FieldEvaluator selection_evaluator{field_context, instances_component.instances_amount()};
|
||||
selection_evaluator.add(params.extract_input<Field<bool>>("Selection"));
|
||||
selection_evaluator.evaluate();
|
||||
const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0);
|
||||
fn::FieldEvaluator evaluator{field_context, instances_component.instances_amount()};
|
||||
evaluator.set_selection(params.extract_input<Field<bool>>("Selection"));
|
||||
evaluator.add(params.extract_input<Field<float3>>("Translation"));
|
||||
evaluator.add(params.extract_input<Field<bool>>("Local Space"));
|
||||
evaluator.evaluate();
|
||||
|
||||
fn::FieldEvaluator transforms_evaluator{field_context, &selection};
|
||||
transforms_evaluator.add(params.extract_input<Field<float3>>("Translation"));
|
||||
transforms_evaluator.add(params.extract_input<Field<bool>>("Local Space"));
|
||||
transforms_evaluator.evaluate();
|
||||
const VArray<float3> &translations = transforms_evaluator.get_evaluated<float3>(0);
|
||||
const VArray<bool> &local_spaces = transforms_evaluator.get_evaluated<bool>(1);
|
||||
const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
|
||||
const VArray<float3> &translations = evaluator.get_evaluated<float3>(0);
|
||||
const VArray<bool> &local_spaces = evaluator.get_evaluated<bool>(1);
|
||||
|
||||
MutableSpan<float4x4> instance_transforms = instances_component.instance_transforms();
|
||||
|
||||
|
|
Loading…
Reference in New Issue