Blender V5.0
obj_export_nurbs.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
8
9#include <numeric>
10
11#include "BLI_listbase.h"
12#include "BLI_utility_mixins.hh"
13
15#include "BKE_curves.hh"
16#include "DNA_curve_types.h"
17
18#include "DEG_depsgraph.hh"
20
21#include "obj_export_nurbs.hh"
22
23namespace blender::io::obj {
24
25/* -------------------------------------------------------------------- */
28
29/* Find the multiplicity entry with the valid span occurring on the right side of the related
30 * breakpoint/knot. */
31static int find_leftmost_span(const int8_t order, const Span<int> multiplicity)
32{
33 int index = -1;
34 int acc = 0;
35 while (acc < order) {
36 acc += multiplicity[++index];
37 }
38 BLI_assert(index > -1);
39 return index;
40}
41
42/* Find the multiplicity entry with the valid span occurring on the left side of the related
43 * breakpoint/knot. */
44static int find_rightmost_span(const int8_t order, const Span<int> multiplicity)
45{
46 int index = multiplicity.size();
47 int acc = 0;
48 while (acc < order) {
49 acc += multiplicity[--index];
50 }
51 BLI_assert(index < multiplicity.size());
52 return index;
53}
54
56 const Span<float> knots,
57 IndexRange &point_range)
58{
59 /* No consideration for cyclic, export must expand the knot vector! */
60 BLI_assert(knots.size() == bke::curves::nurbs::knots_num(point_range.size(), order, false));
61
62 /* This assumes multiplicity < order * 2 */
63 const int order2 = order * 2;
65 knots.slice(0, order2));
67 knots.slice(knots.size() - order2, order2));
68
69 const int leftmost = find_leftmost_span(order, left_mult);
70 const int rightmost = find_rightmost_span(order, right_mult);
71
72 /* For reasonable curve knots they should add up to 0 */
73 const int acc_start = std::accumulate(left_mult.begin(), left_mult.begin() + leftmost + 1, 0);
74 const int acc_end = std::accumulate(&right_mult[rightmost], right_mult.end(), 0);
75 int skip_start = acc_start - order;
76 int skip_end = acc_end - order;
77
78 /* Update ranges */
79 point_range = point_range.drop_front(skip_start).drop_back(skip_end);
80 return knots.drop_front(skip_start).drop_back(skip_end);
81}
82
84
85/* -------------------------------------------------------------------- */
88
90 const float4x4 &transform,
91 const std::string &name)
92 : curve_(curve), transform_(transform), name_(name)
93{
94}
95
97{
98 return transform_;
99}
100
101const char *OBJCurves::get_curve_name() const
102{
103 return name_.c_str();
104}
105
107{
108 return curve_.curve_num;
109}
110
111int OBJCurves::total_spline_vertices(int spline_index) const
112{
113 return curve_.points_by_curve()[spline_index].size();
114}
115
116int OBJCurves::num_control_points_u(int spline_index) const
117{
118 return bke::curves::nurbs::control_points_num(curve_.points_by_curve()[spline_index].size(),
119 get_nurbs_degree_u(spline_index) + 1,
120 get_cyclic_u(spline_index));
121}
122
123int OBJCurves::num_control_points_v(int /*spline_index*/) const
124{
125 return 1;
126}
127
128int OBJCurves::get_nurbs_degree_u(int spline_index) const
129{
130 return curve_.nurbs_orders()[spline_index] - 1;
131}
132
133int OBJCurves::get_nurbs_degree_v(int /*spline_index*/) const
134{
135 return -1;
136}
137
138bool OBJCurves::get_cyclic_u(int spline_index) const
139{
140 return curve_.cyclic()[spline_index];
141}
142
143Span<float> OBJCurves::get_knots_u(int spline_index, Vector<float> &knot_buffer) const
144{
145 const int point_count = curve_.points_by_curve()[spline_index].size();
146 const int8_t order = curve_.nurbs_orders()[spline_index];
147 const bool cyclic = curve_.cyclic()[spline_index];
148 const KnotsMode mode = KnotsMode(curve_.nurbs_knots_modes()[spline_index]);
149 const int knot_count = bke::curves::nurbs::knots_num(point_count, order, cyclic);
150
151 knot_buffer.resize(knot_count);
152 bke::curves::nurbs::calculate_knots(point_count, mode, order, cyclic, knot_buffer);
153 return knot_buffer;
154}
155
157 Vector<float3> & /*dynamic_point_buffer*/) const
158{
159 const IndexRange point_range = curve_.points_by_curve()[spline_index];
160 return curve_.positions().slice(point_range);
161}
162
164
165/* -------------------------------------------------------------------- */
168
169OBJLegacyCurve::OBJLegacyCurve(const Depsgraph *depsgraph, Object *curve_object)
170 : export_object_eval_(curve_object)
171{
172 export_object_eval_ = DEG_get_evaluated(depsgraph, curve_object);
173 export_curve_ = static_cast<Curve *>(export_object_eval_->data);
174}
175
176const Nurb *OBJLegacyCurve::get_spline(const int spline_index) const
177{
178 return static_cast<Nurb *>(BLI_findlink(&export_curve_->nurb, spline_index));
179}
180
182{
183 return export_object_eval_->id.name + 2;
184}
185
187{
188 return BLI_listbase_count(&export_curve_->nurb);
189}
190
192{
193 return export_object_eval_->object_to_world();
194}
195
196int OBJLegacyCurve::total_spline_vertices(const int spline_index) const
197{
198 const Nurb *const nurb = get_spline(spline_index);
199 return nurb->pntsu * nurb->pntsv;
200}
201
203 Vector<float3> &dynamic_point_buffer) const
204{
205 const Nurb *const nurb = get_spline(spline_index);
206 dynamic_point_buffer.resize(nurb->pntsu);
207
208 for (int64_t i = nurb->pntsu - 1; i >= 0; --i) {
209 const BPoint &bpoint = nurb->bp[i];
210 copy_v3_v3(dynamic_point_buffer[i], bpoint.vec);
211 }
212
213 return dynamic_point_buffer.as_span();
214}
215
216int OBJLegacyCurve::num_control_points_u(int spline_index) const
217{
218 const Nurb *const nurb = get_spline(spline_index);
219
221 nurb->pntsu, get_nurbs_degree_u(spline_index) + 1, get_cyclic_u(spline_index));
222}
223
224int OBJLegacyCurve::num_control_points_v(int spline_index) const
225{
226 const Nurb *const nurb = get_spline(spline_index);
227 return nurb->pntsv;
228}
229
230int OBJLegacyCurve::get_nurbs_degree_u(const int spline_index) const
231{
232 const Nurb *const nurb = get_spline(spline_index);
233 return nurb->type == CU_POLY ? 1 : nurb->orderu - 1;
234}
235
236int OBJLegacyCurve::get_nurbs_degree_v(const int spline_index) const
237{
238 const Nurb *const nurb = get_spline(spline_index);
239 return nurb->type == CU_POLY ? 1 : nurb->orderv - 1;
240}
241
242bool OBJLegacyCurve::get_cyclic_u(int spline_index) const
243{
244 const Nurb *const nurb = get_spline(spline_index);
245 return bool(nurb->flagu & CU_NURB_CYCLIC);
246}
247
248Span<float> OBJLegacyCurve::get_knots_u(int spline_index, Vector<float> &knot_buffer) const
249{
250 const Nurb *const nurb = get_spline(spline_index);
251 const short flag = nurb->flagu;
252 const int8_t order = get_nurbs_degree_u(spline_index) + 1; /* Use utility in case of POLY */
253 const bool cyclic = flag & CU_NURB_CYCLIC;
254
255 const int knot_count = bke::curves::nurbs::knots_num(nurb->pntsu, order, cyclic);
256
257 if (flag & CU_NURB_CUSTOM) {
258 return Span<float>(nurb->knotsu, knot_count);
259 }
260
261 knot_buffer.resize(knot_count);
263 nurb->pntsu, bke::knots_mode_from_legacy(flag), order, cyclic, knot_buffer);
264 return knot_buffer;
265}
266
268
269} // namespace blender::io::obj
Low-level operations for curves.
#define BLI_assert(a)
Definition BLI_assert.h:46
void * BLI_findlink(const ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:534
int BLI_listbase_count(const ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:524
MINLINE void copy_v3_v3(float r[3], const float a[3])
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
@ CU_NURB_CYCLIC
@ CU_NURB_CUSTOM
@ CU_POLY
KnotsMode
BPy_StructRNA * depsgraph
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
long long int int64_t
constexpr int64_t size() const
Definition BLI_span.hh:252
constexpr IndexRange drop_back(int64_t n) const
constexpr int64_t size() const
constexpr IndexRange slice(int64_t start, int64_t size) const
constexpr IndexRange drop_front(int64_t n) const
constexpr Span drop_front(int64_t n) const
Definition BLI_span.hh:171
constexpr Span slice(int64_t start, int64_t size) const
Definition BLI_span.hh:137
constexpr Span drop_back(int64_t n) const
Definition BLI_span.hh:182
constexpr int64_t size() const
Definition BLI_span.hh:252
void resize(const int64_t new_size)
Span< T > as_span() const
int num_control_points_v(int spline_index) const override
const char * get_curve_name() const override
int get_nurbs_degree_u(int spline_index) const override
int total_splines() const override
bool get_cyclic_u(int spline_index) const override
Span< float3 > vertex_coordinates(int spline_index, Vector< float3 > &dynamic_point_buffer) const override
OBJCurves(const bke::CurvesGeometry &curve, const float4x4 &transform, const std::string &name)
const float4x4 & object_transform() const override
int total_spline_vertices(int spline_index) const override
Span< float > get_knots_u(int spline_index, Vector< float > &buffer) const override
int num_control_points_u(int spline_index) const override
int get_nurbs_degree_v(int spline_index) const override
bool get_cyclic_u(int spline_index) const override
const float4x4 & object_transform() const override
int get_nurbs_degree_u(int spline_index) const override
int get_nurbs_degree_v(int spline_index) const override
int num_control_points_u(int spline_index) const override
OBJLegacyCurve(const Depsgraph *depsgraph, Object *curve_object)
const char * get_curve_name() const override
Span< float > get_knots_u(int spline_index, Vector< float > &buffer) const override
int total_spline_vertices(int spline_index) const override
int num_control_points_v(int spline_index) const override
Span< float3 > vertex_coordinates(int spline_index, Vector< float3 > &dynamic_point_buffer) const override
Vector< int > calculate_multiplicity_sequence(Span< float > knots)
void calculate_knots(int points_num, KnotsMode mode, int8_t order, bool cyclic, MutableSpan< float > knots)
int control_points_num(int num_control_points, int8_t order, bool cyclic)
int knots_num(int points_num, int8_t order, bool cyclic)
KnotsMode knots_mode_from_legacy(short flag)
static int find_rightmost_span(const int8_t order, const Span< int > multiplicity)
Span< float > valid_nurb_control_point_range(const int8_t order, const Span< float > knots, IndexRange &point_range)
static int find_leftmost_span(const int8_t order, const Span< int > multiplicity)
MatBase< float, 4, 4 > float4x4
const char * name
float vec[4]
ListBase nurb
short flagu
short orderu
short orderv
float * knotsu
short type
BPoint * bp
i
Definition text_draw.cc:230
uint8_t flag
Definition wm_window.cc:145