00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "nurbsCurveEvaluator.h"
00016
00017
00018
00019
00020
00021
00022 NurbsCurveEvaluator::
00023 NurbsCurveEvaluator() {
00024 _order = 4;
00025 _knots_dirty = true;
00026 _basis_dirty = true;
00027 }
00028
00029
00030
00031
00032
00033
00034 NurbsCurveEvaluator::
00035 ~NurbsCurveEvaluator() {
00036 }
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 void NurbsCurveEvaluator::
00048 reset(int num_vertices) {
00049 _vertices.clear();
00050 _vertices.reserve(num_vertices);
00051
00052 for (int i = 0; i < num_vertices; i++) {
00053 _vertices.push_back(NurbsVertex());
00054 }
00055 _knots_dirty = true;
00056 _basis_dirty = true;
00057 }
00058
00059
00060
00061
00062
00063
00064
00065 NodePath NurbsCurveEvaluator::
00066 get_vertex_space(int i, const NodePath &rel_to) const {
00067 #ifndef NDEBUG
00068 static NodePath empty_node_path;
00069 nassertr(i >= 0 && i < (int)_vertices.size(), empty_node_path);
00070 #endif
00071 return _vertices[i].get_space(rel_to);
00072 }
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 void NurbsCurveEvaluator::
00084 set_extended_vertices(int i, int d, const PN_stdfloat values[], int num_values) {
00085 nassertv(i >= 0 && i < (int)_vertices.size());
00086
00087 NurbsVertex &vertex = _vertices[i];
00088 for (int n = 0; n < num_values; n++) {
00089 vertex.set_extended_vertex(d + n, values[n]);
00090 }
00091 }
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 void NurbsCurveEvaluator::
00102 set_knot(int i, PN_stdfloat knot) {
00103 if (_knots_dirty) {
00104 recompute_knots();
00105 }
00106 nassertv(i >= 0 && i < (int)_knots.size());
00107 _knots[i] = knot;
00108 }
00109
00110
00111
00112
00113
00114
00115 PN_stdfloat NurbsCurveEvaluator::
00116 get_knot(int i) const {
00117 if (_knots_dirty) {
00118 ((NurbsCurveEvaluator *)this)->recompute_knots();
00119 }
00120 nassertr(i >= 0 && i < (int)_knots.size(), 0.0f);
00121 return _knots[i];
00122 }
00123
00124
00125
00126
00127
00128
00129
00130 void NurbsCurveEvaluator::
00131 normalize_knots() {
00132 if (_knots_dirty) {
00133 recompute_knots();
00134 }
00135
00136 if (get_num_vertices() > _order - 1) {
00137 double min_value = _knots[_order - 1];
00138 double max_value = _knots[get_num_vertices()];
00139 double range = (max_value - min_value);
00140
00141 for (Knots::iterator ki = _knots.begin(); ki != _knots.end(); ++ki) {
00142 (*ki) = ((*ki) - min_value) / range;
00143 }
00144 _basis_dirty = true;
00145 }
00146 }
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 PT(NurbsCurveResult) NurbsCurveEvaluator::
00157 evaluate(const NodePath &rel_to) const {
00158 if (_basis_dirty) {
00159 ((NurbsCurveEvaluator *)this)->recompute_basis();
00160 }
00161
00162
00163 Vert4Array vecs;
00164 get_vertices(vecs, rel_to);
00165
00166
00167
00168 return new NurbsCurveResult(_basis, &vecs[0], &_vertices[0],
00169 (int)_vertices.size());
00170 }
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181 PT(NurbsCurveResult) NurbsCurveEvaluator::
00182 evaluate(const NodePath &rel_to, const LMatrix4 &mat) const {
00183 if (_basis_dirty) {
00184 ((NurbsCurveEvaluator *)this)->recompute_basis();
00185 }
00186
00187
00188 Vert4Array vecs;
00189 get_vertices(vecs, rel_to);
00190
00191
00192 Vert4Array::iterator vi;
00193 for (vi = vecs.begin(); vi != vecs.end(); ++vi) {
00194 (*vi) = (*vi) * mat;
00195 }
00196
00197
00198
00199 return new NurbsCurveResult(_basis, &vecs[0], &_vertices[0],
00200 (int)_vertices.size());
00201 }
00202
00203
00204
00205
00206
00207
00208 void NurbsCurveEvaluator::
00209 output(ostream &out) const {
00210 out << "NurbsCurve, " << get_num_knots() << " knots.";
00211 }
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 void NurbsCurveEvaluator::
00223 get_vertices(NurbsCurveEvaluator::Vert4Array &verts, const NodePath &rel_to) const {
00224 int num_vertices = (int)_vertices.size();
00225 verts.reserve(verts.size() + num_vertices);
00226 int vi;
00227 for (vi = 0; vi < num_vertices; vi++) {
00228 verts.push_back(get_vertex(vi, rel_to));
00229 }
00230 }
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 void NurbsCurveEvaluator::
00241 get_vertices(NurbsCurveEvaluator::Vert3Array &verts, const NodePath &rel_to) const {
00242 int num_vertices = (int)_vertices.size();
00243 verts.reserve(verts.size() + num_vertices);
00244 int vi;
00245 for (vi = 0; vi < num_vertices; vi++) {
00246 LVecBase4 vertex = get_vertex(vi, rel_to);
00247 LPoint3 v3(vertex[0] / vertex[3], vertex[1] / vertex[3], vertex[2] / vertex[3]);
00248 verts.push_back(v3);
00249 }
00250 }
00251
00252
00253
00254
00255
00256
00257 void NurbsCurveEvaluator::
00258 recompute_knots() {
00259 _knots.clear();
00260 int num_knots = get_num_knots();
00261 _knots.reserve(num_knots);
00262
00263 PN_stdfloat value = 0.0f;
00264
00265 int i = 0;
00266 while (i < _order) {
00267 _knots.push_back(value);
00268 i++;
00269 }
00270 while (i < num_knots - _order) {
00271 value += 1.0f;
00272 _knots.push_back(value);
00273 i++;
00274 }
00275 value += 1.0f;
00276 while (i < num_knots) {
00277 _knots.push_back(value);
00278 i++;
00279 }
00280
00281 _knots_dirty = false;
00282 }
00283
00284
00285
00286
00287
00288
00289
00290 void NurbsCurveEvaluator::
00291 recompute_basis() {
00292 if (_knots_dirty) {
00293 ((NurbsCurveEvaluator *)this)->recompute_knots();
00294 }
00295
00296 _basis.clear(_order);
00297 if ((int)_vertices.size() > _order - 1) {
00298 int min_knot = _order;
00299 int max_knot = (int)_vertices.size();
00300
00301 for (int i = min_knot; i <= max_knot; i++) {
00302 nassertv(i - 1 >= 0 && i < (int)_knots.size());
00303 if (_knots[i - 1] < _knots[i]) {
00304
00305 _basis.append_segment(i - _order, &_knots[i - _order]);
00306 }
00307 }
00308 }
00309
00310 _basis_dirty = false;
00311 }