From 8dcb6f7efacf69e3afd732ecaa024b126013f0c8 Mon Sep 17 00:00:00 2001 From: William Culver Date: Tue, 3 May 2016 12:13:27 +0100 Subject: [PATCH 01/15] cedeon: changes to hmd_bridge --- space_view3d_virtual_reality/lib/hmd_sdk_bridge | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/space_view3d_virtual_reality/lib/hmd_sdk_bridge b/space_view3d_virtual_reality/lib/hmd_sdk_bridge index a6d113e..af3097f 160000 --- a/space_view3d_virtual_reality/lib/hmd_sdk_bridge +++ b/space_view3d_virtual_reality/lib/hmd_sdk_bridge @@ -1 +1 @@ -Subproject commit a6d113e7bec159a28b317f4261a043667275869f +Subproject commit af3097f94a43fb6c0252eb5ed6689cfee4674694 From 5ca24cb31794cb5ae500093f5f5f0d781aee295b Mon Sep 17 00:00:00 2001 From: William Culver Date: Tue, 3 May 2016 14:33:41 +0100 Subject: [PATCH 02/15] Added Option for HTC Vive --- space_view3d_virtual_reality/__init__.py | 1 + space_view3d_virtual_reality/hmd/__init__.py | 3 ++- space_view3d_virtual_reality/hmd/openvr.py | 24 ++++++++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 space_view3d_virtual_reality/hmd/openvr.py diff --git a/space_view3d_virtual_reality/__init__.py b/space_view3d_virtual_reality/__init__.py index 6b4c561..dccccba 100644 --- a/space_view3d_virtual_reality/__init__.py +++ b/space_view3d_virtual_reality/__init__.py @@ -49,6 +49,7 @@ class VirtualRealityPreferences(bpy.types.AddonPreferences): description="Library to use for the display", items=(("OCULUS", "Oculus", "Oculus - oculus.com"), ("OCULUS_LEGACY", "Oculus Legacy", "Oculus 0.5 - oculus.com"), + ("VIVE", "HTC Vive", "OpenVR"), ("DEBUG", "Debug", "Debug backend - no real HMD"), ), default="OCULUS_LEGACY", diff --git a/space_view3d_virtual_reality/hmd/__init__.py b/space_view3d_virtual_reality/hmd/__init__.py index 5632572..26dd509 100644 --- a/space_view3d_virtual_reality/hmd/__init__.py +++ b/space_view3d_virtual_reality/hmd/__init__.py @@ -29,11 +29,13 @@ def HMD(display_backend, context, error_callback): """ from .oculus import Oculus from .oculus_legacy import OculusLegacy + from .openvr import OpenVR from .debug import Debug displays = { 'OCULUS':Oculus, 'OCULUS_LEGACY':OculusLegacy, + 'VIVE':OpenVR, 'DEBUG':Debug, } @@ -295,4 +297,3 @@ def _convertMatrixTo4x4(self, value): matrix[3] = value[12:16] return matrix.transposed() - diff --git a/space_view3d_virtual_reality/hmd/openvr.py b/space_view3d_virtual_reality/hmd/openvr.py new file mode 100644 index 0000000..e89d780 --- /dev/null +++ b/space_view3d_virtual_reality/hmd/openvr.py @@ -0,0 +1,24 @@ +""" +OpenVR Compatible (HTC Vive) +============= + +OpenVR Compatible head mounted display +It uses a python wrapper to connect with the SDK +""" + +from . import HMD_Base + +from .oculus import Oculus + +from ..lib import ( + checkModule, + ) + +class OpenVR(HMD_Base): + def __init__(self, context, error_callback): + super(OpenVR, self).__init__('OpenVR', True, context, error_callback) + checkModule('hmd_sdk_bridge') + + def _getHMDClass(self): + from bridge.hmd.openvr import HMD + return HMD From 9b7050693267c1535f2130cc4a9d472096fef315 Mon Sep 17 00:00:00 2001 From: William Culver Date: Tue, 3 May 2016 15:53:53 +0100 Subject: [PATCH 03/15] Added init --- space_view3d_virtual_reality/hmd/openvr.py | 39 ++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/space_view3d_virtual_reality/hmd/openvr.py b/space_view3d_virtual_reality/hmd/openvr.py index e89d780..0e7d818 100644 --- a/space_view3d_virtual_reality/hmd/openvr.py +++ b/space_view3d_virtual_reality/hmd/openvr.py @@ -8,8 +8,6 @@ from . import HMD_Base -from .oculus import Oculus - from ..lib import ( checkModule, ) @@ -22,3 +20,40 @@ def __init__(self, context, error_callback): def _getHMDClass(self): from bridge.hmd.openvr import HMD return HMD + + def init(self, context): + """ + Initialize device + + :return: return True if the device was properly initialized + :rtype: bool + """ + try: + HMD = self._getHMDClass() + self._hmd = HMD() + + # gather arguments from HMD + + self.setEye(0) + self.width = self._hmd.width_left + self.height = self._hmd.height_left + + self.setEye(1) + self.width = self._hmd.width_right + self.height = self._hmd.height_right + + # initialize FBO + if not super(OpenVR, self).init(): + raise Exception("Failed to initialize HMD") + + # send it back to HMD + if not self._setup(): + raise Exception("Failed to setup OpenVR Compatible HMD") + + except Exception as E: + self.error("init", E, True) + self._hmd = None + return False + + else: + return True From f1a18c35e3189419e1fa9b35db0ca99febadc35b Mon Sep 17 00:00:00 2001 From: William Culver Date: Tue, 3 May 2016 16:13:19 +0100 Subject: [PATCH 04/15] changed submodule --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 0425cd5..dd889ff 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "space_view3d_virtual_reality/lib/hmd_sdk_bridge"] path = space_view3d_virtual_reality/lib/hmd_sdk_bridge - url = ../hmd_sdk_bridge_build + url = ../hmd_sdk_bridge From bdc68c598f453592aa4281444bf91e8294c2a672 Mon Sep 17 00:00:00 2001 From: William Culver Date: Tue, 3 May 2016 16:20:01 +0100 Subject: [PATCH 05/15] removed submodule for now --- space_view3d_virtual_reality/lib/hmd_sdk_bridge | 1 - 1 file changed, 1 deletion(-) delete mode 160000 space_view3d_virtual_reality/lib/hmd_sdk_bridge diff --git a/space_view3d_virtual_reality/lib/hmd_sdk_bridge b/space_view3d_virtual_reality/lib/hmd_sdk_bridge deleted file mode 160000 index af3097f..0000000 --- a/space_view3d_virtual_reality/lib/hmd_sdk_bridge +++ /dev/null @@ -1 +0,0 @@ -Subproject commit af3097f94a43fb6c0252eb5ed6689cfee4674694 From ec574740216b86aa0645e6fbed0f20fb9d76366a Mon Sep 17 00:00:00 2001 From: William Culver Date: Tue, 3 May 2016 16:38:10 +0100 Subject: [PATCH 06/15] added new submodule --- space_view3d_virtual_reality/lib/hmd_sdk_bridge | 1 + 1 file changed, 1 insertion(+) create mode 160000 space_view3d_virtual_reality/lib/hmd_sdk_bridge diff --git a/space_view3d_virtual_reality/lib/hmd_sdk_bridge b/space_view3d_virtual_reality/lib/hmd_sdk_bridge new file mode 160000 index 0000000..a941249 --- /dev/null +++ b/space_view3d_virtual_reality/lib/hmd_sdk_bridge @@ -0,0 +1 @@ +Subproject commit a9412498206cf53ce0051364a36ec18f9cb478b6 From 1c3d6bd1f8bc9cb320458a6e620835fbbbb63ed4 Mon Sep 17 00:00:00 2001 From: William Culver Date: Wed, 4 May 2016 17:42:49 +0100 Subject: [PATCH 07/15] Added introspection functionality --- space_view3d_virtual_reality/hmd/openvr.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/space_view3d_virtual_reality/hmd/openvr.py b/space_view3d_virtual_reality/hmd/openvr.py index 0e7d818..2291c83 100644 --- a/space_view3d_virtual_reality/hmd/openvr.py +++ b/space_view3d_virtual_reality/hmd/openvr.py @@ -18,6 +18,9 @@ def __init__(self, context, error_callback): checkModule('hmd_sdk_bridge') def _getHMDClass(self): + """ + This is the python interface to the DLL file in hmd_sdk_bridge. + """ from bridge.hmd.openvr import HMD return HMD @@ -32,8 +35,12 @@ def init(self, context): HMD = self._getHMDClass() self._hmd = HMD() - # gather arguments from HMD + # bail out early if we didn't initialize properly + if self._hmd.get_state_bool() == False: + raise Exception(self._hmd.get_status()) + + # gather arguments from HMD self.setEye(0) self.width = self._hmd.width_left self.height = self._hmd.height_left From ea9983aec84e319d1218ad49081e7ae56930dc5a Mon Sep 17 00:00:00 2001 From: William Culver Date: Thu, 5 May 2016 17:30:06 +0100 Subject: [PATCH 08/15] Copied Oculus.py class implementation --- space_view3d_virtual_reality/hmd/openvr.py | 59 +++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/space_view3d_virtual_reality/hmd/openvr.py b/space_view3d_virtual_reality/hmd/openvr.py index 2291c83..6d7fa28 100644 --- a/space_view3d_virtual_reality/hmd/openvr.py +++ b/space_view3d_virtual_reality/hmd/openvr.py @@ -35,6 +35,10 @@ def init(self, context): HMD = self._getHMDClass() self._hmd = HMD() + #import pdb + #pdb.set_trace() + + # bail out early if we didn't initialize properly if self._hmd.get_state_bool() == False: raise Exception(self._hmd.get_status()) @@ -58,9 +62,62 @@ def init(self, context): raise Exception("Failed to setup OpenVR Compatible HMD") except Exception as E: - self.error("init", E, True) + self.error("OpenVR.init", E, True) self._hmd = None return False else: return True + + def _setup(self): + return self._hmd.setup(self._color_texture[0], self._color_texture[1]) + + def loop(self, context): + """ + Get fresh tracking data + """ + try: + data = self._hmd.update() + + self._eye_orientation_raw[0] = data[0] + self._eye_orientation_raw[1] = data[2] + self._eye_position_raw[0] = data[1] + self._eye_position_raw[1] = data[3] + + # update matrices + super(OpenVR, self).loop(context) + + except Exception as E: + self.error("OpenVR.loop", E, False) + return False + + return True + + def frameReady(self): + """ + The frame is ready to be sent to the device + """ + try: + self._hmd.frameReady() + + except Exception as E: + self.error("OpenVR.frameReady", E, False) + return False + + return True + + def reCenter(self): + """ + Re-center the HMD device + + :return: return True if success + :rtype: bool + """ + return self._hmd.reCenter() + + def quit(self): + """ + Garbage collection + """ + self._hmd = None + return super(OpenVR, self).quit() From 52e03567e18f46281abc5253327ef55901e12b49 Mon Sep 17 00:00:00 2001 From: William Culver Date: Fri, 6 May 2016 17:41:52 +0100 Subject: [PATCH 09/15] Add Statusline 'Running Modal' --- space_view3d_virtual_reality/operator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/space_view3d_virtual_reality/operator.py b/space_view3d_virtual_reality/operator.py index 5434930..748a6a7 100644 --- a/space_view3d_virtual_reality/operator.py +++ b/space_view3d_virtual_reality/operator.py @@ -135,6 +135,7 @@ def invoke(self, context, event): return {'CANCELLED'} if self.init(context): + print('Running Modal...') return {'RUNNING_MODAL'} else: # quit right away @@ -784,4 +785,3 @@ def unregister(): del bpy.types.WindowManager.virtual_reality bpy.utils.unregister_class(VirtualRealityInfo) bpy.utils.unregister_class(VirtualRealityCommandInfo) - From fb9f9395f55f7e767d3933257dddc051cf32862d Mon Sep 17 00:00:00 2001 From: William Culver Date: Fri, 6 May 2016 17:42:13 +0100 Subject: [PATCH 10/15] Removed debugger lines --- space_view3d_virtual_reality/hmd/openvr.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/space_view3d_virtual_reality/hmd/openvr.py b/space_view3d_virtual_reality/hmd/openvr.py index 6d7fa28..736a6f1 100644 --- a/space_view3d_virtual_reality/hmd/openvr.py +++ b/space_view3d_virtual_reality/hmd/openvr.py @@ -35,10 +35,6 @@ def init(self, context): HMD = self._getHMDClass() self._hmd = HMD() - #import pdb - #pdb.set_trace() - - # bail out early if we didn't initialize properly if self._hmd.get_state_bool() == False: raise Exception(self._hmd.get_status()) From 743dcebffbc539019e5e7e96b117c5734ac142d1 Mon Sep 17 00:00:00 2001 From: William Culver Date: Tue, 10 May 2016 23:06:24 +0100 Subject: [PATCH 11/15] Added projection_matrix implementation to openvr class --- space_view3d_virtual_reality/hmd/openvr.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/space_view3d_virtual_reality/hmd/openvr.py b/space_view3d_virtual_reality/hmd/openvr.py index 736a6f1..670a623 100644 --- a/space_view3d_virtual_reality/hmd/openvr.py +++ b/space_view3d_virtual_reality/hmd/openvr.py @@ -24,6 +24,22 @@ def _getHMDClass(self): from bridge.hmd.openvr import HMD return HMD + @property + def projection_matrix(self): + if self._current_eye: + matrix = self._hmd.getProjectionMatrixRight(self._near, self._far) + else: + matrix = self._hmd.getProjectionMatrixLeft(self._near, self._far) + + self.projection_matrix = matrix + return super(OpenVR, self).projection_matrix + + @projection_matrix.setter + def projection_matrix(self, value): + self._projection_matrix[self._current_eye] = \ + self._convertMatrixTo4x4(value) + + def init(self, context): """ Initialize device @@ -87,6 +103,10 @@ def loop(self, context): self.error("OpenVR.loop", E, False) return False + #if VERBOSE: + # print("Left Eye Orientation Raw: " + str(self._eye_orientation_raw[0])) + # print("Right Eye Orientation Raw: " + str(self._eye_orientation_raw[1])) + return True def frameReady(self): From cde9f9eb1d2aa9844eb71298774456a2b8a13a87 Mon Sep 17 00:00:00 2001 From: William Culver Date: Tue, 10 May 2016 23:38:02 +0100 Subject: [PATCH 12/15] Added HTC Vive to readme --- README.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 9c10291..22adb05 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Virtual Reality Viewport -Addon to bring virtual reality devices to the Blender viewport. +Add-on to bring virtual reality devices to the Blender viewport. This is work in progress, use at your own risk. @@ -13,10 +13,13 @@ Oculus Legacy (Linux, Mac, Windows) Oculus (Windows) * Oculus 0.7 runtime -Note -==== -* Windows 64 builds are not working at the moment, use 32 bits instead -* Extended Mode is the only supported mode +HTC Vive (Windows) +* OpenVR 0.9.20 runtime + +Current Known Issues +==================== +HTC Vive: TODO: Fix Blender crash on OpenVR when stopping. (Pausing works). + How to Use ========== @@ -79,7 +82,7 @@ Roadmap Credits ======= * Oculus SDK 0.5 wrapper by https://github.com/jherico/python-ovrsdk -* Oculus SDK 0.7 bridge: Dalai Felinto and Djalma Lucio @ Visgraf / IMPA +* Oculus SDK 0.7 bridge: Dalai Felinto and Djalma Lucio @ Visgraf / IMPA * Blender Addon - Dalai Felinto - http://www.dalaifelinto.com Acknowledgements From a1225074a439471574bc570a79185d1877fa33e8 Mon Sep 17 00:00:00 2001 From: William Culver Date: Tue, 10 May 2016 23:40:32 +0100 Subject: [PATCH 13/15] Added William Culver to credits --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 22adb05..0150371 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,7 @@ Credits * Oculus SDK 0.5 wrapper by https://github.com/jherico/python-ovrsdk * Oculus SDK 0.7 bridge: Dalai Felinto and Djalma Lucio @ Visgraf / IMPA * Blender Addon - Dalai Felinto - http://www.dalaifelinto.com +* OpenVR Implementation by William Culver (@cedeon) Acknowledgements ================ From e2c850e76dd19f953623db6601122bf4e7484087 Mon Sep 17 00:00:00 2001 From: William Culver Date: Thu, 12 May 2016 11:59:38 +0100 Subject: [PATCH 14/15] Added a status field to the hmd class and then an info popup on success. --- space_view3d_virtual_reality/hmd/__init__.py | 10 ++++++++++ space_view3d_virtual_reality/hmd/oculus.py | 4 +++- space_view3d_virtual_reality/hmd/openvr.py | 2 ++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/space_view3d_virtual_reality/hmd/__init__.py b/space_view3d_virtual_reality/hmd/__init__.py index 26dd509..733e66f 100644 --- a/space_view3d_virtual_reality/hmd/__init__.py +++ b/space_view3d_virtual_reality/hmd/__init__.py @@ -65,6 +65,7 @@ class HMD_Base: "_modelview_matrix", "_near", "_far", + "_status", } def __init__(self, name, is_direct_mode, context, error_callback): @@ -81,6 +82,7 @@ def __init__(self, name, is_direct_mode, context, error_callback): self._eye_orientation_raw = [[1.0, 0.0, 0.0, 0.0], [1.0, 0.0, 0.0, 0.0]] self._eye_position_raw = [[0.0, 0.0, 0.0], [0.0, 0.0, 0.0]] self._scale = self._calculateScale(context) + self._status = "Uninitialized" self._updateViewClipping(context) @@ -120,6 +122,14 @@ def projection_matrix(self): def modelview_matrix(self): return self._modelview_matrix[self._current_eye] + @property + def status(self): + return self._status + + @status.setter + def status(self, value): + self._status = value + def setEye(self, eye): self._current_eye = int(bool(eye)) diff --git a/space_view3d_virtual_reality/hmd/oculus.py b/space_view3d_virtual_reality/hmd/oculus.py index 77bfe4c..b81025c 100644 --- a/space_view3d_virtual_reality/hmd/oculus.py +++ b/space_view3d_virtual_reality/hmd/oculus.py @@ -68,6 +68,9 @@ def init(self, context): if not self._setup(): raise Exception("Failed to setup Oculus") + # set status to okay. + self.status = "HMD Initialized" + except Exception as E: self.error("init", E, True) self._hmd = None @@ -128,4 +131,3 @@ def quit(self): """ self._hmd = None return super(Oculus, self).quit() - diff --git a/space_view3d_virtual_reality/hmd/openvr.py b/space_view3d_virtual_reality/hmd/openvr.py index 670a623..cf93c02 100644 --- a/space_view3d_virtual_reality/hmd/openvr.py +++ b/space_view3d_virtual_reality/hmd/openvr.py @@ -55,6 +55,8 @@ def init(self, context): if self._hmd.get_state_bool() == False: raise Exception(self._hmd.get_status()) + # Tell the user our status at this point. + self.status = "HMD Init OK. Make sure lighthouses running else no display." # gather arguments from HMD self.setEye(0) From 10285cdfd3306690b69ab9c6dc0380aa409d0e9a Mon Sep 17 00:00:00 2001 From: William Culver Date: Thu, 12 May 2016 12:02:24 +0100 Subject: [PATCH 15/15] Changed timer to 90 Hz - might break DK2?!? see description if we need to regress this , perhaps we should refactor so this changes depending on HMD selection. --- space_view3d_virtual_reality/operator.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/space_view3d_virtual_reality/operator.py b/space_view3d_virtual_reality/operator.py index 748a6a7..5c48fa2 100644 --- a/space_view3d_virtual_reality/operator.py +++ b/space_view3d_virtual_reality/operator.py @@ -250,7 +250,8 @@ def init(self, context): self._hash_master = hash(context.area) # setup modal - self._timer = wm.event_timer_add(1.0 / 75.0, context.window) # 75 Hz + # TODO: check: cedeon changed to: 90Hz + self._timer = wm.event_timer_add(1.0 / 90.0, context.window) # 90 Hz self._handle_pre = bpy.types.SpaceView3D.draw_handler_add(self._draw_callback_pre, (context,), 'WINDOW', 'PRE_VIEW') self._handle_post = bpy.types.SpaceView3D.draw_handler_add(self._draw_callback_post, (context,), 'WINDOW', 'POST_VIEW') self._handle_pixel = bpy.types.SpaceView3D.draw_handler_add(self._draw_callback_pixel, (context,), 'WINDOW', 'POST_PIXEL') @@ -268,6 +269,8 @@ def _init(self, context): if not self._hmd.init(context): self.report({'ERROR'}, "Error initializing device") return False + else: + self.report({'INFO'}, self._hmd.status ) # get the data from device color_texture = [0, 0]