diff options
author | Hans Goudey <h.goudey@me.com> | 2022-07-20 02:06:56 +0300 |
---|---|---|
committer | Hans Goudey <h.goudey@me.com> | 2022-07-20 02:06:56 +0300 |
commit | 410a6efb747f188da30c75074d6bf318b862d5d5 (patch) | |
tree | f757ec39c23046873a323fcfd822d218c1e5579a | |
parent | e9f82d3dc7eebadcc52fdc43858d060c3a8214b2 (diff) |
Point Cloud: Remove redundant custom data pointers
Similar to e9f82d3dc7eebadcc52, but for point clouds instead.
Differential Revision: https://developer.blender.org/D15487
15 files changed, 205 insertions, 106 deletions
diff --git a/intern/cycles/blender/pointcloud.cpp b/intern/cycles/blender/pointcloud.cpp index 0312ad87a70..b4e90859877 100644 --- a/intern/cycles/blender/pointcloud.cpp +++ b/intern/cycles/blender/pointcloud.cpp @@ -1,8 +1,10 @@ /* SPDX-License-Identifier: Apache-2.0 * Copyright 2011-2022 Blender Foundation */ -#include "scene/pointcloud.h" +#include <optional> + #include "scene/attribute.h" +#include "scene/pointcloud.h" #include "scene/scene.h" #include "blender/sync.h" @@ -138,6 +140,36 @@ static void copy_attributes(PointCloud *pointcloud, } } +static std::optional<BL::FloatAttribute> find_radius_attribute(BL::PointCloud b_pointcloud) +{ + for (BL::Attribute &b_attribute : b_pointcloud.attributes) { + if (b_attribute.name() != "radius") { + continue; + } + if (b_attribute.data_type() != BL::Attribute::data_type_FLOAT) { + continue; + } + return BL::FloatAttribute{b_attribute}; + } + return std::nullopt; +} + +static BL::FloatVectorAttribute find_position_attribute(BL::PointCloud b_pointcloud) +{ + for (BL::Attribute &b_attribute : b_pointcloud.attributes) { + if (b_attribute.name() != "position") { + continue; + } + if (b_attribute.data_type() != BL::Attribute::data_type_FLOAT_VECTOR) { + continue; + } + return BL::FloatVectorAttribute{b_attribute}; + } + /* The position attribute must exist. */ + assert(false); + return BL::FloatVectorAttribute{b_pointcloud.attributes[0]}; +} + static void export_pointcloud(Scene *scene, PointCloud *pointcloud, BL::PointCloud b_pointcloud, @@ -156,18 +188,18 @@ static void export_pointcloud(Scene *scene, const int num_points = b_pointcloud.points.length(); pointcloud->reserve(num_points); + BL::FloatVectorAttribute b_attr_position = find_position_attribute(b_pointcloud); + std::optional<BL::FloatAttribute> b_attr_radius = find_radius_attribute(b_pointcloud); + /* Export points. */ - BL::PointCloud::points_iterator b_point_iter; - for (b_pointcloud.points.begin(b_point_iter); b_point_iter != b_pointcloud.points.end(); - ++b_point_iter) { - BL::Point b_point = *b_point_iter; - const float3 co = get_float3(b_point.co()); - const float radius = b_point.radius(); + for (int i = 0; i < num_points; i++) { + const float3 co = get_float3(b_attr_position.data[i].vector()); + const float radius = b_attr_radius ? b_attr_radius->data[i].value() : 0.0f; pointcloud->add_point(co, radius); /* Random number per point. */ if (attr_random != NULL) { - attr_random->add(hash_uint2_to_float(b_point.index(), 0)); + attr_random->add(hash_uint2_to_float(i, 0)); } } @@ -195,14 +227,15 @@ static void export_pointcloud_motion(PointCloud *pointcloud, int num_motion_points = 0; const array<float3> &pointcloud_points = pointcloud->get_points(); - BL::PointCloud::points_iterator b_point_iter; - for (b_pointcloud.points.begin(b_point_iter); b_point_iter != b_pointcloud.points.end(); - ++b_point_iter) { - BL::Point b_point = *b_point_iter; + BL::FloatVectorAttribute b_attr_position = find_position_attribute(b_pointcloud); + std::optional<BL::FloatAttribute> b_attr_radius = find_radius_attribute(b_pointcloud); + for (int i = 0; i < num_points; i++) { if (num_motion_points < num_points) { - float3 P = get_float3(b_point.co()); - P.w = b_point.radius(); + const float3 co = get_float3(b_attr_position.data[i].vector()); + const float radius = b_attr_radius ? b_attr_radius->data[i].value() : 0.0f; + float3 P = co; + P.w = radius; mP[num_motion_points] = P; have_motion = have_motion || (P != pointcloud_points[num_motion_points]); num_motion_points++; diff --git a/source/blender/blenkernel/BKE_pointcloud.h b/source/blender/blenkernel/BKE_pointcloud.h index 6dbba11a56d..ee90fea6506 100644 --- a/source/blender/blenkernel/BKE_pointcloud.h +++ b/source/blender/blenkernel/BKE_pointcloud.h @@ -29,7 +29,6 @@ struct PointCloud *BKE_pointcloud_new_nomain(int totpoint); struct BoundBox *BKE_pointcloud_boundbox_get(struct Object *ob); bool BKE_pointcloud_minmax(const struct PointCloud *pointcloud, float r_min[3], float r_max[3]); -void BKE_pointcloud_update_customdata_pointers(struct PointCloud *pointcloud); bool BKE_pointcloud_customdata_required(const struct PointCloud *pointcloud, const char *name); /* Dependency Graph */ diff --git a/source/blender/blenkernel/intern/bvhutils.cc b/source/blender/blenkernel/intern/bvhutils.cc index 35c2039634a..03dd5c89b70 100644 --- a/source/blender/blenkernel/intern/bvhutils.cc +++ b/source/blender/blenkernel/intern/bvhutils.cc @@ -19,6 +19,7 @@ #include "BLI_threads.h" #include "BLI_utildefines.h" +#include "BKE_attribute.hh" #include "BKE_bvhutils.h" #include "BKE_editmesh.h" #include "BKE_mesh.h" @@ -1430,13 +1431,17 @@ BVHTree *BKE_bvhtree_from_pointcloud_get(BVHTreeFromPointCloud *data, return nullptr; } - for (int i = 0; i < pointcloud->totpoint; i++) { - BLI_bvhtree_insert(tree, i, pointcloud->co[i], 1); + blender::bke::AttributeAccessor attributes = blender::bke::pointcloud_attributes(*pointcloud); + blender::VArraySpan<blender::float3> positions = attributes.lookup_or_default<blender::float3>( + "position", ATTR_DOMAIN_POINT, blender::float3(0)); + + for (const int i : positions.index_range()) { + BLI_bvhtree_insert(tree, i, positions[i], 1); } BLI_assert(BLI_bvhtree_get_len(tree) == pointcloud->totpoint); bvhtree_balance(tree, false); - data->coords = pointcloud->co; + data->coords = (const float(*)[3])positions.data(); data->tree = tree; data->nearest_callback = nullptr; diff --git a/source/blender/blenkernel/intern/geometry_component_pointcloud.cc b/source/blender/blenkernel/intern/geometry_component_pointcloud.cc index ccc97f92dbc..4953da8a5ee 100644 --- a/source/blender/blenkernel/intern/geometry_component_pointcloud.cc +++ b/source/blender/blenkernel/intern/geometry_component_pointcloud.cc @@ -111,10 +111,7 @@ namespace blender::bke { */ static ComponentAttributeProviders create_attribute_providers_for_point_cloud() { - static auto update_custom_data_pointers = [](void *owner) { - PointCloud *pointcloud = static_cast<PointCloud *>(owner); - BKE_pointcloud_update_customdata_pointers(pointcloud); - }; + static auto update_custom_data_pointers = [](void * /*owner*/) {}; static CustomDataAccessInfo point_access = { [](void *owner) -> CustomData * { PointCloud *pointcloud = static_cast<PointCloud *>(owner); diff --git a/source/blender/blenkernel/intern/mesh_convert.cc b/source/blender/blenkernel/intern/mesh_convert.cc index 7ebb3e25fd4..923d2703960 100644 --- a/source/blender/blenkernel/intern/mesh_convert.cc +++ b/source/blender/blenkernel/intern/mesh_convert.cc @@ -751,6 +751,8 @@ void BKE_mesh_to_curve(Main *bmain, Depsgraph *depsgraph, Scene *UNUSED(scene), void BKE_pointcloud_from_mesh(Mesh *me, PointCloud *pointcloud) { + using namespace blender; + BLI_assert(me != nullptr); pointcloud->totpoint = me->totvert; @@ -758,14 +760,17 @@ void BKE_pointcloud_from_mesh(Mesh *me, PointCloud *pointcloud) /* Copy over all attributes. */ CustomData_merge(&me->vdata, &pointcloud->pdata, CD_MASK_PROP_ALL, CD_DUPLICATE, me->totvert); - BKE_pointcloud_update_customdata_pointers(pointcloud); - CustomData_update_typemap(&pointcloud->pdata); - MVert *mvert; - mvert = me->mvert; - for (int i = 0; i < me->totvert; i++, mvert++) { - copy_v3_v3(pointcloud->co[i], mvert->co); - } + bke::AttributeAccessor mesh_attributes = bke::mesh_attributes(*me); + bke::MutableAttributeAccessor point_attributes = bke::pointcloud_attributes_for_write( + *pointcloud); + + const VArray<float3> mesh_positions = mesh_attributes.lookup_or_default<float3>( + "position", ATTR_DOMAIN_POINT, float3(0)); + bke::SpanAttributeWriter<float3> point_positions = + point_attributes.lookup_or_add_for_write_only_span<float3>("position", ATTR_DOMAIN_POINT); + mesh_positions.materialize(point_positions.span); + point_positions.finish(); } void BKE_mesh_to_pointcloud(Main *bmain, Depsgraph *depsgraph, Scene *UNUSED(scene), Object *ob) diff --git a/source/blender/blenkernel/intern/pointcloud.cc b/source/blender/blenkernel/intern/pointcloud.cc index e38c20d8eb7..261b053e4f9 100644 --- a/source/blender/blenkernel/intern/pointcloud.cc +++ b/source/blender/blenkernel/intern/pointcloud.cc @@ -68,7 +68,6 @@ static void pointcloud_init_data(ID *id) nullptr, pointcloud->totpoint, POINTCLOUD_ATTR_POSITION); - BKE_pointcloud_update_customdata_pointers(pointcloud); } static void pointcloud_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, const int flag) @@ -83,7 +82,6 @@ static void pointcloud_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_s CD_MASK_ALL, alloc_type, pointcloud_dst->totpoint); - BKE_pointcloud_update_customdata_pointers(pointcloud_dst); pointcloud_dst->batch_cache = nullptr; } @@ -138,7 +136,6 @@ static void pointcloud_blend_read_data(BlendDataReader *reader, ID *id) /* Geometry */ CustomData_blend_read(reader, &pointcloud->pdata, pointcloud->totpoint); - BKE_pointcloud_update_customdata_pointers(pointcloud); /* Materials */ BLO_read_pointer_array(reader, (void **)&pointcloud->mat); @@ -194,17 +191,28 @@ static void pointcloud_random(PointCloud *pointcloud) { pointcloud->totpoint = 400; CustomData_realloc(&pointcloud->pdata, pointcloud->totpoint); - BKE_pointcloud_update_customdata_pointers(pointcloud); RNG *rng = BLI_rng_new(0); - for (int i = 0; i < pointcloud->totpoint; i++) { - pointcloud->co[i][0] = 2.0f * BLI_rng_get_float(rng) - 1.0f; - pointcloud->co[i][1] = 2.0f * BLI_rng_get_float(rng) - 1.0f; - pointcloud->co[i][2] = 2.0f * BLI_rng_get_float(rng) - 1.0f; - pointcloud->radius[i] = 0.05f * BLI_rng_get_float(rng); + blender::bke::MutableAttributeAccessor attributes = + blender::bke::pointcloud_attributes_for_write(*pointcloud); + blender::bke::SpanAttributeWriter positions = + attributes.lookup_or_add_for_write_only_span<float3>(POINTCLOUD_ATTR_POSITION, + ATTR_DOMAIN_POINT); + 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; + radii.span[i] = 0.05f * BLI_rng_get_float(rng); } + positions.finish(); + radii.finish(); + BLI_rng_free(rng); } @@ -250,7 +258,6 @@ PointCloud *BKE_pointcloud_new_nomain(const int totpoint) pointcloud->totpoint = totpoint; CustomData_realloc(&pointcloud->pdata, pointcloud->totpoint); - BKE_pointcloud_update_customdata_pointers(pointcloud); return pointcloud; } @@ -258,10 +265,14 @@ PointCloud *BKE_pointcloud_new_nomain(const int totpoint) static std::optional<blender::bounds::MinMaxResult<float3>> point_cloud_bounds( const PointCloud &pointcloud) { - Span<float3> positions{reinterpret_cast<float3 *>(pointcloud.co), pointcloud.totpoint}; - if (pointcloud.radius) { - Span<float> radii{pointcloud.radius, pointcloud.totpoint}; - return blender::bounds::min_max_with_radii(positions, radii); + blender::bke::AttributeAccessor attributes = blender::bke::pointcloud_attributes(pointcloud); + blender::VArraySpan<float3> positions = attributes.lookup_or_default<float3>( + POINTCLOUD_ATTR_POSITION, ATTR_DOMAIN_POINT, float3(0)); + blender::VArray<float> radii = attributes.lookup_or_default<float>( + POINTCLOUD_ATTR_RADIUS, ATTR_DOMAIN_POINT, 0.0f); + + if (!(radii.is_single() && radii.get_internal_single() == 0.0f)) { + return blender::bounds::min_max_with_radii(positions, radii.get_internal_span()); } return blender::bounds::min_max(positions); } @@ -307,14 +318,6 @@ BoundBox *BKE_pointcloud_boundbox_get(Object *ob) return ob->runtime.bb; } -void BKE_pointcloud_update_customdata_pointers(PointCloud *pointcloud) -{ - pointcloud->co = static_cast<float(*)[3]>( - CustomData_get_layer_named(&pointcloud->pdata, CD_PROP_FLOAT3, POINTCLOUD_ATTR_POSITION)); - pointcloud->radius = static_cast<float *>( - CustomData_get_layer_named(&pointcloud->pdata, CD_PROP_FLOAT, POINTCLOUD_ATTR_RADIUS)); -} - bool BKE_pointcloud_customdata_required(const PointCloud *UNUSED(pointcloud), const char *name) { return STREQ(name, POINTCLOUD_ATTR_POSITION); @@ -334,7 +337,6 @@ PointCloud *BKE_pointcloud_new_for_eval(const PointCloud *pointcloud_src, int to pointcloud_dst->totpoint = totpoint; CustomData_copy( &pointcloud_src->pdata, &pointcloud_dst->pdata, CD_MASK_ALL, CD_CALLOC, totpoint); - BKE_pointcloud_update_customdata_pointers(pointcloud_dst); return pointcloud_dst; } diff --git a/source/blender/draw/intern/draw_cache_impl_pointcloud.c b/source/blender/draw/intern/draw_cache_impl_pointcloud.c index d715899e291..55d0eee00e5 100644 --- a/source/blender/draw/intern/draw_cache_impl_pointcloud.c +++ b/source/blender/draw/intern/draw_cache_impl_pointcloud.c @@ -18,6 +18,7 @@ #include "DNA_object_types.h" #include "DNA_pointcloud_types.h" +#include "BKE_customdata.h" #include "BKE_pointcloud.h" #include "GPU_batch.h" @@ -139,7 +140,11 @@ static void pointcloud_batch_cache_ensure_pos(Object *ob, PointCloudBatchCache * } PointCloud *pointcloud = ob->data; - const bool has_radius = pointcloud->radius != NULL; + const float(*positions)[3] = (float(*)[3])CustomData_get_layer_named( + &pointcloud->pdata, CD_PROP_FLOAT3, "position"); + const float *radii = (float *)CustomData_get_layer_named( + &pointcloud->pdata, CD_PROP_FLOAT, "radius"); + const bool has_radius = radii != NULL; static GPUVertFormat format = {0}; static GPUVertFormat format_no_radius = {0}; @@ -162,14 +167,14 @@ static void pointcloud_batch_cache_ensure_pos(Object *ob, PointCloudBatchCache * if (has_radius) { float(*vbo_data)[4] = (float(*)[4])GPU_vertbuf_get_data(cache->pos); for (int i = 0; i < pointcloud->totpoint; i++) { - copy_v3_v3(vbo_data[i], pointcloud->co[i]); + copy_v3_v3(vbo_data[i], positions[i]); /* TODO(fclem): remove multiplication here. * Here only for keeping the size correct for now. */ - vbo_data[i][3] = pointcloud->radius[i] * 100.0f; + vbo_data[i][3] = radii[i] * 100.0f; } } else { - GPU_vertbuf_attr_fill(cache->pos, pos, pointcloud->co); + GPU_vertbuf_attr_fill(cache->pos, pos, positions); } } diff --git a/source/blender/geometry/intern/point_merge_by_distance.cc b/source/blender/geometry/intern/point_merge_by_distance.cc index 40bc02cbd34..ac10f4ef00c 100644 --- a/source/blender/geometry/intern/point_merge_by_distance.cc +++ b/source/blender/geometry/intern/point_merge_by_distance.cc @@ -18,8 +18,10 @@ PointCloud *point_merge_by_distance(const PointCloudComponent &src_points, const IndexMask selection) { const PointCloud &src_pointcloud = *src_points.get_for_read(); - const int src_size = src_pointcloud.totpoint; - Span<float3> positions{reinterpret_cast<float3 *>(src_pointcloud.co), src_size}; + bke::AttributeAccessor attributes = bke::pointcloud_attributes(src_pointcloud); + VArraySpan<float3> positions = attributes.lookup_or_default<float3>( + "position", ATTR_DOMAIN_POINT, float3(0)); + const int src_size = positions.size(); /* Create the KD tree based on only the selected points, to speed up merge detection and * balancing. */ @@ -106,10 +108,10 @@ PointCloud *point_merge_by_distance(const PointCloudComponent &src_points, const bke::AttributeAccessor src_attributes = *src_points.attributes(); bke::MutableAttributeAccessor dst_attributes = *dst_points.attributes_for_write(); - Set<bke::AttributeIDRef> attributes = src_attributes.all_ids(); + Set<bke::AttributeIDRef> attribute_ids = src_attributes.all_ids(); /* Transfer the ID attribute if it exists, using the ID of the first merged point. */ - if (attributes.contains("id")) { + if (attribute_ids.contains("id")) { VArraySpan<int> src = src_attributes.lookup_or_default<int>("id", ATTR_DOMAIN_POINT, 0); bke::SpanAttributeWriter<int> dst = dst_attributes.lookup_or_add_for_write_only_span<int>( "id", ATTR_DOMAIN_POINT); @@ -122,11 +124,11 @@ PointCloud *point_merge_by_distance(const PointCloudComponent &src_points, }); dst.finish(); - attributes.remove_contained("id"); + attribute_ids.remove_contained("id"); } /* Transfer all other attributes. */ - for (const bke::AttributeIDRef &id : attributes) { + for (const bke::AttributeIDRef &id : attribute_ids) { if (!id.should_be_kept()) { continue; } diff --git a/source/blender/geometry/intern/realize_instances.cc b/source/blender/geometry/intern/realize_instances.cc index 25bcead09b4..0544f304283 100644 --- a/source/blender/geometry/intern/realize_instances.cc +++ b/source/blender/geometry/intern/realize_instances.cc @@ -69,6 +69,7 @@ struct PointCloudRealizeInfo { /** Matches the order stored in #AllPointCloudsInfo.attributes. */ Array<std::optional<GVArraySpan>> attributes; /** Id attribute on the point cloud. If there are no ids, this #Span is empty. */ + Span<float3> positions; Span<int> stored_ids; }; @@ -665,6 +666,9 @@ static AllPointCloudsInfo preprocess_pointclouds(const GeometrySet &geometry_set pointcloud_info.stored_ids = ids_attribute.varray.get_internal_span().typed<int>(); } } + const VArray<float3> position_attribute = attributes.lookup_or_default<float3>( + "position", ATTR_DOMAIN_POINT, float3(0)); + pointcloud_info.positions = position_attribute.get_internal_span(); } return info; } @@ -673,18 +677,16 @@ static void execute_realize_pointcloud_task( const RealizeInstancesOptions &options, const RealizePointCloudTask &task, const OrderedAttributes &ordered_attributes, - PointCloud &dst_pointcloud, MutableSpan<GSpanAttributeWriter> dst_attribute_writers, - MutableSpan<int> all_dst_ids) + MutableSpan<int> all_dst_ids, + MutableSpan<float3> all_dst_positions) { const PointCloudRealizeInfo &pointcloud_info = *task.pointcloud_info; const PointCloud &pointcloud = *pointcloud_info.pointcloud; - const Span<float3> src_positions{(float3 *)pointcloud.co, pointcloud.totpoint}; const IndexRange point_slice{task.start_index, pointcloud.totpoint}; - MutableSpan<float3> dst_positions{(float3 *)dst_pointcloud.co + task.start_index, - pointcloud.totpoint}; - copy_transformed_positions(src_positions, task.transform, dst_positions); + copy_transformed_positions( + pointcloud_info.positions, task.transform, all_dst_positions.slice(point_slice)); /* Create point ids. */ if (!all_dst_ids.is_empty()) { @@ -726,6 +728,9 @@ static void execute_realize_pointcloud_tasks(const RealizeInstancesOptions &opti bke::MutableAttributeAccessor dst_attributes = bke::pointcloud_attributes_for_write( *dst_pointcloud); + SpanAttributeWriter<float3> positions = dst_attributes.lookup_or_add_for_write_only_span<float3>( + "position", ATTR_DOMAIN_POINT); + /* Prepare id attribute. */ SpanAttributeWriter<int> point_ids; if (all_pointclouds_info.create_id_attribute) { @@ -748,9 +753,9 @@ static void execute_realize_pointcloud_tasks(const RealizeInstancesOptions &opti execute_realize_pointcloud_task(options, task, ordered_attributes, - *dst_pointcloud, dst_attribute_writers, - point_ids.span); + point_ids.span, + positions.span); } }); @@ -758,6 +763,7 @@ static void execute_realize_pointcloud_tasks(const RealizeInstancesOptions &opti for (GSpanAttributeWriter &dst_attribute : dst_attribute_writers) { dst_attribute.finish(); } + positions.finish(); if (point_ids) { point_ids.finish(); } diff --git a/source/blender/makesdna/DNA_pointcloud_types.h b/source/blender/makesdna/DNA_pointcloud_types.h index 1cb490190c3..ee829ebcf6e 100644 --- a/source/blender/makesdna/DNA_pointcloud_types.h +++ b/source/blender/makesdna/DNA_pointcloud_types.h @@ -18,13 +18,9 @@ typedef struct PointCloud { struct AnimData *adt; /* animation data (must be immediately after id) */ int flag; - int _pad1[1]; /* Geometry */ - float (*co)[3]; - float *radius; int totpoint; - int _pad2[1]; /* Custom Data */ struct CustomData pdata; diff --git a/source/blender/makesrna/intern/rna_pointcloud.c b/source/blender/makesrna/intern/rna_pointcloud.c index 4c5dcd5a587..df09bff1aea 100644 --- a/source/blender/makesrna/intern/rna_pointcloud.c +++ b/source/blender/makesrna/intern/rna_pointcloud.c @@ -20,6 +20,7 @@ # include "BLI_math_vector.h" +# include "BKE_customdata.h" # include "BKE_pointcloud.h" # include "DEG_depsgraph.h" @@ -36,7 +37,9 @@ static int rna_Point_index_get_const(const PointerRNA *ptr) { const PointCloud *pointcloud = rna_pointcloud(ptr); const float(*co)[3] = ptr->data; - return (int)(co - pointcloud->co); + const float(*positions)[3] = (const float(*)[3])CustomData_get_layer_named( + &pointcloud->pdata, CD_PROP_FLOAT3, "position"); + return (int)(co - positions); } static int rna_Point_index_get(PointerRNA *ptr) @@ -44,6 +47,21 @@ static int rna_Point_index_get(PointerRNA *ptr) return rna_Point_index_get_const(ptr); } +static int rna_PointCloud_points_length(PointerRNA *ptr) +{ + const PointCloud *pointcloud = rna_pointcloud(ptr); + return pointcloud->totpoint; +} + +static void rna_PointCloud_points_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +{ + const PointCloud *pointcloud = rna_pointcloud(ptr); + const float(*positions)[3] = (const float(*)[3])CustomData_get_layer_named( + &pointcloud->pdata, CD_PROP_FLOAT3, "position"); + rna_iterator_array_begin( + iter, (void *)positions, sizeof(float[3]), pointcloud->totpoint, false, NULL); +} + static void rna_Point_location_get(PointerRNA *ptr, float value[3]) { copy_v3_v3(value, (const float *)ptr->data); @@ -57,21 +75,22 @@ static void rna_Point_location_set(PointerRNA *ptr, const float value[3]) static float rna_Point_radius_get(PointerRNA *ptr) { const PointCloud *pointcloud = rna_pointcloud(ptr); - if (pointcloud->radius == NULL) { + const float *radii = (const float *)CustomData_get_layer_named( + &pointcloud->pdata, CD_PROP_FLOAT, "radius"); + if (radii == NULL) { return 0.0f; } - const float(*co)[3] = ptr->data; - return pointcloud->radius[co - pointcloud->co]; + return radii[rna_Point_index_get_const(ptr)]; } static void rna_Point_radius_set(PointerRNA *ptr, float value) { - const PointCloud *pointcloud = rna_pointcloud(ptr); - if (pointcloud->radius == NULL) { + PointCloud *pointcloud = rna_pointcloud(ptr); + float *radii = (float *)CustomData_get_layer_named(&pointcloud->pdata, CD_PROP_FLOAT, "radius"); + if (radii == NULL) { return; } - const float(*co)[3] = ptr->data; - pointcloud->radius[co - pointcloud->co] = value; + radii[rna_Point_index_get_const(ptr)] = value; } static char *rna_Point_path(const PointerRNA *ptr) @@ -130,13 +149,18 @@ static void rna_def_pointcloud(BlenderRNA *brna) RNA_def_struct_ui_icon(srna, ICON_POINTCLOUD_DATA); /* geometry */ - /* TODO: better solution for (*co)[3] parsing issue. */ - RNA_define_verify_sdna(0); prop = RNA_def_property(srna, "points", PROP_COLLECTION, PROP_NONE); - RNA_def_property_collection_sdna(prop, NULL, "co", "totpoint"); RNA_def_property_struct_type(prop, "Point"); + RNA_def_property_collection_funcs(prop, + "rna_PointCloud_points_begin", + "rna_iterator_array_next", + "rna_iterator_array_end", + "rna_iterator_array_get", + "rna_PointCloud_points_length", + NULL, + NULL, + NULL); RNA_def_property_ui_text(prop, "Points", ""); - RNA_define_verify_sdna(1); /* materials */ prop = RNA_def_property(srna, "materials", PROP_COLLECTION, PROP_NONE); diff --git a/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc b/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc index 3394a7cad62..3d0bc9cd462 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc @@ -149,12 +149,17 @@ static Mesh *compute_hull(const GeometrySet &geometry_set) if (geometry_set.has_pointcloud()) { count++; - span_count++; const PointCloudComponent *component = geometry_set.get_component_for_read<PointCloudComponent>(); const PointCloud *pointcloud = component->get_for_read(); - positions_span = {reinterpret_cast<const float3 *>(pointcloud->co), pointcloud->totpoint}; - total_num += pointcloud->totpoint; + const bke::AttributeAccessor attributes = bke::pointcloud_attributes(*pointcloud); + const VArray<float3> positions = attributes.lookup_or_default<float3>( + "position", ATTR_DOMAIN_POINT, float3(0)); + if (positions.is_span()) { + span_count++; + positions_span = positions.get_internal_span(); + } + total_num += positions.size(); } if (geometry_set.has_curves()) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc index faf5b7f65fa..44793926bbd 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc @@ -497,8 +497,17 @@ static void point_distribution_calculate(GeometrySet &geometry_set, } PointCloud *pointcloud = BKE_pointcloud_new_nomain(positions.size()); - memcpy(pointcloud->co, positions.data(), sizeof(float3) * positions.size()); - uninitialized_fill_n(pointcloud->radius, pointcloud->totpoint, 0.05f); + bke::MutableAttributeAccessor point_attributes = bke::pointcloud_attributes_for_write( + *pointcloud); + 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); + point_radii.span.fill(0.05f); + point_positions.finish(); + point_radii.finish(); + geometry_set.replace_pointcloud(pointcloud); PointCloudComponent &point_component = diff --git a/source/blender/nodes/geometry/nodes/node_geo_instances_to_points.cc b/source/blender/nodes/geometry/nodes/node_geo_instances_to_points.cc index edbe6e1593f..b3f04186c63 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_instances_to_points.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_instances_to_points.cc @@ -51,16 +51,24 @@ 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<float> radii = evaluator.get_evaluated<float>(1); PointCloud *pointcloud = BKE_pointcloud_new_nomain(selection.size()); geometry_set.replace_pointcloud(pointcloud); - PointCloudComponent &points = geometry_set.get_component_for_write<PointCloudComponent>(); + bke::MutableAttributeAccessor point_attributes = bke::pointcloud_attributes_for_write( + *pointcloud); - 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); - copy_attribute_to_points(radii, selection, {pointcloud->radius, pointcloud->totpoint}); + 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); + + copy_attribute_to_points(positions, selection, point_positions.span); + copy_attribute_to_points(radii, selection, point_radii.span); + point_positions.finish(); + point_radii.finish(); Map<AttributeIDRef, AttributeKind> attributes_to_propagate; geometry_set.gather_attributes_for_propagation({GEO_COMPONENT_TYPE_INSTANCES}, @@ -78,7 +86,7 @@ static void convert_instances_to_points(GeometrySet &geometry_set, const GVArray src = instances.attributes()->lookup_or_default( attribute_id, ATTR_DOMAIN_INSTANCE, attribute_kind.data_type); BLI_assert(src); - GSpanAttributeWriter dst = points.attributes_for_write()->lookup_or_add_for_write_only_span( + GSpanAttributeWriter dst = point_attributes.lookup_or_add_for_write_only_span( attribute_id, ATTR_DOMAIN_POINT, attribute_kind.data_type); BLI_assert(dst); diff --git a/source/blender/nodes/geometry/nodes/node_geo_transform.cc b/source/blender/nodes/geometry/nodes/node_geo_transform.cc index e95db205920..8e65e73d1e2 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_transform.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_transform.cc @@ -47,21 +47,24 @@ static void transform_mesh(Mesh &mesh, const float4x4 &transform) static void translate_pointcloud(PointCloud &pointcloud, const float3 translation) { - CustomData_duplicate_referenced_layer(&pointcloud.pdata, CD_PROP_FLOAT3, pointcloud.totpoint); - BKE_pointcloud_update_customdata_pointers(&pointcloud); - for (const int i : IndexRange(pointcloud.totpoint)) { - add_v3_v3(pointcloud.co[i], translation); + MutableAttributeAccessor attributes = bke::pointcloud_attributes_for_write(pointcloud); + SpanAttributeWriter position = attributes.lookup_or_add_for_write_span<float3>( + "position", ATTR_DOMAIN_POINT); + for (const int i : position.span.index_range()) { + position.span[i] += translation; } + position.finish(); } static void transform_pointcloud(PointCloud &pointcloud, const float4x4 &transform) { - CustomData_duplicate_referenced_layer(&pointcloud.pdata, CD_PROP_FLOAT3, pointcloud.totpoint); - BKE_pointcloud_update_customdata_pointers(&pointcloud); - for (const int i : IndexRange(pointcloud.totpoint)) { - float3 &co = *(float3 *)pointcloud.co[i]; - co = transform * co; + MutableAttributeAccessor attributes = bke::pointcloud_attributes_for_write(pointcloud); + SpanAttributeWriter position = attributes.lookup_or_add_for_write_span<float3>( + "position", ATTR_DOMAIN_POINT); + for (const int i : position.span.index_range()) { + position.span[i] = transform * position.span[i]; } + position.finish(); } static void translate_instances(InstancesComponent &instances, const float3 translation) |