Panda3D
|
00001 // Filename: nurbsSurfaceEvaluator.cxx 00002 // Created by: drose (10Oct03) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "nurbsSurfaceEvaluator.h" 00016 00017 //////////////////////////////////////////////////////////////////// 00018 // Function: NurbsSurfaceEvaluator::Constructor 00019 // Access: Published 00020 // Description: 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 // Function: NurbsSurfaceEvaluator::Destructor 00034 // Access: Published 00035 // Description: 00036 //////////////////////////////////////////////////////////////////// 00037 NurbsSurfaceEvaluator:: 00038 ~NurbsSurfaceEvaluator() { 00039 } 00040 00041 //////////////////////////////////////////////////////////////////// 00042 // Function: NurbsSurfaceEvaluator::reset 00043 // Access: Published 00044 // Description: Resets all the vertices and knots to their default 00045 // values, and sets the surface up with the indicated 00046 // number of vertices. You must then call set_vertex() 00047 // repeatedly to fill in all of the vertex values 00048 // appropriately. 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 // Function: NurbsSurfaceEvaluator::get_vertex_space 00069 // Access: Published 00070 // Description: Returns the coordinate space of the nth control 00071 // vertex of the surface, expressed as a NodePath. 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 // Function: NurbsSurfaceEvaluator::set_extended_vertices 00085 // Access: Public 00086 // Description: Simultaneously sets several extended values in the 00087 // slots d through (d + num_values - 1) from the 00088 // num_values elements of the indicated array. This is 00089 // equivalent to calling set_extended_vertex() 00090 // num_values times. See set_extended_vertex(). 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 // Function: NurbsSurfaceEvaluator::set_u_knot 00106 // Access: Published 00107 // Description: Sets the value of the nth knot. Each knot value 00108 // should be greater than or equal to the preceding 00109 // value. If no knot values are set, a default knot 00110 // vector is supplied. 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 // Function: NurbsSurfaceEvaluator::get_u_knot 00123 // Access: Published 00124 // Description: Returns the value of the nth knot. 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 // Function: NurbsSurfaceEvaluator::normalize_u_knots 00137 // Access: Published 00138 // Description: Normalizes the knot sequence so that the parametric 00139 // range of the surface in the U direction is 0 .. 1. 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 // Function: NurbsSurfaceEvaluator::set_v_knot 00161 // Access: Published 00162 // Description: Sets the value of the nth knot. Each knot value 00163 // should be greater than or equal to the preceding 00164 // value. If no knot values are set, a default knot 00165 // vector is supplied. 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 // Function: NurbsSurfaceEvaluator::get_v_knot 00178 // Access: Published 00179 // Description: Returns the value of the nth knot. 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 // Function: NurbsSurfaceEvaluator::normalize_v_knots 00192 // Access: Published 00193 // Description: Normalizes the knot sequence so that the parametric 00194 // range of the surface in the U direction is 0 .. 1. 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 // Function: NurbsSurfaceEvaluator::evaluate 00216 // Access: Published 00217 // Description: Returns a NurbsSurfaceResult object that represents the 00218 // result of applying the knots to all of the current 00219 // values of the vertices, transformed into the 00220 // indicated coordinate space. 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 // First, transform the vertices as appropriate. 00232 Vert4Array vecs; 00233 get_vertices(vecs, rel_to); 00234 00235 // And apply those transformed vertices to the basis matrices to 00236 // derive the result. 00237 return new NurbsSurfaceResult(_u_basis, _v_basis, 00238 &vecs[0], &_vertices[0], 00239 _num_u_vertices, _num_v_vertices); 00240 } 00241 00242 //////////////////////////////////////////////////////////////////// 00243 // Function: NurbsSurfaceEvaluator::output 00244 // Access: Published 00245 // Description: 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 // Function: NurbsSurfaceEvaluator::get_vertices 00255 // Access: Public 00256 // Description: Fills the indicated vector with the set of vertices 00257 // in the surface, transformed to the given space. This 00258 // flavor returns the vertices in 4-dimensional 00259 // homogenous space. 00260 // 00261 // Vertices are arranged in linear sequence, with the v 00262 // coordinate changing more rapidly. 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 // Function: NurbsSurfaceEvaluator::get_vertices 00284 // Access: Public 00285 // Description: Fills the indicated vector with the set of vertices 00286 // in the surface, transformed to the given space. This 00287 // flavor returns the vertices in 3-dimensional 00288 // space. 00289 // 00290 // Vertices are arranged in linear sequence, with the v 00291 // coordinate changing more rapidly. 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 // Function: NurbsSurfaceEvaluator::recompute_u_knots 00313 // Access: Private 00314 // Description: Creates a default knot vector. 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 // Function: NurbsSurfaceEvaluator::recompute_v_knots 00345 // Access: Private 00346 // Description: Creates a default knot vector. 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 // Function: NurbsSurfaceEvaluator::recompute_u_basis 00377 // Access: Private 00378 // Description: Recomputes the basis matrices according to the knot 00379 // vector. 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 // Here's a non-empty segment. 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 // Function: NurbsSurfaceEvaluator::recompute_v_basis 00406 // Access: Private 00407 // Description: Recomputes the basis matrices according to the knot 00408 // vector. 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 // Here's a non-empty segment. 00425 _v_basis.append_segment(i - _v_order, &_v_knots[i - _v_order]); 00426 } 00427 } 00428 } 00429 00430 _v_basis_dirty = false; 00431 }