mirror of
https://github.com/DrBeef/ioq3quest.git
synced 2024-11-26 05:52:03 +00:00
First big commit - pretty much playable throughout
This commit is contained in:
parent
3dc2dac2e5
commit
4b4ee4ec6e
35 changed files with 1202 additions and 172 deletions
|
@ -2,10 +2,10 @@ PLATFORM=android
|
|||
ANDROID_SDK_VERSION=android26
|
||||
ANDROID_NDK_VERSION=21.1.6352462
|
||||
## Uncomment for Windows host platform
|
||||
# ANDROID_NDK=C:/Users/<user>/AppData/Local/Android/Sdk/ndk/$(ANDROID_NDK_VERSION)
|
||||
# ANDROID_CC=$(ANDROID_NDK)/toolchains/llvm/prebuilt/windows-x86_64/bin/clang.exe
|
||||
# ANDROID_CFLAGS=--target=aarch64-linux-$(ANDROID_SDK_VERSION)
|
||||
# ANDROID_RANLIB=$(ANDROID_NDK)/toolchains/llvm/prebuilt/windows-x86_64/bin/aarch64-linux-android-ranlib.exe
|
||||
ANDROID_NDK=C:/Users/simon/AppData/Local/Android/Sdk/ndk/$(ANDROID_NDK_VERSION)
|
||||
ANDROID_CC=$(ANDROID_NDK)/toolchains/llvm/prebuilt/windows-x86_64/bin/clang.exe
|
||||
ANDROID_CFLAGS=--target=aarch64-linux-$(ANDROID_SDK_VERSION)
|
||||
ANDROID_RANLIB=$(ANDROID_NDK)/toolchains/llvm/prebuilt/windows-x86_64/bin/aarch64-linux-android-ranlib.exe
|
||||
## Uncomment for Linux host platform
|
||||
# ANDROID_NDK=~/Android/Sdk/ndk/$(ANDROID_NDK_VERSION)
|
||||
# ANDROID_CC=$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-$(ANDROID_SDK_VERSION)-clang
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
android:label="@string/app_name"
|
||||
android:hasCode="true">
|
||||
<meta-data android:name="com.samsung.android.vr.application.mode" android:value="vr_only"/>
|
||||
<meta-data android:name="com.oculus.supportedDevices" android:value="quest|quest2"/>
|
||||
<activity android:name="com.sparkie.ioq3quest.MainActivity"
|
||||
android:label="@string/app_name"
|
||||
android:screenOrientation="landscape"
|
||||
|
|
1
android/app/src/main/cpp/code
Symbolic link
1
android/app/src/main/cpp/code
Symbolic link
|
@ -0,0 +1 @@
|
|||
E:/ioq3quest/code
|
|
@ -13,6 +13,7 @@ extern "C" {
|
|||
#include <qcommon/qcommon.h>
|
||||
#include <vr/vr_base.h>
|
||||
#include <vr/vr_renderer.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
|
@ -60,68 +61,56 @@ static ovrJava engine_get_ovrJava() {
|
|||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
ovrJava java = engine_get_ovrJava();
|
||||
engine_t* engine = nullptr;
|
||||
engine = VR_Init(java);
|
||||
|
||||
//First set up resolution cached values
|
||||
int width, height;
|
||||
VR_GetRsolution( engine, &width, &height );
|
||||
|
||||
CON_LogcatFn(&ioq3_logfn);
|
||||
|
||||
std::string defaultArgs("+set fs_basepath ");
|
||||
defaultArgs += SDL_AndroidGetExternalStoragePath();
|
||||
defaultArgs += " +set fs_game baseq3 +map q3dm6";
|
||||
defaultArgs += " +set fs_game baseq3";
|
||||
|
||||
char* args = new char[defaultArgs.length() + 1];
|
||||
args[defaultArgs.length()] = '\0';
|
||||
memcpy(args, defaultArgs.c_str(), defaultArgs.length());
|
||||
Com_Init(args);
|
||||
|
||||
ovrJava java = engine_get_ovrJava();
|
||||
VR_InitRenderer(engine);
|
||||
|
||||
constexpr auto vrEnabled = true;
|
||||
engine_t* engine = nullptr;
|
||||
VR_EnterVR(engine, java);
|
||||
|
||||
if (vrEnabled)
|
||||
{
|
||||
engine = VR_Init(java);
|
||||
VR_InitRenderer(engine);
|
||||
|
||||
VR_EnterVR(engine, java);
|
||||
}
|
||||
//sleep(20);
|
||||
|
||||
while (1) {
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
LOGI("Received SDL Event: %d", event.type);
|
||||
if (vrEnabled)
|
||||
switch (event.type)
|
||||
{
|
||||
switch (event.type)
|
||||
{
|
||||
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
||||
VR_EnterVR(engine, engine_get_ovrJava());
|
||||
break;
|
||||
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
||||
VR_EnterVR(engine, engine_get_ovrJava());
|
||||
break;
|
||||
|
||||
case SDL_WINDOWEVENT_FOCUS_LOST:
|
||||
VR_LeaveVR(engine);
|
||||
break;
|
||||
}
|
||||
case SDL_WINDOWEVENT_FOCUS_LOST:
|
||||
VR_LeaveVR(engine);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (vrEnabled)
|
||||
{
|
||||
VR_DrawFrame(engine);
|
||||
}
|
||||
else
|
||||
{
|
||||
Com_Frame();
|
||||
}
|
||||
}
|
||||
if (vrEnabled)
|
||||
{
|
||||
VR_LeaveVR(engine);
|
||||
VR_DestroyRenderer(engine);
|
||||
|
||||
VR_DrawFrame(engine);
|
||||
}
|
||||
|
||||
VR_LeaveVR(engine);
|
||||
VR_DestroyRenderer(engine);
|
||||
|
||||
Com_Shutdown();
|
||||
if (vrEnabled)
|
||||
{
|
||||
VR_Destroy(engine);
|
||||
}
|
||||
VR_Destroy(engine);
|
||||
|
||||
delete [] args;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -5,10 +5,13 @@ setlocal
|
|||
set ANDROID_SDK_ROOT=%AppData%\..\Local\Android\Sdk
|
||||
set adb="%ANDROID_SDK_ROOT%\platform-tools\adb.exe"
|
||||
set make="%ANDROID_SDK_ROOT%\ndk\21.1.6352462\prebuilt\windows-x86_64\bin\make.exe"
|
||||
set apksigner="%ANDROID_SDK_ROOT%\build-tools\29.0.2\apksigner.bat"
|
||||
set JAVA_HOME=C:\Program Files\Android\Android Studio\jre\jre
|
||||
set BUILD_TYPE=release
|
||||
set GRADLE_BUILD_TYPE=:app:assembleRelease
|
||||
|
||||
pushd %~dp0\..
|
||||
%make% -j %NUMBER_OF_PROCESSORS% debug
|
||||
%make% -j %NUMBER_OF_PROCESSORS% %BUILD_TYPE%
|
||||
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
popd
|
||||
|
@ -19,7 +22,7 @@ if %ERRORLEVEL% NEQ 0 (
|
|||
pushd android
|
||||
|
||||
set GRADLE_EXIT_CONSOLE=1
|
||||
call gradlew.bat :app:assembleDebug
|
||||
call gradlew.bat %GRADLE_BUILD_TYPE%
|
||||
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
popd
|
||||
|
@ -30,7 +33,9 @@ if %ERRORLEVEL% NEQ 0 (
|
|||
|
||||
set PACKAGE_NAME=com.sparkie.ioq3quest
|
||||
set ANDROID_STORAGE_LOCATION=/sdcard/Android/data/%PACKAGE_NAME%/files/
|
||||
set APK_LOCATION=.\app\build\outputs\apk\debug\app-debug.apk
|
||||
set APK_LOCATION=.\app\build\outputs\apk\%BUILD_TYPE%\app-%BUILD_TYPE%.apk
|
||||
|
||||
REM %apksigner% sign --ks ../drbeef-release-key.keystore --out %APK_LOCATION% .\app\build\outputs\apk\%BUILD_TYPE%\app-%BUILD_TYPE%-unsigned.apk
|
||||
|
||||
%adb% install -r %APK_LOCATION%
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
|
@ -45,7 +50,7 @@ if %ERRORLEVEL% NEQ 0 (
|
|||
)
|
||||
|
||||
%adb% shell mkdir -p %ANDROID_STORAGE_LOCATION%
|
||||
%adb% push --sync "C:\Program Files (x86)\Steam\steamapps\common\Quake 3 Arena\baseq3" %ANDROID_STORAGE_LOCATION%
|
||||
%adb% push --sync "D:\Program Files (x86)\Steam\steamapps\common\Quake 3 Arena\baseq3" %ANDROID_STORAGE_LOCATION%
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
popd
|
||||
popd
|
||||
|
|
|
@ -24,6 +24,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
// active (after loading) gameplay
|
||||
|
||||
#include "cg_local.h"
|
||||
#include "../vr/vr_clientinfo.h"
|
||||
|
||||
#ifdef MISSIONPACK
|
||||
#include "../ui/ui_shared.h"
|
||||
|
@ -38,6 +39,9 @@ int drawTeamOverlayModificationCount = -1;
|
|||
int sortedTeamPlayers[TEAM_MAXOVERLAY];
|
||||
int numSortedTeamPlayers;
|
||||
|
||||
extern vr_clientinfo_t* cgVR;
|
||||
extern stereoFrame_t hudStereoView;
|
||||
|
||||
char systemChat[256];
|
||||
char teamChat1[256];
|
||||
char teamChat2[256];
|
||||
|
@ -278,6 +282,7 @@ void CG_Draw3DModel( float x, float y, float w, float h, qhandle_t model, qhandl
|
|||
|
||||
memset( &ent, 0, sizeof( ent ) );
|
||||
AnglesToAxis( angles, ent.axis );
|
||||
|
||||
VectorCopy( origin, ent.origin );
|
||||
ent.hModel = model;
|
||||
ent.customSkin = skin;
|
||||
|
@ -1923,6 +1928,7 @@ static void CG_DrawCrosshair(void)
|
|||
CG_DrawCrosshair3D
|
||||
=================
|
||||
*/
|
||||
void CG_CalculateVRWeaponPosition( vec3_t origin, vec3_t angles );
|
||||
static void CG_DrawCrosshair3D(void)
|
||||
{
|
||||
float w;
|
||||
|
@ -1976,10 +1982,19 @@ static void CG_DrawCrosshair3D(void)
|
|||
xmax = zProj * tan(cg.refdef.fov_x * M_PI / 360.0f);
|
||||
|
||||
// let the trace run through until a change in stereo separation of the crosshair becomes less than one pixel.
|
||||
vec3_t viewaxis[3];
|
||||
vec3_t weaponangles;
|
||||
vec3_t origin;
|
||||
CG_CalculateVRWeaponPosition(origin, weaponangles);
|
||||
AnglesToAxis(weaponangles, viewaxis);
|
||||
maxdist = cgs.glconfig.vidWidth * stereoSep * zProj / (2 * xmax);
|
||||
VectorMA(origin, maxdist, viewaxis[0], endpos);
|
||||
CG_Trace(&trace, origin, NULL, NULL, endpos, 0, MASK_SHOT);
|
||||
|
||||
/* maxdist = cgs.glconfig.vidWidth * stereoSep * zProj / (2 * xmax);
|
||||
VectorMA(cg.refdef.vieworg, maxdist, cg.refdef.viewaxis[0], endpos);
|
||||
CG_Trace(&trace, cg.refdef.vieworg, NULL, NULL, endpos, 0, MASK_SHOT);
|
||||
|
||||
*/
|
||||
memset(&ent, 0, sizeof(ent));
|
||||
ent.reType = RT_SPRITE;
|
||||
ent.renderfx = RF_DEPTHHACK | RF_CROSSHAIR;
|
||||
|
@ -2647,11 +2662,28 @@ void CG_DrawActive( stereoFrame_t stereoView ) {
|
|||
if(stereoView != STEREO_CENTER)
|
||||
CG_DrawCrosshair3D();
|
||||
|
||||
// offset vieworg appropriately if we're doing stereo separation
|
||||
vec3_t baseOrg;
|
||||
VectorCopy( cg.refdef.vieworg, baseOrg );
|
||||
|
||||
float ipd = 0.065f;
|
||||
float separation = stereoView == STEREO_LEFT ?
|
||||
WORLD_SCALE * (-ipd / 2) : //left
|
||||
WORLD_SCALE * (ipd / 2); // right
|
||||
|
||||
cg.refdef.vieworg[2] -= PLAYER_HEIGHT;
|
||||
cg.refdef.vieworg[2] += cgVR->hmdposition[1] * WORLD_SCALE;
|
||||
|
||||
VectorMA( cg.refdef.vieworg, -separation, cg.refdef.viewaxis[1], cg.refdef.vieworg );
|
||||
|
||||
// draw 3D view
|
||||
trap_R_RenderScene( &cg.refdef );
|
||||
|
||||
VectorCopy( baseOrg, cg.refdef.vieworg );
|
||||
|
||||
// draw status bar and other floating elements
|
||||
CG_Draw2D(stereoView);
|
||||
hudStereoView = stereoView;
|
||||
CG_Draw2D(hudStereoView);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -23,6 +23,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
// cg_drawtools.c -- helper functions called by cg_draw, cg_scoreboard, cg_info, etc
|
||||
#include "cg_local.h"
|
||||
|
||||
int hudflags = 0;
|
||||
stereoFrame_t hudStereoView = STEREO_CENTER;
|
||||
|
||||
/*
|
||||
================
|
||||
CG_AdjustFrom640
|
||||
|
@ -31,17 +34,33 @@ Adjusted for resolution and screen aspect ratio
|
|||
================
|
||||
*/
|
||||
void CG_AdjustFrom640( float *x, float *y, float *w, float *h ) {
|
||||
#if 0
|
||||
// adjust for wide screens
|
||||
if ( cgs.glconfig.vidWidth * 480 > cgs.glconfig.vidHeight * 640 ) {
|
||||
*x += 0.5 * ( cgs.glconfig.vidWidth - ( cgs.glconfig.vidHeight * 640 / 480 ) );
|
||||
|
||||
if (hudflags & HUD_FLAGS_FULLSCREEN)
|
||||
{
|
||||
// scale for screen sizes
|
||||
*x *= cgs.screenXScale;
|
||||
*y *= cgs.screenYScale;
|
||||
*w *= cgs.screenXScale;
|
||||
*h *= cgs.screenYScale;
|
||||
}
|
||||
else // scale to clearly visible portion of VR screen
|
||||
{
|
||||
float screenXScale = cgs.screenXScale / 2.75f;
|
||||
float screenYScale = cgs.screenYScale / 2.75f;
|
||||
|
||||
int xoffset = -64;
|
||||
if (hudStereoView == STEREO_LEFT) {
|
||||
xoffset *= -1;
|
||||
}
|
||||
|
||||
*x *= screenXScale;
|
||||
*y *= screenYScale;
|
||||
*w *= screenXScale;
|
||||
*h *= screenYScale;
|
||||
|
||||
*x += (cg.refdef.width - (640 * screenXScale)) / 2.0f + xoffset;
|
||||
*y += (cg.refdef.height - (480 * screenYScale)) / 2.0f;
|
||||
}
|
||||
#endif
|
||||
// scale for screen sizes
|
||||
*x *= cgs.screenXScale;
|
||||
*y *= cgs.screenYScale;
|
||||
*w *= cgs.screenXScale;
|
||||
*h *= cgs.screenYScale;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -90,6 +90,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
|
||||
#define DEFAULT_REDTEAM_NAME "Stroggs"
|
||||
#define DEFAULT_BLUETEAM_NAME "Pagans"
|
||||
//VR HUD
|
||||
#define HUD_FLAGS_FULLSCREEN 1
|
||||
|
||||
typedef enum {
|
||||
FOOTSTEP_NORMAL,
|
||||
|
|
|
@ -23,12 +23,16 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
// cg_main.c -- initialization and primary entry point for cgame
|
||||
#include "cg_local.h"
|
||||
|
||||
#include "../vr/vr_clientinfo.h"
|
||||
|
||||
#ifdef MISSIONPACK
|
||||
#include "../ui/ui_shared.h"
|
||||
// display context for new ui stuff
|
||||
displayContextDef_t cgDC;
|
||||
#endif
|
||||
|
||||
vr_clientinfo_t *cgVR;
|
||||
|
||||
int forceModelModificationCount = -1;
|
||||
|
||||
void CG_Init( int serverMessageNum, int serverCommandSequence, int clientNum );
|
||||
|
@ -74,6 +78,11 @@ Q_EXPORT intptr_t vmMain( int command, int arg0, int arg1, int arg2, int arg3, i
|
|||
case CG_EVENT_HANDLING:
|
||||
CG_EventHandling(arg0);
|
||||
return 0;
|
||||
case CG_SET_VR_CLIENT_INFO: {
|
||||
int ptr[2] = {arg0, arg1};
|
||||
cgVR = (vr_clientinfo_t *) (*(long*)(ptr));
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
CG_Error( "vmMain: unknown command %i", command );
|
||||
break;
|
||||
|
|
|
@ -231,8 +231,11 @@ typedef enum {
|
|||
|
||||
CG_MOUSE_EVENT,
|
||||
// void (*CG_MouseEvent)( int dx, int dy );
|
||||
CG_EVENT_HANDLING
|
||||
CG_EVENT_HANDLING,
|
||||
// void (*CG_EventHandling)(int type);
|
||||
|
||||
CG_SET_VR_CLIENT_INFO
|
||||
|
||||
} cgameExport_t;
|
||||
|
||||
//----------------------------------------------
|
||||
|
|
|
@ -333,8 +333,8 @@ static void CG_OffsetFirstPersonView( void ) {
|
|||
|
||||
// if dead, fix the angle and don't add any kick
|
||||
if ( cg.snap->ps.stats[STAT_HEALTH] <= 0 ) {
|
||||
angles[ROLL] = 40;
|
||||
angles[PITCH] = -15;
|
||||
//angles[ROLL] = 40;
|
||||
//angles[PITCH] = -15;
|
||||
angles[YAW] = cg.snap->ps.stats[STAT_DEAD_YAW];
|
||||
origin[2] += cg.predictedPlayerState.viewheight;
|
||||
return;
|
||||
|
|
|
@ -22,6 +22,232 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
//
|
||||
// cg_weapons.c -- events and effects dealing with weapons
|
||||
#include "cg_local.h"
|
||||
#include "../vr/vr_clientinfo.h"
|
||||
|
||||
extern vr_clientinfo_t *cgVR;
|
||||
|
||||
|
||||
#define M_PI2 (float)6.28318530717958647692
|
||||
|
||||
/*
|
||||
=================
|
||||
SinCos
|
||||
=================
|
||||
*/
|
||||
void SinCos( float radians, float *sine, float *cosine )
|
||||
{
|
||||
#if _MSC_VER == 1200
|
||||
_asm
|
||||
{
|
||||
fld dword ptr [radians]
|
||||
fsincos
|
||||
|
||||
mov edx, dword ptr [cosine]
|
||||
mov eax, dword ptr [sine]
|
||||
|
||||
fstp dword ptr [edx]
|
||||
fstp dword ptr [eax]
|
||||
}
|
||||
#else
|
||||
// I think, better use math.h function, instead of ^
|
||||
#if defined (__linux__) && !defined (__ANDROID__)
|
||||
sincosf(radians, sine, cosine);
|
||||
#else
|
||||
*sine = sinf(radians);
|
||||
*cosine = cosf(radians);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void Matrix4x4_Concat (matrix4x4 out, const matrix4x4 in1, const matrix4x4 in2)
|
||||
{
|
||||
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0] + in1[0][3] * in2[3][0];
|
||||
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1] + in1[0][3] * in2[3][1];
|
||||
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2] + in1[0][3] * in2[3][2];
|
||||
out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + in1[0][2] * in2[2][3] + in1[0][3] * in2[3][3];
|
||||
out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0] + in1[1][3] * in2[3][0];
|
||||
out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1] + in1[1][3] * in2[3][1];
|
||||
out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2] + in1[1][3] * in2[3][2];
|
||||
out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + in1[1][2] * in2[2][3] + in1[1][3] * in2[3][3];
|
||||
out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0] + in1[2][3] * in2[3][0];
|
||||
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1] + in1[2][3] * in2[3][1];
|
||||
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2] + in1[2][3] * in2[3][2];
|
||||
out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + in1[2][2] * in2[2][3] + in1[2][3] * in2[3][3];
|
||||
out[3][0] = in1[3][0] * in2[0][0] + in1[3][1] * in2[1][0] + in1[3][2] * in2[2][0] + in1[3][3] * in2[3][0];
|
||||
out[3][1] = in1[3][0] * in2[0][1] + in1[3][1] * in2[1][1] + in1[3][2] * in2[2][1] + in1[3][3] * in2[3][1];
|
||||
out[3][2] = in1[3][0] * in2[0][2] + in1[3][1] * in2[1][2] + in1[3][2] * in2[2][2] + in1[3][3] * in2[3][2];
|
||||
out[3][3] = in1[3][0] * in2[0][3] + in1[3][1] * in2[1][3] + in1[3][2] * in2[2][3] + in1[3][3] * in2[3][3];
|
||||
}
|
||||
|
||||
void Matrix4x4_CreateFromEntity( matrix4x4 out, const vec3_t angles, const vec3_t origin, float scale )
|
||||
{
|
||||
float angle, sr, sp, sy, cr, cp, cy;
|
||||
|
||||
if( angles[ROLL] )
|
||||
{
|
||||
#ifdef XASH_VECTORIZE_SINCOS
|
||||
SinCosFastVector3( DEG2RAD(angles[YAW]), DEG2RAD(angles[PITCH]), DEG2RAD(angles[ROLL]),
|
||||
&sy, &sp, &sr,
|
||||
&cy, &cp, &cr);
|
||||
#else
|
||||
angle = angles[YAW] * (M_PI2 / 360.0f);
|
||||
SinCos( angle, &sy, &cy );
|
||||
angle = angles[PITCH] * (M_PI2 / 360.0f);
|
||||
SinCos( angle, &sp, &cp );
|
||||
angle = angles[ROLL] * (M_PI2 / 360.0f);
|
||||
SinCos( angle, &sr, &cr );
|
||||
#endif
|
||||
|
||||
out[0][0] = (cp*cy) * scale;
|
||||
out[0][1] = (sr*sp*cy+cr*-sy) * scale;
|
||||
out[0][2] = (cr*sp*cy+-sr*-sy) * scale;
|
||||
out[0][3] = origin[0];
|
||||
out[1][0] = (cp*sy) * scale;
|
||||
out[1][1] = (sr*sp*sy+cr*cy) * scale;
|
||||
out[1][2] = (cr*sp*sy+-sr*cy) * scale;
|
||||
out[1][3] = origin[1];
|
||||
out[2][0] = (-sp) * scale;
|
||||
out[2][1] = (sr*cp) * scale;
|
||||
out[2][2] = (cr*cp) * scale;
|
||||
out[2][3] = origin[2];
|
||||
out[3][0] = 0.0f;
|
||||
out[3][1] = 0.0f;
|
||||
out[3][2] = 0.0f;
|
||||
out[3][3] = 1.0f;
|
||||
}
|
||||
else if( angles[PITCH] )
|
||||
{
|
||||
#ifdef XASH_VECTORIZE_SINCOS
|
||||
SinCosFastVector2( DEG2RAD(angles[YAW]), DEG2RAD(angles[PITCH]),
|
||||
&sy, &sp,
|
||||
&cy, &cp);
|
||||
#else
|
||||
angle = angles[YAW] * (M_PI2 / 360.0f);
|
||||
SinCos( angle, &sy, &cy );
|
||||
angle = angles[PITCH] * (M_PI2 / 360.0f);
|
||||
SinCos( angle, &sp, &cp );
|
||||
#endif
|
||||
|
||||
out[0][0] = (cp*cy) * scale;
|
||||
out[0][1] = (-sy) * scale;
|
||||
out[0][2] = (sp*cy) * scale;
|
||||
out[0][3] = origin[0];
|
||||
out[1][0] = (cp*sy) * scale;
|
||||
out[1][1] = (cy) * scale;
|
||||
out[1][2] = (sp*sy) * scale;
|
||||
out[1][3] = origin[1];
|
||||
out[2][0] = (-sp) * scale;
|
||||
out[2][1] = 0.0f;
|
||||
out[2][2] = (cp) * scale;
|
||||
out[2][3] = origin[2];
|
||||
out[3][0] = 0.0f;
|
||||
out[3][1] = 0.0f;
|
||||
out[3][2] = 0.0f;
|
||||
out[3][3] = 1.0f;
|
||||
}
|
||||
else if( angles[YAW] )
|
||||
{
|
||||
angle = angles[YAW] * (M_PI2 / 360.0f);
|
||||
SinCos( angle, &sy, &cy );
|
||||
|
||||
out[0][0] = (cy) * scale;
|
||||
out[0][1] = (-sy) * scale;
|
||||
out[0][2] = 0.0f;
|
||||
out[0][3] = origin[0];
|
||||
out[1][0] = (sy) * scale;
|
||||
out[1][1] = (cy) * scale;
|
||||
out[1][2] = 0.0f;
|
||||
out[1][3] = origin[1];
|
||||
out[2][0] = 0.0f;
|
||||
out[2][1] = 0.0f;
|
||||
out[2][2] = scale;
|
||||
out[2][3] = origin[2];
|
||||
out[3][0] = 0.0f;
|
||||
out[3][1] = 0.0f;
|
||||
out[3][2] = 0.0f;
|
||||
out[3][3] = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
out[0][0] = scale;
|
||||
out[0][1] = 0.0f;
|
||||
out[0][2] = 0.0f;
|
||||
out[0][3] = origin[0];
|
||||
out[1][0] = 0.0f;
|
||||
out[1][1] = scale;
|
||||
out[1][2] = 0.0f;
|
||||
out[1][3] = origin[1];
|
||||
out[2][0] = 0.0f;
|
||||
out[2][1] = 0.0f;
|
||||
out[2][2] = scale;
|
||||
out[2][3] = origin[2];
|
||||
out[3][0] = 0.0f;
|
||||
out[3][1] = 0.0f;
|
||||
out[3][2] = 0.0f;
|
||||
out[3][3] = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void Matrix4x4_ConvertToEntity( vec4_t *in, vec3_t angles, vec3_t origin )
|
||||
{
|
||||
float xyDist = sqrt( in[0][0] * in[0][0] + in[1][0] * in[1][0] );
|
||||
|
||||
// enough here to get angles?
|
||||
if( xyDist > 0.001f )
|
||||
{
|
||||
angles[0] = RAD2DEG( atan2( -in[2][0], xyDist ));
|
||||
angles[1] = RAD2DEG( atan2( in[1][0], in[0][0] ));
|
||||
angles[2] = RAD2DEG( atan2( in[2][1], in[2][2] ));
|
||||
}
|
||||
else // forward is mostly Z, gimbal lock
|
||||
{
|
||||
angles[0] = RAD2DEG( atan2( -in[2][0], xyDist ));
|
||||
angles[1] = RAD2DEG( atan2( -in[0][1], in[1][1] ));
|
||||
angles[2] = 0.0f;
|
||||
}
|
||||
|
||||
origin[0] = in[0][3];
|
||||
origin[1] = in[1][3];
|
||||
origin[2] = in[2][3];
|
||||
}
|
||||
|
||||
void rotateAboutOrigin(float x, float y, float rotation, vec2_t out)
|
||||
{
|
||||
out[0] = cosf(DEG2RAD(-rotation)) * x + sinf(DEG2RAD(-rotation)) * y;
|
||||
out[1] = cosf(DEG2RAD(-rotation)) * y - sinf(DEG2RAD(-rotation)) * x;
|
||||
}
|
||||
|
||||
void convertFromVR(vec3_t in, vec3_t offset, vec3_t out)
|
||||
{
|
||||
vec3_t vrSpace;
|
||||
VectorSet(vrSpace, in[2], in[0], in[1] );
|
||||
|
||||
vec2_t r;
|
||||
rotateAboutOrigin(vrSpace[0], vrSpace[1], cg.refdefViewAngles[YAW] - cgVR->hmdorientation[YAW], r);
|
||||
vrSpace[0] = -r[0];
|
||||
vrSpace[1] = -r[1];
|
||||
|
||||
vec3_t temp;
|
||||
VectorScale(vrSpace, WORLD_SCALE, temp);
|
||||
|
||||
if (offset) {
|
||||
VectorAdd(temp, offset, out);
|
||||
} else {
|
||||
VectorCopy(temp, out);
|
||||
}
|
||||
}
|
||||
|
||||
void CG_CalculateVRWeaponPosition( vec3_t origin, vec3_t angles )
|
||||
{
|
||||
convertFromVR(cgVR->calculated_weaponoffset, cg.refdef.vieworg, origin);
|
||||
|
||||
origin[2] -= PLAYER_HEIGHT;
|
||||
origin[2] += cgVR->hmdposition[1] * WORLD_SCALE;
|
||||
|
||||
VectorCopy(cgVR->weaponangles, angles);
|
||||
|
||||
angles[YAW] += (cg.refdefViewAngles[YAW] - cgVR->hmdorientation[YAW]);
|
||||
}
|
||||
|
||||
/*
|
||||
==========================
|
||||
|
@ -207,6 +433,49 @@ static void CG_NailgunEjectBrass( centity_t *cent ) {
|
|||
#endif
|
||||
|
||||
|
||||
/*
|
||||
==========================
|
||||
CG_RailTrail2
|
||||
==========================
|
||||
*/
|
||||
void CG_RailTrail2( clientInfo_t *ci, vec3_t start, vec3_t end ) {
|
||||
localEntity_t *le;
|
||||
refEntity_t *re;
|
||||
|
||||
le = CG_AllocLocalEntity();
|
||||
re = &le->refEntity;
|
||||
|
||||
le->leType = LE_FADE_RGB;
|
||||
le->startTime = cg.time;
|
||||
le->endTime = cg.time + 25;
|
||||
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
|
||||
|
||||
re->shaderTime = cg.time / 1000.0f;
|
||||
re->reType = RT_RAIL_CORE;
|
||||
re->customShader = cgs.media.railCoreShader;
|
||||
|
||||
VectorCopy( start, re->origin );
|
||||
VectorCopy( end, re->oldorigin );
|
||||
|
||||
// // still allow different colors so we can tell AI shots from player shots, etc.
|
||||
le->color[3] = 1.0f;
|
||||
if ( ci ) {
|
||||
if (ci->health == 1)
|
||||
{
|
||||
le->color[3] = (ci->handicap / 255.0f);
|
||||
}
|
||||
le->color[0] = ci->color1[0] * 0.75;
|
||||
le->color[1] = ci->color1[1] * 0.75;
|
||||
le->color[2] = ci->color1[2] * 0.75;
|
||||
} else {
|
||||
le->color[0] = 1;
|
||||
le->color[1] = 0;
|
||||
le->color[2] = 0;
|
||||
}
|
||||
|
||||
AxisClear( re->axis );
|
||||
}
|
||||
|
||||
/*
|
||||
==========================
|
||||
CG_RailTrail
|
||||
|
@ -1398,11 +1667,12 @@ void CG_AddViewWeapon( playerState_t *ps ) {
|
|||
}
|
||||
|
||||
// drop gun lower at higher fov
|
||||
if ( cg_fov.integer > 90 ) {
|
||||
/* if ( cg_fov.integer > 90 ) {
|
||||
fovOffset = -0.2 * ( cg_fov.integer - 90 );
|
||||
} else {
|
||||
fovOffset = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
cent = &cg.predictedPlayerEntity; // &cg_entities[cg.snap->ps.clientNum];
|
||||
CG_RegisterWeapon( ps->weapon );
|
||||
|
@ -1411,11 +1681,61 @@ void CG_AddViewWeapon( playerState_t *ps ) {
|
|||
memset (&hand, 0, sizeof(hand));
|
||||
|
||||
// set up gun position
|
||||
CG_CalculateWeaponPosition( hand.origin, angles );
|
||||
CG_CalculateVRWeaponPosition( hand.origin, angles );
|
||||
|
||||
//Scale / Move gun etc
|
||||
float scale = 1.0f;
|
||||
{
|
||||
char cvar_name[64];
|
||||
Com_sprintf(cvar_name, sizeof(cvar_name), "vr_weapon_adjustment_%i", ps->weapon);
|
||||
|
||||
char weapon_adjustment[256];
|
||||
trap_Cvar_VariableStringBuffer(cvar_name, weapon_adjustment, 256);
|
||||
|
||||
if (strlen(weapon_adjustment) > 0) {
|
||||
vec3_t offset;
|
||||
vec3_t adjust;
|
||||
vec3_t temp_offset;
|
||||
VectorClear(temp_offset);
|
||||
VectorClear(adjust);
|
||||
|
||||
sscanf(weapon_adjustment, "%f,%f,%f,%f,%f,%f,%f", &scale,
|
||||
&(temp_offset[0]), &(temp_offset[1]), &(temp_offset[2]),
|
||||
&(adjust[PITCH]), &(adjust[YAW]), &(adjust[ROLL]));
|
||||
VectorScale(temp_offset, scale, offset);
|
||||
|
||||
if (!cgVR->right_handed)
|
||||
{
|
||||
//yaw needs to go in the other direction as left handed model is reversed
|
||||
adjust[YAW] *= -1.0f;
|
||||
}
|
||||
|
||||
//Adjust angles for weapon models that aren't aligned very well
|
||||
matrix4x4 m1, m2, m3;
|
||||
vec3_t zero;
|
||||
VectorClear(zero);
|
||||
Matrix4x4_CreateFromEntity(m1, angles, zero, 1.0);
|
||||
Matrix4x4_CreateFromEntity(m2, adjust, zero, 1.0);
|
||||
Matrix4x4_Concat(m3, m1, m2);
|
||||
Matrix4x4_ConvertToEntity(m3, angles, zero);
|
||||
|
||||
//Now move weapon closer to proper origin
|
||||
vec3_t forward, right, up;
|
||||
AngleVectors( angles, forward, right, up );
|
||||
VectorMA( hand.origin, offset[2], forward, hand.origin );
|
||||
VectorMA( hand.origin, offset[1], up, hand.origin );
|
||||
if (cgVR->right_handed) {
|
||||
VectorMA(hand.origin, offset[0], right, hand.origin);
|
||||
} else {
|
||||
VectorMA(hand.origin, -offset[0], right, hand.origin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Move gun a bit
|
||||
VectorMA( hand.origin, cg_gun_x.value, cg.refdef.viewaxis[0], hand.origin );
|
||||
VectorMA( hand.origin, cg_gun_y.value, cg.refdef.viewaxis[1], hand.origin );
|
||||
VectorMA( hand.origin, (cg_gun_z.value+fovOffset), cg.refdef.viewaxis[2], hand.origin );
|
||||
VectorMA( hand.origin, cg_gun_z.value, cg.refdef.viewaxis[2], hand.origin );
|
||||
|
||||
AnglesToAxis( angles, hand.axis );
|
||||
|
||||
|
@ -1435,8 +1755,39 @@ void CG_AddViewWeapon( playerState_t *ps ) {
|
|||
hand.hModel = weapon->handsModel;
|
||||
hand.renderfx = RF_DEPTHHACK | RF_FIRST_PERSON | RF_MINLIGHT;
|
||||
|
||||
//scale the whole model
|
||||
for ( int i = 0; i < 3; i++ ) {
|
||||
VectorScale( hand.axis[i], cgVR->right_handed || i != 1 ? scale : -scale, hand.axis[i] );
|
||||
}
|
||||
|
||||
|
||||
// add everything onto the hand
|
||||
CG_AddPlayerWeapon( &hand, ps, &cg.predictedPlayerEntity, ps->persistant[PERS_TEAM] );
|
||||
|
||||
//Weapon offset debugging
|
||||
if (qfalse)
|
||||
{
|
||||
vec3_t _origin;
|
||||
vec3_t endForward, endRight, endUp;
|
||||
vec3_t _angles;
|
||||
clientInfo_t ci;
|
||||
CG_CalculateVRWeaponPosition( _origin, _angles );
|
||||
|
||||
vec3_t forward, right, up;
|
||||
AngleVectors(_angles, forward, right, up);
|
||||
|
||||
VectorMA(_origin, 60, forward, endForward);
|
||||
VectorSet(ci.color1, 1, 0, 0); // Forward is red
|
||||
CG_RailTrail2(&ci, _origin, endForward);
|
||||
|
||||
VectorMA(_origin, 30, right, endRight);
|
||||
VectorSet(ci.color1, 0, 1, 0); // right is green
|
||||
CG_RailTrail2(&ci, _origin, endRight);
|
||||
|
||||
VectorMA(_origin, 30, up, endUp);
|
||||
VectorSet(ci.color1, 0, 0, 1); // up is blue
|
||||
CG_RailTrail2(&ci, _origin, endUp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -24,12 +24,14 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
#include "client.h"
|
||||
|
||||
#include "../botlib/botlib.h"
|
||||
#include "../vr/vr_clientinfo.h"
|
||||
|
||||
#ifdef USE_MUMBLE
|
||||
#include "libmumblelink.h"
|
||||
#endif
|
||||
|
||||
extern botlib_export_t *botlib_export;
|
||||
extern vr_clientinfo_t vr;
|
||||
|
||||
extern qboolean loadCamera(const char *name);
|
||||
extern void startCamera(int time);
|
||||
|
@ -53,6 +55,16 @@ void CL_GetGlconfig( glconfig_t *glconfig ) {
|
|||
*glconfig = cls.glconfig;
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
CL_CGameRendering
|
||||
=====================
|
||||
*/
|
||||
void CL_CGameSetVRClientInfo() {
|
||||
long val = (long)(&vr);
|
||||
int *ptr = (int*)(&val); //HACK!!
|
||||
VM_Call( cgvm, CG_SET_VR_CLIENT_INFO, ptr[0], ptr[1] );
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
|
|
|
@ -23,9 +23,14 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
|
||||
#include "client.h"
|
||||
|
||||
#include "../vr/vr_input.h"
|
||||
#include "../vr/vr_clientinfo.h"
|
||||
|
||||
unsigned frame_msec;
|
||||
int old_com_frameTime;
|
||||
|
||||
extern vr_clientinfo_t vr;
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
|
@ -290,7 +295,7 @@ Moves the local angle positions
|
|||
================
|
||||
*/
|
||||
void CL_AdjustAngles( void ) {
|
||||
float speed;
|
||||
/* float speed;
|
||||
|
||||
if ( in_speed.active ) {
|
||||
speed = 0.001 * cls.frametime * cl_anglespeedkey->value;
|
||||
|
@ -305,6 +310,17 @@ void CL_AdjustAngles( void ) {
|
|||
|
||||
cl.viewangles[PITCH] -= speed*cl_pitchspeed->value * CL_KeyState (&in_lookup);
|
||||
cl.viewangles[PITCH] += speed*cl_pitchspeed->value * CL_KeyState (&in_lookdown);
|
||||
*/
|
||||
cl.viewangles[YAW] -= vr.hmdorientation_delta[YAW];
|
||||
|
||||
//Make angles good
|
||||
while (cl.viewangles[YAW] > 180.0f)
|
||||
cl.viewangles[YAW] -= 360.0f;
|
||||
while (cl.viewangles[YAW] < -180.0f)
|
||||
cl.viewangles[YAW] += 360.0f;
|
||||
|
||||
cl.viewangles[PITCH] = vr.hmdorientation[PITCH];
|
||||
cl.viewangles[ROLL] = vr.hmdorientation[ROLL];
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -354,6 +370,17 @@ void CL_KeyMove( usercmd_t *cmd ) {
|
|||
cmd->upmove = ClampChar( up );
|
||||
}
|
||||
|
||||
void CL_SnapTurn( int dxYaw )
|
||||
{
|
||||
cl.viewangles[YAW] -= dxYaw;
|
||||
|
||||
//Make angles good
|
||||
while (cl.viewangles[YAW] > 180.0f)
|
||||
cl.viewangles[YAW] -= 360.0f;
|
||||
while (cl.viewangles[YAW] < -180.0f)
|
||||
cl.viewangles[YAW] += 360.0f;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_MouseEvent
|
||||
|
@ -554,6 +581,7 @@ void CL_CmdButtons( usercmd_t *cmd ) {
|
|||
CL_FinishMove
|
||||
==============
|
||||
*/
|
||||
void rotateAboutOrigin(float x, float y, float rotation, vec2_t out);
|
||||
void CL_FinishMove( usercmd_t *cmd ) {
|
||||
int i;
|
||||
|
||||
|
@ -564,8 +592,26 @@ void CL_FinishMove( usercmd_t *cmd ) {
|
|||
// can be determined without allowing cheating
|
||||
cmd->serverTime = cl.serverTime;
|
||||
|
||||
for (i=0 ; i<3 ; i++) {
|
||||
cmd->angles[i] = ANGLE2SHORT(cl.viewangles[i]);
|
||||
//If we are running with a remote non-vr server, then the best we can do is pass the angles from the weapon
|
||||
//and adjust the move values accordingly, to "fake" a 3DoF weapon but keeping the movement correct
|
||||
if ( !com_sv_running || !com_sv_running->integer )
|
||||
{
|
||||
vec3_t angles;
|
||||
VectorCopy(vr.weaponangles, angles);
|
||||
angles[YAW] += cl.viewangles[YAW];
|
||||
for (i = 0; i < 3; i++) {
|
||||
cmd->angles[i] = ANGLE2SHORT(angles[i]);
|
||||
}
|
||||
|
||||
vec3_t out;
|
||||
rotateAboutOrigin(cmd->rightmove, cmd->forwardmove, cl.viewangles[YAW], out);
|
||||
cmd->rightmove = out[0];
|
||||
cmd->forwardmove = out[1];
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < 3; i++) {
|
||||
cmd->angles[i] = ANGLE2SHORT(cl.viewangles[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -602,9 +648,9 @@ usercmd_t CL_CreateCmd( void ) {
|
|||
cl.viewangles[PITCH] = oldAngles[PITCH] + 90;
|
||||
} else if ( oldAngles[PITCH] - cl.viewangles[PITCH] > 90 ) {
|
||||
cl.viewangles[PITCH] = oldAngles[PITCH] - 90;
|
||||
}
|
||||
}
|
||||
|
||||
// store out the final values
|
||||
// store out the final values
|
||||
CL_FinishMove( &cmd );
|
||||
|
||||
// draw debug graphs of turning for mouse testing
|
||||
|
@ -1000,6 +1046,8 @@ void CL_InitInput( void ) {
|
|||
|
||||
cl_nodelta = Cvar_Get ("cl_nodelta", "0", 0);
|
||||
cl_debugMove = Cvar_Get ("cl_debugMove", "0", 0);
|
||||
|
||||
IN_VRInit();
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -3544,7 +3544,7 @@ void CL_Init( void ) {
|
|||
cl_packetdup = Cvar_Get ("cl_packetdup", "1", CVAR_ARCHIVE );
|
||||
|
||||
cl_run = Cvar_Get ("cl_run", "1", CVAR_ARCHIVE);
|
||||
cl_sensitivity = Cvar_Get ("sensitivity", "5", CVAR_ARCHIVE);
|
||||
cl_sensitivity = Cvar_Get ("sensitivity", "8", CVAR_ARCHIVE);
|
||||
cl_mouseAccel = Cvar_Get ("cl_mouseAccel", "0", CVAR_ARCHIVE);
|
||||
cl_freelook = Cvar_Get( "cl_freelook", "1", CVAR_ARCHIVE );
|
||||
|
||||
|
@ -3590,8 +3590,8 @@ void CL_Init( void ) {
|
|||
|
||||
j_pitch = Cvar_Get ("j_pitch", "0.022", CVAR_ARCHIVE);
|
||||
j_yaw = Cvar_Get ("j_yaw", "-0.022", CVAR_ARCHIVE);
|
||||
j_forward = Cvar_Get ("j_forward", "-0.25", CVAR_ARCHIVE);
|
||||
j_side = Cvar_Get ("j_side", "0.25", CVAR_ARCHIVE);
|
||||
j_forward = Cvar_Get ("j_forward", "1.0", CVAR_ARCHIVE);
|
||||
j_side = Cvar_Get ("j_side", "1.0", CVAR_ARCHIVE);
|
||||
j_up = Cvar_Get ("j_up", "0", CVAR_ARCHIVE);
|
||||
|
||||
j_pitch_axis = Cvar_Get ("j_pitch_axis", "3", CVAR_ARCHIVE);
|
||||
|
@ -3618,7 +3618,7 @@ void CL_Init( void ) {
|
|||
cl_consoleKeys = Cvar_Get( "cl_consoleKeys", "~ ` 0x7e 0x60", CVAR_ARCHIVE);
|
||||
|
||||
// userinfo
|
||||
Cvar_Get ("name", "UnnamedPlayer", CVAR_USERINFO | CVAR_ARCHIVE );
|
||||
Cvar_Get ("name", "VR_Player", CVAR_USERINFO | CVAR_ARCHIVE );
|
||||
cl_rate = Cvar_Get ("rate", "25000", CVAR_USERINFO | CVAR_ARCHIVE );
|
||||
Cvar_Get ("snaps", "20", CVAR_USERINFO | CVAR_ARCHIVE );
|
||||
Cvar_Get ("model", "sarge", CVAR_USERINFO | CVAR_ARCHIVE );
|
||||
|
|
|
@ -514,6 +514,7 @@ void SCR_DrawScreenField( stereoFrame_t stereoFrame ) {
|
|||
break;
|
||||
case CA_LOADING:
|
||||
case CA_PRIMED:
|
||||
CL_CGameSetVRClientInfo();
|
||||
// draw the game information screen and loading progress
|
||||
CL_CGameRendering(stereoFrame);
|
||||
|
||||
|
@ -524,6 +525,7 @@ void SCR_DrawScreenField( stereoFrame_t stereoFrame ) {
|
|||
VM_Call( uivm, UI_DRAW_CONNECT_SCREEN, qtrue );
|
||||
break;
|
||||
case CA_ACTIVE:
|
||||
CL_CGameSetVRClientInfo();
|
||||
// always supply STEREO_CENTER as vieworg offset is now done by the engine.
|
||||
CL_CGameRendering(stereoFrame);
|
||||
SCR_DrawDemoRecording();
|
||||
|
|
|
@ -507,6 +507,8 @@ void CL_ReadPackets (void);
|
|||
void CL_WritePacket( void );
|
||||
void IN_CenterView (void);
|
||||
|
||||
void CL_CGameSetVRClientInfo();
|
||||
|
||||
void CL_VerifyCode( void );
|
||||
|
||||
float CL_KeyState (kbutton_t *key);
|
||||
|
|
|
@ -35,12 +35,12 @@ float pm_stopspeed = 100.0f;
|
|||
float pm_duckScale = 0.25f;
|
||||
float pm_swimScale = 0.50f;
|
||||
|
||||
float pm_accelerate = 10.0f;
|
||||
float pm_accelerate = 1000.0f;
|
||||
float pm_airaccelerate = 1.0f;
|
||||
float pm_wateraccelerate = 4.0f;
|
||||
float pm_flyaccelerate = 8.0f;
|
||||
|
||||
float pm_friction = 6.0f;
|
||||
float pm_friction = 10.0f;
|
||||
float pm_waterfriction = 1.0f;
|
||||
float pm_flightfriction = 3.0f;
|
||||
float pm_spectatorfriction = 5.0f;
|
||||
|
@ -1807,7 +1807,8 @@ void PM_UpdateViewAngles( playerState_t *ps, const usercmd_t *cmd ) {
|
|||
|
||||
// circularly clamp the angles with deltas
|
||||
for (i=0 ; i<3 ; i++) {
|
||||
temp = cmd->angles[i] + ps->delta_angles[i];
|
||||
//temp = cmd->angles[i] + ps->delta_angles[i];
|
||||
temp = cmd->angles[i] + (i == YAW ? ps->delta_angles[i] : 0);
|
||||
if ( i == PITCH ) {
|
||||
// don't let the player look up or down more than 90 degrees
|
||||
if ( temp > 16000 ) {
|
||||
|
|
|
@ -22,6 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
//
|
||||
|
||||
#include "g_local.h"
|
||||
#include "../vr/vr_clientinfo.h"
|
||||
|
||||
level_locals_t level;
|
||||
|
||||
|
@ -38,6 +39,8 @@ typedef struct {
|
|||
gentity_t g_entities[MAX_GENTITIES];
|
||||
gclient_t g_clients[MAX_CLIENTS];
|
||||
|
||||
vr_clientinfo_t* gVR;
|
||||
|
||||
vmCvar_t g_gametype;
|
||||
vmCvar_t g_dmflags;
|
||||
vmCvar_t g_fraglimit;
|
||||
|
@ -231,6 +234,11 @@ Q_EXPORT intptr_t vmMain( int command, int arg0, int arg1, int arg2, int arg3, i
|
|||
return ConsoleCommand();
|
||||
case BOTAI_START_FRAME:
|
||||
return BotAIStartFrame( arg0 );
|
||||
case GAME_SET_VR_CLIENT_INFO: {
|
||||
int ptr[2] = {arg0, arg1};
|
||||
gVR = (vr_clientinfo_t *) (*(long*)(ptr));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
|
|
@ -425,6 +425,8 @@ typedef enum {
|
|||
// The game can issue trap_argc() / trap_argv() commands to get the command
|
||||
// and parameters. Return qfalse if the game doesn't recognize it as a command.
|
||||
|
||||
BOTAI_START_FRAME // ( int time );
|
||||
BOTAI_START_FRAME, // ( int time );
|
||||
|
||||
GAME_SET_VR_CLIENT_INFO
|
||||
} gameExport_t;
|
||||
|
||||
|
|
|
@ -25,12 +25,43 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
|
||||
#include "g_local.h"
|
||||
|
||||
#include "../vr/vr_clientinfo.h"
|
||||
|
||||
static float s_quadFactor;
|
||||
static vec3_t forward, right, up;
|
||||
static vec3_t muzzle;
|
||||
|
||||
extern vr_clientinfo_t* gVR;
|
||||
|
||||
#define NUM_NAILSHOTS 15
|
||||
|
||||
|
||||
void rotateAboutOrigin(float x, float y, float rotation, vec2_t out)
|
||||
{
|
||||
out[0] = cosf(DEG2RAD(-rotation)) * x + sinf(DEG2RAD(-rotation)) * y;
|
||||
out[1] = cosf(DEG2RAD(-rotation)) * y - sinf(DEG2RAD(-rotation)) * x;
|
||||
}
|
||||
|
||||
void convertFromVR(gentity_t *ent, vec3_t in, vec3_t offset, vec3_t out)
|
||||
{
|
||||
vec3_t vrSpace;
|
||||
VectorSet(vrSpace, in[2], in[0], in[1] );
|
||||
|
||||
vec2_t r;
|
||||
rotateAboutOrigin(vrSpace[0], vrSpace[1], ent->client->ps.viewangles[YAW] - gVR->hmdorientation[YAW], r);
|
||||
vrSpace[0] = -r[0];
|
||||
vrSpace[1] = -r[1];
|
||||
|
||||
vec3_t temp;
|
||||
VectorScale(vrSpace, WORLD_SCALE, temp);
|
||||
|
||||
if (offset) {
|
||||
VectorAdd(temp, offset, out);
|
||||
} else {
|
||||
VectorCopy(temp, out);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
G_BounceProjectile
|
||||
|
@ -770,9 +801,19 @@ set muzzle location relative to pivoting eye
|
|||
===============
|
||||
*/
|
||||
void CalcMuzzlePoint ( gentity_t *ent, vec3_t forward, vec3_t right, vec3_t up, vec3_t muzzlePoint ) {
|
||||
VectorCopy( ent->s.pos.trBase, muzzlePoint );
|
||||
muzzlePoint[2] += ent->client->ps.viewheight;
|
||||
VectorMA( muzzlePoint, 14, forward, muzzlePoint );
|
||||
if ( ( ent->r.svFlags & SVF_BOT ) )
|
||||
{
|
||||
VectorCopy( ent->s.pos.trBase, muzzlePoint );
|
||||
muzzlePoint[2] += ent->client->ps.viewheight;
|
||||
VectorMA( muzzlePoint, 14, forward, muzzlePoint );
|
||||
}
|
||||
else if (gVR != NULL)
|
||||
{
|
||||
convertFromVR(ent, gVR->calculated_weaponoffset, ent->r.currentOrigin, muzzlePoint);
|
||||
muzzlePoint[2] -= ent->client->ps.viewheight;
|
||||
muzzlePoint[2] += gVR->hmdposition[1] * WORLD_SCALE;
|
||||
}
|
||||
|
||||
// snap to integer coordinates for more efficient network bandwidth usage
|
||||
SnapVector( muzzlePoint );
|
||||
}
|
||||
|
@ -785,11 +826,7 @@ set muzzle location relative to pivoting eye
|
|||
===============
|
||||
*/
|
||||
void CalcMuzzlePointOrigin ( gentity_t *ent, vec3_t origin, vec3_t forward, vec3_t right, vec3_t up, vec3_t muzzlePoint ) {
|
||||
VectorCopy( ent->s.pos.trBase, muzzlePoint );
|
||||
muzzlePoint[2] += ent->client->ps.viewheight;
|
||||
VectorMA( muzzlePoint, 14, forward, muzzlePoint );
|
||||
// snap to integer coordinates for more efficient network bandwidth usage
|
||||
SnapVector( muzzlePoint );
|
||||
CalcMuzzlePoint(ent, forward, right, up, muzzlePoint);
|
||||
}
|
||||
|
||||
|
||||
|
@ -824,8 +861,19 @@ void FireWeapon( gentity_t *ent ) {
|
|||
#endif
|
||||
}
|
||||
|
||||
vec3_t viewang;
|
||||
if ( !( ent->r.svFlags & SVF_BOT ) && gVR != NULL)
|
||||
{
|
||||
VectorCopy(gVR->weaponangles, viewang);
|
||||
viewang[YAW] += ent->client->ps.viewangles[YAW] - gVR->hmdorientation[YAW];
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorCopy( ent->client->ps.viewangles, viewang );
|
||||
}
|
||||
|
||||
// set aiming directions
|
||||
AngleVectors (ent->client->ps.viewangles, forward, right, up);
|
||||
AngleVectors (viewang, forward, right, up);
|
||||
|
||||
CalcMuzzlePointOrigin ( ent, ent->client->oldOrigin, forward, right, up, muzzle );
|
||||
|
||||
|
|
|
@ -368,6 +368,8 @@ typedef vec_t vec3_t[3];
|
|||
typedef vec_t vec4_t[4];
|
||||
typedef vec_t vec5_t[5];
|
||||
|
||||
typedef vec_t matrix4x4[4][4];
|
||||
|
||||
typedef vec_t quat_t[4];
|
||||
|
||||
typedef int fixed4_t;
|
||||
|
|
|
@ -991,6 +991,8 @@ void CL_KeyEvent (int key, qboolean down, unsigned time);
|
|||
void CL_CharEvent( int key );
|
||||
// char events are for field typing, not game control
|
||||
|
||||
void CL_SnapTurn(int dx);
|
||||
|
||||
void CL_MouseEvent( int dx, int dy, int time );
|
||||
|
||||
void CL_JoystickEvent( int axis, int value, int time );
|
||||
|
|
|
@ -276,7 +276,7 @@ void GL_SetProjectionMatrix(mat4_t matrix)
|
|||
|
||||
void GL_SetModelviewMatrix(mat4_t matrix, qboolean applyStereoView)
|
||||
{
|
||||
if (applyStereoView)
|
||||
if (qfalse) //applyStereoView)
|
||||
{
|
||||
if (tr.refdef.stereoFrame == STEREO_LEFT) {
|
||||
Mat4Multiply(tr.vrParms.viewL, matrix, glState.modelview);
|
||||
|
|
|
@ -573,7 +573,7 @@ void RE_EndFrame( int *frontEndMsec, int *backEndMsec ) {
|
|||
backEnd.pc.msec = 0;
|
||||
}
|
||||
|
||||
#if __ANDROID__
|
||||
//#if __ANDROID__
|
||||
void R_Mat4Transpose( const float in[4][4], float* out ) {
|
||||
int i, j;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
|
@ -583,14 +583,17 @@ void R_Mat4Transpose( const float in[4][4], float* out ) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void RE_SetVRHeadsetParms( const ovrTracking2* tracking, int renderBufferL, int renderBufferR ) {
|
||||
if (tracking) {
|
||||
R_Mat4Transpose(tracking->Eye[0].ProjectionMatrix.M, tr.vrParms.projectionL);
|
||||
R_Mat4Transpose(tracking->Eye[1].ProjectionMatrix.M, tr.vrParms.projectionR);
|
||||
|
||||
/*
|
||||
R_Mat4Transpose(tracking->Eye[0].ViewMatrix.M, tr.vrParms.viewL);
|
||||
R_Mat4Transpose(tracking->Eye[1].ViewMatrix.M, tr.vrParms.viewR);
|
||||
|
||||
const float worldToMeter = 25.0f; // https://quakewiki.org/wiki/unit, assume 25 units is 1 meter.
|
||||
const float worldToMeter = 37.0f; // https://quakewiki.org/wiki/unit, assume 25 units is 1 meter.
|
||||
tr.vrParms.viewL[12] *= worldToMeter;
|
||||
tr.vrParms.viewL[13] *= worldToMeter;
|
||||
tr.vrParms.viewL[14] *= worldToMeter;
|
||||
|
@ -598,6 +601,8 @@ void RE_SetVRHeadsetParms( const ovrTracking2* tracking, int renderBufferL, int
|
|||
tr.vrParms.viewR[13] *= worldToMeter;
|
||||
tr.vrParms.viewR[14] *= worldToMeter;
|
||||
|
||||
*/
|
||||
|
||||
tr.vrParms.renderBufferL = renderBufferL;
|
||||
tr.vrParms.renderBufferR = renderBufferR;
|
||||
|
||||
|
@ -606,7 +611,7 @@ void RE_SetVRHeadsetParms( const ovrTracking2* tracking, int renderBufferL, int
|
|||
tr.vrParms.valid = qfalse;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
//#endif
|
||||
|
||||
/*
|
||||
=============
|
||||
|
|
|
@ -34,6 +34,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
#include "../renderercommon/tr_common.h"
|
||||
#include "../sys/sys_local.h"
|
||||
#include "sdl_icon.h"
|
||||
#include "../vr/vr_renderer.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
@ -429,8 +430,11 @@ static int GLimp_SetMode(int mode, qboolean fullscreen, qboolean noborder, qbool
|
|||
|
||||
ri.Printf (PRINT_ALL, "...setting mode %d:", mode );
|
||||
|
||||
VR_GetRsolution(0, &glConfig.vidWidth, &glConfig.vidHeight);
|
||||
/*
|
||||
if (mode == -2)
|
||||
{
|
||||
|
||||
// use desktop video resolution
|
||||
if( desktopMode.h > 0 )
|
||||
{
|
||||
|
@ -444,6 +448,7 @@ static int GLimp_SetMode(int mode, qboolean fullscreen, qboolean noborder, qbool
|
|||
ri.Printf( PRINT_ALL,
|
||||
"Cannot determine display resolution, assuming 640x480\n" );
|
||||
}
|
||||
|
||||
|
||||
glConfig.windowAspect = (float)glConfig.vidWidth / (float)glConfig.vidHeight;
|
||||
}
|
||||
|
@ -452,6 +457,7 @@ static int GLimp_SetMode(int mode, qboolean fullscreen, qboolean noborder, qbool
|
|||
ri.Printf( PRINT_ALL, " invalid mode\n" );
|
||||
return RSERR_INVALID_MODE;
|
||||
}
|
||||
*/
|
||||
ri.Printf( PRINT_ALL, " %d %d\n", glConfig.vidWidth, glConfig.vidHeight);
|
||||
|
||||
// Center window
|
||||
|
|
|
@ -21,6 +21,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
*/
|
||||
|
||||
#include "server.h"
|
||||
#include "../vr/vr_clientinfo.h"
|
||||
|
||||
#ifdef USE_VOIP
|
||||
cvar_t *sv_voip;
|
||||
|
@ -30,6 +31,7 @@ cvar_t *sv_voipProtocol;
|
|||
serverStatic_t svs; // persistant server info
|
||||
server_t sv; // local server
|
||||
vm_t *gvm = NULL; // game virtual machine
|
||||
extern vr_clientinfo_t vr;
|
||||
|
||||
cvar_t *sv_fps = NULL; // time rate for running non-clients
|
||||
cvar_t *sv_timeout; // seconds without any message
|
||||
|
@ -1128,6 +1130,11 @@ void SV_Frame( int msec ) {
|
|||
startTime = 0; // quite a compiler warning
|
||||
}
|
||||
|
||||
//Ensure the game library has our VR client info
|
||||
long val = (long)(&vr);
|
||||
int *ptr = (int*)(&val); //HACK!!
|
||||
VM_Call( gvm, GAME_SET_VR_CLIENT_INFO, ptr[0], ptr[1] );
|
||||
|
||||
// update ping based on the all received frames
|
||||
SV_CalcPings();
|
||||
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
#include "vr_base.h"
|
||||
#include "VrApi_Types.h"
|
||||
#include "../VrApi/Include/VrApi_Types.h"
|
||||
#include "../qcommon/q_shared.h"
|
||||
#include "../qcommon/qcommon.h"
|
||||
#include "../client/client.h"
|
||||
|
||||
#if __ANDROID__
|
||||
//#if __ANDROID__
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wstrict-prototypes"
|
||||
#include <VrApi_Helpers.h>
|
||||
#include "../VrApi/Include/VrApi_Helpers.h"
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
@ -24,6 +27,8 @@ engine_t* VR_Init( ovrJava java )
|
|||
initParams = vrapi_DefaultInitParms(&java);
|
||||
initResult = vrapi_Initialize(&initParams);
|
||||
assert(initResult == VRAPI_INITIALIZE_SUCCESS);
|
||||
|
||||
vr_engine.java = java;
|
||||
|
||||
return &vr_engine;
|
||||
}
|
||||
|
@ -45,7 +50,7 @@ void VR_EnterVR( engine_t* engine, ovrJava java ) {
|
|||
engine->ovr = vrapi_EnterVrMode(&modeParams);
|
||||
engine->frameIndex = 0;
|
||||
|
||||
vrapi_SetTrackingSpace(engine->ovr, VRAPI_TRACKING_SPACE_LOCAL);
|
||||
vrapi_SetTrackingSpace(engine->ovr, VRAPI_TRACKING_SPACE_LOCAL_FLOOR);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,4 +64,11 @@ void VR_LeaveVR( engine_t* engine ) {
|
|||
engine_t* VR_GetEngine( void ) {
|
||||
return &vr_engine;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool VR_useScreenLayer( void )
|
||||
{
|
||||
return (bool)(clc.state != CA_ACTIVE ||
|
||||
( Key_GetCatcher( ) & KEYCATCH_UI ) ||
|
||||
( Key_GetCatcher( ) & KEYCATCH_CONSOLE ));
|
||||
}
|
||||
//#endif
|
||||
|
|
|
@ -5,12 +5,16 @@
|
|||
|
||||
#include "vr_types.h"
|
||||
|
||||
#define WORLD_SCALE 37.5f
|
||||
#define PLAYER_HEIGHT 48
|
||||
|
||||
engine_t* VR_Init( ovrJava java );
|
||||
void VR_Destroy( engine_t* engine );
|
||||
void VR_EnterVR( engine_t* engine, ovrJava java );
|
||||
void VR_LeaveVR( engine_t* engine );
|
||||
|
||||
engine_t* VR_GetEngine( void );
|
||||
bool VR_useScreenLayer( void );
|
||||
|
||||
#endif
|
||||
|
||||
|
|
50
code/vr/vr_clientinfo.h
Normal file
50
code/vr/vr_clientinfo.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
#if !defined(vr_clientinfo_h)
|
||||
#define vr_clientinfo_h
|
||||
|
||||
#include "vr_base.h"
|
||||
|
||||
#define NUM_WEAPON_SAMPLES 10
|
||||
#define WEAPON_RECOIL 15.0f;
|
||||
|
||||
typedef struct {
|
||||
qboolean weapon_stabilised;
|
||||
qboolean right_handed;
|
||||
qboolean player_moving;
|
||||
qboolean visible_hud;
|
||||
qboolean dualwield;
|
||||
int weaponid;
|
||||
int lastweaponid;
|
||||
|
||||
vec3_t hmdposition;
|
||||
vec3_t hmdposition_last; // Don't use this, it is just for calculating delta!
|
||||
vec3_t hmdposition_delta;
|
||||
|
||||
vec3_t hmdorientation;
|
||||
vec3_t hmdorientation_last; // Don't use this, it is just for calculating delta!
|
||||
vec3_t hmdorientation_delta;
|
||||
|
||||
vec3_t weaponangles;
|
||||
vec3_t weaponangles_last; // Don't use this, it is just for calculating delta!
|
||||
vec3_t weaponangles_delta;
|
||||
|
||||
vec3_t current_weaponoffset;
|
||||
vec3_t calculated_weaponoffset;
|
||||
float current_weaponoffset_timestamp;
|
||||
vec3_t weaponoffset_history[NUM_WEAPON_SAMPLES];
|
||||
float weaponoffset_history_timestamp[NUM_WEAPON_SAMPLES];
|
||||
|
||||
vec3_t offhandangles;
|
||||
vec3_t offhandoffset;
|
||||
|
||||
//////////////////////////////////////
|
||||
// Test stuff for weapon alignment
|
||||
//////////////////////////////////////
|
||||
|
||||
char test_name[256];
|
||||
float test_scale;
|
||||
vec3_t test_angles;
|
||||
vec3_t test_offset;
|
||||
|
||||
} vr_clientinfo_t;
|
||||
|
||||
#endif //vr_clientinfo_h
|
|
@ -1,12 +1,15 @@
|
|||
#include "vr_input.h"
|
||||
|
||||
#if __ANDROID__
|
||||
//#if __ANDROID__
|
||||
|
||||
#include "../qcommon/q_shared.h"
|
||||
#include "../qcommon/qcommon.h"
|
||||
#include "../client/keycodes.h"
|
||||
#include "vr_base.h"
|
||||
#include "VrApi_Input.h"
|
||||
#include "../VrApi/Include/VrApi_Input.h"
|
||||
#include "../VrApi/Include/VrApi_Helpers.h"
|
||||
#include "vr_clientinfo.h"
|
||||
|
||||
|
||||
#ifdef USE_LOCAL_HEADERS
|
||||
# include "SDL.h"
|
||||
|
@ -27,6 +30,8 @@ typedef struct {
|
|||
uint32_t axisButtons;
|
||||
} vrController_t;
|
||||
|
||||
vr_clientinfo_t vr;
|
||||
|
||||
static qboolean controllerInit = qfalse;
|
||||
|
||||
static vrController_t leftController;
|
||||
|
@ -40,49 +45,261 @@ extern cvar_t *cl_sensitivity;
|
|||
extern cvar_t *m_pitch;
|
||||
extern cvar_t *m_yaw;
|
||||
|
||||
cvar_t *vr_righthanded;
|
||||
cvar_t *vr_snapturn;
|
||||
|
||||
|
||||
float radians(float deg) {
|
||||
return (deg * M_PI) / 180.0;
|
||||
}
|
||||
|
||||
float degrees(float rad) {
|
||||
return (rad * 180.0) / M_PI;
|
||||
}
|
||||
|
||||
|
||||
#ifndef EPSILON
|
||||
#define EPSILON 0.001f
|
||||
#endif
|
||||
|
||||
void rotateAboutOrigin(float x, float y, float rotation, vec2_t out)
|
||||
{
|
||||
out[0] = cosf(DEG2RAD(-rotation)) * x + sinf(DEG2RAD(-rotation)) * y;
|
||||
out[1] = cosf(DEG2RAD(-rotation)) * y - sinf(DEG2RAD(-rotation)) * x;
|
||||
}
|
||||
|
||||
static ovrVector3f normalizeVec(ovrVector3f vec) {
|
||||
//NOTE: leave w-component untouched
|
||||
//@@const float EPSILON = 0.000001f;
|
||||
float xxyyzz = vec.x*vec.x + vec.y*vec.y + vec.z*vec.z;
|
||||
//@@if(xxyyzz < EPSILON)
|
||||
//@@ return *this; // do nothing if it is zero vector
|
||||
|
||||
//float invLength = invSqrt(xxyyzz);
|
||||
ovrVector3f result;
|
||||
float invLength = 1.0f / sqrtf(xxyyzz);
|
||||
result.x = vec.x * invLength;
|
||||
result.y = vec.y * invLength;
|
||||
result.z = vec.z * invLength;
|
||||
return result;
|
||||
}
|
||||
|
||||
void NormalizeAngles(vec3_t angles)
|
||||
{
|
||||
while (angles[0] >= 90) angles[0] -= 180;
|
||||
while (angles[1] >= 180) angles[1] -= 360;
|
||||
while (angles[2] >= 180) angles[2] -= 360;
|
||||
while (angles[0] < -90) angles[0] += 180;
|
||||
while (angles[1] < -180) angles[1] += 360;
|
||||
while (angles[2] < -180) angles[2] += 360;
|
||||
}
|
||||
|
||||
void GetAnglesFromVectors(const ovrVector3f forward, const ovrVector3f right, const ovrVector3f up, vec3_t angles)
|
||||
{
|
||||
float sr, sp, sy, cr, cp, cy;
|
||||
|
||||
sp = -forward.z;
|
||||
|
||||
float cp_x_cy = forward.x;
|
||||
float cp_x_sy = forward.y;
|
||||
float cp_x_sr = -right.z;
|
||||
float cp_x_cr = up.z;
|
||||
|
||||
float yaw = atan2(cp_x_sy, cp_x_cy);
|
||||
float roll = atan2(cp_x_sr, cp_x_cr);
|
||||
|
||||
cy = cos(yaw);
|
||||
sy = sin(yaw);
|
||||
cr = cos(roll);
|
||||
sr = sin(roll);
|
||||
|
||||
if (fabs(cy) > EPSILON)
|
||||
{
|
||||
cp = cp_x_cy / cy;
|
||||
}
|
||||
else if (fabs(sy) > EPSILON)
|
||||
{
|
||||
cp = cp_x_sy / sy;
|
||||
}
|
||||
else if (fabs(sr) > EPSILON)
|
||||
{
|
||||
cp = cp_x_sr / sr;
|
||||
}
|
||||
else if (fabs(cr) > EPSILON)
|
||||
{
|
||||
cp = cp_x_cr / cr;
|
||||
}
|
||||
else
|
||||
{
|
||||
cp = cos(asin(sp));
|
||||
}
|
||||
|
||||
float pitch = atan2(sp, cp);
|
||||
|
||||
angles[0] = pitch / (M_PI*2.f / 360.f);
|
||||
angles[1] = yaw / (M_PI*2.f / 360.f);
|
||||
angles[2] = roll / (M_PI*2.f / 360.f);
|
||||
|
||||
NormalizeAngles(angles);
|
||||
}
|
||||
|
||||
void QuatToYawPitchRoll(ovrQuatf q, vec3_t rotation, vec3_t out) {
|
||||
|
||||
ovrMatrix4f mat = ovrMatrix4f_CreateFromQuaternion( &q );
|
||||
|
||||
if (rotation[0] != 0.0f || rotation[1] != 0.0f || rotation[2] != 0.0f)
|
||||
{
|
||||
ovrMatrix4f rot = ovrMatrix4f_CreateRotation(radians(rotation[0]), radians(rotation[1]), radians(rotation[2]));
|
||||
mat = ovrMatrix4f_Multiply(&mat, &rot);
|
||||
}
|
||||
|
||||
ovrVector4f v1 = {0, 0, -1, 0};
|
||||
ovrVector4f v2 = {1, 0, 0, 0};
|
||||
ovrVector4f v3 = {0, 1, 0, 0};
|
||||
|
||||
ovrVector4f forwardInVRSpace = ovrVector4f_MultiplyMatrix4f(&mat, &v1);
|
||||
ovrVector4f rightInVRSpace = ovrVector4f_MultiplyMatrix4f(&mat, &v2);
|
||||
ovrVector4f upInVRSpace = ovrVector4f_MultiplyMatrix4f(&mat, &v3);
|
||||
|
||||
ovrVector3f forward = {-forwardInVRSpace.z, -forwardInVRSpace.x, forwardInVRSpace.y};
|
||||
ovrVector3f right = {-rightInVRSpace.z, -rightInVRSpace.x, rightInVRSpace.y};
|
||||
ovrVector3f up = {-upInVRSpace.z, -upInVRSpace.x, upInVRSpace.y};
|
||||
|
||||
ovrVector3f forwardNormal = normalizeVec(forward);
|
||||
ovrVector3f rightNormal = normalizeVec(right);
|
||||
ovrVector3f upNormal = normalizeVec(up);
|
||||
|
||||
GetAnglesFromVectors(forwardNormal, rightNormal, upNormal, out);
|
||||
}
|
||||
|
||||
void sendButtonActionSimple(const char* action)
|
||||
{
|
||||
char command[256];
|
||||
snprintf( command, sizeof( command ), "%s\n", action );
|
||||
Cbuf_AddText( command );
|
||||
}
|
||||
|
||||
|
||||
void IN_VRInit( void )
|
||||
{
|
||||
vr_righthanded = Cvar_Get ("vr_righthanded", "1", CVAR_ARCHIVE);
|
||||
vr_snapturn = Cvar_Get ("vr_snapturn", "1", CVAR_ARCHIVE);
|
||||
|
||||
Cvar_Get ("vr_weapon_adjustment_1", "0.8,0,0,0,0,0,0", CVAR_ARCHIVE);
|
||||
Cvar_Get ("vr_weapon_adjustment_2", "0.8,0,0,0,0,0,0", CVAR_ARCHIVE);
|
||||
Cvar_Get ("vr_weapon_adjustment_3", "0.8,0,0,0,0,0,0", CVAR_ARCHIVE);
|
||||
}
|
||||
|
||||
static void IN_VRController( qboolean isRightController, ovrTracking remoteTracking )
|
||||
{
|
||||
if (isRightController == (vr_righthanded->integer != 0))
|
||||
{
|
||||
//Set gun angles - We need to calculate all those we might need (including adjustments) for the client to then take its pick
|
||||
vec3_t rotation = {0};
|
||||
rotation[PITCH] =-20.0f;
|
||||
QuatToYawPitchRoll(remoteTracking.HeadPose.Pose.Orientation, rotation, vr.weaponangles);
|
||||
|
||||
VectorSubtract(vr.weaponangles_last, vr.weaponangles, vr.weaponangles_delta);
|
||||
VectorCopy(vr.weaponangles, vr.weaponangles_last);
|
||||
|
||||
|
||||
//Record recent weapon position for trajectory based stuff
|
||||
for (int i = (NUM_WEAPON_SAMPLES-1); i != 0; --i)
|
||||
{
|
||||
VectorCopy(vr.weaponoffset_history[i-1], vr.weaponoffset_history[i]);
|
||||
vr.weaponoffset_history_timestamp[i] = vr.weaponoffset_history_timestamp[i-1];
|
||||
}
|
||||
VectorCopy(vr.current_weaponoffset, vr.weaponoffset_history[0]);
|
||||
vr.weaponoffset_history_timestamp[0] = vr.current_weaponoffset_timestamp;
|
||||
|
||||
///Weapon location relative to view
|
||||
vr.current_weaponoffset[0] = remoteTracking.HeadPose.Pose.Position.x - vr.hmdposition[0];
|
||||
vr.current_weaponoffset[1] = remoteTracking.HeadPose.Pose.Position.y - vr.hmdposition[1];
|
||||
vr.current_weaponoffset[2] = remoteTracking.HeadPose.Pose.Position.z - vr.hmdposition[2];
|
||||
vr.current_weaponoffset_timestamp = Sys_Milliseconds( );
|
||||
|
||||
//Just copy to calculated offset, used to use this in case we wanted to apply any modifiers, but don't any more
|
||||
VectorCopy(vr.current_weaponoffset, vr.calculated_weaponoffset);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void IN_VRJoystick( qboolean isRightController, float joystickX, float joystickY )
|
||||
{
|
||||
vrController_t* controller = isRightController == qtrue ? &rightController : &leftController;
|
||||
|
||||
// Menu controls mapped to keyboard codes...
|
||||
if (isRightController == qfalse) {
|
||||
if (!(controller->axisButtons & VR_TOUCH_AXIS_UP) && joystickY > pressedThreshold) {
|
||||
controller->axisButtons |= VR_TOUCH_AXIS_UP;
|
||||
Com_QueueEvent(in_vrEventTime, SE_KEY, K_UPARROW, qtrue, 0, NULL);
|
||||
} else if ((controller->axisButtons & VR_TOUCH_AXIS_UP) && joystickY < releasedThreshold) {
|
||||
controller->axisButtons &= ~VR_TOUCH_AXIS_UP;
|
||||
Com_QueueEvent(in_vrEventTime, SE_KEY, K_UPARROW, qfalse, 0, NULL);
|
||||
}
|
||||
//Positional movement speed correction for when we are not hitting target framerate
|
||||
static double lastframetime = 0;
|
||||
int refresh = vrapi_GetSystemPropertyInt(&(VR_GetEngine()->java), VRAPI_SYS_PROP_DISPLAY_REFRESH_RATE);
|
||||
double newframetime = Sys_Milliseconds();
|
||||
float multiplier = (float)((1000.0 / refresh) / (newframetime - lastframetime));
|
||||
lastframetime = newframetime;
|
||||
|
||||
if (!(controller->axisButtons & VR_TOUCH_AXIS_DOWN) && joystickY < -pressedThreshold) {
|
||||
controller->axisButtons |= VR_TOUCH_AXIS_DOWN;
|
||||
Com_QueueEvent(in_vrEventTime, SE_KEY, K_DOWNARROW, qtrue, 0, NULL);
|
||||
} else if ((controller->axisButtons & VR_TOUCH_AXIS_DOWN) && joystickY > -releasedThreshold) {
|
||||
controller->axisButtons &= ~VR_TOUCH_AXIS_DOWN;
|
||||
Com_QueueEvent(in_vrEventTime, SE_KEY, K_DOWNARROW, qfalse, 0, NULL);
|
||||
}
|
||||
vec2_t positional;
|
||||
float factor = (refresh / 72.0F) * 12.0f; // adjust positional factor based on refresh rate
|
||||
rotateAboutOrigin(-vr.hmdposition_delta[0] * factor * multiplier,
|
||||
vr.hmdposition_delta[2] * factor * multiplier, - vr.hmdorientation[YAW], positional);
|
||||
|
||||
if (!(controller->axisButtons & VR_TOUCH_AXIS_LEFT) && joystickX < -pressedThreshold) {
|
||||
controller->axisButtons |= VR_TOUCH_AXIS_LEFT;
|
||||
Com_QueueEvent(in_vrEventTime, SE_KEY, K_LEFTARROW, qtrue, 0, NULL);
|
||||
} else if ((controller->axisButtons & VR_TOUCH_AXIS_LEFT) && joystickX > -releasedThreshold) {
|
||||
controller->axisButtons &= ~VR_TOUCH_AXIS_LEFT;
|
||||
Com_QueueEvent(in_vrEventTime, SE_KEY, K_LEFTARROW, qfalse, 0, NULL);
|
||||
}
|
||||
if (VR_useScreenLayer())
|
||||
{
|
||||
const float x = joystickX * 4.0;
|
||||
const float y = joystickY * -4.0;
|
||||
|
||||
if (!(controller->axisButtons & VR_TOUCH_AXIS_RIGHT) && joystickX > pressedThreshold) {
|
||||
controller->axisButtons |= VR_TOUCH_AXIS_RIGHT;
|
||||
Com_QueueEvent(in_vrEventTime, SE_KEY, K_RIGHTARROW, qtrue, 0, NULL);
|
||||
} else if ((controller->axisButtons & VR_TOUCH_AXIS_RIGHT) && joystickX < releasedThreshold) {
|
||||
controller->axisButtons &= ~VR_TOUCH_AXIS_RIGHT;
|
||||
Com_QueueEvent(in_vrEventTime, SE_KEY, K_RIGHTARROW, qfalse, 0, NULL);
|
||||
}
|
||||
} else {
|
||||
const float sensitivity = cl_sensitivity->value;
|
||||
const float x = joystickX * sensitivity * m_yaw->value;
|
||||
const float y = joystickY * sensitivity * -m_pitch->value;
|
||||
Com_QueueEvent(in_vrEventTime, SE_MOUSE, x, y, 0, NULL);
|
||||
}
|
||||
} else
|
||||
{
|
||||
if (isRightController == qfalse) {
|
||||
//sideways
|
||||
Com_QueueEvent(in_vrEventTime, SE_JOYSTICK_AXIS, 0, joystickX * 127.0f + positional[0] * 127.0f, 0, NULL);
|
||||
|
||||
//forward/back
|
||||
Com_QueueEvent(in_vrEventTime, SE_JOYSTICK_AXIS, 1, joystickY * 127.0f + positional[1] * 127.0f, 0, NULL);
|
||||
}
|
||||
else //right controller
|
||||
{
|
||||
//yaw
|
||||
if (vr_snapturn->integer)
|
||||
{
|
||||
if (!(controller->axisButtons & VR_TOUCH_AXIS_RIGHT) && joystickX > pressedThreshold) {
|
||||
controller->axisButtons |= VR_TOUCH_AXIS_RIGHT;
|
||||
CL_SnapTurn(45);
|
||||
} else if ((controller->axisButtons & VR_TOUCH_AXIS_RIGHT) &&
|
||||
joystickX < releasedThreshold) {
|
||||
controller->axisButtons &= ~VR_TOUCH_AXIS_RIGHT;
|
||||
}
|
||||
|
||||
if (!(controller->axisButtons & VR_TOUCH_AXIS_LEFT) && joystickX < -pressedThreshold) {
|
||||
controller->axisButtons |= VR_TOUCH_AXIS_LEFT;
|
||||
CL_SnapTurn(-45);
|
||||
} else if ((controller->axisButtons & VR_TOUCH_AXIS_LEFT) &&
|
||||
joystickX > -releasedThreshold) {
|
||||
controller->axisButtons &= ~VR_TOUCH_AXIS_LEFT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//smooth turn
|
||||
const float x = joystickX * cl_sensitivity->value * m_yaw->value;
|
||||
Com_QueueEvent(in_vrEventTime, SE_MOUSE, x, 0, 0, NULL);
|
||||
}
|
||||
|
||||
if (!(controller->axisButtons & VR_TOUCH_AXIS_UP) && joystickY > pressedThreshold) {
|
||||
controller->axisButtons |= VR_TOUCH_AXIS_UP;
|
||||
sendButtonActionSimple("weapnext");
|
||||
} else if ((controller->axisButtons & VR_TOUCH_AXIS_UP) &&
|
||||
joystickY < releasedThreshold) {
|
||||
controller->axisButtons &= ~VR_TOUCH_AXIS_UP;
|
||||
}
|
||||
|
||||
if (!(controller->axisButtons & VR_TOUCH_AXIS_DOWN) && joystickY < -pressedThreshold) {
|
||||
controller->axisButtons |= VR_TOUCH_AXIS_DOWN;
|
||||
sendButtonActionSimple("weapprev");
|
||||
} else if ((controller->axisButtons & VR_TOUCH_AXIS_DOWN) &&
|
||||
joystickY > -releasedThreshold) {
|
||||
controller->axisButtons &= ~VR_TOUCH_AXIS_DOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void IN_VRTriggers( qboolean isRightController, float index ) {
|
||||
|
@ -103,16 +320,25 @@ static void IN_VRButtonsChanged( qboolean isRightController, uint32_t buttons )
|
|||
{
|
||||
vrController_t* controller = isRightController == qtrue ? &rightController : &leftController;
|
||||
|
||||
if (isRightController == qfalse)
|
||||
{
|
||||
if ((buttons & ovrButton_Enter) && !(controller->buttons & ovrButton_Enter)) {
|
||||
Com_QueueEvent(in_vrEventTime, SE_KEY, K_ESCAPE, qtrue, 0, NULL);
|
||||
} else if (!(buttons & ovrButton_Enter) && (controller->buttons & ovrButton_Enter)) {
|
||||
Com_QueueEvent(in_vrEventTime, SE_KEY, K_ESCAPE, qfalse, 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if ((buttons & ovrButton_A) && !(controller->buttons & ovrButton_A)) {
|
||||
Com_QueueEvent(in_vrEventTime, SE_KEY, K_PAD0_A, qtrue, 0, NULL);
|
||||
Com_QueueEvent(in_vrEventTime, SE_KEY, K_SPACE, qtrue, 0, NULL);
|
||||
} else if (!(buttons & ovrButton_A) && (controller->buttons & ovrButton_A)) {
|
||||
Com_QueueEvent(in_vrEventTime, SE_KEY, K_PAD0_A, qfalse, 0, NULL);
|
||||
Com_QueueEvent(in_vrEventTime, SE_KEY, K_SPACE, qfalse, 0, NULL);
|
||||
}
|
||||
|
||||
if ((buttons & ovrButton_B) && !(controller->buttons & ovrButton_B)) {
|
||||
Com_QueueEvent(in_vrEventTime, SE_KEY, K_PAD0_B, qtrue, 0, NULL);
|
||||
Com_QueueEvent(in_vrEventTime, SE_KEY, K_ENTER, qtrue, 0, NULL);
|
||||
} else if (!(buttons & ovrButton_B) && (controller->buttons & ovrButton_B)) {
|
||||
Com_QueueEvent(in_vrEventTime, SE_KEY, K_PAD0_B, qfalse, 0, NULL);
|
||||
Com_QueueEvent(in_vrEventTime, SE_KEY, K_ENTER, qfalse, 0, NULL);
|
||||
}
|
||||
|
||||
if ((buttons & ovrButton_X) && !(controller->buttons & ovrButton_B)) {
|
||||
|
@ -143,6 +369,32 @@ void IN_VRInputFrame( void )
|
|||
return;
|
||||
}
|
||||
|
||||
double predictedDisplayTime = vrapi_GetPredictedDisplayTime(ovr, VR_GetEngine()->frameIndex);
|
||||
|
||||
{
|
||||
// We extract Yaw, Pitch, Roll instead of directly using the orientation
|
||||
// to allow "additional" yaw manipulation with mouse/controller.
|
||||
ovrTracking2 tracking = vrapi_GetPredictedTracking2(VR_GetEngine()->ovr, predictedDisplayTime);
|
||||
const ovrQuatf quatHmd = tracking.HeadPose.Pose.Orientation;
|
||||
const ovrVector3f positionHmd = tracking.HeadPose.Pose.Position;
|
||||
vec3_t rotation = {0, 0, 0};
|
||||
QuatToYawPitchRoll(quatHmd, rotation, vr.hmdorientation);
|
||||
VectorSet(vr.hmdposition, positionHmd.x, positionHmd.y, positionHmd.z);
|
||||
|
||||
//Position
|
||||
VectorSubtract(vr.hmdposition_last, vr.hmdposition, vr.hmdposition_delta);
|
||||
|
||||
//Keep this for our records
|
||||
VectorCopy(vr.hmdposition, vr.hmdposition_last);
|
||||
|
||||
//Orientation
|
||||
VectorSubtract(vr.hmdorientation_last, vr.hmdorientation, vr.hmdorientation_delta);
|
||||
|
||||
//Keep this for our records
|
||||
VectorCopy(vr.hmdorientation, vr.hmdorientation_last);
|
||||
}
|
||||
|
||||
|
||||
ovrInputCapabilityHeader capsHeader;
|
||||
uint32_t index = 0;
|
||||
for (;;) {
|
||||
|
@ -170,6 +422,14 @@ void IN_VRInputFrame( void )
|
|||
continue;
|
||||
}
|
||||
|
||||
ovrTracking remoteTracking;
|
||||
stateResult = vrapi_GetInputTrackingState(ovr, capsHeader.DeviceID, predictedDisplayTime,
|
||||
&remoteTracking);
|
||||
if (stateResult < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
qboolean isRight;
|
||||
vrController_t* controller;
|
||||
if (caps.ControllerCapabilities & ovrControllerCaps_LeftHand) {
|
||||
|
@ -183,7 +443,8 @@ void IN_VRInputFrame( void )
|
|||
continue;
|
||||
}
|
||||
|
||||
IN_VRJoystick(isRight, state.JoystickNoDeadZone.x, state.JoystickNoDeadZone.y);
|
||||
IN_VRController(isRight, remoteTracking);
|
||||
IN_VRJoystick(isRight, state.Joystick.x, state.Joystick.y);
|
||||
IN_VRTriggers(isRight, state.IndexTrigger);
|
||||
|
||||
if (controller->buttons ^ state.Buttons) {
|
||||
|
@ -194,4 +455,4 @@ void IN_VRInputFrame( void )
|
|||
in_vrEventTime = Sys_Milliseconds( );
|
||||
}
|
||||
|
||||
#endif
|
||||
//#endif
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#if __ANDROID__
|
||||
|
||||
void IN_VRInputFrame( void );
|
||||
void IN_VRInit( void );
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include "vr_base.h"
|
||||
#include "vr_renderer.h"
|
||||
|
||||
#include "../qcommon/q_shared.h"
|
||||
|
@ -6,6 +7,7 @@
|
|||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wstrict-prototypes"
|
||||
#include <VrApi.h>
|
||||
#include <VrApi_Helpers.h>
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
|
@ -29,6 +31,24 @@ void APIENTRY VR_GLDebugLog(GLenum source, GLenum type, GLuint id,
|
|||
}
|
||||
}
|
||||
|
||||
void VR_GetRsolution(engine_t* engine, int *pWidth, int *pHeight)
|
||||
{
|
||||
static int width = 0;
|
||||
static int height = 0;
|
||||
|
||||
if (engine)
|
||||
{
|
||||
*pWidth = width = vrapi_GetSystemPropertyInt(&engine->java, VRAPI_SYS_PROP_SUGGESTED_EYE_TEXTURE_WIDTH);
|
||||
*pHeight = height = vrapi_GetSystemPropertyInt(&engine->java, VRAPI_SYS_PROP_SUGGESTED_EYE_TEXTURE_HEIGHT);
|
||||
}
|
||||
else
|
||||
{
|
||||
//use cached values
|
||||
*pWidth = width;
|
||||
*pHeight = height;
|
||||
}
|
||||
}
|
||||
|
||||
void VR_InitRenderer( engine_t* engine ) {
|
||||
#if ENABLE_GL_DEBUG
|
||||
glEnable(GL_DEBUG_OUTPUT);
|
||||
|
@ -36,9 +56,8 @@ void VR_InitRenderer( engine_t* engine ) {
|
|||
#endif
|
||||
|
||||
int eyeW, eyeH;
|
||||
|
||||
eyeW = 1440; // vrapi_GetSystemPropertyInt(&java, VRAPI_SYS_PROP_SUGGESTED_EYE_TEXTURE_WIDTH);
|
||||
eyeH = 1600; // vrapi_GetSystemPropertyInt(&java, VRAPI_SYS_PROP_SUGGESTED_EYE_TEXTURE_HEIGHT);
|
||||
VR_GetRsolution(engine, &eyeW, &eyeH);
|
||||
|
||||
for (int eye = 0; eye < VRAPI_FRAME_LAYER_EYE_MAX; ++eye) {
|
||||
framebuffer_t* framebuffer = &engine->framebuffers[eye];
|
||||
framebuffer->colorTexture = vrapi_CreateTextureSwapChain3(VRAPI_TEXTURE_TYPE_2D, GL_RGBA8,
|
||||
|
@ -91,10 +110,91 @@ void VR_DestroyRenderer( engine_t* engine ) {
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Assumes landscape cylinder shape.
|
||||
static ovrMatrix4f CylinderModelMatrix( const int texWidth, const int texHeight,
|
||||
const ovrVector3f translation,
|
||||
const float rotateYaw,
|
||||
const float rotatePitch,
|
||||
const float radius,
|
||||
const float density )
|
||||
{
|
||||
const ovrMatrix4f scaleMatrix = ovrMatrix4f_CreateScale( radius, radius * (float)texHeight * VRAPI_PI / density, radius );
|
||||
const ovrMatrix4f transMatrix = ovrMatrix4f_CreateTranslation( translation.x, translation.y, translation.z );
|
||||
const ovrMatrix4f rotXMatrix = ovrMatrix4f_CreateRotation( rotateYaw, 0.0f, 0.0f );
|
||||
const ovrMatrix4f rotYMatrix = ovrMatrix4f_CreateRotation( 0.0f, rotatePitch, 0.0f );
|
||||
|
||||
const ovrMatrix4f m0 = ovrMatrix4f_Multiply( &transMatrix, &scaleMatrix );
|
||||
const ovrMatrix4f m1 = ovrMatrix4f_Multiply( &rotXMatrix, &m0 );
|
||||
const ovrMatrix4f m2 = ovrMatrix4f_Multiply( &rotYMatrix, &m1 );
|
||||
|
||||
return m2;
|
||||
}
|
||||
|
||||
extern cvar_t *vr_screen_dist;
|
||||
|
||||
ovrLayerCylinder2 BuildCylinderLayer(engine_t* engine, const int textureWidth, const int textureHeight,
|
||||
const ovrTracking2 * tracking, float rotatePitch )
|
||||
{
|
||||
ovrLayerCylinder2 layer = vrapi_DefaultLayerCylinder2();
|
||||
|
||||
const float fadeLevel = 1.0f;
|
||||
layer.Header.ColorScale.x =
|
||||
layer.Header.ColorScale.y =
|
||||
layer.Header.ColorScale.z =
|
||||
layer.Header.ColorScale.w = fadeLevel;
|
||||
layer.Header.SrcBlend = VRAPI_FRAME_LAYER_BLEND_SRC_ALPHA;
|
||||
layer.Header.DstBlend = VRAPI_FRAME_LAYER_BLEND_ONE_MINUS_SRC_ALPHA;
|
||||
|
||||
//layer.Header.Flags = VRAPI_FRAME_LAYER_FLAG_CLIP_TO_TEXTURE_RECT;
|
||||
|
||||
layer.HeadPose = tracking->HeadPose;
|
||||
|
||||
const float density = 4500.0f;
|
||||
const float rotateYaw = 0.0f;
|
||||
const float radius = 4.0f;
|
||||
const float distance = -6.0f;
|
||||
|
||||
const ovrVector3f translation = { 0.0f, 1.0f, distance };
|
||||
|
||||
ovrMatrix4f cylinderTransform =
|
||||
CylinderModelMatrix( textureWidth, textureHeight, translation,
|
||||
rotateYaw, rotatePitch, radius, density );
|
||||
|
||||
const float circScale = density * 0.5f / textureWidth;
|
||||
const float circBias = -circScale * ( 0.5f * ( 1.0f - 1.0f / circScale ) );
|
||||
|
||||
for ( int eye = 0; eye < VRAPI_FRAME_LAYER_EYE_MAX; eye++ )
|
||||
{
|
||||
ovrMatrix4f modelViewMatrix = ovrMatrix4f_Multiply( &tracking->Eye[eye].ViewMatrix, &cylinderTransform );
|
||||
layer.Textures[eye].TexCoordsFromTanAngles = ovrMatrix4f_Inverse( &modelViewMatrix );
|
||||
layer.Textures[eye].ColorSwapChain = engine->framebuffers[eye].colorTexture;
|
||||
layer.Textures[eye].SwapChainIndex = engine->framebuffers[eye].swapchainIndex;
|
||||
|
||||
// Texcoord scale and bias is just a representation of the aspect ratio. The positioning
|
||||
// of the cylinder is handled entirely by the TexCoordsFromTanAngles matrix.
|
||||
|
||||
const float texScaleX = circScale;
|
||||
const float texBiasX = circBias;
|
||||
const float texScaleY = -0.5f;
|
||||
const float texBiasY = texScaleY * ( 0.5f * ( 1.0f - ( 1.0f / texScaleY ) ) );
|
||||
|
||||
layer.Textures[eye].TextureMatrix.M[0][0] = texScaleX;
|
||||
layer.Textures[eye].TextureMatrix.M[0][2] = texBiasX;
|
||||
layer.Textures[eye].TextureMatrix.M[1][1] = texScaleY;
|
||||
layer.Textures[eye].TextureMatrix.M[1][2] = -texBiasY;
|
||||
|
||||
layer.Textures[eye].TextureRect.width = 1.0f;
|
||||
layer.Textures[eye].TextureRect.height = 1.0f;
|
||||
}
|
||||
|
||||
return layer;
|
||||
}
|
||||
|
||||
void VR_DrawFrame( engine_t* engine ) {
|
||||
double predictedDisplayTime;
|
||||
ovrTracking2 tracking;
|
||||
ovrLayerProjection2 layer;
|
||||
|
||||
if (!engine->ovr)
|
||||
{
|
||||
|
@ -105,37 +205,80 @@ void VR_DrawFrame( engine_t* engine ) {
|
|||
predictedDisplayTime = vrapi_GetPredictedDisplayTime(engine->ovr, engine->frameIndex);
|
||||
tracking = vrapi_GetPredictedTracking2(engine->ovr, predictedDisplayTime);
|
||||
|
||||
layer = vrapi_DefaultLayerProjection2();
|
||||
layer.HeadPose = tracking.HeadPose;
|
||||
if (VR_useScreenLayer())
|
||||
{
|
||||
static ovrLayer_Union2 cylinderLayer;
|
||||
memset( &cylinderLayer, 0, sizeof( ovrLayer_Union2 ) );
|
||||
|
||||
for (int eye = 0; eye < VRAPI_FRAME_LAYER_EYE_MAX; ++eye) {
|
||||
layer.Textures[eye].ColorSwapChain = engine->framebuffers[eye].colorTexture;
|
||||
layer.Textures[eye].SwapChainIndex = engine->framebuffers[eye].swapchainIndex;
|
||||
layer.Textures[eye].TexCoordsFromTanAngles = ovrMatrix4f_TanAngleMatrixFromProjection(&tracking.Eye[eye].ProjectionMatrix);
|
||||
int eyeW, eyeH;
|
||||
VR_GetRsolution(engine, &eyeW, &eyeH);
|
||||
|
||||
// Add a simple cylindrical layer
|
||||
cylinderLayer.Cylinder =
|
||||
BuildCylinderLayer(engine, eyeW, eyeW, &tracking, 0 );
|
||||
|
||||
const ovrLayerHeader2* layers[] = {
|
||||
&cylinderLayer.Header
|
||||
};
|
||||
|
||||
// Set up the description for this frame.
|
||||
ovrSubmitFrameDescription2 frameDesc = { 0 };
|
||||
frameDesc.Flags = 0;
|
||||
frameDesc.SwapInterval = 1;
|
||||
frameDesc.FrameIndex = engine->frameIndex;
|
||||
frameDesc.DisplayTime = predictedDisplayTime;
|
||||
frameDesc.LayerCount = 1;
|
||||
frameDesc.Layers = layers;
|
||||
|
||||
const framebuffer_t* framebuffers = engine->framebuffers;
|
||||
re.SetVRHeadsetParms(&tracking,
|
||||
framebuffers[0].framebuffers[framebuffers[0].swapchainIndex],
|
||||
framebuffers[1].framebuffers[framebuffers[1].swapchainIndex]);
|
||||
Com_Frame();
|
||||
|
||||
for (int eye = 0; eye < VRAPI_FRAME_LAYER_EYE_MAX; ++eye) {
|
||||
engine->framebuffers[eye].swapchainIndex = (engine->framebuffers[eye].swapchainIndex + 1) %
|
||||
engine->framebuffers[eye].swapchainLength;
|
||||
}
|
||||
|
||||
// Hand over the eye images to the time warp.
|
||||
vrapi_SubmitFrame2(engine->ovr, &frameDesc);
|
||||
}
|
||||
else
|
||||
{
|
||||
ovrLayerProjection2 layer = vrapi_DefaultLayerProjection2();
|
||||
layer.HeadPose = tracking.HeadPose;
|
||||
|
||||
for (int eye = 0; eye < VRAPI_FRAME_LAYER_EYE_MAX; ++eye) {
|
||||
layer.Textures[eye].ColorSwapChain = engine->framebuffers[eye].colorTexture;
|
||||
layer.Textures[eye].SwapChainIndex = engine->framebuffers[eye].swapchainIndex;
|
||||
layer.Textures[eye].TexCoordsFromTanAngles = ovrMatrix4f_TanAngleMatrixFromProjection(&tracking.Eye[eye].ProjectionMatrix);
|
||||
}
|
||||
|
||||
const framebuffer_t* framebuffers = engine->framebuffers;
|
||||
re.SetVRHeadsetParms(&tracking,
|
||||
framebuffers[0].framebuffers[framebuffers[0].swapchainIndex],
|
||||
framebuffers[1].framebuffers[framebuffers[1].swapchainIndex]);
|
||||
Com_Frame();
|
||||
|
||||
for (int eye = 0; eye < VRAPI_FRAME_LAYER_EYE_MAX; ++eye) {
|
||||
engine->framebuffers[eye].swapchainIndex = (engine->framebuffers[eye].swapchainIndex + 1) %
|
||||
engine->framebuffers[eye].swapchainLength;
|
||||
}
|
||||
|
||||
const ovrLayerHeader2* layers[] = {
|
||||
&layer.Header
|
||||
};
|
||||
|
||||
ovrSubmitFrameDescription2 frameDesc = { 0 };
|
||||
frameDesc.Flags = 0;
|
||||
frameDesc.SwapInterval = 1;
|
||||
frameDesc.FrameIndex = engine->frameIndex;
|
||||
frameDesc.DisplayTime = predictedDisplayTime;
|
||||
frameDesc.LayerCount = 1;
|
||||
frameDesc.Layers = layers;
|
||||
|
||||
vrapi_SubmitFrame2(engine->ovr, &frameDesc);
|
||||
}
|
||||
|
||||
const framebuffer_t* framebuffers = engine->framebuffers;
|
||||
re.SetVRHeadsetParms(&tracking,
|
||||
framebuffers[0].framebuffers[framebuffers[0].swapchainIndex],
|
||||
framebuffers[1].framebuffers[framebuffers[1].swapchainIndex]);
|
||||
Com_Frame();
|
||||
|
||||
for (int eye = 0; eye < VRAPI_FRAME_LAYER_EYE_MAX; ++eye) {
|
||||
engine->framebuffers[eye].swapchainIndex = (engine->framebuffers[eye].swapchainIndex + 1) %
|
||||
engine->framebuffers[eye].swapchainLength;
|
||||
}
|
||||
|
||||
const ovrLayerHeader2* layers[] = {
|
||||
&layer.Header
|
||||
};
|
||||
|
||||
ovrSubmitFrameDescription2 frameDesc = { 0 };
|
||||
frameDesc.Flags = 0;
|
||||
frameDesc.SwapInterval = 1;
|
||||
frameDesc.FrameIndex = engine->frameIndex;
|
||||
frameDesc.DisplayTime = predictedDisplayTime;
|
||||
frameDesc.LayerCount = 1;
|
||||
frameDesc.Layers = layers;
|
||||
|
||||
vrapi_SubmitFrame2(engine->ovr, &frameDesc);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "vr_types.h"
|
||||
|
||||
void VR_GetRsolution( engine_t* engine, int *pWidth, int *pHeight );
|
||||
void VR_InitRenderer( engine_t* engine );
|
||||
void VR_DestroyRenderer( engine_t* engine );
|
||||
void VR_DrawFrame( engine_t* engine );
|
||||
|
|
|
@ -25,6 +25,7 @@ typedef struct {
|
|||
typedef struct {
|
||||
uint64_t frameIndex;
|
||||
ovrMobile* ovr;
|
||||
ovrJava java;
|
||||
framebuffer_t framebuffers[VRAPI_FRAME_LAYER_EYE_MAX];
|
||||
} engine_t;
|
||||
|
||||
|
|
Loading…
Reference in a new issue