From d91a11a83680cd331621ecd03c27eaba0ce4edee Mon Sep 17 00:00:00 2001 From: David Rose Date: Mon, 14 Mar 2011 20:10:00 +0000 Subject: [PATCH] move pfmfile to grutil --- pandatool/src/pfmprogs/Sources.pp | 21 +- pandatool/src/pfmprogs/config_pfm.cxx | 11 - pandatool/src/pfmprogs/config_pfm.h | 2 - pandatool/src/pfmprogs/pfmBba.cxx | 147 +++++ pandatool/src/pfmprogs/pfmBba.h | 50 ++ pandatool/src/pfmprogs/pfmFile.I | 151 ----- pandatool/src/pfmprogs/pfmFile.cxx | 778 -------------------------- pandatool/src/pfmprogs/pfmFile.h | 94 ---- pandatool/src/pfmprogs/pfmTrans.cxx | 36 +- pandatool/src/pfmprogs/pfmTrans.h | 1 - 10 files changed, 218 insertions(+), 1073 deletions(-) create mode 100755 pandatool/src/pfmprogs/pfmBba.cxx create mode 100755 pandatool/src/pfmprogs/pfmBba.h delete mode 100755 pandatool/src/pfmprogs/pfmFile.I delete mode 100755 pandatool/src/pfmprogs/pfmFile.cxx delete mode 100755 pandatool/src/pfmprogs/pfmFile.h diff --git a/pandatool/src/pfmprogs/Sources.pp b/pandatool/src/pfmprogs/Sources.pp index 1252ff9003..8c71d6ed54 100755 --- a/pandatool/src/pfmprogs/Sources.pp +++ b/pandatool/src/pfmprogs/Sources.pp @@ -15,7 +15,26 @@ #define SOURCES \ config_pfm.cxx config_pfm.h \ - pfmFile.cxx pfmFile.h \ pfmTrans.cxx pfmTrans.h #end bin_target + +#begin bin_target + #define TARGET pfm-bba + #define LOCAL_LIBS progbase + + #define SOURCES \ + config_pfm.cxx config_pfm.h \ + pfmBba.cxx pfmBba.h + +#end bin_target + +//#begin bin_target +// #define TARGET pfm-wallpaper +// #define LOCAL_LIBS progbase +// +// #define SOURCES \ +// config_pfm.cxx config_pfm.h \ +// pfmWallpaper.cxx pfmWallpaper.h +// +//#end bin_target diff --git a/pandatool/src/pfmprogs/config_pfm.cxx b/pandatool/src/pfmprogs/config_pfm.cxx index 460fff0751..5f058911a9 100755 --- a/pandatool/src/pfmprogs/config_pfm.cxx +++ b/pandatool/src/pfmprogs/config_pfm.cxx @@ -19,17 +19,6 @@ Configure(config_pfm); NotifyCategoryDef(pfm, ""); -ConfigVariableBool pfm_force_littleendian -("pfm-force-littleendian", false, - PRC_DESC("This forces a pfm file to be read as a sequence of little-endian " - "floats, even if its scale factor is given as a positive number.")); - -ConfigVariableBool pfm_reverse_dimensions -("pfm-reverse-dimensions", false, - PRC_DESC("Understands that the width and height of a pfm file are given " - "backwards, in the form height width instead of width height, " - "on input. Does not affect output, which is always written width height.")); - ConfigVariableDouble pfm_bba_dist ("pfm-bba-dist", "0.2 0.05", PRC_DESC("Specifies the point_dist and sample_radius, in UV space, for " diff --git a/pandatool/src/pfmprogs/config_pfm.h b/pandatool/src/pfmprogs/config_pfm.h index 55d5d07b38..8f15714882 100755 --- a/pandatool/src/pfmprogs/config_pfm.h +++ b/pandatool/src/pfmprogs/config_pfm.h @@ -23,8 +23,6 @@ NotifyCategoryDeclNoExport(pfm); -extern ConfigVariableBool pfm_force_littleendian; -extern ConfigVariableBool pfm_reverse_dimensions; extern ConfigVariableDouble pfm_bba_dist; extern void init_libpfm(); diff --git a/pandatool/src/pfmprogs/pfmBba.cxx b/pandatool/src/pfmprogs/pfmBba.cxx new file mode 100755 index 0000000000..de69ab1294 --- /dev/null +++ b/pandatool/src/pfmprogs/pfmBba.cxx @@ -0,0 +1,147 @@ +// Filename: pfmBba.cxx +// Created by: drose (02Mar11) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#include "pfmBba.h" +#include "config_pfm.h" +#include "pfmFile.h" +#include "pystub.h" + +//////////////////////////////////////////////////////////////////// +// Function: PfmBba::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +PfmBba:: +PfmBba() { + set_program_description + ("pfm-bba generates a .bba file from a .pfm file that lists the " + "planar bounding volume of the pfm's internal data."); + + add_option + ("z", "", 0, + "Treats (0,0,0) in the pfm file as a special don't-touch value.", + &PfmBba::dispatch_none, &_got_zero_special); + + add_option + ("o", "filename", 50, + "Specify the filename to which the resulting bba file will be written.", + &PfmBba::dispatch_filename, &_got_output_filename, &_output_filename); +} + + +//////////////////////////////////////////////////////////////////// +// Function: PfmBba::run +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +void PfmBba:: +run() { + Filenames::const_iterator fi; + for (fi = _input_filenames.begin(); fi != _input_filenames.end(); ++fi) { + PfmFile file; + if (!file.read(*fi)) { + nout << "Cannot read " << *fi << "\n"; + exit(1); + } + if (!process_pfm(*fi, file)) { + exit(1); + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: PfmBba::process_pfm +// Access: Public +// Description: Handles a single pfm file. +//////////////////////////////////////////////////////////////////// +bool PfmBba:: +process_pfm(const Filename &input_filename, PfmFile &file) { + file.set_zero_special(_got_zero_special); + + Filename bba_filename; + if (_got_output_filename) { + bba_filename = _output_filename; + } else { + bba_filename = input_filename; + bba_filename.set_extension("bba"); + } + + if (!bba_filename.empty()) { + bba_filename.set_text(); + PT(BoundingHexahedron) bounds = file.compute_planar_bounds(pfm_bba_dist[0], pfm_bba_dist[1]); + nassertr(bounds != (BoundingHexahedron *)NULL, false); + + pofstream out; + if (!bba_filename.open_write(out)) { + pfm_cat.error() + << "Unable to open " << bba_filename << "\n"; + return false; + } + + // This is the order expected by our existing bba system. + static const int ri = 0; + static const int reorder_points[][8] = { + { 0, 1, 2, 3, 4, 5, 6, 7 }, // unfiltered + { 7, 5, 1, 3, 6, 4, 0, 2 }, // front, floor + { 4, 6, 2, 0, 5, 7, 3, 1 }, // left + { 7, 5, 1, 3, 2, 0, 4, 6 }, // right + }; + + for (int i = 0; i < bounds->get_num_points(); ++i) { + LPoint3f p = bounds->get_point(reorder_points[ri][i]); + out << p[0] << "," << p[1] << "," << p[2] << "\n"; + } + } + + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: PfmBba::handle_args +// Access: Protected, Virtual +// Description: Does something with the additional arguments on the +// command line (after all the -options have been +// parsed). Returns true if the arguments are good, +// false otherwise. +//////////////////////////////////////////////////////////////////// +bool PfmBba:: +handle_args(ProgramBase::Args &args) { + if (args.empty()) { + nout << "You must specify the pfm file(s) to read on the command line.\n"; + return false; + } + + if (args.size() > 1 && _got_output_filename) { + nout << "Cannot use -o when multiple pfm files are specified.\n"; + return false; + } + + Args::const_iterator ai; + for (ai = args.begin(); ai != args.end(); ++ai) { + _input_filenames.push_back(Filename::from_os_specific(*ai)); + } + + return true; +} + + +int main(int argc, char *argv[]) { + // A call to pystub() to force libpystub.so to be linked in. + pystub(); + + PfmBba prog; + prog.parse_command_line(argc, argv); + prog.run(); + return 0; +} diff --git a/pandatool/src/pfmprogs/pfmBba.h b/pandatool/src/pfmprogs/pfmBba.h new file mode 100755 index 0000000000..b22c533602 --- /dev/null +++ b/pandatool/src/pfmprogs/pfmBba.h @@ -0,0 +1,50 @@ +// Filename: pfmBba.h +// Created by: drose (02Mar11) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#ifndef PFMBBA_H +#define PFMBBA_H + +#include "pandatoolbase.h" +#include "programBase.h" +#include "filename.h" +#include "pvector.h" +#include "nodePath.h" +#include "luse.h" + +class PfmFile; + +//////////////////////////////////////////////////////////////////// +// Class : PfmBba +// Description : Generates a bounding-box description of a pfm file. +//////////////////////////////////////////////////////////////////// +class PfmBba : public ProgramBase { +public: + PfmBba(); + + void run(); + bool process_pfm(const Filename &input_filename, PfmFile &file); + +protected: + virtual bool handle_args(Args &args); + +private: + typedef pvector Filenames; + Filenames _input_filenames; + + bool _got_zero_special; + bool _got_output_filename; + Filename _output_filename; +}; + +#endif diff --git a/pandatool/src/pfmprogs/pfmFile.I b/pandatool/src/pfmprogs/pfmFile.I deleted file mode 100755 index 5f697c3b39..0000000000 --- a/pandatool/src/pfmprogs/pfmFile.I +++ /dev/null @@ -1,151 +0,0 @@ -// Filename: pfmFile.I -// Created by: drose (23Dec10) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////// -// Function: PfmFile::is_valid -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE bool PfmFile:: -is_valid() const { - return _num_channels != 0 && (_x_size * _y_size == (int)_table.size()); -} - -//////////////////////////////////////////////////////////////////// -// Function: PfmFile::get_x_size -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE int PfmFile:: -get_x_size() const { - return _x_size; -} - -//////////////////////////////////////////////////////////////////// -// Function: PfmFile::get_y_size -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE int PfmFile:: -get_y_size() const { - return _y_size; -} - -//////////////////////////////////////////////////////////////////// -// Function: PfmFile::get_scale -// Access: Public -// Description: The "scale" is reported in the pfm header and is -// probably meaningless. -//////////////////////////////////////////////////////////////////// -INLINE float PfmFile:: -get_scale() const { - return _scale; -} - -//////////////////////////////////////////////////////////////////// -// Function: PfmFile::get_num_channels -// Access: Public -// Description: A pfm file can be either 1-channel -// (get_num_channels() == 1) or 3-channel -// (get_num_channels() == 3). In the case of a -// 1-channel file, the values can be found in the x -// component of each point, and the y and z components -// are unused. -//////////////////////////////////////////////////////////////////// -INLINE int PfmFile:: -get_num_channels() const { - return _num_channels; -} - -//////////////////////////////////////////////////////////////////// -// Function: PfmFile::get_point -// Access: Public -// Description: Returns the 3-component point value at the indicated -// point. In a 1-channel image, the channel value is in -// the x component. -//////////////////////////////////////////////////////////////////// -INLINE const LPoint3f &PfmFile:: -get_point(int x, int y) const { - nassertr(x >= 0 && x < _x_size, LPoint3f::zero()); - nassertr(y >= 0 && y < _y_size, LPoint3f::zero()); - return _table[y * _x_size + x]; -} - -//////////////////////////////////////////////////////////////////// -// Function: PfmFile::modify_point -// Access: Public -// Description: Returns a modifiable 3-component point value at the -// indicated point. -//////////////////////////////////////////////////////////////////// -INLINE LPoint3f &PfmFile:: -modify_point(int x, int y) { -#ifndef NDEBUG - static LPoint3f dummy_value = LPoint3f::zero(); - nassertr(x >= 0 && x < _x_size, dummy_value); - nassertr(y >= 0 && y < _y_size, dummy_value); -#endif - - return _table[y * _x_size + x]; -} - -//////////////////////////////////////////////////////////////////// -// Function: PfmFile::set_zero_special -// Access: Public -// Description: Sets the zero_special flag. When this flag is true, -// values of (0, 0, 0) in the pfm file are treated as a -// special case, and are not processed. -//////////////////////////////////////////////////////////////////// -INLINE void PfmFile:: -set_zero_special(bool zero_special) { - _zero_special = zero_special; -} - -//////////////////////////////////////////////////////////////////// -// Function: PfmFile::get_zero_special -// Access: Public -// Description: Returns the zero_special flag. When this flag is true, -// values of (0, 0, 0) in the pfm file are treated as a -// special case, and are not processed. -//////////////////////////////////////////////////////////////////// -INLINE bool PfmFile:: -get_zero_special() const { - return _zero_special; -} - -//////////////////////////////////////////////////////////////////// -// Function: PfmFile::set_vis_inverse -// Access: Public -// Description: Sets the vis_inverse flag. When this flag is true, -// vis meshes and point clouds are generated with the -// 3-d depth value in the texture coordinates, and the -// 2-d index value in the vertex position. When it is -// false, meshes are generated normally, with the 3-d -// depth value in the vertex position and the 2-d index -// value in the texture coordinates. -//////////////////////////////////////////////////////////////////// -INLINE void PfmFile:: -set_vis_inverse(bool vis_inverse) { - _vis_inverse = vis_inverse; -} - -//////////////////////////////////////////////////////////////////// -// Function: PfmFile::get_vis_inverse -// Access: Public -// Description: Returns the vis_inverse flag. See set_vis_inverse(). -//////////////////////////////////////////////////////////////////// -INLINE bool PfmFile:: -get_vis_inverse() const { - return _vis_inverse; -} diff --git a/pandatool/src/pfmprogs/pfmFile.cxx b/pandatool/src/pfmprogs/pfmFile.cxx deleted file mode 100755 index 1dc3bffe00..0000000000 --- a/pandatool/src/pfmprogs/pfmFile.cxx +++ /dev/null @@ -1,778 +0,0 @@ -// Filename: pfmFile.cxx -// Created by: drose (23Dec10) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#include "config_pfm.h" -#include "pfmFile.h" -#include "virtualFileSystem.h" -#include "pandaFileStream.h" -#include "littleEndian.h" -#include "bigEndian.h" -#include "cmath.h" -#include "geomNode.h" -#include "geom.h" -#include "geomVertexData.h" -#include "geomVertexFormat.h" -#include "geomPoints.h" -#include "geomTriangles.h" -#include "geomVertexWriter.h" -#include "look_at.h" - -//////////////////////////////////////////////////////////////////// -// Function: PfmFile::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -PfmFile:: -PfmFile() { - _zero_special = false; - _vis_inverse = false; - clear(); -} - -//////////////////////////////////////////////////////////////////// -// Function: PfmFile::Copy Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -PfmFile:: -PfmFile(const PfmFile ©) : - _table(copy._table), - _x_size(copy._x_size), - _y_size(copy._y_size), - _scale(copy._scale), - _num_channels(copy._num_channels), - _zero_special(copy._zero_special) -{ -} - -//////////////////////////////////////////////////////////////////// -// Function: PfmFile::Copy Assignment -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -void PfmFile:: -operator = (const PfmFile ©) { - _table = copy._table; - _x_size = copy._x_size; - _y_size = copy._y_size; - _scale = copy._scale; - _num_channels = copy._num_channels; - _zero_special = copy._zero_special; -} - -//////////////////////////////////////////////////////////////////// -// Function: PfmFile::clear -// Access: Public -// Description: Eliminates all data in the file. -//////////////////////////////////////////////////////////////////// -void PfmFile:: -clear() { - _x_size = 0; - _y_size = 0; - _num_channels = 0; - _table.clear(); -} - -//////////////////////////////////////////////////////////////////// -// Function: PfmFile::read -// Access: Public -// Description: Reads the PFM data from the indicated file, returning -// true on success, false on failure. -//////////////////////////////////////////////////////////////////// -bool PfmFile:: -read(const Filename &fullpath) { - VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); - - Filename filename = Filename::binary_filename(fullpath); - PT(VirtualFile) file = vfs->get_file(filename); - if (file == (VirtualFile *)NULL) { - // No such file. - pfm_cat.error() - << "Could not find " << fullpath << "\n"; - return false; - } - - if (pfm_cat.is_debug()) { - pfm_cat.debug() - << "Reading PFM file " << filename << "\n"; - } - - istream *in = file->open_read_file(true); - bool success = read(*in); - vfs->close_read_file(in); - - return success; -} - -//////////////////////////////////////////////////////////////////// -// Function: PfmFile::read -// Access: Public -// Description: Reads the PFM data from the indicated stream, -// returning true on success, false on failure. -//////////////////////////////////////////////////////////////////// -bool PfmFile:: -read(istream &in) { - clear(); - - string identifier; - in >> identifier; - - if (identifier == "PF") { - _num_channels = 3; - } else if (identifier == "Pf") { - _num_channels = 1; - } else { - pfm_cat.error() - << "Not a pfm file.\n"; - return false; - } - - int width, height; - float scale; - in >> width >> height >> scale; - if (!in) { - pfm_cat.error() - << "Error parsing pfm header.\n"; - return false; - } - - // Skip the last newline/whitespace character before the raw data - // begins. - in.get(); - - bool little_endian = false; - if (scale < 0) { - scale = -scale; - little_endian = true; - } - if (pfm_force_littleendian) { - little_endian = true; - } - if (pfm_reverse_dimensions) { - int t = width; - width = height; - height = t; - } - - _x_size = width; - _y_size = height; - _scale = scale; - - // So far, so good. Now read the data. - int size = _x_size * _y_size; - _table.reserve(size); - - if (little_endian) { - for (int i = 0; i < size; ++i) { - LPoint3f point = LPoint3f::zero(); - for (int ci = 0; ci < _num_channels; ++ci) { - float data; - in.read((char *)&data, sizeof(data)); - LittleEndian value(&data, sizeof(data)); - value.store_value(&(point[ci]), sizeof(point[ci])); - } - _table.push_back(point); - } - } else { - for (int i = 0; i < size; ++i) { - LPoint3f point = LPoint3f::zero(); - for (int ci = 0; ci < _num_channels; ++ci) { - float data; - in.read((char *)&data, sizeof(data)); - BigEndian value(&data, sizeof(data)); - value.store_value(&(point[ci]), sizeof(point[ci])); - } - _table.push_back(point); - } - } - - if (in.fail() && !in.eof()) { - return false; - } - - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: PfmFile::write -// Access: Public -// Description: Writes the PFM data to the indicated file, returning -// true on success, false on failure. -//////////////////////////////////////////////////////////////////// -bool PfmFile:: -write(const Filename &fullpath) { - Filename filename = Filename::binary_filename(fullpath); - pofstream out; - if (!filename.open_write(out)) { - pfm_cat.error() - << "Unable to open " << filename << "\n"; - return false; - } - - if (pfm_cat.is_debug()) { - pfm_cat.debug() - << "Writing PFM file " << filename << "\n"; - } - - return write(out); -} - -//////////////////////////////////////////////////////////////////// -// Function: PfmFile::write -// Access: Public -// Description: Writes the PFM data to the indicated stream, -// returning true on success, false on failure. -//////////////////////////////////////////////////////////////////// -bool PfmFile:: -write(ostream &out) { - nassertr(is_valid(), false); - - if (_num_channels == 1) { - out << "Pf\n"; - } else { - out << "PF\n"; - } - out << _x_size << " " << _y_size << "\n"; - - float scale = cabs(_scale); - if (scale == 0.0f) { - scale = 1.0f; - } -#ifndef WORDS_BIGENDIAN - // Little-endian must write negative values for scale. - scale = -scale; -#endif - out << scale << "\n"; - - int size = _x_size * _y_size; - for (int i = 0; i < size; ++i) { - const LPoint3f &point = _table[i]; - for (int ci = 0; ci < _num_channels; ++ci) { - float data = point[ci]; - out.write((const char *)&data, sizeof(data)); - } - } - - if (out.fail()) { - return false; - } - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: PfmFile::resize -// Access: Public -// Description: Applies a simple filter to resample the pfm file -// in-place to the indicated size. Don't confuse this -// with applying a scale to all of the points via -// xform(). -//////////////////////////////////////////////////////////////////// -void PfmFile:: -resize(int new_x_size, int new_y_size) { - Table new_data; - new_data.reserve(new_x_size * new_y_size); - - double from_x0, from_x1, from_y0, from_y1; - - double x_scale = (double)(_x_size - 1) / (double)(new_x_size - 1); - double y_scale = (double)(_y_size - 1) / (double)(new_y_size - 1); - - from_y0 = 0.0; - for (int to_y = 0; to_y < new_y_size; ++to_y) { - from_y1 = (to_y + 0.5) * y_scale; - from_y1 = min(from_y1, (double) _y_size); - - from_x0 = 0.0; - for (int to_x = 0; to_x < new_x_size; ++to_x) { - from_x1 = (to_x + 0.5) * x_scale; - from_x1 = min(from_x1, (double) _x_size); - - // Now the box from (from_x0, from_y0) - (from_x1, from_y1) - // but not including (from_x1, from_y1) maps to the pixel (to_x, to_y). - LPoint3f result; - box_filter_region(result, from_x0, from_y0, from_x1, from_y1); - new_data.push_back(result); - - from_x0 = from_x1; - } - from_y0 = from_y1; - } - - _table.swap(new_data); - _x_size = new_x_size; - _y_size = new_y_size; -} - -//////////////////////////////////////////////////////////////////// -// Function: PfmFile::reverse_rows -// Access: Public -// Description: Performs an in-place reversal of the row (y) data. -//////////////////////////////////////////////////////////////////// -void PfmFile:: -reverse_rows() { - nassertv(is_valid()); - - Table reversed; - reversed.reserve(_table.size()); - for (int yi = 0; yi < _y_size; ++yi) { - int source_yi = _y_size - 1 - yi; - int start = source_yi * _x_size; - reversed.insert(reversed.end(), - _table.begin() + start, _table.begin() + start + _x_size); - } - - nassertv(reversed.size() == _table.size()); - _table.swap(reversed); -} - -//////////////////////////////////////////////////////////////////// -// Function: PfmFile::xform -// Access: Public -// Description: Applies the indicated transform matrix to all points -// in-place. -//////////////////////////////////////////////////////////////////// -void PfmFile:: -xform(const LMatrix4f &transform) { - nassertv(is_valid()); - - Table::iterator ti; - for (ti = _table.begin(); ti != _table.end(); ++ti) { - if (_zero_special && (*ti) == LPoint3f::zero()) { - continue; - } - - (*ti) = (*ti) * transform; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: PfmFile::compute_planar_bounds -// Access: Public -// Description: Computes the minmax bounding volume of the points in -// 3-D space, assuming the points represent a -// mostly-planar surface. -// -// This algorithm works by sampling the (square) -// sample_radius pixels at three of the four point_dist -// corners around the center (cx - pd, cx + pd) and so -// on, to determine the plane of the surface. Then all -// of the points are projected into that plane and the -// bounding volume within that plane is determined. -// -// point_dist and sample_radius are in UV space, i.e. in -// the range 0..1. -//////////////////////////////////////////////////////////////////// -PT(BoundingHexahedron) PfmFile:: -compute_planar_bounds(double point_dist, double sample_radius) const { - LPoint3f p0, p1, p2; - compute_sample_point(p0, 0.5 + point_dist, 0.5 - point_dist, sample_radius); - compute_sample_point(p1, 0.5 + point_dist, 0.5 + point_dist, sample_radius); - compute_sample_point(p2, 0.5 - point_dist, 0.5 + point_dist, sample_radius); - - LPoint3f normal; - - normal[0] = p0[1] * p1[2] - p0[2] * p1[1]; - normal[1] = p0[2] * p1[0] - p0[0] * p1[2]; - normal[2] = p0[0] * p1[1] - p0[1] * p1[0]; - - normal[0] += p1[1] * p2[2] - p1[2] * p2[1]; - normal[1] += p1[2] * p2[0] - p1[0] * p2[2]; - normal[2] += p1[0] * p2[1] - p1[1] * p2[0]; - - normal[0] += p2[1] * p0[2] - p2[2] * p0[1]; - normal[1] += p2[2] * p0[0] - p2[0] * p0[2]; - normal[2] += p2[0] * p0[1] - p2[1] * p0[0]; - - normal.normalize(); - - // Compute the transform necessary to rotate all of the points into - // the Y = 0 plane. - LMatrix4f rotate; - look_at(rotate, normal, p1 - p0); - - LMatrix4f rinv; - rinv.invert_from(rotate); - - LPoint3f trans = p0 * rinv; - rinv.set_row(3, -trans); - rotate.invert_from(rinv); - - // Now determine the minmax in the XZ plane. - float min_x, min_z, max_x, max_z; - bool got_point = false; - Table::const_iterator ti; - for (ti = _table.begin(); ti != _table.end(); ++ti) { - if (_zero_special && (*ti) == LPoint3f::zero()) { - continue; - } - LPoint3f point = (*ti) * rinv; - if (!got_point) { - min_x = point[0]; - min_z = point[2]; - max_x = point[0]; - max_z = point[2]; - got_point = true; - } else { - min_x = min(min_x, point[0]); - min_z = min(min_z, point[2]); - max_x = max(max_x, point[0]); - max_z = max(max_z, point[2]); - } - } - - PT(BoundingHexahedron) bounds = new BoundingHexahedron - (LPoint3f(min_x, 0, min_z), LPoint3f(max_x, 0, min_z), - LPoint3f(min_x, 0, max_z), LPoint3f(max_x, 0, max_z), - LPoint3f(min_x, 0, min_z), LPoint3f(max_x, 0, min_z), - LPoint3f(min_x, 0, max_z), LPoint3f(max_x, 0, max_z)); - - // Rotate the bounding volume back into the original space of the - // screen. - bounds->xform(rotate); - - return bounds; -} - -//////////////////////////////////////////////////////////////////// -// Function: PfmFile::generate_vis_points -// Access: Public -// Description: Creates a point cloud with the points of the pfm as -// 3-d coordinates in space, and texture coordinates -// ranging from 0 .. 1 based on the position within the -// pfm grid. -//////////////////////////////////////////////////////////////////// -NodePath PfmFile:: -generate_vis_points() const { - nassertr(is_valid(), NodePath()); - - CPT(GeomVertexFormat) format; - if (_vis_inverse) { - // We need a 3-d texture coordinate if we're inverted the vis. - GeomVertexArrayFormat *v3t3 = new GeomVertexArrayFormat - (InternalName::get_vertex(), 3, - Geom::NT_float32, Geom::C_point, - InternalName::get_texcoord(), 3, - Geom::NT_float32, Geom::C_texcoord); - format = GeomVertexFormat::register_format(v3t3); - } else { - format = GeomVertexFormat::get_v3t2(); - } - - PT(GeomVertexData) vdata = new GeomVertexData - ("points", format, Geom::UH_static); - vdata->set_num_rows(_x_size * _y_size); - GeomVertexWriter vertex(vdata, InternalName::get_vertex()); - GeomVertexWriter texcoord(vdata, InternalName::get_texcoord()); - - for (int yi = 0; yi < _y_size; ++yi) { - for (int xi = 0; xi < _x_size; ++xi) { - const LPoint3f &point = get_point(xi, yi); - LPoint2f uv(float(xi) / float(_x_size - 1), - float(yi) / float(_y_size - 1)); - if (_vis_inverse) { - vertex.add_data2f(uv); - texcoord.add_data3f(point); - } else { - vertex.add_data3f(point); - texcoord.add_data2f(uv); - } - } - } - - PT(Geom) geom = new Geom(vdata); - PT(GeomPoints) points = new GeomPoints(Geom::UH_static); - points->add_next_vertices(_x_size * _y_size); - geom->add_primitive(points); - - PT(GeomNode) gnode = new GeomNode(""); - gnode->add_geom(geom); - return NodePath(gnode); -} - -//////////////////////////////////////////////////////////////////// -// Function: PfmFile::generate_vis_mesh -// Access: Public -// Description: Creates a triangle mesh with the points of the pfm as -// 3-d coordinates in space, and texture coordinates -// ranging from 0 .. 1 based on the position within the -// pfm grid. -//////////////////////////////////////////////////////////////////// -NodePath PfmFile:: -generate_vis_mesh() const { - nassertr(is_valid(), NodePath()); - - PT(GeomNode) gnode = new GeomNode(""); - - PT(Geom) geom1 = make_vis_mesh_geom(false); - gnode->add_geom(geom1); - - PT(Geom) geom2 = make_vis_mesh_geom(true); - gnode->add_geom(geom2); - - return NodePath(gnode); -} - -//////////////////////////////////////////////////////////////////// -// Function: PfmFile::make_vis_mesh_geom -// Access: Private -// Description: Returns a triangle mesh for the pfm. If inverted is -// true, the mesh is facing the opposite direction. -//////////////////////////////////////////////////////////////////// -PT(Geom) PfmFile:: -make_vis_mesh_geom(bool inverted) const { - - CPT(GeomVertexFormat) format; - if (_vis_inverse) { - // We need a 3-d texture coordinate if we're inverted the vis. - // But we don't need normals in that case. - GeomVertexArrayFormat *v3t3 = new GeomVertexArrayFormat - (InternalName::get_vertex(), 3, - Geom::NT_float32, Geom::C_point, - InternalName::get_texcoord(), 3, - Geom::NT_float32, Geom::C_texcoord); - format = GeomVertexFormat::register_format(v3t3); - } else { - // Otherwise, we only need a 2-d texture coordinate, and we do - // want normals. - format = GeomVertexFormat::get_v3n3t2(); - } - - PT(GeomVertexData) vdata = new GeomVertexData - ("mesh", format, Geom::UH_static); - int num_vertices = _x_size * _y_size; - vdata->set_num_rows(num_vertices); - GeomVertexWriter vertex(vdata, InternalName::get_vertex()); - GeomVertexWriter normal(vdata, InternalName::get_normal()); - GeomVertexWriter texcoord(vdata, InternalName::get_texcoord()); - - for (int yi = 0; yi < _y_size; ++yi) { - for (int xi = 0; xi < _x_size; ++xi) { - const LPoint3f &point = get_point(xi, yi); - LPoint2f uv(float(xi) / float(_x_size - 1), - float(yi) / float(_y_size - 1)); - - if (_vis_inverse) { - vertex.add_data2f(uv); - texcoord.add_data3f(point); - } else { - vertex.add_data3f(point); - texcoord.add_data2f(uv); - - // Calculate the normal based on two neighboring vertices. - LPoint3f v[3]; - v[0] = get_point(xi, yi); - if (xi + 1 < _x_size) { - v[1] = get_point(xi + 1, yi); - } else { - v[1] = v[0]; - v[0] = get_point(xi - 1, yi); - } - - if (yi + 1 < _y_size) { - v[2] = get_point(xi, yi + 1); - } else { - v[2] = v[0]; - v[0] = get_point(xi, yi - 1); - } - - LVector3f n = LVector3f::zero(); - for (int i = 0; i < 3; ++i) { - const LPoint3f &v0 = v[i]; - const LPoint3f &v1 = v[(i + 1) % 3]; - n[0] += v0[1] * v1[2] - v0[2] * v1[1]; - n[1] += v0[2] * v1[0] - v0[0] * v1[2]; - n[2] += v0[0] * v1[1] - v0[1] * v1[0]; - } - n.normalize(); - if (inverted) { - n = -n; - } - normal.add_data3f(n); - } - } - } - - PT(Geom) geom = new Geom(vdata); - PT(GeomTriangles) tris = new GeomTriangles(Geom::UH_static); - - if (num_vertices > 0xffff) { - // We need 32-bit indices. - tris->set_index_type(Geom::NT_uint32); - } - - // We get direct access to the vertices data so we can speed things - // up by pre-specifying the number of vertices. Need a better - // interface to do this same thing using the high-level access - // methods. - int num_indices = (_x_size - 1) * (_y_size - 1) * 6; - - PT(GeomVertexArrayData) indices = tris->modify_vertices(); - indices->set_num_rows(num_indices); - GeomVertexWriter index(indices, 0); - - int actual_num_indices = 0; - for (int yi = 0; yi < _y_size - 1; ++yi) { - for (int xi = 0; xi < _x_size - 1; ++xi) { - - if (_zero_special) { - if (get_point(xi, yi) == LPoint3f::zero() || - get_point(xi, yi + 1) == LPoint3f::zero() || - get_point(xi + 1, yi + 1) == LPoint3f::zero() || - get_point(xi + 1, yi) == LPoint3f::zero()) { - continue; - } - } - - int vi0 = ((xi) + (yi) * _x_size); - int vi1 = ((xi) + (yi + 1) * _x_size); - int vi2 = ((xi + 1) + (yi + 1) * _x_size); - int vi3 = ((xi + 1) + (yi) * _x_size); - - if (inverted) { - index.add_data1i(vi2); - index.add_data1i(vi0); - index.add_data1i(vi1); - - index.add_data1i(vi3); - index.add_data1i(vi0); - index.add_data1i(vi2); - } else { - index.add_data1i(vi2); - index.add_data1i(vi1); - index.add_data1i(vi0); - - index.add_data1i(vi3); - index.add_data1i(vi2); - index.add_data1i(vi0); - } - - actual_num_indices += 6; - } - } - indices->set_num_rows(actual_num_indices); - geom->add_primitive(tris); - - return geom; -} - - -//////////////////////////////////////////////////////////////////// -// Function: PfmFile::compute_sample_point -// Access: Private -// Description: Computes the average of all the point within -// sample_radius (manhattan distance) and the indicated -// point. -// -// Unlike box_filter_*(), these point values are given -// in UV space, in the range 0..1. -//////////////////////////////////////////////////////////////////// -void PfmFile:: -compute_sample_point(LPoint3f &result, - double x, double y, double sample_radius) const { - x *= _x_size; - y *= _y_size; - double xr = sample_radius * _x_size; - double yr = sample_radius * _y_size; - box_filter_region(result, x - xr, y - yr, x + xr, y + yr); -} - - -//////////////////////////////////////////////////////////////////// -// Function: PfmFile::box_filter_region -// Access: Private -// Description: Averages all the points in the rectangle from x0 -// .. y0 to x1 .. y1 into result. The region may be -// defined by floating-point boundaries; the result will -// be weighted by the degree of coverage of each -// included point. -//////////////////////////////////////////////////////////////////// -void PfmFile:: -box_filter_region(LPoint3f &result, - double x0, double y0, double x1, double y1) const { - result = LPoint3f::zero(); - double coverage = 0.0; - - assert(y0 >= 0.0 && y1 >= 0.0); - - int y = (int)y0; - // Get the first (partial) row - box_filter_line(result, coverage, x0, y, x1, (double)(y+1)-y0); - - int y_last = (int)y1; - if (y < y_last) { - y++; - while (y < y_last) { - // Get each consecutive (complete) row - box_filter_line(result, coverage, x0, y, x1, 1.0); - y++; - } - - // Get the final (partial) row - double y_contrib = y1 - (double)y_last; - if (y_contrib > 0.0001) { - box_filter_line(result, coverage, x0, y, x1, y_contrib); - } - } - - if (coverage != 0.0) { - result /= coverage; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: PfmFile::box_filter_line -// Access: Private -// Description: -//////////////////////////////////////////////////////////////////// -void PfmFile:: -box_filter_line(LPoint3f &result, double &coverage, - double x0, int y, double x1, double y_contrib) const { - int x = (int)x0; - // Get the first (partial) xel - box_filter_point(result, coverage, x, y, (double)(x+1)-x0, y_contrib); - - int x_last = (int)x1; - if (x < x_last) { - x++; - while (x < x_last) { - // Get each consecutive (complete) xel - box_filter_point(result, coverage, x, y, 1.0, y_contrib); - x++; - } - - // Get the final (partial) xel - double x_contrib = x1 - (double)x_last; - if (x_contrib > 0.0001) { - box_filter_point(result, coverage, x, y, x_contrib, y_contrib); - } - } -} - -//////////////////////////////////////////////////////////////////// -// Function: PfmFile::box_filter_point -// Access: Private -// Description: -//////////////////////////////////////////////////////////////////// -void PfmFile:: -box_filter_point(LPoint3f &result, double &coverage, - int x, int y, double x_contrib, double y_contrib) const { - const LPoint3f &point = get_point(x, y); - if (_zero_special && point == LPoint3f::zero()) { - return; - } - - double contrib = x_contrib * y_contrib; - result += point * contrib; - coverage += contrib; -} diff --git a/pandatool/src/pfmprogs/pfmFile.h b/pandatool/src/pfmprogs/pfmFile.h deleted file mode 100755 index 0052266b23..0000000000 --- a/pandatool/src/pfmprogs/pfmFile.h +++ /dev/null @@ -1,94 +0,0 @@ -// Filename: pfmFile.h -// Created by: drose (23Dec10) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#ifndef PFMFILE_H -#define PFMFILE_H - -#include "pandatoolbase.h" -#include "luse.h" -#include "nodePath.h" -#include "boundingHexahedron.h" - -//////////////////////////////////////////////////////////////////// -// Class : PfmFile -// Description : Defines a pfm file, a 2-d table of floating-point -// numbers, either 3-component or 1-component. -//////////////////////////////////////////////////////////////////// -class PfmFile { -public: - PfmFile(); - PfmFile(const PfmFile ©); - void operator = (const PfmFile ©); - - void clear(); - - bool read(const Filename &fullpath); - bool read(istream &in); - bool write(const Filename &fullpath); - bool write(ostream &out); - - INLINE bool is_valid() const; - - INLINE int get_x_size() const; - INLINE int get_y_size() const; - INLINE float get_scale() const; - INLINE int get_num_channels() const; - - INLINE const LPoint3f &get_point(int x, int y) const; - INLINE LPoint3f &modify_point(int x, int y); - - INLINE void set_zero_special(bool zero_special); - INLINE bool get_zero_special() const; - - void resize(int new_x_size, int new_y_size); - void reverse_rows(); - void xform(const LMatrix4f &transform); - - PT(BoundingHexahedron) compute_planar_bounds(double point_dist, double sample_radius) const; - - INLINE void set_vis_inverse(bool vis_inverse); - INLINE bool get_vis_inverse() const; - - NodePath generate_vis_points() const; - NodePath generate_vis_mesh() const; - -private: - PT(Geom) make_vis_mesh_geom(bool inverted) const; - - void compute_sample_point(LPoint3f &result, - double x, double y, double sample_radius) const; - void box_filter_region(LPoint3f &result, - double x0, double y0, double x1, double y1) const; - void box_filter_line(LPoint3f &result, double &coverage, - double x0, int y, double x1, double y_contrib) const; - void box_filter_point(LPoint3f &result, double &coverage, - int x, int y, double x_contrib, double y_contrib) const; - - -private: - typedef pvector Table; - Table _table; - - int _x_size; - int _y_size; - float _scale; - int _num_channels; - - bool _zero_special; - bool _vis_inverse; -}; - -#include "pfmFile.I" - -#endif diff --git a/pandatool/src/pfmprogs/pfmTrans.cxx b/pandatool/src/pfmprogs/pfmTrans.cxx index 2b86d389ce..a288934d17 100755 --- a/pandatool/src/pfmprogs/pfmTrans.cxx +++ b/pandatool/src/pfmprogs/pfmTrans.cxx @@ -72,12 +72,6 @@ PfmTrans() { "in lieu of the -o option.", &PfmTrans::dispatch_filename, &_got_output_dirname, &_output_dirname); - add_option - ("bba", "", 50, - "Generates a .bba file alongside each output file that lists the " - "planar bounding volume of each pfm file's data.", - &PfmTrans::dispatch_none, &_got_bba); - add_option ("vis", "filename.bam", 60, "Generates a bam file that represents a visualization of the pfm file " @@ -149,7 +143,7 @@ process_pfm(const Filename &input_filename, PfmFile &file) { } if (_got_vis_filename) { - NodePath mesh = file.generate_vis_mesh(); + NodePath mesh = file.generate_vis_mesh(true); if (_got_vistex_filename) { PT(Texture) tex = TexturePool::load_texture(_vistex_filename); if (tex == NULL) { @@ -173,34 +167,6 @@ process_pfm(const Filename &input_filename, PfmFile &file) { } if (!output_filename.empty()) { - if (_got_bba) { - Filename bba_filename = output_filename; - bba_filename.set_text(); - bba_filename.set_extension("bba"); - PT(BoundingHexahedron) bounds = file.compute_planar_bounds(pfm_bba_dist[0], pfm_bba_dist[1]); - nassertr(bounds != (BoundingHexahedron *)NULL, false); - - pofstream out; - if (!bba_filename.open_write(out)) { - pfm_cat.error() - << "Unable to open " << bba_filename << "\n"; - return false; - } - - // This is the order expected by our existing bba system. - static const int ri = 0; - static const int reorder_points[][8] = { - { 0, 1, 2, 3, 4, 5, 6, 7 }, // unfiltered - { 7, 5, 1, 3, 6, 4, 0, 2 }, // front, floor - { 4, 6, 2, 0, 5, 7, 3, 1 }, // left - { 7, 5, 1, 3, 2, 0, 4, 6 }, // right - }; - - for (int i = 0; i < bounds->get_num_points(); ++i) { - LPoint3f p = bounds->get_point(reorder_points[ri][i]); - out << p[0] << "," << p[1] << "," << p[2] << "\n"; - } - } return file.write(output_filename); } diff --git a/pandatool/src/pfmprogs/pfmTrans.h b/pandatool/src/pfmprogs/pfmTrans.h index b649d6d621..4bafd55c44 100755 --- a/pandatool/src/pfmprogs/pfmTrans.h +++ b/pandatool/src/pfmprogs/pfmTrans.h @@ -56,7 +56,6 @@ private: bool _got_vis_inverse; bool _got_resize; int _resize[2]; - bool _got_bba; bool _got_output_filename; Filename _output_filename;