[Bf-blender-cvs] [44e104e] cycles-ptex-49: Improve Ptex filter border updates
Nicholas Bishop
noreply at git.blender.org
Thu Feb 12 14:16:48 CET 2015
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. @@
More information about the Bf-blender-cvs
mailing list