30 BLI_assert(!curve_geometry_.nurbs_element_.curv_indices.is_empty());
34 this->create_nurbs(curves, import_params);
40 if (curve_geometry_.nurbs_element_.curv_indices.is_empty()) {
45 if (ob_name.empty() && !curve_geometry_.nurbs_element_.group_.empty()) {
46 ob_name = curve_geometry_.nurbs_element_.group_;
48 if (ob_name.empty()) {
62 this->create_nurbs(curve, import_params);
73 const int degree = std::max(1, std::min<int>(
element.degree,
element.curv_indices.size() - 1));
74 return degree + 1 > std::numeric_limits<int8_t>::max() ? std::numeric_limits<int8_t>::max() - 1 :
87 knots.
slice(1, order - 1));
90 return order - multiplicity.
first();
95 const NurbsElement &nurbs_geometry = curve_geometry_.
nurbs_element_;
111 nurbs_geometry.parm);
112 nurb->
flagu = this->detect_knot_mode(
113 import_params, degree, nurbs_geometry.curv_indices, nurbs_geometry.parm, multiplicity);
119 nurbs_geometry.curv_indices.index_range().drop_back(repeated_points));
122 for (
const int i :
indices.index_range()) {
141void CurveFromGeometry::create_nurbs(bke::CurvesGeometry &curves,
142 const OBJImportParams &import_params)
144 const NurbsElement &nurbs_geometry = curve_geometry_.nurbs_element_;
146 const int8_t order = degree + 1;
149 nurbs_geometry.parm);
150 const short knot_flag = this->detect_knot_mode(
151 import_params, degree, nurbs_geometry.curv_indices, nurbs_geometry.parm, multiplicity);
156 const Span<int>
indices = nurbs_geometry.curv_indices.as_span().slice(
157 nurbs_geometry.curv_indices.index_range().drop_back(repeated_points));
159 const int points_num =
indices.size();
160 const int curve_index = 0;
161 curves.resize(points_num, 1);
163 MutableSpan<int8_t>
types = curves.curve_types_for_write();
164 MutableSpan<bool> cyclic = curves.cyclic_for_write();
165 MutableSpan<int8_t> orders = curves.nurbs_orders_for_write();
166 MutableSpan<int8_t> modes = curves.nurbs_knots_modes_for_write();
169 orders.
first() = order;
171 curves.update_curve_types();
173 const OffsetIndices points_by_curve = curves.points_by_curve();
174 const IndexRange point_range = points_by_curve[curve_index];
176 MutableSpan<float3> positions = curves.positions_for_write().slice(point_range);
177 MutableSpan<float> weights = curves.nurbs_weights_for_write().slice(point_range);
178 for (
const int i :
indices.index_range()) {
179 positions[
i] = global_vertices_.vertices[
indices[
i]];
180 weights[
i] = (global_vertices_.vertex_weights.size() >
indices[
i]) ?
181 global_vertices_.vertex_weights[
indices[
i]] :
186 OffsetIndices<int> knot_offsets = curves.nurbs_custom_knots_by_curve();
187 curves.nurbs_custom_knots_update_size();
188 MutableSpan<float> knots = curves.nurbs_custom_knots_for_write().slice(
189 knot_offsets[curve_index]);
197 const int8_t order = degree + 1;
203 const bool begin_clamped = multiplicity.
first() == order ||
204 (multiplicity.
first() == 1 && multiplicity[1] == degree);
205 const bool end_clamped = multiplicity.
last() == order ||
206 (multiplicity.
last() == 1 && multiplicity.
last(1) == degree);
207 return begin_clamped && end_clamped;
212 const float abs_diff = std::abs(
b - a);
213 return abs_diff < a * epsilon;
220 const bool is_clamped)
222 constexpr float epsilon = 1
e-4;
223 const int8_t order = degree + 1;
238 if (multiplicity.
first() > order || multiplicity.
last() > order) {
256 const float head_span = knots[
i + 1] - knots[
i];
257 const float tail_span = knots_tail[
i + 1] - knots_tail[
i];
266 const int num_points,
269 const int8_t order = degree + 1;
279 if (multiplicity[0] < order && (multiplicity[0] != 1 || multiplicity[1] < degree)) {
284 if (multiplicity.
size() == 2) {
289 if (multiplicity.
first() != order) {
298 if (multiplicity.
last() != order &&
299 (multiplicity.
last() == 1 && multiplicity.
last(1) != degree))
305 const int remainder = (num_points - 1) % degree;
306 if (multiplicity.
last() != order + remainder &&
307 (multiplicity.
last() != 1 || multiplicity.
last(1) < degree))
312 mdegree_span = mdegree_span.
drop_back(1);
315 for (
const int m : mdegree_span) {
328 constexpr float epsilon = 1
e-4;
333 const int O1_clamps = int(multiplicity.
first() == 1) + int(multiplicity.
last() == 1);
334 const int clamped_offset = clamped ? 2 * degree - O1_clamps : 0;
335 if (knots.
size() != multiplicity.
size() + clamped_offset) {
341 if (unclamped_knots.
size() == 2) {
344 if (unclamped_knots.
size() < 2) {
350 const float uniform_delta = unclamped_knots[1] - unclamped_knots[0];
352 const float delta = unclamped_knots[
i] - unclamped_knots[
i - 1];
360short CurveFromGeometry::detect_knot_mode(
const OBJImportParams &import_params,
383 if (check_cyclic && !no_custom_cyclic) {
385 degree,
indices, knots, multiplicity, is_clamped);
ListBase * BKE_curve_nurbs_get(Curve *cu)
void BKE_nurb_knot_calc_u(Nurb *nu)
Curve * BKE_curve_add(Main *bmain, const char *name, int type)
void BKE_nurb_knot_alloc_u(Nurb *nu)
void BKE_nurb_points_add(Nurb *nu, int number)
Low-level operations for curves.
General operations, lookup, etc. for blender objects.
Object * BKE_object_add_only_object(Main *bmain, int type, const char *name) ATTR_RETURNS_NONNULL
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define SET_FLAG_FROM_TEST(value, test, flag)
ATTR_WARN_UNUSED_RESULT const void * element
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
constexpr T & first() const
constexpr IndexRange drop_back(int64_t n) const
constexpr IndexRange drop_front(int64_t n) const
constexpr Span drop_front(int64_t n) const
constexpr Span slice(int64_t start, int64_t size) const
constexpr Span take_back(int64_t n) const
constexpr Span drop_back(int64_t n) const
constexpr const T & first() const
constexpr int64_t size() const
constexpr const T & last(const int64_t n=0) const
constexpr IndexRange index_range() const
Object * create_curve_object(Main *bmain, const OBJImportParams &import_params)
Curves * create_curve(const OBJImportParams &import_params)
static bool is_cyclic(const Nurb *nu)
void * MEM_callocN(size_t len, const char *str)
void copy(const GVArray &src, GMutableSpan dst, int64_t grain_size=4096)
Vector< int > calculate_multiplicity_sequence(Span< float > knots)
KnotsMode knots_mode_from_legacy(short flag)
Curves * curves_new_nomain(int points_num, int curves_num)
static bool detect_knot_mode_bezier_clamped(const int8_t degree, const int num_points, const Span< int > multiplicity)
static int repeating_cyclic_point_num(const int8_t order, const Span< float > knots)
static int8_t get_valid_nurbs_degree(const NurbsElement &element)
static bool almost_equal_relative(const float a, const float b, const float epsilon)
static bool detect_clamped_endpoint(const int8_t degree, const Span< int > multiplicity)
static bool detect_knot_mode_uniform(const int8_t degree, const Span< float > knots, const Span< int > multiplicity, const bool clamped)
static bool detect_knot_mode_cyclic(const int8_t degree, const Span< int > indices, const Span< float > knots, const Span< int > multiplicity, const bool is_clamped)
void transform_object(Object *object, const OBJImportParams &import_params)
std::string get_geometry_name(const std::string &full_name, char separator)
char collection_separator
NurbsElement nurbs_element_
Vector< float > vertex_weights
Vector< float3 > vertices