Ver Fonte

wip: PfmFile::calc_bilinear_point()

David Rose há 12 anos atrás
pai
commit
a99e543f05

+ 6 - 14
panda/src/distort/projectionScreen.cxx

@@ -593,17 +593,13 @@ recompute_geom(Geom *geom, const LMatrix4 &rel_mat) {
     LPoint3 uvw = film * to_uv;
 
     if (good && _has_undist_lut) {
-      int x_size = _undist_lut.get_x_size();
-      int y_size = _undist_lut.get_y_size();
-      
-      int dist_xi = (int)cfloor(uvw[0] * (PN_float32)x_size);
-      int dist_yi = (int)cfloor(uvw[1] * (PN_float32)y_size);
-      if (!_undist_lut.has_point(dist_xi, y_size - 1 - dist_yi)) {
+      LPoint3 p;
+      if (!_undist_lut.calc_bilinear_point(p, uvw[0], 1.0 - uvw[1])) {
         // Point is missing.
         uvw.set(0, 0, 0);
         good = false;
       } else {
-        uvw = _undist_lut.get_point(dist_xi, y_size - 1 - dist_yi);
+        uvw = p;
         uvw[1] = 1.0 - uvw[1];
       }
     }
@@ -767,17 +763,13 @@ make_mesh_geom(const Geom *geom, Lens *lens, LMatrix4 &rel_mat) {
       // Rescale these to [0, 1].
       LPoint3 uvw = film * lens_to_uv;
       
-      int x_size = _undist_lut.get_x_size();
-      int y_size = _undist_lut.get_y_size();
-      
-      int dist_xi = (int)cfloor(uvw[0] * (PN_float32)x_size);
-      int dist_yi = (int)cfloor(uvw[1] * (PN_float32)y_size);
-      if (!_undist_lut.has_point(dist_xi, y_size - 1 - dist_yi)) {
+      LPoint3 p;
+      if (!_undist_lut.calc_bilinear_point(p, uvw[0], 1.0 - uvw[1])) {
         // Point is missing.
         uvw.set(0, 0, 0);
         good = false;
       } else {
-        uvw = _undist_lut.get_point(dist_xi, y_size - 1 - dist_yi);
+        uvw = p;
         uvw[1] = 1.0 - uvw[1];
       }
 

+ 3 - 7
panda/src/grutil/pfmVizzer.cxx

@@ -1022,17 +1022,13 @@ transform_point(LPoint3f &point) const {
   }
 
   if (_undist_lut != NULL) {
-    int x_size = _undist_lut->get_x_size();
-    int y_size = _undist_lut->get_y_size();
-
-    int dist_xi = (int)cfloor(point[0] * (PN_float32)x_size);
-    int dist_yi = (int)cfloor(point[1] * (PN_float32)y_size);
-    if (!_undist_lut->has_point(dist_xi, y_size - 1 - dist_yi)) {
+    LPoint3 p;
+    if (!_undist_lut->calc_bilinear_point(p, point[0], 1.0 - point[1])) {
       // Point is missing.
       point.set(0, 0, 0);
       success = false;
     } else {
-      point = _undist_lut->get_point(dist_xi, y_size - 1 - dist_yi);
+      point = p;
       point[1] = 1.0 - point[1];
     }
   }

+ 54 - 7
panda/src/pnmimage/pfmFile.I

@@ -196,20 +196,67 @@ modify_point2(int x, int y) {
 ////////////////////////////////////////////////////////////////////
 INLINE const LPoint3f &PfmFile::
 get_point(int x, int y) const {
+  return get_point3(x, y);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PfmFile::set_point
+//       Access: Published
+//  Description: Replaces the 3-component point value at the indicated
+//               point.  In a 1-channel image, the channel value is in
+//               the x component.
+////////////////////////////////////////////////////////////////////
+INLINE void PfmFile::
+set_point(int x, int y, const LVecBase3f &point) {
+  set_point3(x, y, point);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PfmFile::set_point
+//       Access: Published
+//  Description: Replaces the 3-component point value at the indicated
+//               point.  In a 1-channel image, the channel value is in
+//               the x component.
+////////////////////////////////////////////////////////////////////
+INLINE void PfmFile::
+set_point(int x, int y, const LVecBase3d &point) {
+  set_point3(x, y, point);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PfmFile::modify_point
+//       Access: Published
+//  Description: Returns a modifiable 3-component point value at the
+//               indicated point.
+////////////////////////////////////////////////////////////////////
+INLINE LPoint3f &PfmFile::
+modify_point(int x, int y) {
+  return modify_point3(x, y);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PfmFile::get_point3
+//       Access: Published
+//  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_point3(int x, int y) const {
   nassertr(x >= 0 && x < _x_size &&
            y >= 0 && y < _y_size, LPoint3f::zero());
   return *(LPoint3f *)&_table[(y * _x_size + x) * _num_channels];
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: PfmFile::set_point
+//     Function: PfmFile::set_point3
 //       Access: Published
 //  Description: Replaces the 3-component point value at the indicated
 //               point.  In a 1-channel image, the channel value is in
 //               the x component.
 ////////////////////////////////////////////////////////////////////
 INLINE void PfmFile::
-set_point(int x, int y, const LVecBase3f &point) {
+set_point3(int x, int y, const LVecBase3f &point) {
   nassertv(!point.is_nan());
   nassertv(x >= 0 && x < _x_size &&
            y >= 0 && y < _y_size);
@@ -233,25 +280,25 @@ set_point(int x, int y, const LVecBase3f &point) {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: PfmFile::set_point
+//     Function: PfmFile::set_point3
 //       Access: Published
 //  Description: Replaces the 3-component point value at the indicated
 //               point.  In a 1-channel image, the channel value is in
 //               the x component.
 ////////////////////////////////////////////////////////////////////
 INLINE void PfmFile::
-set_point(int x, int y, const LVecBase3d &point) {
-  set_point(x, y, LCAST(PN_float32, point));
+set_point3(int x, int y, const LVecBase3d &point) {
+  set_point3(x, y, LCAST(PN_float32, point));
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: PfmFile::modify_point
+//     Function: PfmFile::modify_point3
 //       Access: Published
 //  Description: Returns a modifiable 3-component point value at the
 //               indicated point.
 ////////////////////////////////////////////////////////////////////
 INLINE LPoint3f &PfmFile::
-modify_point(int x, int y) {
+modify_point3(int x, int y) {
 #ifndef NDEBUG
   static LPoint3f dummy_value = LPoint3f::zero();
   nassertr(x >= 0 && x < _x_size &&

+ 56 - 8
panda/src/pnmimage/pfmFile.cxx

@@ -610,6 +610,56 @@ calc_average_point(LPoint3f &result, PN_float32 x, PN_float32 y, PN_float32 radi
   return true;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: PfmFile::calc_bilinear_point
+//       Access: Published
+//  Description: Computes the weighted average of the four nearest
+//               points to the floating-point index (x, y).  Returns
+//               true if the point has any contributors, false if the
+//               point is unknown.
+////////////////////////////////////////////////////////////////////
+bool PfmFile::
+calc_bilinear_point(LPoint3f &result, PN_float32 x, PN_float32 y) const {
+  result = LPoint3f::zero();
+
+  x *= _x_size;
+  y *= _y_size;
+
+  int min_x = int(floor(x));
+  int min_y = int(floor(y));
+
+  PN_float32 frac_x = x - min_x;
+  PN_float32 frac_y = y - min_y;
+
+  LPoint3f p00, p01, p10, p11;
+  PN_float32 w00 = 0.0, w01 = 0.0, w10 = 0.0, w11 = 0.0;
+
+  if (has_point(min_x, min_y)) {
+    w00 = (1.0 - frac_y) * (1.0 - frac_x);
+    p00 = get_point(min_x, min_y);
+  }
+  if (has_point(min_x + 1, min_y)) {
+    w10 = (1.0 - frac_y) * frac_x;
+    p10 = get_point(min_x + 1, min_y);
+  }
+  if (has_point(min_x, min_y + 1)) {
+    w01 = frac_y * (1.0 - frac_x);
+    p01 = get_point(min_x, min_y + 1);
+  }
+  if (has_point(min_x + 1, min_y + 1)) {
+    w11 = frac_y * frac_x;
+    p11 = get_point(min_x + 1, min_y + 1);
+  }
+
+  PN_float32 net_w = w00 + w01 + w10 + w11;
+  if (net_w == 0.0) {
+    return false;
+  }
+
+  result = (p00 * w00 + p01 * w01 + p10 * w10 + p11 * w11) / net_w;
+  return true;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: PfmFile::calc_min_max
 //       Access: Published
@@ -1093,14 +1143,12 @@ forward_distort(const PfmFile &dist, PN_float32 scale_factor) {
       if (!dist_p->has_point(xi, yi)) {
         continue;
       }
-      LPoint2f uv = dist_p->get_point2(xi, yi);
-      int dist_xi = (int)cfloor(uv[0] * (PN_float32)working_x_size);
-      int dist_yi = (int)cfloor(uv[1] * (PN_float32)working_y_size);
-      if (!source_p->has_point(dist_xi, working_y_size - 1 - dist_yi)) {
+      LPoint2 uv = dist_p->get_point2(xi, yi);
+      LPoint3 p;
+      if (!calc_bilinear_point(p, uv[0], 1.0 - uv[1])) {
         continue;
       }
-
-      result.set_point(xi, working_y_size - 1 - yi, source_p->get_point(dist_xi, working_y_size - 1 - dist_yi));
+      result.set_point(xi, working_y_size - 1 - yi, p);
     }
   }
 
@@ -1302,8 +1350,8 @@ clear_to_texcoords(int x_size, int y_size) {
 
   for (int yi = 0; yi < _y_size; ++yi) {
     for (int xi = 0; xi < _x_size; ++xi) {
-      LPoint3f uv(PN_float32(xi) * uv_scale[0] + 0.5,
-                  PN_float32(yi) * uv_scale[1] + 0.5, 
+      LPoint3f uv((PN_float32(xi) + 0.5) * uv_scale[0],
+                  (PN_float32(yi) + 0.5) * uv_scale[1],
                   0.0f);
       set_point(xi, yi, uv);
     }

+ 5 - 0
panda/src/pnmimage/pfmFile.h

@@ -69,6 +69,10 @@ PUBLISHED:
   INLINE void set_point(int x, int y, const LVecBase3f &point);
   INLINE void set_point(int x, int y, const LVecBase3d &point);
   INLINE LPoint3f &modify_point(int x, int y);
+  INLINE const LPoint3f &get_point3(int x, int y) const;
+  INLINE void set_point3(int x, int y, const LVecBase3f &point);
+  INLINE void set_point3(int x, int y, const LVecBase3d &point);
+  INLINE LPoint3f &modify_point3(int x, int y);
   INLINE const LPoint4f &get_point4(int x, int y) const;
   INLINE void set_point4(int x, int y, const LVecBase4f &point);
   INLINE void set_point4(int x, int y, const LVecBase4d &point);
@@ -80,6 +84,7 @@ PUBLISHED:
   void fill(const LPoint4f &value);
 
   BLOCKING bool calc_average_point(LPoint3f &result, PN_float32 x, PN_float32 y, PN_float32 radius) const;
+  BLOCKING bool calc_bilinear_point(LPoint3f &result, PN_float32 x, PN_float32 y) const;
   BLOCKING bool calc_min_max(LVecBase3f &min_points, LVecBase3f &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(LVecBase4f &range) const;