Commit: 9b7bb2960b89fe3d2c3a35c5be51db8289e1ecaf
Author: Nicholas Bishop
Date:   Fri Feb 13 17:30:04 2015 +0100
Branches: cycles-ptex-49
https://developer.blender.org/rB9b7bb2960b89fe3d2c3a35c5be51db8289e1ecaf

Improve filtering across Ptex corners

===================================================================

M       intern/ptex/bpx_c_api.cpp

===================================================================

diff --git a/intern/ptex/bpx_c_api.cpp b/intern/ptex/bpx_c_api.cpp
index 1b1e095..4a47550 100644
--- a/intern/ptex/bpx_c_api.cpp
+++ b/intern/ptex/bpx_c_api.cpp
@@ -320,24 +320,249 @@ static void bpx_create_border(ImageBuf &buf,
        bpx_write_border(buf, dst_edge_roi, side_buf, transform);
 }
 
-static const int CORNER_NUM_SOURCES = 2;
-static bool bpx_corner_average(ImageBuf &buf, const int dst_co[2],
-                                                          const int 
src_co[CORNER_NUM_SOURCES][2])
+static const BPXRect &bpx_get_rect(const int i, const void *rects_v,
+                                                                  const int 
stride)
+{
+       const unsigned char *rects_uc = static_cast<const unsigned 
char*>(rects_v);
+       return *reinterpret_cast<const BPXRect *>(rects_uc + stride * i);
+}
+
+static void bpx_rect_corner_xy(const BPXRect &rect, const BPXRectSide side,
+                                                          int &r_x, int &r_y, 
const bool border)
+{
+       switch (side) {
+               case BPX_RECT_SIDE_BOTTOM:
+                       r_x = rect.xbegin;
+                       r_y = rect.ybegin;
+                       if (border) {
+                               r_x--;
+                               r_y--;
+                       }
+                       break;
+
+               case BPX_RECT_SIDE_RIGHT:
+                       r_x = rect.xend - 1;
+                       r_y = rect.ybegin;
+                       if (border) {
+                               r_x++;
+                               r_y--;
+                       }
+                       break;
+
+               case BPX_RECT_SIDE_TOP:
+                       r_x = rect.xend - 1;
+                       r_y = rect.yend - 1;
+                       if (border) {
+                               r_x++;
+                               r_y++;
+                       }
+                       break;
+
+               case BPX_RECT_SIDE_LEFT:
+                       r_x = rect.xbegin;
+                       r_y = rect.yend - 1;
+                       if (border) {
+                               r_x--;
+                               r_y++;
+                       }
+                       break;
+
+               case BPX_RECT_NUM_SIDES:
+                       break;
+       }
+}
+
+static BPXRectSide bpx_rect_side_wrap(const BPXRectSide start,
+                                                                         const 
int offset)
+{
+       const int start_i = static_cast<int>(start);
+       const int num = static_cast<int>(BPX_RECT_NUM_SIDES);
+       const int new_i = (start_i + num + offset) % num;
+       return static_cast<BPXRectSide>(new_i);
+}
+
+struct BPXCornerIter {
+public:
+       enum Direction {
+               CW,
+               CCW
+       };
+
+       BPXCornerIter(const void *rects_v, const int rects_stride,
+                                 const BPXRect &orig_rect, const BPXRectSide 
orig_side,
+                                 const Direction direction)
+               : rects_v(rects_v),
+                 rects_stride(rects_stride),
+                 orig_rect(&orig_rect),
+                 cur_rect(&orig_rect),
+                 cur_side(orig_side),
+                 direction(direction)
+       {}
+
+       // Return true if the iterator successfully moves to another face,
+       // false if the iterator has reached the end
+       bool next()
+       {
+               if (!cur_rect) {
+                       return false;
+               }
+               const BPXRectSideAdj *adj;
+               if (direction == CW) {
+                       adj = &cur_rect->adj[cur_side];
+               }
+               else {
+                       adj = &cur_rect->adj[bpx_rect_side_wrap(cur_side, -1)];
+               }
+
+               if (adj->index == BPX_RECT_SIDE_ADJ_NONE) {
+                       return false;
+               }
+               const BPXRect *next_rect = &bpx_get_rect(adj->index, rects_v,
+                                                                               
                 rects_stride);
+               if (orig_rect == next_rect) {
+                       return false;
+               }
+
+               cur_rect = next_rect;
+               if (direction == CW) {
+                       cur_side = bpx_rect_side_wrap(adj->side, 1);
+               }
+               else {
+                       cur_side = adj->side;
+               }
+               return true;
+       }
+
+       void flip_direction() {
+               orig_rect = cur_rect;
+               if (direction == CW) {
+                       direction = CCW;
+               }
+               else {
+                       direction = CW;
+               }
+       }
+
+       const BPXRect &get_rect() const {
+               return *cur_rect;
+       }
+
+       BPXRectSide get_side() const {
+               return cur_side;
+       }
+
+private:
+       const void *rects_v;
+       const int rects_stride;
+
+       const BPXRect *orig_rect;
+       const BPXRect *cur_rect;
+       BPXRectSide cur_side;
+
+       Direction direction;
+};
+
+// TODO
+struct BPXRectPixel {
+       int x;
+       int y;
+       int bx;
+       int by;
+};
+
+// TODO, better comments
+static void bpx_update_corner(ImageBuf &buf,
+                                                         const void *rects_v,
+                                                         const int 
rects_stride,
+                                                         const BPXRect 
&orig_rect,
+                                                         const BPXRectSide 
orig_side)
 {
        const int nchannels = buf.nchannels();
-       std::vector<float> a(nchannels, 0.0f);
-       std::vector<float> b(nchannels, 0.0f);
+       std::vector<float> pixel(nchannels);
+
+       BPXCornerIter iter(rects_v, rects_stride,
+                                          orig_rect, orig_side,
+                                          BPXCornerIter::CW);
+       while (iter.next()) {
+               // Iterate as far as possible on one direction. Not needed if
+               // the faces loop all the way around the corner, but needed
+               // for boundaries.
+       }
+
+       std::vector<BPXRectPixel> corners;
+       int my_corner_index = 0;
+
+       // Iterate in the other direction to get all the pixels
+       iter.flip_direction();
+       do {
+               // Find rect corner coordinates
+               BPXRectPixel p;
+               bpx_rect_corner_xy(iter.get_rect(), iter.get_side(),
+                                                  p.x, p.y, false);
+               bpx_rect_corner_xy(iter.get_rect(), iter.get_side(),
+                                                  p.bx, p.by, true);
+
+               if (&iter.get_rect() == &orig_rect) {
+                       my_corner_index = corners.size();
+               }
+               corners.push_back(p);
+       } while (iter.next());
 
-       buf.getpixel(src_co[0][0], src_co[0][1], a.data());
-       buf.getpixel(src_co[1][0], src_co[1][1], b.data());
+       std::vector<float> accum(nchannels, 0.0f);
+       float fac = 1.0f;
 
-       for (int i = 0; i < nchannels; i++) {
-               a[i] = (a[i] + b[i]) * 0.5f;
+       if (corners.size() == 1) {
+               const BPXRectPixel &c = corners[0];
+               buf.getpixel(c.x, c.y, pixel.data());
+       }
+       else if (corners.size() == 2) {
+               // Copy the other rects corner
+               const BPXRectPixel &c = corners[1 - my_corner_index];
+               buf.getpixel(c.x, c.y, pixel.data());
+       }
+       else if (corners.size() == 3) {
+               // Accumulate all three
+               fac = 1.0f / 3.0f;
+               for (int i = 0; i < corners.size(); i++) {
+                       const BPXRectPixel &c = corners[i];
+                       buf.getpixel(c.x, c.y, pixel.data());
+                       for (int c = 0; c < nchannels; c++) {
+                               accum[c] += pixel[c];
+                       }
+               }
+       }
+       else if (corners.size() == 4) {
+               // Special case of the final else block, only one pixel to
+               // accumulate
+               const BPXRectPixel &c = corners[(my_corner_index + 2) % 4];
+               buf.getpixel(c.x, c.y, pixel.data());
+       }
+       else {
+               // Accumulate all but self and adjacent
+               fac = 1.0f / (corners.size() - 3);
+               for (int i = 0; i < corners.size(); i++) {
+                       if (i != my_corner_index &&
+                               ((i + 1) % corners.size()) != my_corner_index &&
+                               ((i + corners.size() - 1) % corners.size()) != 
my_corner_index)
+                       {
+                               const BPXRectPixel &c = corners[i];
+                               buf.getpixel(c.x, c.y, pixel.data());
+                               for (int c = 0; c < nchannels; c++) {
+                                       accum[c] += pixel[c];
+                               }
+                       }
+               }
        }
 
-       buf.setpixel(dst_co[0], dst_co[1], a.data());
+       if (corners.size() == 3 || corners.size() >= 5) {
+               for (int c = 0; c < nchannels; c++) {
+                       pixel[c] = accum[c] * fac;
+               }
+       }
 
-       return true;
+       // Copy pixel into the corner
+       const BPXRectPixel &c = corners[my_corner_index];
+       buf.setpixel(c.bx, c.by, pixel.data());
 }
 
 bool BPX_rect_borders_update(BPXImageBuf *bpx_buf, const BPXRect *dst_rect,
@@ -350,8 +575,6 @@ bool BPX_rect_borders_update(BPXImageBuf *bpx_buf, const 
BPXRect *dst_rect,
        ImageBuf &buf = *bpx_image_buf_to_oiio_image_buf(bpx_buf);
        const ROI dst_roi = bpx_rect_to_oiio_roi(*dst_rect);
 
-       const unsigned char *rects_uc = static_cast<const unsigned 
char*>(rects_v);
-
        // Sample adjacent regions to create filter edges
        for (int i = 0; i < BPX_RECT_NUM_SIDES; i++) {
                const BPXRectSide dst_side = static_cast<BPXRectSide>(i);
@@ -369,8 +592,7 @@ bool BPX_rect_borders_update(BPXImageBuf *bpx_buf, const 
BPXRect *dst_rect,
 
                }
                else {
-                       const int offset = adj.index * rects_stride;
-                       src_rect = reinterpret_cast<const BPXRect *>(rects_uc + 
offset);
+                       src_rect = &bpx_get_rect(adj.index, rects_v, 
rects_stride);
                        src_edge.side = adj.side;
                        src_edge.reverse = true;
                }
@@ -381,31 +603,8 @@ bool BPX_rect_borders_update(BPXImageBuf *bpx_buf, const 
BPXRect *dst_rect,
                // Also update in the other direction. TODO(nicholasbishop):
                // names are a bit confusing now
                bpx_create_border(buf, src_roi, src_edge, dst_roi, dst_edge);
-       }
 
-       // Average adjacent borders to fill in
-       // corners. TODO(nicholasbishop): need to improve this, it is
-       // noticable after all
-       const int dst_co[BPX_RECT_NUM_SIDES][2] = {
-               {dst_roi.xbegin - 1, dst_roi.ybegin - 1},
-               {dst_roi.xend      , dst_roi.ybegin - 1},
-               {dst_roi.xend      , dst_roi.yend      },
-               {dst_roi.xbegin - 1, dst_roi.yend      }
-       };
-       const int src_co[BPX_RECT_NUM_SIDES][CORNER_NUM_SOURCES][2] = {
-               {{dst_co[0][0] + 1, dst_co[0][1]    },
-                {dst_co[0][0],     dst_co[0][1] + 1}},
-               {{dst_co[1][0] - 1, dst_co[1][1]},
-                {dst_co[1][0],     dst_co[1][1] + 1}},
-               {{dst_co[2][0] - 1, dst_co[2][1]},
-                {dst_co[2][0],     dst_co[2][1] - 1}},
-               {{dst_co[3][0] + 1, dst_co[3][1]},
-                {dst_co[3][0],     dst_co[3][1] - 1}}
-       };
-       for (int i = 0; i < BPX_RECT_NUM_SIDES; i++) {
-               if (!bpx_corner_average(buf, dst_co[i], src_co[i])) {
-                       return false;
-               }
+               bpx_update_corner(buf, rects_v, rects_stride, *dst_rect, 
dst_side);
        }
 
        return true;

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to