Panda3D
 All Classes Functions Variables Enumerations
eggNurbsSurface.cxx
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 }
 All Classes Functions Variables Enumerations