X-Git-Url: http://git.eversberg.eu/gitweb.cgi?p=mercenary-reloaded.git;a=blobdiff_plain;f=src%2Flibovr%2Fovr.c;h=8a9007f3f12f9dbba2e50162786e68c1bcbb4d8e;hp=0bc8eb96701c9964f29be99180ce3b1976e8271c;hb=3c70467233fef462f9bc9a132019800386978cc8;hpb=a986f637da17d8efdb9f8814674908bf5c108d3e diff --git a/src/libovr/ovr.c b/src/libovr/ovr.c index 0bc8eb9..8a9007f 100755 --- a/src/libovr/ovr.c +++ b/src/libovr/ovr.c @@ -95,23 +95,34 @@ static ovrHmdDesc hmdDesc; static ovrSizei TextureSize[2]; static ovrTextureSwapChain textureSwapChain[2] = { NULL, NULL }; static GLuint fboId[2] = { 0, 0 }; +static GLuint mirrorFBO = 0; +static int mirror_width; +static int mirror_height; static ovrEyeRenderDesc eyeRenderDesc[2]; static ovrPosef hmdToEyeViewPose[2]; +static ovrPosef headPose; +static ovrPosef handPose; +static ovrInputState inputState; static ovrLayerEyeFov layer; +static int multisampling; static long long frameIndex = 0; static double observer_x = 0.0; -static double observer_x_normalize = 0.0; +static double observer_x_reset = 0.0; +static double hand_x_reset = 0.0; static double observer_y = 0.0; -static double observer_y_normalize = 0.0; +static double observer_y_reset = 0.0; +static double hand_y_reset = 0.0; static double observer_z = 0.0; -static double observer_z_normalize = 0.0; +static double observer_z_reset = 0.0; +static double hand_z_reset = 0.0; -int init_ovr(void) +int init_ovr(int _multisampling) { - int sample_count = 1; // FIXME: make MSAA ovrResult result; int eye; + multisampling = _multisampling; + glewExperimental = GL_TRUE; if (glewInit() != GLEW_OK) { print_error("Failed to init GLEW\n"); @@ -144,12 +155,13 @@ int init_ovr(void) layer.Header.Type = ovrLayerType_EyeFov; layer.Header.Flags = 0; + /* do we need this??? seems to work without */ + if (multisampling > 1) + glEnable(GL_MULTISAMPLE); + /* create render buffers */ for (eye = 0; eye < 2; eye++) { TextureSize[eye] = ovr_GetFovTextureSize(session, (eye == 0) ? ovrEye_Left : ovrEye_Right, hmdDesc.DefaultEyeFov[eye], 1.0); -#warning hacking resolution -//TextureSize[eye].w *= 2; -//TextureSize[eye].h *= 2; ovrTextureSwapChainDesc desc; int length, i; GLuint chainTexId; @@ -161,19 +173,19 @@ int init_ovr(void) desc.Width = TextureSize[eye].w; desc.Height = TextureSize[eye].h; desc.MipLevels = 1; - desc.SampleCount = sample_count; + desc.SampleCount = (multisampling > 1) ? multisampling : 1; desc.StaticImage = ovrFalse; result = ovr_CreateTextureSwapChainGL(session, &desc, &textureSwapChain[eye]); if (OVR_FAILURE(result)) { - print_error("ovr_CreateTextureSwapChainGL() failed!\n"); + print_error("ovr_CreateTextureSwapChainGL() failed! (error %d)\n", result); goto error; } ovr_GetTextureSwapChainLength(session, textureSwapChain[eye], &length); for (i = 0; i < length; i++) { ovr_GetTextureSwapChainBufferGL(session, textureSwapChain[eye], i, &chainTexId); - glBindTexture(GL_TEXTURE_2D, chainTexId); + glBindTexture((multisampling > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D, chainTexId); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -193,6 +205,34 @@ int init_ovr(void) layer.Viewport[eye].Size.h = TextureSize[eye].h; } + ovrMirrorTexture mirrorTexture = NULL; + ovrMirrorTextureDesc desc; + memset(&desc, 0, sizeof(desc)); + desc.Width = mirror_width = TextureSize[0].w; + desc.Height = mirror_height = TextureSize[0].h; + desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; + desc.MirrorOptions = +// ovrMirrorOption_PostDistortion | + ovrMirrorOption_LeftEyeOnly | + ovrMirrorOption_IncludeGuardian | + ovrMirrorOption_IncludeNotifications | + ovrMirrorOption_IncludeSystemGui; + + /* Create mirror texture and an FBO used to copy mirror texture to back buffer */ + result = ovr_CreateMirrorTextureWithOptionsGL(session, &desc, &mirrorTexture); + if (!OVR_SUCCESS(result)) { + print_error("ovr_CreateMirrorTextureWithOptionsGL() failed! (error %d)\n", result); + goto error; + } + + /* Configure the mirror read buffer */ + GLuint texId; + ovr_GetMirrorTextureBufferGL(session, mirrorTexture, &texId); + + glGenFramebuffers(1, &mirrorFBO); + glBindFramebuffer(GL_READ_FRAMEBUFFER, mirrorFBO); + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texId, 0); + glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); return 0; @@ -201,14 +241,91 @@ error: return -EINVAL; } -void begin_render_ovr(void) +void get_poses_ovr(int *button_a, int *button_b, int *button_x, int *button_y, int *button_menu, int *button_left_trigger, int *button_right_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; + double x, y, z; + unsigned int hand_mask = (ovrStatus_OrientationTracked | ovrStatus_PositionTracked); + unsigned int hand_flags = (ovrStatus_OrientationTracked | ovrStatus_PositionTracked); /* Get both eye poses simultaneously, with IPD offset already included. */ - double displayMidpointSeconds = ovr_GetPredictedDisplayTime(session, 0); + 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 head/hand or controller representation */ + headPose = hmdState.HeadPose.ThePose; + handPose = headPose; +// if ((hmdState.HandStatusFlags[ovrHand_Left] & hand_mask) == hand_flags) +// handPose = hmdState.HandPoses[ovrHand_Left].ThePose; + if ((hmdState.HandStatusFlags[ovrHand_Right] & hand_mask) == hand_flags) + handPose = hmdState.HandPoses[ovrHand_Right].ThePose; + x = handPose.Position.x; + y = handPose.Position.y; + z = handPose.Position.z; + x += hand_x_reset; + y += hand_y_reset; + z += hand_z_reset; + *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(handPose.Orientation, &yaw, &pitch, &roll); + *hand_right_yaw = yaw; + *hand_right_pitch = pitch; + *hand_right_roll = roll; + + result = ovr_GetInputState(session, ovrControllerType_Active, &inputState); + if (OVR_SUCCESS(result)) { + if (inputState.Buttons & ovrButton_A) + *button_a = 1; + else + *button_a = 0; + if (inputState.Buttons & ovrButton_B) + *button_b = 1; + else + *button_b = 0; + if (inputState.Buttons & ovrButton_X) + *button_x = 1; + else + *button_x = 0; + if (inputState.Buttons & ovrButton_Y) + *button_y = 1; + else + *button_y = 0; + if (inputState.Buttons & ovrButton_Enter) + *button_menu = 1; + else + *button_menu = 0; + if (inputState.Buttons & ovrButton_LThumb) + *button_left_thumb = 1; + else + *button_left_thumb = 0; + if (inputState.Buttons & ovrButton_RThumb) + *button_right_thumb = 1; + else + *button_right_thumb = 0; + if (inputState.IndexTrigger[ovrHand_Left] >= 0.8) + *button_left_trigger = 1; + else + *button_left_trigger = 0; + if (inputState.IndexTrigger[ovrHand_Right] >= 0.8) + *button_right_trigger = 1; + else + *button_right_trigger = 0; + *stick_left_x = inputState.ThumbstickNoDeadzone[ovrHand_Left].x; + *stick_left_y = inputState.ThumbstickNoDeadzone[ovrHand_Left].y; + *stick_right_x = inputState.ThumbstickNoDeadzone[ovrHand_Right].x; + *stick_right_y = inputState.ThumbstickNoDeadzone[ovrHand_Right].y; + } +} + +void begin_render_ovr(void) +{ + ovrResult result; result = ovr_WaitToBeginFrame(session, frameIndex); if (!OVR_SUCCESS(result)) @@ -218,7 +335,9 @@ void begin_render_ovr(void) print_info("Failed to begin frame (error %d)\n", result); } -void begin_render_ovr_eye(int eye) +static int initial_observer_reset = 1; + +void begin_render_ovr_eye(int eye, double *camera_x, double *camera_y, double *camera_z) { int curIndex; GLuint chainTexId; @@ -229,7 +348,7 @@ void begin_render_ovr_eye(int eye) ovr_GetTextureSwapChainCurrentIndex(session, textureSwapChain[eye], &curIndex); ovr_GetTextureSwapChainBufferGL(session, textureSwapChain[eye], curIndex, &chainTexId); glBindFramebuffer(GL_FRAMEBUFFER, fboId[eye]); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, chainTexId, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, (multisampling > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D, chainTexId, 0); glViewport(0, 0, TextureSize[eye].w, TextureSize[eye].h); glMatrixMode(GL_PROJECTION); @@ -246,19 +365,26 @@ void begin_render_ovr_eye(int eye) y = layer.RenderPose[eye].Position.y; z = layer.RenderPose[eye].Position.z; - /* normalize height to game's observer, if requrested by user */ + /* reset to game's observer, if requrested by user */ observer_x = x; - x += observer_x_normalize; observer_y = y; - y += observer_y_normalize; observer_z = z; - z += observer_z_normalize; + if (initial_observer_reset) { + initial_observer_reset = 0; + reset_observer_ovr(); + } + x += observer_x_reset; + y += observer_y_reset; + z += observer_z_reset; glRotatef(-roll / M_PI * 180.0,0,0,1); glRotatef(-pitch / M_PI * 180.0,1,0,0); glRotatef(-yaw / M_PI * 180.0,0,1,0); - glTranslated(-x / 0.0254, -y / 0.0254, -z / 0.0254); /* convert to inch */ + *camera_x = x / 0.0254; + *camera_y = y / 0.0254; + *camera_z = z / 0.0254; + glTranslated(-(*camera_x), -(*camera_y), -(*camera_z)); /* convert to inch */ glMatrixMode(GL_MODELVIEW); @@ -271,8 +397,8 @@ void end_render_ovr_eye(int eye) { // unset render surface glBindFramebuffer(GL_FRAMEBUFFER, fboId[eye]); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, (multisampling > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D, 0, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, (multisampling > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D, 0, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0); // Commit the changes to the texture swap chain @@ -293,67 +419,61 @@ void end_render_ovr(void) void render_mirror_ovr(int view_width, int view_height) { int view_x = 0, view_y = 0; - int new_width, new_height; - int eye = 0; /* left eye */ - int curIndex; - GLuint chainTexId; + int new_height; //, new_width; /* avoid division by zero, if one dimension is too small */ if (view_width < 1 || view_height < 1) return; /* calculate a viewport that has apect of TextureSize */ - if (view_height * TextureSize[eye].w > view_width * TextureSize[eye].h) { - new_height = view_width * TextureSize[eye].h / TextureSize[eye].w; +// if (view_height * mirror_width > view_width * mirror_height) { + new_height = view_width * mirror_height / mirror_width; view_y = view_y + view_height / 2 - new_height / 2; view_height = new_height; - } else if (view_height * TextureSize[eye].w < view_width * TextureSize[eye].h) { - new_width = view_height * TextureSize[eye].w / TextureSize[eye].h; - view_x = view_x + view_width / 2 - new_width / 2; - view_width = new_width; - } +// } else if (view_height * mirror_width < view_width * mirror_height) { +// new_width = view_height * mirror_width / mirror_height; +// view_x = view_x + view_width / 2 - new_width / 2; +// view_width = new_width; +// } /* avoid views that are too small */ if (view_width < 1 || view_height < 1) return; - /* clear screen */ + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); - /* orthogonal viewport */ - glViewport((GLsizei)view_x, (GLsizei)view_y, (GLsizei)view_width, (GLsizei)view_height); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); - glMatrixMode(GL_MODELVIEW); - - /* get texture from OVR */ - ovr_GetTextureSwapChainCurrentIndex(session, textureSwapChain[eye], &curIndex); - ovr_GetTextureSwapChainBufferGL(session, textureSwapChain[eye], curIndex, &chainTexId); + /* Blit mirror texture to back buffer */ + glBindFramebuffer(GL_READ_FRAMEBUFFER, mirrorFBO); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glBlitFramebuffer(0, mirror_height, mirror_width, 0, + view_x, view_y, view_x + view_width, view_y + view_height, + GL_COLOR_BUFFER_BIT, GL_LINEAR); + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); +} - /* render mirror from texture */ - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, chainTexId); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); /* no modulation with color */ - glBegin(GL_QUADS); - glTexCoord2f(0, 1); - glVertex3f(-1.0, -1.0, 0.0); - glTexCoord2f(1, 1); - glVertex3f(1.0, -1.0, 0.0); - glTexCoord2f(1, 0); - glVertex3f(1.0, 1.0, 0.0); - glTexCoord2f(0, 0); - glVertex3f(-1.0, 1.0, 0.0); - glEnd(); - glDisable(GL_TEXTURE_2D); +void reset_observer_ovr(void) +{ + observer_x_reset = -observer_x; + observer_y_reset = -observer_y; + observer_z_reset = -observer_z; + hand_x_reset = -observer_x; + hand_y_reset = -observer_y; + hand_z_reset = -observer_z; } -void normalize_observer_ovr(void) +int should_quit_ovr(void) { - observer_x_normalize = -observer_x; - observer_y_normalize = -observer_y; - observer_z_normalize = -observer_z; + ovrSessionStatus sessionStatus; + ovrResult result; + + result = ovr_GetSessionStatus(session, &sessionStatus); + + if (OVR_SUCCESS(result)) + return sessionStatus.ShouldQuit; + return 0; } void exit_ovr(void) @@ -371,6 +491,10 @@ void exit_ovr(void) fboId[eye] = 0; } } + if (mirrorFBO) { + glDeleteFramebuffers(1, &mirrorFBO); + mirrorFBO = 0; + } if (session) { ovr_Destroy(session);