00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
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
00027
00028
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
00102
00103
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
00130
00131
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
00184
00185
00186
00187
00188
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
00220
00221
00222
00223
00224
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
00256
00257
00258
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
00295
00296
00297
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
00307
00308
00309
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
00346
00347
00348
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
00358
00359
00360
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
00394
00395
00396
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
00429 pystub();
00430
00431 PfmTrans prog;
00432 prog.parse_command_line(argc, argv);
00433 prog.run();
00434 return 0;
00435 }