Point Cloud: Implement "Affect only Origins" object transform option

Basically the same code as the curves support in this area.
This commit is contained in:
Hans Goudey
2025-02-16 20:48:46 -05:00
parent c1c67c918e
commit aff784aa14
3 changed files with 106 additions and 8 deletions

View File

@@ -40,10 +40,13 @@
#include "BLO_read_write.hh"
using blender::CPPType;
using blender::float3;
using blender::IndexRange;
using blender::MutableSpan;
using blender::Span;
using blender::StringRef;
using blender::VArray;
using blender::Vector;
/* PointCloud datablock */
@@ -200,18 +203,72 @@ static void pointcloud_random(PointCloud *pointcloud)
BLI_rng_free(rng);
}
Span<float3> PointCloud::positions() const
template<typename T>
static VArray<T> get_varray_attribute(const PointCloud &pointcloud,
const StringRef name,
const T default_value)
{
return {static_cast<const float3 *>(
CustomData_get_layer_named(&this->pdata, CD_PROP_FLOAT3, "position")),
this->totpoint};
const eCustomDataType type = blender::bke::cpp_type_to_custom_data_type(CPPType::get<T>());
const T *data = (const T *)CustomData_get_layer_named(&pointcloud.pdata, type, name);
if (data != nullptr) {
return VArray<T>::ForSpan(Span<T>(data, pointcloud.totpoint));
}
return VArray<T>::ForSingle(default_value, pointcloud.totpoint);
}
template<typename T>
static Span<T> get_span_attribute(const PointCloud &pointcloud, const StringRef name)
{
const eCustomDataType type = blender::bke::cpp_type_to_custom_data_type(CPPType::get<T>());
T *data = (T *)CustomData_get_layer_named(&pointcloud.pdata, type, name);
if (data == nullptr) {
return {};
}
return {data, pointcloud.totpoint};
}
template<typename T>
static MutableSpan<T> get_mutable_attribute(PointCloud &pointcloud,
const StringRef name,
const T default_value = T())
{
if (pointcloud.totpoint <= 0) {
return {};
}
const eCustomDataType type = blender::bke::cpp_type_to_custom_data_type(CPPType::get<T>());
T *data = (T *)CustomData_get_layer_named_for_write(
&pointcloud.pdata, type, name, pointcloud.totpoint);
if (data != nullptr) {
return {data, pointcloud.totpoint};
}
data = (T *)CustomData_add_layer_named(
&pointcloud.pdata, type, CD_SET_DEFAULT, pointcloud.totpoint, name);
MutableSpan<T> span = {data, pointcloud.totpoint};
if (pointcloud.totpoint > 0 && span.first() != default_value) {
span.fill(default_value);
}
return span;
}
Span<float3> PointCloud::positions() const
{
return get_span_attribute<float3>(*this, "position");
}
MutableSpan<float3> PointCloud::positions_for_write()
{
return {static_cast<float3 *>(CustomData_get_layer_named_for_write(
&this->pdata, CD_PROP_FLOAT3, "position", this->totpoint)),
this->totpoint};
return get_mutable_attribute<float3>(*this, "position");
}
VArray<float> PointCloud::radius() const
{
return get_varray_attribute<float>(*this, "radius", 0.01f);
}
MutableSpan<float> PointCloud::radius_for_write()
{
return get_mutable_attribute<float>(*this, "radius", 0.01f);
}
PointCloud *BKE_pointcloud_add(Main *bmain, const char *name)

View File

@@ -21,6 +21,7 @@
#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
#include "DNA_object_types.h"
#include "DNA_pointcloud_types.h"
#include "BLI_listbase.h"
#include "BLI_math_matrix.h"
@@ -306,6 +307,12 @@ struct XFormObjectData_Curves : public XFormObjectData {
virtual ~XFormObjectData_Curves() = default;
};
struct XFormObjectData_PointCloud : public XFormObjectData {
Array<float3> positions;
Array<float> radii;
virtual ~XFormObjectData_PointCloud() = default;
};
static std::unique_ptr<XFormObjectData> data_xform_create_ex(ID *id, bool is_edit_mode)
{
if (id == nullptr) {
@@ -463,6 +470,15 @@ static std::unique_ptr<XFormObjectData> data_xform_create_ex(ID *id, bool is_edi
curves.radius().materialize(xod->radii);
return xod;
}
case ID_PT: {
PointCloud *pointcloud = reinterpret_cast<PointCloud *>(id);
auto xod = std::make_unique<XFormObjectData_PointCloud>();
xod->id = id;
xod->positions = pointcloud->positions();
xod->radii.reinitialize(pointcloud->totpoint);
pointcloud->radius().materialize(xod->radii);
return xod;
}
default: {
return {};
}
@@ -614,6 +630,13 @@ void data_xform_by_mat4(XFormObjectData &xod_base, const float4x4 &transform)
copy_transformed_radii(xod.radii, transform, curves.radius_for_write());
break;
}
case ID_PT: {
PointCloud *pointcloud = reinterpret_cast<PointCloud *>(xod_base.id);
const auto &xod = reinterpret_cast<const XFormObjectData_PointCloud &>(xod_base);
copy_transformed_positions(xod.positions, transform, pointcloud->positions_for_write());
copy_transformed_radii(xod.radii, transform, pointcloud->radius_for_write());
break;
}
default: {
break;
}
@@ -722,6 +745,13 @@ void data_xform_restore(XFormObjectData &xod_base)
curves.radius_for_write().copy_from(xod.radii);
break;
}
case ID_PT: {
PointCloud *pointcloud = reinterpret_cast<PointCloud *>(xod_base.id);
const auto &xod = reinterpret_cast<const XFormObjectData_PointCloud &>(xod_base);
pointcloud->positions_for_write().copy_from(xod.positions);
pointcloud->radius_for_write().copy_from(xod.radii);
break;
}
default: {
break;
}
@@ -785,10 +815,17 @@ void data_xform_tag_update(XFormObjectData &xod_base)
Curves *curves_id = reinterpret_cast<Curves *>(xod_base.id);
bke::CurvesGeometry &curves = curves_id->geometry.wrap();
curves.tag_positions_changed();
curves.tag_radii_changed();
DEG_id_tag_update(&curves_id->id, ID_RECALC_GEOMETRY | ID_RECALC_SYNC_TO_EVAL);
break;
}
case ID_PT: {
PointCloud *pointcloud = reinterpret_cast<PointCloud *>(xod_base.id);
pointcloud->tag_positions_changed();
pointcloud->tag_radii_changed();
DEG_id_tag_update(&pointcloud->id, ID_RECALC_GEOMETRY | ID_RECALC_SYNC_TO_EVAL);
break;
}
default: {
break;
}

View File

@@ -18,6 +18,7 @@
# include "BLI_math_vector_types.hh"
# include "BLI_memory_counter_fwd.hh"
# include "BLI_span.hh"
# include "BLI_virtual_array_fwd.hh"
#endif
#ifdef __cplusplus
@@ -58,6 +59,9 @@ typedef struct PointCloud {
blender::Span<blender::float3> positions() const;
blender::MutableSpan<blender::float3> positions_for_write();
blender::VArray<float> radius() const;
blender::MutableSpan<float> radius_for_write();
blender::bke::AttributeAccessor attributes() const;
blender::bke::MutableAttributeAccessor attributes_for_write();