00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
00032
00033
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
00131
00132
00133
00134
00135
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
00156
00157
00158
00159
00160
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
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
00185
00186
00187
00188
00189
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
00208
00209
00210
00211
00212
00213
00214
00215
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
00240
00241
00242
00243
00244 void EggTextureCards::
00245 make_vertices(const LPoint4d &geometry, EggVertexPool *vpool,
00246 EggVertex *&v1, EggVertex *&v2, EggVertex *&v3, EggVertex *&v4) {
00247
00248
00249
00250
00251
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
00271
00272
00273
00274 void EggTextureCards::
00275 run() {
00276
00277
00278
00279 EggGroup *group = new EggGroup();
00280 _data.add_child(group);
00281
00282
00283
00284
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
00297
00298
00299 make_vertices(_polygon_geometry, vpool, v1, v2, v3, v4);
00300 }
00301
00302
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
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
00346
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
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 }