Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/egg/eggTexture.cxx

Go to the documentation of this file.
00001 // Filename: eggTexture.cxx
00002 // Created by:  drose (18Jan99)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "eggTexture.h"
00020 #include "eggMiscFuncs.h"
00021 #include "lexerDefs.h"
00022 
00023 #include <indent.h>
00024 #include <string_utils.h>
00025 
00026 TypeHandle EggTexture::_type_handle;
00027 
00028 
00029 ////////////////////////////////////////////////////////////////////
00030 //     Function: EggTexture::Constructor
00031 //       Access: Public
00032 //  Description:
00033 ////////////////////////////////////////////////////////////////////
00034 EggTexture::
00035 EggTexture(const string &tref_name, const string &filename)
00036   : EggFilenameNode(tref_name, filename)
00037 {
00038   _format = F_unspecified;
00039   _wrap_mode = WM_unspecified;
00040   _wrap_u = WM_unspecified;
00041   _wrap_v = WM_unspecified;
00042   _minfilter = FT_unspecified;
00043   _magfilter = FT_unspecified;
00044   _anisotropic_degree = 0;
00045   _env_type = ET_unspecified;
00046   _flags = 0;
00047   _transform = LMatrix3d::ident_mat();
00048   _alpha_file_channel = 0;
00049 }
00050 
00051 ////////////////////////////////////////////////////////////////////
00052 //     Function: EggTexture::Copy constructor
00053 //       Access: Public
00054 //  Description:
00055 ////////////////////////////////////////////////////////////////////
00056 EggTexture::
00057 EggTexture(const EggTexture &copy) {
00058   (*this) = copy;
00059 }
00060 
00061 ////////////////////////////////////////////////////////////////////
00062 //     Function: EggTexture::Copy assignment operator
00063 //       Access: Public
00064 //  Description:
00065 ////////////////////////////////////////////////////////////////////
00066 EggTexture &EggTexture::
00067 operator = (const EggTexture &copy) {
00068   EggFilenameNode::operator = (copy);
00069   EggRenderMode::operator = (copy);
00070 
00071   _format = copy._format;
00072   _wrap_mode = copy._wrap_mode;
00073   _wrap_u = copy._wrap_u;
00074   _wrap_v = copy._wrap_v;
00075   _minfilter = copy._minfilter;
00076   _magfilter = copy._magfilter;
00077   _anisotropic_degree = copy._anisotropic_degree;
00078   _env_type = copy._env_type;
00079   _flags = copy._flags;
00080   _transform = copy._transform;
00081   _alpha_filename = copy._alpha_filename;
00082   _alpha_fullpath = copy._alpha_fullpath;
00083   _alpha_file_channel = copy._alpha_file_channel;
00084 
00085   return *this;
00086 }
00087 
00088 ////////////////////////////////////////////////////////////////////
00089 //     Function: EggTexture::write
00090 //       Access: Public, Virtual
00091 //  Description: Writes the texture definition to the indicated output
00092 //               stream in Egg format.
00093 ////////////////////////////////////////////////////////////////////
00094 void EggTexture::
00095 write(ostream &out, int indent_level) const {
00096   write_header(out, indent_level, "<Texture>");
00097   enquote_string(out, get_filename(), indent_level + 2) << "\n";
00098 
00099   if (has_alpha_filename()) {
00100     indent(out, indent_level + 2)
00101       << "<Scalar> alpha-file { ";
00102     enquote_string(out, get_alpha_filename());
00103     out << " }\n";
00104   }
00105 
00106   if (has_alpha_file_channel()) {
00107     indent(out, indent_level + 2)
00108       << "<Scalar> alpha-file-channel { " 
00109       << get_alpha_file_channel() << " }\n";
00110   }
00111 
00112   if (get_format() != F_unspecified) {
00113     indent(out, indent_level + 2)
00114       << "<Scalar> format { " << get_format() << " }\n";
00115   }
00116 
00117   if (get_wrap_mode() != WM_unspecified) {
00118     indent(out, indent_level + 2)
00119       << "<Scalar> wrap { " << get_wrap_mode() << " }\n";
00120   }
00121 
00122   if (get_wrap_u() != WM_unspecified) {
00123     indent(out, indent_level + 2)
00124       << "<Scalar> wrapu { " << get_wrap_u() << " }\n";
00125   }
00126 
00127   if (get_wrap_v() != WM_unspecified) {
00128     indent(out, indent_level + 2)
00129       << "<Scalar> wrapv { " << get_wrap_v() << " }\n";
00130   }
00131 
00132   if (get_minfilter() != FT_unspecified) {
00133     indent(out, indent_level + 2)
00134       << "<Scalar> minfilter { " << get_minfilter() << " }\n";
00135   }
00136 
00137   if (get_magfilter() != FT_unspecified) {
00138     indent(out, indent_level + 2)
00139       << "<Scalar> magfilter { " << get_magfilter() << " }\n";
00140   }
00141 
00142   if (has_anisotropic_degree()) {
00143     indent(out, indent_level + 2)
00144       << "<Scalar> anisotropic-degree { " << get_anisotropic_degree() << " }\n";
00145   }
00146 
00147   if (get_env_type() != ET_unspecified) {
00148     indent(out, indent_level + 2)
00149       << "<Scalar> envtype { " << get_env_type() << " }\n";
00150   }
00151 
00152   EggRenderMode::write(out, indent_level + 2);
00153 
00154   if (has_transform()) {
00155     write_transform(out, _transform, indent_level + 2);
00156   }
00157 
00158   indent(out, indent_level) << "}\n";
00159 }
00160 
00161 ////////////////////////////////////////////////////////////////////
00162 //     Function: EggTexture::is_equivalent_to
00163 //       Access: Public
00164 //  Description: Returns true if the two textures are equivalent in
00165 //               all relevant properties (according to eq), false
00166 //               otherwise.
00167 //
00168 //               The Equivalence parameter, eq, should be set to the
00169 //               bitwise OR of the following properties, according to
00170 //               what you consider relevant:
00171 //
00172 //               EggTexture::E_basename:
00173 //                 The basename part of the texture filename, without
00174 //                 the directory prefix *or* the filename extension.
00175 //
00176 //               EggTexture::E_extension:
00177 //                 The extension part of the texture filename.
00178 //
00179 //               EggTexture::E_dirname:
00180 //                 The directory prefix of the texture filename.
00181 //
00182 //               EggTexture::E_complete_filename:
00183 //                 The union of the above three; that is, the complete
00184 //                 filename, with directory, basename, and extension.
00185 //
00186 //               EggTexture::E_transform:
00187 //                 The texture matrix.
00188 //
00189 //               EggTexture::E_attributes:
00190 //                 All remaining texture attributes (mode, mipmap,
00191 //                 etc.) except TRef name.
00192 //
00193 //               EggTexture::E_tref_name:
00194 //                 The TRef name.
00195 ////////////////////////////////////////////////////////////////////
00196 bool EggTexture::
00197 is_equivalent_to(const EggTexture &other, int eq) const {
00198   if ((eq & E_complete_filename) == E_complete_filename) {
00199     if (get_filename() != other.get_filename()) {
00200       return false;
00201     }
00202   } else {
00203     const Filename &a = get_filename();
00204     const Filename &b = other.get_filename();
00205 
00206     if (eq & E_basename) {
00207       if (a.get_basename_wo_extension() != b.get_basename_wo_extension()) {
00208         return false;
00209       }
00210     }
00211     if (eq & E_extension) {
00212       if (a.get_extension() != b.get_extension()) {
00213         return false;
00214       }
00215     }
00216     if (eq & E_dirname) {
00217       if (a.get_dirname() != b.get_dirname()) {
00218         return false;
00219       }
00220     }
00221   }
00222 
00223   if (eq & E_transform) {
00224     if (transform_is_identity() != other.transform_is_identity()) {
00225       return false;
00226     }
00227 
00228     if (has_transform() && other.has_transform()) {
00229       if (!_transform.almost_equal(other._transform, 0.0001)) {
00230         return false;
00231       }
00232     }
00233   }
00234 
00235   if (eq & E_attributes) {
00236     if (_format != other._format ||
00237         _wrap_mode != other._wrap_mode ||
00238         _wrap_u != other._wrap_u ||
00239         _wrap_v != other._wrap_v ||
00240         _minfilter != other._minfilter ||
00241         _magfilter != other._magfilter ||
00242         _env_type != other._env_type) {
00243       return false;
00244     }
00245     if (EggRenderMode::operator != (other)) {
00246       return false;
00247     }
00248   }
00249 
00250   if (eq & E_tref_name) {
00251     if (get_name() != other.get_name()) {
00252       return false;
00253     }
00254   }
00255 
00256   return true;
00257 }
00258 
00259 ////////////////////////////////////////////////////////////////////
00260 //     Function: EggTexture::sorts_less_than
00261 //       Access: Public
00262 //  Description: An ordering operator to compare two textures for
00263 //               sorting order.  This imposes an arbitrary ordering
00264 //               useful to identify unique textures, according to the
00265 //               indicated Equivalence factor.  See
00266 //               is_equivalent_to().
00267 ////////////////////////////////////////////////////////////////////
00268 bool EggTexture::
00269 sorts_less_than(const EggTexture &other, int eq) const {
00270   if ((eq & E_complete_filename) == E_complete_filename) {
00271     if (get_filename() != other.get_filename()) {
00272       return get_filename() < other.get_filename();
00273     }
00274   } else {
00275     const Filename &a = get_filename();
00276     const Filename &b = other.get_filename();
00277 
00278     if (eq & E_basename) {
00279       if (a.get_basename_wo_extension() != b.get_basename_wo_extension()) {
00280         return a.get_basename_wo_extension() < b.get_basename_wo_extension();
00281       }
00282     }
00283     if (eq & E_extension) {
00284       if (a.get_extension() != b.get_extension()) {
00285         return a.get_extension() < b.get_extension();
00286       }
00287     }
00288     if (eq & E_dirname) {
00289       if (a.get_dirname() != b.get_dirname()) {
00290         return a.get_dirname() < b.get_dirname();
00291       }
00292     }
00293   }
00294 
00295   if (eq & E_transform) {
00296     bool is_identity = transform_is_identity();
00297     bool other_is_identity = other.transform_is_identity();
00298     if (is_identity != other_is_identity) {
00299       return (int)is_identity < (int)other_is_identity;
00300     }
00301 
00302     if (has_transform() && other.has_transform()) {
00303       int compare = _transform.compare_to(other._transform);
00304       if (compare != 0) {
00305     return compare < 0;
00306       }
00307     }
00308   }
00309 
00310   if (eq & E_attributes) {
00311     if (_format != other._format) {
00312       return (int)_format < (int)other._format;
00313     }
00314     if (_wrap_mode != other._wrap_mode) {
00315       return (int)_wrap_mode < (int)other._wrap_mode;
00316     }
00317     if (_wrap_u != other._wrap_u) {
00318       return (int)_wrap_u < (int)other._wrap_u;
00319     }
00320     if (_wrap_v != other._wrap_v) {
00321       return (int)_wrap_v < (int)other._wrap_v;
00322     }
00323     if (_minfilter != other._minfilter) {
00324       return (int)_minfilter < (int)other._minfilter;
00325     }
00326     if (_magfilter != other._magfilter) {
00327       return (int)_magfilter < (int)other._magfilter;
00328     }
00329     if (_anisotropic_degree != other._anisotropic_degree) {
00330       return _anisotropic_degree < other._anisotropic_degree;
00331     }
00332     if (_env_type != other._env_type) {
00333       return (int)_env_type < (int)other._env_type;
00334     }
00335     if (EggRenderMode::operator != (other)) {
00336       return EggRenderMode::operator < (other);
00337     }
00338   }
00339 
00340   if (eq & E_tref_name) {
00341     if (get_name() != other.get_name()) {
00342       return get_name() < other.get_name();
00343     }
00344   }
00345 
00346   return false;
00347 }
00348 
00349 ////////////////////////////////////////////////////////////////////
00350 //     Function: EggTexture::has_alpha_channel
00351 //       Access: Public
00352 //  Description: Given the number of color components (channels) in
00353 //               the image file as actually read from the disk, return
00354 //               true if this texture seems to have an alpha channel
00355 //               or not.  This depends on the EggTexture's format as
00356 //               well as the number of channels.
00357 ////////////////////////////////////////////////////////////////////
00358 bool EggTexture::
00359 has_alpha_channel(int num_components) const {
00360   switch (_format) {
00361   case F_red:
00362   case F_green:
00363   case F_blue:
00364   case F_luminance:
00365   case F_rgb:
00366   case F_rgb12:
00367   case F_rgb8:
00368   case F_rgb5:
00369   case F_rgb332:
00370     // These formats never use alpha, regardless of the number of
00371     // components we have.
00372     return false;
00373 
00374   case F_alpha:
00375     // This format always uses alpha.
00376     return true;
00377 
00378   case F_luminance_alpha:
00379   case F_luminance_alphamask:
00380   case F_rgba:
00381   case F_rgbm:
00382   case F_rgba12:
00383   case F_rgba8:
00384   case F_rgba4:
00385   case F_rgba5:
00386   case F_unspecified:
00387     // These formats use alpha if the image had alpha.
00388     return (num_components == 2 || num_components == 4);
00389   }
00390 
00391   return false;
00392 }
00393 
00394 ////////////////////////////////////////////////////////////////////
00395 //     Function: EggTexture::string_format
00396 //       Access: Public
00397 //  Description: Returns the Format value associated with the given
00398 //               string representation, or F_unspecified if the string
00399 //               does not match any known Format value.
00400 ////////////////////////////////////////////////////////////////////
00401 EggTexture::Format EggTexture::
00402 string_format(const string &string) {
00403   if (cmp_nocase_uh(string, "rgba") == 0) {
00404     return F_rgba;
00405   } else if (cmp_nocase_uh(string, "rgbm") == 0) {
00406     return F_rgbm;
00407   } else if (cmp_nocase_uh(string, "rgba12") == 0) {
00408     return F_rgba12;
00409   } else if (cmp_nocase_uh(string, "rgba8") == 0) {
00410     return F_rgba8;
00411   } else if (cmp_nocase_uh(string, "rgba4") == 0) {
00412     return F_rgba4;
00413 
00414   } else if (cmp_nocase_uh(string, "rgb") == 0) {
00415     return F_rgb;
00416   } else if (cmp_nocase_uh(string, "rgb12") == 0) {
00417     return F_rgb12;
00418   } else if (cmp_nocase_uh(string, "rgb8") == 0) {
00419     return F_rgb8;
00420   } else if (cmp_nocase_uh(string, "rgb5") == 0) {
00421     return F_rgb5;
00422   } else if (cmp_nocase_uh(string, "rgba5") == 0) {
00423     return F_rgba5;
00424   } else if (cmp_nocase_uh(string, "rgb332") == 0) {
00425     return F_rgb332;
00426   } else if (cmp_nocase_uh(string, "red") == 0) {
00427     return F_red;
00428   } else if (cmp_nocase_uh(string, "green") == 0) {
00429     return F_green;
00430   } else if (cmp_nocase_uh(string, "blue") == 0) {
00431     return F_blue;
00432   } else if (cmp_nocase_uh(string, "alpha") == 0) {
00433     return F_alpha;
00434   } else if (cmp_nocase_uh(string, "luminance") == 0) {
00435     return F_luminance;
00436   } else if (cmp_nocase_uh(string, "luminance_alpha") == 0) {
00437     return F_luminance_alpha;
00438   } else if (cmp_nocase_uh(string, "luminance_alphamask") == 0) {
00439     return F_luminance_alphamask;
00440   } else {
00441     return F_unspecified;
00442   }
00443 }
00444 
00445 ////////////////////////////////////////////////////////////////////
00446 //     Function: EggTexture::string_wrap_mode
00447 //       Access: Public
00448 //  Description: Returns the WrapMode value associated with the given
00449 //               string representation, or WM_unspecified if the string
00450 //               does not match any known WrapMode value.
00451 ////////////////////////////////////////////////////////////////////
00452 EggTexture::WrapMode EggTexture::
00453 string_wrap_mode(const string &string) {
00454   if (cmp_nocase_uh(string, "repeat") == 0) {
00455     return WM_repeat;
00456   } else if (cmp_nocase_uh(string, "clamp") == 0) {
00457     return WM_clamp;
00458   } else {
00459     return WM_unspecified;
00460   }
00461 }
00462 
00463 ////////////////////////////////////////////////////////////////////
00464 //     Function: EggTexture::string_filter_type
00465 //       Access: Public
00466 //  Description: Returns the FilterType value associated with the given
00467 //               string representation, or FT_unspecified if the string
00468 //               does not match any known FilterType value.
00469 ////////////////////////////////////////////////////////////////////
00470 EggTexture::FilterType EggTexture::
00471 string_filter_type(const string &string) {
00472   // Old egg filter types.
00473   if (cmp_nocase_uh(string, "point") == 0) {
00474     return FT_nearest;
00475   } else if (cmp_nocase_uh(string, "linear") == 0) {
00476     return FT_linear;
00477   } else if (cmp_nocase_uh(string, "bilinear") == 0) {
00478     return FT_linear;
00479   } else if (cmp_nocase_uh(string, "trilinear") == 0) {
00480     return FT_linear;
00481   } else if (cmp_nocase_uh(string, "mipmap_point") == 0) {
00482     return FT_nearest_mipmap_nearest;
00483   } else if (cmp_nocase_uh(string, "mipmap_linear") == 0) {
00484     return FT_nearest_mipmap_linear;
00485   } else if (cmp_nocase_uh(string, "mipmap_bilinear") == 0) {
00486     return FT_linear_mipmap_nearest;
00487   } else if (cmp_nocase_uh(string, "mipmap_trilinear") == 0) {
00488     return FT_linear_mipmap_linear;
00489 
00490     // Current egg filter types, that match those in Texture.
00491   } else if (cmp_nocase_uh(string, "nearest") == 0) {
00492     return FT_nearest;
00493   } else if (cmp_nocase_uh(string, "linear") == 0) {
00494     return FT_linear;
00495   } else if (cmp_nocase_uh(string, "nearest_mipmap_nearest") == 0) {
00496     return FT_nearest_mipmap_nearest;
00497   } else if (cmp_nocase_uh(string, "linear_mipmap_nearest") == 0) {
00498     return FT_linear_mipmap_nearest;
00499   } else if (cmp_nocase_uh(string, "nearest_mipmap_linear") == 0) {
00500     return FT_nearest_mipmap_linear;
00501   } else if (cmp_nocase_uh(string, "linear_mipmap_linear") == 0) {
00502     return FT_linear_mipmap_linear;
00503 
00504   } else {
00505     return FT_unspecified;
00506   }
00507 }
00508 
00509 ////////////////////////////////////////////////////////////////////
00510 //     Function: EggTexture::string_env_type
00511 //       Access: Public
00512 //  Description: Returns the EnvType value associated with the given
00513 //               string representation, or ET_unspecified if the string
00514 //               does not match any known EnvType value.
00515 ////////////////////////////////////////////////////////////////////
00516 EggTexture::EnvType EggTexture::
00517 string_env_type(const string &string) {
00518   if (cmp_nocase_uh(string, "modulate") == 0) {
00519     return ET_modulate;
00520   } else if (cmp_nocase_uh(string, "decal") == 0) {
00521     return ET_decal;
00522   } else {
00523     return ET_unspecified;
00524   }
00525 }
00526 
00527 ////////////////////////////////////////////////////////////////////
00528 //     Function: EggTexture::egg_start_parse_body
00529 //       Access: Protected, Virtual
00530 //  Description: This function is called within parse_egg().  It
00531 //               should call the appropriate function on the lexer to
00532 //               initialize the parser into the state associated with
00533 //               this object.  If the object cannot be parsed into
00534 //               directly, it should return false.
00535 ////////////////////////////////////////////////////////////////////
00536 bool EggTexture::
00537 egg_start_parse_body() {
00538   egg_start_texture_body();
00539   return true;
00540 }
00541 
00542 ////////////////////////////////////////////////////////////////////
00543 //     Function: Format output operator
00544 //  Description:
00545 ////////////////////////////////////////////////////////////////////
00546 ostream &operator << (ostream &out, EggTexture::Format format) {
00547   switch (format) {
00548   case EggTexture::F_unspecified:
00549     return out << "unspecified";
00550 
00551   case EggTexture::F_rgba:
00552     return out << "rgba";
00553   case EggTexture::F_rgbm:
00554     return out << "rgbm";
00555   case EggTexture::F_rgba12:
00556     return out << "rgba12";
00557   case EggTexture::F_rgba8:
00558     return out << "rgba8";
00559   case EggTexture::F_rgba4:
00560     return out << "rgba4";
00561 
00562   case EggTexture::F_rgb:
00563     return out << "rgb";
00564   case EggTexture::F_rgb12:
00565     return out << "rgb12";
00566   case EggTexture::F_rgb8:
00567     return out << "rgb8";
00568   case EggTexture::F_rgb5:
00569     return out << "rgb5";
00570   case EggTexture::F_rgba5:
00571     return out << "rgba5";
00572   case EggTexture::F_rgb332:
00573     return out << "rgb332";
00574 
00575   case EggTexture::F_red:
00576     return out << "red";
00577   case EggTexture::F_green:
00578     return out << "green";
00579   case EggTexture::F_blue:
00580     return out << "blue";
00581   case EggTexture::F_alpha:
00582     return out << "alpha";
00583   case EggTexture::F_luminance:
00584     return out << "luminance";
00585   case EggTexture::F_luminance_alpha:
00586     return out << "luminance_alpha";
00587   case EggTexture::F_luminance_alphamask:
00588     return out << "luminance_alphamask";
00589   }
00590 
00591   nassertr(false, out);
00592   return out << "(**invalid**)";
00593 }
00594 
00595 ////////////////////////////////////////////////////////////////////
00596 //     Function: WrapMode output operator
00597 //  Description:
00598 ////////////////////////////////////////////////////////////////////
00599 ostream &operator << (ostream &out, EggTexture::WrapMode mode) {
00600   switch (mode) {
00601   case EggTexture::WM_unspecified:
00602     return out << "unspecified";
00603   case EggTexture::WM_repeat:
00604     return out << "repeat";
00605   case EggTexture::WM_clamp:
00606     return out << "clamp";
00607   }
00608 
00609   nassertr(false, out);
00610   return out << "(**invalid**)";
00611 }
00612 
00613 ////////////////////////////////////////////////////////////////////
00614 //     Function: FilterType output operator
00615 //  Description:
00616 ////////////////////////////////////////////////////////////////////
00617 ostream &operator << (ostream &out, EggTexture::FilterType type) {
00618   switch (type) {
00619   case EggTexture::FT_unspecified:
00620     return out << "unspecified";
00621 
00622   case EggTexture::FT_nearest:
00623     return out << "nearest";
00624   case EggTexture::FT_linear:
00625     return out << "linear";
00626 
00627   case EggTexture::FT_nearest_mipmap_nearest:
00628     return out << "nearest_mipmap_nearest";
00629   case EggTexture::FT_linear_mipmap_nearest:
00630     return out << "linear_mipmap_nearest";
00631   case EggTexture::FT_nearest_mipmap_linear:
00632     return out << "nearest_mipmap_linear";
00633   case EggTexture::FT_linear_mipmap_linear:
00634     return out << "linear_mipmap_linear";
00635   }
00636 
00637   nassertr(false, out);
00638   return out << "(**invalid**)";
00639 }
00640 
00641 ////////////////////////////////////////////////////////////////////
00642 //     Function: EnvType output operator
00643 //  Description:
00644 ////////////////////////////////////////////////////////////////////
00645 ostream &operator << (ostream &out, EggTexture::EnvType type) {
00646   switch (type) {
00647   case EggTexture::ET_unspecified:
00648     return out << "unspecified";
00649   case EggTexture::ET_modulate:
00650     return out << "modulate";
00651   case EggTexture::ET_decal:
00652     return out << "decal";
00653   }
00654 
00655   nassertr(false, out);
00656   return out << "(**invalid**)";
00657 }

Generated on Fri May 2 00:37:59 2003 for Panda by doxygen1.3