David Rose 13 éve
szülő
commit
68de528a0f

+ 17 - 0
panda/src/grutil/pfmFile.I

@@ -132,6 +132,23 @@ modify_point(int x, int y) {
   return _table[y * _x_size + x];
   return _table[y * _x_size + x];
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: PfmFile::calc_autocrop
+//       Access: Published
+//  Description: Computes the minimum range of x and y across the PFM
+//               file that include all points.  If there are no points
+//               with no_data_value in the grid--that is, all points
+//               are included--then this will return (0, get_x_size(),
+//               0, get_y_size()).
+////////////////////////////////////////////////////////////////////
+INLINE bool PfmFile::
+calc_autocrop(LVecBase4 &range) const {
+  int x_begin, x_end, y_begin, y_end;
+  bool result = calc_autocrop(x_begin, x_end, y_begin, y_end);
+  range.set(x_begin, x_end, y_begin, y_end);
+  return result;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PfmFile::set_zero_special
 //     Function: PfmFile::set_zero_special
 //       Access: Published
 //       Access: Published

+ 120 - 0
panda/src/grutil/pfmFile.cxx

@@ -564,6 +564,97 @@ calc_min_max(LVecBase3 &min_depth, LVecBase3 &max_depth) const {
   return any_points;
   return any_points;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: PfmFile::calc_autocrop
+//       Access: Published
+//  Description: Computes the minimum range of x and y across the PFM
+//               file that include all points.  If there are no points
+//               with no_data_value in the grid--that is, all points
+//               are included--then this will return (0, get_x_size(),
+//               0, get_y_size()).
+////////////////////////////////////////////////////////////////////
+bool PfmFile::
+calc_autocrop(int &x_begin, int &x_end, int &y_begin, int &y_end) const {
+  y_begin = 0;
+  while (is_row_empty(y_begin, 0, _x_size)) {
+    ++y_begin;
+    if (y_begin >= _y_size) {
+      // We've reached the end; the entire grid is empty.
+      x_begin = x_end = y_begin = y_end = 0;
+      return false;
+    }
+  }
+
+  y_end = _y_size;
+  while (is_row_empty(y_end - 1, 0, _x_size)) {
+    --y_end;
+    nassertr(y_end > y_begin, false);
+  }
+
+  // Now we've got the top and bottom bounds.
+  x_begin = 0;
+  while (is_column_empty(x_begin, y_begin, y_end)) {
+    ++x_begin;
+    nassertr(x_begin < _x_size, false);
+  }
+
+  x_end = _x_size;
+  while (is_column_empty(x_end - 1, y_begin, y_end)) {
+    --x_end;
+    nassertr(x_end > x_begin, false);
+  }
+
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PfmFile::is_row_empty
+//       Access: Published
+//  Description: Returns true if all of the points on row y, in the range
+//               [x_begin, x_end), are the no_data value, or false if
+//               any one of these points has a value.
+////////////////////////////////////////////////////////////////////
+bool PfmFile::
+is_row_empty(int y, int x_begin, int x_end) const {
+  nassertr(y >= 0 && y < _y_size && 
+           x_begin >= 0 && x_begin <= x_end && x_end <= _x_size, false);
+
+  if (!_has_no_data_value) {
+    return false;
+  }
+  for (int x = x_begin; x < x_end; ++x) {
+    if (_table[y * _x_size + x] != _no_data_value) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PfmFile::is_column_empty
+//       Access: Published
+//  Description: Returns true if all of the points on column x, from
+//               [y_begin, y_end), are the no_data value, or false if
+//               any one of these points has a value.
+////////////////////////////////////////////////////////////////////
+bool PfmFile::
+is_column_empty(int x, int y_begin, int y_end) const {
+  nassertr(x >= 0 && x < _x_size && 
+           y_begin >= 0 && y_begin <= y_end && y_end <= _y_size, false);
+
+  if (!_has_no_data_value) {
+    return false;
+  }
+  for (int y = y_begin; y < y_end; ++y) {
+    if (_table[y * _x_size + x] != _no_data_value) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PfmFile::resize
 //     Function: PfmFile::resize
 //       Access: Published
 //       Access: Published
@@ -772,6 +863,35 @@ merge(const PfmFile &other) {
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: PfmFile::apply_crop
+//       Access: Published
+//  Description: Reduces the PFM file to the cells in the rectangle
+//               bounded by (x_begin, x_end, y_begin, y_end), where
+//               the _end cells are not included.
+////////////////////////////////////////////////////////////////////
+void PfmFile::
+apply_crop(int x_begin, int x_end, int y_begin, int y_end) {
+  nassertv(x_begin >= 0 && x_begin <= x_end && x_end <= _x_size);
+  nassertv(y_begin >= 0 && y_begin <= y_end && y_end <= _y_size);
+
+  int new_x_size = x_end - x_begin;
+  int new_y_size = y_end - y_begin;
+  Table new_table;
+  int new_size = new_x_size * new_y_size;
+  new_table.insert(new_table.end(), new_size, LPoint3::zero());
+
+  for (int yi = 0; yi < new_y_size; ++yi) {
+    memcpy(&new_table[yi * new_x_size],
+           &_table[(yi + y_begin) * _x_size + x_begin],
+           new_x_size * sizeof(LPoint3));
+  }
+
+  _table.swap(new_table);
+  _x_size = new_x_size;
+  _y_size = new_y_size;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PfmFile::compute_planar_bounds
 //     Function: PfmFile::compute_planar_bounds
 //       Access: Published
 //       Access: Published

+ 6 - 0
panda/src/grutil/pfmFile.h

@@ -62,6 +62,11 @@ PUBLISHED:
 
 
   BLOCKING bool calc_average_point(LPoint3 &result, PN_stdfloat x, PN_stdfloat y, PN_stdfloat radius) const;
   BLOCKING bool calc_average_point(LPoint3 &result, PN_stdfloat x, PN_stdfloat y, PN_stdfloat radius) const;
   BLOCKING bool calc_min_max(LVecBase3 &min_points, LVecBase3 &max_points) const;
   BLOCKING bool calc_min_max(LVecBase3 &min_points, LVecBase3 &max_points) const;
+  BLOCKING bool calc_autocrop(int &x_begin, int &x_end, int &y_begin, int &y_end) const;
+  BLOCKING INLINE bool calc_autocrop(LVecBase4 &range) const;
+ 
+  bool is_row_empty(int y, int x_begin, int x_end) const;
+  bool is_column_empty(int x, int y_begin, int y_end) const;
 
 
   INLINE void set_zero_special(bool zero_special);
   INLINE void set_zero_special(bool zero_special);
   INLINE void set_no_data_value(const LPoint3 &no_data_value);
   INLINE void set_no_data_value(const LPoint3 &no_data_value);
@@ -75,6 +80,7 @@ PUBLISHED:
   BLOCKING void xform(const LMatrix4 &transform);
   BLOCKING void xform(const LMatrix4 &transform);
   BLOCKING void project(const Lens *lens);
   BLOCKING void project(const Lens *lens);
   BLOCKING void merge(const PfmFile &other);
   BLOCKING void merge(const PfmFile &other);
+  BLOCKING void apply_crop(int x_begin, int x_end, int y_begin, int y_end);
 
 
   BLOCKING PT(BoundingHexahedron) compute_planar_bounds(PN_stdfloat point_dist, PN_stdfloat sample_radius) const;
   BLOCKING PT(BoundingHexahedron) compute_planar_bounds(PN_stdfloat point_dist, PN_stdfloat sample_radius) const;
   BLOCKING PT(BoundingHexahedron) compute_planar_bounds(const LPoint2 &center, PN_stdfloat point_dist, PN_stdfloat sample_radius, bool points_only) const;
   BLOCKING PT(BoundingHexahedron) compute_planar_bounds(const LPoint2 &center, PN_stdfloat point_dist, PN_stdfloat sample_radius, bool points_only) const;

+ 19 - 0
pandatool/src/pfmprogs/pfmTrans.cxx

@@ -53,6 +53,17 @@ PfmTrans() {
      "change the number of points.",
      "change the number of points.",
      &PfmTrans::dispatch_int_pair, &_got_resize, &_resize);
      &PfmTrans::dispatch_int_pair, &_got_resize, &_resize);
 
 
+  add_option
+    ("crop", "xbegin,xend,ybegin,yend", 0,
+     "Crops the pfm file to the indicated subregion.",
+     &PfmTrans::dispatch_int_quad, &_got_crop, &_crop);
+
+  add_option
+    ("autocrop", "", 0,
+     "Automatically crops to the smallest possible rectangle that includes "
+     "all points.  Requires -z.",
+     &PfmTrans::dispatch_none, &_got_autocrop);
+
   add_option
   add_option
     ("rotate", "degrees", 0,
     ("rotate", "degrees", 0,
      "Rotates the pfm file the specified number of degrees counterclockwise, "
      "Rotates the pfm file the specified number of degrees counterclockwise, "
@@ -153,6 +164,14 @@ process_pfm(const Filename &input_filename, PfmFile &file) {
   file.set_vis_inverse(_got_vis_inverse);
   file.set_vis_inverse(_got_vis_inverse);
   file.set_vis_2d(_got_vis_2d);
   file.set_vis_2d(_got_vis_2d);
 
 
+  if (_got_autocrop) {
+    _got_crop = file.calc_autocrop(_crop[0], _crop[1], _crop[2], _crop[3]);
+  }
+
+  if (_got_crop) {
+    file.apply_crop(_crop[0], _crop[1], _crop[2], _crop[3]);
+  }    
+
   if (_got_resize) {
   if (_got_resize) {
     file.resize(_resize[0], _resize[1]);
     file.resize(_resize[0], _resize[1]);
   }
   }

+ 3 - 0
pandatool/src/pfmprogs/pfmTrans.h

@@ -56,6 +56,9 @@ private:
   bool _got_vis_2d;
   bool _got_vis_2d;
   bool _got_resize;
   bool _got_resize;
   int _resize[2];
   int _resize[2];
+  bool _got_crop;
+  int _crop[4];
+  bool _got_autocrop;
   int _rotate;
   int _rotate;
   bool _got_mirror_x;
   bool _got_mirror_x;
   bool _got_mirror_y;
   bool _got_mirror_y;

+ 32 - 0
pandatool/src/progbase/programBase.cxx

@@ -830,6 +830,38 @@ dispatch_int_pair(const string &opt, const string &arg, void *var) {
   return true;
   return true;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: ProgramBase::dispatch_int_quad
+//       Access: Protected, Static
+//  Description: Standard dispatch function for an option that takes
+//               a quad of integer parameters.  The data pointer is to
+//               an array of four integers.
+////////////////////////////////////////////////////////////////////
+bool ProgramBase::
+dispatch_int_quad(const string &opt, const string &arg, void *var) {
+  int *ip = (int *)var;
+
+  vector_string words;
+  tokenize(arg, words, ",");
+
+  bool okflag = false;
+  if (words.size() == 4) {
+    okflag =
+      string_to_int(words[0], ip[0]) &&
+      string_to_int(words[1], ip[1]) &&
+      string_to_int(words[1], ip[2]) &&
+      string_to_int(words[1], ip[3]);
+  }
+
+  if (!okflag) {
+    nout << "-" << opt
+         << " requires a quad of integers separated by a comma.\n";
+    return false;
+  }
+
+  return true;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ProgramBase::dispatch_double
 //     Function: ProgramBase::dispatch_double
 //       Access: Protected, Static
 //       Access: Protected, Static

+ 1 - 0
pandatool/src/progbase/programBase.h

@@ -87,6 +87,7 @@ protected:
   static bool dispatch_count(const string &opt, const string &arg, void *var);
   static bool dispatch_count(const string &opt, const string &arg, void *var);
   static bool dispatch_int(const string &opt, const string &arg, void *var);
   static bool dispatch_int(const string &opt, const string &arg, void *var);
   static bool dispatch_int_pair(const string &opt, const string &arg, void *var);
   static bool dispatch_int_pair(const string &opt, const string &arg, void *var);
+  static bool dispatch_int_quad(const string &opt, const string &arg, void *var);
   static bool dispatch_double(const string &opt, const string &arg, void *var);
   static bool dispatch_double(const string &opt, const string &arg, void *var);
   static bool dispatch_double_pair(const string &opt, const string &arg, void *var);
   static bool dispatch_double_pair(const string &opt, const string &arg, void *var);
   static bool dispatch_double_triple(const string &opt, const string &arg, void *var);
   static bool dispatch_double_triple(const string &opt, const string &arg, void *var);