[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