Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/sculpt_paint/paint_mask.c
| Show First 20 Lines • Show All 847 Lines • ▼ Show 20 Lines | static EnumPropertyItem prop_trim_operation_types[] = { | ||||
| {SCULPT_GESTURE_TRIM_JOIN, | {SCULPT_GESTURE_TRIM_JOIN, | ||||
| "JOIN", | "JOIN", | ||||
| 0, | 0, | ||||
| "Join", | "Join", | ||||
| "Join the new mesh as separate geometry, without preforming any boolean operation"}, | "Join the new mesh as separate geometry, without preforming any boolean operation"}, | ||||
| {0, NULL, 0, NULL, NULL}, | {0, NULL, 0, NULL, NULL}, | ||||
| }; | }; | ||||
| typedef enum eSculptTrimOrientationType { | |||||
| SCULPT_GESTURE_TRIM_ORIENTATION_VIEW, | |||||
| SCULPT_GESTURE_TRIM_ORIENTATION_SURFACE, | |||||
| } eSculptTrimOrientationType; | |||||
| static EnumPropertyItem prop_trim_orientation_types[] = { | |||||
| {SCULPT_GESTURE_TRIM_ORIENTATION_VIEW, | |||||
| "VIEW", | |||||
| 0, | |||||
| "View", | |||||
| "Use the view to orientate the trimming shape"}, | |||||
| {SCULPT_GESTURE_TRIM_ORIENTATION_SURFACE, | |||||
| "SURFACE", | |||||
| 0, | |||||
| "Surface", | |||||
| "Use the surface normal to orientate the trimming shape"}, | |||||
| {0, NULL, 0, NULL, NULL}, | |||||
| }; | |||||
| typedef struct SculptGestureTrimOperation { | typedef struct SculptGestureTrimOperation { | ||||
| SculptGestureOperation op; | SculptGestureOperation op; | ||||
| Mesh *mesh; | Mesh *mesh; | ||||
| float (*true_mesh_co)[3]; | float (*true_mesh_co)[3]; | ||||
| float depth_front; | float depth_front; | ||||
| float depth_back; | float depth_back; | ||||
| bool use_cursor_depth; | bool use_cursor_depth; | ||||
| eSculptTrimOperationType mode; | eSculptTrimOperationType mode; | ||||
| eSculptTrimOrientationType orientation; | |||||
| } SculptGestureTrimOperation; | } SculptGestureTrimOperation; | ||||
| static void sculpt_gesture_trim_normals_update(SculptGestureContext *sgcontext) | static void sculpt_gesture_trim_normals_update(SculptGestureContext *sgcontext) | ||||
| { | { | ||||
| SculptGestureTrimOperation *trim_operation = (SculptGestureTrimOperation *)sgcontext->operation; | SculptGestureTrimOperation *trim_operation = (SculptGestureTrimOperation *)sgcontext->operation; | ||||
| Mesh *trim_mesh = trim_operation->mesh; | Mesh *trim_mesh = trim_operation->mesh; | ||||
| BKE_mesh_calc_normals(trim_mesh); | BKE_mesh_calc_normals(trim_mesh); | ||||
| Show All 20 Lines | Mesh *result = BKE_mesh_from_bmesh_nomain(bm, | ||||
| .calc_object_remap = false, | .calc_object_remap = false, | ||||
| }), | }), | ||||
| trim_mesh); | trim_mesh); | ||||
| BM_mesh_free(bm); | BM_mesh_free(bm); | ||||
| BKE_mesh_free(trim_mesh); | BKE_mesh_free(trim_mesh); | ||||
| trim_operation->mesh = result; | trim_operation->mesh = result; | ||||
| } | } | ||||
| static void sculpt_gesture_trim_shape_orientation_normal_get(SculptGestureContext *sgcontext, | |||||
| float *r_origin, | |||||
| float *r_normal) | |||||
| { | |||||
| SculptGestureTrimOperation *trim_operation = (SculptGestureTrimOperation *)sgcontext->operation; | |||||
| switch (trim_operation->orientation) { | |||||
| case SCULPT_GESTURE_TRIM_ORIENTATION_VIEW: | |||||
| /* Use the view origin and normal in world space. The trimming mesh coordinates are | |||||
| * calculated in world space, aligned to the view, and then converted to object space to | |||||
| * store them in the final trimming mesh which is going to be used in the boolean operation. | |||||
| */ | |||||
| copy_v3_v3(r_origin, sgcontext->world_space_view_origin); | |||||
| copy_v3_v3(r_normal, sgcontext->world_space_view_normal); | |||||
| break; | |||||
| case SCULPT_GESTURE_TRIM_ORIENTATION_SURFACE: | |||||
| copy_v3_v3(r_origin, sgcontext->ss->gesture_initial_location); | |||||
| copy_v3_v3(r_normal, sgcontext->ss->gesture_initial_normal); | |||||
| break; | |||||
| } | |||||
| } | |||||
| static void sculpt_gesture_trim_calculate_depth(bContext *C, SculptGestureContext *sgcontext) | static void sculpt_gesture_trim_calculate_depth(bContext *C, SculptGestureContext *sgcontext) | ||||
| { | { | ||||
| SculptGestureTrimOperation *trim_operation = (SculptGestureTrimOperation *)sgcontext->operation; | SculptGestureTrimOperation *trim_operation = (SculptGestureTrimOperation *)sgcontext->operation; | ||||
| SculptSession *ss = sgcontext->ss; | SculptSession *ss = sgcontext->ss; | ||||
| ViewContext *vc = &sgcontext->vc; | ViewContext *vc = &sgcontext->vc; | ||||
| const int totvert = SCULPT_vertex_count_get(ss); | const int totvert = SCULPT_vertex_count_get(ss); | ||||
| float view_plane[4]; | float shape_plane[4]; | ||||
| const float *view_origin = sgcontext->world_space_view_origin; | float shape_origin[3]; | ||||
| const float *view_normal = sgcontext->world_space_view_normal; | float shape_normal[3]; | ||||
| sculpt_gesture_trim_shape_orientation_normal_get(sgcontext, shape_origin, shape_normal); | |||||
| plane_from_point_normal_v3(view_plane, view_origin, view_normal); | |||||
| trim_operation->depth_front = FLT_MAX; | trim_operation->depth_front = FLT_MAX; | ||||
| trim_operation->depth_back = -FLT_MAX; | trim_operation->depth_back = -FLT_MAX; | ||||
| for (int i = 0; i < totvert; i++) { | for (int i = 0; i < totvert; i++) { | ||||
| const float *vco = SCULPT_vertex_co_get(ss, i); | const float *vco = SCULPT_vertex_co_get(ss, i); | ||||
| /* Convert the coordinates to world space to calculate the depth. When generating the trimming | /* Convert the coordinates to world space to calculate the depth. When generating the trimming | ||||
| * mesh, coordinates are first calculated in world space, then converted to object space to | * mesh, coordinates are first calculated in world space, then converted to object space to | ||||
| * store them. */ | * store them. */ | ||||
| float world_space_vco[3]; | float world_space_vco[3]; | ||||
| mul_v3_m4v3(world_space_vco, vc->obact->obmat, vco); | mul_v3_m4v3(world_space_vco, vc->obact->obmat, vco); | ||||
| const float dist = dist_signed_to_plane_v3(world_space_vco, view_plane); | const float dist = dist_signed_to_plane_v3(world_space_vco, shape_plane); | ||||
| trim_operation->depth_front = min_ff(dist, trim_operation->depth_front); | trim_operation->depth_front = min_ff(dist, trim_operation->depth_front); | ||||
| trim_operation->depth_back = max_ff(dist, trim_operation->depth_back); | trim_operation->depth_back = max_ff(dist, trim_operation->depth_back); | ||||
| } | } | ||||
| if (trim_operation->use_cursor_depth) { | if (trim_operation->use_cursor_depth) { | ||||
| float world_space_gesture_initial_location[3]; | float world_space_gesture_initial_location[3]; | ||||
| mul_v3_m4v3( | mul_v3_m4v3( | ||||
| world_space_gesture_initial_location, vc->obact->obmat, ss->gesture_initial_location); | world_space_gesture_initial_location, vc->obact->obmat, ss->gesture_initial_location); | ||||
| const float mid_point_depth = ss->gesture_initial_hit ? | |||||
| float mid_point_depth; | |||||
| if (trim_operation->orientation == SCULPT_GESTURE_TRIM_ORIENTATION_VIEW) { | |||||
| mid_point_depth = ss->gesture_initial_hit ? | |||||
| dist_signed_to_plane_v3(world_space_gesture_initial_location, | dist_signed_to_plane_v3(world_space_gesture_initial_location, | ||||
| view_plane) : | shape_plane) : | ||||
| (trim_operation->depth_back + trim_operation->depth_front) * | (trim_operation->depth_back + trim_operation->depth_front) * 0.5f; | ||||
| 0.5f; | } | ||||
| else { | |||||
| mid_point_depth = ss->gesture_initial_hit ? | |||||
| 0.0f : | |||||
| (trim_operation->depth_back + trim_operation->depth_front) * 0.5f; | |||||
| } | |||||
| Sculpt *sd = CTX_data_tool_settings(C)->sculpt; | Sculpt *sd = CTX_data_tool_settings(C)->sculpt; | ||||
| Brush *brush = BKE_paint_brush(&sd->paint); | Brush *brush = BKE_paint_brush(&sd->paint); | ||||
| Scene *scene = CTX_data_scene(C); | Scene *scene = CTX_data_scene(C); | ||||
| const float depth_radius = BKE_brush_unprojected_radius_get(scene, brush); | const float depth_radius = BKE_brush_unprojected_radius_get(scene, brush); | ||||
| trim_operation->depth_front = mid_point_depth - depth_radius; | trim_operation->depth_front = mid_point_depth - depth_radius; | ||||
| trim_operation->depth_back = mid_point_depth + depth_radius; | trim_operation->depth_back = mid_point_depth + depth_radius; | ||||
| Show All 21 Lines | static void sculpt_gesture_trim_geometry_generate(SculptGestureContext *sgcontext) | ||||
| if (!trim_operation->use_cursor_depth) { | if (!trim_operation->use_cursor_depth) { | ||||
| /* When using cursor depth, don't modify the depth set by the cursor radius. If full depth is | /* When using cursor depth, don't modify the depth set by the cursor radius. If full depth is | ||||
| * used, adding a little padding to the trimming shape can help avoiding booleans with coplanar | * used, adding a little padding to the trimming shape can help avoiding booleans with coplanar | ||||
| * faces. */ | * faces. */ | ||||
| depth_front -= 0.1f; | depth_front -= 0.1f; | ||||
| depth_back += 0.1f; | depth_back += 0.1f; | ||||
| } | } | ||||
| /* Use the view origin and normal in world space. The trimming mesh coordinates are calculated in | float shape_origin[3]; | ||||
| * world space, aligned to the view, and then converted to object space to store them in the | float shape_normal[3]; | ||||
| * final trimming mesh which is going to be used in the boolean operation. | float shape_plane[4]; | ||||
| */ | sculpt_gesture_trim_shape_orientation_normal_get(sgcontext, shape_origin, shape_normal); | ||||
| const float *view_origin = sgcontext->world_space_view_origin; | plane_from_point_normal_v3(shape_plane, shape_origin, shape_normal); | ||||
| const float *view_normal = sgcontext->world_space_view_normal; | |||||
| const float(*ob_imat)[4] = vc->obact->imat; | const float(*ob_imat)[4] = vc->obact->imat; | ||||
| /* Write vertices coordinates for the front face. */ | /* Write vertices coordinates for the front face. */ | ||||
| float depth_point[3]; | float depth_point[3]; | ||||
| madd_v3_v3v3fl(depth_point, view_origin, view_normal, depth_front); | madd_v3_v3v3fl(depth_point, shape_origin, shape_normal, depth_front); | ||||
| for (int i = 0; i < tot_screen_points; i++) { | for (int i = 0; i < tot_screen_points; i++) { | ||||
| float new_point[3]; | float new_point[3]; | ||||
| if (trim_operation->orientation == SCULPT_GESTURE_TRIM_ORIENTATION_VIEW) { | |||||
| ED_view3d_win_to_3d(vc->v3d, region, depth_point, screen_points[i], new_point); | ED_view3d_win_to_3d(vc->v3d, region, depth_point, screen_points[i], new_point); | ||||
| } | |||||
| else { | |||||
| ED_view3d_win_to_3d_on_plane(region, shape_plane, screen_points[i], false, new_point); | |||||
| madd_v3_v3fl(new_point, shape_normal, depth_front); | |||||
| } | |||||
| mul_v3_m4v3(trim_operation->mesh->mvert[i].co, ob_imat, new_point); | mul_v3_m4v3(trim_operation->mesh->mvert[i].co, ob_imat, new_point); | ||||
| mul_v3_m4v3(trim_operation->true_mesh_co[i], ob_imat, new_point); | mul_v3_m4v3(trim_operation->true_mesh_co[i], ob_imat, new_point); | ||||
| } | } | ||||
| /* Write vertices coordinates for the back face. */ | /* Write vertices coordinates for the back face. */ | ||||
| madd_v3_v3v3fl(depth_point, view_origin, view_normal, depth_back); | madd_v3_v3v3fl(depth_point, shape_origin, shape_normal, depth_back); | ||||
| for (int i = 0; i < tot_screen_points; i++) { | for (int i = 0; i < tot_screen_points; i++) { | ||||
| float new_point[3]; | float new_point[3]; | ||||
| if (trim_operation->orientation == SCULPT_GESTURE_TRIM_ORIENTATION_VIEW) { | |||||
| ED_view3d_win_to_3d(vc->v3d, region, depth_point, screen_points[i], new_point); | ED_view3d_win_to_3d(vc->v3d, region, depth_point, screen_points[i], new_point); | ||||
| } | |||||
| else { | |||||
| ED_view3d_win_to_3d_on_plane(region, shape_plane, screen_points[i], false, new_point); | |||||
| madd_v3_v3fl(new_point, shape_normal, depth_back); | |||||
| } | |||||
| mul_v3_m4v3(trim_operation->mesh->mvert[i + tot_screen_points].co, ob_imat, new_point); | mul_v3_m4v3(trim_operation->mesh->mvert[i + tot_screen_points].co, ob_imat, new_point); | ||||
| mul_v3_m4v3(trim_operation->true_mesh_co[i + tot_screen_points], ob_imat, new_point); | mul_v3_m4v3(trim_operation->true_mesh_co[i + tot_screen_points], ob_imat, new_point); | ||||
| } | } | ||||
| /* Get the triangulation for the front/back poly. */ | /* Get the triangulation for the front/back poly. */ | ||||
| const int tot_tris_face = tot_screen_points - 2; | const int tot_tris_face = tot_screen_points - 2; | ||||
| uint(*r_tris)[3] = MEM_malloc_arrayN(tot_tris_face, 3 * sizeof(uint), "tris"); | uint(*r_tris)[3] = MEM_malloc_arrayN(tot_tris_face, 3 * sizeof(uint), "tris"); | ||||
| BLI_polyfill_calc(screen_points, tot_screen_points, 0, r_tris); | BLI_polyfill_calc(screen_points, tot_screen_points, 0, r_tris); | ||||
| ▲ Show 20 Lines • Show All 198 Lines • ▼ Show 20 Lines | static void sculpt_gesture_init_trim_properties(SculptGestureContext *sgcontext, wmOperator *op) | ||||
| trim_operation->op.sculpt_gesture_begin = sculpt_gesture_trim_begin; | trim_operation->op.sculpt_gesture_begin = sculpt_gesture_trim_begin; | ||||
| trim_operation->op.sculpt_gesture_apply_for_symmetry_pass = | trim_operation->op.sculpt_gesture_apply_for_symmetry_pass = | ||||
| sculpt_gesture_trim_apply_for_symmetry_pass; | sculpt_gesture_trim_apply_for_symmetry_pass; | ||||
| trim_operation->op.sculpt_gesture_end = sculpt_gesture_trim_end; | trim_operation->op.sculpt_gesture_end = sculpt_gesture_trim_end; | ||||
| trim_operation->mode = RNA_enum_get(op->ptr, "trim_mode"); | trim_operation->mode = RNA_enum_get(op->ptr, "trim_mode"); | ||||
| trim_operation->use_cursor_depth = RNA_enum_get(op->ptr, "use_cursor_depth"); | trim_operation->use_cursor_depth = RNA_enum_get(op->ptr, "use_cursor_depth"); | ||||
| trim_operation->orientation = RNA_enum_get(op->ptr, "trim_orientation"); | |||||
| /* If the cursor was not over the mesh, force the orientation to view. */ | |||||
| if (!sgcontext->ss->gesture_initial_hit) { | |||||
| trim_operation->orientation = SCULPT_GESTURE_TRIM_ORIENTATION_VIEW; | |||||
| } | |||||
| } | } | ||||
| static void sculpt_trim_gesture_operator_properties(wmOperatorType *ot) | static void sculpt_trim_gesture_operator_properties(wmOperatorType *ot) | ||||
| { | { | ||||
| RNA_def_enum(ot->srna, | RNA_def_enum(ot->srna, | ||||
| "trim_mode", | "trim_mode", | ||||
| prop_trim_operation_types, | prop_trim_operation_types, | ||||
| SCULPT_GESTURE_TRIM_DIFFERENCE, | SCULPT_GESTURE_TRIM_DIFFERENCE, | ||||
| "Trim Mode", | "Trim Mode", | ||||
| NULL); | NULL); | ||||
| RNA_def_boolean( | RNA_def_boolean( | ||||
| ot->srna, | ot->srna, | ||||
| "use_cursor_depth", | "use_cursor_depth", | ||||
| false, | false, | ||||
| "Use Cursor for Depth", | "Use Cursor for Depth", | ||||
| "Use cursor location and radius for the dimensions and position of the trimming shape"); | "Use cursor location and radius for the dimensions and position of the trimming shape"); | ||||
| RNA_def_enum(ot->srna, | |||||
| "trim_orientation", | |||||
| prop_trim_orientation_types, | |||||
| SCULPT_GESTURE_TRIM_ORIENTATION_VIEW, | |||||
| "Shape Orientation", | |||||
| NULL); | |||||
| } | } | ||||
| /* Project Gesture Operation. */ | /* Project Gesture Operation. */ | ||||
| typedef struct SculptGestureProjectOperation { | typedef struct SculptGestureProjectOperation { | ||||
| SculptGestureOperation operation; | SculptGestureOperation operation; | ||||
| } SculptGestureProjectOperation; | } SculptGestureProjectOperation; | ||||
| ▲ Show 20 Lines • Show All 169 Lines • ▼ Show 20 Lines | static int sculpt_trim_gesture_box_invoke(bContext *C, wmOperator *op, const wmEvent *event) | ||||
| SculptSession *ss = ob->sculpt; | SculptSession *ss = ob->sculpt; | ||||
| SculptCursorGeometryInfo sgi; | SculptCursorGeometryInfo sgi; | ||||
| float mouse[2] = {event->mval[0], event->mval[1]}; | float mouse[2] = {event->mval[0], event->mval[1]}; | ||||
| SCULPT_vertex_random_access_ensure(ss); | SCULPT_vertex_random_access_ensure(ss); | ||||
| ss->gesture_initial_hit = SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false); | ss->gesture_initial_hit = SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false); | ||||
| if (ss->gesture_initial_hit) { | if (ss->gesture_initial_hit) { | ||||
| copy_v3_v3(ss->gesture_initial_location, sgi.location); | copy_v3_v3(ss->gesture_initial_location, sgi.location); | ||||
| copy_v3_v3(ss->gesture_initial_normal, sgi.normal); | |||||
| } | } | ||||
| return WM_gesture_box_invoke(C, op, event); | return WM_gesture_box_invoke(C, op, event); | ||||
| } | } | ||||
| static int sculpt_trim_gesture_lasso_exec(bContext *C, wmOperator *op) | static int sculpt_trim_gesture_lasso_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| Object *object = CTX_data_active_object(C); | Object *object = CTX_data_active_object(C); | ||||
| Show All 19 Lines | static int sculpt_trim_gesture_lasso_invoke(bContext *C, wmOperator *op, const wmEvent *event) | ||||
| SculptSession *ss = ob->sculpt; | SculptSession *ss = ob->sculpt; | ||||
| SculptCursorGeometryInfo sgi; | SculptCursorGeometryInfo sgi; | ||||
| float mouse[2] = {event->mval[0], event->mval[1]}; | float mouse[2] = {event->mval[0], event->mval[1]}; | ||||
| SCULPT_vertex_random_access_ensure(ss); | SCULPT_vertex_random_access_ensure(ss); | ||||
| ss->gesture_initial_hit = SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false); | ss->gesture_initial_hit = SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false); | ||||
| if (ss->gesture_initial_hit) { | if (ss->gesture_initial_hit) { | ||||
| copy_v3_v3(ss->gesture_initial_location, sgi.location); | copy_v3_v3(ss->gesture_initial_location, sgi.location); | ||||
| copy_v3_v3(ss->gesture_initial_normal, sgi.normal); | |||||
| } | } | ||||
| return WM_gesture_lasso_invoke(C, op, event); | return WM_gesture_lasso_invoke(C, op, event); | ||||
| } | } | ||||
| static int project_gesture_line_exec(bContext *C, wmOperator *op) | static int project_gesture_line_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| SculptGestureContext *sgcontext = sculpt_gesture_init_from_line(C, op); | SculptGestureContext *sgcontext = sculpt_gesture_init_from_line(C, op); | ||||
| ▲ Show 20 Lines • Show All 166 Lines • Show Last 20 Lines | |||||