csgo-2018-source/game/client/in_trackir.cpp
2021-07-24 21:11:47 -07:00

227 lines
6.2 KiB
C++

//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: TrackIR handling function
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//=============================================================================//
#ifdef IS_WINDOWS_PC
#include <windows.h>
#endif
#include "string_t.h"
// These two have to be included very early
#include <predictableid.h>
#include <predictable_entity.h>
#include "cdll_util.h"
#include <util_shared.h>
#include "vphysics_interface.h"
#include <icvar.h>
#include <baseentity_shared.h>
#include "basehandle.h"
#include "ehandle.h"
#include "utlvector.h"
#include "cdll_client_int.h"
#include "kbutton.h"
#include "usercmd.h"
#include "iclientvehicle.h"
#include "input.h"
#include "iviewrender.h"
#include "convar.h"
#include "hud.h"
#include "vgui/isurface.h"
#include "vgui_controls/controls.h"
#include "vgui/cursor.h"
#include "tier0/icommandline.h"
#include "inputsystem/iinputsystem.h"
#include "inputsystem/ButtonCode.h"
#include "math.h"
#include "tier1/convar_serverbounded.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#ifdef IS_WINDOWS_PC
#include "npsclient.h"
#define TIR_MAX_VALUE 16383
QAngle g_angleCenter;
ConVar tir_maxyaw( "tir_maxyaw", "90", FCVAR_CHEAT, "TrackIR Max Yaw", true, 0.0, true, 180.0);
ConVar tir_maxpitch( "tir_maxpitch", "15", FCVAR_CHEAT, "TrackIR Max Pitch", true, 0.0, true, 180.0);
ConVar tir_maxroll( "tir_maxroll", "90", FCVAR_CHEAT, "TrackIR Max Roll", true, 0.0, true, 180.0);
ConVar tir_maxx( "tir_maxx", "4", FCVAR_CHEAT, "TrackIR Max X", true, 0.0, true, 50.0);
ConVar tir_maxy( "tir_maxy", "6", FCVAR_CHEAT, "TrackIR Max Y", true, 0.0, true, 50.0);
ConVar tir_maxz( "tir_maxz", "1", FCVAR_CHEAT, "TrackIR Max Z", true, 0.0, true, 50.0);
ConVar tir_start( "tir_start", "0", 0, "TrackIR Start", true, 0.0, true, 1.0);
ConVar tir_stop( "tir_stop", "0", 0, "TrackIR Stop", true, 0.0, true, 1.0);
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
return DefWindowProc(hWnd, message, wParam, lParam);
}
HWND CreateHiddenWindow()
{
HWND hWnd;
HINSTANCE hInstance = GetModuleHandle(NULL);
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = 0;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = NULL;
wcex.hCursor = NULL;
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = TEXT("HL2-TrackIR");
wcex.hIconSm = NULL;
RegisterClassEx(&wcex);
hWnd = CreateWindow(TEXT("HL2-TrackIR"), NULL, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (hWnd)
{
ShowWindow(hWnd, SW_HIDE);
UpdateWindow(hWnd);
}
return hWnd;
}
#endif
//-----------------------------------------------------------------------------
// Purpose: Init_TrackIR
//-----------------------------------------------------------------------------
void CInput::Init_TrackIR( void )
{
#ifdef IS_WINDOWS_PC
if ( !IsHeadTrackingEnabled() )
return;
ZeroMemory(&g_angleCenter, sizeof(g_angleCenter));
HWND hWnd = CreateHiddenWindow();
NPRESULT result = NPS_Init(hWnd);
// Mark the TrackIR as available and advanced initialization not completed
// this is needed as correctly set cvars are not available this early during initialization
// FIXME: Is this still the case?
Msg( "TrackIR initialized [%d]\n", result );
m_fTrackIRAvailable = true;
#endif
}
//-----------------------------------------------------------------------------
// Purpose: Init_TrackIR
//-----------------------------------------------------------------------------
void CInput::Shutdown_TrackIR( void )
{
#ifdef IS_WINDOWS_PC
if ( !IsHeadTrackingEnabled() )
return;
NPS_Shutdown();
Msg( "TrackIR shut down\n" );
#endif
}
//-----------------------------------------------------------------------------
// Purpose: Apply TrackIR to CUserCmd creation
// Input : frametime -
// *cmd -
//-----------------------------------------------------------------------------
void CInput::TrackIRMove( float frametime, CUserCmd *cmd )
{
#ifdef IS_WINDOWS_PC
if ( !IsHeadTrackingEnabled() )
return;
// complete initialization if first time in ( needed as cvars are not available at initialization time )
// verify TrackIR is available and that the user wants to use it
if (!m_fTrackIRAvailable )
{
return;
}
if (tir_start.GetFloat() == 1.0)
{
Init_TrackIR();
tir_start.SetValue(0);
}
if (tir_stop.GetFloat() == 1.0)
{
Shutdown_TrackIR();
tir_stop.SetValue(0);
}
// grab the data from the TrackIR
TRACKIRDATA tid;
NPRESULT result;
// Go get the latest data
result = NPS_GetData(&tid);
if( NP_OK == result )
{
QAngle viewangles;
QAngle engineview;
// get the current player
C_BasePlayer * pPlayer = C_BasePlayer::GetLocalPlayer();
// calculate the amount of rotation from TrackIR
viewangles[YAW] = g_angleCenter[YAW] + (tid.fNPYaw / (float) TIR_MAX_VALUE) * tir_maxyaw.GetFloat();
viewangles[PITCH] = g_angleCenter[PITCH] + (tid.fNPPitch / (float) TIR_MAX_VALUE) * tir_maxpitch.GetFloat();
viewangles[ROLL] = g_angleCenter[ROLL] + (tid.fNPRoll / (float) TIR_MAX_VALUE) * tir_maxroll.GetFloat() * -1.0;
// get the direction the player is facing
QAngle eyeAngle;
eyeAngle = pPlayer->EyeAngles();
// add in the head rotation
eyeAngle += viewangles;
// get the rotation matrix for the head
matrix3x4_t mat;
AngleMatrix( pPlayer->EyeAngles(), mat );
// create a normalized vector based on the TIR input
Vector tirForward, tirEye;
tirForward.x = (tid.fNPZ / (float) TIR_MAX_VALUE) * -1;
tirForward.y = (tid.fNPX / (float) TIR_MAX_VALUE);
tirForward.z = (tid.fNPY / (float) TIR_MAX_VALUE);
// now rotate the vector based on the eye angle
VectorRotate(tirForward, mat, tirEye);
// scale the translation vector
tirEye.x *= tir_maxz.GetFloat();
tirEye.y *= tir_maxx.GetFloat();
tirEye.z *= tir_maxy.GetFloat();
// save the values for later
pPlayer->SetEyeOffset(tirEye);
pPlayer->SetEyeAngleOffset(viewangles);
cmd->headangles = viewangles;
cmd->headoffset = tirEye;
}
#endif
}