diff options
author | Nicholas Bishop <nicholasbishop@gmail.com> | 2012-05-15 08:50:57 +0400 |
---|---|---|
committer | Nicholas Bishop <nicholasbishop@gmail.com> | 2012-05-15 08:50:57 +0400 |
commit | 9afb36b1e326a7fbaa3d18fbfefa26b4ab316a6e (patch) | |
tree | 58d85c78ca91c0ae5531017f7d406ae16e59b417 /source/blender | |
parent | a8e9d5533f51455febc40d386c8c2ce0cc561b7a (diff) |
Add 'area' mode for brush texture projection.
This is similar to the 'view' mode, but uses the average local surface
normal rather than the view normal for projection.
Original code by Jason Wilkins (GSoC).
Documentation:
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Sculpting#Brush_Map_Mode
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt.c | 111 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_texture_types.h | 1 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_brush.c | 16 |
3 files changed, 115 insertions, 13 deletions
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 4c19f3ce93e..a124afddc8e 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -253,6 +253,10 @@ typedef struct StrokeCache { transforms */ float sculpt_normal[3]; float sculpt_normal_symm[3]; + + /* Used for wrap texture mode, local_mat gets calculated by + calc_brush_local_mat() and used in tex_strength(). */ + float brush_local_mat[4][4]; float last_center[3]; int radial_symmetry_pass; @@ -786,17 +790,31 @@ static float tex_strength(SculptSession *ss, Brush *br, float point[3], x = point_2d[0]; y = point_2d[1]; } + else 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; - x /= ss->cache->vc->ar->winx; - y /= ss->cache->vc->ar->winy; + mul_m4_v3(ss->cache->brush_local_mat, symm_point); - if (mtex->brush_map_mode == MTEX_MAP_MODE_TILED) { - x -= 0.5f; - y -= 0.5f; + 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; + + 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 *= ss->cache->vc->ar->winx / radius; + y *= ss->cache->vc->ar->winy / radius; + } /* it is probably worth optimizing for those cases where * the texture is not rotated by skipping the calls to @@ -1021,6 +1039,78 @@ static void update_sculpt_normal(Sculpt *sd, Object *ob, } } +static void calc_local_y(ViewContext *vc, const float center[3], float y[3]) +{ + Object *ob = vc->obact; + float loc[3], mval_f[2] = {0.0f, 1.0f}; + + mul_v3_m4v3(loc, ob->imat, center); + initgrabz(vc->rv3d, loc[0], loc[1], loc[2]); + + ED_view3d_win_to_delta(vc->ar, mval_f, y); + normalize_v3(y); + + add_v3_v3(y, ob->loc); + mul_m4_v3(ob->imat, y); +} + +static void calc_brush_local_mat(const Brush *brush, Object *ob, + float local_mat[4][4]) +{ + const StrokeCache *cache = ob->sculpt->cache; + float tmat[4][4]; + float mat[4][4]; + float scale[4][4]; + float angle, v[3]; + float up[3]; + + /* Ensure ob->imat is up to date */ + invert_m4_m4(ob->imat, ob->obmat); + + /* Initialize last column of matrix */ + mat[0][3] = 0; + mat[1][3] = 0; + mat[2][3] = 0; + mat[3][3] = 1; + + /* Get view's up vector in object-space */ + calc_local_y(cache->vc, cache->location, up); + + /* Calculate the X axis of the local matrix */ + cross_v3_v3v3(v, up, cache->sculpt_normal); + /* Apply rotation (user angle, rake, etc.) to X axis */ + angle = brush->mtex.rot - cache->special_rotation; + rotate_v3_v3v3fl(mat[0], v, cache->sculpt_normal, angle); + + /* Get other axes */ + cross_v3_v3v3(mat[1], cache->sculpt_normal, mat[0]); + copy_v3_v3(mat[2], cache->sculpt_normal); + + /* Set location */ + copy_v3_v3(mat[3], cache->location); + + /* Scale by brush radius */ + normalize_m4(mat); + scale_m4_fl(scale, cache->radius); + mult_m4_m4m4(tmat, mat, scale); + + /* Return inverse (for converting from modelspace coords to local + area coords) */ + invert_m4_m4(local_mat, tmat); +} + +static void update_brush_local_mat(Sculpt *sd, Object *ob) +{ + StrokeCache *cache = ob->sculpt->cache; + + if (cache->mirror_symmetry_pass == 0 && + cache->radial_symmetry_pass == 0) + { + calc_brush_local_mat(paint_brush(&sd->paint), ob, + cache->brush_local_mat); + } +} + /* Test whether the StrokeCache.sculpt_normal needs update in do_brush_action() */ static int brush_needs_sculpt_normal(const Brush *brush) @@ -1038,7 +1128,9 @@ static int brush_needs_sculpt_normal(const Brush *brush) SCULPT_TOOL_LAYER, SCULPT_TOOL_NUDGE, SCULPT_TOOL_ROTATE, - SCULPT_TOOL_THUMB)); + SCULPT_TOOL_THUMB) || + + (brush->mtex.brush_map_mode == MTEX_MAP_MODE_AREA)); } /* For the smooth brush, uses the neighboring vertices around vert to calculate @@ -2621,6 +2713,9 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush) if (brush_needs_sculpt_normal(brush)) update_sculpt_normal(sd, ob, nodes, totnode); + if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_AREA) + update_brush_local_mat(sd, ob); + /* Apply one type of brush action */ switch (brush->sculpt_tool) { case SCULPT_TOOL_DRAW: diff --git a/source/blender/makesdna/DNA_texture_types.h b/source/blender/makesdna/DNA_texture_types.h index 413c3502c7e..7497f5e7449 100644 --- a/source/blender/makesdna/DNA_texture_types.h +++ b/source/blender/makesdna/DNA_texture_types.h @@ -520,6 +520,7 @@ typedef struct ColorMapping { #define MTEX_MAP_MODE_VIEW 0 #define MTEX_MAP_MODE_TILED 1 #define MTEX_MAP_MODE_3D 2 +#define MTEX_MAP_MODE_AREA 3 /* **************** EnvMap ********************* */ diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index 0a8c241f5ee..2247e7cf5a8 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -172,7 +172,9 @@ static int rna_SculptCapabilities_has_plane_offset_get(PointerRNA *ptr) static int rna_SculptCapabilities_has_random_texture_angle_get(PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; - return ((br->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) && + return (ELEM(br->mtex.brush_map_mode, + MTEX_MAP_MODE_VIEW, + MTEX_MAP_MODE_AREA) && !(br->flag & BRUSH_ANCHORED) && !ELEM4(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE, @@ -233,15 +235,18 @@ static int rna_SculptCapabilities_has_strength_get(PointerRNA *ptr) static int rna_SculptCapabilities_has_texture_angle_get(PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; - return ELEM(br->mtex.brush_map_mode, - MTEX_MAP_MODE_VIEW, - MTEX_MAP_MODE_TILED); + return ELEM3(br->mtex.brush_map_mode, + MTEX_MAP_MODE_VIEW, + MTEX_MAP_MODE_AREA, + MTEX_MAP_MODE_TILED); } static int rna_SculptCapabilities_has_texture_angle_source_get(PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; - return br->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW; + return ELEM(br->mtex.brush_map_mode, + MTEX_MAP_MODE_VIEW, + MTEX_MAP_MODE_AREA); } static PointerRNA rna_Brush_sculpt_capabilities_get(PointerRNA *ptr) @@ -416,6 +421,7 @@ static void rna_def_brush_texture_slot(BlenderRNA *brna) static EnumPropertyItem prop_map_mode_items[] = { {MTEX_MAP_MODE_VIEW, "VIEW_PLANE", 0, "View Plane", ""}, + {MTEX_MAP_MODE_AREA, "AREA_PLANE", 0, "Area Plane", ""}, {MTEX_MAP_MODE_TILED, "TILED", 0, "Tiled", ""}, {MTEX_MAP_MODE_3D, "3D", 0, "3D", ""}, {0, NULL, 0, NULL, NULL} |