Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/BKE_brush.h9
-rw-r--r--source/blender/blenkernel/intern/brush.c96
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d.c106
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);