Loading space_view3d_virtual_reality/__init__.py +27 −199 Changes for space_view3d_virtual_reality/__init__.py: 27 added lines, 199 removed lines. Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ # <pep8 compliant> bl_info = { "name": "Virtual Reality Viewport", "author": "Dalai Felinto", "author": "Dalai Felinto, Visgraf/IMPA", "version": (0, 9), "blender": (2, 7, 7), "location": "View 3D Tools", Loading @@ -32,206 +32,32 @@ bl_info = { import bpy from bgl import ( Buffer, GL_INT, GL_RGBA, ) from .opengl_helper import ( calculate_image_size, create_image, create_shader, delete_image, draw_callback_px, resize, ) from . import oculus from . import ui from . import operator from . import sandbox def get_context_3dview (context): """returns area and space""" screen = context.screen for area in screen.areas: if area.type == 'VIEW_3D': for region in area.regions: if region.type == 'WINDOW': return area, region return None, None def get_space_3dview(context): area = context.area for space in area.spaces: if space.type == 'VIEW_3D': return space return None def get_glsl_shader(shader_file): import os folderpath = os.path.dirname(os.path.abspath(__file__)) filepath = os.path.join(folderpath, 'shaders', shader_file) f = open(filepath, 'r') data = f.read() f.close() return data class VirtualRealityViewportOperator(bpy.types.Operator): """""" bl_idname = "view3d.virtual_reality_toggle" bl_label = "Toggle Virtual Reality Mode" bl_description = "" _enabled = True _timer = None _display_mode = None _is_multiview = None _space = None @classmethod def poll(cls, context): camera = context.scene.camera return camera and camera.type == 'CAMERA' def modal(self, context, event): if event.type == 'ESC': return self.cancel(context) if event.type == 'TIMER': # bug, waiting for fix: "[#31026] context.region broken after QuadView on + off" # http://projects.blender.org/tracker/index.php?func=detail&aid=31026&group_id=9&atid=498 if not context.region or \ not context.space_data or \ context.space_data.type != 'VIEW_3D': return {'PASS_THROUGH'} viewport_shade = context.space_data.viewport_shade self._enabled = (viewport_shade != 'RENDERED') if (self.width != context.region.width) or (self.height != context.region.height): resize(self, context) self.oculus.update() return {'PASS_THROUGH'} def invoke(self, context, event): """ * Create a fullscreen window with the editor in fullscreen with clean UI. * Views should be on, and this window should have stereo 3d mode set to side-by-side * Also you should lock a camera to the viewport to make sure you always look nicely * Sync the Oculus rotation + translation to the Blender camera * Now the opengl fun ... create a GLSL screen shader to run the warping distortions. """ if context.area.type == 'VIEW_3D': scene = context.scene window = context.window self.oculus = oculus.Oculus(scene, self.report) if not self.oculus.isAvailable(): return {'CANCELLED'} self._display_mode = window.stereo_3d_display.display_mode window.stereo_3d_display.display_mode = 'SIDEBYSIDE' #if bpy.ops.wm.window_fullscreen_toggle.poll(): # bpy.ops.wm.window_fullscreen_toggle() self._render = scene.render, scene.render.use_multiview, scene.render.resolution_x, scene.render.resolution_y scene.render.use_multiview = True scene.render.resolution_x = 1920 scene.render.resolution_y = 1080 #if bpy.ops.screen.screen_full_area.poll(): # bpy.ops.screen.screen_full_area(use_hide_panels=True) space = get_space_3dview(context) self._space = space, space.show_only_render, space.stereo_3d_camera, space.region_3d.view_perspective space.show_only_render = True space.stereo_3d_camera = 'S3D' space.region_3d.view_perspective = 'CAMERA' if bpy.ops.view3d.view_center_camera.poll(): bpy.ops.view3d.view_center_camera() self._timer = context.window_manager.event_timer_add(1.0/75.0, context.window) # 75 Hz self._handle = bpy.types.SpaceView3D.draw_handler_add(draw_callback_px, (self, context), 'WINDOW', 'POST_VIEW') context.window_manager.modal_handler_add(self) self.viewport = Buffer(GL_INT, 4) self.width = context.region.width self.height = context.region.height # power of two dimensions self.buffer_width, self.buffer_height = calculate_image_size(self.width, self.height) # images to dump the screen buffers self.color_id = create_image(self.buffer_width, self.buffer_height, GL_RGBA) # glsl shaders fragment_shader = get_glsl_shader(self.oculus.shader_file) self.program_shader = create_shader(fragment_shader) return {'RUNNING_MODAL'} else: self.report({'WARNING'}, "View3D not found, cannot run operator") return {'CANCELLED'} def cancel(self, context): if self._handle: bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW') del self._handle if self._timer: context.window_manager.event_timer_remove(self._timer) del self._timer self.oculus.quit() self.quit() # set back the original values try: context.window.stereo_3d_display.display_mode = self._display_mode render, use_multiview, resolution_x, resolution_y = self._render render.use_multiview = use_multiview render.resolution_x = resolution_x render.resolution_y = resolution_y space, show_only_render, stereo_3d_camera, view_perspective = self._space space.show_only_render = show_only_render space.stereo_3d_camera = stereo_3d_camera if space.region_3d: space.region_3d.view_perspective = view_perspective except Exception as err: self.report({'ERROR'}, str(err)) # ############################################################ # User Preferences # ############################################################ return {'CANCELLED'} # Preferences class VirtualRealityPreferences(bpy.types.AddonPreferences): bl_idname = __name__ display_backend = bpy.props.EnumProperty( name="Display Backend", description="Library to use for the display", items=(("OCULUS", "Oculus", "Oculus - oculus.com"), ("DEBUG", "Debug", "Debug backend - no real HMD"), ), default="OCULUS", ) def quit(self): """garbage colect""" if self.color_id: delete_image(self.color_id) def draw(self, context): layout = self.layout def is_stereo_left(self, context): """""" space = get_space_3dview(context) return space.stereo_3d_eye == 'LEFT' row = layout.row() row.prop(self, "display_backend") # ############################################################ Loading @@ -239,15 +65,17 @@ class VirtualRealityViewportOperator(bpy.types.Operator): # ############################################################ def register(): bpy.utils.register_class(VirtualRealityViewportOperator) sandbox.register() bpy.utils.register_class(VirtualRealityPreferences) operator.register() ui.register() def unregister(): bpy.utils.unregister_class(VirtualRealityViewportOperator) bpy.utils.unregister_class(VirtualRealityPreferences) operator.unregister() ui.unregister() sandbox.unregister() if __name__ == '__main__': Loading space_view3d_virtual_reality/hmd/__init__.py 0 → 100644 +113 −0 Changes for space_view3d_virtual_reality/hmd/__init__.py: 113 added lines, 0 removed lines. Original line number Diff line number Diff line TODO = True from mathutils import ( Matrix, Vector, ) class HMD_Data: status = None projection_matrix = Matrix() modelview_matrix = Matrix() interpupillary_distance = Vector((0.0, 0.0)) width = 0 height = 0 fbo = 0 texture = 0 class HMD: __slots__ = { "_device", "_projection_matrix", "_modelview_matrix", "_interpupillary_distance", "_width", "_height", "_fbo", "_texture", } def __init__(self, display_backend): self._device = None self._projection_matrix = Matrix() self._modelview_matrix = Matrix() self._interpupillary_distance = Vector((0.0, 0.0)) self._width = 0 self._height = 0 self._fbo = 0 self._texture = 0 from .oculus import Oculus from .debug import Debug displays = { 'OCULUS':Oculus, 'DEBUG':Debug, } assert(display_backend in displays) self._device = displays[display_backend]() @property def fbo(self): return self._fbo @property def texture(self): return self._texture @property def width(self): return self._width @property def height(self): return self._height @property def projection_matrix(self): return self._projection_matrix @property def modelview_matrix(self): return TODO def isConnected(self): """ Check if device is connected :return: return True if the device is connected :rtype: bool """ return self._device.isConnected() def init(self): """ Initialize device :return: return True if the device was properly initialized :rtype: bool """ return self._device.init() def loop(self): """ Get fresh tracking data """ return self._device.loop() def frameReady(self): """ The frame is ready to be send to the device """ return self._device.frameReady() def quit(self): """ Garbage collection """ return self._device.quit() space_view3d_virtual_reality/hmd/debug.py 0 → 100644 +51 −0 Changes for space_view3d_virtual_reality/hmd/debug.py: 51 added lines, 0 removed lines. Original line number Diff line number Diff line """ Debug ===== Debug device for testing """ from . import HMD_Data class Debug: def __init__(self): self._device = None def isConnected(self): """ Check if device is connected :return: return True if the device is connected :rtype: bool """ print('Debug:isConnected()') return True def init(self): """ Initialize device :return: return True if the device was properly initialized :rtype: bool """ print('Debug:init()') return True def loop(self): """ Get fresh tracking data """ print('Debug:loop()') def frameReady(self): """ The frame is ready to be send to the device """ print('Debug:frameReady()') def quit(self): """ Garbage collection """ print('Debug:quit()') space_view3d_virtual_reality/hmd/oculus.py 0 → 100644 +78 −0 Changes for space_view3d_virtual_reality/hmd/oculus.py: 78 added lines, 0 removed lines. Original line number Diff line number Diff line """ Oculus ====== Oculus (oculus.com) head mounted display It uses a C app to connect with the SDK The bridge code is hosted at Visgraf: http://git.impa.br/dfelinto/oculus_sdk_bridge """ TODO = True from . import HMD_Data class Oculus: def __init__(self): self._device = None def isConnected(self): """ Check if device is connected :return: return True if the device is connected :rtype: bool """ TODO """ Oculus SDK bridge return: true/false """ def init(self): """ Initialize device :return: return True if the device was properly initialized :rtype: bool """ TODO """ Oculus SDK bridge return: status, fbo, texture, projection matrix, eye separation, width, height """ def loop(self): """ Get fresh tracking data """ TODO """ Oculus SDK bridge return:head position, head orientation """ def frameReady(self): """ The frame is ready to be send to the device """ TODO """ Oculus SDK bridge """ def quit(self): """ Garbage collection """ TODO """ Oculus SDK bridge delete fbo, rbo, tex_id """ space_view3d_virtual_reality/oculus.pydeleted 100644 → 0 +0 −168 Changes for space_view3d_virtual_reality/oculus.py: 0 added lines, 168 removed lines. Original line number Diff line number Diff line class Oculus(): def __init__(self, scene, report): self._report = report self._available = True self._hmd = None self._description = None self._camera = scene.camera self._version = 2 # DK2 by default self._matrix_world = self._camera.matrix_world.copy() self._lens = self._camera.data.lens self._scale = self._calculateScale(scene) self._checkModule() self._start() def isAvailable(self): return self._available def _checkModule(self): """if library exists append it to sys.path""" import sys import os addon_path = os.path.dirname(os.path.abspath(__file__)) oculus_path = os.path.join(addon_path, "lib", "python-ovrsdk") if oculus_path not in sys.path: sys.path.append(oculus_path) def _start(self): try: from time import sleep from oculusvr import ( Hmd, cast, POINTER, ovrHmdDesc, ovrVector3f, ) Hmd.initialize() sleep(0.5) except SystemError as err: self._error("Oculus initialization failed, check the physical connections and run again") return 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.configure_tracking() self._setVersion(self._description.ProductName) self._camera.data.lens = 16 else: self._error("Oculus not connected") def _error(self, message): self._report({'ERROR'}, message) self._available = False def update(self): # update the camera matrix = self._getMatrix() if not matrix: return self._camera.matrix_world = self._matrix_world * matrix def quit(self): from oculusvr import Hmd if self._camera: self._camera.matrix_world = self._matrix_world self._camera.data.lens = self._lens if Hmd.detect() == 1: self._hmd.destroy() self._hmd = None Hmd.shutdown() def _setVersion(self, product_name): try: if product_name.find(b'DK2') != -1: self._version = 2 elif product_name.find(b'DK1') != -1: self._version = 1 else: raise Exception except: print("Error guessing device version (\"{0}\")".format(product_name)) def _calculateScale(self, scene): """ if BU != 1 meter, scale the transformations """ unit_settings = scene.unit_settings system = unit_settings.system if system == 'NONE': return None elif system == 'METRIC': return 1.0 / unit_settings.scale_length elif system == 'IMPERIAL': return 0.3048 / unit_settings.scale_length else: assert('Unit system not supported ({0})'.format(system)) def _scaleMovement(self, position): """ if BU != 1 meter, scale the transformations """ if self._scale is None: return position return [position[0] * self._scale, position[1] * self._scale, position[2] * self._scale] @property def shader_file(self): if self._version == 1: return 'oculus_dk1.glsl' else: return 'oculus_dk2.glsl' def _getMatrix(self): from oculusvr import Hmd from mathutils import ( Quaternion, Matrix, ) if self._hmd and Hmd.detect() == 1: self._frame += 1 poses = self._hmd.get_eye_poses(self._frame, self._eyes_offset) # oculus may be returning the matrix for both eyes # but we are using a single eye without offset rotation_raw = poses[0].Orientation.toList() position_raw = poses[0].Position.toList() # take scene units into consideration position_raw = self._scaleMovement(position_raw) rotation = Quaternion(rotation_raw).to_matrix().to_4x4() position = Matrix.Translation(position_raw) matrix = position * rotation return matrix return None Loading
space_view3d_virtual_reality/__init__.py +27 −199 Changes for space_view3d_virtual_reality/__init__.py: 27 added lines, 199 removed lines. Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ # <pep8 compliant> bl_info = { "name": "Virtual Reality Viewport", "author": "Dalai Felinto", "author": "Dalai Felinto, Visgraf/IMPA", "version": (0, 9), "blender": (2, 7, 7), "location": "View 3D Tools", Loading @@ -32,206 +32,32 @@ bl_info = { import bpy from bgl import ( Buffer, GL_INT, GL_RGBA, ) from .opengl_helper import ( calculate_image_size, create_image, create_shader, delete_image, draw_callback_px, resize, ) from . import oculus from . import ui from . import operator from . import sandbox def get_context_3dview (context): """returns area and space""" screen = context.screen for area in screen.areas: if area.type == 'VIEW_3D': for region in area.regions: if region.type == 'WINDOW': return area, region return None, None def get_space_3dview(context): area = context.area for space in area.spaces: if space.type == 'VIEW_3D': return space return None def get_glsl_shader(shader_file): import os folderpath = os.path.dirname(os.path.abspath(__file__)) filepath = os.path.join(folderpath, 'shaders', shader_file) f = open(filepath, 'r') data = f.read() f.close() return data class VirtualRealityViewportOperator(bpy.types.Operator): """""" bl_idname = "view3d.virtual_reality_toggle" bl_label = "Toggle Virtual Reality Mode" bl_description = "" _enabled = True _timer = None _display_mode = None _is_multiview = None _space = None @classmethod def poll(cls, context): camera = context.scene.camera return camera and camera.type == 'CAMERA' def modal(self, context, event): if event.type == 'ESC': return self.cancel(context) if event.type == 'TIMER': # bug, waiting for fix: "[#31026] context.region broken after QuadView on + off" # http://projects.blender.org/tracker/index.php?func=detail&aid=31026&group_id=9&atid=498 if not context.region or \ not context.space_data or \ context.space_data.type != 'VIEW_3D': return {'PASS_THROUGH'} viewport_shade = context.space_data.viewport_shade self._enabled = (viewport_shade != 'RENDERED') if (self.width != context.region.width) or (self.height != context.region.height): resize(self, context) self.oculus.update() return {'PASS_THROUGH'} def invoke(self, context, event): """ * Create a fullscreen window with the editor in fullscreen with clean UI. * Views should be on, and this window should have stereo 3d mode set to side-by-side * Also you should lock a camera to the viewport to make sure you always look nicely * Sync the Oculus rotation + translation to the Blender camera * Now the opengl fun ... create a GLSL screen shader to run the warping distortions. """ if context.area.type == 'VIEW_3D': scene = context.scene window = context.window self.oculus = oculus.Oculus(scene, self.report) if not self.oculus.isAvailable(): return {'CANCELLED'} self._display_mode = window.stereo_3d_display.display_mode window.stereo_3d_display.display_mode = 'SIDEBYSIDE' #if bpy.ops.wm.window_fullscreen_toggle.poll(): # bpy.ops.wm.window_fullscreen_toggle() self._render = scene.render, scene.render.use_multiview, scene.render.resolution_x, scene.render.resolution_y scene.render.use_multiview = True scene.render.resolution_x = 1920 scene.render.resolution_y = 1080 #if bpy.ops.screen.screen_full_area.poll(): # bpy.ops.screen.screen_full_area(use_hide_panels=True) space = get_space_3dview(context) self._space = space, space.show_only_render, space.stereo_3d_camera, space.region_3d.view_perspective space.show_only_render = True space.stereo_3d_camera = 'S3D' space.region_3d.view_perspective = 'CAMERA' if bpy.ops.view3d.view_center_camera.poll(): bpy.ops.view3d.view_center_camera() self._timer = context.window_manager.event_timer_add(1.0/75.0, context.window) # 75 Hz self._handle = bpy.types.SpaceView3D.draw_handler_add(draw_callback_px, (self, context), 'WINDOW', 'POST_VIEW') context.window_manager.modal_handler_add(self) self.viewport = Buffer(GL_INT, 4) self.width = context.region.width self.height = context.region.height # power of two dimensions self.buffer_width, self.buffer_height = calculate_image_size(self.width, self.height) # images to dump the screen buffers self.color_id = create_image(self.buffer_width, self.buffer_height, GL_RGBA) # glsl shaders fragment_shader = get_glsl_shader(self.oculus.shader_file) self.program_shader = create_shader(fragment_shader) return {'RUNNING_MODAL'} else: self.report({'WARNING'}, "View3D not found, cannot run operator") return {'CANCELLED'} def cancel(self, context): if self._handle: bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW') del self._handle if self._timer: context.window_manager.event_timer_remove(self._timer) del self._timer self.oculus.quit() self.quit() # set back the original values try: context.window.stereo_3d_display.display_mode = self._display_mode render, use_multiview, resolution_x, resolution_y = self._render render.use_multiview = use_multiview render.resolution_x = resolution_x render.resolution_y = resolution_y space, show_only_render, stereo_3d_camera, view_perspective = self._space space.show_only_render = show_only_render space.stereo_3d_camera = stereo_3d_camera if space.region_3d: space.region_3d.view_perspective = view_perspective except Exception as err: self.report({'ERROR'}, str(err)) # ############################################################ # User Preferences # ############################################################ return {'CANCELLED'} # Preferences class VirtualRealityPreferences(bpy.types.AddonPreferences): bl_idname = __name__ display_backend = bpy.props.EnumProperty( name="Display Backend", description="Library to use for the display", items=(("OCULUS", "Oculus", "Oculus - oculus.com"), ("DEBUG", "Debug", "Debug backend - no real HMD"), ), default="OCULUS", ) def quit(self): """garbage colect""" if self.color_id: delete_image(self.color_id) def draw(self, context): layout = self.layout def is_stereo_left(self, context): """""" space = get_space_3dview(context) return space.stereo_3d_eye == 'LEFT' row = layout.row() row.prop(self, "display_backend") # ############################################################ Loading @@ -239,15 +65,17 @@ class VirtualRealityViewportOperator(bpy.types.Operator): # ############################################################ def register(): bpy.utils.register_class(VirtualRealityViewportOperator) sandbox.register() bpy.utils.register_class(VirtualRealityPreferences) operator.register() ui.register() def unregister(): bpy.utils.unregister_class(VirtualRealityViewportOperator) bpy.utils.unregister_class(VirtualRealityPreferences) operator.unregister() ui.unregister() sandbox.unregister() if __name__ == '__main__': Loading
space_view3d_virtual_reality/hmd/__init__.py 0 → 100644 +113 −0 Changes for space_view3d_virtual_reality/hmd/__init__.py: 113 added lines, 0 removed lines. Original line number Diff line number Diff line TODO = True from mathutils import ( Matrix, Vector, ) class HMD_Data: status = None projection_matrix = Matrix() modelview_matrix = Matrix() interpupillary_distance = Vector((0.0, 0.0)) width = 0 height = 0 fbo = 0 texture = 0 class HMD: __slots__ = { "_device", "_projection_matrix", "_modelview_matrix", "_interpupillary_distance", "_width", "_height", "_fbo", "_texture", } def __init__(self, display_backend): self._device = None self._projection_matrix = Matrix() self._modelview_matrix = Matrix() self._interpupillary_distance = Vector((0.0, 0.0)) self._width = 0 self._height = 0 self._fbo = 0 self._texture = 0 from .oculus import Oculus from .debug import Debug displays = { 'OCULUS':Oculus, 'DEBUG':Debug, } assert(display_backend in displays) self._device = displays[display_backend]() @property def fbo(self): return self._fbo @property def texture(self): return self._texture @property def width(self): return self._width @property def height(self): return self._height @property def projection_matrix(self): return self._projection_matrix @property def modelview_matrix(self): return TODO def isConnected(self): """ Check if device is connected :return: return True if the device is connected :rtype: bool """ return self._device.isConnected() def init(self): """ Initialize device :return: return True if the device was properly initialized :rtype: bool """ return self._device.init() def loop(self): """ Get fresh tracking data """ return self._device.loop() def frameReady(self): """ The frame is ready to be send to the device """ return self._device.frameReady() def quit(self): """ Garbage collection """ return self._device.quit()
space_view3d_virtual_reality/hmd/debug.py 0 → 100644 +51 −0 Changes for space_view3d_virtual_reality/hmd/debug.py: 51 added lines, 0 removed lines. Original line number Diff line number Diff line """ Debug ===== Debug device for testing """ from . import HMD_Data class Debug: def __init__(self): self._device = None def isConnected(self): """ Check if device is connected :return: return True if the device is connected :rtype: bool """ print('Debug:isConnected()') return True def init(self): """ Initialize device :return: return True if the device was properly initialized :rtype: bool """ print('Debug:init()') return True def loop(self): """ Get fresh tracking data """ print('Debug:loop()') def frameReady(self): """ The frame is ready to be send to the device """ print('Debug:frameReady()') def quit(self): """ Garbage collection """ print('Debug:quit()')
space_view3d_virtual_reality/hmd/oculus.py 0 → 100644 +78 −0 Changes for space_view3d_virtual_reality/hmd/oculus.py: 78 added lines, 0 removed lines. Original line number Diff line number Diff line """ Oculus ====== Oculus (oculus.com) head mounted display It uses a C app to connect with the SDK The bridge code is hosted at Visgraf: http://git.impa.br/dfelinto/oculus_sdk_bridge """ TODO = True from . import HMD_Data class Oculus: def __init__(self): self._device = None def isConnected(self): """ Check if device is connected :return: return True if the device is connected :rtype: bool """ TODO """ Oculus SDK bridge return: true/false """ def init(self): """ Initialize device :return: return True if the device was properly initialized :rtype: bool """ TODO """ Oculus SDK bridge return: status, fbo, texture, projection matrix, eye separation, width, height """ def loop(self): """ Get fresh tracking data """ TODO """ Oculus SDK bridge return:head position, head orientation """ def frameReady(self): """ The frame is ready to be send to the device """ TODO """ Oculus SDK bridge """ def quit(self): """ Garbage collection """ TODO """ Oculus SDK bridge delete fbo, rbo, tex_id """
space_view3d_virtual_reality/oculus.pydeleted 100644 → 0 +0 −168 Changes for space_view3d_virtual_reality/oculus.py: 0 added lines, 168 removed lines. Original line number Diff line number Diff line class Oculus(): def __init__(self, scene, report): self._report = report self._available = True self._hmd = None self._description = None self._camera = scene.camera self._version = 2 # DK2 by default self._matrix_world = self._camera.matrix_world.copy() self._lens = self._camera.data.lens self._scale = self._calculateScale(scene) self._checkModule() self._start() def isAvailable(self): return self._available def _checkModule(self): """if library exists append it to sys.path""" import sys import os addon_path = os.path.dirname(os.path.abspath(__file__)) oculus_path = os.path.join(addon_path, "lib", "python-ovrsdk") if oculus_path not in sys.path: sys.path.append(oculus_path) def _start(self): try: from time import sleep from oculusvr import ( Hmd, cast, POINTER, ovrHmdDesc, ovrVector3f, ) Hmd.initialize() sleep(0.5) except SystemError as err: self._error("Oculus initialization failed, check the physical connections and run again") return 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.configure_tracking() self._setVersion(self._description.ProductName) self._camera.data.lens = 16 else: self._error("Oculus not connected") def _error(self, message): self._report({'ERROR'}, message) self._available = False def update(self): # update the camera matrix = self._getMatrix() if not matrix: return self._camera.matrix_world = self._matrix_world * matrix def quit(self): from oculusvr import Hmd if self._camera: self._camera.matrix_world = self._matrix_world self._camera.data.lens = self._lens if Hmd.detect() == 1: self._hmd.destroy() self._hmd = None Hmd.shutdown() def _setVersion(self, product_name): try: if product_name.find(b'DK2') != -1: self._version = 2 elif product_name.find(b'DK1') != -1: self._version = 1 else: raise Exception except: print("Error guessing device version (\"{0}\")".format(product_name)) def _calculateScale(self, scene): """ if BU != 1 meter, scale the transformations """ unit_settings = scene.unit_settings system = unit_settings.system if system == 'NONE': return None elif system == 'METRIC': return 1.0 / unit_settings.scale_length elif system == 'IMPERIAL': return 0.3048 / unit_settings.scale_length else: assert('Unit system not supported ({0})'.format(system)) def _scaleMovement(self, position): """ if BU != 1 meter, scale the transformations """ if self._scale is None: return position return [position[0] * self._scale, position[1] * self._scale, position[2] * self._scale] @property def shader_file(self): if self._version == 1: return 'oculus_dk1.glsl' else: return 'oculus_dk2.glsl' def _getMatrix(self): from oculusvr import Hmd from mathutils import ( Quaternion, Matrix, ) if self._hmd and Hmd.detect() == 1: self._frame += 1 poses = self._hmd.get_eye_poses(self._frame, self._eyes_offset) # oculus may be returning the matrix for both eyes # but we are using a single eye without offset rotation_raw = poses[0].Orientation.toList() position_raw = poses[0].Position.toList() # take scene units into consideration position_raw = self._scaleMovement(position_raw) rotation = Quaternion(rotation_raw).to_matrix().to_4x4() position = Matrix.Translation(position_raw) matrix = position * rotation return matrix return None