Commit: 44e104e25cb125da29c6270741cc76b3d35414da
Author: Nicholas Bishop
Date:   Thu Feb 12 13:49:24 2015 +0100
Branches: cycles-ptex-49
https://developer.blender.org/rB44e104e25cb125da29c6270741cc76b3d35414da

Improve Ptex filter border updates

- Texture paint looks better now

- Still need to fix corners

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

M       extern/ptex/BPX_rect.h
M       extern/ptex/bpx_c_api.cpp
M       source/blender/blenkernel/BKE_ptex.h
M       source/blender/blenkernel/intern/bke_ptex.c
M       source/blender/editors/sculpt_paint/paint_image_proj.c
M       source/blender/imbuf/IMB_imbuf_types.h
M       source/blender/makesrna/intern/rna_image.c

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

diff --git a/extern/ptex/BPX_rect.h b/extern/ptex/BPX_rect.h
index d3dc43e..367f545 100644
--- a/extern/ptex/BPX_rect.h
+++ b/extern/ptex/BPX_rect.h
@@ -45,7 +45,7 @@ typedef struct BPXRectSideAdj {
  * structure. Could be nicer to reuse rcti. */
 
 typedef struct BPXRect {
-       BPXRectSideAdj adj[4];
+       BPXRectSideAdj adj[BPX_RECT_NUM_SIDES];
 
        /* Note: begin is inclusive, end is exclusive to match
         * OIIO::ROI */
@@ -57,6 +57,9 @@ typedef struct BPXRect {
        int yend;
 } BPXRect;
 
+bool bpx_rect_contains_point(const BPXRect *rect, const int x,
+                                                        const int y);
+
 #ifdef __cplusplus
 }  /* extern "C" */
 #endif
diff --git a/extern/ptex/bpx_c_api.cpp b/extern/ptex/bpx_c_api.cpp
index b891a53..7e57371 100644
--- a/extern/ptex/bpx_c_api.cpp
+++ b/extern/ptex/bpx_c_api.cpp
@@ -1169,3 +1169,10 @@ void BPX_packed_layout_delete(BPXPackedLayout *layout)
 {
        delete layout;
 }
+
+bool bpx_rect_contains_point(const BPXRect *rect, const int x,
+                                                        const int y)
+{
+       return (x >= rect->xbegin && x < rect->xend &&
+                       y >= rect->ybegin && y < rect->yend);
+}
diff --git a/source/blender/blenkernel/BKE_ptex.h 
b/source/blender/blenkernel/BKE_ptex.h
index d406bc1..b0f5f37 100644
--- a/source/blender/blenkernel/BKE_ptex.h
+++ b/source/blender/blenkernel/BKE_ptex.h
@@ -24,6 +24,7 @@
 #include "DNA_meshdata_types.h"
 
 struct DerivedMesh;
+struct GSet;
 struct Image;
 struct Mesh;
 struct Object;
@@ -100,4 +101,9 @@ bool BKE_ptex_import(struct Mesh *me, const char 
filepath[]);
 
 void BKE_ptex_image_mark_for_update(struct Mesh *me, const int layer_offset);
 
+/* Update borders for the set of BPXRects in rects
+ *
+ * Return true if successful, false otherwise */
+bool BKE_ptex_filter_borders_update(struct Image *image, struct GSet *rects);
+
 #endif
diff --git a/source/blender/blenkernel/intern/bke_ptex.c 
b/source/blender/blenkernel/intern/bke_ptex.c
index 524acef..b56c97c 100644
--- a/source/blender/blenkernel/intern/bke_ptex.c
+++ b/source/blender/blenkernel/intern/bke_ptex.c
@@ -35,6 +35,7 @@
 #include "DNA_mesh_types.h"
 #include "DNA_modifier_types.h"
 
+#include "BLI_ghash.h"
 #include "BLI_path_util.h"
 #include "BLI_math_base.h"
 #include "BLI_math_interp.h"
@@ -449,33 +450,6 @@ static void ptex_adj_edge(const BKEPtexEdgeAdj *adj,
        }
 }
 
-static void ptex_filter_borders_update(ImBuf *ibuf, const Mesh *me)
-{
-       BPXImageBuf *bpx_buf = IMB_imbuf_as_bpx_image_buf(ibuf);
-       const BPXRect *rects = ibuf->ptex_regions;
-       int i;
-
-       BLI_assert(bpx_buf);
-
-       for (i = 0; i < me->totpoly; i++) {
-               const MPoly *p = &me->mpoly[i];
-               int j;
-
-               for (j = 0; j < p->totloop; j++) {
-                       const int cur_loop = p->loopstart + j;
-
-                       const BPXRect *dst_rect = &rects[cur_loop];
-                       if (!BPX_rect_borders_update(bpx_buf, dst_rect, rects,
-                                                                               
 sizeof(BPXRect)))
-                       {
-                               BLI_assert(!"TODO");
-                       }
-               }
-       }
-
-       BPX_image_buf_free(bpx_buf);
-}
-
 static bool bpx_type_desc_to_mptex_data_type(const BPXTypeDesc type_desc,
                                                                                
         MPtexDataType *data_type)
 {
@@ -590,6 +564,82 @@ static struct BPXPackedLayout 
*bke_ptex_layout_from_mesh(const Mesh *me,
        return layout;
 }
 
+static bool bke_ptex_imbuf_filter_borders_update(ImBuf *ibuf, GSet *rects)
+{
+       BPXImageBuf *bpx_buf;
+       GSetIterator iter;
+       BPXRect *all_rects;
+       int rects_stride;
+       bool result = true;
+
+       if (!ibuf) {
+               return false;
+       }
+
+       bpx_buf = IMB_imbuf_as_bpx_image_buf(ibuf);
+       if (!bpx_buf) {
+               return false;
+       }
+
+       all_rects = ibuf->ptex_regions;
+       rects_stride = sizeof(*ibuf->ptex_regions);
+
+       if (rects) {
+               /* TODO(nicholasbishop): this is not a great
+                * solution. Adjacent edges should probably just be updated
+                * together or something... also need to consider corners */
+               GSet *adj_rects = BLI_gset_ptr_new("GSet adj_rects");
+
+               GSET_ITER (iter, rects) {
+                       const BPXRect *rect = BLI_gsetIterator_getKey(&iter);
+                       int side;
+
+                       for (side = 0; side < BPX_RECT_NUM_SIDES; side++) {
+                               const int adj_index = rect->adj[side].index;
+                               if (adj_index != BPX_RECT_SIDE_ADJ_NONE) {
+                                       BLI_gset_add(adj_rects, 
&all_rects[adj_index]);
+                               }
+                       }
+
+                       if (!BPX_rect_borders_update(bpx_buf, rect, all_rects,
+                                                                               
 rects_stride))
+                       {
+                               result = false;
+                               break;
+                       }
+               }
+
+               GSET_ITER (iter, adj_rects) {
+                       const BPXRect *rect = BLI_gsetIterator_getKey(&iter);
+
+                       if (!BPX_rect_borders_update(bpx_buf, rect, all_rects,
+                                                                               
 rects_stride))
+                       {
+                               result = false;
+                               break;
+                       }
+               }
+
+               BLI_gset_free(adj_rects, NULL);
+       }
+       else {
+               int i;
+               for (i = 0; i < ibuf->num_ptex_regions; i++) {
+                       const BPXRect *rect = &ibuf->ptex_regions[i];
+                       if (!BPX_rect_borders_update(bpx_buf, rect, all_rects,
+                                                                               
 rects_stride))
+                       {
+                               result = false;
+                               break;
+                       }
+               }
+       }
+
+       BPX_image_buf_free(bpx_buf);
+
+       return result;
+}
+
 /* TODO(nicholasbishop): sync up with code in imb_ptex.c */
 /* TODO(nicholasbishop): should function apart, Image stuff really is
  * separate from the packing stuff */
@@ -656,7 +706,9 @@ static bool ptex_pack_loops(Image **image_r, Mesh *me, 
MLoopPtex *loop_ptex,
        }
 
        BPX_image_buf_free(bpx_dst);
-       ptex_filter_borders_update(ibuf, me);
+       if (!bke_ptex_imbuf_filter_borders_update(ibuf, NULL)) {
+               BLI_assert(!"TODO");
+       }
 
        if (texel_info.num_channels < 4) {
                IMB_rectfill_alpha(ibuf, 1);
@@ -1098,6 +1150,27 @@ bool BKE_ptex_update_from_image(MLoopPtex *loop_ptex, 
const int totloop)
        return true;
 }
 
+bool BKE_ptex_filter_borders_update(Image *image, GSet *rects)
+{
+       ImBuf *ibuf;
+       void *lock;
+       bool result;
+
+       if (!image || !rects) {
+               return false;
+       }
+
+       ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
+       if (!ibuf) {
+               return false;
+       }
+
+       result = bke_ptex_imbuf_filter_borders_update(ibuf, rects);
+       BKE_image_release_ibuf(image, ibuf, lock);
+
+       return result;
+}
+
 #else
 /* Stubs if WITH_PTEX is not defined */
 
@@ -1135,4 +1208,10 @@ bool BKE_ptex_update_from_image(MLoopPtex 
*UNUSED(loop_ptex),
        return false;
 }
 
+bool BKE_ptex_filter_borders_update(MLoopPtex *UNUSED(loop_ptex),
+                                                                       Mesh 
*UNUSED(me))
+{
+       return false;
+}
+
 #endif
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c 
b/source/blender/editors/sculpt_paint/paint_image_proj.c
index 8fa2d99..c26c6be 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -131,7 +131,11 @@ BLI_INLINE unsigned char f_to_char(const float val)
 #define PROJ_BOUNDBOX_SQUARED  (PROJ_BOUNDBOX_DIV * PROJ_BOUNDBOX_DIV)
 
 //#define PROJ_DEBUG_PAINT 1
+
+/* TODO(nicholasbishop): investigate if this should become a runtime
+ * option for Ptex */
 //#define PROJ_DEBUG_NOSEAMBLEED 1
+
 //#define PROJ_DEBUG_PRINT_CLIP 1
 #define PROJ_DEBUG_WINCLIP 1
 
@@ -168,6 +172,7 @@ BLI_INLINE unsigned char f_to_char(const float val)
 
 #define PROJ_BUCKET_NULL        0
 #define PROJ_BUCKET_INIT        (1 << 0)
+#define PROJ_BUCKET_PTEX_UPDATE (1 << 1)
 // #define PROJ_BUCKET_CLONE_INIT      (1<<1)
 
 /* used for testing doubles, if a point is on a line etc */
@@ -239,6 +244,7 @@ typedef struct ProjPaintState {
        MemArena *arena_mt[BLENDER_MAX_THREADS]; /* for multithreading, the 
first item is sometimes used for non threaded cases too */
        LinkNode **bucketRect;              /* screen sized 2D array, each 
pixel has a linked list of ProjPixel's */
        LinkNode **bucketFaces;             /* bucketRect aligned array 
linkList of faces overlapping each bucket */
+       GSet **bucketPtexRects;             /* TODO(nicholasbishop): add 
comment */
        unsigned char *bucketFlags;         /* store if the bucks have been 
initialized  */
 #ifndef PROJ_DEBUG_NOSEAMBLEED
        char *faceSeamFlags;                /* store info about faces, if they 
are initialized etc*/
@@ -2401,6 +2407,43 @@ static bool IsectPoly2Df_twoside(const float pt[2], 
float uv[][2], const int tot
        return 1;
 }
 
+static void project_paint_bucket_ptex_rects_init(const ProjPaintState *ps,
+                                                                               
                 ImBuf *ibuf,
+                                                                               
                 const int bucket_index)
+{
+       const LinkNode *pixel_node = NULL;
+       GSet **set = NULL;
+
+       if (!ibuf || !ibuf->num_ptex_regions || !ps->bucketPtexRects) {
+               return;
+       }
+
+       /* Initialize GSet */
+       set = &ps->bucketPtexRects[bucket_index];
+       if (*set) {
+               /* Already initialized */
+               return;
+       }
+       (*set) = BLI_gset_ptr_new("proj paint bucket");
+
+       /* TODO(nicholasbishop): optimize */
+       for (pixel_node = ps->bucketRect[bucket_index]; pixel_node;
+                pixel_node = pixel_node->next) {
+               const ProjPixel *pixel = pixel_node->link;
+               int i;
+
+               for (i = 0; i < ibuf->num_ptex_regions; i++) {
+                       BPXRect *r = &ibuf->ptex_regions[i];
+                       const int px = pixel->x_px;
+                       const int py = pixel->y_px;
+                       if (bpx_rect_contains_point(r, px, py)) {
+                               BLI_gset_add(*set, r);
+                               break;
+                       }
+               }
+       }
+}
+
 /* One of the most important function for projection painting,
  * since it selects the pixels to be added into each bucket.
  *
@@ -2618,7 +2661,7 @@ static void project_paint_face_init(
                }
        } while (side--);
 
-
+       project_paint_bucket_ptex_rects_init(ps, ibuf, bucket_index);
 
 #ifndef PROJ_DEBUG_NOSEAMBLEED
        if (ps->seam_bleed_px > 0.0f) {
@@ -3811,6 +3854,7 @@ static void project_paint_begin(ProjPaintState *ps)
        const int diameter = 2 * BKE_brush_size_get(ps->scene, ps->brush);
 
        bool reset_threads = true;
+       int num_buckets;
 
        /* ---- end defines ---- */
 
@@ -3871,10 +3915,15 @@ static void project_paint_begin(ProjPaintState *ps)
        CLAMP(ps->buckets_x, PROJ_BUCKET_RECT_MIN, PROJ_BUCKET_RECT_MAX);
        CLAMP(ps->buckets_y, PROJ_BUCKET_RECT_MIN, PROJ_BUCKET_RECT_MAX);
 
-       ps->bucketRect = MEM_callocN(sizeof(LinkNode *) * ps->buckets_x * 
ps->buckets_y, "paint-bucketRect");
-       ps->bucketFaces = MEM_callocN(sizeof(LinkNode *) * ps->buckets_x * 
ps->buckets_y, "paint-bucketFaces");
+       num_buckets = ps->buckets_x * ps->buckets_y;
+
+       ps->bucketRect = MEM_callocN(sizeof(LinkNode *) * num_buckets, 
"paint-bucketRect");
+       ps->bucketFaces = MEM_callocN(sizeof(LinkNode *) * num_buckets, 
"paint-bucketFaces");
 
-       ps->bucketFlags = MEM_callocN(sizeof(char) * ps->buckets_x * 
ps->buckets_y, "paint-bucketFaces");
+       /* TODO(nicholasbishop): don't allocate if not ptex painting */
+       ps->bucketPtexRects = MEM_callocN(sizeof(GSet *) * num_bucket

@@ Diff output truncated at 10240 characters. @@

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

Reply via email to