Panda3D
|
00001 // Filename: eggNurbsSurface.cxx 00002 // Created by: drose (15Feb00) 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 "eggNurbsSurface.h" 00016 00017 #include "indent.h" 00018 00019 TypeHandle EggNurbsSurface::_type_handle; 00020 00021 //////////////////////////////////////////////////////////////////// 00022 // Function: EggNurbsSurface::setup 00023 // Access: Public 00024 // Description: Prepares a new surface definition with the indicated 00025 // order and number of knots in each dimension. This 00026 // also implies a particular number of vertices in each 00027 // dimension as well (the number of knots minus the 00028 // order), but it is up to the user to add the correct 00029 // number of vertices to the surface by repeatedly 00030 // calling push_back(). 00031 //////////////////////////////////////////////////////////////////// 00032 void EggNurbsSurface:: 00033 setup(int u_order, int v_order, 00034 int num_u_knots, int num_v_knots) { 00035 _u_order = u_order; 00036 _v_order = v_order; 00037 _u_knots.clear(); 00038 _v_knots.clear(); 00039 00040 int i; 00041 _u_knots.reserve(num_u_knots); 00042 for (i = 0; i < num_u_knots; i++) { 00043 _u_knots.push_back((double)i); 00044 } 00045 _v_knots.reserve(num_v_knots); 00046 for (i = 0; i < num_v_knots; i++) { 00047 _v_knots.push_back((double)i); 00048 } 00049 } 00050 00051 //////////////////////////////////////////////////////////////////// 00052 // Function: EggNurbsSurface::set_num_u_knots 00053 // Access: Public 00054 // Description: Directly changes the number of knots in the U 00055 // direction. This will either add zero-valued knots 00056 // onto the end, or truncate knot values from the end, 00057 // depending on whether the list is being increased or 00058 // decreased. If possible, it is preferable to use the 00059 // setup() method instead of directly setting the number 00060 // of knots, as this may result in an invalid surface. 00061 //////////////////////////////////////////////////////////////////// 00062 void EggNurbsSurface:: 00063 set_num_u_knots(int num) { 00064 if ((int)_u_knots.size() >= num) { 00065 // Truncate knot values at the end. 00066 _u_knots.erase(_u_knots.begin() + num, _u_knots.end()); 00067 } else { 00068 // Append knot values to the end. 00069 _u_knots.reserve(num); 00070 for (int i = _u_knots.size(); i < num; i++) { 00071 _u_knots.push_back(0.0); 00072 } 00073 } 00074 } 00075 00076 //////////////////////////////////////////////////////////////////// 00077 // Function: EggNurbsSurface::set_num_v_knots 00078 // Access: Public 00079 // Description: Directly changes the number of knots in the V 00080 // direction. This will either add zero-valued knots 00081 // onto the end, or truncate knot values from the end, 00082 // depending on whether the list is being increased or 00083 // decreased. If possible, it is preferable to use the 00084 // setup() method instead of directly setting the number 00085 // of knots, as this may result in an invalid surface. 00086 //////////////////////////////////////////////////////////////////// 00087 void EggNurbsSurface:: 00088 set_num_v_knots(int num) { 00089 if ((int)_v_knots.size() >= num) { 00090 // Truncate knot values at the end. 00091 _v_knots.erase(_v_knots.begin() + num, _v_knots.end()); 00092 } else { 00093 // Append knot values to the end. 00094 _v_knots.reserve(num); 00095 for (int i = _v_knots.size(); i < num; i++) { 00096 _v_knots.push_back(0.0); 00097 } 00098 } 00099 } 00100 00101 //////////////////////////////////////////////////////////////////// 00102 // Function: EggNurbsSurface::is_valid 00103 // Access: Public 00104 // Description: Returns true if the NURBS parameters are all 00105 // internally consistent (e.g. it has the right number 00106 // of vertices to match its number of knots and order in 00107 // each dimension), or false otherwise. 00108 //////////////////////////////////////////////////////////////////// 00109 bool EggNurbsSurface:: 00110 is_valid() const { 00111 if (_u_order < 1 || _u_order > 4 || _v_order < 1 || _v_order > 4) { 00112 // Invalid order. 00113 return false; 00114 } 00115 00116 if (get_num_cvs() != (int)size()) { 00117 // Wrong number of CV's. 00118 return false; 00119 } 00120 00121 // Do all the knot values monotonically increase? 00122 int i; 00123 for (i = 1; i < get_num_u_knots(); i++) { 00124 if (get_u_knot(i) < get_u_knot(i - 1)) { 00125 return false; 00126 } 00127 } 00128 for (i = 1; i < get_num_v_knots(); i++) { 00129 if (get_v_knot(i) < get_v_knot(i - 1)) { 00130 return false; 00131 } 00132 } 00133 00134 // Everything's looking good! 00135 return true; 00136 } 00137 00138 //////////////////////////////////////////////////////////////////// 00139 // Function: EggNurbsSurface::is_closed_u 00140 // Access: Public 00141 // Description: Returns true if the surface appears to be closed in 00142 // the U direction. Since the Egg syntax does not 00143 // provide a means for explicit indication of closure, 00144 // this has to be guessed at by examining the surface 00145 // itself. 00146 //////////////////////////////////////////////////////////////////// 00147 bool EggNurbsSurface:: 00148 is_closed_u() const { 00149 // Technically, the surface is closed if the CV's at the end are 00150 // repeated from the beginning. We'll do a cheesy test for 00151 // expediency's sake: the surface is closed if the first n knots are 00152 // not repeated. I think this will catch all the normal surfaces 00153 // we're likely to see. 00154 00155 int i; 00156 for (i = 1; i < get_u_order(); i++) { 00157 if (get_u_knot(i) != get_u_knot(i-1)) { 00158 return true; 00159 } 00160 } 00161 return false; 00162 } 00163 00164 //////////////////////////////////////////////////////////////////// 00165 // Function: EggNurbsSurface::is_closed_v 00166 // Access: Public 00167 // Description: Returns true if the surface appears to be closed in 00168 // the V direction. Since the Egg syntax does not 00169 // provide a means for explicit indication of closure, 00170 // this has to be guessed at by examining the surface 00171 // itself. 00172 //////////////////////////////////////////////////////////////////// 00173 bool EggNurbsSurface:: 00174 is_closed_v() const { 00175 int i; 00176 for (i = 1; i < get_v_order(); i++) { 00177 if (get_v_knot(i) != get_v_knot(i-1)) { 00178 return true; 00179 } 00180 } 00181 return false; 00182 } 00183 00184 //////////////////////////////////////////////////////////////////// 00185 // Function: EggNurbsSurface::write 00186 // Access: Public, Virtual 00187 // Description: Writes the nurbsSurface to the indicated output stream in 00188 // Egg format. 00189 //////////////////////////////////////////////////////////////////// 00190 void EggNurbsSurface:: 00191 write(ostream &out, int indent_level) const { 00192 write_header(out, indent_level, "<NurbsSurface>"); 00193 00194 Trims::const_iterator ti; 00195 for (ti = _trims.begin(); ti != _trims.end(); ++ti) { 00196 indent(out, indent_level + 2) << "<Trim> {\n"; 00197 Loops::const_iterator li; 00198 for (li = (*ti).begin(); li != (*ti).end(); ++li) { 00199 indent(out, indent_level + 4) << "<Loop> {\n"; 00200 Curves::const_iterator ci; 00201 for (ci = (*li).begin(); ci != (*li).end(); ++ci) { 00202 (*ci)->write(out, indent_level + 6); 00203 } 00204 indent(out, indent_level + 4) << "}\n"; 00205 } 00206 indent(out, indent_level + 2) << "}\n"; 00207 } 00208 00209 if (get_u_subdiv() != 0) { 00210 indent(out, indent_level + 2) 00211 << "<Scalar> U-subdiv { " << get_u_subdiv() << " }\n"; 00212 } 00213 if (get_v_subdiv() != 0) { 00214 indent(out, indent_level + 2) 00215 << "<Scalar> V-subdiv { " << get_v_subdiv() << " }\n"; 00216 } 00217 indent(out, indent_level + 2) 00218 << "<Order> { " << get_u_order() << " " << get_v_order() << " }\n"; 00219 indent(out, indent_level + 2) 00220 << "<U-Knots> {\n"; 00221 write_long_list(out, indent_level+4, _u_knots.begin(), _u_knots.end(), 00222 "", "", 72); 00223 indent(out, indent_level + 2) 00224 << "}\n"; 00225 indent(out, indent_level + 2) 00226 << "<V-Knots> {\n"; 00227 write_long_list(out, indent_level+4, _v_knots.begin(), _v_knots.end(), 00228 "", "", 72); 00229 indent(out, indent_level + 2) 00230 << "}\n"; 00231 00232 write_body(out, indent_level+2); 00233 00234 Curves::const_iterator ci; 00235 for (ci = _curves_on_surface.begin(); ci != _curves_on_surface.end(); ++ci) { 00236 (*ci)->write(out, indent_level + 2); 00237 } 00238 00239 indent(out, indent_level) << "}\n"; 00240 } 00241 00242 //////////////////////////////////////////////////////////////////// 00243 // Function: EggNurbsSurface::r_apply_texmats 00244 // Access: Protected, Virtual 00245 // Description: The recursive implementation of apply_texmats(). 00246 //////////////////////////////////////////////////////////////////// 00247 void EggNurbsSurface:: 00248 r_apply_texmats(EggTextureCollection &textures) { 00249 // A NURBS cannot safely apply texture matrices, so we leave it 00250 // alone. 00251 }