require 'core/appkit/lua/class' GearVRSystem = Appkit.class(GearVRSystem) local Application = stingray.Application local Viewport = stingray.Viewport local World = stingray.World local Unit = stingray.Unit local Matrix4x4 = stingray.Matrix4x4 local Camera = stingray.Camera local GearVR = stingray.GearVR function GearVRSystem.exists() return GearVR ~= nil end function GearVRSystem:init(world) if not GearVR then return end self._world = world self._enabled = false self._is_initialized = false end function GearVRSystem:initialize(near, far, left_rt, right_rt) if not GearVR then return end if not self then return end -- Intialize VR system self._is_initialized = GearVR.initialize() -- Bail if there was an error on initialization if not self._is_initialized then return end -- Fetch GearVR information self._hmd_info = GearVR.hmd_info() self._left_eye_info = GearVR.eye_info(GearVR.EYE_LEFT) self._right_eye_info = GearVR.eye_info(GearVR.EYE_RIGHT) -- Create left, right and blit cameras self._left_camera_unit = World.spawn_unit(self._world, "core/units/camera") self._right_camera_unit = World.spawn_unit(self._world, "core/units/camera") self._blit_camera_unit = World.spawn_unit(self._world, "core/units/camera") self._left_camera = Unit.camera(self._left_camera_unit , "camera") self._right_camera = Unit.camera(self._right_camera_unit, "camera") self._blit_camera = Unit.camera(self._blit_camera_unit , "camera") -- Create left, right and blit viewports self._viewport_left = Application.create_viewport(self._world, "vr_left" ) self._viewport_right = Application.create_viewport(self._world, "vr_right") -- Setup performance options GearVR.set_mobile_options{ reduced_latency = true, correct_chromatic_aberration = false, --minimum_vsyncs = 2, --extra_latency_mode = GearVR.EXTRA_LATENCY_ON, cpu_level = 3, gpu_level = 3, } -- Setup GearVR GearVR.setup_hmd( left_rt, right_rt, self._left_eye_info.default_fov_left_tan, self._left_eye_info.default_fov_right_tan, self._left_eye_info.default_fov_down_tan, self._left_eye_info.default_fov_up_tan, self._right_eye_info.default_fov_left_tan, self._right_eye_info.default_fov_right_tan, self._right_eye_info.default_fov_down_tan, self._right_eye_info.default_fov_up_tan ) -- Initialize cameras Camera.set_projection_type(self._left_camera , Camera.PERSPECTIVE) Camera.set_projection_type(self._right_camera, Camera.PERSPECTIVE) Camera.set_near_range(self._left_camera , near) Camera.set_near_range(self._right_camera, near) Camera.set_far_range (self._left_camera , far ) Camera.set_far_range (self._right_camera, far ) Camera.set_frustum_half_angles( self._left_camera, self._left_eye_info.default_fov_left_tan, self._left_eye_info.default_fov_right_tan, self._left_eye_info.default_fov_down_tan, self._left_eye_info.default_fov_up_tan ) Camera.set_frustum_half_angles( self._right_camera, self._right_eye_info.default_fov_left_tan, self._right_eye_info.default_fov_right_tan, self._right_eye_info.default_fov_down_tan, self._right_eye_info.default_fov_up_tan ) GearVR.link_node_to_tracker( self._left_camera_unit, Unit.node(self._left_camera_unit, "rp_root"), GearVR.LINK_HMD, GearVR.EYE_LEFT, self._world ) GearVR.link_node_to_tracker( self._right_camera_unit, Unit.node(self._right_camera_unit, "rp_root"), GearVR.LINK_HMD, GearVR.EYE_RIGHT, self._world ) end --[[ Enable VR rendering ]]-- function GearVRSystem:enable() if not GearVR then return end if not self or not self._is_initialized then return end self._enabled = true GearVR.enable(self._enabled); Application.set_render_setting("vr_enabled", "true") end --[[ Disable VR rendering --]] function GearVRSystem:disable() if not GearVR then return end if not self or not self._is_initialized then return end self._enabled = false GearVR.enable(self._enabled); Application.set_render_setting("vr_enabled", "false") end --[[ Returns if VR rendering currently enabled ]]-- function GearVRSystem:is_enabled() if not GearVR then return end if not self or not self._is_initialized then return false end return self._enabled end --[[ Returns VR render buffer size ]]-- function GearVRSystem:vr_back_buffer_size() if not GearVR then return nil end if not self or not self._is_initialized then return nil end return Application.back_buffer_size() end --[[ Shutdown VR system --]] function GearVRSystem:shutdown() if not GearVR then return end if not self or not self._is_initialized then return end GearVRSystem.disable(self) GearVR.shutdown() World.destroy_unit(self._world, self._left_camera_unit) World.destroy_unit(self._world, self._right_camera_unit) World.destroy_unit(self._world, self._blit_camera_unit) Application.destroy_viewport(self._world, self._viewport_left) Application.destroy_viewport(self._world, self._viewport_right) self._is_initialized = false end --[[ Returns the current GearVR profile values specified in meters such as: - profile.player_height - profile.eye_height - profile.ipd - profile.eye_to_neck_x - profile.eye_to_neck_y --]] function GearVRSystem:profile() if not GearVR then return end if not self or not self._is_initialized then return nil end return GearVR.profile() end --[[ Returns the current HMD info values such as: - hmd_info.product_name - hmd_info.manufacturer - hmd_info.resolution_w - hmd_info.resolution_h - hmd_info.refresh_rate --]] function GearVRSystem:hmd_info() if not GearVR then return end if not self or not self._is_initialized then return nil end return self._hmd_info; end --[[ Recenters the GearVR pose ]]-- function GearVRSystem:recenter() if not GearVR then return end if not self or not self._is_initialized then return end GearVR.recenter() end --[[ Returns HMD forward vector and local eye poses ]]-- function GearVRSystem:hmd_local_pose() if not GearVR then return nil end if not self or not self._is_initialized then return nil end head, left, right = GearVR.hmd_local_pose() return { forward = Matrix4x4.forward(head), left_eye = left, right_eye = right } end --[[ Returns HMD forward vector and world eye poses --]] function GearVRSystem:hmd_world_pose() if not GearVR then return nil end if not self or not self._is_initialized then return nil end head, left, right = GearVR.hmd_world_pose() return { forward = Matrix4x4.forward(head), left_eye = left, right_eye = right } end --[[ Sets tracking space pose --]] function GearVRSystem:set_tracking_space_pose(pose) if not GearVR then return end if not self or not self._is_initialized then return end GearVR.set_tracking_space_pose(pose) end --[[ Render in VR mode ]]-- function GearVRSystem:render(shading_environment) if not GearVR then return end if not self or not self._enabled then return end -- Render world for left and right cameras Application.render_world(self._world, self._left_camera, self._viewport_left, shading_environment) Application.render_world(self._world, self._right_camera, self._viewport_right, shading_environment) end return GearVRSystem