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:
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user