diff options
-rw-r--r-- | source/blender/blenkernel/BKE_brush.h | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_paint.h | 3 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/brush.c | 96 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/paint.c | 20 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_cursor.c | 48 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_image_2d.c | 4 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_intern.h | 5 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_stroke.c | 143 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt.c | 196 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_scene_types.h | 13 |
10 files changed, 325 insertions, 207 deletions
diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h index 3c65cb03c68..2247495ce9e 100644 --- a/source/blender/blenkernel/BKE_brush.h +++ b/source/blender/blenkernel/BKE_brush.h @@ -70,7 +70,9 @@ float BKE_brush_curve_strength(struct Brush *br, float p, const float len); /* u /* sampling */ void BKE_brush_sample_tex(const struct Scene *scene, struct Brush *brush, const float sampleco[3], float rgba[4], const int thread, struct ImagePool *pool); -void BKE_brush_sample_tex_2D(const struct Scene *scene, struct Brush *brush, const float xy[2], float rgba[4], const int thread); +float BKE_brush_sample_tex_3D(const Scene *scene, struct Brush *br,const float point[3], + float rgba[3], struct ImagePool *pool); +float BKE_brush_sample_tex_2D(const struct Scene *scene, struct Brush *brush, const float xy[2], float rgba[4], struct ImagePool *pool); 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); diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 6e9dfdb5cba..35941d0a05a 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -48,6 +48,7 @@ struct PBVH; struct Scene; struct StrokeCache; struct ImagePool; +struct UnifiedPaintSettings; extern const char PAINT_CURSOR_SCULPT[3]; extern const char PAINT_CURSOR_VERTEX_PAINT[3]; @@ -90,7 +91,7 @@ int paint_is_bmesh_face_hidden(struct BMFace *f); /* paint masks */ float paint_grid_paint_mask(const struct GridPaintMask *gpm, unsigned level, unsigned x, unsigned y); - +void paint_calculate_rake_rotation(struct UnifiedPaintSettings *ups, const float mouse_pos[2]); /* Session data (mode-specific) */ typedef struct SculptSession { diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index ab821ec37a1..4ec20d5fe04 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -513,8 +513,98 @@ void BKE_brush_sample_tex(const Scene *scene, Brush *brush, const float sampleco } } + +/* Return a multiplier for brush strength on a particular vertex. */ +float BKE_brush_sample_tex_3D(const Scene *scene, Brush *br, + const float point[3], + float rgba[3], + struct ImagePool *pool) +{ + UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; + MTex *mtex = &br->mtex; + float intensity = 1.0; + bool hasrgb = false; + + if (!mtex->tex) { + intensity = 1; + } + else if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) { + /* Get strength by feeding the vertex + * location directly into a texture */ + hasrgb = externtex(mtex, point, &intensity, + rgba, rgba + 1, rgba + 2, rgba + 3, 0, pool); + } + else { + 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[2]; + + if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) { + /* keep coordinates relative to mouse */ + + rotation += ups->brush_rotation; + + point_2d[0] -= ups->tex_mouse[0]; + point_2d[1] -= ups->tex_mouse[1]; + + /* use pressure adjusted size for fixed mode */ + radius = ups->pixel_radius; + + x = point_2d[0]; + y = point_2d[1]; + } + else if (mtex->brush_map_mode == MTEX_MAP_MODE_TILED) { + /* leave the coordinates relative to the screen */ + + /* use unadjusted size for tiled mode */ + radius = BKE_brush_size_get(scene, br); + + x = point_2d[0]; + y = point_2d[1]; + } + + x /= radius; + y /= radius; + + /* it is probably worth optimizing for those cases where + * the texture is not rotated by skipping the calls to + * atan2, sqrtf, sin, and cos. */ + 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 *= br->mtex.size[0]; + y *= br->mtex.size[1]; + + co[0] = x + br->mtex.ofs[0]; + co[1] = y + br->mtex.ofs[1]; + co[2] = 0.0f; + + hasrgb = externtex(mtex, co, &intensity, + rgba, rgba + 1, rgba + 2, rgba + 3, 0, pool); + } + + intensity += br->texture_sample_bias; + + if (!hasrgb) { + rgba[0] = intensity; + rgba[1] = intensity; + rgba[2] = intensity; + rgba[3] = 1.0f; + } + + return intensity; +} + + /* 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) +float BKE_brush_sample_tex_2D(const Scene *scene, Brush *brush, const float xy[2], float rgba[4], struct ImagePool *pool) { MTex *mtex = &brush->mtex; @@ -527,7 +617,7 @@ void BKE_brush_sample_tex_2D(const Scene *scene, Brush *brush, const float xy[2] co[1] = xy[1] / radius; co[2] = 0.0f; - hasrgb = externtex(mtex, co, &tin, &tr, &tg, &tb, &ta, thread, NULL); + hasrgb = externtex(mtex, co, &tin, &tr, &tg, &tb, &ta, 0, pool); if (hasrgb) { rgba[0] = tr; @@ -541,9 +631,11 @@ void BKE_brush_sample_tex_2D(const Scene *scene, Brush *brush, const float xy[2] rgba[2] = tin; rgba[3] = 1.0f; } + return tin; } else { rgba[0] = rgba[1] = rgba[2] = rgba[3] = 1.0f; + return 1.0; } } diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index a001a13d000..cc647a90c8f 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -40,6 +40,7 @@ #include "BLI_bitmap.h" #include "BLI_utildefines.h" +#include "BLI_math_vector.h" #include "BKE_brush.h" #include "BKE_context.h" @@ -300,3 +301,22 @@ float paint_grid_paint_mask(const GridPaintMask *gpm, unsigned level, return gpm->data[(y * factor) * gridsize + (x * factor)]; } + +/* threshhold to move before updating the brush rotation */ +#define RAKE_THRESHHOLD 20 + +void paint_calculate_rake_rotation(UnifiedPaintSettings *ups, const float mouse_pos[2]) +{ + const float u = 0.5f; + const float r = RAKE_THRESHHOLD; + + float dpos[2]; + sub_v2_v2v2(dpos, ups->last_rake, mouse_pos); + + if (len_squared_v2(dpos) >= r * r) { + ups->brush_rotation = atan2(dpos[0], dpos[1]); + + interp_v2_v2v2(ups->last_rake, ups->last_rake, + mouse_pos, u); + } +} diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c index bf6ad32efc1..8d9cbbbcf11 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.c +++ b/source/blender/editors/sculpt_paint/paint_cursor.c @@ -207,14 +207,14 @@ static int load_tex(Brush *br, ViewContext *vc) x = (float)i / size; y = (float)j / size; - x -= 0.5f; - y -= 0.5f; - if (br->mtex.brush_map_mode == MTEX_MAP_MODE_TILED) { x *= vc->ar->winx / radius; y *= vc->ar->winy / radius; } else { + x -= 0.5f; + y -= 0.5f; + x *= 2; y *= 2; } @@ -420,8 +420,7 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush, if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) { /* brush rotation */ glTranslatef(0.5, 0.5, 0); - glRotatef((double)RAD2DEGF((brush->flag & BRUSH_RAKE) ? - ups->last_angle : ups->special_rotation), + glRotatef((double)RAD2DEGF(ups->brush_rotation), 0.0, 0.0, 1.0); glTranslatef(-0.5f, -0.5f, 0); @@ -434,11 +433,10 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush, if (ups->draw_anchored) { const float *aim = ups->anchored_initial_mouse; - const rcti *win = &vc->ar->winrct; - quad.xmin = aim[0] - ups->anchored_size - win->xmin; - quad.ymin = aim[1] - ups->anchored_size - win->ymin; - quad.xmax = aim[0] + ups->anchored_size - win->xmin; - quad.ymax = aim[1] + ups->anchored_size - win->ymin; + quad.xmin = aim[0] - ups->anchored_size; + quad.ymin = aim[1] - ups->anchored_size; + quad.xmax = aim[0] + ups->anchored_size; + quad.ymax = aim[1] + ups->anchored_size; } else { const int radius = BKE_brush_size_get(vc->scene, brush); @@ -537,38 +535,22 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) * mouse over too, not just during a stroke */ view3d_set_viewcontext(C, &vc); + if (brush->flag & BRUSH_RAKE) + /* here, translation contains the mouse coordinates. */ + paint_calculate_rake_rotation(ups, translation); + + /* draw overlay */ + paint_draw_alpha_overlay(ups, brush, &vc, x, y); + /* TODO: as sculpt and other paint modes are unified, this * special mode of drawing will go away */ if (vc.obact->sculpt) { float location[3]; int pixel_radius, hit; - /* this is probably here so that rake takes into - * account the brush movements before the stroke - * starts, but this doesn't really belong in draw code - * TODO) */ - { - const float u = 0.5f; - const float v = 1 - u; - const float r = 20; - - const float dx = ups->last_x - x; - const float dy = ups->last_y - y; - - if (dx * dx + dy * dy >= r * r) { - ups->last_angle = atan2(dx, dy); - - ups->last_x = u * ups->last_x + v * x; - ups->last_y = u * ups->last_y + v * y; - } - } - /* test if brush is over the mesh */ hit = sculpt_get_brush_geometry(C, &vc, x, y, &pixel_radius, location); - /* draw overlay */ - paint_draw_alpha_overlay(ups, brush, &vc, x, y); - if (BKE_brush_use_locked_size(scene, brush)) BKE_brush_size_set(scene, brush, pixel_radius); diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c index 6c512d1cec8..e2e448646b2 100644 --- a/source/blender/editors/sculpt_paint/paint_image_2d.c +++ b/source/blender/editors/sculpt_paint/paint_image_2d.c @@ -234,7 +234,7 @@ static void brush_painter_2d_do_partial(BrushPainter *painter, ImBuf *oldtexibuf xy[0] = x + xoff; xy[1] = y + yoff; - BKE_brush_sample_tex_2D(scene, brush, xy, tf, 0); + BKE_brush_sample_tex_2D(scene, brush, xy, tf, NULL); } bf[0] = tf[0] * mf[0]; @@ -265,7 +265,7 @@ static void brush_painter_2d_do_partial(BrushPainter *painter, ImBuf *oldtexibuf xy[0] = x + xoff; xy[1] = y + yoff; - BKE_brush_sample_tex_2D(scene, brush, xy, rgba, 0); + BKE_brush_sample_tex_2D(scene, brush, xy, rgba, NULL); rgba_float_to_uchar(t, rgba); } diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h index 8d1076479cd..5371f644bcb 100644 --- a/source/blender/editors/sculpt_paint/paint_intern.h +++ b/source/blender/editors/sculpt_paint/paint_intern.h @@ -64,8 +64,9 @@ struct PaintStroke *paint_stroke_new(struct bContext *C, StrokeUpdateStep update_step, StrokeDone done, int event_type); void paint_stroke_data_free(struct wmOperator *op); -bool paint_space_stroke_enabled(struct Brush *br); -bool paint_supports_dynamic_size(struct Brush *br); +bool paint_space_stroke_enabled(struct Brush *br, enum PaintMode mode); +bool paint_supports_dynamic_size(struct Brush *br, enum PaintMode mode); +bool paint_supports_moving_texture(struct Brush *br, enum PaintMode mode); bool paint_supports_jitter(enum PaintMode mode); struct wmKeyMap *paint_stroke_modal_keymap(struct wmKeyConfig *keyconf); diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 244b5f6b6fb..a7e97e55ca6 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -35,6 +35,7 @@ #include "BLI_math.h" #include "BLI_utildefines.h" +#include "BLI_rand.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -91,6 +92,10 @@ typedef struct PaintStroke { /* event that started stroke, for modal() return */ int event_type; + bool brush_init; + float initial_mouse[2]; + float cached_pressure; + StrokeGetLocation get_location; StrokeTestStart test_start; StrokeUpdateStep update_step; @@ -136,6 +141,98 @@ static float event_tablet_data(wmEvent *event, int *pen_flip) return pressure; } +#if 1 +/* Initialize the stroke cache variants from operator properties */ +static void paint_brush_update(bContext *C, Brush *brush, PaintMode mode, + struct PaintStroke *stroke, + float mouse[2], float pressure) +{ + Scene *scene = CTX_data_scene(C); + UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; + + /* XXX: Use pressure value from first brush step for brushes which don't + * support strokes (grab, thumb). They depends on initial state and + * brush coord/pressure/etc. + * It's more an events design issue, which doesn't split coordinate/pressure/angle + * changing events. We should avoid this after events system re-design */ + if (paint_supports_dynamic_size(brush, mode) || !stroke->brush_init) { + copy_v2_v2(stroke->initial_mouse, mouse); + copy_v2_v2(ups->tex_mouse, mouse); + stroke->cached_pressure = pressure; + } + + /* Truly temporary data that isn't stored in properties */ + + ups->draw_pressure = TRUE; + ups->pressure_value = stroke->cached_pressure; + + ups->pixel_radius = BKE_brush_size_get(scene, brush); + + if (BKE_brush_use_size_pressure(scene, brush) && paint_supports_dynamic_size(brush, mode)) { + ups->pixel_radius *= stroke->cached_pressure; + } + + if (!(brush->flag & BRUSH_ANCHORED || + ELEM4(brush->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_SNAKE_HOOK, + SCULPT_TOOL_THUMB, SCULPT_TOOL_ROTATE))) + { + copy_v2_v2(ups->tex_mouse, mouse); + + if ((brush->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) && + (brush->flag & BRUSH_RANDOM_ROTATION) && + !(brush->flag & BRUSH_RAKE)) + { + ups->brush_rotation = 2.0f * (float)M_PI * BLI_frand(); + } + } + + if (brush->flag & BRUSH_ANCHORED) { + bool hit = false; + float halfway[2]; + + const float dx = mouse[0] - stroke->initial_mouse[0]; + const float dy = mouse[1] - stroke->initial_mouse[1]; + + ups->anchored_size = ups->pixel_radius = sqrt(dx * dx + dy * dy); + + ups->brush_rotation = atan2(dx, dy) + M_PI; + + if (brush->flag & BRUSH_EDGE_TO_EDGE) { + float out[3]; + + halfway[0] = dx * 0.5f + stroke->initial_mouse[0]; + halfway[1] = dy * 0.5f + stroke->initial_mouse[1]; + + if (stroke->get_location) { + if(stroke->get_location(C, out, halfway)) { + hit = true; + } + } else { + hit = true; + } + } + if(hit) { + copy_v2_v2(ups->anchored_initial_mouse, halfway); + copy_v2_v2(ups->tex_mouse, halfway); + ups->anchored_size /= 2.0f; + ups->pixel_radius /= 2.0f; + } + else + copy_v2_v2(ups->anchored_initial_mouse, stroke->initial_mouse); + + ups->draw_anchored = 1; + } + else if (brush->flag & BRUSH_RAKE) { + if (!stroke->brush_init) + copy_v2_v2(ups->last_rake, mouse); + else + paint_calculate_rake_rotation(ups, mouse); + } + + stroke->brush_init = TRUE; +} +#endif + /* Put the location of the next stroke dot into the stroke RNA and apply it to the mesh */ static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, wmEvent *event, const float mouse_in[2]) { @@ -199,6 +296,8 @@ static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, wmEvent *ev else zero_v3(location); + paint_brush_update(C, brush, mode, stroke, mouse_out, pressure); + /* Add to stroke */ RNA_collection_add(op->ptr, "stroke", &itemptr); @@ -247,9 +346,11 @@ static int paint_smooth_stroke(PaintStroke *stroke, float output[2], static int paint_space_stroke(bContext *C, wmOperator *op, wmEvent *event, const float final_mouse[2]) { PaintStroke *stroke = op->customdata; + PaintMode mode = paintmode_get_active_from_context(C); + int cnt = 0; - if (paint_space_stroke_enabled(stroke->brush)) { + if (paint_space_stroke_enabled(stroke->brush, mode)) { float mouse[2]; float vec[2]; float length, scale; @@ -355,16 +456,41 @@ static void stroke_done(struct bContext *C, struct wmOperator *op) } /* Returns zero if the stroke dots should not be spaced, non-zero otherwise */ -bool paint_space_stroke_enabled(Brush *br) +bool paint_space_stroke_enabled(Brush *br, PaintMode mode) { - return (br->flag & BRUSH_SPACE) && paint_supports_dynamic_size(br); + return (br->flag & BRUSH_SPACE) && paint_supports_dynamic_size(br, mode); } /* return true if the brush size can change during paint (normally used for pressure) */ -bool paint_supports_dynamic_size(Brush *br) +bool paint_supports_dynamic_size(Brush *br, PaintMode mode) { - return !(br->flag & BRUSH_ANCHORED) && - !ELEM4(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_THUMB, SCULPT_TOOL_ROTATE, SCULPT_TOOL_SNAKE_HOOK); + if(br->flag & BRUSH_ANCHORED) + return false; + + switch(mode) { + case PAINT_SCULPT: + if(ELEM4(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_THUMB, SCULPT_TOOL_ROTATE, SCULPT_TOOL_SNAKE_HOOK)) + return false; + default: + ; + } + return true; +} + +/* return true if the brush size can change during paint (normally used for pressure) */ +bool paint_supports_moving_texture(Brush *br, PaintMode mode) +{ + if(br->flag & BRUSH_ANCHORED) + return false; + + switch(mode) { + case PAINT_SCULPT: + if(ELEM4(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_THUMB, SCULPT_TOOL_ROTATE, SCULPT_TOOL_SNAKE_HOOK)) + return false; + default: + ; + } + return true; } bool paint_supports_jitter(PaintMode mode) @@ -439,6 +565,7 @@ static void paint_stroke_sample_average(const PaintStroke *stroke, int paint_stroke_modal(bContext *C, wmOperator *op, wmEvent *event) { Paint *p = paint_get_active_from_context(C); + PaintMode mode = paintmode_get_active_from_context(C); PaintStroke *stroke = op->customdata; PaintSample sample_average; float mouse[2]; @@ -489,7 +616,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, wmEvent *event) { if (stroke->stroke_started) { if (paint_smooth_stroke(stroke, mouse, &sample_average)) { - if (paint_space_stroke_enabled(stroke->brush)) { + if (paint_space_stroke_enabled(stroke->brush, mode)) { if (!paint_space_stroke(C, op, event, mouse)) { //ED_region_tag_redraw(ar); } @@ -508,7 +635,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, wmEvent *event) * instead of waiting till we have moved the space distance */ if (first && stroke->stroke_started && - paint_space_stroke_enabled(stroke->brush) && + paint_space_stroke_enabled(stroke->brush, mode) && !(stroke->brush->flag & BRUSH_ANCHORED) && !(stroke->brush->flag & BRUSH_SMOOTH_STROKE)) { diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index a43944f6609..7a6096b32d4 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -245,7 +245,6 @@ typedef struct StrokeCache { float pressure; float mouse[2]; float bstrength; - float tex_mouse[2]; /* The rest is temporary storage that isn't saved as a property */ @@ -259,8 +258,8 @@ typedef struct StrokeCache { Brush *brush; float (*face_norms)[3]; /* Copy of the mesh faces' normals */ - float special_rotation; /* Texture rotation (radians) for anchored and rake modes */ - int pixel_radius, previous_pixel_radius; + + float special_rotation; float grab_delta[3], grab_delta_symmetry[3]; float old_grab_location[3], orig_grab_location[3]; @@ -284,8 +283,8 @@ typedef struct StrokeCache { int radial_symmetry_pass; float symm_rot_mat[4][4]; float symm_rot_mat_inv[4][4]; - float last_rake[2]; /* Last location of updating rake rotation */ int original; + float anchored_location[3]; float vertex_rotation; @@ -924,25 +923,22 @@ static float tex_strength(SculptSession *ss, Brush *br, const float fno[3], const float mask) { + const Scene *scene = ss->cache->vc->scene; MTex *mtex = &br->mtex; float avg = 1; + float rgba[4]; if (!mtex->tex) { avg = 1; } else if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) { - float jnk; - /* Get strength by feeding the vertex * location directly into a texture */ - externtex(mtex, point, &avg, - &jnk, &jnk, &jnk, &jnk, 0, ss->tex_pool); + avg = BKE_brush_sample_tex_3D(scene, br, point, rgba, ss->tex_pool); } else if (ss->texcache) { - float rotation = -mtex->rot; float symm_point[3], point_2d[2]; float x = 0.0f, y = 0.0f; /* Quite warnings */ - float radius = 1.0f; /* Quite warnings */ /* if the active area is being applied for symmetry, flip it * across the symmetry axis and rotate it back to the original @@ -956,77 +952,31 @@ static float tex_strength(SculptSession *ss, Brush *br, ED_view3d_project_float_v2_m4(ss->cache->vc->ar, symm_point, point_2d, ss->cache->projection_mat); - if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) { - /* keep coordinates relative to mouse */ - - rotation += ss->cache->special_rotation; - - point_2d[0] -= ss->cache->tex_mouse[0]; - point_2d[1] -= ss->cache->tex_mouse[1]; - - /* use pressure adjusted size for fixed mode */ - radius = ss->cache->pixel_radius; - - x = point_2d[0]; - y = point_2d[1]; - } - else if (mtex->brush_map_mode == MTEX_MAP_MODE_TILED) { - /* leave the coordinates relative to the screen */ - - /* use unadjusted size for tiled mode */ - radius = BKE_brush_size_get(ss->cache->vc->scene, br); - - x = point_2d[0]; - y = point_2d[1]; - } - else if (mtex->brush_map_mode == MTEX_MAP_MODE_AREA) { + /* still no symmetry supported for other paint modes. + * Sculpt does it DIY */ + if (mtex->brush_map_mode == MTEX_MAP_MODE_AREA) { /* Similar to fixed mode, but projects from brush angle * rather than view direction */ - /* Rotation is handled by the brush_local_mat */ - rotation = 0; - mul_m4_v3(ss->cache->brush_local_mat, symm_point); x = symm_point[0]; y = symm_point[1]; - } - if (mtex->brush_map_mode != MTEX_MAP_MODE_AREA) { - x /= ss->cache->vc->ar->winx; - y /= ss->cache->vc->ar->winy; + x *= br->mtex.size[0]; + y *= br->mtex.size[1]; - if (mtex->brush_map_mode == MTEX_MAP_MODE_TILED) { - x -= 0.5f; - y -= 0.5f; - } - - x *= ss->cache->vc->ar->winx / radius; - y *= ss->cache->vc->ar->winy / radius; - } + x += br->mtex.ofs[0]; + y += br->mtex.ofs[1]; - /* it is probably worth optimizing for those cases where - * the texture is not rotated by skipping the calls to - * atan2, sqrtf, sin, and cos. */ - if (rotation > 0.001f || rotation < -0.001f) { - const float angle = atan2f(y, x) + rotation; - const float flen = sqrtf(x * x + y * y); + avg = paint_get_tex_pixel(br, x, y, ss->tex_pool); - x = flen * cosf(angle); - y = flen * sinf(angle); + avg += br->texture_sample_bias; + } else { + avg = BKE_brush_sample_tex_3D(scene, br, point_2d, rgba, ss->tex_pool); } - - x *= br->mtex.size[0]; - y *= br->mtex.size[1]; - - x += br->mtex.ofs[0]; - y += br->mtex.ofs[1]; - - avg = paint_get_tex_pixel(br, x, y, ss->tex_pool); } - avg += br->texture_sample_bias; - /* Falloff curve */ avg *= BKE_brush_curve_strength(br, len, ss->cache->radius); @@ -3716,21 +3666,21 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio ss->cache = cache; /* Set scaling adjustment */ - ss->cache->scale[0] = 1.0f / ob->size[0]; - ss->cache->scale[1] = 1.0f / ob->size[1]; - ss->cache->scale[2] = 1.0f / ob->size[2]; + cache->scale[0] = 1.0f / ob->size[0]; + cache->scale[1] = 1.0f / ob->size[1]; + cache->scale[2] = 1.0f / ob->size[2]; - ss->cache->plane_trim_squared = brush->plane_trim * brush->plane_trim; + cache->plane_trim_squared = brush->plane_trim * brush->plane_trim; - ss->cache->flag = 0; + cache->flag = 0; sculpt_init_mirror_clipping(ob, ss); /* Initial mouse location */ if (mouse) - copy_v2_v2(ss->cache->initial_mouse, mouse); + copy_v2_v2(cache->initial_mouse, mouse); else - zero_v2(ss->cache->initial_mouse); + zero_v2(cache->initial_mouse); mode = RNA_enum_get(op->ptr, "mode"); cache->invert = mode == BRUSH_STROKE_INVERT; @@ -3742,7 +3692,7 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio else brush->flag &= ~BRUSH_INVERTED; /* Alt-Smooth */ - if (ss->cache->alt_smooth) { + if (cache->alt_smooth) { if (brush->sculpt_tool == SCULPT_TOOL_MASK) { cache->saved_mask_brush_tool = brush->mask_tool; brush->mask_tool = BRUSH_MASK_SMOOTH; @@ -3763,7 +3713,7 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio } copy_v2_v2(cache->mouse, cache->initial_mouse); - copy_v2_v2(cache->tex_mouse, cache->initial_mouse); + copy_v2_v2(ups->tex_mouse, cache->initial_mouse); /* Truly temporary data that isn't stored in properties */ @@ -3818,8 +3768,6 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio } } - cache->special_rotation = (brush->flag & BRUSH_RAKE) ? ups->last_angle : 0; - cache->first_time = 1; cache->vertex_rotation = 0; @@ -3890,9 +3838,9 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru copy_v3_v3(cache->old_grab_location, grab_location); if (tool == SCULPT_TOOL_GRAB) - copy_v3_v3(ups->anchored_location, cache->true_location); + copy_v3_v3(cache->anchored_location, cache->true_location); else if (tool == SCULPT_TOOL_THUMB) - copy_v3_v3(ups->anchored_location, cache->orig_grab_location); + copy_v3_v3(cache->anchored_location, cache->orig_grab_location); if (ELEM(tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_THUMB)) { /* location stays the same for finding vertices in brush radius */ @@ -3900,7 +3848,7 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru ups->draw_anchored = 1; copy_v2_v2(ups->anchored_initial_mouse, cache->initial_mouse); - ups->anchored_size = cache->pixel_radius; + ups->anchored_size = ups->pixel_radius; } } } @@ -3935,18 +3883,11 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, * brush coord/pressure/etc. * It's more an events design issue, which doesn't split coordinate/pressure/angle * changing events. We should avoid this after events system re-design */ - if (paint_supports_dynamic_size(brush) || cache->first_time) { + if (paint_supports_dynamic_size(brush, PAINT_SCULPT) || cache->first_time) { cache->pressure = RNA_float_get(ptr, "pressure"); } /* Truly temporary data that isn't stored in properties */ - - ups->draw_pressure = 1; - ups->pressure_value = cache->pressure; - - cache->previous_pixel_radius = cache->pixel_radius; - cache->pixel_radius = BKE_brush_size_get(scene, brush); - if (cache->first_time) { if (!BKE_brush_use_locked_size(scene, brush)) { cache->initial_radius = paint_calc_object_space_radius(cache->vc, @@ -3959,8 +3900,7 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, } } - if (BKE_brush_use_size_pressure(scene, brush) && paint_supports_dynamic_size(brush)) { - cache->pixel_radius *= cache->pressure; + if (BKE_brush_use_size_pressure(scene, brush) && paint_supports_dynamic_size(brush, PAINT_SCULPT)) { cache->radius = cache->initial_radius * cache->pressure; } else { @@ -3969,77 +3909,25 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, cache->radius_squared = cache->radius * cache->radius; - if (!(brush->flag & BRUSH_ANCHORED || - ELEM4(brush->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_SNAKE_HOOK, - SCULPT_TOOL_THUMB, SCULPT_TOOL_ROTATE))) - { - copy_v2_v2(cache->tex_mouse, cache->mouse); - - if ((brush->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) && - (brush->flag & BRUSH_RANDOM_ROTATION) && - !(brush->flag & BRUSH_RAKE)) - { - cache->special_rotation = 2.0f * (float)M_PI * BLI_frand(); - } - } - if (brush->flag & BRUSH_ANCHORED) { - int hit = 0; - - const float dx = cache->mouse[0] - cache->initial_mouse[0]; - const float dy = cache->mouse[1] - cache->initial_mouse[1]; - - ups->anchored_size = cache->pixel_radius = sqrt(dx * dx + dy * dy); - - cache->special_rotation = atan2(dx, dy) + M_PI; - if (brush->flag & BRUSH_EDGE_TO_EDGE) { float halfway[2]; float out[3]; - - halfway[0] = dx * 0.5f + cache->initial_mouse[0]; - halfway[1] = dy * 0.5f + cache->initial_mouse[1]; + halfway[0] = 0.5f * (cache->mouse[0] + cache->initial_mouse[0]); + halfway[1] = 0.5f * (cache->mouse[1] + cache->initial_mouse[1]); if (sculpt_stroke_get_location(C, out, halfway)) { - copy_v3_v3(ups->anchored_location, out); - copy_v2_v2(ups->anchored_initial_mouse, halfway); - copy_v2_v2(cache->tex_mouse, halfway); - copy_v3_v3(cache->true_location, ups->anchored_location); - ups->anchored_size /= 2.0f; - cache->pixel_radius /= 2.0f; - hit = 1; + copy_v3_v3(cache->anchored_location, out); + copy_v3_v3(cache->true_location, cache->anchored_location); } } - if (!hit) - copy_v2_v2(ups->anchored_initial_mouse, cache->initial_mouse); - cache->radius = paint_calc_object_space_radius(paint_stroke_view_context(stroke), cache->true_location, - cache->pixel_radius); + ups->pixel_radius); cache->radius_squared = cache->radius * cache->radius; - copy_v3_v3(ups->anchored_location, cache->true_location); - - ups->draw_anchored = 1; - } - else if (brush->flag & BRUSH_RAKE) { - const float u = 0.5f; - const float v = 1 - u; - const float r = 20; - - const float dx = cache->last_rake[0] - cache->mouse[0]; - const float dy = cache->last_rake[1] - cache->mouse[1]; - - if (cache->first_time) { - copy_v2_v2(cache->last_rake, cache->mouse); - } - else if (dx * dx + dy * dy >= r * r) { - cache->special_rotation = atan2(dx, dy); - - cache->last_rake[0] = u * cache->last_rake[0] + v * cache->mouse[0]; - cache->last_rake[1] = u * cache->last_rake[1] + v * cache->mouse[1]; - } + copy_v3_v3(cache->anchored_location, cache->true_location); } sculpt_update_brush_delta(ups, ob, brush); @@ -4052,11 +3940,11 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, ups->draw_anchored = 1; copy_v2_v2(ups->anchored_initial_mouse, cache->initial_mouse); - copy_v3_v3(ups->anchored_location, cache->true_location); - ups->anchored_size = cache->pixel_radius; + copy_v3_v3(cache->anchored_location, cache->true_location); + ups->anchored_size = ups->pixel_radius; } - ups->special_rotation = cache->special_rotation; + cache->special_rotation = ups->brush_rotation; } /* Returns true if any of the smoothing modes are active (currently @@ -4312,6 +4200,7 @@ static int sculpt_stroke_test_start(bContext *C, struct wmOperator *op, static void sculpt_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr) { + UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings; Sculpt *sd = CTX_data_tool_settings(C)->sculpt; Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; @@ -4323,7 +4212,7 @@ static void sculpt_stroke_update_step(bContext *C, struct PaintStroke *stroke, P BKE_pbvh_bmesh_detail_size_set(ss->pbvh, (ss->cache->radius / - (float)ss->cache->pixel_radius) * + (float)ups->pixel_radius) * (float)sd->detail_size); if (sculpt_stroke_dynamic_topology(ss, brush)) { @@ -4368,7 +4257,6 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str /* reset values used to draw brush after completing the stroke */ ups->draw_anchored = 0; ups->draw_pressure = 0; - ups->special_rotation = 0; /* Finished */ if (ss->cache) { diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index fa6fd41f568..cd1acb53029 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -888,20 +888,25 @@ typedef struct UnifiedPaintSettings { /* rake rotation */ /* record movement of mouse so that rake can start at an intuitive angle */ - float last_x, last_y; - float last_angle; + float last_rake[2]; + int pad; - float special_rotation; + float brush_rotation; // all this below is used to communicate with the cursor drawing routine int draw_anchored; int anchored_size; - float anchored_location[3]; float anchored_initial_mouse[2]; /* drawing pressure */ int draw_pressure; float pressure_value; + + /* position of mouse, used to sample the texture */ + float tex_mouse[2]; + /* radius of brush, premultiplied with pressure. + * In case of anchored brushes contains that radius */ + float pixel_radius; } UnifiedPaintSettings; typedef enum { |