diff --git a/Common/VR/PPSSPPVR.cpp b/Common/VR/PPSSPPVR.cpp index 9c6cac4640..d4ab5471cc 100644 --- a/Common/VR/PPSSPPVR.cpp +++ b/Common/VR/PPSSPPVR.cpp @@ -1,6 +1,7 @@ #include "Common/VR/PPSSPPVR.h" #include "Common/VR/VRBase.h" #include "Common/VR/VRInput.h" +#include "Common/VR/VRMath.h" #include "Common/VR/VRRenderer.h" #include "Common/VR/VRTweaks.h" @@ -31,6 +32,16 @@ struct ButtonMapping { } }; +struct MouseActivator { + bool activate; + ovrButton ovr; + + MouseActivator(bool activate, ovrButton ovr) { + this->activate = activate; + this->ovr = ovr; + } +}; + static std::vector leftControllerMapping = { ButtonMapping(NKCODE_BUTTON_X, ovrButton_X), ButtonMapping(NKCODE_BUTTON_Y, ovrButton_Y), @@ -61,6 +72,16 @@ static std::vector controllerMapping[2] = { leftControllerMapping, rightControllerMapping }; +static int mouseController = -1; +static bool mousePressed[] = {false, false}; + +static std::vector mouseActivators = { + MouseActivator(true, ovrButton_Trigger), + MouseActivator(false, ovrButton_Up), + MouseActivator(false, ovrButton_Down), + MouseActivator(false, ovrButton_Left), + MouseActivator(false, ovrButton_Right), +}; /* ================================================================================ @@ -99,7 +120,8 @@ void GetVRResolutionPerEye(int* width, int* height) { } } -void UpdateVRInput(bool(*NativeKey)(const KeyInput &key), bool haptics) { +void UpdateVRInput(bool(*NativeKey)(const KeyInput &key), bool(*NativeTouch)(const TouchInput &touch), bool haptics, float dp_xscale, float dp_yscale) { + //buttons KeyInput keyInput = {}; for (int j = 0; j < 2; j++) { int status = IN_VRGetButtonState(j); @@ -125,6 +147,53 @@ void UpdateVRInput(bool(*NativeKey)(const KeyInput &key), bool haptics) { } } } + + //enable or disable mouse + for (int j = 0; j < 2; j++) { + int status = IN_VRGetButtonState(j); + for (MouseActivator& m : mouseActivators) { + if (status & m.ovr) { + mouseController = m.activate ? j : -1; + } + } + } + + //mouse cursor + if (mouseController >= 0) { + //get position on screen + XrPosef pose = IN_VRGetPose(mouseController); + XrVector3f angles = XrQuaternionf_ToEulerAngles(pose.orientation); + float width = (float)VR_GetConfig(VR_CONFIG_VIEWPORT_WIDTH); + float height = (float)VR_GetConfig(VR_CONFIG_VIEWPORT_HEIGHT); + float cx = width / 2; + float cy = height / 2; + float speed = (cx + cy) / 2; + float x = cx - tan(ToRadians(angles.y - (float)VR_GetConfig(VR_CONFIG_MENU_YAW))) * speed; + float y = cy - tan(ToRadians(angles.x)) * speed; + + //set renderer + VR_SetConfig(VR_CONFIG_MOUSE_X, (int)x); + VR_SetConfig(VR_CONFIG_MOUSE_Y, (int)y); + VR_SetConfig(VR_CONFIG_MOUSE_SIZE, 6 * (int)pow(VR_GetConfig(VR_CONFIG_CANVAS_DISTANCE), 0.25f)); + + //inform engine about the status + TouchInput touch; + touch.id = mouseController; + touch.x = x * dp_xscale; + touch.y = (height - y - 1) * dp_yscale; + bool pressed = IN_VRGetButtonState(mouseController) & ovrButton_Trigger; + if (mousePressed[mouseController] != pressed) { + if (!pressed) { + touch.flags = TOUCH_DOWN; + NativeTouch(touch); + touch.flags = TOUCH_UP; + NativeTouch(touch); + } + mousePressed[mouseController] = pressed; + } + } else { + VR_SetConfig(VR_CONFIG_MOUSE_SIZE, 0); + } } void UpdateVRScreenKey(const KeyInput &key) { diff --git a/Common/VR/PPSSPPVR.h b/Common/VR/PPSSPPVR.h index c605980d28..4b6b6774c2 100644 --- a/Common/VR/PPSSPPVR.h +++ b/Common/VR/PPSSPPVR.h @@ -10,7 +10,7 @@ bool IsVRBuild(); void InitVROnAndroid(void* vm, void* activity, int version, char* name); void EnterVR(bool firstStart); void GetVRResolutionPerEye(int* width, int* height); -void UpdateVRInput(bool(*NativeKey)(const KeyInput &key), bool haptics); +void UpdateVRInput(bool(*NativeKey)(const KeyInput &key), bool(*NativeTouch)(const TouchInput &touch), bool haptics, float dp_xscale, float dp_yscale); void UpdateVRScreenKey(const KeyInput &key); // VR rendering integration diff --git a/Common/VR/VRInput.cpp b/Common/VR/VRInput.cpp index b25bc4b6ca..63fc97a030 100644 --- a/Common/VR/VRInput.cpp +++ b/Common/VR/VRInput.cpp @@ -506,3 +506,12 @@ uint32_t IN_VRGetButtonState( int controllerIndex ) { XrVector2f IN_VRGetJoystickState( int controllerIndex ) { return moveJoystickState[controllerIndex].currentState; } + +XrPosef IN_VRGetPose( int controllerIndex ) { + engine_t* engine = VR_GetEngine(); + XrSpaceLocation loc = {}; + loc.type = XR_TYPE_SPACE_LOCATION; + XrSpace aimSpace[] = { leftControllerAimSpace, rightControllerAimSpace }; + xrLocateSpace(aimSpace[controllerIndex], engine->appState.CurrentSpace, engine->predictedDisplayTime, &loc); + return loc.pose; +} diff --git a/Common/VR/VRInput.h b/Common/VR/VRInput.h index 241bf2791e..126cc56eaa 100644 --- a/Common/VR/VRInput.h +++ b/Common/VR/VRInput.h @@ -32,4 +32,5 @@ void IN_VRInit( engine_t *engine ); void IN_VRInputFrame( engine_t* engine ); uint32_t IN_VRGetButtonState( int controllerIndex ); XrVector2f IN_VRGetJoystickState( int controllerIndex ); +XrPosef IN_VRGetPose( int controllerIndex ); void INVR_Vibrate( int duration, int chan, float intensity ); diff --git a/Common/VR/VRRenderer.cpp b/Common/VR/VRRenderer.cpp index 343a496620..f4c4d7f805 100644 --- a/Common/VR/VRRenderer.cpp +++ b/Common/VR/VRRenderer.cpp @@ -16,9 +16,6 @@ GLboolean initialized = GL_FALSE; GLboolean stageSupported = GL_FALSE; int vrConfig[VR_CONFIG_MAX] = {}; -float menuPitch = 0; -float menuYaw = 0; -float recenterYaw = 0; XrVector3f hmdorientation; XrVector3f hmdposition; @@ -135,7 +132,8 @@ void VR_Recenter(engine_t* engine) { OXR(xrLocateSpace(engine->appState.HeadSpace, engine->appState.CurrentSpace, engine->predictedDisplayTime, &loc)); hmdorientation = XrQuaternionf_ToEulerAngles(loc.pose.orientation); - recenterYaw += ToRadians(hmdorientation.y); + vrConfig[VR_CONFIG_RECENTER_YAW] += (int)hmdorientation.y; + float recenterYaw = ToRadians((float)vrConfig[VR_CONFIG_RECENTER_YAW]); spaceCreateInfo.poseInReferenceSpace.orientation.x = 0; spaceCreateInfo.poseInReferenceSpace.orientation.y = sin(recenterYaw / 2); spaceCreateInfo.poseInReferenceSpace.orientation.z = 0; @@ -171,8 +169,8 @@ void VR_Recenter(engine_t* engine) { } // Update menu orientation - menuPitch = hmdorientation.x; - menuYaw = 0; + vrConfig[VR_CONFIG_MENU_PITCH] = (int)hmdorientation.x; + vrConfig[VR_CONFIG_MENU_YAW] = 0; } void VR_InitRenderer( engine_t* engine, bool multiview ) { @@ -182,6 +180,8 @@ void VR_InitRenderer( engine_t* engine, bool multiview ) { int eyeW, eyeH; VR_GetResolution(engine, &eyeW, &eyeH); + vrConfig[VR_CONFIG_VIEWPORT_WIDTH] = eyeW; + vrConfig[VR_CONFIG_VIEWPORT_HEIGHT] = eyeH; // Get the viewport configuration info for the chosen viewport configuration type. engine->appState.ViewportConfig.type = XR_TYPE_VIEW_CONFIGURATION_PROPERTIES; @@ -321,15 +321,26 @@ void VR_EndFrame( engine_t* engine ) { glClear(GL_COLOR_BUFFER_BIT); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + // Show mouse cursor + int vrMode = vrConfig[VR_CONFIG_MODE]; + int size = vrConfig[VR_CONFIG_MOUSE_SIZE]; + if ((vrMode == VR_MODE_FLAT_SCREEN) && (size > 0)) { + glEnable(GL_SCISSOR_TEST); + glScissor(vrConfig[VR_CONFIG_MOUSE_X], vrConfig[VR_CONFIG_MOUSE_Y], size, size); + glViewport(vrConfig[VR_CONFIG_MOUSE_X], vrConfig[VR_CONFIG_MOUSE_Y], size, size); + glClearColor(1, 1, 1, 1); + glClear(GL_COLOR_BUFFER_BIT); + glDisable(GL_SCISSOR_TEST); + } + ovrFramebuffer* frameBuffer = &engine->appState.Renderer.FrameBuffer; //ovrFramebuffer_Resolve(frameBuffer); ovrFramebuffer_Release(frameBuffer); ovrFramebuffer_SetNone(); XrCompositionLayerProjectionView projection_layer_elements[2] = {}; - int vrMode = vrConfig[VR_CONFIG_MODE]; if ((vrMode == VR_MODE_MONO_6DOF) || (vrMode == VR_MODE_STEREO_6DOF)) { - menuYaw = hmdorientation.y; + vrConfig[VR_CONFIG_MENU_YAW] = (int)hmdorientation.y; for (int eye = 0; eye < ovrMaxNumEyes; eye++) { int imageLayer = eye; @@ -379,14 +390,16 @@ void VR_EndFrame( engine_t* engine ) { cylinder_layer.subImage.imageRect.extent.width = width; cylinder_layer.subImage.imageRect.extent.height = height; cylinder_layer.subImage.imageArrayIndex = 0; - float distance = vrConfig[VR_CONFIG_CANVAS_DISTANCE]; + float distance = (float)vrConfig[VR_CONFIG_CANVAS_DISTANCE]; + float menuPitch = ToRadians((float)vrConfig[VR_CONFIG_MENU_PITCH]); + float menuYaw = ToRadians((float)vrConfig[VR_CONFIG_MENU_YAW]); XrVector3f pos = { - invViewTransform[0].position.x - sin(ToRadians(menuYaw)) * distance, + invViewTransform[0].position.x - sin(menuYaw) * distance, invViewTransform[0].position.y, - invViewTransform[0].position.z - cos(ToRadians(menuYaw)) * distance + invViewTransform[0].position.z - cos(menuYaw) * distance }; - XrQuaternionf pitch = XrQuaternionf_CreateFromVectorAngle({1, 0, 0}, -ToRadians(menuPitch)); - XrQuaternionf yaw = XrQuaternionf_CreateFromVectorAngle({0, 1, 0}, ToRadians(menuYaw)); + XrQuaternionf pitch = XrQuaternionf_CreateFromVectorAngle({1, 0, 0}, -menuPitch); + XrQuaternionf yaw = XrQuaternionf_CreateFromVectorAngle({0, 1, 0}, menuYaw); cylinder_layer.pose.orientation = XrQuaternionf_Multiply(pitch, yaw); cylinder_layer.pose.position = pos; cylinder_layer.radius = 12.0f; diff --git a/Common/VR/VRRenderer.h b/Common/VR/VRRenderer.h index 872bda7772..5527480bc3 100644 --- a/Common/VR/VRRenderer.h +++ b/Common/VR/VRRenderer.h @@ -4,19 +4,22 @@ #include "VRMath.h" enum VRConfig { - VR_CONFIG_MODE, - VR_CONFIG_6DOF_ENABLED, - VR_CONFIG_6DOF_SCALE, - VR_CONFIG_MIRROR_AXIS_X, - VR_CONFIG_MIRROR_AXIS_Y, - VR_CONFIG_MIRROR_AXIS_Z, - VR_CONFIG_MIRROR_PITCH, - VR_CONFIG_MIRROR_YAW, - VR_CONFIG_MIRROR_ROLL, - VR_CONFIG_3D_GEOMETRY_COUNT, - VR_CONFIG_FOV_SCALE, - VR_CONFIG_FORCE_2D, - VR_CONFIG_CANVAS_DISTANCE, + //switching between 2D and 3D + VR_CONFIG_MODE, VR_CONFIG_3D_GEOMETRY_COUNT, VR_CONFIG_FORCE_2D, + //camera setup + VR_CONFIG_FOV_SCALE, VR_CONFIG_CANVAS_DISTANCE, + //6DoF + VR_CONFIG_6DOF_ENABLED, VR_CONFIG_6DOF_SCALE, + VR_CONFIG_MIRROR_AXIS_X, VR_CONFIG_MIRROR_AXIS_Y, VR_CONFIG_MIRROR_AXIS_Z, + VR_CONFIG_MIRROR_PITCH, VR_CONFIG_MIRROR_YAW, VR_CONFIG_MIRROR_ROLL, + //2D canvas positioning + VR_CONFIG_MENU_PITCH, VR_CONFIG_MENU_YAW, VR_CONFIG_RECENTER_YAW, + //mouse cursor + VR_CONFIG_MOUSE_SIZE, VR_CONFIG_MOUSE_X, VR_CONFIG_MOUSE_Y, + //viewport size + VR_CONFIG_VIEWPORT_WIDTH, VR_CONFIG_VIEWPORT_HEIGHT, + + //end VR_CONFIG_MAX }; diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 6cc3ea0885..482b864ea5 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -1066,7 +1066,7 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayRender(JNIEnv *env, } if (IsVRBuild()) { - UpdateVRInput(NativeKey, g_Config.bHapticFeedback); + UpdateVRInput(NativeKey, NativeTouch, g_Config.bHapticFeedback, dp_xscale, dp_yscale); } }