Panda3D
 All Classes Functions Variables Enumerations
pfmTrans.cxx
00001 // Filename: pfmTrans.cxx
00002 // Created by:  drose (23Dec10)
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 "pfmTrans.h"
00016 #include "config_pfm.h"
00017 #include "pfmFile.h"
00018 #include "pystub.h"
00019 #include "texture.h"
00020 #include "texturePool.h"
00021 #include "pointerTo.h"
00022 #include "string_utils.h"
00023 #include "pandaFileStream.h"
00024 
00025 ////////////////////////////////////////////////////////////////////
00026 //     Function: PfmTrans::Constructor
00027 //       Access: Public
00028 //  Description:
00029 ////////////////////////////////////////////////////////////////////
00030 PfmTrans::
00031 PfmTrans() {
00032   _got_transform = false;
00033   _transform = LMatrix4::ident_mat();
00034 
00035   add_transform_options();
00036 
00037   set_program_description
00038     ("pfm-trans reads an pfm file and transforms it, filters it, "
00039      "operates on it, writing the output to another pfm file.  A pfm "
00040      "file contains a 2-d table of floating-point values.");
00041 
00042   add_option
00043     ("r", "", 0,
00044      "Reverses the rows of the pfm data vertically.",
00045      &PfmTrans::dispatch_none, &_got_reverse);
00046 
00047   add_option
00048     ("z", "", 0,
00049      "Treats (0,0,0) in the pfm file as a special don't-touch value.",
00050      &PfmTrans::dispatch_none, &_got_zero_special);
00051 
00052   add_option
00053     ("resize", "width,height", 0,
00054      "Resamples the pfm file to scale it to the indicated grid size.  "
00055      "A simple box filter is applied during the scale.  Don't confuse this "
00056      "with -TS, which scales the individual point values, but doesn't "
00057      "change the number of points.",
00058      &PfmTrans::dispatch_int_pair, &_got_resize, &_resize);
00059 
00060   add_option
00061     ("o", "filename", 50,
00062      "Specify the filename to which the resulting pfm file will be written.  "
00063      "This is only valid when there is only one input pfm file on the command "
00064      "line.  If you want to process multiple files simultaneously, you must "
00065      "use -d.",
00066      &PfmTrans::dispatch_filename, &_got_output_filename, &_output_filename);
00067 
00068   add_option
00069     ("d", "dirname", 50,
00070      "Specify the name of the directory in which to write the processed pfm "
00071      "files.  If you are processing only one pfm file, this may be omitted "
00072      "in lieu of the -o option.",
00073      &PfmTrans::dispatch_filename, &_got_output_dirname, &_output_dirname);
00074 
00075   add_option
00076     ("vis", "filename.bam", 60,
00077      "Generates a bam file that represents a visualization of the pfm file "
00078      "as a 3-D geometric mesh.  If -vistex is specified, the mesh is "
00079      "textured.",
00080      &PfmTrans::dispatch_filename, &_got_vis_filename, &_vis_filename);
00081 
00082   add_option
00083     ("visinv", "", 60,
00084      "Inverts the visualization, generating a uniform 2-d mesh with the "
00085      "3-d depth values encoded in the texture coordinates.",
00086      &PfmTrans::dispatch_none, &_got_vis_inverse);
00087 
00088   add_option
00089     ("vis2d", "", 60,
00090      "Respect only the first two components of each depth value, ignoring z.",
00091      &PfmTrans::dispatch_none, &_got_vis_2d);
00092 
00093   add_option
00094     ("vistex", "texture.jpg", 60,
00095      "Specifies the name of the texture to apply to the visualization.",
00096      &PfmTrans::dispatch_filename, &_got_vistex_filename, &_vistex_filename);
00097 }
00098 
00099 
00100 ////////////////////////////////////////////////////////////////////
00101 //     Function: PfmTrans::run
00102 //       Access: Public
00103 //  Description:
00104 ////////////////////////////////////////////////////////////////////
00105 void PfmTrans::
00106 run() {
00107   if (_got_vis_filename) {
00108     _mesh_root = NodePath("mesh_root");
00109   }
00110 
00111   Filenames::const_iterator fi;
00112   for (fi = _input_filenames.begin(); fi != _input_filenames.end(); ++fi) {
00113     PfmFile file;
00114     if (!file.read(*fi)) {
00115       nout << "Cannot read " << *fi << "\n";
00116       exit(1);
00117     }
00118     if (!process_pfm(*fi, file)) {
00119       exit(1);
00120     }
00121   }
00122 
00123   if (_got_vis_filename) {
00124     _mesh_root.write_bam_file(_vis_filename);
00125   }
00126 }
00127 
00128 ////////////////////////////////////////////////////////////////////
00129 //     Function: PfmTrans::process_pfm
00130 //       Access: Public
00131 //  Description: Handles a single pfm file.
00132 ////////////////////////////////////////////////////////////////////
00133 bool PfmTrans::
00134 process_pfm(const Filename &input_filename, PfmFile &file) {
00135   file.set_zero_special(_got_zero_special);
00136   file.set_vis_inverse(_got_vis_inverse);
00137   file.set_vis_2d(_got_vis_2d);
00138 
00139   if (_got_resize) {
00140     file.resize(_resize[0], _resize[1]);
00141   }
00142 
00143   if (_got_reverse) {
00144     file.reverse_rows();
00145   }
00146 
00147   if (_got_transform) {
00148     file.xform(_transform);
00149   }
00150 
00151   if (_got_vis_filename) {
00152     NodePath mesh = file.generate_vis_mesh(PfmFile::MF_both);
00153     if (_got_vistex_filename) {
00154       PT(Texture) tex = TexturePool::load_texture(_vistex_filename);
00155       if (tex == NULL) {
00156         nout << "Couldn't find " << _vistex_filename << "\n";
00157       } else {
00158         mesh.set_texture(tex);
00159       }
00160       if (tex->has_alpha(tex->get_format())) {
00161         mesh.set_transparency(TransparencyAttrib::M_dual);
00162       }
00163     }
00164     mesh.set_name(input_filename.get_basename_wo_extension());
00165     mesh.reparent_to(_mesh_root);
00166   }
00167 
00168   Filename output_filename;
00169   if (_got_output_filename) {
00170     output_filename = _output_filename;
00171   } else if (_got_output_dirname) {
00172     output_filename = Filename(_output_dirname, input_filename.get_basename());
00173   }
00174 
00175   if (!output_filename.empty()) {
00176     return file.write(output_filename);
00177   }
00178 
00179   return true;
00180 }
00181 
00182 ////////////////////////////////////////////////////////////////////
00183 //     Function: PfmTrans::add_transform_options
00184 //       Access: Public
00185 //  Description: Adds -TS, -TT, etc. as valid options for this
00186 //               program.  If the user specifies one of the options on
00187 //               the command line, the data will be transformed when
00188 //               the egg file is written out.
00189 ////////////////////////////////////////////////////////////////////
00190 void PfmTrans::
00191 add_transform_options() {
00192   add_option
00193     ("TS", "sx[,sy,sz]", 49,
00194      "Scale the model uniformly by the given factor (if only one number "
00195      "is given) or in each axis by sx, sy, sz (if three numbers are given).",
00196      &PfmTrans::dispatch_scale, &_got_transform, &_transform);
00197 
00198   add_option
00199     ("TR", "x,y,z", 49,
00200      "Rotate the model x degrees about the x axis, then y degrees about the "
00201      "y axis, and then z degrees about the z axis.",
00202      &PfmTrans::dispatch_rotate_xyz, &_got_transform, &_transform);
00203 
00204   add_option
00205     ("TA", "angle,x,y,z", 49,
00206      "Rotate the model angle degrees counterclockwise about the given "
00207      "axis.",
00208      &PfmTrans::dispatch_rotate_axis, &_got_transform, &_transform);
00209 
00210   add_option
00211     ("TT", "x,y,z", 49,
00212      "Translate the model by the indicated amount.\n\n"
00213      "All transformation options (-TS, -TR, -TA, -TT) are cumulative and are "
00214      "applied in the order they are encountered on the command line.",
00215      &PfmTrans::dispatch_translate, &_got_transform, &_transform);
00216 }
00217 
00218 ////////////////////////////////////////////////////////////////////
00219 //     Function: PfmTrans::handle_args
00220 //       Access: Protected, Virtual
00221 //  Description: Does something with the additional arguments on the
00222 //               command line (after all the -options have been
00223 //               parsed).  Returns true if the arguments are good,
00224 //               false otherwise.
00225 ////////////////////////////////////////////////////////////////////
00226 bool PfmTrans::
00227 handle_args(ProgramBase::Args &args) {
00228   if (args.empty()) {
00229     nout << "You must specify the pfm file(s) to read on the command line.\n";
00230     return false;
00231   }
00232 
00233   if (_got_output_filename && args.size() == 1) {
00234     if (_got_output_dirname) {
00235       nout << "Cannot specify both -o and -d.\n";
00236       return false;
00237     }
00238     
00239   } else {
00240     if (_got_output_filename) {
00241       nout << "Cannot use -o when multiple pfm files are specified.\n";
00242       return false;
00243     }
00244   }
00245 
00246   Args::const_iterator ai;
00247   for (ai = args.begin(); ai != args.end(); ++ai) {
00248     _input_filenames.push_back(Filename::from_os_specific(*ai));
00249   }
00250 
00251   return true;
00252 }
00253 
00254 ////////////////////////////////////////////////////////////////////
00255 //     Function: PfmTrans::dispatch_scale
00256 //       Access: Protected, Static
00257 //  Description: Handles -TS, which specifies a scale transform.  Var
00258 //               is an LMatrix4.
00259 ////////////////////////////////////////////////////////////////////
00260 bool PfmTrans::
00261 dispatch_scale(const string &opt, const string &arg, void *var) {
00262   LMatrix4 *transform = (LMatrix4 *)var;
00263 
00264   vector_string words;
00265   tokenize(arg, words, ",");
00266 
00267   PN_stdfloat sx, sy, sz;
00268 
00269   bool okflag = false;
00270   if (words.size() == 3) {
00271     okflag =
00272       string_to_float(words[0], sx) &&
00273       string_to_float(words[1], sy) &&
00274       string_to_float(words[2], sz);
00275 
00276   } else if (words.size() == 1) {
00277     okflag =
00278       string_to_float(words[0], sx);
00279     sy = sz = sx;
00280   }
00281 
00282   if (!okflag) {
00283     nout << "-" << opt
00284          << " requires one or three numbers separated by commas.\n";
00285     return false;
00286   }
00287 
00288   *transform = (*transform) * LMatrix4::scale_mat(sx, sy, sz);
00289 
00290   return true;
00291 }
00292 
00293 ////////////////////////////////////////////////////////////////////
00294 //     Function: PfmTrans::dispatch_rotate_xyz
00295 //       Access: Protected, Static
00296 //  Description: Handles -TR, which specifies a rotate transform about
00297 //               the three cardinal axes.  Var is an LMatrix4.
00298 ////////////////////////////////////////////////////////////////////
00299 bool PfmTrans::
00300 dispatch_rotate_xyz(ProgramBase *self, const string &opt, const string &arg, void *var) {
00301   PfmTrans *base = (PfmTrans *)self;
00302   return base->ns_dispatch_rotate_xyz(opt, arg, var);
00303 }
00304 
00305 ////////////////////////////////////////////////////////////////////
00306 //     Function: PfmTrans::ns_dispatch_rotate_xyz
00307 //       Access: Protected
00308 //  Description: Handles -TR, which specifies a rotate transform about
00309 //               the three cardinal axes.  Var is an LMatrix4.
00310 ////////////////////////////////////////////////////////////////////
00311 bool PfmTrans::
00312 ns_dispatch_rotate_xyz(const string &opt, const string &arg, void *var) {
00313   LMatrix4 *transform = (LMatrix4 *)var;
00314 
00315   vector_string words;
00316   tokenize(arg, words, ",");
00317 
00318   LVecBase3 xyz;
00319 
00320   bool okflag = false;
00321   if (words.size() == 3) {
00322     okflag =
00323       string_to_float(words[0], xyz[0]) &&
00324       string_to_float(words[1], xyz[1]) &&
00325       string_to_float(words[2], xyz[2]);
00326   }
00327 
00328   if (!okflag) {
00329     nout << "-" << opt
00330          << " requires three numbers separated by commas.\n";
00331     return false;
00332   }
00333 
00334   LMatrix4 mat =
00335     LMatrix4::rotate_mat(xyz[0], LVector3(1.0, 0.0, 0.0)) *
00336     LMatrix4::rotate_mat(xyz[1], LVector3(0.0, 1.0, 0.0)) *
00337     LMatrix4::rotate_mat(xyz[2], LVector3(0.0, 0.0, 1.0));
00338 
00339   *transform = (*transform) * mat;
00340 
00341   return true;
00342 }
00343 
00344 ////////////////////////////////////////////////////////////////////
00345 //     Function: PfmTrans::dispatch_rotate_axis
00346 //       Access: Protected, Static
00347 //  Description: Handles -TA, which specifies a rotate transform about
00348 //               an arbitrary axis.  Var is an LMatrix4.
00349 ////////////////////////////////////////////////////////////////////
00350 bool PfmTrans::
00351 dispatch_rotate_axis(ProgramBase *self, const string &opt, const string &arg, void *var) {
00352   PfmTrans *base = (PfmTrans *)self;
00353   return base->ns_dispatch_rotate_axis(opt, arg, var);
00354 }
00355 
00356 ////////////////////////////////////////////////////////////////////
00357 //     Function: PfmTrans::ns_dispatch_rotate_axis
00358 //       Access: Protected
00359 //  Description: Handles -TA, which specifies a rotate transform about
00360 //               an arbitrary axis.  Var is an LMatrix4.
00361 ////////////////////////////////////////////////////////////////////
00362 bool PfmTrans::
00363 ns_dispatch_rotate_axis(const string &opt, const string &arg, void *var) {
00364   LMatrix4 *transform = (LMatrix4 *)var;
00365 
00366   vector_string words;
00367   tokenize(arg, words, ",");
00368 
00369   PN_stdfloat angle;
00370   LVecBase3 axis;
00371 
00372   bool okflag = false;
00373   if (words.size() == 4) {
00374     okflag =
00375       string_to_float(words[0], angle) &&
00376       string_to_float(words[1], axis[0]) &&
00377       string_to_float(words[2], axis[1]) &&
00378       string_to_float(words[3], axis[2]);
00379   }
00380 
00381   if (!okflag) {
00382     nout << "-" << opt
00383          << " requires four numbers separated by commas.\n";
00384     return false;
00385   }
00386 
00387   *transform = (*transform) * LMatrix4::rotate_mat(angle, axis);
00388 
00389   return true;
00390 }
00391 
00392 ////////////////////////////////////////////////////////////////////
00393 //     Function: PfmTrans::dispatch_translate
00394 //       Access: Protected, Static
00395 //  Description: Handles -TT, which specifies a translate transform.
00396 //               Var is an LMatrix4.
00397 ////////////////////////////////////////////////////////////////////
00398 bool PfmTrans::
00399 dispatch_translate(const string &opt, const string &arg, void *var) {
00400   LMatrix4 *transform = (LMatrix4 *)var;
00401 
00402   vector_string words;
00403   tokenize(arg, words, ",");
00404 
00405   LVector3 trans;
00406 
00407   bool okflag = false;
00408   if (words.size() == 3) {
00409     okflag =
00410       string_to_float(words[0], trans[0]) &&
00411       string_to_float(words[1], trans[1]) &&
00412       string_to_float(words[2], trans[2]);
00413   }
00414 
00415   if (!okflag) {
00416     nout << "-" << opt
00417          << " requires three numbers separated by commas.\n";
00418     return false;
00419   }
00420 
00421   *transform = (*transform) * LMatrix4::translate_mat(trans);
00422 
00423   return true;
00424 }
00425 
00426 
00427 int main(int argc, char *argv[]) {
00428   // A call to pystub() to force libpystub.so to be linked in.
00429   pystub();
00430 
00431   PfmTrans prog;
00432   prog.parse_command_line(argc, argv);
00433   prog.run();
00434   return 0;
00435 }
 All Classes Functions Variables Enumerations