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[]) {
The name of a file, such as a texture file or an Egg file.
std::string get_basename() const
Returns the basename part of the filename.
void set_text()
Indicates that the filename represents a text file.
static Filename from_os_specific(const std::string &os_specific, Type type=T_general)
This named constructor returns a Panda-style filename (that is, using forward slashes,...
bool open_write(std::ofstream &stream, bool truncate=true) const
Opens the indicated ifstream for writing the file, if possible.
std::string get_basename_wo_extension() const
Returns the basename part of the filename, without the file extension.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
void set_texture(Texture *tex, int priority=0)
Adds the indicated texture to the list of textures that will be rendered on the default texture stage...
set_name
Changes the name of the referenced node.
void reparent_to(const NodePath &other, int sort=0, Thread *current_thread=Thread::get_current_thread())
Removes the referenced node of the NodePath from its current parent and attaches it to the referenced...
bool write_bam_file(const Filename &filename) const
Writes the contents of this node and below out to a bam file with the indicated filename.
void set_transparency(TransparencyAttrib::Mode mode, int priority=0)
Specifically sets or disables transparent rendering mode on this particular node.
Defines a pfm file, a 2-d table of floating-point numbers, either 3-component or 1-component,...
void set_no_data_nan(int num_channels)
Sets the no_data_nan flag.
bool read(const Filename &fullpath)
Reads the PFM data from the indicated file, returning true on success, false on failure.
bool write(const Filename &fullpath)
Writes the PFM data to the indicated file, returning true on success, false on failure.
void resize(int new_x_size, int new_y_size)
Applies a simple filter to resample the pfm file in-place to the indicated size.
void xform(const LMatrix4f &transform)
Applies the indicated transform matrix to all points in-place.
void set_zero_special(bool zero_special)
Sets the zero_special flag.
PN_float32 get_channel(int x, int y, int c) const
Returns the cth channel of the point value at the indicated point.
void flip(bool flip_x, bool flip_y, bool transpose)
Reverses, transposes, and/or rotates the table in-place according to the specified parameters.
bool calc_autocrop(int &x_begin, int &x_end, int &y_begin, int &y_end) const
Computes the minimum range of x and y across the PFM file that include all points.
void apply_crop(int x_begin, int x_end, int y_begin, int y_end)
Reduces the PFM file to the cells in the rectangle bounded by (x_begin, x_end, y_begin,...
bool has_point(int x, int y) const
Returns true if there is a valid point at x, y.
void add_transform_options()
Adds -TS, -TT, etc.
bool process_pfm(const Filename &input_filename, PfmFile &file)
Handles a single pfm file.
This class aids in the visualization and manipulation of PfmFile objects.
NodePath generate_vis_mesh(MeshFace face=MF_front) const
Creates a triangle mesh with the points of the pfm as 3-d coordinates in space, and texture coordinat...
void set_vis_2d(bool vis_2d)
Sets the vis_2d flag.
void set_vis_inverse(bool vis_inverse)
Sets the vis_inverse flag.
This is intended to be the base class for most general-purpose utility programs in the PANDATOOL tree...
virtual void parse_command_line(int argc, char **argv)
Dispatches on each of the options on the command line, and passes the remaining parameters to handle_...
static Texture * load_texture(const Filename &filename, int primary_file_num_channels=0, bool read_mipmaps=false, const LoaderOptions &options=LoaderOptions())
Loads the given filename up into a texture, if it has not already been loaded, and returns the new te...
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void tokenize(const string &str, vector_string &words, const string &delimiters, bool discard_repeated_delimiters)
Chops the source string up into pieces delimited by any of the characters specified in delimiters.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.