40 while (!queue.is_empty()) {
41 int64_t index = queue.pop_index();
48 if (index > 0 && !
visited[index - 1]) {
49 int adjacent = index - 1;
50 float dist = r_distances[index] +
math::distance(positions[index], positions[adjacent]);
51 if (dist < r_distances[adjacent]) {
52 r_distances[adjacent] = dist;
53 queue.priority_changed(adjacent);
56 if (index < positions.size() - 1 && !
visited[index + 1]) {
57 int adjacent = index + 1;
58 float dist = r_distances[index] +
math::distance(positions[index], positions[adjacent]);
59 if (dist < r_distances[adjacent]) {
60 r_distances[adjacent] = dist;
61 queue.priority_changed(adjacent);
78 transform_data.
positions.as_mutable_span().slice(data_offset, selection.size()));
94 for (
const int i : trans_data_contrainers.
index_range()) {
102 std::array<IndexMask, 3> selection_per_attribute;
104 for (
const int attribute_i : selection_attribute_names.
index_range()) {
105 const StringRef &selection_name = selection_attribute_names[attribute_i];
107 curves, selection_name, curves_transform_data->
memory);
111 curves.curve_type_counts(),
113 curves.curves_range(),
114 curves_transform_data->
memory);
116 if (!bezier_curves[i].is_empty()) {
118 const VArray<int8_t> handle_types_left = curves.handle_types_left();
119 const VArray<int8_t> handle_types_right = curves.handle_types_right();
121 must_be_selected.
clear();
122 bezier_curves[i].foreach_index([&](
const int bezier_index) {
123 for (
const int point_i : points_by_curve[bezier_index]) {
124 if (selection_per_attribute[0].contains(point_i)) {
130 must_be_selected.
append(point_i);
138 curves_transform_data->
memory);
139 if (must_be_selected.
size()) {
141 selection_per_attribute[1], must_be_selected_mask, curves_transform_data->
memory);
143 selection_per_attribute[2], must_be_selected_mask, curves_transform_data->
memory);
147 if (use_proportional_edit) {
150 curves.points_by_curve(), bezier_curves[i], bezier_point_offset_data);
152 const int bezier_point_count = bezier_offsets.
total_size();
153 tc.
data_len = curves.points_num() + 2 * bezier_point_count;
154 points_to_transform_per_attribute[i].append(curves.points_range());
156 if (bezier_point_count > 0) {
159 bezier_curves[i].foreach_index(
GrainSize(512), [&](
const int bezier_curve_i) {
160 bezier_point_ranges.
append(points_by_curve[bezier_curve_i]);
163 curves_transform_data->
memory);
164 points_to_transform_per_attribute[i].append(bezier_points);
165 points_to_transform_per_attribute[i].append(bezier_points);
170 for (
const int selection_i : selection_attribute_names.
index_range()) {
171 points_to_transform_per_attribute[i].append(selection_per_attribute[selection_i]);
172 tc.
data_len += points_to_transform_per_attribute[i][selection_i].
size();
177 tc.
data = MEM_cnew_array<TransData>(tc.
data_len, __func__);
186 for (
const int i : trans_data_contrainers.
index_range()) {
192 Curves *curves_id =
static_cast<Curves *
>(
object->data);
195 std::optional<MutableSpan<float>> value_attribute;
199 attribute_writer = attributes.lookup_or_add_for_write_span<
float>(
203 value_attribute = attribute_writer.
span;
207 attribute_writer = attributes.lookup_or_add_for_write_span<
float>(
"tilt",
209 value_attribute = attribute_writer.
span;
214 object->object_to_world(),
216 points_to_transform_per_attribute[i],
217 curves.curves_range(),
222 attribute_writer.
finish();
230 Curves *curves_id =
static_cast<Curves *
>(tc.obedit->data);
236 curves.tag_normals_changed();
241 for (
const int i : positions_per_selection_attr.
index_range()) {
243 tc.custom.type, i, positions_per_selection_attr[i]);
245 curves.tag_positions_changed();
246 curves.calculate_bezier_auto_handles();
270 const int handles_offset,
273 const int position_index = curve_points.
start() + position_offsets_in_td[0].start();
275 const int left_handle_index = handles_offset + position_offsets_in_td[1].start();
276 const int right_handle_index = handles_offset + position_offsets_in_td[2].start();
277 std::array<int, 3> first_per_attr = {left_handle_index, position_index, right_handle_index};
279 for (const int i : range) {
280 for (const int attr : IndexRange(3)) {
281 map[i * 3 + attr] = first_per_attr[attr] + i;
297 custom_data.
data = transform_data;
301 custom_data->
data =
nullptr;
303 return transform_data;
318 array_utils::scatter(positions, selection, positions_dst);
328 bool use_connected_only,
332 const std::array<Span<float3>, 3> src_positions_per_selection_attr = {
333 curves.positions(), curves.handle_positions_left(), curves.handle_positions_right()};
334 std::array<MutableSpan<float3>, 3> positions_per_selection_attr;
336 for (
const int selection_i : points_to_transform_per_attr.
index_range()) {
337 positions_per_selection_attr[selection_i] =
338 ed::transform::curves::append_positions_to_custom_data(
339 points_to_transform_per_attr[selection_i],
340 src_positions_per_selection_attr[selection_i],
344 float mtx[3][3], smtx[3][3];
349 OffsetIndices<int> position_offsets_in_td = ed::transform::curves::recent_position_offsets(
352 Vector<VArray<bool>> selection_attrs;
353 Span<StringRef> selection_attribute_names = ed::curves::get_curves_selection_attribute_names(
355 for (
const StringRef selection_name : selection_attribute_names) {
356 const VArray<bool> selection_attr = *curves.attributes().lookup_or_default<
bool>(
357 selection_name, bke::AttrDomain::Point,
true);
358 selection_attrs.append(selection_attr);
361 for (
const int selection_i : position_offsets_in_td.index_range()) {
362 if (position_offsets_in_td[selection_i].is_empty()) {
367 IndexMask points_to_transform = points_to_transform_per_attr[selection_i];
370 threading::parallel_for(points_to_transform.index_range(), 1024, [&](
const IndexRange range) {
371 for (const int tranform_point_i : range) {
372 const int point_in_domain_i = points_to_transform[tranform_point_i];
373 TransData &td = tc_data[tranform_point_i];
374 float3 *elem = &positions[tranform_point_i];
376 copy_v3_v3(td.iloc, *elem);
377 copy_v3_v3(td.center, td.iloc);
381 if (selection[point_in_domain_i]) {
382 td.flag = TD_SELECTED;
385 if (value_attribute) {
386 float *value = &((*value_attribute)[point_in_domain_i]);
392 copy_m3_m3(td.smtx, smtx);
393 copy_m3_m3(td.mtx, mtx);
397 if (use_connected_only) {
399 const OffsetIndices<int> points_by_curve = curves.points_by_curve();
400 Array<int> bezier_offsets_in_td(curves.curves_num() + 1, 0);
401 offset_indices::copy_group_sizes(points_by_curve, bezier_curves, bezier_offsets_in_td);
402 offset_indices::accumulate_counts_to_offsets(bezier_offsets_in_td);
409 for (
const int curve_i : segment) {
410 const int selection_attrs_num = curve_types[curve_i] ==
CURVE_TYPE_BEZIER ? 3 : 1;
411 const IndexRange curve_points = points_by_curve[curve_i];
412 const int total_curve_points = selection_attrs_num * curve_points.
size();
413 map.reinitialize(total_curve_points);
415 closest_distances.
fill(std::numeric_limits<float>::max());
416 mapped_curve_positions.
reinitialize(total_curve_points);
418 ed::transform::curves::fill_map(
CurveType(curve_types[curve_i]),
420 position_offsets_in_td,
421 bezier_offsets_in_td[curve_i],
424 bool has_any_selected =
false;
425 for (
const int selection_attr_i :
IndexRange(selection_attrs_num)) {
426 has_any_selected = has_any_selected ||
427 ed::curves::has_anything_selected(selection_attrs[selection_attr_i],
430 if (!has_any_selected) {
431 for (
const int i : map) {
438 for (
const int i : closest_distances.index_range()) {
440 mapped_curve_positions[i] = td.loc;
442 closest_distances[i] = 0.0f;
447 for (
const int i : closest_distances.index_range()) {
449 td.
dist = closest_distances[i];
Low-level operations for curves.
Low-level operations for curves.
void pseudoinverse_m3_m3(float inverse[3][3], const float mat[3][3], float epsilon)
void copy_m3_m4(float m1[3][3], const float m2[4][4])
#define PSEUDOINVERSE_EPSILON
void DEG_id_tag_update(ID *id, unsigned int flags)
Read Guarded memory(de)allocation.
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Span< T > as_span() const
MutableSpan< T > as_mutable_span()
void fill(const T &value) const
void reinitialize(const int64_t new_size)
constexpr int64_t size() const
constexpr int64_t start() const
constexpr IndexRange index_range() const
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
constexpr IndexRange index_range() const
constexpr Span slice(int64_t start, int64_t size) const
constexpr int64_t size() const
constexpr IndexRange index_range() const
void append(const T &value)
const T & last(const int64_t n=0) const
IndexRange index_range() const
Span< T > as_span() const
static IndexMask from_union(const IndexMask &mask_a, const IndexMask &mask_b, IndexMaskMemory &memory)
static IndexMask from_indices(Span< T > indices, IndexMaskMemory &memory)
static IndexMask from_initializers(const Span< Initializer > initializers, IndexMaskMemory &memory)
Set< ComponentNode * > visited
void gather(const GVArray &src, const IndexMask &indices, GMutableSpan dst, int64_t grain_size=4096)
void fill_index_range(MutableSpan< T > span, const T start=0)
IndexMask indices_for_type(const VArray< int8_t > &types, const std::array< int, CURVE_TYPES_NUM > &type_counts, const CurveType type, const IndexMask &selection, IndexMaskMemory &memory)
Vector< MutableSpan< float3 > > get_curves_positions_for_write(bke::CurvesGeometry &curves)
Span< StringRef > get_curves_selection_attribute_names(const bke::CurvesGeometry &curves)
IndexMask retrieve_selected_points(const bke::CurvesGeometry &curves, IndexMaskMemory &memory)
T distance(const T &a, const T &b)
OffsetIndices< int > gather_selected_offsets(OffsetIndices< int > src_offsets, const IndexMask &selection, int start_offset, MutableSpan< int > dst_offsets)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
void(* free_cb)(TransInfo *, TransDataContainer *tc, TransCustomData *custom_data)
TransCustomDataContainer custom
TransDataContainer * data_container
MutableVArraySpan< T > span