Panda3D
|
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 }