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

pandatool/src/eggprogs/eggTextureCards.cxx

Go to the documentation of this file.
00001 // Filename: eggTextureCards.cxx
00002 // Created by:  drose (21Feb01)
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 "eggTextureCards.h"
00020 
00021 #include "eggGroup.h"
00022 #include "eggVertexPool.h"
00023 #include "eggVertex.h"
00024 #include "eggTexture.h"
00025 #include "eggPolygon.h"
00026 #include "pnmImageHeader.h"
00027 
00028 #include <algorithm>
00029 
00030 ////////////////////////////////////////////////////////////////////
00031 //     Function: EggTextureCards::Constructor
00032 //       Access: Public
00033 //  Description:
00034 ////////////////////////////////////////////////////////////////////
00035 EggTextureCards::
00036 EggTextureCards() : EggWriter(true, true) {
00037   set_program_description
00038     ("egg-texture-cards generates an egg file consisting of several "
00039      "square polygons, one for each texture name that appears on the "
00040      "command line.\n\n"
00041 
00042      "This is a handy thing to have for importing texture images through "
00043      "egg-palettize, even when those textures do not appear on any real "
00044      "geometry; it can also be used for creating a lot of simple polygons "
00045      "for rendering click buttons and similar interfaces.");
00046 
00047   clear_runlines();
00048   add_runline("[opts] texture [texture ...] output.egg");
00049   add_runline("[opts] -o output.egg texture [texture ...]");
00050   add_runline("[opts] texture [texture ...] >output.egg");
00051 
00052   add_option
00053     ("g", "left,right,bottom,top", 0,
00054      "Specifies the geometry of each polygon.  The default is a unit polygon "
00055      "centered on the origin: -0.5,0.5,-0.5,0.5.  Polygons are always created "
00056      "on the X-Y plane.  If -p is not also specified, all polygons will be "
00057      "the same size and shape.",
00058      &EggTextureCards::dispatch_double_quad, NULL, &_polygon_geometry[0]);
00059 
00060   add_option
00061     ("p", "xpixels,ypixels", 0,
00062      "Indicates that polygons should be sized in proportion to the pixel "
00063      "size of the texture image.  This will potentially create a "
00064      "different size and shape polygon for each texture.  The coordinate "
00065      "pair represents the image size in "
00066      "pixels that will exactly fill up the polygon described with -g (or the "
00067      "default polygon if -g is not specified); smaller images will be "
00068      "given proportionately smaller polygons, and larger images will be "
00069      "given proportionately larger polygons.",
00070      &EggTextureCards::dispatch_double_pair, &_got_pixel_scale, &_pixel_scale[0]);
00071 
00072   add_option
00073     ("c", "r,g,b[,a]", 0,
00074      "Specifies the color of each polygon.  The default is white: 1,1,1,1.",
00075      &EggTextureCards::dispatch_color, NULL, &_polygon_color[0]);
00076 
00077   add_option
00078     ("wm", "[repeat | clamp]", 0,
00079      "Indicates the wrap mode of the texture: either \"repeat\" or \"clamp\" "
00080      "(or \"r\" or \"c\").  The default is to leave this unspecified.",
00081      &EggTextureCards::dispatch_wrap_mode, NULL, &_wrap_mode);
00082 
00083   add_option
00084     ("f", "format", 0,
00085      "Indicates the format for all textures: typical choices are \"rgba12\" "
00086      "or \"rgb5\" or \"alpha\".  The default is to leave this unspecified.",
00087      &EggTextureCards::dispatch_format, NULL, &_format);
00088 
00089   add_option
00090     ("f1", "format", 0,
00091      "Indicates the format for one-channel textures only.  If specified, this "
00092      "overrides the format specified by -f.",
00093      &EggTextureCards::dispatch_format, NULL, &_format_1);
00094 
00095   add_option
00096     ("f2", "format", 0,
00097      "Indicates the format for two-channel textures only.  If specified, this "
00098      "overrides the format specified by -f.",
00099      &EggTextureCards::dispatch_format, NULL, &_format_2);
00100 
00101   add_option
00102     ("f3", "format", 0,
00103      "Indicates the format for three-channel textures only.  If specified, this "
00104      "overrides the format specified by -f.",
00105      &EggTextureCards::dispatch_format, NULL, &_format_3);
00106 
00107   add_option
00108     ("f4", "format", 0,
00109      "Indicates the format for four-channel textures only.  If specified, this "
00110      "overrides the format specified by -f.",
00111      &EggTextureCards::dispatch_format, NULL, &_format_4);
00112 
00113   add_option
00114     ("b", "", 0,
00115      "Make the textured polygons backfaced",
00116      &EggTextureCards::dispatch_none, &_apply_bface);
00117 
00118 
00119   _polygon_geometry.set(-0.5, 0.5, -0.5, 0.5);
00120   _polygon_color.set(1.0, 1.0, 1.0, 1.0);
00121   _wrap_mode = EggTexture::WM_unspecified;
00122   _format = EggTexture::F_unspecified;
00123   _format_1 = EggTexture::F_unspecified;
00124   _format_2 = EggTexture::F_unspecified;
00125   _format_3 = EggTexture::F_unspecified;
00126   _format_4 = EggTexture::F_unspecified;
00127 }
00128 
00129 ////////////////////////////////////////////////////////////////////
00130 //     Function: EggTextureCards::handle_args
00131 //       Access: Protected, Virtual
00132 //  Description: Does something with the additional arguments on the
00133 //               command line (after all the -options have been
00134 //               parsed).  Returns true if the arguments are good,
00135 //               false otherwise.
00136 ////////////////////////////////////////////////////////////////////
00137 bool EggTextureCards::
00138 handle_args(ProgramBase::Args &args) {
00139   if (!check_last_arg(args, 0)) {
00140     return false;
00141   }
00142 
00143   if (args.empty()) {
00144     nout << "No texture names specified on the command line.\n";
00145     return false;
00146   }
00147 
00148   copy(args.begin(), args.end(),
00149        back_inserter(_texture_names));
00150 
00151   return true;
00152 }
00153 
00154 ////////////////////////////////////////////////////////////////////
00155 //     Function: EggTextureCards::dispatch_wrap_mode
00156 //       Access: Protected, Static
00157 //  Description: Standard dispatch function for an option that takes
00158 //               one parameter, which is to be interpreted as a
00159 //               WrapMode string.  The data pointer is to a WrapMode
00160 //               enum variable.
00161 ////////////////////////////////////////////////////////////////////
00162 bool EggTextureCards::
00163 dispatch_wrap_mode(const string &opt, const string &arg, void *var) {
00164   EggTexture::WrapMode *wmp = (EggTexture::WrapMode *)var;
00165 
00166   *wmp = EggTexture::string_wrap_mode(arg);
00167   if (*wmp == EggTexture::WM_unspecified) {
00168     // An unknown string.  Let's check for our special cases.
00169     if (arg == "r") {
00170       *wmp = EggTexture::WM_repeat;
00171     } else if (arg == "c") {
00172       *wmp = EggTexture::WM_clamp;
00173     } else {
00174       nout << "Invalid wrap mode parameter for -" << opt << ": "
00175            << arg << "\n";
00176       return false;
00177     }
00178   }
00179 
00180   return true;
00181 }
00182 
00183 ////////////////////////////////////////////////////////////////////
00184 //     Function: EggTextureCards::dispatch_format
00185 //       Access: Protected, Static
00186 //  Description: Standard dispatch function for an option that takes
00187 //               one parameter, which is to be interpreted as a
00188 //               Format string.  The data pointer is to a Format
00189 //               enum variable.
00190 ////////////////////////////////////////////////////////////////////
00191 bool EggTextureCards::
00192 dispatch_format(const string &opt, const string &arg, void *var) {
00193   EggTexture::Format *fp = (EggTexture::Format *)var;
00194 
00195   *fp = EggTexture::string_format(arg);
00196   if (*fp == EggTexture::F_unspecified) {
00197     nout << "Invalid format parameter for -" << opt << ": "
00198          << arg << "\n";
00199     return false;
00200   }
00201 
00202   return true;
00203 }
00204 
00205 
00206 ////////////////////////////////////////////////////////////////////
00207 //     Function: EggTextureCards::scan_texture
00208 //       Access: Private
00209 //  Description: Reads the texture image header to determine its size,
00210 //               and based on this size, computes the appropriate
00211 //               left,right,bottom,top geometry of the card that
00212 //               correspond to this texture.
00213 //
00214 //               Returns true if successful, or false if the texture
00215 //               cannot be read.
00216 ////////////////////////////////////////////////////////////////////
00217 bool EggTextureCards::
00218 scan_texture(const Filename &filename, LVecBase4d &geometry,
00219              int &num_channels) {
00220   PNMImageHeader header;
00221   if (!header.read_header(filename)) {
00222     nout << "Unable to read image " << filename << "\n";
00223     return false;
00224   }
00225 
00226   num_channels = header.get_num_channels();
00227 
00228   double xscale = header.get_x_size() / _pixel_scale[0];
00229   double yscale = header.get_y_size() / _pixel_scale[1];
00230 
00231   geometry.set(_polygon_geometry[0] * xscale,
00232                _polygon_geometry[1] * xscale,
00233                _polygon_geometry[2] * yscale,
00234                _polygon_geometry[3] * yscale);
00235   return true;
00236 }
00237 
00238 ////////////////////////////////////////////////////////////////////
00239 //     Function: EggTextureCards::make_vertices
00240 //       Access: Private
00241 //  Description: Creates a set of four vertices for the polygon
00242 //               according to the left,right,bottom,top geometry.
00243 ////////////////////////////////////////////////////////////////////
00244 void EggTextureCards::
00245 make_vertices(const LPoint4d &geometry, EggVertexPool *vpool,
00246               EggVertex *&v1, EggVertex *&v2, EggVertex *&v3, EggVertex *&v4) {
00247   //
00248   //   1     4
00249   //
00250   //
00251   //   2     3
00252   //
00253 
00254   v1 = vpool->make_new_vertex
00255     (LPoint3d(geometry[0], geometry[3], 0.0));
00256   v2 = vpool->make_new_vertex
00257     (LPoint3d(geometry[0], geometry[2], 0.0));
00258   v3 = vpool->make_new_vertex
00259     (LPoint3d(geometry[1], geometry[2], 0.0));
00260   v4 = vpool->make_new_vertex
00261     (LPoint3d(geometry[1], geometry[3], 0.0));
00262 
00263   v1->set_uv(TexCoordd(0.0, 1.0));
00264   v2->set_uv(TexCoordd(0.0, 0.0));
00265   v3->set_uv(TexCoordd(1.0, 0.0));
00266   v4->set_uv(TexCoordd(1.0, 1.0));
00267 }
00268 
00269 ////////////////////////////////////////////////////////////////////
00270 //     Function: EggTextureCards::run
00271 //       Access: Public
00272 //  Description:
00273 ////////////////////////////////////////////////////////////////////
00274 void EggTextureCards::
00275 run() {
00276   // First, create an enclosing group and a vertex pool with four
00277   // vertices.  We can use the same four vertices on all polygons.
00278 
00279   EggGroup *group = new EggGroup();
00280   _data.add_child(group);
00281 
00282   // If we have more than one tile, make the group a sequence, as a
00283   // convenience.  If we view the egg file directly we can see all the
00284   // tiles one at a time.
00285   if (_texture_names.size() > 1) {
00286     group->set_switch_flag(true);
00287     group->set_switch_fps(2.0);
00288   }
00289 
00290   EggVertexPool *vpool = new EggVertexPool("vpool");
00291   group->add_child(vpool);
00292 
00293   EggVertex *v1, *v2, *v3, *v4;
00294 
00295   if (!_got_pixel_scale) {
00296     // If we don't have a per-texture pixel scale, all the polygons
00297     // will be the same size, and hence may all share the same four
00298     // vertices.
00299     make_vertices(_polygon_geometry, vpool, v1, v2, v3, v4);
00300   }
00301 
00302   // Now, create a texture reference and a polygon for each texture.
00303 
00304   vector_string::const_iterator ti;
00305   for (ti = _texture_names.begin(); ti != _texture_names.end(); ++ti) {
00306     Filename filename = (*ti);
00307     string name = filename.get_basename_wo_extension();
00308 
00309     // Read in the texture header and determine its size.
00310     LVecBase4d geometry;
00311     int num_channels;
00312     bool texture_ok = scan_texture(filename, geometry, num_channels);
00313 
00314     if (texture_ok) {
00315       if (_got_pixel_scale) {
00316         make_vertices(geometry, vpool, v1, v2, v3, v4);
00317       }
00318 
00319       EggTexture *tref = new EggTexture(name, filename);
00320       tref->set_wrap_mode(_wrap_mode);
00321 
00322       switch (num_channels) {
00323       case 1:
00324         tref->set_format(_format_1);
00325         break;
00326 
00327       case 2:
00328         tref->set_format(_format_2);
00329         break;
00330 
00331       case 3:
00332         tref->set_format(_format_3);
00333         break;
00334 
00335       case 4:
00336         tref->set_format(_format_4);
00337         break;
00338       }
00339 
00340       if (tref->get_format() == EggTexture::F_unspecified) {
00341         tref->set_format(_format);
00342       }
00343       group->add_child(tref);
00344 
00345       // Each polygon gets placed in its own sub-group.  This will make
00346       // pulling them out by name at runtime possible.
00347       EggGroup *sub_group = new EggGroup(name);
00348       group->add_child(sub_group);
00349       EggPolygon *poly = new EggPolygon();
00350       sub_group->add_child(poly);
00351       poly->set_texture(tref);
00352       poly->set_color(_polygon_color);
00353       if (_apply_bface){
00354         poly->set_bface_flag(1);
00355       }
00356 
00357       poly->add_vertex(v1);
00358       poly->add_vertex(v2);
00359       poly->add_vertex(v3);
00360       poly->add_vertex(v4);
00361     }
00362   }
00363 
00364   // Done!
00365   write_egg_file();
00366 }
00367 
00368 
00369 int main(int argc, char *argv[]) {
00370   EggTextureCards prog;
00371   prog.parse_command_line(argc, argv);
00372   prog.run();
00373   return 0;
00374 }

Generated on Fri May 2 03:18:52 2003 for Panda-Tool by doxygen1.3