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_SDK_VERSION=android26
|
||||||
ANDROID_NDK_VERSION=21.1.6352462
|
ANDROID_NDK_VERSION=21.1.6352462
|
||||||
## Uncomment for Windows host platform
|
## Uncomment for Windows host platform
|
||||||
# ANDROID_NDK=C:/Users/<user>/AppData/Local/Android/Sdk/ndk/$(ANDROID_NDK_VERSION)
|
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_CC=$(ANDROID_NDK)/toolchains/llvm/prebuilt/windows-x86_64/bin/clang.exe
|
||||||
# ANDROID_CFLAGS=--target=aarch64-linux-$(ANDROID_SDK_VERSION)
|
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_RANLIB=$(ANDROID_NDK)/toolchains/llvm/prebuilt/windows-x86_64/bin/aarch64-linux-android-ranlib.exe
|
||||||
## Uncomment for Linux host platform
|
## Uncomment for Linux host platform
|
||||||
# ANDROID_NDK=~/Android/Sdk/ndk/$(ANDROID_NDK_VERSION)
|
# 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
|
# 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:label="@string/app_name"
|
||||||
android:hasCode="true">
|
android:hasCode="true">
|
||||||
<meta-data android:name="com.samsung.android.vr.application.mode" android:value="vr_only"/>
|
<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"
|
<activity android:name="com.sparkie.ioq3quest.MainActivity"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:screenOrientation="landscape"
|
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 <qcommon/qcommon.h>
|
||||||
#include <vr/vr_base.h>
|
#include <vr/vr_base.h>
|
||||||
#include <vr/vr_renderer.h>
|
#include <vr/vr_renderer.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
|
|
||||||
|
@ -60,68 +61,56 @@ static ovrJava engine_get_ovrJava() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
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);
|
CON_LogcatFn(&ioq3_logfn);
|
||||||
|
|
||||||
std::string defaultArgs("+set fs_basepath ");
|
std::string defaultArgs("+set fs_basepath ");
|
||||||
defaultArgs += SDL_AndroidGetExternalStoragePath();
|
defaultArgs += SDL_AndroidGetExternalStoragePath();
|
||||||
defaultArgs += " +set fs_game baseq3 +map q3dm6";
|
defaultArgs += " +set fs_game baseq3";
|
||||||
|
|
||||||
char* args = new char[defaultArgs.length() + 1];
|
char* args = new char[defaultArgs.length() + 1];
|
||||||
args[defaultArgs.length()] = '\0';
|
args[defaultArgs.length()] = '\0';
|
||||||
memcpy(args, defaultArgs.c_str(), defaultArgs.length());
|
memcpy(args, defaultArgs.c_str(), defaultArgs.length());
|
||||||
Com_Init(args);
|
Com_Init(args);
|
||||||
|
|
||||||
ovrJava java = engine_get_ovrJava();
|
VR_InitRenderer(engine);
|
||||||
|
|
||||||
constexpr auto vrEnabled = true;
|
VR_EnterVR(engine, java);
|
||||||
engine_t* engine = nullptr;
|
|
||||||
|
|
||||||
if (vrEnabled)
|
//sleep(20);
|
||||||
{
|
|
||||||
engine = VR_Init(java);
|
|
||||||
VR_InitRenderer(engine);
|
|
||||||
|
|
||||||
VR_EnterVR(engine, java);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
while (SDL_PollEvent(&event)) {
|
while (SDL_PollEvent(&event)) {
|
||||||
LOGI("Received SDL Event: %d", event.type);
|
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());
|
||||||
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
break;
|
||||||
VR_EnterVR(engine, engine_get_ovrJava());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SDL_WINDOWEVENT_FOCUS_LOST:
|
case SDL_WINDOWEVENT_FOCUS_LOST:
|
||||||
VR_LeaveVR(engine);
|
VR_LeaveVR(engine);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (vrEnabled)
|
|
||||||
{
|
VR_DrawFrame(engine);
|
||||||
VR_DrawFrame(engine);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Com_Frame();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (vrEnabled)
|
|
||||||
{
|
|
||||||
VR_LeaveVR(engine);
|
|
||||||
VR_DestroyRenderer(engine);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VR_LeaveVR(engine);
|
||||||
|
VR_DestroyRenderer(engine);
|
||||||
|
|
||||||
Com_Shutdown();
|
Com_Shutdown();
|
||||||
if (vrEnabled)
|
VR_Destroy(engine);
|
||||||
{
|
|
||||||
VR_Destroy(engine);
|
|
||||||
}
|
|
||||||
delete [] args;
|
delete [] args;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,13 @@ setlocal
|
||||||
set ANDROID_SDK_ROOT=%AppData%\..\Local\Android\Sdk
|
set ANDROID_SDK_ROOT=%AppData%\..\Local\Android\Sdk
|
||||||
set adb="%ANDROID_SDK_ROOT%\platform-tools\adb.exe"
|
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 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 JAVA_HOME=C:\Program Files\Android\Android Studio\jre\jre
|
||||||
|
set BUILD_TYPE=release
|
||||||
|
set GRADLE_BUILD_TYPE=:app:assembleRelease
|
||||||
|
|
||||||
pushd %~dp0\..
|
pushd %~dp0\..
|
||||||
%make% -j %NUMBER_OF_PROCESSORS% debug
|
%make% -j %NUMBER_OF_PROCESSORS% %BUILD_TYPE%
|
||||||
|
|
||||||
if %ERRORLEVEL% NEQ 0 (
|
if %ERRORLEVEL% NEQ 0 (
|
||||||
popd
|
popd
|
||||||
|
@ -19,7 +22,7 @@ if %ERRORLEVEL% NEQ 0 (
|
||||||
pushd android
|
pushd android
|
||||||
|
|
||||||
set GRADLE_EXIT_CONSOLE=1
|
set GRADLE_EXIT_CONSOLE=1
|
||||||
call gradlew.bat :app:assembleDebug
|
call gradlew.bat %GRADLE_BUILD_TYPE%
|
||||||
|
|
||||||
if %ERRORLEVEL% NEQ 0 (
|
if %ERRORLEVEL% NEQ 0 (
|
||||||
popd
|
popd
|
||||||
|
@ -30,7 +33,9 @@ if %ERRORLEVEL% NEQ 0 (
|
||||||
|
|
||||||
set PACKAGE_NAME=com.sparkie.ioq3quest
|
set PACKAGE_NAME=com.sparkie.ioq3quest
|
||||||
set ANDROID_STORAGE_LOCATION=/sdcard/Android/data/%PACKAGE_NAME%/files/
|
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%
|
%adb% install -r %APK_LOCATION%
|
||||||
if %ERRORLEVEL% NEQ 0 (
|
if %ERRORLEVEL% NEQ 0 (
|
||||||
|
@ -45,7 +50,7 @@ if %ERRORLEVEL% NEQ 0 (
|
||||||
)
|
)
|
||||||
|
|
||||||
%adb% shell mkdir -p %ANDROID_STORAGE_LOCATION%
|
%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 (
|
if %ERRORLEVEL% NEQ 0 (
|
||||||
popd
|
popd
|
||||||
popd
|
popd
|
||||||
|
|
|
@ -24,6 +24,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
// active (after loading) gameplay
|
// active (after loading) gameplay
|
||||||
|
|
||||||
#include "cg_local.h"
|
#include "cg_local.h"
|
||||||
|
#include "../vr/vr_clientinfo.h"
|
||||||
|
|
||||||
#ifdef MISSIONPACK
|
#ifdef MISSIONPACK
|
||||||
#include "../ui/ui_shared.h"
|
#include "../ui/ui_shared.h"
|
||||||
|
@ -38,6 +39,9 @@ int drawTeamOverlayModificationCount = -1;
|
||||||
int sortedTeamPlayers[TEAM_MAXOVERLAY];
|
int sortedTeamPlayers[TEAM_MAXOVERLAY];
|
||||||
int numSortedTeamPlayers;
|
int numSortedTeamPlayers;
|
||||||
|
|
||||||
|
extern vr_clientinfo_t* cgVR;
|
||||||
|
extern stereoFrame_t hudStereoView;
|
||||||
|
|
||||||
char systemChat[256];
|
char systemChat[256];
|
||||||
char teamChat1[256];
|
char teamChat1[256];
|
||||||
char teamChat2[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 ) );
|
memset( &ent, 0, sizeof( ent ) );
|
||||||
AnglesToAxis( angles, ent.axis );
|
AnglesToAxis( angles, ent.axis );
|
||||||
|
|
||||||
VectorCopy( origin, ent.origin );
|
VectorCopy( origin, ent.origin );
|
||||||
ent.hModel = model;
|
ent.hModel = model;
|
||||||
ent.customSkin = skin;
|
ent.customSkin = skin;
|
||||||
|
@ -1923,6 +1928,7 @@ static void CG_DrawCrosshair(void)
|
||||||
CG_DrawCrosshair3D
|
CG_DrawCrosshair3D
|
||||||
=================
|
=================
|
||||||
*/
|
*/
|
||||||
|
void CG_CalculateVRWeaponPosition( vec3_t origin, vec3_t angles );
|
||||||
static void CG_DrawCrosshair3D(void)
|
static void CG_DrawCrosshair3D(void)
|
||||||
{
|
{
|
||||||
float w;
|
float w;
|
||||||
|
@ -1976,10 +1982,19 @@ static void CG_DrawCrosshair3D(void)
|
||||||
xmax = zProj * tan(cg.refdef.fov_x * M_PI / 360.0f);
|
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.
|
// 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);
|
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);
|
VectorMA(cg.refdef.vieworg, maxdist, cg.refdef.viewaxis[0], endpos);
|
||||||
CG_Trace(&trace, cg.refdef.vieworg, NULL, NULL, endpos, 0, MASK_SHOT);
|
CG_Trace(&trace, cg.refdef.vieworg, NULL, NULL, endpos, 0, MASK_SHOT);
|
||||||
|
*/
|
||||||
memset(&ent, 0, sizeof(ent));
|
memset(&ent, 0, sizeof(ent));
|
||||||
ent.reType = RT_SPRITE;
|
ent.reType = RT_SPRITE;
|
||||||
ent.renderfx = RF_DEPTHHACK | RF_CROSSHAIR;
|
ent.renderfx = RF_DEPTHHACK | RF_CROSSHAIR;
|
||||||
|
@ -2647,11 +2662,28 @@ void CG_DrawActive( stereoFrame_t stereoView ) {
|
||||||
if(stereoView != STEREO_CENTER)
|
if(stereoView != STEREO_CENTER)
|
||||||
CG_DrawCrosshair3D();
|
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
|
// draw 3D view
|
||||||
trap_R_RenderScene( &cg.refdef );
|
trap_R_RenderScene( &cg.refdef );
|
||||||
|
|
||||||
|
VectorCopy( baseOrg, cg.refdef.vieworg );
|
||||||
|
|
||||||
// draw status bar and other floating elements
|
// 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
|
// cg_drawtools.c -- helper functions called by cg_draw, cg_scoreboard, cg_info, etc
|
||||||
#include "cg_local.h"
|
#include "cg_local.h"
|
||||||
|
|
||||||
|
int hudflags = 0;
|
||||||
|
stereoFrame_t hudStereoView = STEREO_CENTER;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
================
|
================
|
||||||
CG_AdjustFrom640
|
CG_AdjustFrom640
|
||||||
|
@ -31,17 +34,33 @@ Adjusted for resolution and screen aspect ratio
|
||||||
================
|
================
|
||||||
*/
|
*/
|
||||||
void CG_AdjustFrom640( float *x, float *y, float *w, float *h ) {
|
void CG_AdjustFrom640( float *x, float *y, float *w, float *h ) {
|
||||||
#if 0
|
|
||||||
// adjust for wide screens
|
if (hudflags & HUD_FLAGS_FULLSCREEN)
|
||||||
if ( cgs.glconfig.vidWidth * 480 > cgs.glconfig.vidHeight * 640 ) {
|
{
|
||||||
*x += 0.5 * ( cgs.glconfig.vidWidth - ( cgs.glconfig.vidHeight * 640 / 480 ) );
|
// 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_REDTEAM_NAME "Stroggs"
|
||||||
#define DEFAULT_BLUETEAM_NAME "Pagans"
|
#define DEFAULT_BLUETEAM_NAME "Pagans"
|
||||||
|
//VR HUD
|
||||||
|
#define HUD_FLAGS_FULLSCREEN 1
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
FOOTSTEP_NORMAL,
|
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
|
// cg_main.c -- initialization and primary entry point for cgame
|
||||||
#include "cg_local.h"
|
#include "cg_local.h"
|
||||||
|
|
||||||
|
#include "../vr/vr_clientinfo.h"
|
||||||
|
|
||||||
#ifdef MISSIONPACK
|
#ifdef MISSIONPACK
|
||||||
#include "../ui/ui_shared.h"
|
#include "../ui/ui_shared.h"
|
||||||
// display context for new ui stuff
|
// display context for new ui stuff
|
||||||
displayContextDef_t cgDC;
|
displayContextDef_t cgDC;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
vr_clientinfo_t *cgVR;
|
||||||
|
|
||||||
int forceModelModificationCount = -1;
|
int forceModelModificationCount = -1;
|
||||||
|
|
||||||
void CG_Init( int serverMessageNum, int serverCommandSequence, int clientNum );
|
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:
|
case CG_EVENT_HANDLING:
|
||||||
CG_EventHandling(arg0);
|
CG_EventHandling(arg0);
|
||||||
return 0;
|
return 0;
|
||||||
|
case CG_SET_VR_CLIENT_INFO: {
|
||||||
|
int ptr[2] = {arg0, arg1};
|
||||||
|
cgVR = (vr_clientinfo_t *) (*(long*)(ptr));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
CG_Error( "vmMain: unknown command %i", command );
|
CG_Error( "vmMain: unknown command %i", command );
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -231,8 +231,11 @@ typedef enum {
|
||||||
|
|
||||||
CG_MOUSE_EVENT,
|
CG_MOUSE_EVENT,
|
||||||
// void (*CG_MouseEvent)( int dx, int dy );
|
// void (*CG_MouseEvent)( int dx, int dy );
|
||||||
CG_EVENT_HANDLING
|
CG_EVENT_HANDLING,
|
||||||
// void (*CG_EventHandling)(int type);
|
// void (*CG_EventHandling)(int type);
|
||||||
|
|
||||||
|
CG_SET_VR_CLIENT_INFO
|
||||||
|
|
||||||
} cgameExport_t;
|
} cgameExport_t;
|
||||||
|
|
||||||
//----------------------------------------------
|
//----------------------------------------------
|
||||||
|
|
|
@ -333,8 +333,8 @@ static void CG_OffsetFirstPersonView( void ) {
|
||||||
|
|
||||||
// if dead, fix the angle and don't add any kick
|
// if dead, fix the angle and don't add any kick
|
||||||
if ( cg.snap->ps.stats[STAT_HEALTH] <= 0 ) {
|
if ( cg.snap->ps.stats[STAT_HEALTH] <= 0 ) {
|
||||||
angles[ROLL] = 40;
|
//angles[ROLL] = 40;
|
||||||
angles[PITCH] = -15;
|
//angles[PITCH] = -15;
|
||||||
angles[YAW] = cg.snap->ps.stats[STAT_DEAD_YAW];
|
angles[YAW] = cg.snap->ps.stats[STAT_DEAD_YAW];
|
||||||
origin[2] += cg.predictedPlayerState.viewheight;
|
origin[2] += cg.predictedPlayerState.viewheight;
|
||||||
return;
|
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
|
// cg_weapons.c -- events and effects dealing with weapons
|
||||||
#include "cg_local.h"
|
#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
|
#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
|
CG_RailTrail
|
||||||
|
@ -1398,11 +1667,12 @@ void CG_AddViewWeapon( playerState_t *ps ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// drop gun lower at higher fov
|
// drop gun lower at higher fov
|
||||||
if ( cg_fov.integer > 90 ) {
|
/* if ( cg_fov.integer > 90 ) {
|
||||||
fovOffset = -0.2 * ( cg_fov.integer - 90 );
|
fovOffset = -0.2 * ( cg_fov.integer - 90 );
|
||||||
} else {
|
} else {
|
||||||
fovOffset = 0;
|
fovOffset = 0;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
cent = &cg.predictedPlayerEntity; // &cg_entities[cg.snap->ps.clientNum];
|
cent = &cg.predictedPlayerEntity; // &cg_entities[cg.snap->ps.clientNum];
|
||||||
CG_RegisterWeapon( ps->weapon );
|
CG_RegisterWeapon( ps->weapon );
|
||||||
|
@ -1411,11 +1681,61 @@ void CG_AddViewWeapon( playerState_t *ps ) {
|
||||||
memset (&hand, 0, sizeof(hand));
|
memset (&hand, 0, sizeof(hand));
|
||||||
|
|
||||||
// set up gun position
|
// 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_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_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 );
|
AnglesToAxis( angles, hand.axis );
|
||||||
|
|
||||||
|
@ -1435,8 +1755,39 @@ void CG_AddViewWeapon( playerState_t *ps ) {
|
||||||
hand.hModel = weapon->handsModel;
|
hand.hModel = weapon->handsModel;
|
||||||
hand.renderfx = RF_DEPTHHACK | RF_FIRST_PERSON | RF_MINLIGHT;
|
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
|
// add everything onto the hand
|
||||||
CG_AddPlayerWeapon( &hand, ps, &cg.predictedPlayerEntity, ps->persistant[PERS_TEAM] );
|
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 "client.h"
|
||||||
|
|
||||||
#include "../botlib/botlib.h"
|
#include "../botlib/botlib.h"
|
||||||
|
#include "../vr/vr_clientinfo.h"
|
||||||
|
|
||||||
#ifdef USE_MUMBLE
|
#ifdef USE_MUMBLE
|
||||||
#include "libmumblelink.h"
|
#include "libmumblelink.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern botlib_export_t *botlib_export;
|
extern botlib_export_t *botlib_export;
|
||||||
|
extern vr_clientinfo_t vr;
|
||||||
|
|
||||||
extern qboolean loadCamera(const char *name);
|
extern qboolean loadCamera(const char *name);
|
||||||
extern void startCamera(int time);
|
extern void startCamera(int time);
|
||||||
|
@ -53,6 +55,16 @@ void CL_GetGlconfig( glconfig_t *glconfig ) {
|
||||||
*glconfig = cls.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 "client.h"
|
||||||
|
|
||||||
|
#include "../vr/vr_input.h"
|
||||||
|
#include "../vr/vr_clientinfo.h"
|
||||||
|
|
||||||
unsigned frame_msec;
|
unsigned frame_msec;
|
||||||
int old_com_frameTime;
|
int old_com_frameTime;
|
||||||
|
|
||||||
|
extern vr_clientinfo_t vr;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
===============================================================================
|
===============================================================================
|
||||||
|
|
||||||
|
@ -290,7 +295,7 @@ Moves the local angle positions
|
||||||
================
|
================
|
||||||
*/
|
*/
|
||||||
void CL_AdjustAngles( void ) {
|
void CL_AdjustAngles( void ) {
|
||||||
float speed;
|
/* float speed;
|
||||||
|
|
||||||
if ( in_speed.active ) {
|
if ( in_speed.active ) {
|
||||||
speed = 0.001 * cls.frametime * cl_anglespeedkey->value;
|
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_lookup);
|
||||||
cl.viewangles[PITCH] += speed*cl_pitchspeed->value * CL_KeyState (&in_lookdown);
|
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 );
|
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
|
CL_MouseEvent
|
||||||
|
@ -554,6 +581,7 @@ void CL_CmdButtons( usercmd_t *cmd ) {
|
||||||
CL_FinishMove
|
CL_FinishMove
|
||||||
==============
|
==============
|
||||||
*/
|
*/
|
||||||
|
void rotateAboutOrigin(float x, float y, float rotation, vec2_t out);
|
||||||
void CL_FinishMove( usercmd_t *cmd ) {
|
void CL_FinishMove( usercmd_t *cmd ) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -564,8 +592,26 @@ void CL_FinishMove( usercmd_t *cmd ) {
|
||||||
// can be determined without allowing cheating
|
// can be determined without allowing cheating
|
||||||
cmd->serverTime = cl.serverTime;
|
cmd->serverTime = cl.serverTime;
|
||||||
|
|
||||||
for (i=0 ; i<3 ; i++) {
|
//If we are running with a remote non-vr server, then the best we can do is pass the angles from the weapon
|
||||||
cmd->angles[i] = ANGLE2SHORT(cl.viewangles[i]);
|
//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;
|
cl.viewangles[PITCH] = oldAngles[PITCH] + 90;
|
||||||
} else if ( oldAngles[PITCH] - cl.viewangles[PITCH] > 90 ) {
|
} else if ( oldAngles[PITCH] - cl.viewangles[PITCH] > 90 ) {
|
||||||
cl.viewangles[PITCH] = oldAngles[PITCH] - 90;
|
cl.viewangles[PITCH] = oldAngles[PITCH] - 90;
|
||||||
}
|
}
|
||||||
|
|
||||||
// store out the final values
|
// store out the final values
|
||||||
CL_FinishMove( &cmd );
|
CL_FinishMove( &cmd );
|
||||||
|
|
||||||
// draw debug graphs of turning for mouse testing
|
// 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_nodelta = Cvar_Get ("cl_nodelta", "0", 0);
|
||||||
cl_debugMove = Cvar_Get ("cl_debugMove", "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_packetdup = Cvar_Get ("cl_packetdup", "1", CVAR_ARCHIVE );
|
||||||
|
|
||||||
cl_run = Cvar_Get ("cl_run", "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_mouseAccel = Cvar_Get ("cl_mouseAccel", "0", CVAR_ARCHIVE);
|
||||||
cl_freelook = Cvar_Get( "cl_freelook", "1", 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_pitch = Cvar_Get ("j_pitch", "0.022", CVAR_ARCHIVE);
|
||||||
j_yaw = Cvar_Get ("j_yaw", "-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_forward = Cvar_Get ("j_forward", "1.0", CVAR_ARCHIVE);
|
||||||
j_side = Cvar_Get ("j_side", "0.25", CVAR_ARCHIVE);
|
j_side = Cvar_Get ("j_side", "1.0", CVAR_ARCHIVE);
|
||||||
j_up = Cvar_Get ("j_up", "0", CVAR_ARCHIVE);
|
j_up = Cvar_Get ("j_up", "0", CVAR_ARCHIVE);
|
||||||
|
|
||||||
j_pitch_axis = Cvar_Get ("j_pitch_axis", "3", 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);
|
cl_consoleKeys = Cvar_Get( "cl_consoleKeys", "~ ` 0x7e 0x60", CVAR_ARCHIVE);
|
||||||
|
|
||||||
// userinfo
|
// 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 );
|
cl_rate = Cvar_Get ("rate", "25000", CVAR_USERINFO | CVAR_ARCHIVE );
|
||||||
Cvar_Get ("snaps", "20", CVAR_USERINFO | CVAR_ARCHIVE );
|
Cvar_Get ("snaps", "20", CVAR_USERINFO | CVAR_ARCHIVE );
|
||||||
Cvar_Get ("model", "sarge", CVAR_USERINFO | CVAR_ARCHIVE );
|
Cvar_Get ("model", "sarge", CVAR_USERINFO | CVAR_ARCHIVE );
|
||||||
|
|
|
@ -514,6 +514,7 @@ void SCR_DrawScreenField( stereoFrame_t stereoFrame ) {
|
||||||
break;
|
break;
|
||||||
case CA_LOADING:
|
case CA_LOADING:
|
||||||
case CA_PRIMED:
|
case CA_PRIMED:
|
||||||
|
CL_CGameSetVRClientInfo();
|
||||||
// draw the game information screen and loading progress
|
// draw the game information screen and loading progress
|
||||||
CL_CGameRendering(stereoFrame);
|
CL_CGameRendering(stereoFrame);
|
||||||
|
|
||||||
|
@ -524,6 +525,7 @@ void SCR_DrawScreenField( stereoFrame_t stereoFrame ) {
|
||||||
VM_Call( uivm, UI_DRAW_CONNECT_SCREEN, qtrue );
|
VM_Call( uivm, UI_DRAW_CONNECT_SCREEN, qtrue );
|
||||||
break;
|
break;
|
||||||
case CA_ACTIVE:
|
case CA_ACTIVE:
|
||||||
|
CL_CGameSetVRClientInfo();
|
||||||
// always supply STEREO_CENTER as vieworg offset is now done by the engine.
|
// always supply STEREO_CENTER as vieworg offset is now done by the engine.
|
||||||
CL_CGameRendering(stereoFrame);
|
CL_CGameRendering(stereoFrame);
|
||||||
SCR_DrawDemoRecording();
|
SCR_DrawDemoRecording();
|
||||||
|
|
|
@ -507,6 +507,8 @@ void CL_ReadPackets (void);
|
||||||
void CL_WritePacket( void );
|
void CL_WritePacket( void );
|
||||||
void IN_CenterView (void);
|
void IN_CenterView (void);
|
||||||
|
|
||||||
|
void CL_CGameSetVRClientInfo();
|
||||||
|
|
||||||
void CL_VerifyCode( void );
|
void CL_VerifyCode( void );
|
||||||
|
|
||||||
float CL_KeyState (kbutton_t *key);
|
float CL_KeyState (kbutton_t *key);
|
||||||
|
|
|
@ -35,12 +35,12 @@ float pm_stopspeed = 100.0f;
|
||||||
float pm_duckScale = 0.25f;
|
float pm_duckScale = 0.25f;
|
||||||
float pm_swimScale = 0.50f;
|
float pm_swimScale = 0.50f;
|
||||||
|
|
||||||
float pm_accelerate = 10.0f;
|
float pm_accelerate = 1000.0f;
|
||||||
float pm_airaccelerate = 1.0f;
|
float pm_airaccelerate = 1.0f;
|
||||||
float pm_wateraccelerate = 4.0f;
|
float pm_wateraccelerate = 4.0f;
|
||||||
float pm_flyaccelerate = 8.0f;
|
float pm_flyaccelerate = 8.0f;
|
||||||
|
|
||||||
float pm_friction = 6.0f;
|
float pm_friction = 10.0f;
|
||||||
float pm_waterfriction = 1.0f;
|
float pm_waterfriction = 1.0f;
|
||||||
float pm_flightfriction = 3.0f;
|
float pm_flightfriction = 3.0f;
|
||||||
float pm_spectatorfriction = 5.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
|
// circularly clamp the angles with deltas
|
||||||
for (i=0 ; i<3 ; i++) {
|
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 ) {
|
if ( i == PITCH ) {
|
||||||
// don't let the player look up or down more than 90 degrees
|
// don't let the player look up or down more than 90 degrees
|
||||||
if ( temp > 16000 ) {
|
if ( temp > 16000 ) {
|
||||||
|
|
|
@ -22,6 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "g_local.h"
|
#include "g_local.h"
|
||||||
|
#include "../vr/vr_clientinfo.h"
|
||||||
|
|
||||||
level_locals_t level;
|
level_locals_t level;
|
||||||
|
|
||||||
|
@ -38,6 +39,8 @@ typedef struct {
|
||||||
gentity_t g_entities[MAX_GENTITIES];
|
gentity_t g_entities[MAX_GENTITIES];
|
||||||
gclient_t g_clients[MAX_CLIENTS];
|
gclient_t g_clients[MAX_CLIENTS];
|
||||||
|
|
||||||
|
vr_clientinfo_t* gVR;
|
||||||
|
|
||||||
vmCvar_t g_gametype;
|
vmCvar_t g_gametype;
|
||||||
vmCvar_t g_dmflags;
|
vmCvar_t g_dmflags;
|
||||||
vmCvar_t g_fraglimit;
|
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();
|
return ConsoleCommand();
|
||||||
case BOTAI_START_FRAME:
|
case BOTAI_START_FRAME:
|
||||||
return BotAIStartFrame( arg0 );
|
return BotAIStartFrame( arg0 );
|
||||||
|
case GAME_SET_VR_CLIENT_INFO: {
|
||||||
|
int ptr[2] = {arg0, arg1};
|
||||||
|
gVR = (vr_clientinfo_t *) (*(long*)(ptr));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -425,6 +425,8 @@ typedef enum {
|
||||||
// The game can issue trap_argc() / trap_argv() commands to get the command
|
// 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.
|
// 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;
|
} gameExport_t;
|
||||||
|
|
||||||
|
|
|
@ -25,12 +25,43 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
#include "g_local.h"
|
#include "g_local.h"
|
||||||
|
|
||||||
|
#include "../vr/vr_clientinfo.h"
|
||||||
|
|
||||||
static float s_quadFactor;
|
static float s_quadFactor;
|
||||||
static vec3_t forward, right, up;
|
static vec3_t forward, right, up;
|
||||||
static vec3_t muzzle;
|
static vec3_t muzzle;
|
||||||
|
|
||||||
|
extern vr_clientinfo_t* gVR;
|
||||||
|
|
||||||
#define NUM_NAILSHOTS 15
|
#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
|
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 ) {
|
void CalcMuzzlePoint ( gentity_t *ent, vec3_t forward, vec3_t right, vec3_t up, vec3_t muzzlePoint ) {
|
||||||
VectorCopy( ent->s.pos.trBase, muzzlePoint );
|
if ( ( ent->r.svFlags & SVF_BOT ) )
|
||||||
muzzlePoint[2] += ent->client->ps.viewheight;
|
{
|
||||||
VectorMA( muzzlePoint, 14, forward, muzzlePoint );
|
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
|
// snap to integer coordinates for more efficient network bandwidth usage
|
||||||
SnapVector( muzzlePoint );
|
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 ) {
|
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 );
|
CalcMuzzlePoint(ent, forward, right, up, muzzlePoint);
|
||||||
muzzlePoint[2] += ent->client->ps.viewheight;
|
|
||||||
VectorMA( muzzlePoint, 14, forward, muzzlePoint );
|
|
||||||
// snap to integer coordinates for more efficient network bandwidth usage
|
|
||||||
SnapVector( muzzlePoint );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -824,8 +861,19 @@ void FireWeapon( gentity_t *ent ) {
|
||||||
#endif
|
#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
|
// 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 );
|
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 vec4_t[4];
|
||||||
typedef vec_t vec5_t[5];
|
typedef vec_t vec5_t[5];
|
||||||
|
|
||||||
|
typedef vec_t matrix4x4[4][4];
|
||||||
|
|
||||||
typedef vec_t quat_t[4];
|
typedef vec_t quat_t[4];
|
||||||
|
|
||||||
typedef int fixed4_t;
|
typedef int fixed4_t;
|
||||||
|
|
|
@ -991,6 +991,8 @@ void CL_KeyEvent (int key, qboolean down, unsigned time);
|
||||||
void CL_CharEvent( int key );
|
void CL_CharEvent( int key );
|
||||||
// char events are for field typing, not game control
|
// 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_MouseEvent( int dx, int dy, int time );
|
||||||
|
|
||||||
void CL_JoystickEvent( int axis, int value, 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)
|
void GL_SetModelviewMatrix(mat4_t matrix, qboolean applyStereoView)
|
||||||
{
|
{
|
||||||
if (applyStereoView)
|
if (qfalse) //applyStereoView)
|
||||||
{
|
{
|
||||||
if (tr.refdef.stereoFrame == STEREO_LEFT) {
|
if (tr.refdef.stereoFrame == STEREO_LEFT) {
|
||||||
Mat4Multiply(tr.vrParms.viewL, matrix, glState.modelview);
|
Mat4Multiply(tr.vrParms.viewL, matrix, glState.modelview);
|
||||||
|
|
|
@ -573,7 +573,7 @@ void RE_EndFrame( int *frontEndMsec, int *backEndMsec ) {
|
||||||
backEnd.pc.msec = 0;
|
backEnd.pc.msec = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if __ANDROID__
|
//#if __ANDROID__
|
||||||
void R_Mat4Transpose( const float in[4][4], float* out ) {
|
void R_Mat4Transpose( const float in[4][4], float* out ) {
|
||||||
int i, j;
|
int i, j;
|
||||||
for (i = 0; i < 4; ++i) {
|
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 ) {
|
void RE_SetVRHeadsetParms( const ovrTracking2* tracking, int renderBufferL, int renderBufferR ) {
|
||||||
if (tracking) {
|
if (tracking) {
|
||||||
R_Mat4Transpose(tracking->Eye[0].ProjectionMatrix.M, tr.vrParms.projectionL);
|
R_Mat4Transpose(tracking->Eye[0].ProjectionMatrix.M, tr.vrParms.projectionL);
|
||||||
R_Mat4Transpose(tracking->Eye[1].ProjectionMatrix.M, tr.vrParms.projectionR);
|
R_Mat4Transpose(tracking->Eye[1].ProjectionMatrix.M, tr.vrParms.projectionR);
|
||||||
|
|
||||||
|
/*
|
||||||
R_Mat4Transpose(tracking->Eye[0].ViewMatrix.M, tr.vrParms.viewL);
|
R_Mat4Transpose(tracking->Eye[0].ViewMatrix.M, tr.vrParms.viewL);
|
||||||
R_Mat4Transpose(tracking->Eye[1].ViewMatrix.M, tr.vrParms.viewR);
|
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[12] *= worldToMeter;
|
||||||
tr.vrParms.viewL[13] *= worldToMeter;
|
tr.vrParms.viewL[13] *= worldToMeter;
|
||||||
tr.vrParms.viewL[14] *= 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[13] *= worldToMeter;
|
||||||
tr.vrParms.viewR[14] *= worldToMeter;
|
tr.vrParms.viewR[14] *= worldToMeter;
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
tr.vrParms.renderBufferL = renderBufferL;
|
tr.vrParms.renderBufferL = renderBufferL;
|
||||||
tr.vrParms.renderBufferR = renderBufferR;
|
tr.vrParms.renderBufferR = renderBufferR;
|
||||||
|
|
||||||
|
@ -606,7 +611,7 @@ void RE_SetVRHeadsetParms( const ovrTracking2* tracking, int renderBufferL, int
|
||||||
tr.vrParms.valid = qfalse;
|
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 "../renderercommon/tr_common.h"
|
||||||
#include "../sys/sys_local.h"
|
#include "../sys/sys_local.h"
|
||||||
#include "sdl_icon.h"
|
#include "sdl_icon.h"
|
||||||
|
#include "../vr/vr_renderer.h"
|
||||||
|
|
||||||
typedef enum
|
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 );
|
ri.Printf (PRINT_ALL, "...setting mode %d:", mode );
|
||||||
|
|
||||||
|
VR_GetRsolution(0, &glConfig.vidWidth, &glConfig.vidHeight);
|
||||||
|
/*
|
||||||
if (mode == -2)
|
if (mode == -2)
|
||||||
{
|
{
|
||||||
|
|
||||||
// use desktop video resolution
|
// use desktop video resolution
|
||||||
if( desktopMode.h > 0 )
|
if( desktopMode.h > 0 )
|
||||||
{
|
{
|
||||||
|
@ -444,6 +448,7 @@ static int GLimp_SetMode(int mode, qboolean fullscreen, qboolean noborder, qbool
|
||||||
ri.Printf( PRINT_ALL,
|
ri.Printf( PRINT_ALL,
|
||||||
"Cannot determine display resolution, assuming 640x480\n" );
|
"Cannot determine display resolution, assuming 640x480\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
glConfig.windowAspect = (float)glConfig.vidWidth / (float)glConfig.vidHeight;
|
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" );
|
ri.Printf( PRINT_ALL, " invalid mode\n" );
|
||||||
return RSERR_INVALID_MODE;
|
return RSERR_INVALID_MODE;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
ri.Printf( PRINT_ALL, " %d %d\n", glConfig.vidWidth, glConfig.vidHeight);
|
ri.Printf( PRINT_ALL, " %d %d\n", glConfig.vidWidth, glConfig.vidHeight);
|
||||||
|
|
||||||
// Center window
|
// Center window
|
||||||
|
|
|
@ -21,6 +21,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
|
#include "../vr/vr_clientinfo.h"
|
||||||
|
|
||||||
#ifdef USE_VOIP
|
#ifdef USE_VOIP
|
||||||
cvar_t *sv_voip;
|
cvar_t *sv_voip;
|
||||||
|
@ -30,6 +31,7 @@ cvar_t *sv_voipProtocol;
|
||||||
serverStatic_t svs; // persistant server info
|
serverStatic_t svs; // persistant server info
|
||||||
server_t sv; // local server
|
server_t sv; // local server
|
||||||
vm_t *gvm = NULL; // game virtual machine
|
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_fps = NULL; // time rate for running non-clients
|
||||||
cvar_t *sv_timeout; // seconds without any message
|
cvar_t *sv_timeout; // seconds without any message
|
||||||
|
@ -1128,6 +1130,11 @@ void SV_Frame( int msec ) {
|
||||||
startTime = 0; // quite a compiler warning
|
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
|
// update ping based on the all received frames
|
||||||
SV_CalcPings();
|
SV_CalcPings();
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
#include "vr_base.h"
|
#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 push
|
||||||
#pragma clang diagnostic ignored "-Wstrict-prototypes"
|
#pragma clang diagnostic ignored "-Wstrict-prototypes"
|
||||||
#include <VrApi_Helpers.h>
|
#include "../VrApi/Include/VrApi_Helpers.h"
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
|
@ -24,6 +27,8 @@ engine_t* VR_Init( ovrJava java )
|
||||||
initParams = vrapi_DefaultInitParms(&java);
|
initParams = vrapi_DefaultInitParms(&java);
|
||||||
initResult = vrapi_Initialize(&initParams);
|
initResult = vrapi_Initialize(&initParams);
|
||||||
assert(initResult == VRAPI_INITIALIZE_SUCCESS);
|
assert(initResult == VRAPI_INITIALIZE_SUCCESS);
|
||||||
|
|
||||||
|
vr_engine.java = java;
|
||||||
|
|
||||||
return &vr_engine;
|
return &vr_engine;
|
||||||
}
|
}
|
||||||
|
@ -45,7 +50,7 @@ void VR_EnterVR( engine_t* engine, ovrJava java ) {
|
||||||
engine->ovr = vrapi_EnterVrMode(&modeParams);
|
engine->ovr = vrapi_EnterVrMode(&modeParams);
|
||||||
engine->frameIndex = 0;
|
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 ) {
|
engine_t* VR_GetEngine( void ) {
|
||||||
return &vr_engine;
|
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"
|
#include "vr_types.h"
|
||||||
|
|
||||||
|
#define WORLD_SCALE 37.5f
|
||||||
|
#define PLAYER_HEIGHT 48
|
||||||
|
|
||||||
engine_t* VR_Init( ovrJava java );
|
engine_t* VR_Init( ovrJava java );
|
||||||
void VR_Destroy( engine_t* engine );
|
void VR_Destroy( engine_t* engine );
|
||||||
void VR_EnterVR( engine_t* engine, ovrJava java );
|
void VR_EnterVR( engine_t* engine, ovrJava java );
|
||||||
void VR_LeaveVR( engine_t* engine );
|
void VR_LeaveVR( engine_t* engine );
|
||||||
|
|
||||||
engine_t* VR_GetEngine( void );
|
engine_t* VR_GetEngine( void );
|
||||||
|
bool VR_useScreenLayer( void );
|
||||||
|
|
||||||
#endif
|
#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"
|
#include "vr_input.h"
|
||||||
|
|
||||||
#if __ANDROID__
|
//#if __ANDROID__
|
||||||
|
|
||||||
#include "../qcommon/q_shared.h"
|
#include "../qcommon/q_shared.h"
|
||||||
#include "../qcommon/qcommon.h"
|
#include "../qcommon/qcommon.h"
|
||||||
#include "../client/keycodes.h"
|
#include "../client/keycodes.h"
|
||||||
#include "vr_base.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
|
#ifdef USE_LOCAL_HEADERS
|
||||||
# include "SDL.h"
|
# include "SDL.h"
|
||||||
|
@ -27,6 +30,8 @@ typedef struct {
|
||||||
uint32_t axisButtons;
|
uint32_t axisButtons;
|
||||||
} vrController_t;
|
} vrController_t;
|
||||||
|
|
||||||
|
vr_clientinfo_t vr;
|
||||||
|
|
||||||
static qboolean controllerInit = qfalse;
|
static qboolean controllerInit = qfalse;
|
||||||
|
|
||||||
static vrController_t leftController;
|
static vrController_t leftController;
|
||||||
|
@ -40,49 +45,261 @@ extern cvar_t *cl_sensitivity;
|
||||||
extern cvar_t *m_pitch;
|
extern cvar_t *m_pitch;
|
||||||
extern cvar_t *m_yaw;
|
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 )
|
static void IN_VRJoystick( qboolean isRightController, float joystickX, float joystickY )
|
||||||
{
|
{
|
||||||
vrController_t* controller = isRightController == qtrue ? &rightController : &leftController;
|
vrController_t* controller = isRightController == qtrue ? &rightController : &leftController;
|
||||||
|
|
||||||
// Menu controls mapped to keyboard codes...
|
//Positional movement speed correction for when we are not hitting target framerate
|
||||||
if (isRightController == qfalse) {
|
static double lastframetime = 0;
|
||||||
if (!(controller->axisButtons & VR_TOUCH_AXIS_UP) && joystickY > pressedThreshold) {
|
int refresh = vrapi_GetSystemPropertyInt(&(VR_GetEngine()->java), VRAPI_SYS_PROP_DISPLAY_REFRESH_RATE);
|
||||||
controller->axisButtons |= VR_TOUCH_AXIS_UP;
|
double newframetime = Sys_Milliseconds();
|
||||||
Com_QueueEvent(in_vrEventTime, SE_KEY, K_UPARROW, qtrue, 0, NULL);
|
float multiplier = (float)((1000.0 / refresh) / (newframetime - lastframetime));
|
||||||
} else if ((controller->axisButtons & VR_TOUCH_AXIS_UP) && joystickY < releasedThreshold) {
|
lastframetime = newframetime;
|
||||||
controller->axisButtons &= ~VR_TOUCH_AXIS_UP;
|
|
||||||
Com_QueueEvent(in_vrEventTime, SE_KEY, K_UPARROW, qfalse, 0, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(controller->axisButtons & VR_TOUCH_AXIS_DOWN) && joystickY < -pressedThreshold) {
|
vec2_t positional;
|
||||||
controller->axisButtons |= VR_TOUCH_AXIS_DOWN;
|
float factor = (refresh / 72.0F) * 12.0f; // adjust positional factor based on refresh rate
|
||||||
Com_QueueEvent(in_vrEventTime, SE_KEY, K_DOWNARROW, qtrue, 0, NULL);
|
rotateAboutOrigin(-vr.hmdposition_delta[0] * factor * multiplier,
|
||||||
} else if ((controller->axisButtons & VR_TOUCH_AXIS_DOWN) && joystickY > -releasedThreshold) {
|
vr.hmdposition_delta[2] * factor * multiplier, - vr.hmdorientation[YAW], positional);
|
||||||
controller->axisButtons &= ~VR_TOUCH_AXIS_DOWN;
|
|
||||||
Com_QueueEvent(in_vrEventTime, SE_KEY, K_DOWNARROW, qfalse, 0, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(controller->axisButtons & VR_TOUCH_AXIS_LEFT) && joystickX < -pressedThreshold) {
|
if (VR_useScreenLayer())
|
||||||
controller->axisButtons |= VR_TOUCH_AXIS_LEFT;
|
{
|
||||||
Com_QueueEvent(in_vrEventTime, SE_KEY, K_LEFTARROW, qtrue, 0, NULL);
|
const float x = joystickX * 4.0;
|
||||||
} else if ((controller->axisButtons & VR_TOUCH_AXIS_LEFT) && joystickX > -releasedThreshold) {
|
const float y = joystickY * -4.0;
|
||||||
controller->axisButtons &= ~VR_TOUCH_AXIS_LEFT;
|
|
||||||
Com_QueueEvent(in_vrEventTime, SE_KEY, K_LEFTARROW, qfalse, 0, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
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 ) {
|
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;
|
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)) {
|
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)) {
|
} 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)) {
|
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)) {
|
} 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)) {
|
if ((buttons & ovrButton_X) && !(controller->buttons & ovrButton_B)) {
|
||||||
|
@ -143,6 +369,32 @@ void IN_VRInputFrame( void )
|
||||||
return;
|
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;
|
ovrInputCapabilityHeader capsHeader;
|
||||||
uint32_t index = 0;
|
uint32_t index = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -170,6 +422,14 @@ void IN_VRInputFrame( void )
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ovrTracking remoteTracking;
|
||||||
|
stateResult = vrapi_GetInputTrackingState(ovr, capsHeader.DeviceID, predictedDisplayTime,
|
||||||
|
&remoteTracking);
|
||||||
|
if (stateResult < 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
qboolean isRight;
|
qboolean isRight;
|
||||||
vrController_t* controller;
|
vrController_t* controller;
|
||||||
if (caps.ControllerCapabilities & ovrControllerCaps_LeftHand) {
|
if (caps.ControllerCapabilities & ovrControllerCaps_LeftHand) {
|
||||||
|
@ -183,7 +443,8 @@ void IN_VRInputFrame( void )
|
||||||
continue;
|
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);
|
IN_VRTriggers(isRight, state.IndexTrigger);
|
||||||
|
|
||||||
if (controller->buttons ^ state.Buttons) {
|
if (controller->buttons ^ state.Buttons) {
|
||||||
|
@ -194,4 +455,4 @@ void IN_VRInputFrame( void )
|
||||||
in_vrEventTime = Sys_Milliseconds( );
|
in_vrEventTime = Sys_Milliseconds( );
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
//#endif
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#if __ANDROID__
|
#if __ANDROID__
|
||||||
|
|
||||||
void IN_VRInputFrame( void );
|
void IN_VRInputFrame( void );
|
||||||
|
void IN_VRInit( void );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include "vr_base.h"
|
||||||
#include "vr_renderer.h"
|
#include "vr_renderer.h"
|
||||||
|
|
||||||
#include "../qcommon/q_shared.h"
|
#include "../qcommon/q_shared.h"
|
||||||
|
@ -6,6 +7,7 @@
|
||||||
|
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
#pragma clang diagnostic ignored "-Wstrict-prototypes"
|
#pragma clang diagnostic ignored "-Wstrict-prototypes"
|
||||||
|
#include <VrApi.h>
|
||||||
#include <VrApi_Helpers.h>
|
#include <VrApi_Helpers.h>
|
||||||
#pragma clang diagnostic pop
|
#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 ) {
|
void VR_InitRenderer( engine_t* engine ) {
|
||||||
#if ENABLE_GL_DEBUG
|
#if ENABLE_GL_DEBUG
|
||||||
glEnable(GL_DEBUG_OUTPUT);
|
glEnable(GL_DEBUG_OUTPUT);
|
||||||
|
@ -36,9 +56,8 @@ void VR_InitRenderer( engine_t* engine ) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int eyeW, eyeH;
|
int eyeW, eyeH;
|
||||||
|
VR_GetRsolution(engine, &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);
|
|
||||||
for (int eye = 0; eye < VRAPI_FRAME_LAYER_EYE_MAX; ++eye) {
|
for (int eye = 0; eye < VRAPI_FRAME_LAYER_EYE_MAX; ++eye) {
|
||||||
framebuffer_t* framebuffer = &engine->framebuffers[eye];
|
framebuffer_t* framebuffer = &engine->framebuffers[eye];
|
||||||
framebuffer->colorTexture = vrapi_CreateTextureSwapChain3(VRAPI_TEXTURE_TYPE_2D, GL_RGBA8,
|
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 ) {
|
void VR_DrawFrame( engine_t* engine ) {
|
||||||
double predictedDisplayTime;
|
double predictedDisplayTime;
|
||||||
ovrTracking2 tracking;
|
ovrTracking2 tracking;
|
||||||
ovrLayerProjection2 layer;
|
|
||||||
|
|
||||||
if (!engine->ovr)
|
if (!engine->ovr)
|
||||||
{
|
{
|
||||||
|
@ -105,37 +205,80 @@ void VR_DrawFrame( engine_t* engine ) {
|
||||||
predictedDisplayTime = vrapi_GetPredictedDisplayTime(engine->ovr, engine->frameIndex);
|
predictedDisplayTime = vrapi_GetPredictedDisplayTime(engine->ovr, engine->frameIndex);
|
||||||
tracking = vrapi_GetPredictedTracking2(engine->ovr, predictedDisplayTime);
|
tracking = vrapi_GetPredictedTracking2(engine->ovr, predictedDisplayTime);
|
||||||
|
|
||||||
layer = vrapi_DefaultLayerProjection2();
|
if (VR_useScreenLayer())
|
||||||
layer.HeadPose = tracking.HeadPose;
|
{
|
||||||
|
static ovrLayer_Union2 cylinderLayer;
|
||||||
|
memset( &cylinderLayer, 0, sizeof( ovrLayer_Union2 ) );
|
||||||
|
|
||||||
for (int eye = 0; eye < VRAPI_FRAME_LAYER_EYE_MAX; ++eye) {
|
int eyeW, eyeH;
|
||||||
layer.Textures[eye].ColorSwapChain = engine->framebuffers[eye].colorTexture;
|
VR_GetRsolution(engine, &eyeW, &eyeH);
|
||||||
layer.Textures[eye].SwapChainIndex = engine->framebuffers[eye].swapchainIndex;
|
|
||||||
layer.Textures[eye].TexCoordsFromTanAngles = ovrMatrix4f_TanAngleMatrixFromProjection(&tracking.Eye[eye].ProjectionMatrix);
|
// 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"
|
#include "vr_types.h"
|
||||||
|
|
||||||
|
void VR_GetRsolution( engine_t* engine, int *pWidth, int *pHeight );
|
||||||
void VR_InitRenderer( engine_t* engine );
|
void VR_InitRenderer( engine_t* engine );
|
||||||
void VR_DestroyRenderer( engine_t* engine );
|
void VR_DestroyRenderer( engine_t* engine );
|
||||||
void VR_DrawFrame( engine_t* engine );
|
void VR_DrawFrame( engine_t* engine );
|
||||||
|
|
|
@ -25,6 +25,7 @@ typedef struct {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint64_t frameIndex;
|
uint64_t frameIndex;
|
||||||
ovrMobile* ovr;
|
ovrMobile* ovr;
|
||||||
|
ovrJava java;
|
||||||
framebuffer_t framebuffers[VRAPI_FRAME_LAYER_EYE_MAX];
|
framebuffer_t framebuffers[VRAPI_FRAME_LAYER_EYE_MAX];
|
||||||
} engine_t;
|
} engine_t;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue