Initial support for OpenXR. Remember to side-load the openxr plugin and set _pext_vrinputs to 1.

This commit is contained in:
Marco Cawthorne 2022-05-07 17:04:05 -07:00
parent 5e70290017
commit 9e0f93c796
Signed by: eukara
GPG Key ID: C196CD8BA993248A
19 changed files with 580 additions and 18 deletions

View File

@ -267,6 +267,30 @@ Cmd_Parse(string sCMD)
case "player_geomtest":
CMD_player_geomtest();
break;
/* XR binds, engine binds them currently */
case "+attack_left":
pSeat->m_bMoveForward = true;
break;
case "-attack_left":
pSeat->m_bMoveForward = false;
break;
case "+menu_left":
break;
case "-menu_left":
break;
case "+attack_right":
pSeat->m_iInputAttack = true;
break;
case "-attack_right":
pSeat->m_iInputAttack = false;
break;
case "+menu_right":
pSeat->m_iInputReload = TRUE;
break;
case "-menu_right":
pSeat->m_iInputReload = FALSE;
break;
default:
return (0);
}
@ -343,4 +367,14 @@ Cmd_Init(void)
/* Requested by Slacer */
registercommand("+zoomin");
registercommand("-zoomin");
/* XR binds, temporady until the engine standardizes things */
registercommand("+attack_left");
registercommand("-attack_left");
registercommand("+attack_right");
registercommand("-attack_right");
registercommand("+menu_left");
registercommand("-menu_left");
registercommand("+menu_right");
registercommand("-menu_right");
}

View File

@ -185,6 +185,7 @@ struct
string m_strPrintBuffer[5];
int m_iPrintLines;
bool m_iInputAttack;
int m_iInputAttack2;
int m_iInputReload;
int m_iInputUse;
@ -212,4 +213,7 @@ struct
/* vehicles */
float m_flVehTransition;
vector m_vecVehEntry;
/* new XR helpers */
bool m_bMoveForward;
} g_seats[4], *pSeat;

View File

@ -272,7 +272,6 @@ CSQC_UpdateView(float w, float h, float focus)
View_PreDraw();
#endif
addentities(MASK_ENGINE);
/* ideally move this into a base_player method */
@ -347,6 +346,7 @@ CSQC_UpdateView(float w, float h, float focus)
addentities(MASK_GLOWS);
setproperty(VF_DRAWWORLD, 1);
SkyCamera_Setup(getproperty(VF_ORIGIN));
XR_UpdateView(self);
/* draw the viewmodel in a second pass if desired */
if (autocvar_r_viewmodelpass && pl.health > 0) {

View File

@ -207,12 +207,25 @@ View_DrawViewModel(void)
/* now apply the scale hack */
m_eViewModelL.scale = m_eViewModel.scale = autocvar_r_viewmodelscale;
m_eViewModelL.origin = m_eViewModel.origin = pSeat->m_vecPredictedOrigin + pl.view_ofs;
m_eViewModelL.origin = pl.m_xrInputLeft.GetOrigin();
m_eViewModel.origin = pl.m_xrInputRight.GetOrigin();
/* we only calculate bob on the right model, to avoid double speed bobbing */
Viewmodel_CalcBob();
Viewmodel_ApplyBob(m_eViewModel);
Viewmodel_ApplyBob(m_eViewModelL);
if (XR_Available(pl)) {
m_eViewModel.angles = pl.m_xrInputLeft.GetAngles();
m_eViewModelL.angles = pl.m_xrInputRight.GetAngles();
} else {
/* we only calculate bob on the right model, to avoid double speed bobbing */
Viewmodel_CalcBob();
Viewmodel_ApplyBob(m_eViewModel);
Viewmodel_ApplyBob(m_eViewModelL);
/* view roll */
if (pl.movetype == MOVETYPE_WALK) {
Camera_StrafeRoll(view_angles);
Camera_RunBob(view_angles);
setproperty(VF_ANGLES, view_angles + pl.punchangle);
}
}
/* this is currently broken */
#if 0
@ -260,13 +273,6 @@ View_DrawViewModel(void)
addentity(m_eViewModel);
addentity(m_eViewModelL);
}
/* view roll */
if (pl.movetype == MOVETYPE_WALK) {
Camera_StrafeRoll(view_angles);
Camera_RunBob(view_angles);
setproperty(VF_ANGLES, view_angles + pl.punchangle);
}
}
void

View File

@ -5,6 +5,11 @@ base_client:NSSurfacePropEntity
vector origin_net;
vector velocity_net;
NSXRSpace m_xrSpace;
NSXRInput m_xrInputHead;
NSXRInput m_xrInputLeft;
NSXRInput m_xrInputRight;
void(void) base_client;
/* final input handling of the client */
@ -18,6 +23,8 @@ base_client:NSSurfacePropEntity
virtual bool(void) IsDead;
virtual bool(void) IsPlayer;
virtual void(void) OnRemoveEntity;
#ifdef CLIENT
/* gives the chance to override input variables before networking */
virtual void(void) ClientInputFrame;

View File

@ -1,3 +1,9 @@
void
base_client::OnRemoveEntity(void)
{
XR_Shutdown(this);
}
void
base_client::ClientInput(void)
{
@ -63,7 +69,7 @@ base_client::predraw(void)
void
base_client::base_client(void)
{
XR_Init(this);
}

View File

@ -41,6 +41,7 @@
#endif
#include "../gs-entbase/shared/baseentity.h"
#include "../xr/defs.h"
#include "client.h"
#include "spectator.h"
#include "player.h"

View File

@ -9,4 +9,5 @@ player.qc
player_pmove.qc
propdata.qc
surfaceproperties.qc
../xr/include.src
#endlist

View File

@ -102,6 +102,8 @@ base_player::PostFrame(void)
void
base_player::ClientInput(void)
{
XR_InputFrame(this);
if (!Client_InIntermission() && IsFakeSpectator()) {
spectator::ClientInput();
SpectatorTrackPlayer();
@ -135,6 +137,8 @@ base_player::OnRemoveEntity(void)
{
if (p_model)
remove(p_model);
super::OnRemoveEntity();
}
/*
@ -197,6 +201,17 @@ base_player::ClientInputFrame(void)
return;
}
/* some input overrides for XR */
if (XR_Available(this)) {
if (pSeat->m_bMoveForward) {
input_movevalues[0] = cvar("cl_forwardspeed");
}
if (pSeat->m_iInputAttack) {
input_buttons |= INPUT_BUTTON0;
}
}
/* compat*/
if (input_impulse == 201) {
sendevent("Spraylogo", "");
@ -931,5 +946,6 @@ base_player::InputUse_Up(void)
void
base_player::base_player(void)
{
super::spectator();
vehicle = __NULL__;
}

View File

@ -330,6 +330,10 @@ base_player::Physics_Run(void)
input_buttons = saved_input_buttons;
Physics_InputPostMove();
angles[0] = Math_FixDelta(angles[0]);
angles[1] = Math_FixDelta(angles[1]);
angles[2] = Math_FixDelta(angles[2]);
#ifdef SERVER
/* Use Flagger */
vector src, dest;
@ -345,9 +349,9 @@ base_player::Physics_Run(void)
flags |= FL_ONUSABLE;
}
}
#endif
angles[0] = Math_FixDelta(angles[0]);
angles[1] = Math_FixDelta(angles[1]);
angles[2] = Math_FixDelta(angles[2]);
m_xrSpace.SetOrigin(origin + view_ofs);
m_xrSpace.SetAngles(angles);
#endif
}

View File

@ -450,6 +450,7 @@ spectator::PostFrame(void)
void
spectator::spectator(void)
{
super::base_client();
modelindex = 0;
flags = FL_CLIENT;
SetSolid(SOLID_NOT);

59
src/xr/NSXRInput.h Normal file
View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2016-2022 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
typedef enum
{
XR_INPUT_UNKNOWN,
XR_INPUT_HEAD,
XR_INPUT_LEFT,
XR_INPUT_RIGHT
} xrinput_e;
#define XR_STATUS_ORG (1u<<0)
#define XR_STATUS_ANG (1u<<1)
#define XR_STATUS_VEL (1u<<2)
#define XR_STATUS_AVEL (1u<<3)
class
NSXRInput
{
NSXRSpace m_xrSpace;
vector m_vecOrigin;
vector m_vecAngles;
vector m_vecVelocity;
vector m_vecAVelocity;
unsigned int m_iStatus;
unsigned int m_iWeapon;
xrinput_e m_inputType;
void(void) NSXRInput;
virtual void(xrinput_e) SetType;
virtual void(NSXRSpace) SetParentSpace;
virtual vector(void) GetOrigin;
virtual vector(void) GetAngles;
virtual vector(void) GetVelocity;
virtual vector(void) GetAngularVelocity;
virtual unsigned int(void) GetStatus;
virtual unsigned int(void) GetWeapon;
virtual xrinput_e (void) GetType;
virtual bool(void) IsAvailable;
virtual void(void) InputFrame;
virtual void(void) PrintInfo;
};

149
src/xr/NSXRInput.qc Normal file
View File

@ -0,0 +1,149 @@
/*
* Copyright (c) 2016-2022 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
vector
NSXRInput::GetOrigin(void)
{
if (!m_xrSpace) {
print("WARNING: XR Space not yet present!\n");
return [0,0,0];
}
return m_xrSpace.RoomToWorldOrigin(m_vecOrigin);
}
vector
NSXRInput::GetAngles(void)
{
if (!m_xrSpace) {
print("WARNING: XR Space not yet present!\n");
return [0,0,0];
}
return m_xrSpace.RoomToWorldAngles(m_vecAngles);
}
vector
NSXRInput::GetVelocity(void)
{
return m_vecVelocity;
}
vector
NSXRInput::GetAngularVelocity(void)
{
return m_vecAVelocity;
}
unsigned int
NSXRInput::GetStatus(void)
{
return m_iStatus;
}
unsigned int
NSXRInput::GetWeapon(void)
{
return m_iWeapon;
}
xrinput_e
NSXRInput::GetType(void)
{
return m_inputType;
}
void
NSXRInput::InputFrame(void)
{
switch (m_inputType) {
case XR_INPUT_HEAD:
m_vecOrigin = input_head_origin;
m_vecAngles = input_head_angles;
m_vecVelocity = input_head_velocity;
m_vecAVelocity = input_head_avelocity;
m_iStatus = input_head_status;
m_iWeapon = input_head_weapon;
break;
case XR_INPUT_LEFT:
m_vecOrigin = input_left_origin;
m_vecAngles = input_left_angles;
m_vecVelocity = input_left_velocity;
m_vecAVelocity = input_left_avelocity;
m_iStatus = input_left_status;
m_iWeapon = input_left_weapon;
break;
case XR_INPUT_RIGHT:
m_vecOrigin = input_right_origin;
m_vecAngles = input_right_angles;
m_vecVelocity = input_right_velocity;
m_vecAVelocity = input_right_avelocity;
m_iStatus = input_right_status;
m_iWeapon = input_right_weapon;
break;
default:
print(sprintf("NSXRInput: Cannot run InputFrame() on unknown type"));
}
//PrintInfo();
}
bool
NSXRInput::IsAvailable(void)
{
/* if it's generating new origin/angles, then the device is very clearly available */
return (m_iStatus & (XR_STATUS_ORG | XR_STATUS_ANG)) ? true : false;
}
void
NSXRInput::SetType(xrinput_e type)
{
m_inputType = type;
}
void
NSXRInput::SetParentSpace(NSXRSpace xrSpace)
{
m_xrSpace = xrSpace;
}
void
NSXRInput::PrintInfo(void)
{
string deviceType;
switch (m_inputType) {
case XR_INPUT_HEAD:
deviceType = "HEAD";
break;
case XR_INPUT_LEFT:
deviceType = "LEFT";
break;
case XR_INPUT_RIGHT:
deviceType = "RIGHT";
break;
default:
print(sprintf("NSXRInput: Cannot run PrintInfo() on unknown type"));
}
crossprint(sprintf("%s o: %v a: %v v:%v va:%v s:%i w:%i\n", deviceType, GetOrigin(), GetAngles(), GetVelocity(), GetAngularVelocity(), GetStatus(), GetWeapon()));
}
void
NSXRInput::NSXRInput(void)
{
print("registered NSXRInput\n");
}

37
src/xr/NSXRSpace.h Normal file
View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2016-2022 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* class handling the room to world translations for XR */
class
NSXRSpace
{
vector m_vecForward;
vector m_vecRight;
vector m_vecUp;
vector m_vecOrigin;
void(void) NSXRSpace;
virtual void(vector) SetOrigin;
virtual void(vector) SetAngles;
virtual vector(void) GetForward;
virtual vector(void) GetRight;
virtual vector(void) GetUp;
virtual vector(vector) RoomToWorldOrigin;
virtual vector(vector) RoomToWorldAngles;
};

73
src/xr/NSXRSpace.qc Normal file
View File

@ -0,0 +1,73 @@
/*
* Copyright (c) 2016-2022 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
vector
NSXRSpace::GetForward(void)
{
return m_vecForward;
}
vector
NSXRSpace::GetRight(void)
{
return m_vecRight;
}
vector
NSXRSpace::GetUp(void)
{
return m_vecUp;
}
vector
NSXRSpace::RoomToWorldOrigin(vector vecRoomOrg)
{
vector vecOut;
vecOut = m_vecOrigin;
vecOut += (m_vecForward * vecRoomOrg[0]);
vecOut -= (m_vecRight * vecRoomOrg[1]);
vecOut += (m_vecUp * vecRoomOrg[2]);
return vecOut;
}
vector
NSXRSpace::RoomToWorldAngles(vector vecRoomAng)
{
makevectors(vecRoomAng);
rotatevectorsbyvectors(m_vecForward, m_vecRight, m_vecUp);
return vectoangles(v_forward, v_up);
}
void
NSXRSpace::SetOrigin(vector vecOrigin)
{
m_vecOrigin = vecOrigin;
}
void
NSXRSpace::SetAngles(vector vecAngles)
{
makevectors(vecAngles);
m_vecForward = v_forward;
m_vecRight = v_right;
m_vecUp = v_up;
}
void
NSXRSpace::NSXRSpace(void)
{
print("allocated NSXRSpace\n");
}

19
src/xr/defs.h Normal file
View File

@ -0,0 +1,19 @@
/*
* Copyright (c) 2016-2022 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "NSXRSpace.h"
#include "NSXRInput.h"
#include "xr.h"

5
src/xr/include.src Normal file
View File

@ -0,0 +1,5 @@
#includelist
../xr/NSXRSpace.qc
../xr/NSXRInput.qc
../xr/xr.qc
#endlist

24
src/xr/xr.h Normal file
View File

@ -0,0 +1,24 @@
/*
* Copyright (c) 2016-2022 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
void XR_Init(entity);
void XR_Shutdown(entity);
bool XR_Available(entity);
void XR_InputFrame(entity);
#ifdef CLIENT
void XR_UpdateView(entity);
#endif

116
src/xr/xr.qc Normal file
View File

@ -0,0 +1,116 @@
/*
* Copyright (c) 2016-2022 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
The engine provides us with 3 devices right now, each giving us
their position, angle etc. as well as field stating which bits
of information have gotten updated.
If no updates are happening from the HMD/head, that means we're
most like not in VR, or the player has taken the headset off and
laid it down.
If we have no updates from the left and right XR devices, we
will use the regular input_angles and view position for weapons.
*/
void
XR_Init(entity ePlayer)
{
base_client pl = (base_client)ePlayer;
print("--------- Initializing XR ----------\n");
pl.m_xrSpace = spawn(NSXRSpace);
/* the only 3 devices that matter right now */
pl.m_xrInputHead = spawn(NSXRInput);
pl.m_xrInputHead.SetType(XR_INPUT_HEAD);
pl.m_xrInputHead.SetParentSpace(pl.m_xrSpace);
pl.m_xrInputLeft = spawn(NSXRInput);
pl.m_xrInputLeft.SetType(XR_INPUT_LEFT);
pl.m_xrInputLeft.SetParentSpace(pl.m_xrSpace);
pl.m_xrInputRight = spawn(NSXRInput);
pl.m_xrInputRight.SetType(XR_INPUT_RIGHT);
pl.m_xrInputRight.SetParentSpace(pl.m_xrSpace);
}
void
XR_Shutdown(entity ePlayer)
{
base_client pl = (base_client)ePlayer;
remove(pl.m_xrInputHead);
remove(pl.m_xrInputLeft);
remove(pl.m_xrInputRight);
}
#ifdef CLIENT
void
XR_UpdateView(entity ePlayer)
{
base_client pl = (base_client)ePlayer;
/* not yet ready */
if (!pl.m_xrSpace)
return;
/* update our space */
pl.m_xrSpace.SetOrigin(pSeat->m_vecPredictedOrigin + pSeat->m_ePlayer.view_ofs);
pl.m_xrSpace.SetAngles(input_angles);
/* now we get the HMD's org/ang and send that off to the renderer */
setviewprop(VF_ANGLES, pl.m_xrInputHead.GetAngles());
setviewprop(VF_ORIGIN, pl.m_xrInputHead.GetOrigin());
}
#endif
void
XR_InputFrame(entity ePlayer)
{
base_client pl = (base_client)ePlayer;
/* not yet ready */
if (!pl.m_xrSpace)
return;
if (autocvar(debug_fakevr, 0)) {
input_head_status = (XR_STATUS_ORG | XR_STATUS_ANG);
input_left_status = (XR_STATUS_ORG | XR_STATUS_ANG);
input_right_status = (XR_STATUS_ORG | XR_STATUS_ANG);
input_head_angles = [sin(time), sin(time * 1.25) * 5, sin(time * 1.45)];
input_left_angles = [cos(time) * 5,cos(time) * 25,sin(time) * 5];
input_right_angles = [cos(time) * 5,cos(time) * 25,sin(time) * 5];
input_head_origin = [sin(time)*5,cos(time)*5,sin(time)*5];
input_left_origin = input_head_origin + [cos(time*8) * 2,4,sin(time*8) * 2];
input_right_origin = input_head_origin + [cos(time*8) * 2,-4,sin(time*8) * 2];
}
/* update the input internals for keeping track*/
pl.m_xrInputHead.InputFrame();
pl.m_xrInputLeft.InputFrame();
pl.m_xrInputRight.InputFrame();
}
bool
XR_Available(entity ePlayer)
{
base_client pl = (base_client)ePlayer;
/* we only care about the HMD... otherwise why even bother? */
return pl.m_xrInputHead.IsAvailable();
}