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
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.