Commit: d6d51674a2fee3a1110d241b96d31480ce440cf1 Author: Pablo Dobarro Date: Fri Aug 16 00:12:43 2019 +0200 Branches: sculpt-mode-features https://developer.blender.org/rBd6d51674a2fee3a1110d241b96d31480ce440cf1
Sculpt: Pose brush This commit also includes the MOUSE_INBETWEEN events fix for other brushes. =================================================================== M source/blender/blenkernel/intern/brush.c M source/blender/editors/sculpt_paint/paint_stroke.c M source/blender/editors/sculpt_paint/sculpt.c M source/blender/editors/sculpt_paint/sculpt_intern.h M source/blender/makesdna/DNA_brush_types.h M source/blender/makesrna/intern/rna_brush.c =================================================================== diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 56ebfe72162..262f47655f6 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -895,6 +895,7 @@ void BKE_brush_sculpt_reset(Brush *br) br->add_col[2] = 0.750000; break; case SCULPT_TOOL_GRAB: + case SCULPT_TOOL_POSE: case SCULPT_TOOL_SNAKE_HOOK: case SCULPT_TOOL_THUMB: br->size = 75; diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 5f3075b12f5..7df06d99509 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -219,6 +219,7 @@ static bool paint_tool_require_location(Brush *brush, ePaintMode mode) case PAINT_MODE_SCULPT: if (ELEM(brush->sculpt_tool, SCULPT_TOOL_GRAB, + SCULPT_TOOL_POSE, SCULPT_TOOL_ROTATE, SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB)) { @@ -234,6 +235,27 @@ static bool paint_tool_require_location(Brush *brush, ePaintMode mode) return true; } +static bool paint_tool_require_inbetween_mouse_events(Brush *brush, ePaintMode mode) +{ + switch (mode) { + case PAINT_MODE_SCULPT: + if (ELEM(brush->sculpt_tool, + SCULPT_TOOL_GRAB, + SCULPT_TOOL_ROTATE, + SCULPT_TOOL_THUMB, + SCULPT_TOOL_POSE)) { + return false; + } + else { + return true; + } + default: + break; + } + + return true; +} + /* Initialize the stroke cache variants from operator properties */ static bool paint_brush_update(bContext *C, Brush *brush, @@ -872,6 +894,7 @@ static bool sculpt_is_grab_tool(Brush *br) { return ELEM(br->sculpt_tool, SCULPT_TOOL_GRAB, + SCULPT_TOOL_POSE, SCULPT_TOOL_THUMB, SCULPT_TOOL_ROTATE, SCULPT_TOOL_SNAKE_HOOK); @@ -1206,6 +1229,10 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event) bool redraw = false; float pressure; + if (event->type == INBETWEEN_MOUSEMOVE && !paint_tool_require_inbetween_mouse_events(br, mode)) { + return OPERATOR_RUNNING_MODAL; + } + /* see if tablet affects event. Line, anchored and drag dot strokes do not support pressure */ pressure = ((br->flag & (BRUSH_LINE | BRUSH_ANCHORED | BRUSH_DRAG_DOT)) ? 1.0f : diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 6803f01a26c..701ccb799d0 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -426,8 +426,12 @@ static bool sculpt_has_active_modifiers(Scene *scene, Object *ob) static bool sculpt_tool_needs_original(const char sculpt_tool) { - return ELEM( - sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE, SCULPT_TOOL_THUMB, SCULPT_TOOL_LAYER); + return ELEM(sculpt_tool, + SCULPT_TOOL_GRAB, + SCULPT_TOOL_ROTATE, + SCULPT_TOOL_THUMB, + SCULPT_TOOL_LAYER, + SCULPT_TOOL_POSE); } static bool sculpt_tool_is_proxy_used(const char sculpt_tool) @@ -1528,6 +1532,9 @@ static float brush_strength(const Sculpt *sd, case SCULPT_TOOL_GRAB: return root_alpha * feather; + case SCULPT_TOOL_POSE: + return root_alpha * feather; + case SCULPT_TOOL_ROTATE: return alpha * pressure * feather; @@ -3420,6 +3427,94 @@ static void do_pinch_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode BLI_task_parallel_range(0, totnode, &data, do_pinch_brush_task_cb_ex, &settings); } +static bool check_vertex_pivot_symmetry(float vco[3], float pco[3], char symm); +static void do_pose_brush_task_cb_ex(void *__restrict userdata, + const int n, + const ParallelRangeTLS *__restrict tls) +{ + SculptThreadedTaskData *data = userdata; + SculptSession *ss = data->ob->sculpt; + + PBVHVertexIter vd; + float disp[3], val[3]; + float final_pos[3]; + + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) + { + + if (check_vertex_pivot_symmetry(ss->cache->pose_orco[vd.index], + data->pose_initial_co, + ss->cache->mirror_symmetry_pass)) { + copy_v3_v3(val, ss->cache->pose_orco[vd.index]); + mul_m4_v3(data->transform_trans_inv, val); + mul_m4_v3(data->transform_rot, val); + mul_m4_v3(data->transform_trans, val); + sub_v3_v3v3(disp, val, ss->cache->pose_orco[vd.index]); + + mul_v3_fl(disp, ss->cache->pose_factor[vd.index]); + float mask = vd.mask ? *vd.mask : 0.0f; + mul_v3_fl(disp, 1.0f - mask); + add_v3_v3v3(final_pos, ss->cache->pose_orco[vd.index], disp); + sculpt_vertex_co_set(ss, vd.index, final_pos); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; + } + } + } + BKE_pbvh_vertex_iter_end; +} + +static void do_pose_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) +{ + SculptSession *ss = ob->sculpt; + Brush *brush = BKE_paint_brush(&sd->paint); + float grab_delta[3], rot_quat[4], initial_v[3], current_v[3], temp[3]; + float pose_origin[3]; + float pose_initial_co[3]; + float transform_rot[4][4], transform_trans[4][4], transform_trans_inv[4][4]; + + copy_v3_v3(grab_delta, ss->cache->grab_delta_symmetry); + + copy_v3_v3(pose_origin, ss->cache->pose_origin); + flip_v3(pose_origin, (char)ss->cache->mirror_symmetry_pass); + + copy_v3_v3(pose_initial_co, ss->cache->pose_initial_co); + flip_v3(pose_initial_co, (char)ss->cache->mirror_symmetry_pass); + + sub_v3_v3v3(initial_v, pose_initial_co, pose_origin); + normalize_v3(initial_v); + + add_v3_v3v3(temp, pose_initial_co, grab_delta); + sub_v3_v3v3(current_v, temp, pose_origin); + normalize_v3(current_v); + + rotation_between_vecs_to_quat(rot_quat, initial_v, current_v); + unit_m4(transform_rot); + unit_m4(transform_trans); + quat_to_mat4(transform_rot, rot_quat); + translate_m4(transform_trans, pose_origin[0], pose_origin[1], pose_origin[2]); + invert_m4_m4(transform_trans_inv, transform_trans); + + SculptThreadedTaskData data = { + .sd = sd, + .ob = ob, + .brush = brush, + .nodes = nodes, + .grab_delta = grab_delta, + .pose_origin = pose_origin, + .pose_initial_co = pose_initial_co, + .transform_rot = transform_rot, + .transform_trans = transform_trans, + .transform_trans_inv = transform_trans_inv, + }; + + ParallelRangeSettings settings; + BLI_parallel_range_settings_defaults(&settings); + settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT); + BLI_task_parallel_range(0, totnode, &data, do_pose_brush_task_cb_ex, &settings); +} + static void do_grab_brush_task_cb_ex(void *__restrict userdata, const int n, const ParallelRangeTLS *__restrict tls) @@ -5074,6 +5169,151 @@ static float *sculpt_topology_automasking_init(Sculpt *sd, Object *ob, int initi return automask_factor; } +static void pose_brush_init_task_cb_ex(void *__restrict userdata, + const int n, + const ParallelRangeTLS *__restrict tls) +{ + SculptThreadedTaskData *data = userdata; + SculptSession *ss = data->ob->sculpt; + const Brush *brush = data->brush; + + PBVHVertexIter vd; + + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) + { + SculptVertexNeighbourIter ni; + float avg = 0; + int total = 0; + sculpt_vertex_neighbours_iter_begin(ss, vd.index, ni) + { + avg += ss->cache->pose_factor[ni.index]; + total++; + } + sculpt_vertex_neighbours_iter_end(ni) + + if (total > 0) + { + ss->cache->pose_factor[vd.index] = avg / (float)total; + } + } + BKE_pbvh_vertex_iter_end; +} + +static bool sculpt_pose_brush_is_vertex_inside_brush_radius(float vertex[3], + float br_co[3], + float radius, + char symm) +{ + int i; + for (i = 0; i <= symm; ++i) { + if (i == 0 || (symm & i && (symm != 5 || i != 3) && (symm != 6 || (i != 3 && i != 5)))) { + float location[3]; + flip_v3_v3(location, br_co, i); + if (len_v3v3(location, vertex) < radius) { + return true; + } + } + } + return false; +} + +static void sculpt_pose_brush_init(Sculpt *sd, Object *ob, SculptSession *ss, Brush *br) +{ + ss->cache->pose_factor = MEM_callocN(sculpt_vertex_count_get(ss) * sizeof(float), "Pose factor"); + ss->cache->pose_orco = MEM_callocN(sculpt_vertex_count_get(ss) * 3 * sizeof(float), "Pose orco"); + + copy_v3_v3(ss->cache->pose_initial_co, ss->cache->location); + + char *visited_vertices = MEM_callocN(sculpt_vertex_count_get(ss) * sizeof(char), "prevmask"); + GSQueue *queue = BLI_gsqueue_new(sizeof(vertex_topology_it)); + + float tot_co = 0; + zero_v3(ss->cache->pose_origin); + + for (int i = 0; i < sculpt_vertex_count_get(ss); i++) { + copy_v3_v3(ss->cache->pose_orco[i], sculpt_vertex_co_get(ss, i)); + } + + vertex_topology_it mevit; + + const char symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL; + int i; + for (i = 0; i <= symm; ++i) { + if (i == 0 || (symm & i && (symm != 5 || i != 3) && (symm != 6 || (i != 3 && i != 5)))) { + float location[3]; + flip_v3_v3(location, sculpt_vertex_co_get(ss, sculpt_active_vertex_get(ss)), i); + if (i == 0) { + mevit.v = sculpt_active_vertex_get(ss); + } + else { + mevit.v = sculpt_nearest_vertex_get(sd, ob, location, FLT_MAX, false); + } + if (mevit.v != -1) { + mevit.it = 1; + BLI_gsqueue_push(queue, &mevit); + } + } + } + + while (!BLI_gsqueue_is_empty(queue)) { + @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org https://lists.blender.org/mailman/listinfo/bf-blender-cvs