From c4c2ffbb7ae1f19aee820b85eb4586bf05a0369a Mon Sep 17 00:00:00 2001 From: Simon Date: Sun, 15 Mar 2020 08:36:32 +0000 Subject: [PATCH] Weapons working Thanks to Fishbiter for the OpenVR port which showed me how to do it! --- .../Android/jni/QzDoom/QzDoom_SurfaceView.c | 9 +- Projects/Android/jni/QzDoom/VrCommon.h | 2 +- Projects/Android/jni/QzDoom/VrInputDefault.c | 33 ++--- .../jni/gzdoom-g3.3mgw_mobile/src/actor.h | 3 +- .../src/gl/stereo3d/gl_oculusquest.cpp | 123 ++++++++++-------- .../jni/gzdoom-g3.3mgw_mobile/src/p_map.cpp | 4 +- .../jni/gzdoom-g3.3mgw_mobile/src/p_mobj.cpp | 2 +- 7 files changed, 99 insertions(+), 77 deletions(-) diff --git a/Projects/Android/jni/QzDoom/QzDoom_SurfaceView.c b/Projects/Android/jni/QzDoom/QzDoom_SurfaceView.c index a7d4de2..c78db3c 100644 --- a/Projects/Android/jni/QzDoom/QzDoom_SurfaceView.c +++ b/Projects/Android/jni/QzDoom/QzDoom_SurfaceView.c @@ -766,13 +766,13 @@ void GetAnglesFromVectors(const ovrVector3f forward, const ovrVector3f right, co NormalizeAngles(angles); } -void QuatToYawPitchRoll(ovrQuatf q, float pitchAdjust, vec3_t out) { +void QuatToYawPitchRoll(ovrQuatf q, vec3_t rotation, vec3_t out) { ovrMatrix4f mat = ovrMatrix4f_CreateFromQuaternion( &q ); - if (pitchAdjust != 0.0f) + if (rotation[0] != 0.0f || rotation[1] != 0.0f || rotation[2] != 0.0f) { - ovrMatrix4f rot = ovrMatrix4f_CreateRotation(radians(pitchAdjust), 0.0f, 0.0f); + ovrMatrix4f rot = ovrMatrix4f_CreateRotation(radians(rotation[0]), radians(rotation[1]), radians(rotation[2])); mat = ovrMatrix4f_Multiply(&mat, &rot); } @@ -1528,7 +1528,8 @@ void getHMDOrientation(ovrTracking2 *tracking) {//Get orientation // to allow "additional" yaw manipulation with mouse/controller. const ovrQuatf quatHmd = (*tracking).HeadPose.Pose.Orientation; const ovrVector3f positionHmd = (*tracking).HeadPose.Pose.Position; - QuatToYawPitchRoll(quatHmd, 0.0f, hmdorientation); + vec3_t rotation = {0}; + QuatToYawPitchRoll(quatHmd, rotation, hmdorientation); setHMDPosition(positionHmd.x, positionHmd.y, positionHmd.z, hmdorientation[YAW]); //TODO: fix - set to use HMD position for world position diff --git a/Projects/Android/jni/QzDoom/VrCommon.h b/Projects/Android/jni/QzDoom/VrCommon.h index 8e86962..ad349ea 100644 --- a/Projects/Android/jni/QzDoom/VrCommon.h +++ b/Projects/Android/jni/QzDoom/VrCommon.h @@ -68,7 +68,7 @@ float length(float x, float y); float nonLinearFilter(float in); bool between(float min, float val, float max); void rotateAboutOrigin(float v1, float v2, float rotation, vec2_t out); -void QuatToYawPitchRoll(ovrQuatf q, float pitchAdjust, vec3_t out); +void QuatToYawPitchRoll(ovrQuatf q, vec3_t rotation, vec3_t out); bool useScreenLayer(); void handleTrackedControllerButton(ovrInputStateTrackedRemote * trackedRemoteState, ovrInputStateTrackedRemote * prevTrackedRemoteState, uint32_t button, int key); void VR_GetScreenRes(uint32_t *width, uint32_t *height); diff --git a/Projects/Android/jni/QzDoom/VrInputDefault.c b/Projects/Android/jni/QzDoom/VrInputDefault.c index 52392f1..cbb5058 100644 --- a/Projects/Android/jni/QzDoom/VrInputDefault.c +++ b/Projects/Android/jni/QzDoom/VrInputDefault.c @@ -45,8 +45,8 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew, disable_clock_gettime = !disable_clock_gettime; } - //Menu button - handleTrackedControllerButton(&leftTrackedRemoteState_new, &leftTrackedRemoteState_old, ovrButton_Enter, KEY_ESCAPE); + //Menu button - invoke menu + handleTrackedControllerButton(&leftTrackedRemoteState_new, &leftTrackedRemoteState_old, ovrButton_Enter, KEY_ESCAPE); if (getGameState() != 0 || isMenuActive()) //gamestate != GS_LEVEL { @@ -61,6 +61,7 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew, handleTrackedControllerButton(pDominantTrackedRemoteNew, pDominantTrackedRemoteOld, domButton1, KEY_PAD_A); handleTrackedControllerButton(pDominantTrackedRemoteNew, pDominantTrackedRemoteOld, ovrButton_Trigger, KEY_PAD_A); handleTrackedControllerButton(pDominantTrackedRemoteNew, pDominantTrackedRemoteOld, domButton2, KEY_PAD_B); + handleTrackedControllerButton(&leftTrackedRemoteState_new, &leftTrackedRemoteState_old, ovrButton_Enter, KEY_PAD_B); } else { @@ -94,16 +95,17 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew, { vec2_t v; - rotateAboutOrigin(-weaponoffset[0], weaponoffset[2], VR_GetRawYaw(), v); - weaponoffset[0] = v[0]; - weaponoffset[2] = v[1]; + rotateAboutOrigin(weaponoffset[0], weaponoffset[2], -(doomYaw - hmdorientation[YAW]), v); + weaponoffset[0] = v[1]; + weaponoffset[2] = v[0]; } - //Set gun angles - We need to calculate all those we might need (including adjustments) for the client to then take its pick + //Set gun angles const ovrQuatf quatRemote = pDominantTracking->HeadPose.Pose.Orientation; - QuatToYawPitchRoll(quatRemote, vr_weapon_pitchadjust, weaponangles); - weaponangles[YAW] -= VR_GetRawYaw(); - weaponangles[ROLL] = 0.0f; // remove roll for weapons + vec3_t rotation = {0}; + rotation[PITCH] = vr_weapon_pitchadjust; + //rotation[YAW] = (doomYaw - hmdorientation[YAW]); + QuatToYawPitchRoll(quatRemote, rotation, weaponangles); if (weaponStabilised) @@ -114,7 +116,7 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew, float zxDist = length(x, z); if (zxDist != 0.0f && z != 0.0f) { - VectorSet(weaponangles, -degrees(atanf(y / zxDist)), VR_GetRawYaw() - degrees(atan2f(x, -z)), 0.0f); + VectorSet(weaponangles, -degrees(atanf(y / zxDist)), (-(doomYaw - hmdorientation[YAW])) - degrees(atan2f(x, -z)), 0.0f); } } } @@ -128,11 +130,12 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew, offhandoffset[2] = pOffTracking->HeadPose.Pose.Position.z - hmdPosition[2]; vec2_t v; - rotateAboutOrigin(-offhandoffset[0], offhandoffset[2], VR_GetRawYaw(), v); - offhandoffset[0] = v[0]; - offhandoffset[2] = v[1]; + rotateAboutOrigin(offhandoffset[0], offhandoffset[2], -(doomYaw - hmdorientation[YAW]), v); + offhandoffset[0] = v[1]; + offhandoffset[2] = v[0]; - QuatToYawPitchRoll(pOffTracking->HeadPose.Pose.Orientation, 0.0f, offhandangles); + vec3_t rotation = {0}; + QuatToYawPitchRoll(pOffTracking->HeadPose.Pose.Orientation, rotation, offhandangles); if (vr_walkdirection == 0) { controllerYawHeading = offhandangles[YAW] - hmdorientation[YAW]; @@ -141,8 +144,6 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew, { controllerYawHeading = 0.0f; } - - offhandangles[YAW] -= VR_GetRawYaw(); } //Positional movement diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/actor.h b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/actor.h index 51b8b80..05b8fb0 100644 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/actor.h +++ b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/actor.h @@ -1506,7 +1506,8 @@ public: //For VR, override firing position - Thank-you Fishbiter for this code!! bool OverrideAttackPosDir; DVector3 AttackPos; - DVector3 AttackDir; + //DVector3 AttackDir; + DVector3 (*AttackDir)(AActor* actor, DAngle yaw, DAngle pitch); }; class FActorIterator diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/gl/stereo3d/gl_oculusquest.cpp b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/gl/stereo3d/gl_oculusquest.cpp index 8517b77..8a94ac2 100644 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/gl/stereo3d/gl_oculusquest.cpp +++ b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/gl/stereo3d/gl_oculusquest.cpp @@ -91,39 +91,13 @@ namespace s3d dispose(); } - - static void vSMatrixFromOvrMatrix(VSMatrix& m1, const ovrMatrix4f& m2) - { - float tmp[16]; - for (int i = 0; i < 3; ++i) { - for (int j = 0; j < 4; ++j) { - tmp[4 * i + j] = m2.M[i][j]; - } - } - int i = 3; - for (int j = 0; j < 4; ++j) { - tmp[4 * i + j] = 0; - } - tmp[15] = 1; - m1.loadMatrix(&tmp[0]); - } - - /* virtual */ void OculusQuestEyePose::GetViewShift(FLOATTYPE yaw, FLOATTYPE outViewShift[3]) const { outViewShift[0] = outViewShift[1] = outViewShift[2] = 0; - // Pitch and Roll are identical between OpenVR and Doom worlds. - // But yaw can differ, depending on starting state, and controller movement. - float doomYawDegrees = r_viewpoint.Angles.Yaw.Degrees; - while (doomYawDegrees > 180) - doomYawDegrees -= 360; - while (doomYawDegrees < -180) - doomYawDegrees += 360; - vec3_t angles; - VectorSet(angles, -GLRenderer->mAngles.Pitch.Degrees, doomYawDegrees, GLRenderer->mAngles.Roll.Degrees); + VectorSet(angles, -GLRenderer->mAngles.Pitch.Degrees, doomYaw, GLRenderer->mAngles.Roll.Degrees); vec3_t v_forward, v_right, v_up; AngleVectors(angles, v_forward, v_right, v_up); @@ -242,7 +216,6 @@ namespace s3d void OculusQuestEyePose::AdjustHud() const { - // Draw crosshair on a separate quad, before updating HUD matrix const Stereo3DMode * mode3d = &Stereo3DMode::getCurrentMode(); if (mode3d->IsMono()) return; @@ -320,7 +293,7 @@ namespace s3d float scale = 0.000625f * vr_weaponScale; gl_RenderState.mModelMatrix.scale(scale, -scale, scale); - gl_RenderState.mModelMatrix.translate(-viewwidth / 2, -viewheight * 3 / 4, 0.0f); + gl_RenderState.mModelMatrix.translate(-viewwidth / 2, -viewheight * 3 / 4, 0.0f); // What dis?! gl_RenderState.EnableModelMatrix(true); } @@ -330,40 +303,50 @@ namespace s3d gl_RenderState.EnableModelMatrix(false); } + static void vSMatrixFromOvrMatrix(VSMatrix& m1, const ovrMatrix4f& m2) + { + float tmp[16]; + for (int i = 0; i < 4; ++i) { + for (int j = 0; j < 4; ++j) { + //Do the transpose step at the same time + tmp[4 * j + 1] = m2.M[i][j]; + } + } + + m1.loadMatrix(&tmp[0]); + } + bool OculusQuestMode::GetHandTransform(int hand, VSMatrix* mat) const { + AActor* playermo = r_viewpoint.camera->player->mo; + DVector3 pos = playermo->InterpolatedPosition(r_viewpoint.TicFrac); + { mat->loadIdentity(); - AActor* playermo = r_viewpoint.camera->player->mo; - DVector3 pos = playermo->InterpolatedPosition(r_viewpoint.TicFrac); - mat->translate(pos.X, pos.Z, pos.Y); mat->scale(vr_vunits_per_meter, vr_vunits_per_meter, -vr_vunits_per_meter); - float doomYawDegrees = r_viewpoint.Angles.Yaw.Degrees; - while (doomYawDegrees > 180) - doomYawDegrees -= 360; - while (doomYawDegrees < -180) - doomYawDegrees += 360; - if ((vr_control_scheme < 10 && hand == 1) || (vr_control_scheme > 10 && hand == 0)) { mat->translate(-weaponoffset[0], hmdPosition[1] + weaponoffset[1] - vr_floor_offset, weaponoffset[2]); - mat->rotate(-weaponangles[ROLL], 1, 0, 0); - mat->rotate(-weaponangles[PITCH], 0, 1, 0); - mat->rotate(-doomYawDegrees-weaponangles[YAW], 0, 0, 1); + + mat->rotate(-90 + (doomYaw - hmdorientation[YAW]) + weaponangles[YAW], 0, 1, 0); + mat->rotate(-weaponangles[PITCH], 1, 0, 0); + mat->rotate(-weaponangles[ROLL], 0, 0, 1); } else { - //mat->rotate(-offhandangles[ROLL], 1, 0, 0); - //mat->rotate(-offhandangles[PITCH], 0, 1, 0); - //mat->rotate(-offhandangles[YAW], 0, 0, 1); + mat->rotate(-90 + (doomYaw - hmdorientation[YAW]) + offhandangles[YAW], 0, 1, 0); + mat->rotate(-offhandangles[PITCH], 1, 0, 0); + mat->rotate(-offhandangles[ROLL], 0, 0, 1); + mat->translate(offhandoffset[0], hmdPosition[1] + offhandoffset[1] - vr_floor_offset, -offhandoffset[2]); } return true; + } return false; @@ -398,7 +381,40 @@ namespace s3d return int(m); } -/* virtual */ + + static DVector3 MapAttackDir(AActor* actor, DAngle yaw, DAngle pitch) + { + LSMatrix44 mat; + if (!s3d::Stereo3DMode::getCurrentMode().GetWeaponTransform(&mat)) + { + double pc = pitch.Cos(); + + DVector3 direction = { pc * yaw.Cos(), pc * yaw.Sin(), -pitch.Sin() }; + return direction; + } + double pc = pitch.Cos(); + + yaw -= actor->Angles.Yaw; + + //ignore specified pitch (would need to compensate for auto aim and no (vanilla) Doom weapon varies this) + //pitch -= actor->Angles.Pitch; + pitch.Degrees = 0; + + pc = pitch.Cos(); + + LSVec3 local = { (float)(pc * yaw.Cos()), (float)(pc * yaw.Sin()), (float)(-pitch.Sin()), 0.0f }; + + DVector3 dir; + dir.X = local.x * -mat[2][0] + local.y * -mat[0][0] + local.z * -mat[1][0]; + dir.Y = local.x * -mat[2][2] + local.y * -mat[0][2] + local.z * -mat[1][2]; + dir.Z = local.x * -mat[2][1] + local.y * -mat[0][1] + local.z * -mat[1][1]; + dir.MakeUnit(); + + return dir; + } + + + /* virtual */ void OculusQuestMode::SetUp() const { super::SetUp(); @@ -432,7 +448,7 @@ namespace s3d //Some crazy stuff to ascertain the actual yaw that doom is using at the right times! if (gamestate != GS_LEVEL || isMenuActive() || (gamestate == GS_LEVEL && resetDoomYaw)) { - doomYaw = r_viewpoint.Angles.Yaw.Degrees; + doomYaw = (float)r_viewpoint.Angles.Yaw.Degrees; if (gamestate == GS_LEVEL && resetDoomYaw) { resetDoomYaw = false; } @@ -446,15 +462,20 @@ namespace s3d { if (player) { - //Weapon firing tracking - Thanks Fishbiter! + //Weapon firing tracking - Thanks Fishbiter for the inspiration of how/where to use this! { player->mo->OverrideAttackPosDir = true; - player->mo->AttackPos.X = player->mo->X() + weaponoffset[0]; - player->mo->AttackPos.Y = player->mo->Y() + weaponoffset[1]; - player->mo->AttackPos.Z = player->mo->Z() + weaponoffset[2]; + player->mo->AttackPos.X = player->mo->X() - (weaponoffset[0] * vr_vunits_per_meter); + player->mo->AttackPos.Y = player->mo->Y() + (weaponoffset[2] * vr_vunits_per_meter); + player->mo->AttackPos.Z = player->mo->Z() + ((hmdPosition[1] + weaponoffset[1] + vr_floor_offset) * vr_vunits_per_meter); - player->mo->AttackDir = DVector3(weaponangles[0], weaponangles[1], weaponangles[2]); + vec3_t angles; + VectorSet(angles, -GLRenderer->mAngles.Pitch.Degrees, (doomYaw - hmdorientation[YAW]) + weaponangles[YAW], 0); + + vec3_t v_forward, v_right, v_up; + AngleVectors(angles, v_forward, v_right, v_up); + player->mo->AttackDir = MapAttackDir;//DVector3(v_forward[0], v_forward[1], v_forward[2]); } //Positional Movement diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/p_map.cpp b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/p_map.cpp index b7b0e8c..8f12289 100644 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/p_map.cpp +++ b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/p_map.cpp @@ -4495,12 +4495,10 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, // LAF_ABSOFFSET: Ignore the angle. DVector3 tempos; - - if (t1->player != NULL && t1->player->mo->OverrideAttackPosDir) { tempos = t1->player->mo->AttackPos; - direction = t1->player->mo->AttackDir; + direction = t1->player->mo->AttackDir(t1, angle, pitch); } else if (flags & LAF_ABSPOSITION) { diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/p_mobj.cpp b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/p_mobj.cpp index 000e129..85bba33 100644 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/p_mobj.cpp +++ b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/p_mobj.cpp @@ -6748,7 +6748,7 @@ AActor *P_SpawnPlayerMissile (AActor *source, double x, double y, double z, if (source->player != NULL && source->player->mo->OverrideAttackPosDir) { pos = source->player->mo->AttackPos; - DVector3 dir = source->player->mo->AttackDir; + DVector3 dir = source->player->mo->AttackDir(source, angle, pitch); an = dir.Angle(); pitch = -dir.Pitch(); }