Panda3D
Loading...
Searching...
No Matches
nurbsCurveEvaluator.cxx
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file nurbsCurveEvaluator.cxx
10 * @author drose
11 * @date 2002-12-03
12 */
13
14#include "nurbsCurveEvaluator.h"
15
16/**
17 *
18 */
19NurbsCurveEvaluator::
20NurbsCurveEvaluator() {
21 _order = 4;
22 _knots_dirty = true;
23 _basis_dirty = true;
24}
25
26/**
27 *
28 */
29NurbsCurveEvaluator::
30~NurbsCurveEvaluator() {
31}
32
33/**
34 * Resets all the vertices and knots to their default values, and sets the
35 * curve up with the indicated number of vertices. You must then call
36 * set_vertex() repeatedly to fill in all of the vertex values appropriately.
37 */
39reset(int num_vertices) {
40 _vertices.clear();
41 _vertices.reserve(num_vertices);
42
43 for (int i = 0; i < num_vertices; i++) {
44 _vertices.push_back(NurbsVertex());
45 }
46 _knots_dirty = true;
47 _basis_dirty = true;
48}
49
50/**
51 * Returns the coordinate space of the nth control vertex of the curve,
52 * expressed as a NodePath.
53 */
55get_vertex_space(int i, const NodePath &rel_to) const {
56#ifndef NDEBUG
57 static NodePath empty_node_path;
58 nassertr(i >= 0 && i < (int)_vertices.size(), empty_node_path);
59#endif
60 return _vertices[i].get_space(rel_to);
61}
62
63/**
64 * Simultaneously sets several extended values in the slots d through (d +
65 * num_values - 1) from the num_values elements of the indicated array. This
66 * is equivalent to calling set_extended_vertex() num_values times. See
67 * set_extended_vertex().
68 */
70set_extended_vertices(int i, int d, const PN_stdfloat values[], int num_values) {
71 nassertv(i >= 0 && i < (int)_vertices.size());
72
73 NurbsVertex &vertex = _vertices[i];
74 for (int n = 0; n < num_values; n++) {
75 vertex.set_extended_vertex(d + n, values[n]);
76 }
77}
78
79/**
80 * Sets the value of the nth knot. Each knot value should be greater than or
81 * equal to the preceding value. If no knot values are set, a default knot
82 * vector is supplied.
83 */
85set_knot(int i, PN_stdfloat knot) {
86 if (_knots_dirty) {
87 recompute_knots();
88 }
89 nassertv(i >= 0 && i < (int)_knots.size());
90 _knots[i] = knot;
91}
92
93/**
94 * Returns the value of the nth knot.
95 */
96PN_stdfloat NurbsCurveEvaluator::
97get_knot(int i) const {
98 if (_knots_dirty) {
99 ((NurbsCurveEvaluator *)this)->recompute_knots();
100 }
101 nassertr(i >= 0 && i < (int)_knots.size(), 0.0f);
102 return _knots[i];
103}
104
105/**
106 * Normalizes the knot sequence so that the parametric range of the curve is 0
107 * .. 1.
108 */
111 if (_knots_dirty) {
112 recompute_knots();
113 }
114
115 if (get_num_vertices() > _order - 1) {
116 double min_value = _knots[_order - 1];
117 double max_value = _knots[get_num_vertices()];
118 double range = (max_value - min_value);
119
120 for (Knots::iterator ki = _knots.begin(); ki != _knots.end(); ++ki) {
121 (*ki) = ((*ki) - min_value) / range;
122 }
123 _basis_dirty = true;
124 }
125}
126
127/**
128 * Returns a NurbsCurveResult object that represents the result of applying
129 * the knots to all of the current values of the vertices, transformed into
130 * the indicated coordinate space.
131 */
132PT(NurbsCurveResult) NurbsCurveEvaluator::
133evaluate(const NodePath &rel_to) const {
134 if (_basis_dirty) {
135 ((NurbsCurveEvaluator *)this)->recompute_basis();
136 }
137
138 // First, transform the vertices as appropriate.
139 Vert4Array vecs;
140 get_vertices(vecs, rel_to);
141
142 // And apply those transformed vertices to the basis matrices to derive the
143 // result.
144 return new NurbsCurveResult(_basis, &vecs[0], &_vertices[0],
145 (int)_vertices.size());
146}
147
148/**
149 * Returns a NurbsCurveResult object that represents the result of applying
150 * the knots to all of the current values of the vertices, transformed into
151 * the indicated coordinate space, and then further transformed by the
152 * indicated matrix.
153 */
154PT(NurbsCurveResult) NurbsCurveEvaluator::
155evaluate(const NodePath &rel_to, const LMatrix4 &mat) const {
156 if (_basis_dirty) {
157 ((NurbsCurveEvaluator *)this)->recompute_basis();
158 }
159
160 // First, transform the vertices as appropriate.
161 Vert4Array vecs;
162 get_vertices(vecs, rel_to);
163
164 // And then apply the indicated matrix.
165 Vert4Array::iterator vi;
166 for (vi = vecs.begin(); vi != vecs.end(); ++vi) {
167 (*vi) = (*vi) * mat;
168 }
169
170 // And apply those transformed vertices to the basis matrices to derive the
171 // result.
172 return new NurbsCurveResult(_basis, &vecs[0], &_vertices[0],
173 (int)_vertices.size());
174}
175
176/**
177 *
178 */
179void NurbsCurveEvaluator::
180output(std::ostream &out) const {
181 out << "NurbsCurve, " << get_num_knots() << " knots.";
182}
183
184
185/**
186 * Fills the indicated vector with the set of vertices in the curve,
187 * transformed to the given space. This flavor returns the vertices in
188 * 4-dimensional homogenous space.
189 */
190void NurbsCurveEvaluator::
191get_vertices(NurbsCurveEvaluator::Vert4Array &verts, const NodePath &rel_to) const {
192 int num_vertices = (int)_vertices.size();
193 verts.reserve(verts.size() + num_vertices);
194 int vi;
195 for (vi = 0; vi < num_vertices; vi++) {
196 verts.push_back(get_vertex(vi, rel_to));
197 }
198}
199
200/**
201 * Fills the indicated vector with the set of vertices in the curve,
202 * transformed to the given space. This flavor returns the vertices in
203 * 3-dimensional space.
204 */
205void NurbsCurveEvaluator::
206get_vertices(NurbsCurveEvaluator::Vert3Array &verts, const NodePath &rel_to) const {
207 int num_vertices = (int)_vertices.size();
208 verts.reserve(verts.size() + num_vertices);
209 int vi;
210 for (vi = 0; vi < num_vertices; vi++) {
211 LVecBase4 vertex = get_vertex(vi, rel_to);
212 // Avoid division by zero
213 if (vertex[3] == 0.0) {
214 verts.push_back(LPoint3(vertex[0], vertex[1], vertex[2]));
215 } else {
216 LPoint3 v3(vertex[0] / vertex[3], vertex[1] / vertex[3], vertex[2] / vertex[3]);
217 verts.push_back(v3);
218 }
219 }
220}
221
222/**
223 * Creates a default knot vector.
224 */
225void NurbsCurveEvaluator::
226recompute_knots() {
227 _knots.clear();
228 int num_knots = get_num_knots();
229 _knots.reserve(num_knots);
230
231 PN_stdfloat value = 0.0f;
232
233 int i = 0;
234 while (i < _order) {
235 _knots.push_back(value);
236 i++;
237 }
238 while (i < num_knots - _order) {
239 value += 1.0f;
240 _knots.push_back(value);
241 i++;
242 }
243 value += 1.0f;
244 while (i < num_knots) {
245 _knots.push_back(value);
246 i++;
247 }
248
249 _knots_dirty = false;
250}
251
252/**
253 * Recomputes the basis matrices according to the knot vector.
254 */
255void NurbsCurveEvaluator::
256recompute_basis() {
257 if (_knots_dirty) {
258 ((NurbsCurveEvaluator *)this)->recompute_knots();
259 }
260
261 _basis.clear(_order);
262 if ((int)_vertices.size() > _order - 1) {
263 int min_knot = _order;
264 int max_knot = (int)_vertices.size();
265
266 for (int i = min_knot; i <= max_knot; i++) {
267 nassertv(i - 1 >= 0 && i < (int)_knots.size());
268 if (_knots[i - 1] < _knots[i]) {
269 // Here's a non-empty segment.
270 _basis.append_segment(i - _order, &_knots[i - _order]);
271 }
272 }
273 }
274
275 _basis_dirty = false;
276}
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition nodePath.h:159
void append_segment(int vertex_index, const PN_stdfloat knots[])
Computes a NURBS basis for one segment of the curve and appends it to the set of basis matrices.
void clear(int order)
Removes all the segments from the curve.
This class is an abstraction for evaluating NURBS curves.
void reset(int num_vertices)
Resets all the vertices and knots to their default values, and sets the curve up with the indicated n...
get_num_vertices
Returns the number of control vertices in the curve.
void normalize_knots()
Normalizes the knot sequence so that the parametric range of the curve is 0
NodePath get_vertex_space(int i, const NodePath &rel_to) const
Returns the coordinate space of the nth control vertex of the curve, expressed as a NodePath.
get_vertex
Returns the nth control vertex of the curve, relative to its indicated coordinate space.
void set_extended_vertices(int i, int d, const PN_stdfloat values[], int num_values)
Simultaneously sets several extended values in the slots d through (d + num_values - 1) from the num_...
get_num_knots
Returns the number of knot values in the curve.
get_knot
Returns the value of the nth knot.
void set_knot(int i, PN_stdfloat knot)
Sets the value of the nth knot.
The result of a NurbsCurveEvaluator.
This represents a single control vertex in a NurbsEvaluator.
Definition nurbsVertex.h:32
void set_extended_vertex(int d, PN_stdfloat value)
Sets an n-dimensional vertex value.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.