Blender V4.3
curve_legacy_convert.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
5#include "BLI_listbase.h"
6#include "BLI_task.hh"
7#include "BLI_vector.hh"
8
9#include "DNA_curve_types.h"
10#include "DNA_curves_types.h"
11
12#include "BKE_curve.hh"
14#include "BKE_curves.hh"
15#include "BKE_curves_utils.hh"
16#include "BKE_geometry_set.hh"
17
18namespace blender::bke {
19
20static CurveType curve_type_from_legacy(const short type)
21{
22 switch (type) {
23 case CU_POLY:
24 return CURVE_TYPE_POLY;
25 case CU_BEZIER:
26 return CURVE_TYPE_BEZIER;
27 case CU_NURBS:
28 return CURVE_TYPE_NURBS;
29 }
31 return CURVE_TYPE_POLY;
32}
33
34static HandleType handle_type_from_legacy(const uint8_t handle_type_legacy)
35{
36 switch (handle_type_legacy) {
37 case HD_FREE:
38 return BEZIER_HANDLE_FREE;
39 case HD_AUTO:
40 return BEZIER_HANDLE_AUTO;
41 case HD_VECT:
43 case HD_ALIGN:
45 case HD_AUTO_ANIM:
46 return BEZIER_HANDLE_AUTO;
49 }
51 return BEZIER_HANDLE_AUTO;
52}
53
54static NormalMode normal_mode_from_legacy(const short twist_mode)
55{
56 switch (twist_mode) {
57 case CU_TWIST_Z_UP:
59 return NORMAL_MODE_Z_UP;
62 }
65}
66
82
83Curves *curve_legacy_to_curves(const Curve &curve_legacy, const ListBase &nurbs_list)
84{
85 Vector<const Nurb *> src_curves;
86 LISTBASE_FOREACH (const Nurb *, item, &nurbs_list) {
87 src_curves.append(item);
88 }
89 if (src_curves.is_empty()) {
90 return nullptr;
91 }
92
93 Curves *curves_id = curves_new_nomain(0, src_curves.size());
94 CurvesGeometry &curves = curves_id->geometry.wrap();
95 MutableAttributeAccessor curves_attributes = curves.attributes_for_write();
96
97 MutableSpan<int8_t> types = curves.curve_types_for_write();
98 MutableSpan<bool> cyclic = curves.cyclic_for_write();
99
100 int offset = 0;
101 MutableSpan<int> offsets = curves.offsets_for_write();
102 for (const int i : src_curves.index_range()) {
103 offsets[i] = offset;
104
105 const Nurb &src_curve = *src_curves[i];
106 types[i] = curve_type_from_legacy(src_curve.type);
107 cyclic[i] = src_curve.flagu & CU_NURB_CYCLIC;
108
109 offset += src_curve.pntsu;
110 }
111 offsets.last() = offset;
112 curves.resize(curves.offsets().last(), curves.curves_num());
113
114 curves.update_curve_types();
115
116 const OffsetIndices points_by_curve = curves.points_by_curve();
117 MutableSpan<float3> positions = curves.positions_for_write();
118 SpanAttributeWriter<float> radius_attribute =
119 curves_attributes.lookup_or_add_for_write_only_span<float>("radius", AttrDomain::Point);
120 MutableSpan<float> radii = radius_attribute.span;
121 MutableSpan<float> tilts = curves.tilt_for_write();
122
123 auto create_poly = [&](const IndexMask &selection) {
124 selection.foreach_index(GrainSize(256), [&](const int curve_i) {
125 const Nurb &src_curve = *src_curves[curve_i];
126 const Span<BPoint> src_points(src_curve.bp, src_curve.pntsu);
127 const IndexRange points = points_by_curve[curve_i];
128
129 for (const int i : src_points.index_range()) {
130 const BPoint &bp = src_points[i];
131 positions[points[i]] = bp.vec;
132 radii[points[i]] = bp.radius;
133 tilts[points[i]] = bp.tilt;
134 }
135 });
136 };
137
138 /* NOTE: For curve handles, legacy curves can end up in invalid situations where the handle
139 * positions don't agree with the types because of evaluation, or because one-sided aligned
140 * handles weren't considered. While recalculating automatic handles to fix those situations
141 * is an option, currently this opts not to for the sake of flexibility. */
142 auto create_bezier = [&](const IndexMask &selection) {
143 MutableSpan<int> resolutions = curves.resolution_for_write();
144 MutableSpan<float3> handle_positions_l = curves.handle_positions_left_for_write();
145 MutableSpan<float3> handle_positions_r = curves.handle_positions_right_for_write();
146 MutableSpan<int8_t> handle_types_l = curves.handle_types_left_for_write();
147 MutableSpan<int8_t> handle_types_r = curves.handle_types_right_for_write();
148
149 selection.foreach_index(GrainSize(256), [&](const int curve_i) {
150 const Nurb &src_curve = *src_curves[curve_i];
151 const Span<BezTriple> src_points(src_curve.bezt, src_curve.pntsu);
152 const IndexRange points = points_by_curve[curve_i];
153
154 resolutions[curve_i] = src_curve.resolu;
155
156 for (const int i : src_points.index_range()) {
157 const BezTriple &point = src_points[i];
158 positions[points[i]] = point.vec[1];
159 handle_positions_l[points[i]] = point.vec[0];
160 handle_types_l[points[i]] = handle_type_from_legacy(point.h1);
161 handle_positions_r[points[i]] = point.vec[2];
162 handle_types_r[points[i]] = handle_type_from_legacy(point.h2);
163 radii[points[i]] = point.radius;
164 tilts[points[i]] = point.tilt;
165 }
166 });
167 };
168
169 auto create_nurbs = [&](const IndexMask &selection) {
170 MutableSpan<int> resolutions = curves.resolution_for_write();
171 MutableSpan<float> nurbs_weights = curves.nurbs_weights_for_write();
172 MutableSpan<int8_t> nurbs_orders = curves.nurbs_orders_for_write();
173 MutableSpan<int8_t> nurbs_knots_modes = curves.nurbs_knots_modes_for_write();
174
175 selection.foreach_index(GrainSize(256), [&](const int curve_i) {
176 const Nurb &src_curve = *src_curves[curve_i];
177 const Span src_points(src_curve.bp, src_curve.pntsu);
178 const IndexRange points = points_by_curve[curve_i];
179
180 resolutions[curve_i] = src_curve.resolu;
181 nurbs_orders[curve_i] = src_curve.orderu;
182 nurbs_knots_modes[curve_i] = knots_mode_from_legacy(src_curve.flagu);
183
184 for (const int i : src_points.index_range()) {
185 const BPoint &bp = src_points[i];
186 positions[points[i]] = bp.vec;
187 radii[points[i]] = bp.radius;
188 tilts[points[i]] = bp.tilt;
189 nurbs_weights[points[i]] = bp.vec[3];
190 }
191 });
192 };
193
195 curves.curve_types(),
196 curves.curve_type_counts(),
197 curves.curves_range(),
198 [&](const 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
211{
212 return curve_legacy_to_curves(curve_legacy, *BKE_curve_nurbs_get_for_read(&curve_legacy));
213}
214
215} // namespace blender::bke
const ListBase * BKE_curve_nurbs_get_for_read(const Curve *cu)
Definition curve.cc:4974
Low-level operations for curves.
Low-level operations for curves.
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define LISTBASE_FOREACH(type, var, list)
@ CU_BEZIER
@ CU_POLY
@ CU_NURBS
@ HD_AUTO_ANIM
@ HD_VECT
@ HD_FREE
@ HD_AUTO
@ HD_ALIGN_DOUBLESIDE
@ HD_ALIGN
@ CU_TWIST_MINIMUM
@ CU_TWIST_TANGENT
@ CU_TWIST_Z_UP
@ CU_NURB_CYCLIC
@ CU_NURB_ENDPOINT
@ CU_NURB_BEZIER
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
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a point
constexpr T & last(const int64_t n=0) const
Definition BLI_span.hh:690
constexpr IndexRange index_range() const
Definition BLI_span.hh:402
int64_t size() const
void append(const T &value)
bool is_empty() const
IndexRange index_range() const
GSpanAttributeWriter lookup_or_add_for_write_only_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type)
static char ** types
Definition makesdna.cc:71
void foreach_curve_by_type(const VArray< int8_t > &types, const std::array< int, CURVE_TYPES_NUM > &type_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)
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)
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[]
unsigned char uint8_t
Definition stdint.h:78
float vec[4]
short twist_mode
CurvesGeometry geometry
short flagu
short orderu
short type
BezTriple * bezt
BPoint * bp
short resolu
uint8_t flag
Definition wm_window.cc:138