31 _no_data_nan_num_channels = 0;
32 _got_transform =
false;
33 _transform = LMatrix4::ident_mat();
38 set_program_brief(
"transform .pfm files");
39 set_program_description
40 (
"pfm-trans reads an pfm file and transforms it, filters it, "
41 "operates on it, writing the output to another pfm file. A pfm "
42 "file contains a 2-d table of floating-point values.");
46 "Treats (0,0,0) in the pfm file as a special don't-touch value.",
47 &PfmTrans::dispatch_none, &_got_zero_special);
50 (
"nan",
"num_channels", 0,
51 "Treats a NaN in any of the first num_channels channels as a special don't-touch value.",
52 &PfmTrans::dispatch_int, &_got_no_data_nan, &_no_data_nan_num_channels);
55 (
"resize",
"width,height", 0,
56 "Resamples the pfm file to scale it to the indicated grid size. "
57 "A simple box filter is applied during the scale. Don't confuse this "
58 "with -TS, which scales the individual point values, but doesn't "
59 "change the number of points.",
60 &PfmTrans::dispatch_int_pair, &_got_resize, &_resize);
63 (
"crop",
"xbegin,xend,ybegin,yend", 0,
64 "Crops the pfm file to the indicated subregion.",
65 &PfmTrans::dispatch_int_quad, &_got_crop, &_crop);
69 "Automatically crops to the smallest possible rectangle that includes "
70 "all points. Requires -z or -nan.",
71 &PfmTrans::dispatch_none, &_got_autocrop);
74 (
"rotate",
"degrees", 0,
75 "Rotates the pfm file the specified number of degrees counterclockwise, "
76 "which must be a multiple of 90.",
77 &PfmTrans::dispatch_int,
nullptr, &_rotate);
81 "Flips the pfm file about the x axis.",
82 &PfmTrans::dispatch_none, &_got_mirror_x);
86 "Flips the pfm file about the y axis.",
87 &PfmTrans::dispatch_none, &_got_mirror_y);
91 "Specify the filename to which the resulting pfm file will be written. "
92 "This is only valid when there is only one input pfm file on the command "
93 "line. If you want to process multiple files simultaneously, you must "
95 &PfmTrans::dispatch_filename, &_got_output_filename, &_output_filename);
99 "Specify the name of the directory in which to write the processed pfm "
100 "files. If you are processing only one pfm file, this may be omitted "
101 "in lieu of the -o option.",
102 &PfmTrans::dispatch_filename, &_got_output_dirname, &_output_dirname);
105 (
"vis",
"filename.bam", 60,
106 "Generates a bam file that represents a visualization of the pfm file "
107 "as a 3-D geometric mesh. If -vistex is specified, the mesh is "
109 &PfmTrans::dispatch_filename, &_got_vis_filename, &_vis_filename);
113 "Inverts the visualization, generating a uniform 2-d mesh with the "
114 "3-d depth values encoded in the texture coordinates.",
115 &PfmTrans::dispatch_none, &_got_vis_inverse);
119 "Respect only the first two components of each depth value, ignoring z.",
120 &PfmTrans::dispatch_none, &_got_vis_2d);
123 (
"vistex",
"texture.jpg", 60,
124 "Specifies the name of the texture to apply to the visualization.",
125 &PfmTrans::dispatch_filename, &_got_vistex_filename, &_vistex_filename);
128 (
"ls",
"filename.txt", 60,
129 "Lists the points in the file to the indicated text file.",
130 &PfmTrans::dispatch_filename, &_got_ls_filename, &_ls_filename);
139 if ((
int)(_rotate / 90) * 90 != _rotate) {
140 nout <<
"-rotate can only accept a multiple of 90 degrees.\n";
144 if (_got_vis_filename) {
148 Filenames::const_iterator fi;
149 for (fi = _input_filenames.begin(); fi != _input_filenames.end(); ++fi) {
151 if (!file.
read(*fi)) {
152 nout <<
"Cannot read " << *fi <<
"\n";
160 if (_got_vis_filename) {
171 if (_got_no_data_nan) {
173 }
else if (_got_zero_special) {
180 _got_crop = file.
calc_autocrop(_crop[0], _crop[1], _crop[2], _crop[3]);
184 file.
apply_crop(_crop[0], _crop[1], _crop[2], _crop[3]);
188 file.
resize(_resize[0], _resize[1]);
192 int r = (_rotate / 90) % 4;
201 file.
flip(
true,
false,
true);
208 file.
flip(
true,
false,
false);
209 file.
flip(
false,
true,
false);
213 file.
flip(
false,
true,
true);
216 nassertr(
false,
false);
221 file.
flip(
true,
false,
false);
225 file.
flip(
false,
true,
false);
228 if (_got_transform) {
229 file.
xform(LCAST(PN_float32, _transform));
232 if (_got_vis_filename) {
234 if (_got_vistex_filename) {
236 if (tex ==
nullptr) {
237 nout <<
"Couldn't find " << _vistex_filename <<
"\n";
239 tex->set_minfilter(SamplerState::FT_linear_mipmap_linear);
241 if (tex->has_alpha(tex->get_format())) {
250 if (_got_ls_filename) {
254 for (
int yi = 0; yi < file.
get_y_size(); ++yi) {
255 for (
int xi = 0; xi < file.
get_x_size(); ++xi) {
257 out <<
"(" << xi <<
", " << yi <<
"):";
269 if (_got_output_filename) {
270 output_filename = _output_filename;
271 }
else if (_got_output_dirname) {
275 if (!output_filename.empty()) {
276 return file.
write(output_filename);
290 (
"TS",
"sx[,sy,sz]", 49,
291 "Scale the model uniformly by the given factor (if only one number "
292 "is given) or in each axis by sx, sy, sz (if three numbers are given).",
293 &PfmTrans::dispatch_scale, &_got_transform, &_transform);
297 "Rotate the model x degrees about the x axis, then y degrees about the "
298 "y axis, and then z degrees about the z axis.",
299 &PfmTrans::dispatch_rotate_xyz, &_got_transform, &_transform);
302 (
"TA",
"angle,x,y,z", 49,
303 "Rotate the model angle degrees counterclockwise about the given "
305 &PfmTrans::dispatch_rotate_axis, &_got_transform, &_transform);
309 "Translate the model by the indicated amount.\n\n"
310 "All transformation options (-TS, -TR, -TA, -TT) are cumulative and are "
311 "applied in the order they are encountered on the command line.",
312 &PfmTrans::dispatch_translate, &_got_transform, &_transform);
323 nout <<
"You must specify the pfm file(s) to read on the command line.\n";
327 if (_got_output_filename && args.size() == 1) {
328 if (_got_output_dirname) {
329 nout <<
"Cannot specify both -o and -d.\n";
334 if (_got_output_filename) {
335 nout <<
"Cannot use -o when multiple pfm files are specified.\n";
340 Args::const_iterator ai;
341 for (ai = args.begin(); ai != args.end(); ++ai) {
352 dispatch_scale(
const string &opt,
const string &arg,
void *var) {
353 LMatrix4 *transform = (LMatrix4 *)var;
358 PN_stdfloat sx, sy, sz;
361 if (words.size() == 3) {
363 string_to_stdfloat(words[0], sx) &&
364 string_to_stdfloat(words[1], sy) &&
365 string_to_stdfloat(words[2], sz);
367 }
else if (words.size() == 1) {
369 string_to_stdfloat(words[0], sx);
375 <<
" requires one or three numbers separated by commas.\n";
379 *transform = (*transform) * LMatrix4::scale_mat(sx, sy, sz);
389 dispatch_rotate_xyz(
ProgramBase *
self,
const string &opt,
const string &arg,
void *var) {
391 return base->ns_dispatch_rotate_xyz(opt, arg, var);
399 ns_dispatch_rotate_xyz(
const string &opt,
const string &arg,
void *var) {
400 LMatrix4 *transform = (LMatrix4 *)var;
408 if (words.size() == 3) {
410 string_to_stdfloat(words[0], xyz[0]) &&
411 string_to_stdfloat(words[1], xyz[1]) &&
412 string_to_stdfloat(words[2], xyz[2]);
417 <<
" requires three numbers separated by commas.\n";
422 LMatrix4::rotate_mat(xyz[0], LVector3(1.0, 0.0, 0.0)) *
423 LMatrix4::rotate_mat(xyz[1], LVector3(0.0, 1.0, 0.0)) *
424 LMatrix4::rotate_mat(xyz[2], LVector3(0.0, 0.0, 1.0));
426 *transform = (*transform) * mat;
436 dispatch_rotate_axis(
ProgramBase *
self,
const string &opt,
const string &arg,
void *var) {
438 return base->ns_dispatch_rotate_axis(opt, arg, var);
446 ns_dispatch_rotate_axis(
const string &opt,
const string &arg,
void *var) {
447 LMatrix4 *transform = (LMatrix4 *)var;
456 if (words.size() == 4) {
458 string_to_stdfloat(words[0], angle) &&
459 string_to_stdfloat(words[1], axis[0]) &&
460 string_to_stdfloat(words[2], axis[1]) &&
461 string_to_stdfloat(words[3], axis[2]);
466 <<
" requires four numbers separated by commas.\n";
470 *transform = (*transform) * LMatrix4::rotate_mat(angle, axis);
479 dispatch_translate(
const string &opt,
const string &arg,
void *var) {
480 LMatrix4 *transform = (LMatrix4 *)var;
488 if (words.size() == 3) {
490 string_to_stdfloat(words[0], trans[0]) &&
491 string_to_stdfloat(words[1], trans[1]) &&
492 string_to_stdfloat(words[2], trans[2]);
497 <<
" requires three numbers separated by commas.\n";
501 *transform = (*transform) * LMatrix4::translate_mat(trans);
507 int main(
int argc,
char *argv[]) {