void ED_view3d_win_to_segment(ARegion *ar, View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3]) { RegionView3D *rv3d = ar->regiondata; if (rv3d->is_persp) { float vec[3]; ED_view3d_win_to_vector(ar, mval, vec); copy_v3_v3(ray_start, rv3d->viewinv[3]); madd_v3_v3v3fl(ray_start, rv3d->viewinv[3], vec, v3d->near); madd_v3_v3v3fl(ray_end, rv3d->viewinv[3], vec, v3d->far); } else { float vec[4]; vec[0] = 2.0f * mval[0] / ar->winx - 1; vec[1] = 2.0f * mval[1] / ar->winy - 1; vec[2] = 0.0f; vec[3] = 1.0f; mul_m4_v4(rv3d->persinv, vec); madd_v3_v3v3fl(ray_start, vec, rv3d->viewinv[2], 1000.0f); madd_v3_v3v3fl(ray_end, vec, rv3d->viewinv[2], -1000.0f); } }
/** * Calculate a 3d location from 2d window coordinates. * \param ar The region (used for the window width and height). * \param depth_pt The reference location used to calculate the Z depth. * \param mval The area relative location (such as event->mval converted to floats). * \param out The resulting world-space location. */ void ED_view3d_win_to_3d(ARegion *ar, const float depth_pt[3], const float mval[2], float out[3]) { RegionView3D *rv3d = ar->regiondata; float line_sta[3]; float line_end[3]; if (rv3d->is_persp) { float mousevec[3]; copy_v3_v3(line_sta, rv3d->viewinv[3]); ED_view3d_win_to_vector(ar, mval, mousevec); add_v3_v3v3(line_end, line_sta, mousevec); if (isect_line_plane_v3(out, line_sta, line_end, depth_pt, rv3d->viewinv[2], TRUE) == 0) { /* highly unlikely to ever happen, mouse vec paralelle with view plane */ zero_v3(out); } } else { const float dx = (2.0f * mval[0] / (float)ar->winx) - 1.0f; const float dy = (2.0f * mval[1] / (float)ar->winy) - 1.0f; line_sta[0] = (rv3d->persinv[0][0] * dx) + (rv3d->persinv[1][0] * dy) + rv3d->viewinv[3][0]; line_sta[1] = (rv3d->persinv[0][1] * dx) + (rv3d->persinv[1][1] * dy) + rv3d->viewinv[3][1]; line_sta[2] = (rv3d->persinv[0][2] * dx) + (rv3d->persinv[1][2] * dy) + rv3d->viewinv[3][2]; add_v3_v3v3(line_end, line_sta, rv3d->viewinv[2]); closest_to_line_v3(out, depth_pt, line_sta, line_end); } }
/* create intersection coordinates in view Z direction at mouse coordinates */ void ED_view3d_win_to_segment_clip(ARegion *ar, View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3]) { RegionView3D *rv3d= ar->regiondata; if(rv3d->is_persp) { float vec[3]; ED_view3d_win_to_vector(ar, mval, vec); copy_v3_v3(ray_start, rv3d->viewinv[3]); madd_v3_v3v3fl(ray_start, rv3d->viewinv[3], vec, v3d->near); madd_v3_v3v3fl(ray_end, rv3d->viewinv[3], vec, v3d->far); } else { float vec[4]; vec[0] = 2.0f * mval[0] / ar->winx - 1; vec[1] = 2.0f * mval[1] / ar->winy - 1; vec[2] = 0.0f; vec[3] = 1.0f; mul_m4_v4(rv3d->persinv, vec); madd_v3_v3v3fl(ray_start, vec, rv3d->viewinv[2], 1000.0f); madd_v3_v3v3fl(ray_end, vec, rv3d->viewinv[2], -1000.0f); } /* clipping */ if(rv3d->rflag & RV3D_CLIPPING) { int a; for(a=0; a<4; a++) { clip_line_plane(ray_start, ray_end, rv3d->clip[a]); } } }
static bool mesh_bisect_interactive_calc( bContext *C, wmOperator *op, BMEditMesh *em, float plane_co[3], float plane_no[3]) { wmGesture *gesture = op->customdata; BisectData *opdata; ARegion *ar = CTX_wm_region(C); RegionView3D *rv3d = ar->regiondata; int x_start = RNA_int_get(op->ptr, "xstart"); int y_start = RNA_int_get(op->ptr, "ystart"); int x_end = RNA_int_get(op->ptr, "xend"); int y_end = RNA_int_get(op->ptr, "yend"); /* reference location (some point in front of the view) for finding a point on a plane */ const float *co_ref = rv3d->ofs; float co_a_ss[2] = {x_start, y_start}, co_b_ss[2] = {x_end, y_end}, co_delta_ss[2]; float co_a[3], co_b[3]; const float zfac = ED_view3d_calc_zfac(rv3d, co_ref, NULL); opdata = gesture->userdata; /* view vector */ ED_view3d_win_to_vector(ar, co_a_ss, co_a); /* view delta */ sub_v2_v2v2(co_delta_ss, co_a_ss, co_b_ss); ED_view3d_win_to_delta(ar, co_delta_ss, co_b, zfac); /* cross both to get a normal */ cross_v3_v3v3(plane_no, co_a, co_b); normalize_v3(plane_no); /* not needed but nicer for user */ /* point on plane, can use either start or endpoint */ ED_view3d_win_to_3d(ar, co_ref, co_a_ss, plane_co); if (opdata->is_first == false) EDBM_redo_state_restore(opdata->mesh_backup, em, false); opdata->is_first = false; return true; }
static void view3d_win_to_ray_segment( const ARegion *ar, const View3D *v3d, const float mval[2], float r_ray_co[3], float r_ray_dir[3], float r_ray_start[3], float r_ray_end[3]) { RegionView3D *rv3d = ar->regiondata; float _ray_co[3], _ray_dir[3], start_offset, end_offset; if (!r_ray_co) r_ray_co = _ray_co; if (!r_ray_dir) r_ray_dir = _ray_dir; ED_view3d_win_to_vector(ar, mval, r_ray_dir); if (rv3d->is_persp) { copy_v3_v3(r_ray_co, rv3d->viewinv[3]); } else { r_ray_co[0] = 2.0f * mval[0] / ar->winx - 1.0f; r_ray_co[1] = 2.0f * mval[1] / ar->winy - 1.0f; if (rv3d->persp == RV3D_CAMOB) { r_ray_co[2] = -1.0f; } else { r_ray_co[2] = 0.0f; } mul_project_m4_v3(rv3d->persinv, r_ray_co); } if ((rv3d->is_persp == false) && (rv3d->persp != RV3D_CAMOB)) { end_offset = v3d->far / 2.0f; start_offset = -end_offset; } else { ED_view3d_clip_range_get(v3d, rv3d, &start_offset, &end_offset, false); } if (r_ray_start) { madd_v3_v3v3fl(r_ray_start, r_ray_co, r_ray_dir, start_offset); } if (r_ray_end) { madd_v3_v3v3fl(r_ray_end, r_ray_co, r_ray_dir, end_offset); } }
/** * Calculate a 3d location from 2d window coordinates. * \param ar The region (used for the window width and height). * \param depth_pt The reference location used to calculate the Z depth. * \param mval The area relative location (such as event->mval converted to floats). * \param out The resulting world-space location. */ void ED_view3d_win_to_3d(const ARegion *ar, const float depth_pt[3], const float mval[2], float out[3]) { RegionView3D *rv3d = ar->regiondata; float ray_origin[3]; float ray_direction[3]; float lambda; if (rv3d->is_persp) { float plane[4]; copy_v3_v3(ray_origin, rv3d->viewinv[3]); ED_view3d_win_to_vector(ar, mval, ray_direction); /* note, we could use isect_line_plane_v3() however we want the intersection to be infront of the * view no matter what, so apply the unsigned factor instead */ plane_from_point_normal_v3(plane, depth_pt, rv3d->viewinv[2]); isect_ray_plane_v3(ray_origin, ray_direction, plane, &lambda, false); lambda = fabsf(lambda); } else { float dx = (2.0f * mval[0] / (float)ar->winx) - 1.0f; float dy = (2.0f * mval[1] / (float)ar->winy) - 1.0f; if (rv3d->persp == RV3D_CAMOB) { /* ortho camera needs offset applied */ const float zoomfac = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom) * 4.0f; dx += rv3d->camdx * zoomfac; dy += rv3d->camdy * zoomfac; } ray_origin[0] = (rv3d->persinv[0][0] * dx) + (rv3d->persinv[1][0] * dy) + rv3d->viewinv[3][0]; ray_origin[1] = (rv3d->persinv[0][1] * dx) + (rv3d->persinv[1][1] * dy) + rv3d->viewinv[3][1]; ray_origin[2] = (rv3d->persinv[0][2] * dx) + (rv3d->persinv[1][2] * dy) + rv3d->viewinv[3][2]; copy_v3_v3(ray_direction, rv3d->viewinv[2]); lambda = ray_point_factor_v3(depth_pt, ray_origin, ray_direction); } madd_v3_v3v3fl(out, ray_origin, ray_direction, lambda); }