Blender  V3.3
curve_legacy_convert.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include "BLI_task.hh"
4 #include "BLI_vector.hh"
5 
6 #include "DNA_curve_types.h"
7 #include "DNA_curves_types.h"
8 
9 #include "BKE_curve.h"
11 #include "BKE_curves.hh"
12 #include "BKE_curves_utils.hh"
13 #include "BKE_geometry_set.hh"
14 
15 namespace blender::bke {
16 
18 {
19  switch (type) {
20  case CU_POLY:
21  return CURVE_TYPE_POLY;
22  case CU_BEZIER:
23  return CURVE_TYPE_BEZIER;
24  case CU_NURBS:
25  return CURVE_TYPE_NURBS;
26  }
28  return CURVE_TYPE_POLY;
29 }
30 
31 static HandleType handle_type_from_legacy(const uint8_t handle_type_legacy)
32 {
33  switch (handle_type_legacy) {
34  case HD_FREE:
35  return BEZIER_HANDLE_FREE;
36  case HD_AUTO:
37  return BEZIER_HANDLE_AUTO;
38  case HD_VECT:
39  return BEZIER_HANDLE_VECTOR;
40  case HD_ALIGN:
41  return BEZIER_HANDLE_ALIGN;
42  case HD_AUTO_ANIM:
43  return BEZIER_HANDLE_AUTO;
45  return BEZIER_HANDLE_ALIGN;
46  }
48  return BEZIER_HANDLE_AUTO;
49 }
50 
51 static NormalMode normal_mode_from_legacy(const short twist_mode)
52 {
53  switch (twist_mode) {
54  case CU_TWIST_Z_UP:
55  case CU_TWIST_TANGENT:
56  return NORMAL_MODE_Z_UP;
57  case CU_TWIST_MINIMUM:
59  }
62 }
63 
64 static KnotsMode knots_mode_from_legacy(const short flag)
65 {
66  switch (flag & (CU_NURB_ENDPOINT | CU_NURB_BEZIER)) {
67  case CU_NURB_ENDPOINT:
69  case CU_NURB_BEZIER:
73  case 0:
75  }
78 }
79 
80 Curves *curve_legacy_to_curves(const Curve &curve_legacy, const ListBase &nurbs_list)
81 {
82  const Vector<const Nurb *> src_curves(nurbs_list);
83 
84  Curves *curves_id = curves_new_nomain(0, src_curves.size());
86  MutableAttributeAccessor curves_attributes = curves.attributes_for_write();
87 
88  MutableSpan<int8_t> types = curves.curve_types_for_write();
89  MutableSpan<bool> cyclic = curves.cyclic_for_write();
90 
91  int offset = 0;
92  MutableSpan<int> offsets = curves.offsets_for_write();
93  for (const int i : src_curves.index_range()) {
94  offsets[i] = offset;
95 
96  const Nurb &src_curve = *src_curves[i];
97  types[i] = curve_type_from_legacy(src_curve.type);
98  cyclic[i] = src_curve.flagu & CU_NURB_CYCLIC;
99 
100  offset += src_curve.pntsu;
101  }
102  offsets.last() = offset;
103  curves.resize(curves.offsets().last(), curves.curves_num());
104 
105  curves.update_curve_types();
106 
107  if (curves.curves_num() == 0) {
108  return curves_id;
109  }
110 
111  MutableSpan<float3> positions = curves.positions_for_write();
112  SpanAttributeWriter<float> radius_attribute =
113  curves_attributes.lookup_or_add_for_write_only_span<float>("radius", ATTR_DOMAIN_POINT);
114  MutableSpan<float> radii = radius_attribute.span;
115  MutableSpan<float> tilts = curves.tilt_for_write();
116 
117  auto create_poly = [&](IndexMask selection) {
118  threading::parallel_for(selection.index_range(), 256, [&](IndexRange range) {
119  for (const int curve_i : selection.slice(range)) {
120  const Nurb &src_curve = *src_curves[curve_i];
121  const Span<BPoint> src_points(src_curve.bp, src_curve.pntsu);
122  const IndexRange points = curves.points_for_curve(curve_i);
123 
124  for (const int i : src_points.index_range()) {
125  const BPoint &bp = src_points[i];
126  positions[points[i]] = bp.vec;
127  radii[points[i]] = bp.radius;
128  tilts[points[i]] = bp.tilt;
129  }
130  }
131  });
132  };
133 
134  /* NOTE: For curve handles, legacy curves can end up in invalid situations where the handle
135  * positions don't agree with the types because of evaluation, or because one-sided aligned
136  * handles weren't considered. While recalculating automatic handles to fix those situations
137  * is an option, currently this opts not to for the sake of flexibility. */
138  auto create_bezier = [&](IndexMask selection) {
139  MutableSpan<int> resolutions = curves.resolution_for_write();
140  MutableSpan<float3> handle_positions_l = curves.handle_positions_left_for_write();
141  MutableSpan<float3> handle_positions_r = curves.handle_positions_right_for_write();
142  MutableSpan<int8_t> handle_types_l = curves.handle_types_left_for_write();
143  MutableSpan<int8_t> handle_types_r = curves.handle_types_right_for_write();
144 
145  threading::parallel_for(selection.index_range(), 256, [&](IndexRange range) {
146  for (const int curve_i : selection.slice(range)) {
147  const Nurb &src_curve = *src_curves[curve_i];
148  const Span<BezTriple> src_points(src_curve.bezt, src_curve.pntsu);
149  const IndexRange points = curves.points_for_curve(curve_i);
150 
151  resolutions[curve_i] = src_curve.resolu;
152 
153  for (const int i : src_points.index_range()) {
154  const BezTriple &point = src_points[i];
155  positions[points[i]] = point.vec[1];
156  handle_positions_l[points[i]] = point.vec[0];
157  handle_types_l[points[i]] = handle_type_from_legacy(point.h1);
158  handle_positions_r[points[i]] = point.vec[2];
159  handle_types_r[points[i]] = handle_type_from_legacy(point.h2);
160  radii[points[i]] = point.radius;
161  tilts[points[i]] = point.tilt;
162  }
163  }
164  });
165  };
166 
167  auto create_nurbs = [&](IndexMask selection) {
168  MutableSpan<int> resolutions = curves.resolution_for_write();
169  MutableSpan<float> nurbs_weights = curves.nurbs_weights_for_write();
170  MutableSpan<int8_t> nurbs_orders = curves.nurbs_orders_for_write();
171  MutableSpan<int8_t> nurbs_knots_modes = curves.nurbs_knots_modes_for_write();
172 
173  threading::parallel_for(selection.index_range(), 256, [&](IndexRange range) {
174  for (const int curve_i : selection.slice(range)) {
175  const Nurb &src_curve = *src_curves[curve_i];
176  const Span src_points(src_curve.bp, src_curve.pntsu);
177  const IndexRange points = curves.points_for_curve(curve_i);
178 
179  resolutions[curve_i] = src_curve.resolu;
180  nurbs_orders[curve_i] = src_curve.orderu;
181  nurbs_knots_modes[curve_i] = knots_mode_from_legacy(src_curve.flagu);
182 
183  for (const int i : src_points.index_range()) {
184  const BPoint &bp = src_points[i];
185  positions[points[i]] = bp.vec;
186  radii[points[i]] = bp.radius;
187  tilts[points[i]] = bp.tilt;
188  nurbs_weights[points[i]] = bp.vec[3];
189  }
190  }
191  });
192  };
193 
195  curves.curve_types(),
196  curves.curve_type_counts(),
197  curves.curves_range(),
198  [&](IndexMask /*selection*/) { BLI_assert_unreachable(); },
199  create_poly,
200  create_bezier,
201  create_nurbs);
202 
203  curves.normal_mode_for_write().fill(normal_mode_from_legacy(curve_legacy.twist_mode));
204 
205  radius_attribute.finish();
206 
207  return curves_id;
208 }
209 
210 Curves *curve_legacy_to_curves(const Curve &curve_legacy)
211 {
212  return curve_legacy_to_curves(curve_legacy, *BKE_curve_nurbs_get_for_read(&curve_legacy));
213 }
214 
215 } // namespace blender::bke
@ ATTR_DOMAIN_POINT
Definition: BKE_attribute.h:27
const ListBase * BKE_curve_nurbs_get_for_read(const struct Curve *cu)
Low-level operations for curves.
Low-level operations for curves.
#define BLI_assert_unreachable()
Definition: BLI_assert.h:93
@ CU_BEZIER
@ CU_POLY
@ CU_NURBS
@ CU_NURB_CYCLIC
@ CU_NURB_ENDPOINT
@ CU_NURB_BEZIER
@ HD_AUTO_ANIM
@ HD_VECT
@ HD_FREE
@ HD_AUTO
@ HD_ALIGN_DOUBLESIDE
@ HD_ALIGN
@ CU_TWIST_MINIMUM
@ CU_TWIST_TANGENT
@ CU_TWIST_Z_UP
CurveType
@ CURVE_TYPE_BEZIER
@ CURVE_TYPE_NURBS
@ CURVE_TYPE_POLY
NormalMode
@ NORMAL_MODE_MINIMUM_TWIST
@ NORMAL_MODE_Z_UP
HandleType
@ BEZIER_HANDLE_FREE
@ BEZIER_HANDLE_ALIGN
@ BEZIER_HANDLE_VECTOR
@ BEZIER_HANDLE_AUTO
KnotsMode
@ NURBS_KNOT_MODE_ENDPOINT
@ NURBS_KNOT_MODE_NORMAL
@ NURBS_KNOT_MODE_BEZIER
@ NURBS_KNOT_MODE_ENDPOINT_BEZIER
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to curves
constexpr T & last(const int64_t n=0) const
Definition: BLI_span.hh:680
int64_t size() const
Definition: BLI_vector.hh:694
IndexRange index_range() const
Definition: BLI_vector.hh:920
static CurvesGeometry & wrap(::CurvesGeometry &dna_struct)
Definition: BKE_curves.hh:138
GSpanAttributeWriter lookup_or_add_for_write_only_span(const AttributeIDRef &attribute_id, const eAttrDomain domain, const eCustomDataType data_type)
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
static char ** types
Definition: makesdna.c:67
void foreach_curve_by_type(const VArray< int8_t > &types, const std::array< int, CURVE_TYPES_NUM > &type_counts, IndexMask selection, FunctionRef< void(IndexMask)> catmull_rom_fn, FunctionRef< void(IndexMask)> poly_fn, FunctionRef< void(IndexMask)> bezier_fn, FunctionRef< void(IndexMask)> nurbs_fn)
Curves * curve_legacy_to_curves(const Curve &curve_legacy)
static KnotsMode knots_mode_from_legacy(const short flag)
static CurveType curve_type_from_legacy(const short type)
static NormalMode normal_mode_from_legacy(const short twist_mode)
static HandleType handle_type_from_legacy(const uint8_t handle_type_legacy)
Curves * curves_new_nomain(int points_num, int curves_num)
Definition: curves.cc:367
void parallel_for(IndexRange range, int64_t grain_size, const Function &function)
Definition: BLI_task.hh:51
MutableSpan< float3 > positions
MutableSpan< float > radii
unsigned char uint8_t
Definition: stdint.h:78
CurvesGeometry geometry
short flagu
short type