diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2013-04-30 13:59:40 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2013-04-30 13:59:40 +0400 |
commit | 9461af89f1da9d4d1f4eef952084bbc7711376d7 (patch) | |
tree | a37b94ed22a4657de052dd4377e5900681d7016a /source | |
parent | f01986c97c9b5f3fce9e11dadc1e89f8266732f3 (diff) |
Fix #35141: stencil and 3D texture mode did not work with 2D image paint.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/BKE_brush.h | 9 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/brush.c | 96 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_image_2d.c | 106 |
3 files changed, 108 insertions, 103 deletions
diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h index 863d7b05693..0ae243483dd 100644 --- a/source/blender/blenkernel/BKE_brush.h +++ b/source/blender/blenkernel/BKE_brush.h @@ -38,6 +38,7 @@ struct Brush; struct ImBuf; struct ImagePool; struct Main; +struct rctf; struct Scene; struct wmOperator; // enum CurveMappingPreset; @@ -77,12 +78,12 @@ float BKE_brush_curve_strength(struct Brush *br, float p, const float len); /* u /* sampling */ float BKE_brush_sample_tex_3D(const Scene *scene, struct Brush *br, const float point[3], float rgba[4], const int thread, struct ImagePool *pool); -float BKE_brush_sample_tex_2D(const struct Scene *scene, struct Brush *brush, const float xy[2], - float rgba[4]); float BKE_brush_sample_masktex(const Scene *scene, struct Brush *br, const float point[3], const int thread, struct ImagePool *pool); -void BKE_brush_imbuf_new(const struct Scene *scene, struct Brush *brush, short flt, short texfalloff, int size, - struct ImBuf **imbuf, bool use_color_correction, bool use_brush_alpha); +void BKE_brush_imbuf_new(const struct Scene *scene, struct Brush *brush, short flt, + short texfalloff, int size, struct ImBuf **imbuf, + bool use_color_correction, bool use_brush_alpha, + struct ImagePool *pool, struct rctf *mapping); /* texture */ unsigned int *BKE_brush_gen_texture_cache(struct Brush *br, int half_side); diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index c24aab1629c..41eb641f899 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -38,6 +38,7 @@ #include "BLI_math.h" #include "BLI_blenlib.h" #include "BLI_rand.h" +#include "BLI_rect.h" #include "BKE_brush.h" #include "BKE_colortools.h" @@ -757,87 +758,27 @@ float BKE_brush_sample_masktex(const Scene *scene, Brush *br, return intensity; } -/* Brush Sampling for 2D brushes. when we unify the brush systems this will be - * necessarily a separate function. - * - * rgba outputs straight alpha. */ -float BKE_brush_sample_tex_2D(const Scene *scene, Brush *brush, const float xy[2], float rgba[4]) +static void brush_imbuf_tex_co(rctf *mapping, int x, int y, float texco[3]) { - UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; - MTex *mtex = &brush->mtex; - - if (mtex && mtex->tex) { - float co[3], tin, tr, tg, tb, ta; - float x = xy[0], y = xy[1]; - int hasrgb; - int radius = BKE_brush_size_get(scene, brush); - float rotation = -mtex->rot; - - if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) { - rotation += ups->brush_rotation; - radius = ups->pixel_radius; - } - else if (mtex->brush_map_mode == MTEX_MAP_MODE_RANDOM) { - rotation += ups->brush_rotation; - /* these contain a random coordinate */ - x -= ups->tex_mouse[0]; - y -= ups->tex_mouse[1]; - - radius = ups->pixel_radius; - } - - x /= radius; - y /= radius; - - if (rotation > 0.001f || rotation < -0.001f) { - const float angle = atan2f(y, x) + rotation; - const float flen = sqrtf(x * x + y * y); - - x = flen * cosf(angle); - y = flen * sinf(angle); - } - - x *= brush->mtex.size[0]; - y *= brush->mtex.size[1]; - - co[0] = x + brush->mtex.ofs[0]; - co[1] = y + brush->mtex.ofs[1]; - co[2] = 0.0f; - - hasrgb = externtex(mtex, co, &tin, &tr, &tg, &tb, &ta, 0, NULL); - - 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; - } - return tin; - } - else { - rgba[0] = rgba[1] = rgba[2] = rgba[3] = 1.0f; - return 1.0; - } + texco[0] = mapping->xmin + x*mapping->xmax; + texco[1] = mapping->ymin + y*mapping->ymax; + texco[2] = 0.0f; } /* 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, bool use_color_correction, bool use_brush_alpha) + ImBuf **outbuf, bool use_color_correction, bool use_brush_alpha, + struct ImagePool *pool, rctf *mapping) { ImBuf *ibuf; - float xy[2], rgba[4], *dstf; + float xy[2], texco[3], rgba[4], *dstf; int x, y, rowbytes, xoff, yoff, imbflag; const int radius = BKE_brush_size_get(scene, brush); unsigned char *dst, crgb[3]; const float alpha = (use_brush_alpha)? BKE_brush_alpha_get(scene, brush): 1.0f; float brush_rgb[3]; + int thread = 0; imbflag = (flt) ? IB_rectfloat : IB_rect; xoff = -bufsize / 2.0f + 0.5f; @@ -867,15 +808,19 @@ void BKE_brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texf dstf[3] = alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius); } else if (texfall == 1) { - BKE_brush_sample_tex_2D(scene, brush, xy, dstf); + brush_imbuf_tex_co(mapping, x, y, texco); + BKE_brush_sample_tex_3D(scene, brush, texco, dstf, thread, pool); } else if (texfall == 2) { - BKE_brush_sample_tex_2D(scene, brush, xy, rgba); + brush_imbuf_tex_co(mapping, x, y, texco); + BKE_brush_sample_tex_3D(scene, brush, texco, rgba, thread, pool); + mul_v3_v3v3(dstf, rgba, brush_rgb); dstf[3] = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius); } else { - BKE_brush_sample_tex_2D(scene, brush, xy, rgba); + brush_imbuf_tex_co(mapping, x, y, texco); + BKE_brush_sample_tex_3D(scene, brush, texco, rgba, thread, pool); copy_v3_v3(dstf, brush_rgb); dstf[3] = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius); } @@ -907,11 +852,13 @@ void BKE_brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texf dst[3] = FTOCHAR(alpha_f); } else if (texfall == 1) { - BKE_brush_sample_tex_2D(scene, brush, xy, rgba); + brush_imbuf_tex_co(mapping, x, y, texco); + BKE_brush_sample_tex_3D(scene, brush, texco, rgba, thread, pool); rgba_float_to_uchar(dst, rgba); } else if (texfall == 2) { - BKE_brush_sample_tex_2D(scene, brush, xy, rgba); + brush_imbuf_tex_co(mapping, x, y, texco); + BKE_brush_sample_tex_3D(scene, brush, texco, rgba, thread, pool); mul_v3_v3(rgba, brush->rgb); alpha_f = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius); @@ -920,7 +867,8 @@ void BKE_brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texf dst[3] = FTOCHAR(alpha_f); } else { - BKE_brush_sample_tex_2D(scene, brush, xy, rgba); + brush_imbuf_tex_co(mapping, x, y, texco); + BKE_brush_sample_tex_3D(scene, brush, texco, rgba, thread, pool); alpha_f = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius); dst[0] = crgb[0]; diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c index d6a634ec404..5cba3394a18 100644 --- a/source/blender/editors/sculpt_paint/paint_image_2d.c +++ b/source/blender/editors/sculpt_paint/paint_image_2d.c @@ -39,6 +39,7 @@ #include "DNA_object_types.h" #include "BLI_math.h" +#include "BLI_rect.h" #include "BKE_context.h" #include "BKE_brush.h" @@ -109,6 +110,9 @@ typedef struct BrushPainter { short firsttouch; /* first paint op */ + struct ImagePool *pool; /* image pool */ + rctf mapping; /* texture coordinate mapping */ + BrushPainterCache cache; } BrushPainter; @@ -124,6 +128,7 @@ typedef struct ImagePaintState { View2D *v2d; Scene *scene; bScreen *screen; + struct ImagePool *image_pool; Brush *brush; short tool, blend; @@ -190,15 +195,16 @@ static void brush_painter_2d_do_partial(BrushPainter *painter, ImBuf *oldtexibuf Scene *scene = painter->scene; Brush *brush = painter->brush; ImBuf *ibuf, *maskibuf, *texibuf; - float *bf, *mf, *tf, *otf = NULL, xoff, yoff, xy[2], rgba[4]; + float *bf, *mf, *tf, *otf = NULL, texco[3], rgba[4]; unsigned char *b, *m, *t, *ot = NULL; int dotexold, origx = x, origy = y; - const int radius = BKE_brush_size_get(painter->scene, brush); + int thread = 0; + rctf mapping = painter->mapping; - xoff = -radius + 0.5f; - yoff = -radius + 0.5f; - xoff += (int)pos[0] - (int)painter->startpaintpos[0]; - yoff += (int)pos[1] - (int)painter->startpaintpos[1]; + if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_TILED) { + mapping.xmin += (int)pos[0] - (int)painter->startpaintpos[0]; + mapping.ymin += (int)pos[1] - (int)painter->startpaintpos[1]; + } ibuf = painter->cache.ibuf; texibuf = painter->cache.texibuf; @@ -227,10 +233,11 @@ static void brush_painter_2d_do_partial(BrushPainter *painter, ImBuf *oldtexibuf otf += 4; } else { - xy[0] = x + xoff; - xy[1] = y + yoff; + texco[0] = mapping.xmin + x*mapping.xmax; + texco[1] = mapping.ymin + y*mapping.ymax; + texco[2] = 0.0f; - BKE_brush_sample_tex_2D(scene, brush, xy, tf); + BKE_brush_sample_tex_3D(scene, brush, texco, tf, thread, painter->pool); } /* output premultiplied float image, mf was already premultiplied */ @@ -259,10 +266,11 @@ static void brush_painter_2d_do_partial(BrushPainter *painter, ImBuf *oldtexibuf ot += 4; } else { - xy[0] = x + xoff; - xy[1] = y + yoff; + texco[0] = mapping.xmin + x*mapping.xmax; + texco[1] = mapping.ymin + y*mapping.ymax; + texco[2] = 0.0f; - BKE_brush_sample_tex_2D(scene, brush, xy, rgba); + BKE_brush_sample_tex_3D(scene, brush, texco, rgba, thread, painter->pool); rgba_float_to_uchar(t, rgba); } @@ -329,25 +337,71 @@ static void brush_painter_2d_tiled_tex_partial_update(BrushPainter *painter, con brush_painter_2d_do_partial(painter, NULL, x1, y2, x2, ibuf->y, 0, 0, pos); } -static void brush_painter_2d_refresh_cache(BrushPainter *painter, const float pos[2], bool use_color_correction, bool use_brush_alpha) +static void brush_painter_2d_tex_mapping(ImagePaintState *s, int bufsize, const float pos[2], bool do_stencil, bool do_3D, rctf *mapping) +{ + float invw = 1.0f/(float)s->canvas->x; + float invh = 1.0f/(float)s->canvas->y; + int xmin, ymin, xmax, ymax; + int ipos[2]; + + /* find start coordinate of brush in canvas */ + ipos[0] = (int)floorf((pos[0] - bufsize / 2) + 1.0f); + ipos[1] = (int)floorf((pos[1] - bufsize / 2) + 1.0f); + + if (do_stencil) { + /* map from view coordinates of brush to region coordinates */ + UI_view2d_to_region_no_clip(s->v2d, ipos[0]*invw, ipos[1]*invh, &xmin, &ymin); + UI_view2d_to_region_no_clip(s->v2d, (ipos[0] + bufsize)*invw, (ipos[1] + bufsize)*invh, &xmax, &ymax); + + /* output mapping from brush ibuf x/y to region coordinates */ + mapping->xmin = xmin; + mapping->ymin = ymin; + mapping->xmax = (xmax - xmin)/(float)bufsize; + mapping->ymax = (ymax - ymin)/(float)bufsize; + } + else if (do_3D) { + /* 3D mapping, just mapping to canvas 0..1 */ + mapping->xmin = ipos[0]*invw; + mapping->ymin = ipos[1]*invh; + mapping->xmax = bufsize*invw/(float)bufsize; + mapping->ymax = bufsize*invh/(float)bufsize; + } + else { + /* other mapping */ + mapping->xmin = -bufsize * 0.5f + 0.5f; + mapping->ymin = -bufsize * 0.5f + 0.5f; + mapping->xmax = 1.0f; + mapping->ymax = 1.0f; + } +} + +static void brush_painter_2d_refresh_cache(ImagePaintState *s, BrushPainter *painter, const float pos[2], bool use_color_correction) { const Scene *scene = painter->scene; UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; Brush *brush = painter->brush; BrushPainterCache *cache = &painter->cache; MTex *mtex = &brush->mtex; - int size; - short flt; const int diameter = 2 * BKE_brush_size_get(scene, brush); + const int size = (cache->size) ? cache->size : diameter; + const short flt = cache->flt; const float alpha = BKE_brush_alpha_get(scene, brush); - const bool do_tiled = ELEM(brush->mtex.brush_map_mode, MTEX_MAP_MODE_TILED, MTEX_MAP_MODE_3D); + const bool do_3D = brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D; + const bool do_tiled = brush->mtex.brush_map_mode == MTEX_MAP_MODE_TILED; + const bool do_stencil = brush->mtex.brush_map_mode == MTEX_MAP_MODE_STENCIL; const bool do_random = brush->mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM; + const bool do_view = brush->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW; + const bool use_brush_alpha = !s->do_masking; float rotation = -mtex->rot; - if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) { + if (do_view) { rotation += ups->brush_rotation; } + brush_painter_2d_tex_mapping(s, size, pos, do_stencil, do_3D, &painter->mapping); + + painter->pool = BKE_image_pool_new(); + if (diameter != cache->lastsize || (use_brush_alpha && alpha != cache->lastalpha) || brush->jitter != cache->lastjitter || @@ -363,30 +417,32 @@ static void brush_painter_2d_refresh_cache(BrushPainter *painter, const float po cache->maskibuf = NULL; } - flt = cache->flt; - size = (cache->size) ? cache->size : diameter; - - if (do_tiled) { + if (do_tiled || do_3D || do_stencil) { BKE_brush_imbuf_new(scene, brush, flt, 3, size, &cache->maskibuf, - use_color_correction, use_brush_alpha); + use_color_correction, use_brush_alpha, + painter->pool, &painter->mapping); brush_painter_2d_tiled_tex_partial_update(painter, pos); } else BKE_brush_imbuf_new(scene, brush, flt, 2, size, &cache->ibuf, - use_color_correction, use_brush_alpha); + use_color_correction, use_brush_alpha, + painter->pool, &painter->mapping); cache->lastsize = diameter; cache->lastalpha = alpha; cache->lastjitter = brush->jitter; cache->last_rotation = rotation; } - else if (do_tiled && mtex && mtex->tex) { + else if ((do_tiled || do_3D || do_stencil) && mtex && mtex->tex) { int dx = (int)painter->lastpaintpos[0] - (int)pos[0]; int dy = (int)painter->lastpaintpos[1] - (int)pos[1]; if ((dx != 0) || (dy != 0)) brush_painter_2d_tiled_tex_partial_update(painter, pos); } + + BKE_image_pool_free(painter->pool); + painter->pool = NULL; } /* keep these functions in sync */ @@ -785,7 +841,7 @@ int paint_2d_stroke(void *ps, const int prev_mval[2], const int mval[2], int era */ brush_painter_2d_require_imbuf(painter, ((ibuf->rect_float) ? 1 : 0), 0); - brush_painter_2d_refresh_cache(painter, newuv, is_data == false, s->do_masking); + brush_painter_2d_refresh_cache(s, painter, newuv, is_data == false); if (paint_2d_op(s, painter->cache.ibuf, olduv, newuv)) { imapaint_image_update(s->sima, s->image, ibuf, false); |