OVR: Move player with controller to the direction it points to
authorAndreas Eversberg <jolly@eversberg.eu>
Thu, 26 Apr 2018 17:22:51 +0000 (19:22 +0200)
committerAndreas Eversberg <jolly@eversberg.eu>
Fri, 27 Apr 2018 19:21:16 +0000 (21:21 +0200)
src/libovr/ovr.c
src/libovr/ovr.h
src/mercenary/main.c
src/mercenary/mercenary.h
src/mercenary/mercenary2.c
src/mercenary/mercenary3.c

index 9083471..204f10b 100755 (executable)
@@ -100,6 +100,7 @@ static int mirror_width;
 static int mirror_height;
 static ovrEyeRenderDesc eyeRenderDesc[2];
 static ovrPosef hmdToEyeViewPose[2];
+static ovrPosef headPose;
 static ovrPosef handPoses[2];
 static ovrInputState inputState;
 static ovrLayerEyeFov layer;
@@ -239,7 +240,7 @@ error:
        return -EINVAL;
 }
 
-void get_poses_ovr(int *button_a, int *button_b, int *button_x, int *button_y, int *button_menu, int *button_trigger, int *button_left_thumb, int *button_right_thumb, double *hand_right_x, double *hand_right_y, double *hand_right_z, double *hand_right_yaw, double *hand_right_pitch, double *hand_right_roll, double *stick_left_x, double *stick_left_y, double *stick_right_x, double *stick_right_y)
+void get_poses_ovr(int *button_a, int *button_b, int *button_x, int *button_y, int *button_menu, int *button_trigger, int *button_left_thumb, int *button_right_thumb, double *hand_right_x, double *hand_right_y, double *hand_right_z, double *hand_right_yaw, double *hand_right_pitch, double *hand_right_roll, double *stick_left_x, double *stick_left_y, double *stick_right_x, double *stick_right_y, double *head_yaw, double *head_pitch, double *head_roll)
 {      
        ovrResult result;
        float yaw, pitch, roll;
@@ -249,7 +250,8 @@ void get_poses_ovr(int *button_a, int *button_b, int *button_x, int *button_y, i
        double displayMidpointSeconds = ovr_GetPredictedDisplayTime(session, frameIndex);
        ovrTrackingState hmdState = ovr_GetTrackingState(session, displayMidpointSeconds, ovrTrue);
        ovr_CalcEyePoses(hmdState.HeadPose.ThePose, hmdToEyeViewPose, layer.RenderPose);
-       /* Grab hand poses useful for rendering hand or controller representation */
+       /* Grab hand poses useful for rendering head/hand or controller representation */
+       headPose = hmdState.HeadPose.ThePose;
        handPoses[ovrHand_Left]  = hmdState.HandPoses[ovrHand_Left].ThePose;
        handPoses[ovrHand_Right] = hmdState.HandPoses[ovrHand_Right].ThePose;
        x = handPoses[ovrHand_Right].Position.x;
@@ -261,6 +263,10 @@ void get_poses_ovr(int *button_a, int *button_b, int *button_x, int *button_y, i
        *hand_right_x = x / 0.0254;
        *hand_right_y = y / 0.0254;
        *hand_right_z = z / 0.0254;
+       ovrOrientation2yawpitchroll(headPose.Orientation, &yaw, &pitch, &roll);
+       *head_yaw = yaw;
+       *head_pitch = pitch;
+       *head_roll = roll;
        ovrOrientation2yawpitchroll(handPoses[ovrHand_Right].Orientation, &yaw, &pitch, &roll);
        *hand_right_yaw = yaw;
        *hand_right_pitch = pitch;
index 9cd9aa5..18e8c8f 100755 (executable)
@@ -1,7 +1,7 @@
 
 int init_ovr(int multisampling);
 void exit_ovr(void);
-void get_poses_ovr(int *button_a, int *button_b, int *button_x, int *button_y, int *button_menu, int *button_trigger, int *button_left_thumb, int *button_right_thumb, double *hand_right_x, double *hand_right_y, double *hand_right_z, double *hand_right_yaw, double *hand_right_pitch, double *hand_right_roll, double *stick_left_x, double *stick_left_y, double *stick_right_x, double *stick_right_y);
+void get_poses_ovr(int *button_a, int *button_b, int *button_x, int *button_y, int *button_menu, int *button_trigger, int *button_left_thumb, int *button_right_thumb, double *hand_right_x, double *hand_right_y, double *hand_right_z, double *hand_right_yaw, double *hand_right_pitch, double *hand_right_roll, double *stick_left_x, double *stick_left_y, double *stick_right_x, double *stick_right_y, double *head_yaw, double *head_pitch, double *head_roll);
 void begin_render_ovr(void);
 void begin_render_ovr_eye(int eye, double *camera_x, double *camera_y, double *camera_z);
 void end_render_ovr_eye(int eye);
index bd0fca6..2f7d314 100644 (file)
@@ -21,6 +21,7 @@
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
+#include <math.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include "../../include/keycodes.h"
 #define FOV_JOLLY      80.0
 #define FOV_MAX                170.0
 
+#define STICK_WALK_THRESHOLD 0.2 /* move the stick until the player moves */
+#define STICK_ROTATE_THRESHOLD 0.2 /* move the stick until the player rotates */
+#define STICK_THRUST_THRESHOLD 0.2 /* move the stick until the craft moves */
+
 static int config_ctrl_c = 0;
 static int config_amiga_speed = 0; /* fast speed */
 static double config_fps = 16.0;
@@ -311,10 +316,11 @@ static void handle_vr_poses(void)
        int button_a = 0, button_b = 0, button_x = 0, button_y = 0, button_menu = 0, button_trigger = 0, button_left_thumb = 0, button_right_thumb = 0;
        double hand_right_x = 0.0, hand_right_y = 0.0, hand_right_z = 0.0;
        double hand_right_yaw = 0.0, hand_right_pitch = 0.0, hand_right_roll = 0.0;
+       double head_yaw = 0.0, head_pitch = 0.0, head_roll = 0.0;
        double stick_left_x = 0.0, stick_left_y = 0.0, stick_right_x = 0.0, stick_right_y = 0.0;
        int thrust = KEYCODE_SPACE;
 
-       get_poses_ovr(&button_a, &button_b, &button_x, &button_y, &button_menu, &button_trigger, &button_left_thumb, &button_right_thumb, &hand_right_x, &hand_right_y, &hand_right_z, &hand_right_yaw, &hand_right_pitch, &hand_right_roll, &stick_left_x, &stick_left_y, &stick_right_x, &stick_right_y);
+       get_poses_ovr(&button_a, &button_b, &button_x, &button_y, &button_menu, &button_trigger, &button_left_thumb, &button_right_thumb, &hand_right_x, &hand_right_y, &hand_right_z, &hand_right_yaw, &hand_right_pitch, &hand_right_roll, &stick_left_x, &stick_left_y, &stick_right_x, &stick_right_y, &head_yaw, &head_pitch, &head_roll);
        if (button_menu && !button_menu_last) {
                /* menu toggle */
                if (help_view == help_views)
@@ -364,11 +370,6 @@ static void handle_vr_poses(void)
                        set_amiga_key(KEYCODE_SPACE, 1);
                        set_amiga_key(KEYCODE_SPACE, 0);
                }
-               if (button_right_thumb && !button_right_thumb_last) {
-                       /* 'running' pressed */
-                       set_amiga_key(KEYCODE_r, 1);
-                       set_amiga_key(KEYCODE_r, 0);
-               }
                if (button_trigger && !button_trigger_last) {
                        /* trigger pressed */
                        if (!keyboard_on) {
@@ -387,28 +388,28 @@ static void handle_vr_poses(void)
                        }
                }
                /* joystick */
-               if (stick_right_x > 0.5)
+               if (stick_right_x > STICK_ROTATE_THRESHOLD)
                        set_joystick(0, 1, -1, -1, -1);
                else
-               if (stick_right_x < -0.5)
+               if (stick_right_x < -STICK_ROTATE_THRESHOLD)
                        set_joystick(1, 0, -1, -1, -1);
                else
-               if (stick_right_x_last > 0.5 || stick_right_x_last < -0.5)
+               if (stick_right_x_last > STICK_ROTATE_THRESHOLD || stick_right_x_last < -STICK_ROTATE_THRESHOLD)
                        set_joystick(0, 0, -1, -1, -1);
-               if (stick_right_y > 0.5)
+               if (stick_right_y > STICK_WALK_THRESHOLD)
                        set_joystick(-1, -1, 1, 0, -1);
                else
-               if (stick_right_y < -0.5)
+               if (stick_right_y < -STICK_WALK_THRESHOLD)
                        set_joystick(-1, -1, 0, 1, -1);
                else
-               if (stick_right_y_last > 0.5 || stick_right_y_last < -0.5)
+               if (stick_right_y_last > STICK_WALK_THRESHOLD || stick_right_y_last < -STICK_WALK_THRESHOLD)
                        set_joystick(-1, -1, 0, 0, -1);
                /* thrust */
-               if (stick_left_y > 0.3)
-                       thrust = (stick_left_y - 0.3) / 0.6 * 11.0;
+               if (stick_left_y > STICK_THRUST_THRESHOLD)
+                       thrust = (stick_left_y - STICK_THRUST_THRESHOLD) / (1.0 - STICK_THRUST_THRESHOLD) * 10.5;
                else
-               if (stick_left_y < -0.3)
-                       thrust = (stick_left_y + 0.3) / 0.6 * 11.0;
+               if (stick_left_y < -STICK_THRUST_THRESHOLD)
+                       thrust = (stick_left_y - -STICK_THRUST_THRESHOLD) / (1.0 - -STICK_THRUST_THRESHOLD) * 10.5;
                else
                        thrust = 0;
                if (thrust >= 10)
@@ -448,6 +449,42 @@ static void handle_vr_poses(void)
        vr_key = 0;
        if (keyboard_on)
                handle_vr_keyboard(keyboard_on - 1, hand_right_x, hand_right_y, hand_right_z, hand_right_yaw, hand_right_pitch, &vr_key);
+
+       if (stick_right_y > STICK_WALK_THRESHOLD || stick_right_y < -STICK_WALK_THRESHOLD) {
+               double roll, pitch, yaw;
+               double dist, east, north;
+               int32_t move_east[4], move_north[4];
+
+               mercenary_get_orientation(&roll, &pitch, &yaw);
+               /* we use a maximum move of 40 for all 4 steps (this is 10 for each step - equal to 'running') */
+               if (stick_right_y > 0.0)
+                       dist = (stick_right_y - STICK_WALK_THRESHOLD) / (1.0 - STICK_WALK_THRESHOLD) * 40.0;
+               else
+                       dist = (stick_right_y + STICK_WALK_THRESHOLD) / (1.0 - STICK_WALK_THRESHOLD) * 40.0;
+               east = sin(hand_right_yaw + yaw + M_PI) * dist;
+               north = -cos(hand_right_yaw + yaw + M_PI) * dist;
+               /* calculatate the integer positions of 4 steps */
+               move_east[0] = (int32_t)((east * 0.25) + 0.5);
+               move_north[0] = (int32_t)((north * 0.25) + 0.5);
+               move_east[1] = (int32_t)((east * 0.5) + 0.5);
+               move_north[1] = (int32_t)((north * 0.5) + 0.5);
+               move_east[2] = (int32_t)((east * 0.75) + 0.5);
+               move_north[2] = (int32_t)((north * 0.75) + 0.5);
+               move_east[3] = (int32_t)(east + 0.5);
+               move_north[3] = (int32_t)(north + 0.5);
+               /* calculate the delta between each of the 4 step */
+               move_east[3] -= move_east[2];
+               move_north[3] -= move_north[2];
+               move_east[2] -= move_east[1];
+               move_north[2] -= move_north[1];
+               move_east[1] -= move_east[0];
+               move_north[1] -= move_north[0];
+               /* the game takes 4 steps to move the player */
+               mercenary_vr_move(1, move_east, move_north);
+       } else {
+               /* don't change what the game actually does when moving joystick in y-direction */
+               mercenary_vr_move(0, NULL, NULL);
+       }
 }
 #endif
 
@@ -485,6 +522,14 @@ static void skip_intro(void)
 
 static void special_event(int event)
 {
+#ifdef HAVE_OVR
+       /* handle VR events */
+       if (event == STOP_AT_PATCH_VR) {
+               mercenary_patch_vr();
+               return;
+       }
+#endif
+       /* handle events to improve rendering */
        if (render_improved)
                render_capture_event(event);
 }
@@ -508,6 +553,10 @@ static void main_loop(void)
 
        /* render result on window */
        while (!quit) {
+#ifdef HAVE_OVR
+               /* get vr poses */
+               handle_vr_poses();
+#endif
                /* if we are in interstellar fligt, we use 50 Hz */
                /* if we are approaching to Eris Space Port, we use 10 Hz */
                /* else we use whatever frame rate the user wants */
@@ -571,8 +620,6 @@ static void main_loop(void)
 
                /* STEP 2: transfer legacy image (or just benson) in memory to OpenGL texture */
 #ifdef HAVE_OVR
-               handle_vr_poses();
-
                begin_render_ovr();
 
                for (eye = 0; eye < 2; eye++) {
@@ -1210,7 +1257,6 @@ int main(int argc, char *argv[])
                "\n"
                "Walking / Driving / Flying using Controller:\n"
                "        Use thumb stick on right controller, to move player / craft.\n"
-               "        Press thumb stick on tright controller to toggle running/walking speed.\n"
                "        Press `X' button to board, `Y' button to leave.\n"
                "        Move thumb stick on left controller to drive/fly forward or backward.\n"
                "        Press and hold thumb stick on left controller for escape sequence.\n"
index c8bd3d3..bcabc3f 100644 (file)
@@ -3,6 +3,7 @@
 enum {
        STOP_AT_END = 0,
        STOP_AT_PATCH_RENDER,
+       STOP_AT_PATCH_VR,
        STOP_AT_WAIT_VBL,
        STOP_AT_WAIT_INPUT,
        STOP_AT_CLEAR_SCREEN1,
@@ -64,10 +65,18 @@ enum {
        STOP_AT_EXPLOSION,
 };
 
+struct vr_move {
+       int override;
+       int index;
+       int32_t east[4];
+       int32_t north[4];
+};
+
 extern const struct cpu_stop mercenary_stop_at[];
 void mercenary_load(void);
 void mercenary_patch(void);
 void mercenary_patch_render(void);
+void mercenary_patch_vr(void);
 uint32_t mercenary_palette_view(void);
 uint32_t mercenary_palette_render(void);
 uint32_t mercenary_palette_predefined(void);
@@ -85,6 +94,7 @@ uint16_t mercenary_poly_tags_color(void);
 int mercenary_background_index(void);
 uint32_t mercenary_planet_scale_index(void);
 uint32_t mercenary_star_table(void);
+void mercenary_vr_move(int override, int32_t *east, int32_t *north);
 extern const char *mercenary_name;
 extern const char *mercenary_gamesavesuffix;
 
index 55449d2..74d9c29 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <stdio.h>
+#include <string.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <math.h>
@@ -30,6 +31,9 @@
 #define        INITIAL_STACK   0x7fffa
 #define RESET_VECTOR   0x59484
 
+/* VR heading to alter direction we walk to */
+static struct vr_move vr_move;
+
 /* interrupt CPU execution at special break points and tell emulation what to do */
 const struct cpu_stop mercenary_stop_at[] = {
        { 0x59a4e,      STOP_AT_WAIT_VBL },                     /* done with rendering, waiting for VBL */
@@ -108,6 +112,7 @@ const struct cpu_stop mercenary_stop_at[] = {
        { 0x528C4,      STOP_AT_PATCH_RENDER },                 /* patch away planet check (behind observer) */
        { 0x45806,      STOP_AT_PATCH_RENDER },                 /* patch away planet rendering (would crash without check above) */
        { 0x53276,      STOP_AT_PATCH_RENDER },                 /* patch away beacon check (not visible on screen) */
+       { 0x58EA8,      STOP_AT_PATCH_VR },                     /* step that moves player */
        { 0x0,          STOP_AT_END },                          /* end */
 };
 
@@ -118,6 +123,8 @@ void mercenary_load(void)
 {
        int i;
 
+       memset(&vr_move, 0, sizeof(vr_move));
+
        /* load game binary from constant to volatile memory */
        for (i = 0; i < mercenary2_hex_size; i += 4) {
                m68k_write_memory_32(i, mercenary2_hex[i / 4]);
@@ -183,6 +190,20 @@ void mercenary_patch_render(void)
        }
 }
 
+/* patch execution for VR improvement */
+void mercenary_patch_vr(void)
+{
+       switch (REG_PC) {
+       case 0x58EA8: /* at this point we process one step of the player walking on the ground */
+               if (vr_move.override && vr_move.index < 4) {
+                       REG_D[2] = vr_move.east[vr_move.index];
+                       REG_D[3] = vr_move.north[vr_move.index];
+                       vr_move.index++;
+               }
+               break;
+       }
+}
+
 uint32_t mercenary_palette_view(void)
 {
        return m68k_read_memory_32(0x007c14);
@@ -303,6 +324,15 @@ uint32_t mercenary_star_table(void)
        return 0x005D8C0;
 }
 
+void mercenary_vr_move(int override, int32_t *east, int32_t *north)
+{
+       vr_move.override = override;
+       if (east)
+               memcpy(vr_move.east, east, sizeof(vr_move.east));
+       if (north)
+               memcpy(vr_move.north, north, sizeof(vr_move.north));
+       vr_move.index = 0;
+}
 const char *mercenary_name = "Mercenary II - Damocles";
 const char *mercenary_gamesavesuffix = ".m2save";
 
index 0a5a76d..9afd60b 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <stdio.h>
+#include <string.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <math.h>
@@ -36,6 +37,9 @@
 #define RESET_VECTOR   0x5a16c
 // #define RESET_VECTOR        0x5a1a4 /* strange reset vector that causes the player to fly around */
 
+/* VR heading to alter direction we walk to */
+static struct vr_move vr_move;
+
 /* interrupt CPU execution at special break points and tell emulation what to do */
 const struct cpu_stop mercenary_stop_at[] = {
        { 0x5a826,      STOP_AT_WAIT_VBL },                     /* done with rendering, waiting for VBL */
@@ -114,6 +118,7 @@ const struct cpu_stop mercenary_stop_at[] = {
        { 0x537B0,      STOP_AT_PATCH_RENDER },                 /* patch away planet check (behind observer) */
        { 0x45806,      STOP_AT_PATCH_RENDER },                 /* patch away planet rendering (would crash without check above) */
        { 0x5406E,      STOP_AT_PATCH_RENDER },                 /* patch away beacon check (not visible on screen) */
+       { 0x59A00,      STOP_AT_PATCH_VR },                     /* step that moves player */
        { 0x0,          STOP_AT_END },                          /* end */
 };
 
@@ -124,6 +129,8 @@ void mercenary_load(void)
 {
        int i;
 
+       memset(&vr_move, 0, sizeof(vr_move));
+
        /* load game binary from constant to volatile memory */
        for (i = 0; i < mercenary3_hex_size; i += 4) {
                m68k_write_memory_32(i, mercenary3_hex[i / 4]);
@@ -219,6 +226,20 @@ void mercenary_patch_render(void)
        }
 }
 
+/* patch execution for VR improvement */
+void mercenary_patch_vr(void)
+{
+       switch (REG_PC) {
+       case 0x59A00: /* at this point we process one step of the player walking on the ground */
+               if (vr_move.override && vr_move.index < 4) {
+                       REG_D[2] = vr_move.east[vr_move.index];
+                       REG_D[3] = vr_move.north[vr_move.index];
+                       vr_move.index++;
+               }
+               break;
+       }
+}
+
 uint32_t mercenary_palette_view(void)
 {
        return m68k_read_memory_32(0x0072b0);
@@ -342,6 +363,16 @@ uint32_t mercenary_star_table(void)
        return DS_84+0x6A;
 }
 
+void mercenary_vr_move(int override, int32_t *east, int32_t *north)
+{
+       vr_move.override = override;
+       if (east)
+               memcpy(vr_move.east, east, sizeof(vr_move.east));
+       if (north)
+               memcpy(vr_move.north, north, sizeof(vr_move.north));
+       vr_move.index = 0;
+}
+
 const char *mercenary_name = "Mercenary III - The Dion Crisis";
 const char *mercenary_gamesavesuffix = ".m3save";