diff options
-rw-r--r-- | source/blender/blenkernel/BKE_brush.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/brush.c | 124 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_stroke.c | 16 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_scene_types.h | 4 |
4 files changed, 111 insertions, 35 deletions
diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h index 503c7a7f435..452030d05e6 100644 --- a/source/blender/blenkernel/BKE_brush.h +++ b/source/blender/blenkernel/BKE_brush.h @@ -67,7 +67,7 @@ int BKE_brush_clone_image_delete(struct Brush *brush); /* jitter */ void BKE_brush_jitter_pos(const struct Scene *scene, struct Brush *brush, const float pos[2], float jitterpos[2]); -void BKE_brush_randomize_texture_coordinates(struct UnifiedPaintSettings *ups); +void BKE_brush_randomize_texture_coordinates(struct UnifiedPaintSettings *ups, bool mask); /* brush curve */ void BKE_brush_curve_preset(struct Brush *b, int preset); diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index dd299be9764..064e902f831 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -560,11 +560,11 @@ float BKE_brush_sample_tex_3D(const Scene *scene, Brush *br, x /= (br->stencil_dimension[0]); y /= (br->stencil_dimension[1]); - x *= br->mtex.size[0]; - y *= br->mtex.size[1]; + x *= mtex->size[0]; + y *= mtex->size[1]; - co[0] = x + br->mtex.ofs[0]; - co[1] = y + br->mtex.ofs[1]; + co[0] = x + mtex->ofs[0]; + co[1] = y + mtex->ofs[1]; co[2] = 0.0f; hasrgb = externtex(mtex, co, &intensity, @@ -620,11 +620,11 @@ float BKE_brush_sample_tex_3D(const Scene *scene, Brush *br, y = flen * sinf(angle); } - x *= br->mtex.size[0]; - y *= br->mtex.size[1]; + x *= mtex->size[0]; + y *= mtex->size[1]; - co[0] = x + br->mtex.ofs[0]; - co[1] = y + br->mtex.ofs[1]; + co[0] = x + mtex->ofs[0]; + co[1] = y + mtex->ofs[1]; co[2] = 0.0f; hasrgb = externtex(mtex, co, &intensity, @@ -650,26 +650,83 @@ float BKE_brush_sample_masktex(const Scene *scene, Brush *br, { UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; MTex *mtex = &br->mask_mtex; + float rgba[4], intensity; - if (mtex && mtex->tex) { + if (!mtex->tex) { + return 1.0f; + } + if (mtex->brush_map_mode == MTEX_MAP_MODE_STENCIL) { float rotation = -mtex->rot; float point_2d[2] = {point[0], point[1]}; float x = 0.0f, y = 0.0f; /* Quite warnings */ - float radius = 1.0f; /* Quite warnings */ float co[3]; - float rgba[4], intensity = 1.0; - point_2d[0] -= ups->tex_mouse[0]; - point_2d[1] -= ups->tex_mouse[1]; + x = point_2d[0] - br->stencil_pos[0]; + y = point_2d[1] - br->stencil_pos[1]; - /* use pressure adjusted size for fixed mode */ - radius = ups->pixel_radius; + if (rotation > 0.001f || rotation < -0.001f) { + const float angle = atan2f(y, x) + rotation; + const float flen = sqrtf(x * x + y * y); - x = point_2d[0]; - y = point_2d[1]; + x = flen * cosf(angle); + y = flen * sinf(angle); + } - x /= radius; - y /= radius; + if (fabsf(x) > br->stencil_dimension[0] || fabsf(y) > br->stencil_dimension[1]) { + zero_v4(rgba); + return 0.0f; + } + x /= (br->stencil_dimension[0]); + y /= (br->stencil_dimension[1]); + + x *= mtex->size[0]; + y *= mtex->size[1]; + + co[0] = x + mtex->ofs[0]; + co[1] = y + mtex->ofs[1]; + co[2] = 0.0f; + + externtex(mtex, co, &intensity, + rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool); + } + else { + float rotation = -mtex->rot; + float point_2d[2] = {point[0], point[1]}; + float x = 0.0f, y = 0.0f; /* Quite warnings */ + float invradius = 1.0f; /* Quite warnings */ + float co[3]; + + if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) { + /* keep coordinates relative to mouse */ + + rotation += ups->brush_rotation; + + x = point_2d[0] - ups->mask_tex_mouse[0]; + y = point_2d[1] - ups->mask_tex_mouse[1]; + + /* use pressure adjusted size for fixed mode */ + invradius = 1.0f / ups->pixel_radius; + } + else if (mtex->brush_map_mode == MTEX_MAP_MODE_TILED) { + /* leave the coordinates relative to the screen */ + + /* use unadjusted size for tiled mode */ + invradius = 1.0f / BKE_brush_size_get(scene, br); + + x = point_2d[0]; + y = point_2d[1]; + } + else if (mtex->brush_map_mode == MTEX_MAP_MODE_RANDOM) { + rotation += ups->brush_rotation; + /* these contain a random coordinate */ + x = point_2d[0] - ups->mask_tex_mouse[0]; + y = point_2d[1] - ups->mask_tex_mouse[1]; + + invradius = 1.0f / ups->pixel_radius; + } + + x *= invradius; + y *= invradius; /* it is probably worth optimizing for those cases where * the texture is not rotated by skipping the calls to @@ -682,21 +739,18 @@ float BKE_brush_sample_masktex(const Scene *scene, Brush *br, y = flen * sinf(angle); } - x *= br->mask_mtex.size[0]; - y *= br->mask_mtex.size[1]; + x *= mtex->size[0]; + y *= mtex->size[1]; - co[0] = x + br->mask_mtex.ofs[0]; - co[1] = y + br->mask_mtex.ofs[1]; + co[0] = x + mtex->ofs[0]; + co[1] = y + mtex->ofs[1]; co[2] = 0.0f; externtex(mtex, co, &intensity, - rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool); - - return intensity; - } - else { - return 1.0f; + rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool); } + + return intensity; } /* Brush Sampling for 2D brushes. when we unify the brush systems this will be necessarily a separate function */ @@ -1044,12 +1098,18 @@ void BKE_brush_jitter_pos(const Scene *scene, Brush *brush, const float pos[2], } } -void BKE_brush_randomize_texture_coordinates(UnifiedPaintSettings *ups) +void BKE_brush_randomize_texture_coordinates(UnifiedPaintSettings *ups, bool mask) { /* we multiply with brush radius as an optimization for the brush * texture sampling functions */ - ups->tex_mouse[0] = BLI_rng_get_float(brush_rng) * ups->pixel_radius; - ups->tex_mouse[1] = BLI_rng_get_float(brush_rng) * ups->pixel_radius; + if (mask) { + ups->mask_tex_mouse[0] = BLI_rng_get_float(brush_rng) * ups->pixel_radius; + ups->mask_tex_mouse[1] = BLI_rng_get_float(brush_rng) * ups->pixel_radius; + } + else { + ups->tex_mouse[0] = BLI_rng_get_float(brush_rng) * ups->pixel_radius; + ups->tex_mouse[1] = BLI_rng_get_float(brush_rng) * ups->pixel_radius; + } } /* Uses the brush curve control to find a strength value between 0 and 1 */ diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index bbddd2e4a69..d754567bd99 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -160,6 +160,7 @@ static void paint_brush_update(bContext *C, Brush *brush, PaintMode mode, if (paint_supports_dynamic_size(brush, mode) || !stroke->brush_init) { copy_v2_v2(stroke->initial_mouse, mouse); copy_v2_v2(ups->tex_mouse, mouse); + copy_v2_v2(ups->mask_tex_mouse, mouse); stroke->cached_pressure = pressure; } @@ -186,11 +187,22 @@ static void paint_brush_update(bContext *C, Brush *brush, PaintMode mode, } if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM) - BKE_brush_randomize_texture_coordinates(ups); - else + BKE_brush_randomize_texture_coordinates(ups, false); + else { copy_v2_v2(ups->tex_mouse, mouse); + } + } + + /* take care of mask texture, if any */ + if (brush->mask_mtex.tex) { + if (brush->mask_mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM) + BKE_brush_randomize_texture_coordinates(ups, true); + else { + copy_v2_v2(ups->mask_tex_mouse, mouse); + } } + if (brush->flag & BRUSH_ANCHORED) { bool hit = false; float halfway[2]; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index e5127e51d13..eb8c8138e85 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -914,6 +914,10 @@ typedef struct UnifiedPaintSettings { /* position of mouse, used to sample the texture */ float tex_mouse[2]; + + /* position of mouse, used to sample the mask texture */ + float mask_tex_mouse[2]; + /* radius of brush, premultiplied with pressure. * In case of anchored brushes contains that radius */ float pixel_radius; |