Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/gpencil/gpencil_utils.c
| Show First 20 Lines • Show All 606 Lines • ▼ Show 20 Lines | if (area->spacetype == SPACE_VIEW3D) { | ||||
| if (rv3d->persp == RV3D_CAMOB) { | if (rv3d->persp == RV3D_CAMOB) { | ||||
| ED_view3d_calc_camera_border( | ED_view3d_calc_camera_border( | ||||
| scene, depsgraph, region, v3d, rv3d, &r_gsc->subrect_data, true); | scene, depsgraph, region, v3d, rv3d, &r_gsc->subrect_data, true); | ||||
| r_gsc->subrect = &r_gsc->subrect_data; | r_gsc->subrect = &r_gsc->subrect_data; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| void gpencil_point_to_parent_space(const bGPDspoint *pt, | void gpencil_point_to_world_space(const bGPDspoint *pt, | ||||
| const float diff_mat[4][4], | const float diff_mat[4][4], | ||||
| bGPDspoint *r_pt) | bGPDspoint *r_pt) | ||||
| { | { | ||||
| float fpt[3]; | mul_v3_m4v3(&r_pt->x, diff_mat, &pt->x); | ||||
| mul_v3_m4v3(fpt, diff_mat, &pt->x); | |||||
| copy_v3_v3(&r_pt->x, fpt); | |||||
| } | } | ||||
| void gpencil_apply_parent(Depsgraph *depsgraph, Object *obact, bGPDlayer *gpl, bGPDstroke *gps) | void gpencil_world_to_object_space(Depsgraph *depsgraph, | ||||
| Object *obact, | |||||
| bGPDlayer *gpl, | |||||
| bGPDstroke *gps) | |||||
| { | { | ||||
| bGPDspoint *pt; | bGPDspoint *pt; | ||||
| int i; | int i; | ||||
| /* undo matrix */ | /* undo matrix */ | ||||
| float diff_mat[4][4]; | float diff_mat[4][4]; | ||||
| float inverse_diff_mat[4][4]; | float inverse_diff_mat[4][4]; | ||||
| float fpt[3]; | |||||
| BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); | BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); | ||||
| invert_m4_m4(inverse_diff_mat, diff_mat); | invert_m4_m4(inverse_diff_mat, diff_mat); | ||||
| for (i = 0; i < gps->totpoints; i++) { | for (i = 0; i < gps->totpoints; i++) { | ||||
| pt = &gps->points[i]; | pt = &gps->points[i]; | ||||
| mul_v3_m4v3(fpt, inverse_diff_mat, &pt->x); | mul_m4_v3(inverse_diff_mat, &pt->x); | ||||
| copy_v3_v3(&pt->x, fpt); | |||||
| } | } | ||||
| } | } | ||||
| void gpencil_apply_parent_point(Depsgraph *depsgraph, | void gpencil_world_to_object_space_point(Depsgraph *depsgraph, | ||||
| Object *obact, | Object *obact, | ||||
| bGPDlayer *gpl, | bGPDlayer *gpl, | ||||
| bGPDspoint *pt) | bGPDspoint *pt) | ||||
| { | { | ||||
| /* undo matrix */ | /* undo matrix */ | ||||
| float diff_mat[4][4]; | float diff_mat[4][4]; | ||||
| float inverse_diff_mat[4][4]; | float inverse_diff_mat[4][4]; | ||||
| float fpt[3]; | |||||
| BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); | BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); | ||||
| invert_m4_m4(inverse_diff_mat, diff_mat); | invert_m4_m4(inverse_diff_mat, diff_mat); | ||||
| mul_v3_m4v3(fpt, inverse_diff_mat, &pt->x); | mul_m4_v3(inverse_diff_mat, &pt->x); | ||||
| copy_v3_v3(&pt->x, fpt); | |||||
| } | } | ||||
| void gpencil_point_to_xy( | void gpencil_point_to_xy( | ||||
| const GP_SpaceConversion *gsc, const bGPDstroke *gps, const bGPDspoint *pt, int *r_x, int *r_y) | const GP_SpaceConversion *gsc, const bGPDstroke *gps, const bGPDspoint *pt, int *r_x, int *r_y) | ||||
| { | { | ||||
| const ARegion *region = gsc->region; | const ARegion *region = gsc->region; | ||||
| const View2D *v2d = gsc->v2d; | const View2D *v2d = gsc->v2d; | ||||
| const rctf *subrect = gsc->subrect; | const rctf *subrect = gsc->subrect; | ||||
| ▲ Show 20 Lines • Show All 268 Lines • ▼ Show 20 Lines | void ED_gpencil_project_stroke_to_view(bContext *C, bGPDlayer *gpl, bGPDstroke *gps) | ||||
| BKE_gpencil_layer_transform_matrix_get(depsgraph, ob, gpl, diff_mat); | BKE_gpencil_layer_transform_matrix_get(depsgraph, ob, gpl, diff_mat); | ||||
| invert_m4_m4(inverse_diff_mat, diff_mat); | invert_m4_m4(inverse_diff_mat, diff_mat); | ||||
| /* Adjust each point */ | /* Adjust each point */ | ||||
| for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { | for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { | ||||
| float xy[2]; | float xy[2]; | ||||
| bGPDspoint pt2; | bGPDspoint pt2; | ||||
| gpencil_point_to_parent_space(pt, diff_mat, &pt2); | gpencil_point_to_world_space(pt, diff_mat, &pt2); | ||||
| gpencil_point_to_xy_fl(&gsc, gps, &pt2, &xy[0], &xy[1]); | gpencil_point_to_xy_fl(&gsc, gps, &pt2, &xy[0], &xy[1]); | ||||
| /* Planar - All on same plane parallel to the viewplane */ | /* Planar - All on same plane parallel to the viewplane */ | ||||
| gpencil_point_xy_to_3d(&gsc, scene, xy, &pt->x); | gpencil_point_xy_to_3d(&gsc, scene, xy, &pt->x); | ||||
| /* Unapply parent corrections */ | /* Unapply parent corrections */ | ||||
| mul_m4_v3(inverse_diff_mat, &pt->x); | mul_m4_v3(inverse_diff_mat, &pt->x); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 129 Lines • ▼ Show 20 Lines | for (i = 0, pt = gps_active->points; i < gps_active->totpoints; i++, pt++) { | ||||
| float xy[2]; | float xy[2]; | ||||
| /* 3D to Screen-space */ | /* 3D to Screen-space */ | ||||
| /* NOTE: We can't use gpencil_point_to_xy() here because that uses ints for the screen-space | /* NOTE: We can't use gpencil_point_to_xy() here because that uses ints for the screen-space | ||||
| * coordinates, resulting in lost precision, which in turn causes stair-stepping | * coordinates, resulting in lost precision, which in turn causes stair-stepping | ||||
| * artifacts in the final points. */ | * artifacts in the final points. */ | ||||
| bGPDspoint pt2; | bGPDspoint pt2; | ||||
| gpencil_point_to_parent_space(pt, diff_mat, &pt2); | gpencil_point_to_world_space(pt, diff_mat, &pt2); | ||||
| gpencil_point_to_xy_fl(gsc, gps_active, &pt2, &xy[0], &xy[1]); | gpencil_point_to_xy_fl(gsc, gps_active, &pt2, &xy[0], &xy[1]); | ||||
| /* Project stroke in one axis */ | /* Project stroke in one axis */ | ||||
| if (ELEM(mode, GP_REPROJECT_FRONT, GP_REPROJECT_SIDE, GP_REPROJECT_TOP, GP_REPROJECT_CURSOR)) { | if (ELEM(mode, GP_REPROJECT_FRONT, GP_REPROJECT_SIDE, GP_REPROJECT_TOP, GP_REPROJECT_CURSOR)) { | ||||
| int axis = 0; | int axis = 0; | ||||
| switch (mode) { | switch (mode) { | ||||
| case GP_REPROJECT_FRONT: { | case GP_REPROJECT_FRONT: { | ||||
| axis = 1; | axis = 1; | ||||
| Show All 17 Lines | if (ELEM(mode, GP_REPROJECT_FRONT, GP_REPROJECT_SIDE, GP_REPROJECT_TOP, GP_REPROJECT_CURSOR)) { | ||||
| } | } | ||||
| } | } | ||||
| ED_gpencil_project_point_to_plane(gsc->scene, gsc->ob, gpl, rv3d, origin, axis, &pt2); | ED_gpencil_project_point_to_plane(gsc->scene, gsc->ob, gpl, rv3d, origin, axis, &pt2); | ||||
| copy_v3_v3(&pt->x, &pt2.x); | copy_v3_v3(&pt->x, &pt2.x); | ||||
| /* apply parent again */ | /* apply parent again */ | ||||
| gpencil_apply_parent_point(depsgraph, gsc->ob, gpl, pt); | gpencil_world_to_object_space_point(depsgraph, gsc->ob, gpl, pt); | ||||
| } | } | ||||
| /* Project screen-space back to 3D space (from current perspective) | /* Project screen-space back to 3D space (from current perspective) | ||||
| * so that all points have been treated the same way. */ | * so that all points have been treated the same way. */ | ||||
| else if (mode == GP_REPROJECT_VIEW) { | else if (mode == GP_REPROJECT_VIEW) { | ||||
| /* Planar - All on same plane parallel to the view-plane. */ | /* Planar - All on same plane parallel to the view-plane. */ | ||||
| gpencil_point_xy_to_3d(gsc, gsc->scene, xy, &pt->x); | gpencil_point_xy_to_3d(gsc, gsc->scene, xy, &pt->x); | ||||
| } | } | ||||
| else { | else { | ||||
| ▲ Show 20 Lines • Show All 1,809 Lines • ▼ Show 20 Lines | void ED_gpencil_projected_2d_bound_box(const GP_SpaceConversion *gsc, | ||||
| float bounds[8][2]; | float bounds[8][2]; | ||||
| BoundBox bb; | BoundBox bb; | ||||
| BKE_boundbox_init_from_minmax(&bb, gps->boundbox_min, gps->boundbox_max); | BKE_boundbox_init_from_minmax(&bb, gps->boundbox_min, gps->boundbox_max); | ||||
| /* Project 8 vertices in 2D. */ | /* Project 8 vertices in 2D. */ | ||||
| for (int i = 0; i < 8; i++) { | for (int i = 0; i < 8; i++) { | ||||
| bGPDspoint pt_dummy, pt_dummy_ps; | bGPDspoint pt_dummy, pt_dummy_ps; | ||||
| copy_v3_v3(&pt_dummy.x, bb.vec[i]); | copy_v3_v3(&pt_dummy.x, bb.vec[i]); | ||||
| gpencil_point_to_parent_space(&pt_dummy, diff_mat, &pt_dummy_ps); | gpencil_point_to_world_space(&pt_dummy, diff_mat, &pt_dummy_ps); | ||||
| gpencil_point_to_xy_fl(gsc, gps, &pt_dummy_ps, &bounds[i][0], &bounds[i][1]); | gpencil_point_to_xy_fl(gsc, gps, &pt_dummy_ps, &bounds[i][0], &bounds[i][1]); | ||||
| } | } | ||||
| /* Take extremes. */ | /* Take extremes. */ | ||||
| INIT_MINMAX2(r_min, r_max); | INIT_MINMAX2(r_min, r_max); | ||||
| for (int i = 0; i < 8; i++) { | for (int i = 0; i < 8; i++) { | ||||
| minmax_v2v2_v2(r_min, r_max, bounds[i]); | minmax_v2v2_v2(r_min, r_max, bounds[i]); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | bool ED_gpencil_stroke_point_is_inside(const bGPDstroke *gps, | ||||
| int len = gps->totpoints; | int len = gps->totpoints; | ||||
| mcoords = MEM_mallocN(sizeof(int[2]) * len, __func__); | mcoords = MEM_mallocN(sizeof(int[2]) * len, __func__); | ||||
| /* Convert stroke to 2D array of points. */ | /* Convert stroke to 2D array of points. */ | ||||
| const bGPDspoint *pt; | const bGPDspoint *pt; | ||||
| int i; | int i; | ||||
| for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { | for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { | ||||
| bGPDspoint pt2; | bGPDspoint pt2; | ||||
| gpencil_point_to_parent_space(pt, diff_mat, &pt2); | gpencil_point_to_world_space(pt, diff_mat, &pt2); | ||||
| gpencil_point_to_xy(gsc, gps, &pt2, &mcoords[i][0], &mcoords[i][1]); | gpencil_point_to_xy(gsc, gps, &pt2, &mcoords[i][0], &mcoords[i][1]); | ||||
| } | } | ||||
| /* Compute bound-box of lasso (for faster testing later). */ | /* Compute bound-box of lasso (for faster testing later). */ | ||||
| rcti rect; | rcti rect; | ||||
| BLI_lasso_boundbox(&rect, mcoords, len); | BLI_lasso_boundbox(&rect, mcoords, len); | ||||
| /* Test if point inside stroke. */ | /* Test if point inside stroke. */ | ||||
| Show All 9 Lines | |||||
| void ED_gpencil_stroke_extremes_to2d(const GP_SpaceConversion *gsc, | void ED_gpencil_stroke_extremes_to2d(const GP_SpaceConversion *gsc, | ||||
| const float diff_mat[4][4], | const float diff_mat[4][4], | ||||
| bGPDstroke *gps, | bGPDstroke *gps, | ||||
| float r_ctrl1[2], | float r_ctrl1[2], | ||||
| float r_ctrl2[2]) | float r_ctrl2[2]) | ||||
| { | { | ||||
| bGPDspoint pt_dummy_ps; | bGPDspoint pt_dummy_ps; | ||||
| gpencil_point_to_parent_space(&gps->points[0], diff_mat, &pt_dummy_ps); | gpencil_point_to_world_space(&gps->points[0], diff_mat, &pt_dummy_ps); | ||||
| gpencil_point_to_xy_fl(gsc, gps, &pt_dummy_ps, &r_ctrl1[0], &r_ctrl1[1]); | gpencil_point_to_xy_fl(gsc, gps, &pt_dummy_ps, &r_ctrl1[0], &r_ctrl1[1]); | ||||
| gpencil_point_to_parent_space(&gps->points[gps->totpoints - 1], diff_mat, &pt_dummy_ps); | gpencil_point_to_world_space(&gps->points[gps->totpoints - 1], diff_mat, &pt_dummy_ps); | ||||
| gpencil_point_to_xy_fl(gsc, gps, &pt_dummy_ps, &r_ctrl2[0], &r_ctrl2[1]); | gpencil_point_to_xy_fl(gsc, gps, &pt_dummy_ps, &r_ctrl2[0], &r_ctrl2[1]); | ||||
| } | } | ||||
| bGPDstroke *ED_gpencil_stroke_nearest_to_ends(bContext *C, | bGPDstroke *ED_gpencil_stroke_nearest_to_ends(bContext *C, | ||||
| const GP_SpaceConversion *gsc, | const GP_SpaceConversion *gsc, | ||||
| bGPDlayer *gpl, | bGPDlayer *gpl, | ||||
| bGPDframe *gpf, | bGPDframe *gpf, | ||||
| bGPDstroke *gps, | bGPDstroke *gps, | ||||
| Show All 11 Lines | bGPDstroke *ED_gpencil_stroke_nearest_to_ends(bContext *C, | ||||
| float diff_mat[4][4]; | float diff_mat[4][4]; | ||||
| BKE_gpencil_layer_transform_matrix_get(depsgraph, ob, gpl, diff_mat); | BKE_gpencil_layer_transform_matrix_get(depsgraph, ob, gpl, diff_mat); | ||||
| /* Calculate the extremes of the stroke in 2D. */ | /* Calculate the extremes of the stroke in 2D. */ | ||||
| bGPDspoint pt_parent; | bGPDspoint pt_parent; | ||||
| float pt2d_start[2], pt2d_end[2]; | float pt2d_start[2], pt2d_end[2]; | ||||
| bGPDspoint *pt = &gps->points[0]; | bGPDspoint *pt = &gps->points[0]; | ||||
| gpencil_point_to_parent_space(pt, diff_mat, &pt_parent); | gpencil_point_to_world_space(pt, diff_mat, &pt_parent); | ||||
| gpencil_point_to_xy_fl(gsc, gps, &pt_parent, &pt2d_start[0], &pt2d_start[1]); | gpencil_point_to_xy_fl(gsc, gps, &pt_parent, &pt2d_start[0], &pt2d_start[1]); | ||||
| pt = &gps->points[gps->totpoints - 1]; | pt = &gps->points[gps->totpoints - 1]; | ||||
| gpencil_point_to_parent_space(pt, diff_mat, &pt_parent); | gpencil_point_to_world_space(pt, diff_mat, &pt_parent); | ||||
| gpencil_point_to_xy_fl(gsc, gps, &pt_parent, &pt2d_end[0], &pt2d_end[1]); | gpencil_point_to_xy_fl(gsc, gps, &pt_parent, &pt2d_end[0], &pt2d_end[1]); | ||||
| /* Loop all strokes of the active frame. */ | /* Loop all strokes of the active frame. */ | ||||
| float dist_min = FLT_MAX; | float dist_min = FLT_MAX; | ||||
| LISTBASE_FOREACH (bGPDstroke *, gps_target, &gpf->strokes) { | LISTBASE_FOREACH (bGPDstroke *, gps_target, &gpf->strokes) { | ||||
| /* Check if the color is editable. */ | /* Check if the color is editable. */ | ||||
| if ((gps_target == gps) || (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false)) { | if ((gps_target == gps) || (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false)) { | ||||
| continue; | continue; | ||||
| Show All 9 Lines | if ((!ED_gpencil_stroke_check_collision(gsc, gps_target, pt2d_start, radius, diff_mat)) && | ||||
| (!ED_gpencil_stroke_check_collision(gsc, gps_target, pt2d_end, radius, diff_mat))) { | (!ED_gpencil_stroke_check_collision(gsc, gps_target, pt2d_end, radius, diff_mat))) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| /* Check the distance of the ends with the ends of target stroke to avoid middle contact. | /* Check the distance of the ends with the ends of target stroke to avoid middle contact. | ||||
| * All is done in 2D plane. */ | * All is done in 2D plane. */ | ||||
| float pt2d_target_start[2], pt2d_target_end[2]; | float pt2d_target_start[2], pt2d_target_end[2]; | ||||
| pt = &gps_target->points[0]; | pt = &gps_target->points[0]; | ||||
| gpencil_point_to_parent_space(pt, diff_mat, &pt_parent); | gpencil_point_to_world_space(pt, diff_mat, &pt_parent); | ||||
| gpencil_point_to_xy_fl(gsc, gps, &pt_parent, &pt2d_target_start[0], &pt2d_target_start[1]); | gpencil_point_to_xy_fl(gsc, gps, &pt_parent, &pt2d_target_start[0], &pt2d_target_start[1]); | ||||
| pt = &gps_target->points[gps_target->totpoints - 1]; | pt = &gps_target->points[gps_target->totpoints - 1]; | ||||
| gpencil_point_to_parent_space(pt, diff_mat, &pt_parent); | gpencil_point_to_world_space(pt, diff_mat, &pt_parent); | ||||
| gpencil_point_to_xy_fl(gsc, gps, &pt_parent, &pt2d_target_end[0], &pt2d_target_end[1]); | gpencil_point_to_xy_fl(gsc, gps, &pt_parent, &pt2d_target_end[0], &pt2d_target_end[1]); | ||||
| /* If the distance to the original stroke extremes is too big, the stroke must not be joined. | /* If the distance to the original stroke extremes is too big, the stroke must not be joined. | ||||
| */ | */ | ||||
| if ((len_squared_v2v2(ctrl1, pt2d_target_start) > radius_sqr) && | if ((len_squared_v2v2(ctrl1, pt2d_target_start) > radius_sqr) && | ||||
| (len_squared_v2v2(ctrl1, pt2d_target_end) > radius_sqr) && | (len_squared_v2v2(ctrl1, pt2d_target_end) > radius_sqr) && | ||||
| (len_squared_v2v2(ctrl2, pt2d_target_start) > radius_sqr) && | (len_squared_v2v2(ctrl2, pt2d_target_start) > radius_sqr) && | ||||
| (len_squared_v2v2(ctrl2, pt2d_target_end) > radius_sqr)) { | (len_squared_v2v2(ctrl2, pt2d_target_end) > radius_sqr)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| if ((len_squared_v2v2(pt2d_start, pt2d_target_start) > radius_sqr) && | if ((len_squared_v2v2(pt2d_start, pt2d_target_start) > radius_sqr) && | ||||
| (len_squared_v2v2(pt2d_start, pt2d_target_end) > radius_sqr) && | (len_squared_v2v2(pt2d_start, pt2d_target_end) > radius_sqr) && | ||||
| (len_squared_v2v2(pt2d_end, pt2d_target_start) > radius_sqr) && | (len_squared_v2v2(pt2d_end, pt2d_target_start) > radius_sqr) && | ||||
| (len_squared_v2v2(pt2d_end, pt2d_target_end) > radius_sqr)) { | (len_squared_v2v2(pt2d_end, pt2d_target_end) > radius_sqr)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| /* Loop all points and check what is the nearest point. */ | /* Loop all points and check what is the nearest point. */ | ||||
| int i; | int i; | ||||
| for (i = 0, pt = gps_target->points; i < gps_target->totpoints; i++, pt++) { | for (i = 0, pt = gps_target->points; i < gps_target->totpoints; i++, pt++) { | ||||
| /* Convert point to 2D. */ | /* Convert point to 2D. */ | ||||
| float pt2d[2]; | float pt2d[2]; | ||||
| gpencil_point_to_parent_space(pt, diff_mat, &pt_parent); | gpencil_point_to_world_space(pt, diff_mat, &pt_parent); | ||||
| gpencil_point_to_xy_fl(gsc, gps, &pt_parent, &pt2d[0], &pt2d[1]); | gpencil_point_to_xy_fl(gsc, gps, &pt_parent, &pt2d[0], &pt2d[1]); | ||||
| /* Check with Start point. */ | /* Check with Start point. */ | ||||
| float dist = len_squared_v2v2(pt2d, pt2d_start); | float dist = len_squared_v2v2(pt2d, pt2d_start); | ||||
| if ((dist <= radius_sqr) && (dist < dist_min)) { | if ((dist <= radius_sqr) && (dist < dist_min)) { | ||||
| *r_index = i; | *r_index = i; | ||||
| dist_min = dist; | dist_min = dist; | ||||
| gps_rtn = gps_target; | gps_rtn = gps_target; | ||||
| ▲ Show 20 Lines • Show All 165 Lines • Show Last 20 Lines | |||||