40 while (!queue.is_empty()) {
41 int64_t index = queue.pop_index();
45 visited[index] =
true;
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);
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];
111 curves.curve_type_counts(),
114 curves_transform_data->
memory);
116 if (!bezier_curves[i].is_empty()) {
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();
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;
203 value_attribute = attribute_writer.
span;
209 value_attribute = attribute_writer.
span;
214 object->object_to_world(),
216 points_to_transform_per_attribute[i],
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;
328 bool use_connected_only,
333 const std::array<Span<float3>, 3> src_positions_per_selection_attr = {
335 std::array<MutableSpan<float3>, 3> positions_per_selection_attr;
337 for (
const int selection_i : points_to_transform_per_attr.
index_range()) {
338 positions_per_selection_attr[selection_i] =
340 points_to_transform_per_attr[selection_i],
341 src_positions_per_selection_attr[selection_i],
345 float mtx[3][3], smtx[3][3];
356 for (
const StringRef selection_name : selection_attribute_names) {
359 selection_attrs.
append(selection_attr);
362 for (
const int selection_i : position_offsets_in_td.
index_range()) {
363 if (position_offsets_in_td[selection_i].is_empty()) {
368 IndexMask points_to_transform = points_to_transform_per_attr[selection_i];
372 for (const int tranform_point_i : range) {
373 const int point_in_domain_i = points_to_transform[tranform_point_i];
374 TransData &td = tc_data[tranform_point_i];
375 float3 *elem = &positions[tranform_point_i];
377 copy_v3_v3(td.iloc, *elem);
378 copy_v3_v3(td.center, td.iloc);
382 if (selection[point_in_domain_i]) {
383 td.flag = TD_SELECTED;
388 if (value_attribute) {
389 float *value = &((*value_attribute)[point_in_domain_i]);
395 copy_m3_m3(td.smtx, smtx);
396 copy_m3_m3(td.mtx, mtx);
400 if (use_connected_only) {
403 Array<int> bezier_offsets_in_td(curves.curves_num() + 1, 0);
412 for (
const int curve_i : segment) {
413 const int selection_attrs_num = curve_types[curve_i] ==
CURVE_TYPE_BEZIER ? 3 : 1;
414 const IndexRange curve_points = points_by_curve[curve_i];
415 const int total_curve_points = selection_attrs_num * curve_points.
size();
418 closest_distances.
fill(std::numeric_limits<float>::max());
419 mapped_curve_positions.
reinitialize(total_curve_points);
423 position_offsets_in_td,
424 bezier_offsets_in_td[curve_i],
427 bool has_any_selected =
false;
428 for (
const int selection_attr_i :
IndexRange(selection_attrs_num)) {
429 has_any_selected = has_any_selected ||
433 if (!has_any_selected) {
434 for (
const int i : map) {
441 for (
const int i : closest_distances.
index_range()) {
443 mapped_curve_positions[i] = td.loc;
445 closest_distances[i] = 0.0f;
450 for (
const int i : closest_distances.
index_range()) {
452 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.
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Span< T > as_span() const
MutableSpan< T > as_mutable_span()
IndexRange index_range() const
void fill(const T &value) const
void reinitialize(const int64_t new_size)
IndexRange index_range() const
constexpr int64_t size() const
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
constexpr Span slice(int64_t start, int64_t size) const
void append(const T &value)
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)
constexpr int64_t start() const
constexpr IndexRange index_range() const
constexpr IndexRange index_range() const
constexpr int64_t size() const
constexpr IndexRange index_range() const
static VArray ForSingle(T value, const int64_t size)
void append(const T &value)
const T & last(const int64_t n=0) const
IndexRange index_range() const
Span< T > as_span() const
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const void *default_value=nullptr) const
Span< float3 > handle_positions_left() const
Span< float3 > positions() const
Span< float3 > handle_positions_right() const
AttributeAccessor attributes() const
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
IndexRange index_range() const
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)
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)
static bool has_anything_selected(const Span< Curves * > curves_ids)
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)
void copy_group_sizes(OffsetIndices< int > offsets, const IndexMask &mask, MutableSpan< int > sizes)
OffsetIndices< int > accumulate_counts_to_offsets(MutableSpan< int > counts_to_offsets, int start_offset=0)
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))
MatBase< float, 4, 4 > float4x4
GPU_SHADER_INTERFACE_INFO(overlay_edit_curve_handle_iface, "vert").flat(Type pos vertex_in(1, Type::UINT, "data") .vertex_out(overlay_edit_curve_handle_iface) .geometry_layout(PrimitiveIn Frequency::GEOMETRY storage_buf(1, Qualifier::READ, "uint", "data[]", Frequency::GEOMETRY) .push_constant(Type Frequency::GEOMETRY selection[]
void(* free_cb)(TransInfo *, TransDataContainer *tc, TransCustomData *custom_data)
TransCustomDataContainer custom
TransDataContainer * data_container
MutableVArraySpan< T > span