[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [57970] branches/soc-2013-paint/source/ blender/editors/sculpt_paint: Fix old undo issue for projective texture paint

Antony Riakiotakis kalast at gmail.com
Wed Jul 3 21:21:26 CEST 2013


Revision: 57970
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=57970
Author:   psy-fi
Date:     2013-07-03 19:21:26 +0000 (Wed, 03 Jul 2013)
Log Message:
-----------
Fix old undo issue for projective texture paint

Undoing when faces accessed the same region in uv space could create
artifacts. The issue here is that buckets get their original colour
initialized with the colour that exists in the image at the point of
initialization. If two faces on different buckets accessed the same
region, then one bucket would get the modified colour as the original
colour. The undo push code simply checked if the final colour was
different than the original colour and as a result it could copy
modified colours in the undo stack.

Now simply push the undo stack when initializing the buckets. This
ensures that the stack contains really original colours. Of course there
is some overhead.

Also added mask code creation as part of the undo tile creation. The
accumulated mask should be in canvas space pixels, not on screen space
bucket pixels. I will next hook up the projection pixels to reference
this mask. This will hopefully solve cases like painting on mirrored
meshes or meshes that the same canvas region is accessed by many faces.

Modified Paths:
--------------
    branches/soc-2013-paint/source/blender/editors/sculpt_paint/paint_image.c
    branches/soc-2013-paint/source/blender/editors/sculpt_paint/paint_image_proj.c
    branches/soc-2013-paint/source/blender/editors/sculpt_paint/paint_intern.h

Modified: branches/soc-2013-paint/source/blender/editors/sculpt_paint/paint_image.c
===================================================================
--- branches/soc-2013-paint/source/blender/editors/sculpt_paint/paint_image.c	2013-07-03 19:21:19 UTC (rev 57969)
+++ branches/soc-2013-paint/source/blender/editors/sculpt_paint/paint_image.c	2013-07-03 19:21:26 UTC (rev 57970)
@@ -205,7 +205,7 @@
 	return NULL;
 }
 
-void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile, int y_tile)
+void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile, int y_tile, unsigned short **mask)
 {
 	ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE);
 	UndoImageTile *tile;
@@ -214,7 +214,7 @@
 	void *data;
 
 	/* check if tile is already pushed */
-	data = image_undo_find_tile(ima, ibuf, x_tile, y_tile, NULL, true);
+	data = image_undo_find_tile(ima, ibuf, x_tile, y_tile, mask, true);
 	if (data)
 		return data;
 	
@@ -226,6 +226,11 @@
 	tile->x = x_tile;
 	tile->y = y_tile;
 
+	/* add mask explicitly here */
+	if (mask)
+		*mask = tile->mask = MEM_callocN(sizeof(unsigned short) * IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE,
+		                         "UndoImageTile.mask");
+
 	allocsize = IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE * 4;
 	allocsize *= (ibuf->rect_float) ? sizeof(float) : sizeof(char);
 	tile->rect.pt = MEM_mapallocN(allocsize, "UndeImageTile.rect");
@@ -396,7 +401,7 @@
 
 	for (ty = tiley; ty <= tileh; ty++)
 		for (tx = tilex; tx <= tilew; tx++)
-			image_undo_push_tile(ima, ibuf, &tmpibuf, tx, ty);
+			image_undo_push_tile(ima, ibuf, &tmpibuf, tx, ty, NULL);
 
 	ibuf->userflags |= IB_BITMAPDIRTY;
 	

Modified: branches/soc-2013-paint/source/blender/editors/sculpt_paint/paint_image_proj.c
===================================================================
--- branches/soc-2013-paint/source/blender/editors/sculpt_paint/paint_image_proj.c	2013-07-03 19:21:19 UTC (rev 57969)
+++ branches/soc-2013-paint/source/blender/editors/sculpt_paint/paint_image_proj.c	2013-07-03 19:21:26 UTC (rev 57970)
@@ -176,6 +176,8 @@
 	ImBuf *ibuf;
 	ImagePaintPartialRedraw *partRedrawRect;
 	void **undoRect; /* only used to build undo tiles after painting */
+	void **maskRect; /* the mask accumulation must happen on canvas, not on space screen bucket.
+	                  * Here we store the mask rectangle */
 	int touch;
 } ProjPaintImage;
 
@@ -2167,7 +2169,7 @@
 
 /* One of the most important function for projection painting, since it selects the pixels to be added into each bucket.
  * initialize pixels from this face where it intersects with the bucket_index, optionally initialize pixels for removing seams */
-static void project_paint_face_init(const ProjPaintState *ps, const int thread_index, const int bucket_index, const int face_index, const int image_index, rctf *bucket_bounds, const ImBuf *ibuf, const short clamp_u, const short clamp_v)
+static void project_paint_face_init(const ProjPaintState *ps, const int thread_index, const int bucket_index, const int face_index, const int image_index, rctf *bucket_bounds, ImBuf *ibuf, const short clamp_u, const short clamp_v)
 {
 	/* Projection vars, to get the 3D locations into screen space  */
 	MemArena *arena = ps->arena_mt[thread_index];
@@ -2182,6 +2184,7 @@
 	int y; /* Image Y-Pixel */
 	float mask;
 	float uv[2]; /* Image floating point UV - same as x, y but from 0.0-1.0 */
+	int tile_width;
 
 	int side;
 	float *v1coSS, *v2coSS, *v3coSS; /* vert co screen-space, these will be assigned to mf->v1,2,3 or mf->v1,3,4 */
@@ -2252,6 +2255,8 @@
 		side = 0;
 	}
 
+	tile_width =  IMAPAINT_TILE_NUMBER(ibuf->x);
+
 	do {
 		if (side == 1) {
 			i1 = 0; i2 = 2; i3 = 3;
@@ -2284,6 +2289,9 @@
 #endif
 
 		if (pixel_bounds_array(uv_clip, &bounds_px, ibuf->x, ibuf->y, uv_clip_tot)) {
+			int tilex, tiley, tilew, tileh, tx, ty;
+			ImBuf *tmpibuf = NULL;
+			unsigned short *maskrect;
 
 			if (clamp_u) {
 				CLAMP(bounds_px.xmin, 0, ibuf->x);
@@ -2295,6 +2303,35 @@
 				CLAMP(bounds_px.ymax, 0, ibuf->y);
 			}
 
+			/* find the tiles covered by this face and make sure they are initialized */
+			imapaint_region_tiles(ibuf, bounds_px.xmin, bounds_px.ymin,
+			                      bounds_px.xmax - bounds_px.xmin, bounds_px.ymax - bounds_px.ymin,
+			                      &tilex, &tiley, &tilew, &tileh);
+
+			if (ps->thread_tot > 1)
+				BLI_lock_thread(LOCK_CUSTOM1);  /* Other threads could be modifying these vars */
+
+			for (ty = tiley; ty <= tileh; ty++) {
+				for (tx = tilex; tx <= tilew; tx++) {
+					int tileindex = tx + tile_width * ty;
+
+					if (!ps->projImages[image_index].undoRect[tileindex]) {
+						ps->projImages[image_index].undoRect[tileindex] = image_undo_push_tile(ps->projImages[image_index].ima, ibuf, &tmpibuf, tx, ty, &maskrect);
+						ps->projImages[image_index].maskRect[tileindex] = maskrect;
+						ibuf->userflags |= IB_BITMAPDIRTY;
+					}
+					else {
+
+					}
+				}
+			}
+
+			if (tmpibuf)
+				IMB_freeImBuf(tmpibuf);
+
+			if (ps->thread_tot > 1)
+				BLI_unlock_thread(LOCK_CUSTOM1);
+
 			/* clip face and */
 
 			has_isect = 0;
@@ -3237,11 +3274,17 @@
 	projIma = ps->projImages = (ProjPaintImage *)BLI_memarena_alloc(arena, sizeof(ProjPaintImage) * ps->image_tot);
 
 	for (node = image_LinkList, i = 0; node; node = node->next, i++, projIma++) {
+		int size;
 		projIma->ima = node->link;
 		projIma->touch = 0;
 		projIma->ibuf = BKE_image_acquire_ibuf(projIma->ima, NULL, NULL);
+		size = sizeof(void **) * IMAPAINT_TILE_NUMBER(projIma->ibuf->x) * IMAPAINT_TILE_NUMBER(projIma->ibuf->y);
 		projIma->partRedrawRect =  BLI_memarena_alloc(arena, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
 		memset(projIma->partRedrawRect, 0, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
+		projIma->undoRect = (void **) BLI_memarena_alloc(arena, size);
+		memset(projIma->undoRect, 0, size);
+		projIma->maskRect = (void **) BLI_memarena_alloc(arena, size);
+		memset(projIma->maskRect, 0, size);
 	}
 
 	/* we have built the array, discard the linked list */
@@ -3263,8 +3306,9 @@
 	}
 }
 
-static void project_paint_undo_push(ProjPaintState *ps)
+static void project_paint_undo_push(ProjPaintState *UNUSED(ps))
 {
+#if 0
 	/* build undo data from original pixel colors */
 	if (U.uiflag & USER_GLOBALUNDO) {
 		ProjPixel *projPixel;
@@ -3328,7 +3372,7 @@
 
 					if (last_projIma->undoRect[tile_index] == NULL) {
 						/* add the undo tile from the modified image, then write the original colors back into it */
-						tilerect = last_projIma->undoRect[tile_index] = image_undo_push_tile(last_projIma->ima, last_projIma->ibuf, is_float ? (&tmpibuf_float) : (&tmpibuf), x_tile, y_tile);
+						tilerect = last_projIma->undoRect[tile_index] = image_undo_push_tile(last_projIma->ima, last_projIma->ibuf, is_float ? (&tmpibuf_float) : (&tmpibuf), x_tile, y_tile, NULL);
 					}
 					else {
 						tilerect = last_projIma->undoRect[tile_index];
@@ -3351,6 +3395,7 @@
 		if (tmpibuf) IMB_freeImBuf(tmpibuf);
 		if (tmpibuf_float) IMB_freeImBuf(tmpibuf_float);
 	}
+#endif
 }
 
 
@@ -3359,6 +3404,7 @@
 	int a;
 	ProjPaintImage *projIma;
 
+	image_undo_remove_masks();
 	project_paint_undo_push(ps);
 
 	/* dereference used image buffers */

Modified: branches/soc-2013-paint/source/blender/editors/sculpt_paint/paint_intern.h
===================================================================
--- branches/soc-2013-paint/source/blender/editors/sculpt_paint/paint_intern.h	2013-07-03 19:21:19 UTC (rev 57969)
+++ branches/soc-2013-paint/source/blender/editors/sculpt_paint/paint_intern.h	2013-07-03 19:21:26 UTC (rev 57970)
@@ -142,7 +142,7 @@
 
 int image_texture_paint_poll(struct bContext *C);
 void *image_undo_find_tile(struct Image *ima, struct ImBuf *ibuf, int x_tile, int y_tile, unsigned short **mask, bool validate);
-void *image_undo_push_tile(struct Image *ima, struct ImBuf *ibuf, struct ImBuf **tmpibuf, int x_tile, int y_tile);
+void *image_undo_push_tile(struct Image *ima, struct ImBuf *ibuf, struct ImBuf **tmpibuf, int x_tile, int y_tile,  unsigned short **);
 void image_undo_remove_masks(void);
 void image_undo_restore(struct bContext *C, struct ListBase *lb);
 void image_undo_free(struct ListBase *lb);




More information about the Bf-blender-cvs mailing list