From 5f25402b3b4ca7ce4a99b8fc8bb0a2b57146189b Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Thu, 22 Oct 2015 16:06:06 -0200 Subject: [PATCH 1/6] Initial support for correct projection matrix --- .../blendervr/player/screen/hmd/oculus_dk2.py | 122 +++++++++++++++++ .../virtual_environment/__init__.py | 123 +++++++++++------- 2 files changed, 196 insertions(+), 49 deletions(-) diff --git a/modules/blendervr/player/screen/hmd/oculus_dk2.py b/modules/blendervr/player/screen/hmd/oculus_dk2.py index beefb05..ebf0fce 100644 --- a/modules/blendervr/player/screen/hmd/oculus_dk2.py +++ b/modules/blendervr/player/screen/hmd/oculus_dk2.py @@ -37,6 +37,8 @@ ## import mathutils +from mathutils import Matrix, Quaternion + import bge from . import base from ... import exceptions @@ -52,6 +54,25 @@ class Device(base.Device): def __init__(self, parent, configuration): super(Device, self).__init__(parent, configuration) self._plugin = None + self._modelview_matrix = [Matrix.Identity(4), Matrix.Identity(4)] + self._projection_matrix = [Matrix.Identity(4), Matrix.Identity(4)] + self._near = -1 + self._far = -1 + + self.checkLibraryPath() + + try: + from oculusvr import Hmd + assert(Hmd) + + except ImportError: + self.logger.info('Oculus DK2 plugin error: no \"oculusvr\" module available. Make sure you have the project submodules. Please refer to the BlenderVR documentation') + return + + except Exception as err: + self.logger.error(err) + self._available = False + return def start(self): super(Device, self).start() @@ -86,3 +107,104 @@ def start(self): except Exception as err: self.logger.error(err) + + def _updateMatrixForBuffer(self, bufferName, camera, depth): + + scale = self.BlenderVR.scale + user = self._buffers[bufferName]['user'] + + if bufferName == 'left': + near = camera.near * scale + far = camera.far * scale + + self._updateProjectionMatrix(near, far) + self._updateModelViewMatrix(user.getPosition() * user.getVehiclePosition(), camera.modelview_matrix) + + self._setModelViewMatrix(self._modelview_matrix[0]) + self._setProjectionMatrix(self._projection_matrix[0]) + else: + self._setModelViewMatrix(self._modelview_matrix[1]) + self._setProjectionMatrix(self._projection_matrix[1]) + + + def _updateModelViewMatrix(self, user_matrix, camera_matrix): + from oculusvr import Hmd + from bge import logic + + global_dict = logic.globalDict + hmd = global_dict.get('hmd') + + if hmd and Hmd.detect() == 1: + global_dict['frame'] += 1 + + frame = global_dict['frame'] + fov_ports = global_dict['fovPorts'] + eye_offsets = global_dict['eyeOffsets'] + + poses = hmd.get_eye_poses(frame, eye_offsets) + hmd.begin_frame(frame) + + orientation = [None, None] + position = [None, None] + + for eye in range(2): + orientation_raw = poses[eye].Orientation.toList() + position_raw = poses[eye].Position.toList() + + orientation = Quaternion(orientation_raw).to_matrix().to_4x4() + position = Matrix.Translation(position_raw) + + matrix = position * orientation + matrix.invert() + + self._modelview_matrix[eye] = self._convertMatrixTo4x4(user_matrix * matrix * camera_matrix) + + def _convertMatrixTo4x4(self, value): + matrix = Matrix() + + matrix[0] = value[0:4] + matrix[1] = value[4:8] + matrix[2] = value[8:12] + matrix[3] = value[12:16] + + return matrix.transposed() + + + def _updateProjectionMatrix(self, near, far): + + if not self._cameraClippingChanged(near, far): + return + + from bge import logic + import oculusvr as ovr + + global_dict = logic.globalDict + fov_ports = global_dict['fovPorts'] + + self._projection_matrix[0] = self._convertMatrixTo4x4(ovr.Hmd.get_perspective(fov_ports[0], near, far, True).toList()) + self._projection_matrix[1] = self._convertMatrixTo4x4(ovr.Hmd.get_perspective(fov_ports[1], near, far, True).toList()) + + def _cameraClippingChanged(self, near, far): + """ + check if near of far values changed + """ + if near == self._near and far == self._far: + return False + + self._near = near + self._far = far + + return True + + def checkLibraryPath(self): + """if library exists append it to sys.path""" + import sys + import os + from .... import tools + + libs_path = tools.getLibsPath() + oculus_path = os.path.join(libs_path, "python-ovrsdk") + + if oculus_path not in sys.path: + sys.path.append(oculus_path) + diff --git a/modules/blendervr/plugins/oculus_dk2/virtual_environment/__init__.py b/modules/blendervr/plugins/oculus_dk2/virtual_environment/__init__.py index e2a41f4..03b1a5c 100644 --- a/modules/blendervr/plugins/oculus_dk2/virtual_environment/__init__.py +++ b/modules/blendervr/plugins/oculus_dk2/virtual_environment/__init__.py @@ -47,7 +47,10 @@ def __init__(self, parent, configuration): self._user = None self._hmd = None self._description = None - self._matrix = None + self._modelview_matrix = [None, None] + self._projection_matrix = [None, None] + self._near = -100.0 + self._far = -100.0 self.checkLibraryPath() @@ -56,7 +59,7 @@ def __init__(self, parent, configuration): assert(Hmd) except ImportError: - self.logger.info('Oculus DK2 plugin error: no \"oculusvr\" module available. Make sure you have the projec submodules. Please refer to the BlenderVR documentation') + self.logger.info('Oculus DK2 plugin error: no \"oculusvr\" module available. Make sure you have the project submodules. Please refer to the BlenderVR documentation') self._available = False return @@ -84,31 +87,17 @@ def start(self): super(OculusDK2, self).start() from mathutils import Matrix + self.logger.debug("START PLUGIN") + try: - self._matrix = Matrix.Identity(4) self._startOculus() + except Exception: self._available = False def run(self): super(OculusDK2, self).run() - try: - self._updateMatrix() - info = {'matrix' : self._matrix} - self._user.run(info) - - except Exception as err: - self.logger.log_traceback(err) - - def _updateMatrix(self): - try: - matrix = self._getMatrix() - if matrix: - self._matrix = matrix - except Exception as err: - self.logger.log_traceback(err) - def checkMethods(self): if not self._available: self.logger.info('Oculus DK2 python module not available !') @@ -139,6 +128,8 @@ def checkLibraryPath(self): sys.path.append(oculus_path) def _startOculus(self): + from time import sleep + import oculusvr as ovr from oculusvr import ( Hmd, cast, @@ -152,44 +143,78 @@ def _startOculus(self): except SystemError as err: self.logger.error("Oculus initialization failed, check the physical connections and run again") - if Hmd.detect() == 1: - self._hmd = Hmd() - self._description = cast(self._hmd.hmd, POINTER(ovrHmdDesc)).contents - self._frame = 0 - self._eyes_offset = [ ovrVector3f(), ovrVector3f() ] - self._eyes_offset[0] = 0.0, 0.0, 0.0 - self._eyes_offset[1] = 0.0, 0.0, 0.0 + """ + self._hmd = Hmd() + self._description = cast(self._hmd.hmd, POINTER(ovrHmdDesc)).contents + self._frame = 0 + self._eyes_offset = [ ovrVector3f(), ovrVector3f() ] + self._eyes_offset[0] = 0.0, 0.0, 0.0 + self._eyes_offset[1] = 0.0, 0.0, 0.0 + self._hmd.configure_tracking() + self.logger.info(self._description.ProductName) + """ + + try: + debug = not Hmd.detect() + + if debug: + self.logger.error("Oculus not connected") + + self._hmd = Hmd(debug=debug) + + desc = self._hmd.hmd.contents + self._frame = -1 + + sleep(0.1) self._hmd.configure_tracking() - self.logger.info(self._description.ProductName) - else: - self.logger.error("Oculus not connected") - raise Exception - - def _getMatrix(self): - from oculusvr import Hmd - from mathutils import ( - Quaternion, - Matrix, + self._fovPorts = ( + desc.DefaultEyeFov[0], + desc.DefaultEyeFov[1], ) - if self._hmd and Hmd.detect() == 1: - self._frame += 1 + #self._eyeTextures = [ ovrGLTexture(), ovrGLTexture() ] + self._eyeOffsets = [ ovrVector3f(), ovrVector3f() ] + self._width = [-1, -1] + self._height = [-1, -1] - poses = self._hmd.get_eye_poses(self._frame, self._eyes_offset) + rc = ovr.ovrRenderAPIConfig() + header = rc.Header + header.API = ovr.ovrRenderAPI_OpenGL + header.BackBufferSize = desc.Resolution + header.Multisample = 1 - # oculus may be returning the matrix for both eyes - # but we are using a single eye without offset + for i in range(8): + rc.PlatformData[i] = 0 - rotation_raw = poses[0].Orientation.toList() - position_raw = poses[0].Position.toList() + self._eyeRenderDescs = self._hmd.configure_rendering(rc, self._fovPorts) - rotation = Quaternion(rotation_raw).to_matrix().to_4x4() - position = Matrix.Translation(position_raw) + for eye in range(2): + size = self._hmd.get_fov_texture_size(eye, self._fovPorts[eye]) + self._width[eye], self._height[eye] = size.w, size.h + #eyeTexture = self._eyeTextures[eye] + #eyeTexture.API = ovr.ovrRenderAPI_OpenGL + #header = eyeTexture.Texture.Header + #header.TextureSize = size + #vp = header.RenderViewport + #vp.Size = size + #vp.Pos.x = 0 + #vp.Pos.y = 0 - matrix = position * rotation - matrix.invert() + self._eyeOffsets[eye] = self._eyeRenderDescs[eye].HmdToEyeViewOffset - return matrix - return None + + # store the data globally, to access it in screen + from bge import logic + global_dict = logic.globalDict + + global_dict['hmd'] = self._hmd + global_dict['frame'] = self._frame + global_dict['eyeOffsets'] = self._eyeOffsets + global_dict['fovPorts'] = self._fovPorts + + except Exception as err: + self.logger.error("Error initializing Oculus", str(err)) + else: + self.logger.info("Oculus properly initialized") From fcd10ac41b6ed33cda97e59254702c5217268a81 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Thu, 22 Oct 2015 16:19:25 -0200 Subject: [PATCH 2/6] Fix modelview matrix --- modules/blendervr/player/screen/hmd/oculus_dk2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/blendervr/player/screen/hmd/oculus_dk2.py b/modules/blendervr/player/screen/hmd/oculus_dk2.py index ebf0fce..76a06f4 100644 --- a/modules/blendervr/player/screen/hmd/oculus_dk2.py +++ b/modules/blendervr/player/screen/hmd/oculus_dk2.py @@ -157,7 +157,7 @@ def _updateModelViewMatrix(self, user_matrix, camera_matrix): matrix = position * orientation matrix.invert() - self._modelview_matrix[eye] = self._convertMatrixTo4x4(user_matrix * matrix * camera_matrix) + self._modelview_matrix[eye] = user_matrix * matrix * camera_matrix def _convertMatrixTo4x4(self, value): matrix = Matrix() From 7e1bbe2ffa3479c38812a8bb8e8ad2f1785afbf7 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Thu, 22 Oct 2015 16:25:23 -0200 Subject: [PATCH 3/6] debug mode only when needed --- .../plugins/oculus_dk2/virtual_environment/__init__.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/blendervr/plugins/oculus_dk2/virtual_environment/__init__.py b/modules/blendervr/plugins/oculus_dk2/virtual_environment/__init__.py index 03b1a5c..16beeb2 100644 --- a/modules/blendervr/plugins/oculus_dk2/virtual_environment/__init__.py +++ b/modules/blendervr/plugins/oculus_dk2/virtual_environment/__init__.py @@ -161,7 +161,10 @@ def _startOculus(self): if debug: self.logger.error("Oculus not connected") - self._hmd = Hmd(debug=debug) + try: + self._hmd = Hmd() + except: + self._hmd = Hmd(debug=True) desc = self._hmd.hmd.contents self._frame = -1 From 5e5e42937d06210f2234f452e8e007fbef083133 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Thu, 22 Oct 2015 17:00:42 -0200 Subject: [PATCH 4/6] update python-ovrsdk --- libs/python-ovrsdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/python-ovrsdk b/libs/python-ovrsdk index b291b2a..ebb4a42 160000 --- a/libs/python-ovrsdk +++ b/libs/python-ovrsdk @@ -1 +1 @@ -Subproject commit b291b2a72ebbaf70ff82d643da4bc8568f6da5fb +Subproject commit ebb4a423cf15eb19a76a309793f13f611baaad4e From 9dfd9ef81d81de06583c1c73b30e13a214ce81ae Mon Sep 17 00:00:00 2001 From: David Poirier-Quinot Date: Sat, 13 Feb 2016 16:38:30 +0100 Subject: [PATCH 5/6] modified scale factor in oculus dk2 shader, from 0.6 to 0.78. (euristic, does look right though) --- modules/blendervr/loader/oculus_dk2.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/blendervr/loader/oculus_dk2.glsl b/modules/blendervr/loader/oculus_dk2.glsl index 2c2db24..9742362 100644 --- a/modules/blendervr/loader/oculus_dk2.glsl +++ b/modules/blendervr/loader/oculus_dk2.glsl @@ -5,7 +5,7 @@ const vec4 kappa = vec4(1.0,1.7,0.7,15.0); uniform float screen_width; uniform float screen_height; -const float scaleFactor = 0.6; +const float scaleFactor = 0.78; const vec2 leftCenter = vec2(0.25, 0.5); const vec2 rightCenter = vec2(0.75, 0.5); From a66a92f71721e85cadac0992806558b334f8757f Mon Sep 17 00:00:00 2001 From: David Poirier-Quinot Date: Sat, 13 Feb 2016 16:41:18 +0100 Subject: [PATCH 6/6] updated oculus _updateModelViewMatrix mecanism: since the proper modelview matrix (one for each eye) implementation, user position matrix was not updated to reflect oculus'. it does now. --- .../blendervr/player/screen/hmd/oculus_dk2.py | 23 +++++++++++++++---- .../virtual_environment/__init__.py | 2 +- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/modules/blendervr/player/screen/hmd/oculus_dk2.py b/modules/blendervr/player/screen/hmd/oculus_dk2.py index 76a06f4..dadd3f7 100644 --- a/modules/blendervr/player/screen/hmd/oculus_dk2.py +++ b/modules/blendervr/player/screen/hmd/oculus_dk2.py @@ -118,7 +118,8 @@ def _updateMatrixForBuffer(self, bufferName, camera, depth): far = camera.far * scale self._updateProjectionMatrix(near, far) - self._updateModelViewMatrix(user.getPosition() * user.getVehiclePosition(), camera.modelview_matrix) + # self._updateModelViewMatrix(user.getPosition() * user.getVehiclePosition(), camera.modelview_matrix) + self._updateModelViewMatrix(user.getVehiclePosition(), camera.modelview_matrix) self._setModelViewMatrix(self._modelview_matrix[0]) self._setProjectionMatrix(self._projection_matrix[0]) @@ -157,7 +158,17 @@ def _updateModelViewMatrix(self, user_matrix, camera_matrix): matrix = position * orientation matrix.invert() - self._modelview_matrix[eye] = user_matrix * matrix * camera_matrix + # self._modelview_matrix[eye] = user_matrix * matrix * camera_matrix + self._modelview_matrix[eye] = matrix * user_matrix * camera_matrix + + # update user position to be used e.g. in processor files (arbitrary: take modelview matrix of eye 0) + if eye == 0: + try: + bufferName = 'left' + user = self._buffers[bufferName]['user'] + user.setPosition(matrix) + except Exception as err: + self.logger.log_traceback(err) def _convertMatrixTo4x4(self, value): matrix = Matrix() @@ -179,10 +190,12 @@ def _updateProjectionMatrix(self, near, far): import oculusvr as ovr global_dict = logic.globalDict - fov_ports = global_dict['fovPorts'] - self._projection_matrix[0] = self._convertMatrixTo4x4(ovr.Hmd.get_perspective(fov_ports[0], near, far, True).toList()) - self._projection_matrix[1] = self._convertMatrixTo4x4(ovr.Hmd.get_perspective(fov_ports[1], near, far, True).toList()) + fov_ports = global_dict.get('fovPorts') + + if fov_ports: + self._projection_matrix[0] = self._convertMatrixTo4x4(ovr.Hmd.get_perspective(fov_ports[0], near, far, True).toList()) + self._projection_matrix[1] = self._convertMatrixTo4x4(ovr.Hmd.get_perspective(fov_ports[1], near, far, True).toList()) def _cameraClippingChanged(self, near, far): """ diff --git a/modules/blendervr/plugins/oculus_dk2/virtual_environment/__init__.py b/modules/blendervr/plugins/oculus_dk2/virtual_environment/__init__.py index 16beeb2..f8664fe 100644 --- a/modules/blendervr/plugins/oculus_dk2/virtual_environment/__init__.py +++ b/modules/blendervr/plugins/oculus_dk2/virtual_environment/__init__.py @@ -87,7 +87,7 @@ def start(self): super(OculusDK2, self).start() from mathutils import Matrix - self.logger.debug("START PLUGIN") + self.logger.debug("Start Oculus DK2 plugin") try: self._startOculus()