31 int order = _basis.get_order();
32 int num_segments = _basis.get_num_segments();
34 _composed.reserve(num_segments);
35 for (
int i = 0; i < num_segments; i++) {
36 int vi = _basis.get_vertex_index(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)));
104 nassertr(segment >= 0 && segment < _basis.get_num_segments(), 0.0f);
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));
113 int order = _basis.get_order();
114 int vi = _basis.get_vertex_index(segment);
119 geom[ci] = _verts[vi + ci].get_extended_vertex(d);
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 {
146 nassertv(segment >= 0 && segment < _basis.get_num_segments());
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);
156 int order = _basis.get_order();
157 int vi = _basis.get_vertex_index(segment);
159 for (
int n = 0; n < num_values; n++) {
163 geom[ci] = _verts[vi + ci].get_extended_vertex(d + 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();
195 int num_segments = _basis.get_num_segments();
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);
215int NurbsCurveResult::
216find_segment(PN_stdfloat t) {
226 if (_last_segment != -1 && (t >= _last_from && t < _last_to)) {
227 return _last_segment;
231 int segment = r_find_segment(t, 0, _basis.get_num_segments() - 1);
233 _last_segment = segment;
234 _last_from = _basis.get_from(segment);
235 _last_to = _basis.get_to(segment);
245int NurbsCurveResult::
246r_find_segment(PN_stdfloat t,
int top,
int bot)
const {
251 int mid = (top + bot) / 2;
252 nassertr(mid >= 0 && mid < _basis.get_num_segments(), -1);
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);
275void NurbsCurveResult::
276r_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));
297PN_stdfloat NurbsCurveResult::
298sqr_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;
This encapsulates a series of matrices that are used to represent the sequential segments of a NurbsC...
int get_num_segments() const
Returns the number of piecewise continuous segments in the curve.
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.
PN_stdfloat get_end_t() const
Returns the last legal value of t on the curve.
PN_stdfloat get_start_t() const
Returns the first 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,...
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...
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.
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...
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...
This represents a single control vertex in a NurbsEvaluator.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.