34 _composed.reserve(num_segments);
35 for (
int i = 0; i < num_segments; i++) {
37 nassertv(vi >= 0 && vi + order - 1 < num_vertices);
43 geom.set_row(ci, vecs[vi + ci]);
47 geom.set_row(ci, LVecBase4::zero());
54 result.multiply(_basis.
get_basis(i), geom);
55 _composed.push_back(result);
74 LVecBase4 tvec(t*t2, t2, t, 1.0f);
76 PN_stdfloat weight = tvec.dot(_composed[segment].get_col(3));
78 point.set(tvec.dot(_composed[segment].get_col(0)) / weight,
79 tvec.dot(_composed[segment].get_col(1)) / weight,
80 tvec.dot(_composed[segment].get_col(2)) / weight);
91 LVecBase4 tvec(3.0 * t2, 2.0 * t, 1.0f, 0.0f);
93 tangent.set(tvec.dot(_composed[segment].get_col(0)),
94 tvec.dot(_composed[segment].get_col(1)),
95 tvec.dot(_composed[segment].get_col(2)));
106 PN_stdfloat t2 = t*t;
107 LVecBase4 tvec(t*t2, t2, t, 1.0f);
109 PN_stdfloat weight = tvec.dot(_composed[segment].get_col(3));
127 const LMatrix4 &basis = _basis.
get_basis(segment);
130 LVecBase4 composed_geom(basis.get_row(0).dot(geom),
131 basis.get_row(1).dot(geom),
132 basis.get_row(2).dot(geom),
133 basis.get_row(3).dot(geom));
134 return tvec.dot(composed_geom) / weight;
145 PN_stdfloat result[],
int num_values)
const {
148 PN_stdfloat t2 = t*t;
149 LVecBase4 tvec(t*t2, t2, t, 1.0f);
151 PN_stdfloat weight = tvec.dot(_composed[segment].get_col(3));
155 const LMatrix4 &basis = _basis.
get_basis(segment);
159 for (
int n = 0; n < num_values; n++) {
172 LVecBase4 composed_geom(basis.get_row(0).dot(geom),
173 basis.get_row(1).dot(geom),
174 basis.get_row(2).dot(geom),
175 basis.get_row(3).dot(geom));
176 result[n] = tvec.dot(composed_geom) / weight;
190 PN_stdfloat tolerance_2 = tolerance * tolerance;
191 _adaptive_result.clear();
196 for (
int segment = 0; segment < num_segments; ++segment) {
198 if (segment == 0 || !p0.almost_equal(p1)) {
201 _adaptive_result.push_back(AdaptiveSample(_basis.
get_from(segment), p0));
207 r_adaptive_sample(segment, 0.0f, p0, 1.0f, p1, tolerance_2);
215 int NurbsCurveResult::
216 find_segment(PN_stdfloat t) {
226 if (_last_segment != -1 && (t >= _last_from && t < _last_to)) {
227 return _last_segment;
233 _last_segment = segment;
234 _last_from = _basis.
get_from(segment);
235 _last_to = _basis.
get_to(segment);
245 int NurbsCurveResult::
246 r_find_segment(PN_stdfloat t,
int top,
int bot)
const {
251 int mid = (top + bot) / 2;
254 PN_stdfloat from = _basis.
get_from(mid);
255 PN_stdfloat to = _basis.
get_to(mid);
258 return r_find_segment(t, top, mid - 1);
260 }
else if (to <= t) {
262 return r_find_segment(t, mid + 1, bot);
275 void NurbsCurveResult::
276 r_adaptive_sample(
int segment, PN_stdfloat t0,
const LPoint3 &p0,
277 PN_stdfloat t1,
const LPoint3 &p1, PN_stdfloat tolerance_2) {
278 PN_stdfloat tmid = (t0 + t1) * 0.5f;
282 if (sqr_dist_to_line(pmid, p0, p1 - p0) > tolerance_2) {
284 r_adaptive_sample(segment, t0, p0, tmid, pmid, tolerance_2);
285 r_adaptive_sample(segment, tmid, pmid, t1, p1, tolerance_2);
289 _adaptive_result.push_back(AdaptiveSample(_basis.
scale_t(segment, t1), p1));
297 PN_stdfloat NurbsCurveResult::
298 sqr_dist_to_line(
const LPoint3 &point,
const LPoint3 &origin,
299 const LVector3 &vec) {
302 LVector3 d = point - origin;
303 PN_stdfloat hyp_2 = d.length_squared();
304 PN_stdfloat leg = d.dot(norm);
305 return hyp_2 - leg * leg;
void eval_segment_extended_points(int segment, PN_stdfloat t, int d, PN_stdfloat result[], int num_values) const
Simultaneously performs eval_extended_point on a contiguous sequence of dimensions.
PN_stdfloat eval_segment_extended_point(int segment, PN_stdfloat t, int d) const
Evaluates the curve in n-dimensional space according to the extended vertices associated with the cur...
const LMatrix4 & get_basis(int segment) const
Returns the basis matrix associated with the nth segment.
int get_num_segments() const
Returns the number of piecewise continuous segments in the curve.
PN_stdfloat get_from(int segment) const
Returns the t value of the beginning of this segment.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_vertex_index(int segment) const
Returns the vertex index of the nth segment.
PN_stdfloat get_to(int segment) const
Returns the t value of the end of this segment.
void eval_segment_tangent(int segment, PN_stdfloat t, LVecBase3 &tangent) const
As eval_segment_point, but computes the tangent to the curve at the indicated point.
void eval_segment_point(int segment, PN_stdfloat t, LVecBase3 &point) const
Evaluates the point on the curve corresponding to the indicated value in parametric time within the i...
This represents a single control vertex in a NurbsEvaluator.
NurbsCurveResult(const NurbsBasisVector &basis, const LVecBase4 vecs[], const NurbsVertex *verts, int num_vertices)
The constructor automatically builds up the result as the product of the indicated set of basis matri...
int get_order() const
Returns the order of the segments in the curve.
This encapsulates a series of matrices that are used to represent the sequential segments of a NurbsC...
PN_stdfloat scale_t(int segment, PN_stdfloat t) const
Scales the value of t into the range [0, 1] corresponding to [from, to].
PN_stdfloat get_start_t() const
Returns the first legal value of t on the curve.
PN_stdfloat get_extended_vertex(int d) const
Returns an n-dimensional vertex value.
PN_stdfloat get_end_t() const
Returns the last legal value of t on the curve.
void adaptive_sample(PN_stdfloat tolerance)
Determines the set of subdivisions necessary to approximate the curve with a set of linear segments,...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.