Browse Source

extend compute_planar_bounds()

David Rose 14 years ago
parent
commit
61fa1e4c26
2 changed files with 127 additions and 82 deletions
  1. 117 73
      panda/src/grutil/pfmFile.cxx
  2. 10 9
      panda/src/grutil/pfmFile.h

+ 117 - 73
panda/src/grutil/pfmFile.cxx

@@ -318,7 +318,7 @@ write(ostream &out) {
 //               value cannot be determined.
 ////////////////////////////////////////////////////////////////////
 bool PfmFile::
-calc_average_point(LPoint3 &result, double x, double y, double radius) const {
+calc_average_point(LPoint3 &result, PN_stdfloat x, PN_stdfloat y, PN_stdfloat radius) const {
   result = LPoint3::zero();
 
   int min_x = int(ceil(x - radius));
@@ -456,27 +456,27 @@ 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;
+  PN_stdfloat from_x0, from_x1, from_y0, from_y1;
 
-  double x_scale = 1.0;
-  double y_scale = 1.0;
+  PN_stdfloat x_scale = 1.0;
+  PN_stdfloat y_scale = 1.0;
 
   if (new_x_size > 1) {
-    x_scale = (double)(_x_size - 1) / (double)(new_x_size - 1);
+    x_scale = (PN_stdfloat)(_x_size - 1) / (PN_stdfloat)(new_x_size - 1);
   }
   if (new_y_size > 1) {
-    y_scale = (double)(_y_size - 1) / (double)(new_y_size - 1);
+    y_scale = (PN_stdfloat)(_y_size - 1) / (PN_stdfloat)(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_y1 = min(from_y1, (PN_stdfloat) _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);
+      from_x1 = min(from_x1, (PN_stdfloat) _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).
@@ -594,6 +594,18 @@ merge(const PfmFile &other) {
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: PfmFile::compute_planar_bounds
+//       Access: Published
+//  Description: This version of this method exists for temporary
+//               backward compatibility only.
+////////////////////////////////////////////////////////////////////
+PT(BoundingHexahedron) PfmFile::
+compute_planar_bounds(PN_stdfloat point_dist, PN_stdfloat sample_radius) const {
+  return compute_planar_bounds(LPoint2::zero(), point_dist, sample_radius, false);
+}
+
+
 ////////////////////////////////////////////////////////////////////
 //     Function: PfmFile::compute_planar_bounds
 //       Access: Published
@@ -606,18 +618,20 @@ merge(const PfmFile &other) {
 //               around the center (cx - pd, cx + pd) and so on, to
 //               approximate the plane of the surface.  Then all of
 //               the points are projected into that plane and the
-//               bounding volume within that plane is determined.
+//               bounding volume of the entire mesh within that plane
+//               is determined.  If points_only is true, the bounding
+//               volume of only those four points is determined.
 //
-//               point_dist and sample_radius are in UV space, i.e. in
-//               the range 0..1.
+//               center, 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 {
+compute_planar_bounds(const LPoint2 &center, PN_stdfloat point_dist, PN_stdfloat sample_radius, bool points_only) const {
   LPoint3 p0, p1, p2, p3;
-  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);
-  compute_sample_point(p3, 0.5 - point_dist, 0.5 - point_dist, sample_radius);
+  compute_sample_point(p0, center[0] + point_dist, center[1] - point_dist, sample_radius);
+  compute_sample_point(p1, center[0] + point_dist, center[1] + point_dist, sample_radius);
+  compute_sample_point(p2, center[0] - point_dist, center[1] + point_dist, sample_radius);
+  compute_sample_point(p3, center[0] - point_dist, center[1] - point_dist, sample_radius);
 
   LPoint3 normal;
 
@@ -639,60 +653,111 @@ compute_planar_bounds(double point_dist, double sample_radius) const {
 
   normal.normalize();
 
+  LVector3 up = (p1 - p0) + (p2 - p3);
+  LPoint3 pcenter = ((p0 + p1 + p2 + p3) * 0.25);
+
   // Compute the transform necessary to rotate all of the points into
   // the Y = 0 plane.
   LMatrix4 rotate;
-  look_at(rotate, normal, p1 - p0);
+  look_at(rotate, normal, up);
 
   LMatrix4 rinv;
   rinv.invert_from(rotate);
 
-  LPoint3 trans = p0 * rinv;
+  LPoint3 trans = pcenter * rinv;
   rinv.set_row(3, -trans);
   rotate.invert_from(rinv);
 
   // Now determine the minmax.
   PN_stdfloat min_x, min_y, min_z, max_x, max_y, max_z;
   bool got_point = false;
-  Table::const_iterator ti;
-  for (ti = _table.begin(); ti != _table.end(); ++ti) {
-    if (_zero_special && (*ti) == LPoint3::zero()) {
-      continue;
+  if (points_only) {
+    LPoint3 points[4] = {
+      p0 * rinv,
+      p1 * rinv,
+      p2 * rinv,
+      p3 * rinv,
+    };
+    for (int i = 0; i < 4; ++i) {
+      const LPoint3 &point = points[i];
+      if (!got_point) {
+        min_x = point[0];
+        min_y = point[1];
+        min_z = point[2];
+        max_x = point[0];
+        max_y = point[1];
+        max_z = point[2];
+        got_point = true;
+      } else {
+        min_x = min(min_x, point[0]);
+        min_y = min(min_y, point[1]);
+        min_z = min(min_z, point[2]);
+        max_x = max(max_x, point[0]);
+        max_y = max(max_y, point[1]);
+        max_z = max(max_z, point[2]);
+      }
     }
-    LPoint3 point = (*ti) * rinv;
-    if (!got_point) {
-      min_x = point[0];
-      min_y = point[1];
-      min_z = point[2];
-      max_x = point[0];
-      max_y = point[1];
-      max_z = point[2];
-      got_point = true;
-    } else {
-      min_x = min(min_x, point[0]);
-      min_y = min(min_y, point[1]);
-      min_z = min(min_z, point[2]);
-      max_x = max(max_x, point[0]);
-      max_y = max(max_y, point[1]);
-      max_z = max(max_z, point[2]);
+
+  } else {
+    Table::const_iterator ti;
+    for (ti = _table.begin(); ti != _table.end(); ++ti) {
+      if (_zero_special && (*ti) == LPoint3::zero()) {
+        continue;
+      }
+      LPoint3 point = (*ti) * rinv;
+      if (!got_point) {
+        min_x = point[0];
+        min_y = point[1];
+        min_z = point[2];
+        max_x = point[0];
+        max_y = point[1];
+        max_z = point[2];
+        got_point = true;
+      } else {
+        min_x = min(min_x, point[0]);
+        min_y = min(min_y, point[1]);
+        min_z = min(min_z, point[2]);
+        max_x = max(max_x, point[0]);
+        max_y = max(max_y, point[1]);
+        max_z = max(max_z, point[2]);
+      }
     }
   }
-
+    
   PT(BoundingHexahedron) bounds = new BoundingHexahedron
     (LPoint3(min_x, min_y, min_z), LPoint3(max_x, min_y, min_z),
      LPoint3(min_x, min_y, max_z), LPoint3(max_x, min_y, max_z),
      LPoint3(min_x, max_y, min_z), LPoint3(max_x, max_y, min_z),
      LPoint3(min_x, max_y, max_z), LPoint3(max_x, max_y, max_z));
-  bounds->write(cerr);
 
   // Rotate the bounding volume back into the original space of the
   // screen.
   bounds->xform(rotate);
-  bounds->write(cerr);
 
   return bounds;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: PfmFile::compute_sample_point
+//       Access: Published
+//  Description: Computes the average of all the point within
+//               sample_radius (manhattan distance) and the indicated
+//               point.
+//
+//               The point coordinates are given in UV space, in the
+//               range 0..1.
+////////////////////////////////////////////////////////////////////
+void PfmFile::
+compute_sample_point(LPoint3 &result,
+                     PN_stdfloat x, PN_stdfloat y, PN_stdfloat sample_radius) const {
+  x *= _x_size;
+  y *= _y_size;
+  PN_stdfloat xr = sample_radius * _x_size;
+  PN_stdfloat yr = sample_radius * _y_size;
+  box_filter_region(result, x - xr, y - yr, x + xr, y + yr);
+}
+
+
 ////////////////////////////////////////////////////////////////////
 //     Function: PfmFile::generate_vis_points
 //       Access: Published
@@ -1016,27 +1081,6 @@ make_vis_mesh_geom(GeomNode *gnode, bool inverted) const {
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     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(LPoint3 &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
@@ -1048,9 +1092,9 @@ compute_sample_point(LPoint3 &result,
 ////////////////////////////////////////////////////////////////////
 void PfmFile::
 box_filter_region(LPoint3 &result,
-                  double x0, double y0, double x1, double y1) const {
+                  PN_stdfloat x0, PN_stdfloat y0, PN_stdfloat x1, PN_stdfloat y1) const {
   result = LPoint3::zero();
-  double coverage = 0.0;
+  PN_stdfloat coverage = 0.0;
 
   if (x1 < x0 || y1 < y0) {
     return;
@@ -1059,7 +1103,7 @@ box_filter_region(LPoint3 &result,
 
   int y = (int)y0;
   // Get the first (partial) row
-  box_filter_line(result, coverage, x0, y, x1, (double)(y+1)-y0);
+  box_filter_line(result, coverage, x0, y, x1, (PN_stdfloat)(y+1)-y0);
 
   int y_last = (int)y1;
   if (y < y_last) {
@@ -1071,7 +1115,7 @@ box_filter_region(LPoint3 &result,
     }
 
     // Get the final (partial) row
-    double y_contrib = y1 - (double)y_last;
+    PN_stdfloat y_contrib = y1 - (PN_stdfloat)y_last;
     if (y_contrib > 0.0001) {
       box_filter_line(result, coverage, x0, y, x1, y_contrib);
     }
@@ -1088,11 +1132,11 @@ box_filter_region(LPoint3 &result,
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 void PfmFile::
-box_filter_line(LPoint3 &result, double &coverage,
-                double x0, int y, double x1, double y_contrib) const {
+box_filter_line(LPoint3 &result, PN_stdfloat &coverage,
+                PN_stdfloat x0, int y, PN_stdfloat x1, PN_stdfloat 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);
+  box_filter_point(result, coverage, x, y, (PN_stdfloat)(x+1)-x0, y_contrib);
 
   int x_last = (int)x1;
   if (x < x_last) {
@@ -1104,7 +1148,7 @@ box_filter_line(LPoint3 &result, double &coverage,
     }
 
     // Get the final (partial) xel
-    double x_contrib = x1 - (double)x_last;
+    PN_stdfloat x_contrib = x1 - (PN_stdfloat)x_last;
     if (x_contrib > 0.0001) {
       box_filter_point(result, coverage, x, y, x_contrib, y_contrib);
     }
@@ -1117,14 +1161,14 @@ box_filter_line(LPoint3 &result, double &coverage,
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 void PfmFile::
-box_filter_point(LPoint3 &result, double &coverage,
-                 int x, int y, double x_contrib, double y_contrib) const {
+box_filter_point(LPoint3 &result, PN_stdfloat &coverage,
+                 int x, int y, PN_stdfloat x_contrib, PN_stdfloat y_contrib) const {
   const LPoint3 &point = get_point(x, y);
   if (_zero_special && point == LPoint3::zero()) {
     return;
   }
 
-  double contrib = x_contrib * y_contrib;
+  PN_stdfloat contrib = x_contrib * y_contrib;
   result += point * contrib;
   coverage += contrib;
 }

+ 10 - 9
panda/src/grutil/pfmFile.h

@@ -55,7 +55,7 @@ PUBLISHED:
   INLINE void set_point(int x, int y, const LVecBase3 &point);
   INLINE LPoint3 &modify_point(int x, int y);
 
-  BLOCKING bool calc_average_point(LPoint3 &result, double x, double y, double 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;
 
   INLINE void set_zero_special(bool zero_special);
@@ -67,7 +67,10 @@ PUBLISHED:
   BLOCKING void project(const Lens *lens);
   BLOCKING void merge(const PfmFile &other);
 
-  BLOCKING PT(BoundingHexahedron) compute_planar_bounds(double point_dist, double 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;
+  void compute_sample_point(LPoint3 &result,
+                            PN_stdfloat x, PN_stdfloat y, PN_stdfloat sample_radius) const;
 
   INLINE void set_vis_inverse(bool vis_inverse);
   INLINE bool get_vis_inverse() const;
@@ -89,14 +92,12 @@ PUBLISHED:
 private:
   void make_vis_mesh_geom(GeomNode *gnode, bool inverted) const;
 
-  void compute_sample_point(LPoint3 &result,
-                            double x, double y, double sample_radius) const;
   void box_filter_region(LPoint3 &result,
-                         double x0, double y0, double x1, double y1) const;
-  void box_filter_line(LPoint3 &result, double &coverage,
-                       double x0, int y, double x1, double y_contrib) const;
-  void box_filter_point(LPoint3 &result, double &coverage,
-                        int x, int y, double x_contrib, double y_contrib) const;
+                         PN_stdfloat x0, PN_stdfloat y0, PN_stdfloat x1, PN_stdfloat y1) const;
+  void box_filter_line(LPoint3 &result, PN_stdfloat &coverage,
+                       PN_stdfloat x0, int y, PN_stdfloat x1, PN_stdfloat y_contrib) const;
+  void box_filter_point(LPoint3 &result, PN_stdfloat &coverage,
+                        int x, int y, PN_stdfloat x_contrib, PN_stdfloat y_contrib) const;
 
   class MiniGridCell {
   public: