Cleanup: Add access method for point cloud positions

The position attribute has special meaning for point clouds, and
meshes and curves have access methods for the attribute as well.
This saves boilerplate and gives more consistency between types.
This commit is contained in:
Hans Goudey
2023-04-13 11:55:32 -04:00
parent cef128e68a
commit a7bee90c1d
11 changed files with 42 additions and 37 deletions

View File

@@ -13,6 +13,10 @@
# include "BLI_bounds_types.hh"
# include "BLI_math_vector_types.hh"
# include "BLI_shared_cache.hh"
# include "DNA_pointcloud_types.h"
# include "BKE_customdata.h"
#endif
#ifdef __cplusplus
@@ -45,6 +49,21 @@ struct PointCloudRuntime {
};
} // namespace blender::bke
inline blender::Span<blender::float3> PointCloud::positions() const
{
return {static_cast<const blender::float3 *>(
CustomData_get_layer_named(&this->pdata, CD_PROP_FLOAT3, "position")),
this->totpoint};
}
inline blender::MutableSpan<blender::float3> PointCloud::positions_for_write()
{
return {static_cast<blender::float3 *>(CustomData_get_layer_named_for_write(
&this->pdata, CD_PROP_FLOAT3, "position", this->totpoint)),
this->totpoint};
}
#endif
void *BKE_pointcloud_add(struct Main *bmain, const char *name);

View File

@@ -26,6 +26,7 @@
#include "BKE_editmesh.h"
#include "BKE_mesh.hh"
#include "BKE_mesh_runtime.h"
#include "BKE_pointcloud.h"
#include "MEM_guardedalloc.h"
@@ -1425,10 +1426,7 @@ BVHTree *BKE_bvhtree_from_pointcloud_get(BVHTreeFromPointCloud *data,
return nullptr;
}
blender::bke::AttributeAccessor attributes = pointcloud->attributes();
blender::VArraySpan<blender::float3> positions = attributes.lookup_or_default<blender::float3>(
"position", ATTR_DOMAIN_POINT, blender::float3(0));
const Span<float3> positions = pointcloud->positions();
for (const int i : positions.index_range()) {
BLI_bvhtree_insert(tree, i, positions[i], 1);
}

View File

@@ -202,21 +202,18 @@ static void pointcloud_random(PointCloud *pointcloud)
RNG *rng = BLI_rng_new(0);
blender::bke::MutableAttributeAccessor attributes = pointcloud->attributes_for_write();
blender::bke::SpanAttributeWriter positions =
attributes.lookup_or_add_for_write_only_span<float3>(POINTCLOUD_ATTR_POSITION,
ATTR_DOMAIN_POINT);
blender::MutableSpan<float3> positions = pointcloud->positions_for_write();
blender::bke::SpanAttributeWriter<float> radii =
attributes.lookup_or_add_for_write_only_span<float>(POINTCLOUD_ATTR_RADIUS,
ATTR_DOMAIN_POINT);
for (const int i : positions.span.index_range()) {
positions.span[i] =
float3(BLI_rng_get_float(rng), BLI_rng_get_float(rng), BLI_rng_get_float(rng)) * 2.0f -
1.0f;
for (const int i : positions.index_range()) {
positions[i] = float3(BLI_rng_get_float(rng), BLI_rng_get_float(rng), BLI_rng_get_float(rng)) *
2.0f -
1.0f;
radii.span[i] = 0.05f * BLI_rng_get_float(rng);
}
positions.finish();
radii.finish();
BLI_rng_free(rng);

View File

@@ -73,7 +73,7 @@ inline void gather(const VArray<T> &src,
{
BLI_assert(indices.size() == dst.size());
threading::parallel_for(indices.index_range(), grain_size, [&](const IndexRange range) {
src.materialize_compressed_to_uninitialized(indices.slice(range), dst.slice(range).data());
src.materialize_compressed_to_uninitialized(indices.slice(range), dst.slice(range));
});
}

View File

@@ -250,7 +250,7 @@ static void pointcloud_extract_position_and_radius(const PointCloud &pointcloud,
using namespace blender;
const bke::AttributeAccessor attributes = pointcloud.attributes();
const VArraySpan<float3> positions = attributes.lookup<float3>("position", ATTR_DOMAIN_POINT);
const Span<float3> positions = pointcloud.positions();
const VArray<float> radii = attributes.lookup<float>("radius", ATTR_DOMAIN_POINT);
static GPUVertFormat format = {0};
if (format.attr_len == 0) {

View File

@@ -19,8 +19,7 @@ PointCloud *point_merge_by_distance(const PointCloud &src_points,
const bke::AnonymousAttributePropagationInfo &propagation_info)
{
const bke::AttributeAccessor src_attributes = src_points.attributes();
VArraySpan<float3> positions = src_attributes.lookup_or_default<float3>(
"position", ATTR_DOMAIN_POINT, float3(0));
const Span<float3> positions = src_points.positions();
const int src_size = positions.size();
/* Create the KD tree based on only the selected points, to speed up merge detection and

View File

@@ -11,6 +11,7 @@
#ifdef __cplusplus
# include "BLI_math_vector_types.hh"
# include "BLI_span.hh"
#endif
#ifdef __cplusplus
@@ -51,6 +52,9 @@ typedef struct PointCloud {
short _pad3[3];
#ifdef __cplusplus
blender::Span<blender::float3> positions() const;
blender::MutableSpan<blender::float3> positions_for_write();
blender::bke::AttributeAccessor attributes() const;
blender::bke::MutableAttributeAccessor attributes_for_write();

View File

@@ -243,14 +243,11 @@ static void node_geo_exec(GeoNodeExecParams params)
PointCloud *pointcloud = BKE_pointcloud_new_nomain(positions.size());
bke::MutableAttributeAccessor point_attributes = pointcloud->attributes_for_write();
bke::SpanAttributeWriter<float3> point_positions =
point_attributes.lookup_or_add_for_write_only_span<float3>("position", ATTR_DOMAIN_POINT);
pointcloud->positions_for_write().copy_from(positions);
bke::SpanAttributeWriter<float> point_radii =
point_attributes.lookup_or_add_for_write_only_span<float>("radius", ATTR_DOMAIN_POINT);
point_positions.span.copy_from(positions);
point_radii.span.fill(0.05f);
point_positions.finish();
point_radii.finish();
geometry_set.replace_pointcloud(pointcloud);

View File

@@ -539,13 +539,10 @@ static void point_distribution_calculate(GeometrySet &geometry_set,
PointCloud *pointcloud = BKE_pointcloud_new_nomain(positions.size());
bke::MutableAttributeAccessor point_attributes = pointcloud->attributes_for_write();
bke::SpanAttributeWriter<float3> point_positions =
point_attributes.lookup_or_add_for_write_only_span<float3>("position", ATTR_DOMAIN_POINT);
bke::SpanAttributeWriter<float> point_radii =
point_attributes.lookup_or_add_for_write_only_span<float>("radius", ATTR_DOMAIN_POINT);
point_positions.span.copy_from(positions);
pointcloud->positions_for_write().copy_from(positions);
point_radii.span.fill(0.05f);
point_positions.finish();
point_radii.finish();
geometry_set.replace_pointcloud(pointcloud);

View File

@@ -1,5 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_array_utils.hh"
#include "DNA_pointcloud_types.h"
#include "BKE_attribute_math.hh"
@@ -26,7 +28,7 @@ static void node_declare(NodeDeclarationBuilder &b)
static void convert_instances_to_points(GeometrySet &geometry_set,
Field<float3> position_field,
Field<float> radius_field,
const Field<bool> selection_field,
Field<bool> selection_field,
const AnonymousAttributePropagationInfo &propagation_info)
{
const bke::Instances &instances = *geometry_set.get_instances_for_read();
@@ -41,22 +43,17 @@ static void convert_instances_to_points(GeometrySet &geometry_set,
if (selection.is_empty()) {
return;
}
const VArray<float3> &positions = evaluator.get_evaluated<float3>(0);
const VArray<float3> positions = evaluator.get_evaluated<float3>(0);
const VArray<float> radii = evaluator.get_evaluated<float>(1);
PointCloud *pointcloud = BKE_pointcloud_new_nomain(selection.size());
geometry_set.replace_pointcloud(pointcloud);
array_utils::gather(positions, selection, pointcloud->positions_for_write());
bke::MutableAttributeAccessor point_attributes = pointcloud->attributes_for_write();
bke::SpanAttributeWriter<float3> point_positions =
point_attributes.lookup_or_add_for_write_only_span<float3>("position", ATTR_DOMAIN_POINT);
bke::SpanAttributeWriter<float> point_radii =
point_attributes.lookup_or_add_for_write_only_span<float>("radius", ATTR_DOMAIN_POINT);
positions.materialize_compressed_to_uninitialized(selection, point_positions.span);
radii.materialize_compressed_to_uninitialized(selection, point_radii.span);
point_positions.finish();
array_utils::gather(radii, selection, point_radii.span);
point_radii.finish();
Map<AttributeIDRef, AttributeKind> attributes_to_propagate;

View File

@@ -71,18 +71,15 @@ static void node_geo_exec(GeoNodeExecParams params)
PointCloud *points = BKE_pointcloud_new_nomain(count);
MutableAttributeAccessor attributes = points->attributes_for_write();
AttributeWriter<float3> output_position = attributes.lookup_or_add_for_write<float3>(
"position", ATTR_DOMAIN_POINT);
AttributeWriter<float> output_radii = attributes.lookup_or_add_for_write<float>(
"radius", ATTR_DOMAIN_POINT);
PointsFieldContext context{count};
fn::FieldEvaluator evaluator{context, count};
evaluator.add_with_destination(position_field, output_position.varray);
evaluator.add_with_destination(position_field, points->positions_for_write());
evaluator.add_with_destination(radius_field, output_radii.varray);
evaluator.evaluate();
output_position.finish();
output_radii.finish();
params.set_output("Geometry", GeometrySet::create_with_pointcloud(points));
}