Blender V5.0
transform_convert_pointcloud.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "BLI_array.hh"
10#include "BLI_array_utils.hh"
11#include "BLI_math_matrix.h"
12#include "BLI_span.hh"
13
15
16#include "BKE_attribute.hh"
17#include "BKE_context.hh"
18#include "BKE_geometry_set.hh"
19
20#include "ED_curves.hh"
21
22#include "MEM_guardedalloc.h"
23
24#include "transform.hh"
25#include "transform_convert.hh"
26
27/* -------------------------------------------------------------------- */
30
32
40
42{
43 PointCloudTransformData *transform_data = MEM_new<PointCloudTransformData>(__func__);
44 custom_data.data = transform_data;
45 custom_data.free_cb = [](TransInfo *, TransDataContainer *, TransCustomData *custom_data) {
46 PointCloudTransformData *data = static_cast<PointCloudTransformData *>(custom_data->data);
47 MEM_delete(data);
48 custom_data->data = nullptr;
49 };
50 return transform_data;
51}
52
54{
56 const bool use_proportional_edit = (t->flag & T_PROP_EDIT_ALL) != 0;
57
58 for (const int i : trans_data_contrainers.index_range()) {
59 TransDataContainer &tc = trans_data_contrainers[i];
60 PointCloud &pointcloud = *static_cast<PointCloud *>(tc.obedit->data);
61 bke::MutableAttributeAccessor attributes = pointcloud.attributes_for_write();
63 const VArray selection_attr = *attributes.lookup_or_default<bool>(
64 ".selection", bke::AttrDomain::Point, true);
65 if (use_proportional_edit) {
66 transform_data.selection = IndexMask(pointcloud.totpoint);
67 tc.data_len = transform_data.selection.size();
68 }
69 else {
70 transform_data.selection = IndexMask::from_bools(selection_attr, transform_data.memory);
71 tc.data_len = transform_data.selection.size();
72 }
73 if (tc.data_len == 0) {
74 tc.custom.type.free_cb(t, &tc, &tc.custom.type);
75 continue;
76 }
77
80
81 transform_data.positions.reinitialize(tc.data_len);
83 transform_data.selection,
84 transform_data.positions.as_mutable_span());
85
86 if (t->mode == TFM_CURVE_SHRINKFATTEN) {
87 transform_data.radii.reinitialize(transform_data.selection.size());
89 pointcloud.radius(), transform_data.selection, transform_data.radii.as_mutable_span());
90 }
91
92 const float4x4 &transform = tc.obedit->object_to_world();
93 const float3x3 mtx_base = transform.view<3, 3>();
94 const float3x3 smtx_base = math::pseudo_invert(mtx_base);
95
96 threading::parallel_for(tc_data.index_range(), 1024, [&](const IndexRange range) {
97 for (const int64_t i : range) {
98 TransData &td = tc_data[i];
99 float3 *elem = &transform_data.positions[i];
100 copy_v3_v3(td.iloc, *elem);
101 copy_v3_v3(td.center, *elem);
102 td.loc = *elem;
103
104 td.flag = 0;
105 if (use_proportional_edit) {
106 if (selection_attr[i]) {
107 td.flag = TD_SELECTED;
108 }
109 }
110 else {
111 td.flag = TD_SELECTED;
112 }
113
114 if (t->mode == TFM_CURVE_SHRINKFATTEN) {
115 float *value = &transform_data.radii[i];
116 td.val = value;
117 td.ival = *value;
118 }
119
120 copy_m3_m3(td.smtx, smtx_base.ptr());
121 copy_m3_m3(td.mtx, mtx_base.ptr());
122 }
123 });
124 }
125}
126
128{
129 const Span<TransDataContainer> trans_data_contrainers(t->data_container, t->data_container_len);
130 for (const TransDataContainer &tc : trans_data_contrainers) {
131 const PointCloudTransformData &transform_data = *static_cast<PointCloudTransformData *>(
132 tc.custom.type.data);
133 PointCloud &pointcloud = *static_cast<PointCloud *>(tc.obedit->data);
134 if (t->mode == TFM_CURVE_SHRINKFATTEN) {
136 transform_data.radii.as_span(), transform_data.selection, pointcloud.radius_for_write());
137 pointcloud.tag_radii_changed();
138 }
139 else {
140 array_utils::scatter(transform_data.positions.as_span(),
141 transform_data.selection,
142 pointcloud.positions_for_write());
143 pointcloud.tag_positions_changed();
144 }
146 }
147}
148
150
152 /*flags*/ (T_EDIT | T_POINTS),
153 /*create_trans_data*/ pointcloud::createTransPointCloudVerts,
154 /*recalc_data*/ pointcloud::recalcData_pointcloud,
155 /*special_aftertrans_update*/ nullptr,
156};
157
158} // namespace blender::ed::transform::pointcloud
void DEG_id_tag_update(ID *id, unsigned int flags)
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1074
Read Guarded memory(de)allocation.
BMesh const char void * data
Span< T > as_span() const
Definition BLI_array.hh:243
MutableSpan< T > as_mutable_span()
Definition BLI_array.hh:248
void reinitialize(const int64_t new_size)
Definition BLI_array.hh:419
static IndexMask from_bools(Span< bool > bools, IndexMaskMemory &memory)
constexpr IndexRange index_range() const
Definition BLI_span.hh:670
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, AttrType data_type, const void *default_value=nullptr) const
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void scatter(const Span< T > src, const Span< IndexT > indices, MutableSpan< T > dst, const int64_t grain_size=4096)
void gather(const GVArray &src, const IndexMask &indices, GMutableSpan dst, int64_t grain_size=4096)
static void createTransPointCloudVerts(bContext *, TransInfo *t)
static PointCloudTransformData * create_transform_custom_data(TransCustomData &custom_data)
MatBase< T, Size, Size > pseudo_invert(const MatBase< T, Size, Size > &mat, T epsilon=1e-8)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Definition BLI_task.hh:93
MatBase< float, 4, 4 > float4x4
MatBase< float, 3, 3 > float3x3
void(* free_cb)(TransInfo *, TransDataContainer *tc, TransCustomData *custom_data)
Definition transform.hh:633
TransDataContainer * data_container
Definition transform.hh:802
i
Definition text_draw.cc:230
#define T_PROP_EDIT_ALL
Definition transform.hh:28
conversion and adaptation of different datablocks to a common struct.