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:
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.
|
@ -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++;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue