diff options
author | Julian Eisel <eiseljulian@gmail.com> | 2017-04-12 20:55:42 +0300 |
---|---|---|
committer | Julian Eisel <eiseljulian@gmail.com> | 2017-04-12 20:55:42 +0300 |
commit | a993466b22434138b88aa46f1ab3392c2b1e1b9f (patch) | |
tree | d14837cb9d730f21383947fdda72c877d46d7e0d | |
parent | a21130f737b65a7f96cd4b501349149bbf76e3fa (diff) |
Fix projection matrices not taking focal length of HMD into account
-rw-r--r-- | intern/ghost/GHOST_C-api.h | 2 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_C-api.cpp | 22 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_draw.c | 36 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_intern.h | 4 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_view.c | 21 | ||||
-rw-r--r-- | source/blender/windowmanager/WM_api.h | 1 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_device.c | 13 |
7 files changed, 87 insertions, 12 deletions
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index 1eeb0fda3e8..6c705253732 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -949,6 +949,8 @@ extern float GHOST_HMDgetLensHorizontalSeparation(void); extern float GHOST_HMDgetProjectionZNear(void); extern float GHOST_HMDgetProjectionZFar(void); extern float GHOST_HMDgetScreenHorizontalSize(void); +extern float GHOST_HMDgetLeftEyeFOV(void); +extern float GHOST_HMDgetRightEyeFOV(void); extern void GHOST_HMDgetLeftModelviewMatrix(float r_mat[4][4]); extern void GHOST_HMDgetRightModelviewMatrix(float r_mat[4][4]); extern void* GHOST_HMDgetDistortionParameters(void); diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp index 28b1bbcd50d..5f5bfc17f09 100644 --- a/intern/ghost/intern/GHOST_C-api.cpp +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -1074,6 +1074,28 @@ float GHOST_HMDgetScreenHorizontalSize() #endif } +float GHOST_HMDgetLeftEyeFOV() +{ +#ifdef WITH_OPENHMD + GHOST_ISystem *system = GHOST_ISystem::getSystem(); + GHOST_OpenHMDManager *ohmd = system->getOpenHMDManager(); + return ohmd->getLeftEyeFOV(); +#else + return -1.0f; +#endif +} + +float GHOST_HMDgetRightEyeFOV() +{ +#ifdef WITH_OPENHMD + GHOST_ISystem *system = GHOST_ISystem::getSystem(); + GHOST_OpenHMDManager *ohmd = system->getOpenHMDManager(); + return ohmd->getRightEyeFOV(); +#else + return -1.0f; +#endif +} + #ifndef WITH_OPENHMD static void ghost_UnitMat(float r_mat[4][4]) { diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 9eacbebc047..38e9248704c 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -3766,7 +3766,7 @@ bool view3d_is_hmd_view_mirror(const wmWindowManager *wm, const View3D *v3d, con } static void view3d_hmd_calc_projection_matrix_from_device( - ARegion *region, View3D *v3d, + ARegion *region, View3D *v3d, const RegionView3D *rv3d, const rcti *viewplane_rect, enum HMDViewMatrixType mat_type, float r_projectionmat[4][4]) { @@ -3775,16 +3775,39 @@ static void view3d_hmd_calc_projection_matrix_from_device( * * For selecting, viewplane_rect has to be used for view-plane clipping. * * OpenHMD doesn't allow us to set custom screen dimensions, it always uses device ones. */ + rctf viewplane; + CameraParams params; + + const bool is_left = mat_type == HMD_MATRIX_LEFT_EYE; const float v3d_znear = v3d->near; const float v3d_zfar = v3d->far; + const float v3d_lens = v3d->lens; const float hmd_znear = WM_device_HMD_projection_z_near_get(); const float hmd_zfar = WM_device_HMD_projection_z_far_get(); + const float hmd_fov = WM_device_HMD_FOV_get(is_left); + const int winx = region->winx; + const int winy = region->winy; + v3d->near = hmd_znear; v3d->far = hmd_zfar; + v3d->lens = fov_to_focallength(hmd_fov, DEFAULT_SENSOR_WIDTH); + + /* from ED_view3d_viewplane_get, but we override zoom */ + BKE_camera_params_init(¶ms); + BKE_camera_params_from_view3d(¶ms, v3d, rv3d); + params.zoom = 1.0f; + BKE_camera_params_compute_viewplane(¶ms, winx, winy, 1.0f, 1.0f); + viewplane = params.viewplane; + + if (viewplane_rect) { + /* picking/selecting */ + view3d_winmatrix_viewplane_adjust_for_rect(&viewplane, viewplane_rect, winx, winy, &viewplane); + } - view3d_winmatrix_set(region, v3d, viewplane_rect); - glGetFloatv(GL_PROJECTION_MATRIX, (float *)r_projectionmat); + BLI_assert(params.clipsta == hmd_znear && params.clipend == hmd_zfar); + perspective_m4(r_projectionmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, + params.clipsta, params.clipend); if (mat_type != HMD_MATRIX_CENTER) { /* calculate lens offset in [-1, 1] range to apply onto projection matrix. @@ -3795,11 +3818,12 @@ static void view3d_hmd_calc_projection_matrix_from_device( /* apply lens separation (IPD is applied onto modelview matrix) */ BLI_assert(IN_RANGE_INCL(proj_offset, -1.0f, 1.0f)); - translate_m4(r_projectionmat, (mat_type == HMD_MATRIX_LEFT_EYE) ? proj_offset : -proj_offset, 0, 0); + translate_m4(r_projectionmat, is_left ? proj_offset : -proj_offset, 0, 0); } v3d->near = v3d_znear; v3d->far = v3d_zfar; + v3d->lens = v3d_lens; } static void view3d_hmd_calc_modelview_matrix_from_device( @@ -3854,10 +3878,10 @@ static void view3d_hmd_get_matrices( } else if (use_device_rot) { view3d_hmd_calc_modelview_matrix_from_device(v3d, rv3d, mat_type, r_modelviewmat); - view3d_hmd_calc_projection_matrix_from_device(region, v3d, viewplane_rect, mat_type, r_projectionmat); + view3d_hmd_calc_projection_matrix_from_device(region, v3d, rv3d, viewplane_rect, mat_type, r_projectionmat); } else { - view3d_hmd_calc_projection_matrix_from_device(region, v3d, viewplane_rect, mat_type, r_projectionmat); + view3d_hmd_calc_projection_matrix_from_device(region, v3d, rv3d, viewplane_rect, mat_type, r_projectionmat); copy_m4_m4(r_modelviewmat, rv3d->viewmat); diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 62f5d7bcbbe..d7a17a92f0a 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -261,6 +261,10 @@ void ED_view3d_smooth_view_force_finish( void view3d_winmatrix_set(ARegion *ar, const View3D *v3d, const rcti *rect); void view3d_viewmatrix_set(Scene *scene, const View3D *v3d, RegionView3D *rv3d); +void view3d_winmatrix_viewplane_adjust_for_rect( + const rctf *viewplane, const rcti *rect, + float winx, float winy, + rctf *r_viewplane); void fly_modal_keymap(struct wmKeyConfig *keyconf); void walk_modal_keymap(struct wmKeyConfig *keyconf); diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 7ed6a6f3be1..8108e9c402d 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -928,12 +928,7 @@ void view3d_winmatrix_set(ARegion *ar, const View3D *v3d, const rcti *rect) #endif if (rect) { /* picking */ - rctf r; - r.xmin = viewplane.xmin + (BLI_rctf_size_x(&viewplane) * (rect->xmin / (float)ar->winx)); - r.ymin = viewplane.ymin + (BLI_rctf_size_y(&viewplane) * (rect->ymin / (float)ar->winy)); - r.xmax = viewplane.xmin + (BLI_rctf_size_x(&viewplane) * (rect->xmax / (float)ar->winx)); - r.ymax = viewplane.ymin + (BLI_rctf_size_y(&viewplane) * (rect->ymax / (float)ar->winy)); - viewplane = r; + view3d_winmatrix_viewplane_adjust_for_rect(&viewplane, rect, ar->winx, ar->winy, &viewplane); } if (is_ortho) { @@ -947,6 +942,20 @@ void view3d_winmatrix_set(ARegion *ar, const View3D *v3d, const rcti *rect) glGetFloatv(GL_PROJECTION_MATRIX, (float *)rv3d->winmat); } +void view3d_winmatrix_viewplane_adjust_for_rect( + const rctf *viewplane, const rcti *rect, + float winx, float winy, + rctf *r_viewplane) +{ + /* allow passing same pointer for viewplane and r_viewplane */ + rctf viewplane_local = *viewplane; + + r_viewplane->xmin = viewplane_local.xmin + (BLI_rctf_size_x(&viewplane_local) * (rect->xmin / winx)); + r_viewplane->ymin = viewplane_local.ymin + (BLI_rctf_size_y(&viewplane_local) * (rect->ymin / winy)); + r_viewplane->xmax = viewplane_local.xmin + (BLI_rctf_size_x(&viewplane_local) * (rect->xmax / winx)); + r_viewplane->ymax = viewplane_local.ymin + (BLI_rctf_size_y(&viewplane_local) * (rect->ymax / winy)); +} + static void obmat_to_viewmat(RegionView3D *rv3d, Object *ob) { float bmat[4][4]; diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 88a76b6736d..fb564f3c223 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -544,6 +544,7 @@ float WM_device_HMD_screen_horizontal_size_get(void); /* Utils */ void WM_device_HMD_state_set(const int device, const bool enable); void WM_device_HMD_modelview_matrix_get(const bool is_left, float r_modelviewmat[4][4]) ATTR_NONNULL(); +float WM_device_HMD_FOV_get(const bool is_left); void *WM_device_HMD_distortion_parameters_get(void); #endif /* WITH_INPUT_HMD */ diff --git a/source/blender/windowmanager/intern/wm_device.c b/source/blender/windowmanager/intern/wm_device.c index 98d6ab25210..73f866bc7c1 100644 --- a/source/blender/windowmanager/intern/wm_device.c +++ b/source/blender/windowmanager/intern/wm_device.c @@ -143,6 +143,19 @@ void WM_device_HMD_modelview_matrix_get(const bool is_left, float r_modelviewmat } } +float WM_device_HMD_FOV_get(const bool is_left) +{ + if (U.hmd_settings.device == -1) { + return -1.0f; + } + else if (is_left) { + return GHOST_HMDgetLeftEyeFOV(); + } + else { + return GHOST_HMDgetRightEyeFOV(); + } +} + void* WM_device_HMD_distortion_parameters_get(void) { return GHOST_HMDgetDistortionParameters(); |