Welcome to mirror list, hosted at ThFree Co, Russian Federation.

curves_utils.cc « intern « blenkernel « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 2b13a7d3c8a1d76603ccae09516fb72ed3912c7c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/* SPDX-License-Identifier: GPL-2.0-or-later */

/** \file
 * \ingroup bke
 */

#include "BLI_index_mask_ops.hh"

#include "BKE_curves_utils.hh"

namespace blender::bke::curves {

void fill_curve_counts(const bke::CurvesGeometry &curves,
                       const Span<IndexRange> curve_ranges,
                       MutableSpan<int> counts)
{
  threading::parallel_for(curve_ranges.index_range(), 512, [&](IndexRange ranges_range) {
    for (const IndexRange curves_range : curve_ranges.slice(ranges_range)) {
      threading::parallel_for(curves_range, 4096, [&](IndexRange range) {
        for (const int i : range) {
          counts[i] = curves.points_for_curve(i).size();
        }
      });
    }
  });
}

void accumulate_counts_to_offsets(MutableSpan<int> counts_to_offsets, const int start_offset)
{
  int offset = start_offset;
  for (const int i : counts_to_offsets.index_range().drop_back(1)) {
    const int count = counts_to_offsets[i];
    BLI_assert(count > 0);
    counts_to_offsets[i] = offset;
    offset += count;
  }
  counts_to_offsets.last() = offset;
}

void copy_point_data(const CurvesGeometry &src_curves,
                     const CurvesGeometry &dst_curves,
                     const Span<IndexRange> curve_ranges,
                     const GSpan src,
                     GMutableSpan dst)
{
  threading::parallel_for(curve_ranges.index_range(), 512, [&](IndexRange range) {
    for (const IndexRange range : curve_ranges.slice(range)) {
      const IndexRange src_points = src_curves.points_for_curves(range);
      const IndexRange dst_points = dst_curves.points_for_curves(range);
      /* The arrays might be large, so a threaded copy might make sense here too. */
      dst.slice(dst_points).copy_from(src.slice(src_points));
    }
  });
}

void copy_point_data(const CurvesGeometry &src_curves,
                     const CurvesGeometry &dst_curves,
                     const IndexMask src_curve_selection,
                     const GSpan src,
                     GMutableSpan dst)
{
  threading::parallel_for(src_curve_selection.index_range(), 512, [&](IndexRange range) {
    for (const int i : src_curve_selection.slice(range)) {
      const IndexRange src_points = src_curves.points_for_curve(i);
      const IndexRange dst_points = dst_curves.points_for_curve(i);
      /* The arrays might be large, so a threaded copy might make sense here too. */
      dst.slice(dst_points).copy_from(src.slice(src_points));
    }
  });
}

void fill_points(const CurvesGeometry &curves,
                 const IndexMask curve_selection,
                 const GPointer value,
                 GMutableSpan dst)
{
  BLI_assert(*value.type() == dst.type());
  const CPPType &type = dst.type();
  threading::parallel_for(curve_selection.index_range(), 512, [&](IndexRange range) {
    for (const int i : curve_selection.slice(range)) {
      const IndexRange points = curves.points_for_curve(i);
      type.fill_assign_n(value.get(), dst.slice(curves.points_for_curve(i)).data(), points.size());
    }
  });
}

void fill_points(const CurvesGeometry &curves,
                 Span<IndexRange> curve_ranges,
                 GPointer value,
                 GMutableSpan dst)
{
  BLI_assert(*value.type() == dst.type());
  const CPPType &type = dst.type();
  threading::parallel_for(curve_ranges.index_range(), 512, [&](IndexRange range) {
    for (const IndexRange range : curve_ranges.slice(range)) {
      const IndexRange points = curves.points_for_curves(range);
      type.fill_assign_n(value.get(), dst.slice(points).data(), points.size());
    }
  });
}

bke::CurvesGeometry copy_only_curve_domain(const bke::CurvesGeometry &src_curves)
{
  bke::CurvesGeometry dst_curves(0, src_curves.curves_num());
  CustomData_copy(&src_curves.curve_data,
                  &dst_curves.curve_data,
                  CD_MASK_ALL,
                  CD_DUPLICATE,
                  src_curves.curves_num());
  dst_curves.runtime->type_counts = src_curves.runtime->type_counts;
  return dst_curves;
}

IndexMask indices_for_type(const VArray<int8_t> &types,
                           const std::array<int, CURVE_TYPES_NUM> &type_counts,
                           const CurveType type,
                           const IndexMask selection,
                           Vector<int64_t> &r_indices)
{
  if (type_counts[type] == types.size()) {
    return selection;
  }
  if (types.is_single()) {
    return types.get_internal_single() == type ? IndexMask(types.size()) : IndexMask(0);
  }
  Span<int8_t> types_span = types.get_internal_span();
  return index_mask_ops::find_indices_based_on_predicate(
      selection, 4096, r_indices, [&](const int index) { return types_span[index] == type; });
}

void indices_for_each_type(const VArray<int8_t> &types,
                           const std::array<int, CURVE_TYPES_NUM> &counts,
                           const IndexMask selection,
                           std::array<IndexMask, CURVE_TYPES_NUM> &r_type_masks,
                           std::array<Vector<int64_t>, CURVE_TYPES_NUM> &r_type_indices)
{
  for (const int64_t curve_type : IndexRange(CURVE_TYPES_NUM)) {
    r_type_masks[curve_type] = indices_for_type(
        types, counts, CurveType(curve_type), selection, r_type_indices[curve_type]);
  }
}

void foreach_curve_by_type(const VArray<int8_t> &types,
                           const std::array<int, CURVE_TYPES_NUM> &counts,
                           const IndexMask selection,
                           FunctionRef<void(IndexMask)> catmull_rom_fn,
                           FunctionRef<void(IndexMask)> poly_fn,
                           FunctionRef<void(IndexMask)> bezier_fn,
                           FunctionRef<void(IndexMask)> nurbs_fn)
{
  Vector<int64_t> indices;
  auto call_if_not_empty = [&](const CurveType type, FunctionRef<void(IndexMask)> fn) {
    indices.clear();
    const IndexMask mask = indices_for_type(types, counts, type, selection, indices);
    if (!mask.is_empty()) {
      fn(mask);
    }
  };
  call_if_not_empty(CURVE_TYPE_CATMULL_ROM, catmull_rom_fn);
  call_if_not_empty(CURVE_TYPE_POLY, poly_fn);
  call_if_not_empty(CURVE_TYPE_BEZIER, bezier_fn);
  call_if_not_empty(CURVE_TYPE_NURBS, nurbs_fn);
}

void foreach_curve_by_type_mask(const std::array<IndexMask, CURVE_TYPES_NUM> &curve_type_mask,
                                FunctionRef<void(IndexMask)> catmull_rom_fn,
                                FunctionRef<void(IndexMask)> poly_fn,
                                FunctionRef<void(IndexMask)> bezier_fn,
                                FunctionRef<void(IndexMask)> nurbs_fn)
{
  auto call_if_not_empty = [&](const IndexMask curve_type_mask, FunctionRef<void(IndexMask)> fn) {
    if (!curve_type_mask.is_empty()) {
      fn(curve_type_mask);
    }
  };
  call_if_not_empty(curve_type_mask[0], catmull_rom_fn);
  call_if_not_empty(curve_type_mask[1], poly_fn);
  call_if_not_empty(curve_type_mask[2], bezier_fn);
  call_if_not_empty(curve_type_mask[3], nurbs_fn);
}

}  // namespace blender::bke::curves