00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "nurbsSurfaceEvaluator.h"
00016
00017
00018
00019
00020
00021
00022 NurbsSurfaceEvaluator::
00023 NurbsSurfaceEvaluator() {
00024 _u_order = 4;
00025 _v_order = 4;
00026 _u_knots_dirty = true;
00027 _v_knots_dirty = true;
00028 _u_basis_dirty = true;
00029 _v_basis_dirty = true;
00030 }
00031
00032
00033
00034
00035
00036
00037 NurbsSurfaceEvaluator::
00038 ~NurbsSurfaceEvaluator() {
00039 }
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 void NurbsSurfaceEvaluator::
00051 reset(int num_u_vertices, int num_v_vertices) {
00052 int num_vertices = num_u_vertices * num_v_vertices;
00053 _vertices.clear();
00054 _vertices.reserve(num_vertices);
00055 _num_u_vertices = num_u_vertices;
00056 _num_v_vertices = num_v_vertices;
00057
00058 for (int i = 0; i < num_vertices; i++) {
00059 _vertices.push_back(NurbsVertex());
00060 }
00061 _u_knots_dirty = true;
00062 _v_knots_dirty = true;
00063 _u_basis_dirty = true;
00064 _v_basis_dirty = true;
00065 }
00066
00067
00068
00069
00070
00071
00072
00073 NodePath NurbsSurfaceEvaluator::
00074 get_vertex_space(int ui, int vi, const NodePath &rel_to) const {
00075 #ifndef NDEBUG
00076 static NodePath empty_node_path;
00077 nassertr(ui >= 0 && ui < _num_u_vertices &&
00078 vi >= 0 && vi < _num_v_vertices, empty_node_path);
00079 #endif
00080 return vert(ui, vi).get_space(rel_to);
00081 }
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092 void NurbsSurfaceEvaluator::
00093 set_extended_vertices(int ui, int vi, int d,
00094 const PN_stdfloat values[], int num_values) {
00095 nassertv(ui >= 0 && ui < _num_u_vertices &&
00096 vi >= 0 && vi < _num_v_vertices);
00097
00098 NurbsVertex &vertex = vert(ui, vi);
00099 for (int n = 0; n < num_values; n++) {
00100 vertex.set_extended_vertex(d + n, values[n]);
00101 }
00102 }
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 void NurbsSurfaceEvaluator::
00113 set_u_knot(int i, PN_stdfloat knot) {
00114 if (_u_knots_dirty) {
00115 recompute_u_knots();
00116 }
00117 nassertv(i >= 0 && i < (int)_u_knots.size());
00118 _u_knots[i] = knot;
00119 }
00120
00121
00122
00123
00124
00125
00126 PN_stdfloat NurbsSurfaceEvaluator::
00127 get_u_knot(int i) const {
00128 if (_u_knots_dirty) {
00129 ((NurbsSurfaceEvaluator *)this)->recompute_u_knots();
00130 }
00131 nassertr(i >= 0 && i < (int)_u_knots.size(), 0.0f);
00132 return _u_knots[i];
00133 }
00134
00135
00136
00137
00138
00139
00140
00141 void NurbsSurfaceEvaluator::
00142 normalize_u_knots() {
00143 if (_u_knots_dirty) {
00144 recompute_u_knots();
00145 }
00146
00147 if (_num_u_vertices > _u_order - 1) {
00148 double min_value = _u_knots[_u_order - 1];
00149 double max_value = _u_knots[_num_u_vertices];
00150 double range = (max_value - min_value);
00151
00152 for (Knots::iterator ki = _u_knots.begin(); ki != _u_knots.end(); ++ki) {
00153 (*ki) = ((*ki) - min_value) / range;
00154 }
00155 _u_basis_dirty = true;
00156 }
00157 }
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167 void NurbsSurfaceEvaluator::
00168 set_v_knot(int i, PN_stdfloat knot) {
00169 if (_v_knots_dirty) {
00170 recompute_v_knots();
00171 }
00172 nassertv(i >= 0 && i < (int)_v_knots.size());
00173 _v_knots[i] = knot;
00174 }
00175
00176
00177
00178
00179
00180
00181 PN_stdfloat NurbsSurfaceEvaluator::
00182 get_v_knot(int i) const {
00183 if (_v_knots_dirty) {
00184 ((NurbsSurfaceEvaluator *)this)->recompute_v_knots();
00185 }
00186 nassertr(i >= 0 && i < (int)_v_knots.size(), 0.0f);
00187 return _v_knots[i];
00188 }
00189
00190
00191
00192
00193
00194
00195
00196 void NurbsSurfaceEvaluator::
00197 normalize_v_knots() {
00198 if (_v_knots_dirty) {
00199 recompute_v_knots();
00200 }
00201
00202 if (_num_v_vertices > _v_order - 1) {
00203 double min_value = _v_knots[_v_order - 1];
00204 double max_value = _v_knots[_num_v_vertices];
00205 double range = (max_value - min_value);
00206
00207 for (Knots::iterator ki = _v_knots.begin(); ki != _v_knots.end(); ++ki) {
00208 (*ki) = ((*ki) - min_value) / range;
00209 }
00210 _v_basis_dirty = true;
00211 }
00212 }
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 PT(NurbsSurfaceResult) NurbsSurfaceEvaluator::
00223 evaluate(const NodePath &rel_to) const {
00224 if (_u_basis_dirty) {
00225 ((NurbsSurfaceEvaluator *)this)->recompute_u_basis();
00226 }
00227 if (_v_basis_dirty) {
00228 ((NurbsSurfaceEvaluator *)this)->recompute_v_basis();
00229 }
00230
00231
00232 Vert4Array vecs;
00233 get_vertices(vecs, rel_to);
00234
00235
00236
00237 return new NurbsSurfaceResult(_u_basis, _v_basis,
00238 &vecs[0], &_vertices[0],
00239 _num_u_vertices, _num_v_vertices);
00240 }
00241
00242
00243
00244
00245
00246
00247 void NurbsSurfaceEvaluator::
00248 output(ostream &out) const {
00249 out << "NurbsSurface, (" << get_num_u_knots() << ", " << get_num_v_knots()
00250 << ") knots.";
00251 }
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264 void NurbsSurfaceEvaluator::
00265 get_vertices(NurbsSurfaceEvaluator::Vert4Array &verts, const NodePath &rel_to) const {
00266 int num_vertices = (int)_vertices.size();
00267 verts.reserve(verts.size() + num_vertices);
00268 int vi;
00269 for (vi = 0; vi < num_vertices; vi++) {
00270 NodePath space = _vertices[vi].get_space(rel_to);
00271 const LVecBase4 &vertex = _vertices[vi].get_vertex();
00272 if (space.is_empty()) {
00273 verts.push_back(vertex);
00274 } else {
00275 CPT(TransformState) transform = space.get_transform(rel_to);
00276 const LMatrix4 &mat = transform->get_mat();
00277 verts.push_back(vertex * mat);
00278 }
00279 }
00280 }
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 void NurbsSurfaceEvaluator::
00294 get_vertices(NurbsSurfaceEvaluator::Vert3Array &verts, const NodePath &rel_to) const {
00295 int num_vertices = (int)_vertices.size();
00296 verts.reserve(verts.size() + num_vertices);
00297 int vi;
00298 for (vi = 0; vi < num_vertices; vi++) {
00299 const NodePath &space = _vertices[vi].get_space(rel_to);
00300 LVecBase4 vertex = _vertices[vi].get_vertex();
00301 if (!space.is_empty()) {
00302 CPT(TransformState) transform = space.get_transform(rel_to);
00303 const LMatrix4 &mat = transform->get_mat();
00304 vertex = vertex * mat;
00305 }
00306 LPoint3 v3(vertex[0] / vertex[3], vertex[1] / vertex[3], vertex[2] / vertex[3]);
00307 verts.push_back(v3);
00308 }
00309 }
00310
00311
00312
00313
00314
00315
00316 void NurbsSurfaceEvaluator::
00317 recompute_u_knots() {
00318 _u_knots.clear();
00319 int num_knots = get_num_u_knots();
00320 _u_knots.reserve(num_knots);
00321
00322 PN_stdfloat value = 0.0f;
00323
00324 int i = 0;
00325 while (i < _u_order) {
00326 _u_knots.push_back(value);
00327 i++;
00328 }
00329 while (i < num_knots - _u_order) {
00330 value += 1.0f;
00331 _u_knots.push_back(value);
00332 i++;
00333 }
00334 value += 1.0f;
00335 while (i < num_knots) {
00336 _u_knots.push_back(value);
00337 i++;
00338 }
00339
00340 _u_knots_dirty = false;
00341 }
00342
00343
00344
00345
00346
00347
00348 void NurbsSurfaceEvaluator::
00349 recompute_v_knots() {
00350 _v_knots.clear();
00351 int num_knots = get_num_v_knots();
00352 _v_knots.reserve(num_knots);
00353
00354 PN_stdfloat value = 0.0f;
00355
00356 int i = 0;
00357 while (i < _v_order) {
00358 _v_knots.push_back(value);
00359 i++;
00360 }
00361 while (i < num_knots - _v_order) {
00362 value += 1.0f;
00363 _v_knots.push_back(value);
00364 i++;
00365 }
00366 value += 1.0f;
00367 while (i < num_knots) {
00368 _v_knots.push_back(value);
00369 i++;
00370 }
00371
00372 _v_knots_dirty = false;
00373 }
00374
00375
00376
00377
00378
00379
00380
00381 void NurbsSurfaceEvaluator::
00382 recompute_u_basis() {
00383 if (_u_knots_dirty) {
00384 ((NurbsSurfaceEvaluator *)this)->recompute_u_knots();
00385 }
00386
00387 _u_basis.clear(_u_order);
00388 if (_num_u_vertices > _u_order - 1) {
00389 int min_knot = _u_order;
00390 int max_knot = _num_u_vertices;
00391
00392 for (int i = min_knot; i <= max_knot; i++) {
00393 nassertv(i - 1 >= 0 && i < (int)_u_knots.size());
00394 if (_u_knots[i - 1] < _u_knots[i]) {
00395
00396 _u_basis.append_segment(i - _u_order, &_u_knots[i - _u_order]);
00397 }
00398 }
00399 }
00400
00401 _u_basis_dirty = false;
00402 }
00403
00404
00405
00406
00407
00408
00409
00410 void NurbsSurfaceEvaluator::
00411 recompute_v_basis() {
00412 if (_v_knots_dirty) {
00413 ((NurbsSurfaceEvaluator *)this)->recompute_v_knots();
00414 }
00415
00416 _v_basis.clear(_v_order);
00417 if (_num_v_vertices > _v_order - 1) {
00418 int min_knot = _v_order;
00419 int max_knot = _num_v_vertices;
00420
00421 for (int i = min_knot; i <= max_knot; i++) {
00422 nassertv(i - 1 >= 0 && i < (int)_v_knots.size());
00423 if (_v_knots[i - 1] < _v_knots[i]) {
00424
00425 _v_basis.append_segment(i - _v_order, &_v_knots[i - _v_order]);
00426 }
00427 }
00428 }
00429
00430 _v_basis_dirty = false;
00431 }