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