Point Cloud: Remove redundant custom data pointers

Similar to e9f82d3dc7, but for point clouds instead.

Differential Revision: https://developer.blender.org/D15487
This commit is contained in:
Hans Goudey 2022-07-19 18:06:56 -05:00
parent e9f82d3dc7
commit 410a6efb74
Notes: blender-bot 2023-11-20 12:14:32 +01:00
Referenced by commit 21ed3b3258, Fix T101025: Cycles motion blur crash with changing point cloud size
Referenced by issue #101025, Regression: Animating parameter in geometry nodes causes a crash on animated render
Referenced by issue #95842, Prepare custom data API for attribute sharing.
15 changed files with 205 additions and 106 deletions

View File

@ -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++;

View File

@ -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 */

View File

@ -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;

View File

@ -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);

View File

@ -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)

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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;

View File

@ -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);

View File

@ -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()) {

View File

@ -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 =

View File

@ -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);

View File

@ -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)