[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [53932] trunk/blender/source/blender: 3D mapping for projective texture painting (only for draw brush).

Antony Riakiotakis kalast at gmail.com
Sun Jan 20 22:32:16 CET 2013


Revision: 53932
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=53932
Author:   psy-fi
Date:     2013-01-20 21:32:14 +0000 (Sun, 20 Jan 2013)
Log Message:
-----------
3D mapping for projective texture painting (only for draw brush). Useful
to draw with procedural textures on surface of object. 2D painting will
still paint as if tiled.

When we unify the paint systems, the texture sampling functions will
need to be changed. Sculpt uses a slightly different system that passes
both screen and 3d coordinates to the sampling function. This commit
however is not too disrupting for that however so it can go in now.

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/BKE_brush.h
    trunk/blender/source/blender/blenkernel/intern/brush.c
    trunk/blender/source/blender/editors/sculpt_paint/paint_image.c
    trunk/blender/source/blender/editors/sculpt_paint/paint_image_2d.c
    trunk/blender/source/blender/makesrna/intern/rna_brush.c

Modified: trunk/blender/source/blender/blenkernel/BKE_brush.h
===================================================================
--- trunk/blender/source/blender/blenkernel/BKE_brush.h	2013-01-20 18:17:01 UTC (rev 53931)
+++ trunk/blender/source/blender/blenkernel/BKE_brush.h	2013-01-20 21:32:14 UTC (rev 53932)
@@ -67,7 +67,8 @@
 float BKE_brush_curve_strength(struct Brush *br, float p, const float len); /* used for sculpt */
 
 /* sampling */
-void BKE_brush_sample_tex(const struct Scene *scene, struct Brush *brush, const float xy[2], float rgba[4], const int thread);
+void BKE_brush_sample_tex(const struct Scene *scene, struct Brush *brush, const float sampleco[3], float rgba[4], const int thread);
+void BKE_brush_sample_tex_2D(const struct Scene *scene, struct Brush *brush, const float xy[2], float rgba[4], const int thread);
 void BKE_brush_imbuf_new(const struct Scene *scene, struct Brush *brush, short flt, short texfalloff, int size,
                          struct ImBuf **imbuf, int use_color_correction);
 

Modified: trunk/blender/source/blender/blenkernel/intern/brush.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/brush.c	2013-01-20 18:17:01 UTC (rev 53931)
+++ trunk/blender/source/blender/blenkernel/intern/brush.c	2013-01-20 21:32:14 UTC (rev 53932)
@@ -471,8 +471,8 @@
 	return 0;
 }
 
-/* Brush Sampling */
-void BKE_brush_sample_tex(const Scene *scene, Brush *brush, const float xy[2], float rgba[4], const int thread)
+/* Brush Sampling for 3d brushes. Currently used for texture painting only, but should be generalized */
+void BKE_brush_sample_tex(const Scene *scene, Brush *brush, const float sampleco[3], float rgba[4], const int thread)
 {
 	MTex *mtex = &brush->mtex;
 
@@ -481,6 +481,44 @@
 		int hasrgb;
 		const int radius = BKE_brush_size_get(scene, brush);
 
+		if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) {
+			copy_v3_v3(co, sampleco);
+		} else {
+			co[0] = sampleco[0] / radius;
+			co[1] = sampleco[1] / radius;
+			co[2] = 0.0f;
+		}
+
+		hasrgb = externtex(mtex, co, &tin, &tr, &tg, &tb, &ta, thread);
+
+		if (hasrgb) {
+			rgba[0] = tr;
+			rgba[1] = tg;
+			rgba[2] = tb;
+			rgba[3] = ta;
+		}
+		else {
+			rgba[0] = tin;
+			rgba[1] = tin;
+			rgba[2] = tin;
+			rgba[3] = 1.0f;
+		}
+	}
+	else {
+		rgba[0] = rgba[1] = rgba[2] = rgba[3] = 1.0f;
+	}
+}
+
+/* Brush Sampling for 2D brushes. when we unify the brush systems this will be necessarily a separate function */
+void BKE_brush_sample_tex_2D(const Scene *scene, Brush *brush, const float xy[2], float rgba[4], const int thread)
+{
+	MTex *mtex = &brush->mtex;
+
+	if (mtex && mtex->tex) {
+		float co[3], tin, tr, tg, tb, ta;
+		int hasrgb;
+		const int radius = BKE_brush_size_get(scene, brush);
+
 		co[0] = xy[0] / radius;
 		co[1] = xy[1] / radius;
 		co[2] = 0.0f;
@@ -505,7 +543,8 @@
 	}
 }
 
-/* TODO, use define for 'texfall' arg */
+/* TODO, use define for 'texfall' arg
+ * NOTE: only used for 2d brushes currently! */
 void BKE_brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texfall, int bufsize, ImBuf **outbuf, int use_color_correction)
 {
 	ImBuf *ibuf;
@@ -544,10 +583,10 @@
 					dstf[3] = alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius);
 				}
 				else if (texfall == 1) {
-					BKE_brush_sample_tex(scene, brush, xy, dstf, 0);
+					BKE_brush_sample_tex_2D(scene, brush, xy, dstf, 0);
 				}
 				else {
-					BKE_brush_sample_tex(scene, brush, xy, rgba, 0);
+					BKE_brush_sample_tex_2D(scene, brush, xy, rgba, 0);
 					mul_v3_v3v3(dstf, rgba, brush_rgb);
 					dstf[3] = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius);
 				}
@@ -574,11 +613,11 @@
 					dst[3] = FTOCHAR(alpha_f);
 				}
 				else if (texfall == 1) {
-					BKE_brush_sample_tex(scene, brush, xy, rgba, 0);
+					BKE_brush_sample_tex_2D(scene, brush, xy, rgba, 0);
 					rgba_float_to_uchar(dst, rgba);
 				}
 				else if (texfall == 2) {
-					BKE_brush_sample_tex(scene, brush, xy, rgba, 0);
+					BKE_brush_sample_tex_2D(scene, brush, xy, rgba, 0);
 					mul_v3_v3(rgba, brush->rgb);
 					alpha_f = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius);
 
@@ -587,7 +626,7 @@
 					dst[3] = FTOCHAR(alpha_f);
 				}
 				else {
-					BKE_brush_sample_tex(scene, brush, xy, rgba, 0);
+					BKE_brush_sample_tex_2D(scene, brush, xy, rgba, 0);
 					alpha_f = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius);
 
 					dst[0] = crgb[0];

Modified: trunk/blender/source/blender/editors/sculpt_paint/paint_image.c
===================================================================
--- trunk/blender/source/blender/editors/sculpt_paint/paint_image.c	2013-01-20 18:17:01 UTC (rev 53931)
+++ trunk/blender/source/blender/editors/sculpt_paint/paint_image.c	2013-01-20 21:32:14 UTC (rev 53932)
@@ -355,7 +355,7 @@
 
 typedef struct ProjPixel {
 	float projCoSS[2]; /* the floating point screen projection of this pixel */
-	
+	float worldCoSS[3];
 	/* Only used when the airbrush is disabled.
 	 * Store the max mask value to avoid painting over an area with a lower opacity
 	 * with an advantage that we can avoid touching the pixel at all, if the 
@@ -1526,6 +1526,11 @@
 	}
 }
 
+static bool project_paint_supports_3d_mapping(Brush *brush)
+{
+	return (brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) && (brush->imagepaint_tool == PAINT_TOOL_DRAW);
+}
+
 /* run this function when we know a bucket's, face's pixel can be initialized,
  * return the ProjPixel which is added to 'ps->bucketRect[bucket_index]' */
 static ProjPixel *project_paint_uvpixel_init(
@@ -1537,6 +1542,7 @@
         const int face_index,
         const int image_index,
         const float pixelScreenCo[4],
+        const float world_spaceCo[3],
         const int side,
         const float w[3])
 {
@@ -1565,6 +1571,9 @@
 	}
 	
 	/* screenspace unclamped, we could keep its z and w values but don't need them at the moment */
+	if(project_paint_supports_3d_mapping(ps->brush))
+		copy_v3_v3(projPixel->worldCoSS, world_spaceCo);
+
 	copy_v2_v2(projPixel->projCoSS, pixelScreenCo);
 	
 	projPixel->x_px = x_px;
@@ -2374,6 +2383,7 @@
 	
 	float *uv1co, *uv2co, *uv3co; /* for convenience only, these will be assigned to tf->uv[0],1,2 or tf->uv[0],2,3 */
 	float pixelScreenCo[4];
+	bool do_3d_mapping = project_paint_supports_3d_mapping(ps->brush);
 	
 	rcti bounds_px; /* ispace bounds */
 	/* vars for getting uvspace bounds */
@@ -2449,7 +2459,7 @@
 		v1coSS = ps->screenCoords[(*(&mf->v1 + i1))];
 		v2coSS = ps->screenCoords[(*(&mf->v1 + i2))];
 		v3coSS = ps->screenCoords[(*(&mf->v1 + i3))];
-		
+
 		/* This funtion gives is a concave polyline in UV space from the clipped quad and tri*/
 		project_bucket_clip_face(
 		        is_ortho, bucket_bounds,
@@ -2501,9 +2511,9 @@
 						else          screen_px_from_persp(uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w);
 						
 						/* a pity we need to get the worldspace pixel location here */
-						if (do_clip) {
+						if (do_clip || do_3d_mapping) {
 							interp_v3_v3v3v3(wco, ps->dm_mvert[(*(&mf->v1 + i1))].co, ps->dm_mvert[(*(&mf->v1 + i2))].co, ps->dm_mvert[(*(&mf->v1 + i3))].co, w);
-							if (ED_view3d_clipping_test(ps->rv3d, wco, TRUE)) {
+							if (do_clip && ED_view3d_clipping_test(ps->rv3d, wco, TRUE)) {
 								continue; /* Watch out that no code below this needs to run */
 							}
 						}
@@ -2520,9 +2530,10 @@
 							if (mask > 0.0f) {
 								BLI_linklist_prepend_arena(
 								        bucketPixelNodes,
-								        project_paint_uvpixel_init(ps, arena, ibuf, x, y, mask, face_index, image_index, pixelScreenCo, side, w),
-								        arena
-								        );
+								        project_paint_uvpixel_init(ps, arena, ibuf, x, y, mask, face_index,
+												image_index, pixelScreenCo, wco, side, w),
+												arena
+												);
 							}
 						}
 						
@@ -2725,11 +2736,11 @@
 											}
 											
 											/* a pity we need to get the worldspace pixel location here */
-											if (do_clip) {
+											if (do_clip || do_3d_mapping) {
 												if (side) interp_v3_v3v3v3(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v3].co, ps->dm_mvert[mf->v4].co, w);
 												else      interp_v3_v3v3v3(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v2].co, ps->dm_mvert[mf->v3].co, w);
 
-												if (ED_view3d_clipping_test(ps->rv3d, wco, TRUE)) {
+												if (do_clip && ED_view3d_clipping_test(ps->rv3d, wco, TRUE)) {
 													continue; /* Watch out that no code below this needs to run */
 												}
 											}
@@ -2739,7 +2750,7 @@
 											if (mask > 0.0f) {
 												BLI_linklist_prepend_arena(
 												        bucketPixelNodes,
-												        project_paint_uvpixel_init(ps, arena, ibuf, x, y, mask, face_index, image_index, pixelScreenCo, side, w),
+												        project_paint_uvpixel_init(ps, arena, ibuf, x, y, mask, face_index, image_index, pixelScreenCo, wco, side, w),
 												        arena
 												        );
 											}
@@ -4105,7 +4116,7 @@
 
 				/*if (dist < radius) {*/ /* correct but uses a sqrtf */
 				if (dist_nosqrt <= radius_squared) {
-					float samplecos[2];
+					float samplecos[3];
 					dist = sqrtf(dist_nosqrt);
 
 					falloff = BKE_brush_curve_strength_clamp(ps->brush, dist, radius);
@@ -4114,9 +4125,11 @@
 						if (ps->brush->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) {
 							sub_v2_v2v2(samplecos, projPixel->projCoSS, pos);
 						}
-						else {
-							copy_v2_v2(samplecos, projPixel->projCoSS);
-						}
+						/* taking 3d copy to account for 3D mapping too. It gets concatenated during sampling */
+						else if (project_paint_supports_3d_mapping(ps->brush))
+							copy_v3_v3(samplecos, projPixel->worldCoSS);
+						else
+							copy_v3_v3(samplecos, projPixel->projCoSS);
 					}
 
 					if (falloff > 0.0f) {
@@ -5008,7 +5021,9 @@
 	ps->pixel_sizeof = project_paint_pixel_sizeof(ps->tool);
 	BLI_assert(ps->pixel_sizeof >= sizeof(ProjPixel));
 
-	ps->do_masking = (brush->flag & BRUSH_AIRBRUSH || brush->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) ? false : true;
+	/* disable for 3d mapping also because painting on mirrored mesh can create "stripes" */
+	ps->do_masking = (brush->flag & BRUSH_AIRBRUSH || brush->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW ||
+						project_paint_supports_3d_mapping(brush)) ? false : true;

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list