[Bf-blender-cvs] [a993466b224] HMD_viewport: Fix projection matrices not taking focal length of HMD into account

Julian Eisel noreply at git.blender.org
Wed Apr 12 19:57:02 CEST 2017


Commit: a993466b22434138b88aa46f1ab3392c2b1e1b9f
Author: Julian Eisel
Date:   Wed Apr 12 19:55:42 2017 +0200
Branches: HMD_viewport
https://developer.blender.org/rBa993466b22434138b88aa46f1ab3392c2b1e1b9f

Fix projection matrices not taking focal length of HMD into account

===================================================================

M	intern/ghost/GHOST_C-api.h
M	intern/ghost/intern/GHOST_C-api.cpp
M	source/blender/editors/space_view3d/view3d_draw.c
M	source/blender/editors/space_view3d/view3d_intern.h
M	source/blender/editors/space_view3d/view3d_view.c
M	source/blender/windowmanager/WM_api.h
M	source/blender/windowmanager/intern/wm_device.c

===================================================================

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(&params);
+	BKE_camera_params_from_view3d(&params, v3d, rv3d);
+	params.zoom = 1.0f;
+	BKE_camera_params_compute_viewplane(&params, 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();




More information about the Bf-blender-cvs mailing list