mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-26 05:41:52 +00:00
OpenXR stuff should be a little more usable now.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5850 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
13d524a30b
commit
f35928f4fd
25 changed files with 360 additions and 353 deletions
|
@ -49,7 +49,8 @@ static cvar_t cl_sendchatstate = CVARD("cl_sendchatstate", "1", "Announce your c
|
||||||
|
|
||||||
cvar_t cl_prydoncursor = CVAR("cl_prydoncursor", ""); //for dp protocol
|
cvar_t cl_prydoncursor = CVAR("cl_prydoncursor", ""); //for dp protocol
|
||||||
cvar_t cl_instantrotate = CVARF("cl_instantrotate", "1", CVAR_SEMICHEAT);
|
cvar_t cl_instantrotate = CVARF("cl_instantrotate", "1", CVAR_SEMICHEAT);
|
||||||
cvar_t in_xflip = {"in_xflip", "0"};
|
cvar_t in_xflip = CVAR("in_xflip", "0");
|
||||||
|
cvar_t in_vraim = CVARD("in_vraim", "1", "When set to 1, the 'view' angle sent to the server is controlled by your vr headset instead of separately. This is for fallback behaviour and blocks mouse+joy+gamepad aiming.");
|
||||||
|
|
||||||
cvar_t prox_inmenu = CVAR("prox_inmenu", "0");
|
cvar_t prox_inmenu = CVAR("prox_inmenu", "0");
|
||||||
|
|
||||||
|
@ -915,7 +916,7 @@ void CL_BaseMove (usercmd_t *cmd, int pnum, float priortime, float extratime)
|
||||||
float nscale = extratime?extratime / (extratime+priortime):0;
|
float nscale = extratime?extratime / (extratime+priortime):0;
|
||||||
float oscale = 1 - nscale;
|
float oscale = 1 - nscale;
|
||||||
|
|
||||||
cmd->fservertime = cl.time*1000;
|
cmd->fservertime = cl.time;
|
||||||
cmd->servertime = cl.time*1000;
|
cmd->servertime = cl.time*1000;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -940,7 +941,7 @@ void CL_BaseMove (usercmd_t *cmd, int pnum, float priortime, float extratime)
|
||||||
CL_GatherButtons(cmd, pnum);
|
CL_GatherButtons(cmd, pnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CL_ClampPitch (int pnum, float frametime)
|
void CL_ClampPitch (int pnum, float frametime)
|
||||||
{
|
{
|
||||||
float mat[16];
|
float mat[16];
|
||||||
float roll;
|
float roll;
|
||||||
|
@ -1097,6 +1098,30 @@ static void CL_ClampPitch (int pnum, float frametime)
|
||||||
pv->viewangles[YAW] *= 360;
|
pv->viewangles[YAW] *= 360;
|
||||||
VectorClear(pv->viewanglechange);
|
VectorClear(pv->viewanglechange);
|
||||||
|
|
||||||
|
if (in_vraim.ival && (pv->vrdev[VRDEV_HEAD].status&VRSTATUS_ANG))
|
||||||
|
{ //overcomplicated code to replace the pitch+roll angles and add to the yaw angle.
|
||||||
|
#if 0
|
||||||
|
matrix3x4 base, head, res;
|
||||||
|
vec3_t na = {0, pv->viewangles[YAW], 0};
|
||||||
|
vec3_t f,l,u,o;
|
||||||
|
Matrix3x4_RM_FromAngles(na, vec3_origin, base[0]);
|
||||||
|
for (i=0 ; i<3 ; i++)
|
||||||
|
na[i] = SHORT2ANGLE(pv->vrdev[VRDEV_HEAD].angles[i]);
|
||||||
|
Matrix3x4_RM_FromAngles(na, pv->vrdev[VRDEV_HEAD].origin, head[0]);
|
||||||
|
Matrix3x4_Multiply(head[0], base[0], res[0]);
|
||||||
|
Matrix3x4_RM_ToVectors(res[0], f,l,u,o);
|
||||||
|
VectorAngles(f,u,pv->aimangles,false);
|
||||||
|
for (i=0 ; i<3 ; i++)
|
||||||
|
cmd->angles[i] = ANGLE2SHORT(na[i]);
|
||||||
|
#else
|
||||||
|
pv->aimangles[PITCH] = SHORT2ANGLE(pv->vrdev[VRDEV_HEAD].angles[PITCH]);
|
||||||
|
pv->aimangles[YAW] = SHORT2ANGLE(pv->vrdev[VRDEV_HEAD].angles[YAW]) + pv->viewangles[YAW];
|
||||||
|
pv->aimangles[ROLL] = SHORT2ANGLE(pv->vrdev[VRDEV_HEAD].angles[ROLL]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
VectorCopy(pv->viewangles, pv->aimangles);
|
||||||
|
|
||||||
#ifdef Q2CLIENT
|
#ifdef Q2CLIENT
|
||||||
if (cls.protocol == CP_QUAKE2)
|
if (cls.protocol == CP_QUAKE2)
|
||||||
{
|
{
|
||||||
|
@ -1129,6 +1154,11 @@ static void CL_ClampPitch (int pnum, float frametime)
|
||||||
pv->viewangles[PITCH] = cl.maxpitch;
|
pv->viewangles[PITCH] = cl.maxpitch;
|
||||||
if (pv->viewangles[PITCH] < cl.minpitch)
|
if (pv->viewangles[PITCH] < cl.minpitch)
|
||||||
pv->viewangles[PITCH] = cl.minpitch;
|
pv->viewangles[PITCH] = cl.minpitch;
|
||||||
|
|
||||||
|
if (pv->aimangles[PITCH] > cl.maxpitch)
|
||||||
|
pv->aimangles[PITCH] = cl.maxpitch;
|
||||||
|
if (pv->aimangles[PITCH] < cl.minpitch)
|
||||||
|
pv->aimangles[PITCH] = cl.minpitch;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (cl.viewangles[pnum][ROLL] > 50)
|
// if (cl.viewangles[pnum][ROLL] > 50)
|
||||||
|
@ -1169,7 +1199,10 @@ static void CL_FinishMove (usercmd_t *cmd, int pnum)
|
||||||
CL_GatherButtons(cmd, pnum);
|
CL_GatherButtons(cmd, pnum);
|
||||||
|
|
||||||
for (i=0 ; i<3 ; i++)
|
for (i=0 ; i<3 ; i++)
|
||||||
cmd->angles[i] = ((int)(cl.playerview[pnum].viewangles[i]*65536.0/360)&65535);
|
cmd->angles[i] = (int)(ANGLE2SHORT(cl.playerview[pnum].aimangles[i]))&65535;
|
||||||
|
cmd->vr[VRDEV_LEFT] = cl.playerview[pnum].vrdev[VRDEV_LEFT];
|
||||||
|
cmd->vr[VRDEV_RIGHT] = cl.playerview[pnum].vrdev[VRDEV_RIGHT];
|
||||||
|
cmd->vr[VRDEV_HEAD] = cl.playerview[pnum].vrdev[VRDEV_HEAD];
|
||||||
|
|
||||||
if (in_impulsespending[pnum] && !cl.paused)
|
if (in_impulsespending[pnum] && !cl.paused)
|
||||||
{
|
{
|
||||||
|
@ -2559,6 +2592,7 @@ void CL_InitInput (void)
|
||||||
|
|
||||||
Cvar_Register (&cl_fastaccel, inputnetworkcvargroup);
|
Cvar_Register (&cl_fastaccel, inputnetworkcvargroup);
|
||||||
Cvar_Register (&in_xflip, inputnetworkcvargroup);
|
Cvar_Register (&in_xflip, inputnetworkcvargroup);
|
||||||
|
Cvar_Register (&in_vraim, inputnetworkcvargroup);
|
||||||
Cvar_Register (&cl_nodelta, inputnetworkcvargroup);
|
Cvar_Register (&cl_nodelta, inputnetworkcvargroup);
|
||||||
|
|
||||||
Cvar_Register (&prox_inmenu, inputnetworkcvargroup);
|
Cvar_Register (&prox_inmenu, inputnetworkcvargroup);
|
||||||
|
|
|
@ -5978,55 +5978,6 @@ qboolean Host_RunFile(const char *fname, int nlen, vfsfile_t *file)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CL_UpdateHeadAngles(void)
|
|
||||||
{
|
|
||||||
/*FIXME: no idea what I'm doing with this. lets just not break anything for now
|
|
||||||
//identity, for now
|
|
||||||
vec3_t headchange[3] =
|
|
||||||
{
|
|
||||||
{1,0,0},
|
|
||||||
{0,1,0},
|
|
||||||
{0,0,1}
|
|
||||||
};
|
|
||||||
vec3_t tmp[3], tmp2[3];
|
|
||||||
playerview_t *pv = &cl.playerview[0];
|
|
||||||
|
|
||||||
tmp2[0][0] = 0;
|
|
||||||
tmp2[0][1] = host_frametime*90;
|
|
||||||
tmp2[0][2] = 0;
|
|
||||||
AngleVectorsFLU(tmp2[0], headchange[0], headchange[1], headchange[2]);
|
|
||||||
|
|
||||||
switch(cl_headmode.ival)
|
|
||||||
{
|
|
||||||
case 3: //head angles change both
|
|
||||||
R_ConcatRotations(headchange, r_refdef.headaxis, tmp);
|
|
||||||
break;
|
|
||||||
case 2: //head changes are entirely relative to the 'view' angle
|
|
||||||
R_ConcatRotations(headchange, r_refdef.headaxis, tmp);
|
|
||||||
memcpy(r_refdef.headaxis, tmp, sizeof(r_refdef.headaxis));
|
|
||||||
break;
|
|
||||||
case 1: //head changes change the view angle directly.
|
|
||||||
|
|
||||||
AngleVectorsFLU(pv->viewangles, tmp[0], tmp[1], tmp[2]);
|
|
||||||
R_ConcatRotations(headchange, tmp, tmp2);
|
|
||||||
VectorAngles(tmp2[0], tmp2[2], pv->viewangles);
|
|
||||||
pv->viewangles[0] *= r_meshpitch.value;
|
|
||||||
pv->viewangles[2] *= r_meshroll.value;
|
|
||||||
|
|
||||||
//fall through
|
|
||||||
default:
|
|
||||||
case 0: //off
|
|
||||||
VectorSet(r_refdef.headaxis[0], 1, 0, 0);
|
|
||||||
VectorSet(r_refdef.headaxis[1], 0, 1, 0);
|
|
||||||
VectorSet(r_refdef.headaxis[2], 0, 0, 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
VectorSet(r_refdef.headaxis[0], 1, 0, 0);
|
|
||||||
VectorSet(r_refdef.headaxis[1], 0, 1, 0);
|
|
||||||
VectorSet(r_refdef.headaxis[2], 0, 0, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
==================
|
==================
|
||||||
Host_Frame
|
Host_Frame
|
||||||
|
@ -6363,8 +6314,6 @@ double Host_Frame (double time)
|
||||||
if (emscriptenfte_getvrframedata())
|
if (emscriptenfte_getvrframedata())
|
||||||
r_refdef.stereomethod = STEREO_WEBVR;
|
r_refdef.stereomethod = STEREO_WEBVR;
|
||||||
#endif
|
#endif
|
||||||
CL_UpdateHeadAngles();
|
|
||||||
|
|
||||||
{
|
{
|
||||||
RSpeedMark();
|
RSpeedMark();
|
||||||
vid.ime_allow = false;
|
vid.ime_allow = false;
|
||||||
|
|
|
@ -1036,7 +1036,7 @@ void CL_PredictMovePNum (int seat)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lerpangles = (cls.demoplayback == DPB_QUAKEWORLD);
|
lerpangles = (cls.demoplayback == DPB_QUAKEWORLD);
|
||||||
VectorCopy (pv->viewangles, pv->simangles);
|
VectorCopy (pv->aimangles, pv->simangles);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -661,6 +661,7 @@ struct playerview_s
|
||||||
// the client maintains its own idea of view angles, which are
|
// the client maintains its own idea of view angles, which are
|
||||||
// sent to the server each frame. And only reset at level change
|
// sent to the server each frame. And only reset at level change
|
||||||
// and teleport times
|
// and teleport times
|
||||||
|
vec3_t aimangles; //angles actually being sent to the server (different due to in_vraim)
|
||||||
vec3_t viewangles; //current angles
|
vec3_t viewangles; //current angles
|
||||||
vec3_t viewanglechange; //angles set by input code this frame
|
vec3_t viewanglechange; //angles set by input code this frame
|
||||||
vec3_t intermissionangles; //absolute angles for intermission
|
vec3_t intermissionangles; //absolute angles for intermission
|
||||||
|
@ -773,6 +774,8 @@ struct playerview_s
|
||||||
size_t reverbtype;
|
size_t reverbtype;
|
||||||
vec3_t velocity;
|
vec3_t velocity;
|
||||||
} audio;
|
} audio;
|
||||||
|
|
||||||
|
struct vrdevinfo_s vrdev[VRDEV_COUNT];
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -1092,6 +1092,7 @@ qboolean IN_SetHandPosition(const char *devname, vec3_t org, vec3_t ang, vec3_t
|
||||||
{
|
{
|
||||||
int dtype;
|
int dtype;
|
||||||
int seat;
|
int seat;
|
||||||
|
struct vrdevinfo_s *dev;
|
||||||
if (!strncmp(devname, "left", 4))
|
if (!strncmp(devname, "left", 4))
|
||||||
{
|
{
|
||||||
seat = atoi(devname+4);
|
seat = atoi(devname+4);
|
||||||
|
@ -1111,23 +1112,35 @@ qboolean IN_SetHandPosition(const char *devname, vec3_t org, vec3_t ang, vec3_t
|
||||||
return false; //no idea what you're talking about.
|
return false; //no idea what you're talking about.
|
||||||
if (seat < 0 || seat >= MAX_SPLITS)
|
if (seat < 0 || seat >= MAX_SPLITS)
|
||||||
return false; //duuuude!
|
return false; //duuuude!
|
||||||
cl_pendingcmd[seat].vr[dtype].status =
|
dev = &cl.playerview[seat].vrdev[dtype];
|
||||||
|
|
||||||
|
if (org)
|
||||||
|
VectorCopy(org, dev->origin);
|
||||||
|
else
|
||||||
|
VectorClear(dev->origin);
|
||||||
|
if (ang)
|
||||||
|
{
|
||||||
|
dev->angles[0] = ANGLE2SHORT(ang[0]),
|
||||||
|
dev->angles[1] = ANGLE2SHORT(ang[1]),
|
||||||
|
dev->angles[2] = ANGLE2SHORT(ang[2]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
VectorClear(dev->angles);
|
||||||
|
if (vel)
|
||||||
|
VectorCopy(vel, dev->velocity);
|
||||||
|
else
|
||||||
|
VectorClear(dev->velocity);
|
||||||
|
if (avel)
|
||||||
|
dev->avelocity[0] = ANGLE2SHORT(avel[0]),
|
||||||
|
dev->avelocity[1] = ANGLE2SHORT(avel[1]),
|
||||||
|
dev->avelocity[2] = ANGLE2SHORT(avel[2]);
|
||||||
|
else
|
||||||
|
VectorClear(dev->avelocity);
|
||||||
|
|
||||||
|
dev->status =
|
||||||
(org ?VRSTATUS_ORG:0)|
|
(org ?VRSTATUS_ORG:0)|
|
||||||
(ang ?VRSTATUS_ANG:0)|
|
(ang ?VRSTATUS_ANG:0)|
|
||||||
(vel ?VRSTATUS_VEL:0)|
|
(vel ?VRSTATUS_VEL:0)|
|
||||||
(avel?VRSTATUS_AVEL:0);
|
(avel?VRSTATUS_AVEL:0);
|
||||||
|
|
||||||
if (org)
|
|
||||||
VectorCopy(org, cl_pendingcmd[seat].vr[dtype].origin);
|
|
||||||
if (ang)
|
|
||||||
cl_pendingcmd[seat].vr[dtype].angles[0] = ANGLE2SHORT(ang[0]),
|
|
||||||
cl_pendingcmd[seat].vr[dtype].angles[1] = ANGLE2SHORT(ang[1]),
|
|
||||||
cl_pendingcmd[seat].vr[dtype].angles[2] = ANGLE2SHORT(ang[2]);
|
|
||||||
if (vel)
|
|
||||||
VectorCopy(vel, cl_pendingcmd[seat].vr[dtype].velocity);
|
|
||||||
if (avel)
|
|
||||||
cl_pendingcmd[seat].vr[dtype].avelocity[0] = ANGLE2SHORT(avel[0]),
|
|
||||||
cl_pendingcmd[seat].vr[dtype].avelocity[1] = ANGLE2SHORT(avel[1]),
|
|
||||||
cl_pendingcmd[seat].vr[dtype].avelocity[2] = ANGLE2SHORT(avel[2]);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,6 +90,7 @@ cvar_t pr_csqc_formenus = CVAR("pr_csqc_formenus", "0");
|
||||||
#endif
|
#endif
|
||||||
static cvar_t dpcompat_csqcinputeventtypes = CVARD("dpcompat_csqcinputeventtypes", "999999", "Specifies the first csqc input event that the mod does not recognise. This should never have been a thing, but some mods are simply too buggy.");
|
static cvar_t dpcompat_csqcinputeventtypes = CVARD("dpcompat_csqcinputeventtypes", "999999", "Specifies the first csqc input event that the mod does not recognise. This should never have been a thing, but some mods are simply too buggy.");
|
||||||
extern cvar_t dpcompat_stats;
|
extern cvar_t dpcompat_stats;
|
||||||
|
extern cvar_t in_vraim;
|
||||||
|
|
||||||
// standard effect cvars/sounds
|
// standard effect cvars/sounds
|
||||||
extern cvar_t r_explosionlight;
|
extern cvar_t r_explosionlight;
|
||||||
|
@ -2244,6 +2245,12 @@ nogameaccess:
|
||||||
*r = r_refdef.viewangles[parametertype-VF_ANGLES_X];
|
*r = r_refdef.viewangles[parametertype-VF_ANGLES_X];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case VF_VRBASEORIENTATION:
|
||||||
|
if (csqc_nogameaccess && prinst == csqc_world.progs)
|
||||||
|
goto nogameaccess;
|
||||||
|
VectorCopy(r_refdef.base_angles, r);
|
||||||
|
break;
|
||||||
|
|
||||||
case VF_CL_VIEWANGLES_V:
|
case VF_CL_VIEWANGLES_V:
|
||||||
if (csqc_nogameaccess && prinst == csqc_world.progs)
|
if (csqc_nogameaccess && prinst == csqc_world.progs)
|
||||||
goto nogameaccess;
|
goto nogameaccess;
|
||||||
|
@ -2510,6 +2517,13 @@ void QCBUILTIN PF_R_SetViewFlag(pubprogfuncs_t *prinst, struct globalvars_s *pr_
|
||||||
r_refdef.viewangles[parametertype-VF_ANGLES_X] = *p;
|
r_refdef.viewangles[parametertype-VF_ANGLES_X] = *p;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case VF_VRBASEORIENTATION:
|
||||||
|
in_vraim.ival = 0; //csqc mod with explicit vr stuff.
|
||||||
|
r_refdef.base_known = true;
|
||||||
|
VectorCopy(p, r_refdef.base_angles);
|
||||||
|
VectorCopy(G_VECTOR(OFS_PARM2), r_refdef.base_origin);
|
||||||
|
break;
|
||||||
|
|
||||||
case VF_CL_VIEWANGLES_V:
|
case VF_CL_VIEWANGLES_V:
|
||||||
if (csqc_playerview)
|
if (csqc_playerview)
|
||||||
VectorCopy(p, csqc_playerview->viewangles);
|
VectorCopy(p, csqc_playerview->viewangles);
|
||||||
|
@ -3823,7 +3837,7 @@ static void cs_set_input_state (usercmd_t *cmd)
|
||||||
if (csqcg.input_servertime)
|
if (csqcg.input_servertime)
|
||||||
*csqcg.input_servertime = cmd->fservertime;
|
*csqcg.input_servertime = cmd->fservertime;
|
||||||
if (csqcg.input_clienttime)
|
if (csqcg.input_clienttime)
|
||||||
*csqcg.input_clienttime = cmd->fclienttime/1000.0f;
|
*csqcg.input_clienttime = cmd->fclienttime;
|
||||||
|
|
||||||
if (csqcg.input_cursor_screen)
|
if (csqcg.input_cursor_screen)
|
||||||
{
|
{
|
||||||
|
@ -3922,7 +3936,10 @@ static void cs_get_input_state (usercmd_t *cmd)
|
||||||
if (csqcg.input_weapon)
|
if (csqcg.input_weapon)
|
||||||
cmd->weapon = *csqcg.input_weapon;
|
cmd->weapon = *csqcg.input_weapon;
|
||||||
if (csqcg.input_servertime)
|
if (csqcg.input_servertime)
|
||||||
|
{
|
||||||
cmd->fservertime = *csqcg.input_servertime;
|
cmd->fservertime = *csqcg.input_servertime;
|
||||||
|
cmd->servertime = *csqcg.input_servertime*1000;
|
||||||
|
}
|
||||||
|
|
||||||
if (csqcg.input_cursor_screen)
|
if (csqcg.input_cursor_screen)
|
||||||
Vector2Copy(csqcg.input_cursor_screen, cmd->cursor_screen);
|
Vector2Copy(csqcg.input_cursor_screen, cmd->cursor_screen);
|
||||||
|
@ -4064,6 +4081,11 @@ static void QCBUILTIN PF_cs_getinputstate (pubprogfuncs_t *prinst, struct global
|
||||||
if (!cmd->msec)
|
if (!cmd->msec)
|
||||||
*cmd = cl.outframes[(f-1)&UPDATE_MASK].cmd[seat];
|
*cmd = cl.outframes[(f-1)&UPDATE_MASK].cmd[seat];
|
||||||
cmd->msec = (realtime - cl.outframes[(f-1)&UPDATE_MASK].senttime)*1000;
|
cmd->msec = (realtime - cl.outframes[(f-1)&UPDATE_MASK].senttime)*1000;
|
||||||
|
|
||||||
|
//make sure we have the latest info...
|
||||||
|
cmd->vr[VRDEV_LEFT] = csqc_playerview->vrdev[VRDEV_LEFT];
|
||||||
|
cmd->vr[VRDEV_RIGHT] = csqc_playerview->vrdev[VRDEV_RIGHT];
|
||||||
|
cmd->vr[VRDEV_HEAD] = csqc_playerview->vrdev[VRDEV_HEAD];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -7752,6 +7774,8 @@ void CSQC_Shutdown(void)
|
||||||
memset(&csqc_world, 0, sizeof(csqc_world));
|
memset(&csqc_world, 0, sizeof(csqc_world));
|
||||||
memset(&csqcg, 0, sizeof(csqcg));
|
memset(&csqcg, 0, sizeof(csqcg));
|
||||||
|
|
||||||
|
in_vraim.ival = in_vraim.value; //csqc mod with explicit vr stuff.
|
||||||
|
|
||||||
if (csqc_deprecated_warned>1)
|
if (csqc_deprecated_warned>1)
|
||||||
{
|
{
|
||||||
if (!cl_csqc_nodeprecate.ival)
|
if (!cl_csqc_nodeprecate.ival)
|
||||||
|
|
|
@ -260,10 +260,12 @@ typedef struct
|
||||||
vec3_t vieworg; /*logical view center*/
|
vec3_t vieworg; /*logical view center*/
|
||||||
vec3_t viewangles;
|
vec3_t viewangles;
|
||||||
vec3_t viewaxis[3]; /*forward, left, up (NOT RIGHT)*/
|
vec3_t viewaxis[3]; /*forward, left, up (NOT RIGHT)*/
|
||||||
vec3_t headaxis[3]; /*this is for head mounted displays. this is relative to the view*/
|
|
||||||
vec3_t eyeoffset; /*world space, for vr screenies*/
|
vec3_t eyeoffset; /*world space, for vr screenies*/
|
||||||
vec2_t projectionoffset; /*for off-centre rendering*/
|
vec2_t projectionoffset; /*for off-centre rendering*/
|
||||||
|
|
||||||
|
qboolean base_known; /*otherwise we do some fallback behaviour (ie: viewangles.0y0 and forcing input_angles)*/
|
||||||
|
vec3_t base_angles, base_origin; /*for vr output, overrides per-eye viewangles according to that eye's matrix.*/
|
||||||
|
|
||||||
float fov_x, fov_y, afov;
|
float fov_x, fov_y, afov;
|
||||||
float fovv_x, fovv_y; //viewmodel fovs
|
float fovv_x, fovv_y; //viewmodel fovs
|
||||||
float mindist, maxdist; //maxdist may be 0, for 'infinite', in which case mindist probably isn't valid either.
|
float mindist, maxdist; //maxdist may be 0, for 'infinite', in which case mindist probably isn't valid either.
|
||||||
|
|
|
@ -326,7 +326,11 @@ void V_DriftPitch (playerview_t *pv)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef QUAKESTATS
|
||||||
|
delta = pv->statsf[STAT_IDEALPITCH] - pv->viewangles[PITCH];
|
||||||
|
#else
|
||||||
delta = 0 - pv->viewangles[PITCH];
|
delta = 0 - pv->viewangles[PITCH];
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!delta)
|
if (!delta)
|
||||||
{
|
{
|
||||||
|
|
|
@ -74,7 +74,7 @@ typedef struct plugvrfuncs_s
|
||||||
qboolean (*Prepare) (vrsetup_t *setupinfo); //called before graphics context init
|
qboolean (*Prepare) (vrsetup_t *setupinfo); //called before graphics context init
|
||||||
qboolean (*Init) (vrsetup_t *setupinfo, rendererstate_t *info); //called after graphics context init
|
qboolean (*Init) (vrsetup_t *setupinfo, rendererstate_t *info); //called after graphics context init
|
||||||
qboolean (*SyncFrame)(double *frametime); //called in the client's main loop, to block/tweak frame times. True means the game should render as fast as possible.
|
qboolean (*SyncFrame)(double *frametime); //called in the client's main loop, to block/tweak frame times. True means the game should render as fast as possible.
|
||||||
qboolean (*Render) (void(*rendereye)(texid_t tex, vec4_t fovoverride, matrix3x4 axisorg));
|
qboolean (*Render) (void(*rendereye)(texid_t tex, vec4_t fovoverride, vec3_t angorg[2]));
|
||||||
void (*Shutdown) (void);
|
void (*Shutdown) (void);
|
||||||
#define plugvrfuncs_name "VR"
|
#define plugvrfuncs_name "VR"
|
||||||
} plugvrfuncs_t;
|
} plugvrfuncs_t;
|
||||||
|
|
|
@ -245,10 +245,10 @@ typedef struct
|
||||||
int position;
|
int position;
|
||||||
int size;
|
int size;
|
||||||
} texwadlump_t;
|
} texwadlump_t;
|
||||||
int numwadtextures;
|
static int numwadtextures;
|
||||||
static texwadlump_t texwadlump[TEXWAD_MAXIMAGES];
|
static texwadlump_t texwadlump[TEXWAD_MAXIMAGES];
|
||||||
|
|
||||||
wadfile_t *openwadfiles;
|
static wadfile_t *openwadfiles;
|
||||||
|
|
||||||
void Wads_Flush (void)
|
void Wads_Flush (void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -772,6 +772,39 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#define fte_alignof(type) sizeof(qintptr_t)
|
#define fte_alignof(type) sizeof(qintptr_t)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//WARNING: FTE_CONSTRUCTOR things are unordered.
|
||||||
|
#ifdef __cplusplus
|
||||||
|
//use standard constructors in any c++ code...
|
||||||
|
#define FTE_CONSTRUCTOR(fn) \
|
||||||
|
static void fn(void); \
|
||||||
|
class atinit_##fn {atinit_##fn(void){fn();}}; \
|
||||||
|
static void fn(void)
|
||||||
|
#elif _MSC_VER
|
||||||
|
#pragma section(".CRT$XCU",read)
|
||||||
|
#if _MSC_VER >= 1500 //use '/include' so it doesn't get stripped from linker optimisations
|
||||||
|
#define INITIALIZER2_(f,p) \
|
||||||
|
static void f(void); \
|
||||||
|
__declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \
|
||||||
|
__pragma(comment(linker,"/include:" p #f "_")) \
|
||||||
|
static void f(void)
|
||||||
|
#else // '/include' doesn't exist, hope there's no linker optimisations.
|
||||||
|
#define INITIALIZER2_(f,p) \
|
||||||
|
static void f(void); \
|
||||||
|
__declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \
|
||||||
|
static void f(void)
|
||||||
|
#endif
|
||||||
|
#ifdef _WIN64
|
||||||
|
#define INITIALIZER(f) INITIALIZER2_(f,"")
|
||||||
|
#else
|
||||||
|
#define INITIALIZER(f) INITIALIZER2_(f,"_")
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
//assume gcc/clang...
|
||||||
|
#define FTE_CONSTRUCTOR(fn) \
|
||||||
|
__attribute__((constructor)) static void fn(void)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//safeswitch(foo){safedefault: break;}
|
//safeswitch(foo){safedefault: break;}
|
||||||
//switch, but errors for any omitted enum values despite the presence of a default case.
|
//switch, but errors for any omitted enum values despite the presence of a default case.
|
||||||
//(gcc will generally give warnings without the default, but sometimes you don't have control over the source of your enumeration values)
|
//(gcc will generally give warnings without the default, but sometimes you don't have control over the source of your enumeration values)
|
||||||
|
|
|
@ -500,7 +500,7 @@ typedef struct
|
||||||
|
|
||||||
#define FTECONTENTS_EMPTY 0x00000000
|
#define FTECONTENTS_EMPTY 0x00000000
|
||||||
#define FTECONTENTS_SOLID 0x00000001
|
#define FTECONTENTS_SOLID 0x00000001
|
||||||
//q2window 0x00000002
|
#define FTECONTENTS_WINDOW 0x00000002 //solid to bullets, but not sight/agro
|
||||||
//q2aux 0x00000004
|
//q2aux 0x00000004
|
||||||
#define FTECONTENTS_LAVA 0x00000008
|
#define FTECONTENTS_LAVA 0x00000008
|
||||||
#define FTECONTENTS_SLIME 0x00000010
|
#define FTECONTENTS_SLIME 0x00000010
|
||||||
|
@ -656,8 +656,8 @@ typedef struct
|
||||||
|
|
||||||
// content masks. Allow q2contents_window in here
|
// content masks. Allow q2contents_window in here
|
||||||
//#define MASK_ALL (-1)
|
//#define MASK_ALL (-1)
|
||||||
#define MASK_WORLDSOLID (FTECONTENTS_SOLID|Q2CONTENTS_WINDOW) /*default trace type for something simple that ignores non-bsp stuff*/
|
#define MASK_WORLDSOLID (FTECONTENTS_SOLID|FTECONTENTS_WINDOW) /*default trace type for something simple that ignores non-bsp stuff*/
|
||||||
#define MASK_POINTSOLID (FTECONTENTS_SOLID|Q2CONTENTS_WINDOW|FTECONTENTS_BODY) /*default trace type for an entity of no size*/
|
#define MASK_POINTSOLID (FTECONTENTS_SOLID|FTECONTENTS_WINDOW|FTECONTENTS_BODY) /*default trace type for an entity of no size*/
|
||||||
#define MASK_BOXSOLID (FTECONTENTS_SOLID|FTECONTENTS_PLAYERCLIP|Q2CONTENTS_WINDOW|FTECONTENTS_BODY) /*default trace type for an entity that does have size*/
|
#define MASK_BOXSOLID (FTECONTENTS_SOLID|FTECONTENTS_PLAYERCLIP|Q2CONTENTS_WINDOW|FTECONTENTS_BODY) /*default trace type for an entity that does have size*/
|
||||||
#define MASK_PLAYERSOLID MASK_BOXSOLID
|
#define MASK_PLAYERSOLID MASK_BOXSOLID
|
||||||
//#define MASK_DEADSOLID (Q2CONTENTS_SOLID|Q2CONTENTS_PLAYERCLIP|Q2CONTENTS_WINDOW)
|
//#define MASK_DEADSOLID (Q2CONTENTS_SOLID|Q2CONTENTS_PLAYERCLIP|Q2CONTENTS_WINDOW)
|
||||||
|
|
|
@ -787,12 +787,12 @@ typedef enum
|
||||||
VF_SKYROOM_CAMERA = 222,
|
VF_SKYROOM_CAMERA = 222,
|
||||||
VF_PIXELPSCALE = 223, //[dpi_x, dpi_y, dpi_y/dpi_x]
|
VF_PIXELPSCALE = 223, //[dpi_x, dpi_y, dpi_y/dpi_x]
|
||||||
VF_PROJECTIONOFFSET = 224, //allows for off-axis projections.
|
VF_PROJECTIONOFFSET = 224, //allows for off-axis projections.
|
||||||
|
VF_VRBASEORIENTATION= 225, //specifies the worldspace coords+angles of the VR room space.
|
||||||
//WARNING: update fteqcc when new entries are added.
|
//WARNING: update fteqcc when new entries are added.
|
||||||
|
|
||||||
|
|
||||||
VF_DP_CLEARSCREEN = 201, //misnomer - NOTOVERLAY would be a better name. when set to false prevents any and all post-proc things that might write colour values in areas with no geometry there.
|
VF_DP_CLEARSCREEN = 201, //misnomer - NOTOVERLAY would be a better name. when set to false prevents any and all post-proc things that might write colour values in areas with no geometry there.
|
||||||
//fuck DP and their complete lack of respect for existing implemenetations
|
VF_DP_FOG_DENSITY = 202, //misassigned - fuck DP and their complete lack of respect for existing implemenetations
|
||||||
VF_DP_FOG_DENSITY = 202, //misassigned
|
|
||||||
VF_DP_FOG_COLOR = 203, //misassigned
|
VF_DP_FOG_COLOR = 203, //misassigned
|
||||||
VF_DP_FOG_COLOR_R = 204, //misassigned
|
VF_DP_FOG_COLOR_R = 204, //misassigned
|
||||||
VF_DP_FOG_COLOR_G = 205, //misassigned
|
VF_DP_FOG_COLOR_G = 205, //misassigned
|
||||||
|
@ -802,7 +802,7 @@ typedef enum
|
||||||
VF_DP_FOG_END = 209, //misassigned
|
VF_DP_FOG_END = 209, //misassigned
|
||||||
VF_DP_FOG_HEIGHT = 210, //misassigned
|
VF_DP_FOG_HEIGHT = 210, //misassigned
|
||||||
VF_DP_FOG_FADEDEPTH = 211, //misassigned
|
VF_DP_FOG_FADEDEPTH = 211, //misassigned
|
||||||
VF_DP_MAINVIEW = 400, // defective. should be a viewid instead, allowing for per-view motionblur instead of disabling it outright
|
VF_DP_MAINVIEW = 400, // defective. should have been a 1-based viewid instead, allowing for per-view motionblur instead of disabling it outright
|
||||||
VF_DP_MINFPS_QUALITY = 401, //multiplier for lod and culling to try to reduce costs.
|
VF_DP_MINFPS_QUALITY = 401, //multiplier for lod and culling to try to reduce costs.
|
||||||
} viewflags;
|
} viewflags;
|
||||||
|
|
||||||
|
|
|
@ -1189,6 +1189,22 @@ typedef struct
|
||||||
size_t bonedatamax;
|
size_t bonedatamax;
|
||||||
} packet_entities_t;
|
} packet_entities_t;
|
||||||
|
|
||||||
|
struct vrdevinfo_s
|
||||||
|
{
|
||||||
|
unsigned int status;
|
||||||
|
#define VRSTATUS_ORG (1u<<0)
|
||||||
|
#define VRSTATUS_ANG (1u<<1)
|
||||||
|
#define VRSTATUS_VEL (1u<<2)
|
||||||
|
#define VRSTATUS_AVEL (1u<<3)
|
||||||
|
short angles[3];
|
||||||
|
short avelocity[3];
|
||||||
|
vec3_t origin;
|
||||||
|
vec3_t velocity;
|
||||||
|
#define VRDEV_LEFT 0
|
||||||
|
#define VRDEV_RIGHT 1
|
||||||
|
#define VRDEV_HEAD 2
|
||||||
|
#define VRDEV_COUNT 3
|
||||||
|
};
|
||||||
typedef struct usercmd_s
|
typedef struct usercmd_s
|
||||||
{
|
{
|
||||||
//the first members of this structure MUST match the q2 version
|
//the first members of this structure MUST match the q2 version
|
||||||
|
@ -1214,21 +1230,7 @@ typedef struct usercmd_s
|
||||||
unsigned int cursor_entitynumber;
|
unsigned int cursor_entitynumber;
|
||||||
|
|
||||||
//vr things
|
//vr things
|
||||||
struct
|
struct vrdevinfo_s vr[VRDEV_COUNT]; //left, right, head.
|
||||||
{
|
|
||||||
unsigned int status;
|
|
||||||
#define VRSTATUS_ORG (1u<<0)
|
|
||||||
#define VRSTATUS_ANG (1u<<1)
|
|
||||||
#define VRSTATUS_VEL (1u<<2)
|
|
||||||
#define VRSTATUS_AVEL (1u<<3)
|
|
||||||
short angles[3];
|
|
||||||
short avelocity[3];
|
|
||||||
vec3_t origin;
|
|
||||||
vec3_t velocity;
|
|
||||||
#define VRDEV_LEFT 0
|
|
||||||
#define VRDEV_RIGHT 1
|
|
||||||
#define VRDEV_HEAD 2
|
|
||||||
} vr[3]; //left, right, head.
|
|
||||||
} usercmd_t;
|
} usercmd_t;
|
||||||
|
|
||||||
typedef struct q2usercmd_s
|
typedef struct q2usercmd_s
|
||||||
|
|
|
@ -88,6 +88,7 @@ Zone block
|
||||||
#else
|
#else
|
||||||
#define VALGRIND_MAKE_MEM_UNDEFINED(ptr,sz) //as an alternative to memzero..
|
#define VALGRIND_MAKE_MEM_UNDEFINED(ptr,sz) //as an alternative to memzero..
|
||||||
#define VALGRIND_MAKE_MEM_NOACCESS(ptr,sz)
|
#define VALGRIND_MAKE_MEM_NOACCESS(ptr,sz)
|
||||||
|
#define VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(ptr,sz) //undo VALGRIND_MAKE_MEM_UNDEFINED, to make sure we don't read past the end of buffers.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Memory_Init (void);
|
void Memory_Init (void);
|
||||||
|
|
|
@ -435,7 +435,7 @@ void R_RotateForEntity (float *m, float *modelview, const entity_t *e, const mod
|
||||||
R_SetupGL
|
R_SetupGL
|
||||||
=============
|
=============
|
||||||
*/
|
*/
|
||||||
static void R_SetupGL (matrix3x4 eyematrix, vec4_t fovoverrides, float projmatrix[16]/*for webvr*/, texid_t fbo)
|
static void R_SetupGL (vec3_t eyeangorg[2], vec4_t fovoverrides, float projmatrix[16]/*for webvr*/, texid_t fbo)
|
||||||
{
|
{
|
||||||
int x, x2, y2, y, w, h;
|
int x, x2, y2, y, w, h;
|
||||||
vec3_t newa;
|
vec3_t newa;
|
||||||
|
@ -450,16 +450,34 @@ static void R_SetupGL (matrix3x4 eyematrix, vec4_t fovoverrides, float projmatri
|
||||||
newa[0] = r_refdef.viewangles[0];
|
newa[0] = r_refdef.viewangles[0];
|
||||||
newa[1] = r_refdef.viewangles[1];
|
newa[1] = r_refdef.viewangles[1];
|
||||||
newa[2] = r_refdef.viewangles[2] + gl_screenangle.value;
|
newa[2] = r_refdef.viewangles[2] + gl_screenangle.value;
|
||||||
if (eyematrix)
|
if (eyeangorg)
|
||||||
{
|
{
|
||||||
matrix3x4 headmatrix;
|
extern cvar_t in_vraim;
|
||||||
|
matrix3x4 basematrix;
|
||||||
|
matrix3x4 eyematrix;
|
||||||
matrix3x4 viewmatrix;
|
matrix3x4 viewmatrix;
|
||||||
Matrix3x4_RM_FromAngles(newa, r_refdef.vieworg, headmatrix[0]);
|
|
||||||
Matrix3x4_Multiply(headmatrix[0], eyematrix[0], viewmatrix[0]);
|
Matrix3x4_RM_FromAngles(eyeangorg[0], eyeangorg[1], eyematrix[0]);
|
||||||
|
if (r_refdef.base_known)
|
||||||
|
{ //mod is specifying its own base ang+org.
|
||||||
|
Matrix3x4_RM_FromAngles(r_refdef.base_angles, r_refdef.base_origin, basematrix[0]);
|
||||||
|
Matrix3x4_Multiply(eyematrix[0], basematrix[0], viewmatrix[0]);
|
||||||
Matrix3x4_RM_ToVectors(viewmatrix[0], vpn, vright, vup, r_origin);
|
Matrix3x4_RM_ToVectors(viewmatrix[0], vpn, vright, vup, r_origin);
|
||||||
VectorNegate(vright, vright);
|
VectorNegate(vright, vright);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{ //mod provides no info.
|
||||||
|
//client will fiddle with input_angles
|
||||||
|
newa[0] = newa[2] = 0; //ignore player pitch+roll. sorry. apply the eye's transform on top.
|
||||||
|
if (in_vraim.ival)
|
||||||
|
newa[1] -= SHORT2ANGLE(r_refdef.playerview->vrdev[VRDEV_HEAD].angles[YAW]);
|
||||||
|
Matrix3x4_RM_FromAngles(newa, r_refdef.vieworg, basematrix[0]);
|
||||||
|
Matrix3x4_Multiply(eyematrix[0], basematrix[0], viewmatrix[0]);
|
||||||
|
Matrix3x4_RM_ToVectors(viewmatrix[0], vpn, vright, vup, r_origin);
|
||||||
|
VectorNegate(vright, vright);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
AngleVectors (newa, vpn, vright, vup);
|
AngleVectors (newa, vpn, vright, vup);
|
||||||
VectorCopy(r_refdef.vieworg, r_origin);
|
VectorCopy(r_refdef.vieworg, r_origin);
|
||||||
|
@ -717,7 +735,7 @@ static void R_RenderScene_Internal(void)
|
||||||
|
|
||||||
depthcleared = false; //whatever is in the depth buffer is no longer useful.
|
depthcleared = false; //whatever is in the depth buffer is no longer useful.
|
||||||
}
|
}
|
||||||
static void R_RenderEyeScene (texid_t rendertarget, vec4_t fovoverride, matrix3x4 eyematrix)
|
static void R_RenderEyeScene (texid_t rendertarget, vec4_t fovoverride, vec3_t eyeangorg[2])
|
||||||
{
|
{
|
||||||
extern qboolean depthcleared;
|
extern qboolean depthcleared;
|
||||||
refdef_t refdef = r_refdef;
|
refdef_t refdef = r_refdef;
|
||||||
|
@ -725,6 +743,11 @@ static void R_RenderEyeScene (texid_t rendertarget, vec4_t fovoverride, matrix3x
|
||||||
int ph = vid.fbpheight;
|
int ph = vid.fbpheight;
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
|
extern void CL_ClampPitch (int pnum, float frametime);
|
||||||
|
/*the vr code tends to be somewhat laggy with its head angles, leaving it to the last minute, so redo this to reduce latency*/
|
||||||
|
if ((size_t)(refdef.playerview-cl.playerview) < MAX_SPLITS)
|
||||||
|
CL_ClampPitch (refdef.playerview-cl.playerview, 0);
|
||||||
|
|
||||||
if (rendertarget)
|
if (rendertarget)
|
||||||
{
|
{
|
||||||
r = GLBE_FBO_Update(&fbo_vr, FBO_RB_DEPTH, &rendertarget, 1, r_nulltex, rendertarget->width, rendertarget->height, 0);
|
r = GLBE_FBO_Update(&fbo_vr, FBO_RB_DEPTH, &rendertarget, 1, r_nulltex, rendertarget->width, rendertarget->height, 0);
|
||||||
|
@ -735,10 +758,10 @@ static void R_RenderEyeScene (texid_t rendertarget, vec4_t fovoverride, matrix3x
|
||||||
vid.fbpheight = rendertarget->height;
|
vid.fbpheight = rendertarget->height;
|
||||||
}
|
}
|
||||||
|
|
||||||
R_SetupGL (eyematrix, fovoverride, NULL, rendertarget);
|
R_SetupGL (eyeangorg, fovoverride, NULL, rendertarget);
|
||||||
R_RenderScene_Internal();
|
R_RenderScene_Internal();
|
||||||
|
|
||||||
//if (eyematrix)
|
/*//if (eyematrix)
|
||||||
{
|
{
|
||||||
vec3_t newa, newo;
|
vec3_t newa, newo;
|
||||||
matrix3x4 headmatrix; //position of the head in local space
|
matrix3x4 headmatrix; //position of the head in local space
|
||||||
|
@ -774,7 +797,7 @@ static void R_RenderEyeScene (texid_t rendertarget, vec4_t fovoverride, matrix3x
|
||||||
if (R2D_Flush)
|
if (R2D_Flush)
|
||||||
R2D_Flush();
|
R2D_Flush();
|
||||||
GL_SetShaderState2D(false);
|
GL_SetShaderState2D(false);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
if (rendertarget)
|
if (rendertarget)
|
||||||
{
|
{
|
||||||
|
@ -795,8 +818,7 @@ static void R_RenderScene (void)
|
||||||
int i;
|
int i;
|
||||||
int cull = r_refdef.flipcull;
|
int cull = r_refdef.flipcull;
|
||||||
unsigned int colourmask = r_refdef.colourmask;
|
unsigned int colourmask = r_refdef.colourmask;
|
||||||
vec3_t ang, org;
|
vec3_t eyeangorg[2];
|
||||||
matrix3x4 eyematrix;
|
|
||||||
extern qboolean depthcleared;
|
extern qboolean depthcleared;
|
||||||
|
|
||||||
r_refdef.colourmask = 0u;
|
r_refdef.colourmask = 0u;
|
||||||
|
@ -914,12 +936,11 @@ static void R_RenderScene (void)
|
||||||
}
|
}
|
||||||
r_framecount++; //view position changes, if only slightly. which means we need to rebuild vis info. :(
|
r_framecount++; //view position changes, if only slightly. which means we need to rebuild vis info. :(
|
||||||
|
|
||||||
ang[0] = 0;
|
eyeangorg[0][0] = 0;
|
||||||
ang[1] = r_stereo_convergence.value * (i?0.5:-0.5);
|
eyeangorg[0][1] = r_stereo_convergence.value * (i?0.5:-0.5);
|
||||||
ang[2] = 0;
|
eyeangorg[0][2] = 0;
|
||||||
VectorSet(org, 0, stereooffset[i], 0);
|
VectorSet(eyeangorg[1], 0, stereooffset[i], 0);
|
||||||
Matrix3x4_RM_FromAngles(ang, org, eyematrix[0]);
|
R_SetupGL (eyeangorg, NULL, NULL, NULL);
|
||||||
R_SetupGL (eyematrix, NULL, NULL, NULL);
|
|
||||||
R_RenderScene_Internal ();
|
R_RenderScene_Internal ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,7 @@ cvar_t r_shadow_realtime_world = CVARFD ("r_shadow_realtime_world", "0", CVAR
|
||||||
cvar_t r_shadow_realtime_world_shadows = CVARF ("r_shadow_realtime_world_shadows", "1", CVAR_ARCHIVE);
|
cvar_t r_shadow_realtime_world_shadows = CVARF ("r_shadow_realtime_world_shadows", "1", CVAR_ARCHIVE);
|
||||||
cvar_t r_shadow_realtime_world_lightmaps = CVARFD ("r_shadow_realtime_world_lightmaps", "0", 0, "Specifies how much of the map's normal lightmap to retain when using world realtime lights. 0 completely replaces lighting.");
|
cvar_t r_shadow_realtime_world_lightmaps = CVARFD ("r_shadow_realtime_world_lightmaps", "0", 0, "Specifies how much of the map's normal lightmap to retain when using world realtime lights. 0 completely replaces lighting.");
|
||||||
cvar_t r_shadow_realtime_world_importlightentitiesfrommap = CVARFD ("r_shadow_realtime_world_importlightentitiesfrommap", "0", CVAR_ARCHIVE, "Controls default loading of map-based realtime lights.\n0: Load explicit .rtlight files only.\n1: Load explicit lights then try fallback to parsing the entities lump.\n2: Load only the entities lump.");
|
cvar_t r_shadow_realtime_world_importlightentitiesfrommap = CVARFD ("r_shadow_realtime_world_importlightentitiesfrommap", "0", CVAR_ARCHIVE, "Controls default loading of map-based realtime lights.\n0: Load explicit .rtlight files only.\n1: Load explicit lights then try fallback to parsing the entities lump.\n2: Load only the entities lump.");
|
||||||
cvar_t r_shadow_realtime_dlight = CVARFD ("r_shadow_realtime_dlight", "1", CVAR_ARCHIVE, "Enables the use of dynamic realtime lights, allowing explosions to use bumpmaps etc properly.");
|
cvar_t r_shadow_realtime_dlight = CVARAFD ("r_shadow_realtime_dlight", "1", "r_shadow_realtime_dynamic", CVAR_ARCHIVE, "Enables the use of dynamic realtime lights, allowing explosions to use bumpmaps etc properly.");
|
||||||
cvar_t r_shadow_realtime_dlight_shadows = CVARFD ("r_shadow_realtime_dlight_shadows", "1", CVAR_ARCHIVE, "Allows dynamic realtime lights to cast shadows as they move.");
|
cvar_t r_shadow_realtime_dlight_shadows = CVARFD ("r_shadow_realtime_dlight_shadows", "1", CVAR_ARCHIVE, "Allows dynamic realtime lights to cast shadows as they move.");
|
||||||
cvar_t r_shadow_realtime_dlight_ambient = CVAR ("r_shadow_realtime_dlight_ambient", "0");
|
cvar_t r_shadow_realtime_dlight_ambient = CVAR ("r_shadow_realtime_dlight_ambient", "0");
|
||||||
cvar_t r_shadow_realtime_dlight_diffuse = CVAR ("r_shadow_realtime_dlight_diffuse", "1");
|
cvar_t r_shadow_realtime_dlight_diffuse = CVAR ("r_shadow_realtime_dlight_diffuse", "1");
|
||||||
|
|
|
@ -1594,7 +1594,10 @@ void DL_DeThread(void)
|
||||||
{
|
{
|
||||||
dl->threadenable = false;
|
dl->threadenable = false;
|
||||||
if (dl->threadctx)
|
if (dl->threadctx)
|
||||||
|
{
|
||||||
Sys_WaitOnThread(dl->threadctx);
|
Sys_WaitOnThread(dl->threadctx);
|
||||||
|
dl->threadctx = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -6147,7 +6147,7 @@ static void QCC_VerifyArgs_setviewprop (const char *funcname, QCC_ref_t **arglis
|
||||||
{"VF_CL_VIEWANGLES_X", 35, ev_float},
|
{"VF_CL_VIEWANGLES_X", 35, ev_float},
|
||||||
{"VF_CL_VIEWANGLES_X", 36, ev_float},
|
{"VF_CL_VIEWANGLES_X", 36, ev_float},
|
||||||
{"VF_PERSPECTIVE", 200, ev_float},
|
{"VF_PERSPECTIVE", 200, ev_float},
|
||||||
//201
|
// {"VF_DP_CLEARSCENE", 201, ev_float},
|
||||||
{"VF_ACTIVESEAT", 202, ev_float, ev_float},
|
{"VF_ACTIVESEAT", 202, ev_float, ev_float},
|
||||||
{"VF_AFOV", 203, ev_float},
|
{"VF_AFOV", 203, ev_float},
|
||||||
// {"VF_SCREENVSIZE", 204, ev_vector},
|
// {"VF_SCREENVSIZE", 204, ev_vector},
|
||||||
|
@ -6171,6 +6171,10 @@ static void QCC_VerifyArgs_setviewprop (const char *funcname, QCC_ref_t **arglis
|
||||||
{"VF_SKYROOM_CAMERA", 222, ev_vector},
|
{"VF_SKYROOM_CAMERA", 222, ev_vector},
|
||||||
// {"VF_PIXELPSCALE", 223, ev_vector},
|
// {"VF_PIXELPSCALE", 223, ev_vector},
|
||||||
{"VF_PROJECTIONOFFSET", 224, ev_vector},
|
{"VF_PROJECTIONOFFSET", 224, ev_vector},
|
||||||
|
{"VF_VRBASEORIENTATION",225, ev_vector, ev_vector},
|
||||||
|
|
||||||
|
{"VF_DP_MAINVIEW", 400, ev_float},
|
||||||
|
// {"VF_DP_MINFPS_QUALITY", 401, ev_float},
|
||||||
};
|
};
|
||||||
|
|
||||||
char temp[256];
|
char temp[256];
|
||||||
|
|
|
@ -5069,8 +5069,6 @@ QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype)
|
||||||
if (QCC_PR_CheckToken("="))
|
if (QCC_PR_CheckToken("="))
|
||||||
{
|
{
|
||||||
paramlist[numparms].defltvalue = QCC_PR_ParseDefaultInitialiser(paramlist[numparms].type);
|
paramlist[numparms].defltvalue = QCC_PR_ParseDefaultInitialiser(paramlist[numparms].type);
|
||||||
if (!paramlist[numparms].defltvalue.sym->constant)
|
|
||||||
QCC_PR_ParseError(0, "Default initialiser is not constant\n");
|
|
||||||
QCC_FreeTemp(paramlist[numparms].defltvalue);
|
QCC_FreeTemp(paramlist[numparms].defltvalue);
|
||||||
}
|
}
|
||||||
numparms++;
|
numparms++;
|
||||||
|
|
|
@ -10291,79 +10291,11 @@ void SV_SetEntityButtons(edict_t *ent, unsigned int buttonbits)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//EXT_CSQC_1 (called when a movement command is received. runs full acceleration + movement)
|
static void SV_SetSSQCInputs(usercmd_t *ucmd)
|
||||||
qboolean SV_RunFullQCMovement(client_t *client, usercmd_t *ucmd)
|
|
||||||
{
|
{
|
||||||
if (gfuncs.RunClientCommand)
|
|
||||||
{
|
|
||||||
vec3_t startangle;
|
|
||||||
#ifdef SVCHAT
|
|
||||||
if (SV_ChatMove(ucmd->impulse))
|
|
||||||
{
|
|
||||||
ucmd->buttons = 0;
|
|
||||||
ucmd->impulse = 0;
|
|
||||||
ucmd->forwardmove = ucmd->sidemove = ucmd->upmove = 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!sv_player->v->fixangle)
|
|
||||||
{
|
|
||||||
sv_player->v->v_angle[0] = SHORT2ANGLE(ucmd->angles[0]);
|
|
||||||
sv_player->v->v_angle[1] = SHORT2ANGLE(ucmd->angles[1]);
|
|
||||||
sv_player->v->v_angle[2] = SHORT2ANGLE(ucmd->angles[2]);
|
|
||||||
}
|
|
||||||
VectorCopy(sv_player->v->v_angle, startangle);
|
|
||||||
|
|
||||||
#ifdef HEXEN2
|
|
||||||
if (progstype == PROG_H2)
|
|
||||||
sv_player->xv->light_level = 128; //hmm... HACK!!!
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SV_SetEntityButtons(sv_player, ucmd->buttons);
|
|
||||||
if (ucmd->impulse && SV_FilterImpulse(ucmd->impulse, host_client->trustlevel))
|
|
||||||
sv_player->v->impulse = ucmd->impulse;
|
|
||||||
|
|
||||||
if (host_client->penalties & BAN_CUFF)
|
|
||||||
{
|
|
||||||
sv_player->v->impulse = 0;
|
|
||||||
sv_player->v->button0 = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (host_client->state && host_client->protocol != SCP_BAD)
|
|
||||||
{
|
|
||||||
sv_player->xv->movement[0] = ucmd->forwardmove;
|
|
||||||
sv_player->xv->movement[1] = ucmd->sidemove;
|
|
||||||
sv_player->xv->movement[2] = ucmd->upmove;
|
|
||||||
}
|
|
||||||
|
|
||||||
WPhys_CheckVelocity(&sv.world, (wedict_t*)sv_player);
|
|
||||||
|
|
||||||
//
|
|
||||||
// angles
|
|
||||||
// show 1/3 the pitch angle and all the roll angle
|
|
||||||
if (sv_player->v->health > 0)
|
|
||||||
{
|
|
||||||
if (!sv_player->v->fixangle)
|
|
||||||
{
|
|
||||||
sv_player->v->angles[PITCH] = r_meshpitch.value * sv_player->v->v_angle[PITCH]/3;
|
|
||||||
sv_player->v->angles[YAW] = sv_player->v->v_angle[YAW];
|
|
||||||
}
|
|
||||||
sv_player->v->angles[ROLL] =
|
|
||||||
V_CalcRoll (sv_player->v->angles, sv_player->v->velocity)*4;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pr_global_struct->input_timelength = ucmd->msec/1000.0f * sv.gamespeed;
|
pr_global_struct->input_timelength = ucmd->msec/1000.0f * sv.gamespeed;
|
||||||
pr_global_struct->input_impulse = ucmd->impulse;
|
pr_global_struct->input_impulse = ucmd->impulse;
|
||||||
//precision inaccuracies. :(
|
//precision inaccuracies. :(
|
||||||
#define ANGLE2SHORT(x) (x) * (65536/360.0)
|
#define ANGLE2SHORT(x) (x) * (65536/360.0)
|
||||||
if (sv_player->v->fixangle)
|
if (sv_player->v->fixangle)
|
||||||
{
|
{
|
||||||
|
@ -10452,6 +10384,73 @@ qboolean SV_RunFullQCMovement(client_t *client, usercmd_t *ucmd)
|
||||||
(pr_global_struct->input_right_avelocity)[1] = SHORT2ANGLE(ucmd->vr[VRDEV_RIGHT].avelocity[1]);
|
(pr_global_struct->input_right_avelocity)[1] = SHORT2ANGLE(ucmd->vr[VRDEV_RIGHT].avelocity[1]);
|
||||||
(pr_global_struct->input_right_avelocity)[2] = SHORT2ANGLE(ucmd->vr[VRDEV_RIGHT].avelocity[2]);
|
(pr_global_struct->input_right_avelocity)[2] = SHORT2ANGLE(ucmd->vr[VRDEV_RIGHT].avelocity[2]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//EXT_CSQC_1 (called when a movement command is received. runs full acceleration + movement)
|
||||||
|
qboolean SV_RunFullQCMovement(client_t *client, usercmd_t *ucmd)
|
||||||
|
{
|
||||||
|
if (ucmd->vr[VRDEV_HEAD].status & VRSTATUS_ANG)
|
||||||
|
sv_player->xv->idealpitch = SHORT2ANGLE(ucmd->vr[VRDEV_HEAD].angles[0]);
|
||||||
|
else
|
||||||
|
sv_player->xv->idealpitch = 0;
|
||||||
|
SV_SetSSQCInputs(ucmd); //make sure its available for PlayerPreThink.
|
||||||
|
if (gfuncs.RunClientCommand)
|
||||||
|
{
|
||||||
|
vec3_t startangle;
|
||||||
|
#ifdef SVCHAT
|
||||||
|
if (SV_ChatMove(ucmd->impulse))
|
||||||
|
{
|
||||||
|
ucmd->buttons = 0;
|
||||||
|
ucmd->impulse = 0;
|
||||||
|
ucmd->forwardmove = ucmd->sidemove = ucmd->upmove = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!sv_player->v->fixangle)
|
||||||
|
{
|
||||||
|
sv_player->v->v_angle[0] = SHORT2ANGLE(ucmd->angles[0]);
|
||||||
|
sv_player->v->v_angle[1] = SHORT2ANGLE(ucmd->angles[1]);
|
||||||
|
sv_player->v->v_angle[2] = SHORT2ANGLE(ucmd->angles[2]);
|
||||||
|
}
|
||||||
|
VectorCopy(sv_player->v->v_angle, startangle);
|
||||||
|
|
||||||
|
#ifdef HEXEN2
|
||||||
|
if (progstype == PROG_H2)
|
||||||
|
sv_player->xv->light_level = 128; //hmm... HACK!!!
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SV_SetEntityButtons(sv_player, ucmd->buttons);
|
||||||
|
if (ucmd->impulse && SV_FilterImpulse(ucmd->impulse, host_client->trustlevel))
|
||||||
|
sv_player->v->impulse = ucmd->impulse;
|
||||||
|
|
||||||
|
if (host_client->penalties & BAN_CUFF)
|
||||||
|
{
|
||||||
|
sv_player->v->impulse = 0;
|
||||||
|
sv_player->v->button0 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (host_client->state && host_client->protocol != SCP_BAD)
|
||||||
|
{
|
||||||
|
sv_player->xv->movement[0] = ucmd->forwardmove;
|
||||||
|
sv_player->xv->movement[1] = ucmd->sidemove;
|
||||||
|
sv_player->xv->movement[2] = ucmd->upmove;
|
||||||
|
}
|
||||||
|
|
||||||
|
WPhys_CheckVelocity(&sv.world, (wedict_t*)sv_player);
|
||||||
|
|
||||||
|
//
|
||||||
|
// angles
|
||||||
|
// show 1/3 the pitch angle and all the roll angle
|
||||||
|
if (sv_player->v->health > 0)
|
||||||
|
{
|
||||||
|
if (!sv_player->v->fixangle)
|
||||||
|
{
|
||||||
|
sv_player->v->angles[PITCH] = r_meshpitch.value * sv_player->v->v_angle[PITCH]/3;
|
||||||
|
sv_player->v->angles[YAW] = sv_player->v->v_angle[YAW];
|
||||||
|
}
|
||||||
|
sv_player->v->angles[ROLL] =
|
||||||
|
V_CalcRoll (sv_player->v->angles, sv_player->v->velocity)*4;
|
||||||
|
}
|
||||||
|
|
||||||
//prethink should be consistant with what the engine normally does
|
//prethink should be consistant with what the engine normally does
|
||||||
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, client->edict);
|
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, client->edict);
|
||||||
|
|
|
@ -2271,6 +2271,7 @@ void SV_CalcClientStats(client_t *client, int statsi[MAX_CL_STATS], float statsf
|
||||||
}
|
}
|
||||||
|
|
||||||
statsf[STAT_VIEWHEIGHT] = ent->v->view_ofs[2];
|
statsf[STAT_VIEWHEIGHT] = ent->v->view_ofs[2];
|
||||||
|
statsf[STAT_IDEALPITCH] = ent->xv->idealpitch;
|
||||||
|
|
||||||
statsf[STAT_PUNCHANGLE_X] = ent->xv->punchangle[0];
|
statsf[STAT_PUNCHANGLE_X] = ent->xv->punchangle[0];
|
||||||
statsf[STAT_PUNCHANGLE_Y] = ent->xv->punchangle[1];
|
statsf[STAT_PUNCHANGLE_Y] = ent->xv->punchangle[1];
|
||||||
|
|
|
@ -8113,9 +8113,9 @@ void SV_ExecuteClientMessage (client_t *cl)
|
||||||
else while (split->lastruncmd < newcmd.servertime)
|
else while (split->lastruncmd < newcmd.servertime)
|
||||||
{
|
{
|
||||||
//try to find the oldest (valid) command.
|
//try to find the oldest (valid) command.
|
||||||
if (split->lastcmd.servertime < oldest.servertime)
|
if (split->lastruncmd < oldest.servertime)
|
||||||
c = &oldest;
|
c = &oldest;
|
||||||
else if (split->lastcmd.servertime < oldcmd.servertime)
|
else if (split->lastruncmd < oldcmd.servertime)
|
||||||
c = &oldcmd;
|
c = &oldcmd;
|
||||||
else
|
else
|
||||||
c = &newcmd;
|
c = &newcmd;
|
||||||
|
|
|
@ -2656,7 +2656,7 @@ static qboolean VK_R_RenderScene_Cubemap(struct vk_rendertarg *fb)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VK_R_RenderEye(texid_t image, vec4_t fovoverride, matrix3x4 axisorg)
|
void VK_R_RenderEye(texid_t image, vec4_t fovoverride, vec3_t eyeangorg[2])
|
||||||
{
|
{
|
||||||
struct vk_rendertarg *rt;
|
struct vk_rendertarg *rt;
|
||||||
|
|
||||||
|
|
174
plugins/openxr.c
174
plugins/openxr.c
|
@ -126,36 +126,6 @@ static cvar_t *xr_skipregularview;
|
||||||
#define METRES_TO_QUAKE(x) ((x)*xr_metresize->value)
|
#define METRES_TO_QUAKE(x) ((x)*xr_metresize->value)
|
||||||
#define QUAKE_TO_METRES(x) ((x)/xr_metresize->value)
|
#define QUAKE_TO_METRES(x) ((x)/xr_metresize->value)
|
||||||
|
|
||||||
static void Matrix3x4_FromAngles (const vec3_t angles, const vec3_t org, float *fte_restrict transform)
|
|
||||||
{
|
|
||||||
float angle;
|
|
||||||
float sr, sp, sy, cr, cp, cy;
|
|
||||||
|
|
||||||
angle = angles[YAW] * (M_PI*2 / 360);
|
|
||||||
sy = sin(angle);
|
|
||||||
cy = cos(angle);
|
|
||||||
angle = angles[PITCH] * (M_PI*2 / 360);
|
|
||||||
sp = sin(angle);
|
|
||||||
cp = cos(angle);
|
|
||||||
angle = angles[ROLL] * (M_PI*2 / 360);
|
|
||||||
sr = sin(angle);
|
|
||||||
cr = cos(angle);
|
|
||||||
|
|
||||||
transform[0+0] = cp*cy;
|
|
||||||
transform[0+1] = cp*sy;
|
|
||||||
transform[0+2] = -sp;
|
|
||||||
transform[0+3] = org[0];
|
|
||||||
|
|
||||||
transform[4+0] = (-1*sr*sp*cy+-1*cr*-sy);
|
|
||||||
transform[4+1] = (-1*sr*sp*sy+-1*cr*cy);
|
|
||||||
transform[4+2] = -1*sr*cp;
|
|
||||||
transform[4+3] = org[1];
|
|
||||||
|
|
||||||
transform[8+0] = (cr*sp*cy+-sr*-sy);
|
|
||||||
transform[8+1] = (cr*sp*sy+-sr*cy);
|
|
||||||
transform[8+2] = cr*cp;
|
|
||||||
transform[8+3] = org[2];
|
|
||||||
}
|
|
||||||
static void XR_PoseToAngOrg(const XrPosef *pose, vec3_t ang, vec3_t org)
|
static void XR_PoseToAngOrg(const XrPosef *pose, vec3_t ang, vec3_t org)
|
||||||
{
|
{
|
||||||
XrQuaternionf q = pose->orientation;
|
XrQuaternionf q = pose->orientation;
|
||||||
|
@ -178,62 +148,6 @@ static void XR_PoseToAngOrg(const XrPosef *pose, vec3_t ang, vec3_t org)
|
||||||
org[2] = METRES_TO_QUAKE(pose->position.z);
|
org[2] = METRES_TO_QUAKE(pose->position.z);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
static void XR_PoseToTransform(const XrPosef *pose, float *fte_restrict transform)
|
|
||||||
{
|
|
||||||
vec3_t ang, org;
|
|
||||||
XR_PoseToAngOrg(pose, ang, org);
|
|
||||||
Matrix3x4_FromAngles(ang, org, transform);
|
|
||||||
}
|
|
||||||
static void Matrix3x4_Invert_XR (const float *in1, float *fte_restrict out)
|
|
||||||
{
|
|
||||||
// we only support uniform scaling, so assume the first row is enough
|
|
||||||
// (note the lack of sqrt here, because we're trying to undo the scaling,
|
|
||||||
// this means multiplying by the inverse scale twice - squaring it, which
|
|
||||||
// makes the sqrt a waste of time)
|
|
||||||
#if 1
|
|
||||||
double scale = 1.0 / (in1[0] * in1[0] + in1[1] * in1[1] + in1[2] * in1[2]);
|
|
||||||
#else
|
|
||||||
double scale = 3.0 / sqrt
|
|
||||||
(in1->m[0][0] * in1->m[0][0] + in1->m[0][1] * in1->m[0][1] + in1->m[0][2] * in1->m[0][2]
|
|
||||||
+ in1->m[1][0] * in1->m[1][0] + in1->m[1][1] * in1->m[1][1] + in1->m[1][2] * in1->m[1][2]
|
|
||||||
+ in1->m[2][0] * in1->m[2][0] + in1->m[2][1] * in1->m[2][1] + in1->m[2][2] * in1->m[2][2]);
|
|
||||||
scale *= scale;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// invert the rotation by transposing and multiplying by the squared
|
|
||||||
// recipricol of the input matrix scale as described above
|
|
||||||
out[0] = in1[0] * scale;
|
|
||||||
out[1] = in1[4] * scale;
|
|
||||||
out[2] = in1[8] * scale;
|
|
||||||
out[4] = in1[1] * scale;
|
|
||||||
out[5] = in1[5] * scale;
|
|
||||||
out[6] = in1[9] * scale;
|
|
||||||
out[8] = in1[2] * scale;
|
|
||||||
out[9] = in1[6] * scale;
|
|
||||||
out[10] = in1[10] * scale;
|
|
||||||
|
|
||||||
// invert the translate
|
|
||||||
out[3] = -(in1[3] * out[0] + in1[7] * out[1] + in1[11] * out[2]);
|
|
||||||
out[7] = -(in1[3] * out[4] + in1[7] * out[5] + in1[11] * out[6]);
|
|
||||||
out[11] = -(in1[3] * out[8] + in1[7] * out[9] + in1[11] * out[10]);
|
|
||||||
}
|
|
||||||
static void Matrix3x4_Multiply_XR(const float *a, const float *b, float *fte_restrict out)
|
|
||||||
{
|
|
||||||
out[0] = a[0] * b[0] + a[4] * b[1] + a[8] * b[2];
|
|
||||||
out[1] = a[1] * b[0] + a[5] * b[1] + a[9] * b[2];
|
|
||||||
out[2] = a[2] * b[0] + a[6] * b[1] + a[10] * b[2];
|
|
||||||
out[3] = a[3] * b[0] + a[7] * b[1] + a[11] * b[2] + b[3];
|
|
||||||
|
|
||||||
out[4] = a[0] * b[4] + a[4] * b[5] + a[8] * b[6];
|
|
||||||
out[5] = a[1] * b[4] + a[5] * b[5] + a[9] * b[6];
|
|
||||||
out[6] = a[2] * b[4] + a[6] * b[5] + a[10] * b[6];
|
|
||||||
out[7] = a[3] * b[4] + a[7] * b[5] + a[11] * b[6] + b[7];
|
|
||||||
|
|
||||||
out[8] = a[0] * b[8] + a[4] * b[9] + a[8] * b[10];
|
|
||||||
out[9] = a[1] * b[8] + a[5] * b[9] + a[9] * b[10];
|
|
||||||
out[10] = a[2] * b[8] + a[6] * b[9] + a[10] * b[10];
|
|
||||||
out[11] = a[3] * b[8] + a[7] * b[9] + a[11] * b[10] + b[11];
|
|
||||||
}
|
|
||||||
|
|
||||||
#define VectorAngles VectorAnglesPluginsSuck
|
#define VectorAngles VectorAnglesPluginsSuck
|
||||||
static void VectorAngles(const float *forward, const float *up, float *result, qboolean meshpitch) //up may be NULL
|
static void VectorAngles(const float *forward, const float *up, float *result, qboolean meshpitch) //up may be NULL
|
||||||
|
@ -1037,32 +951,14 @@ static int QDECL XR_BindProfileFile(const char *fname, qofs_t fsize, time_t mtim
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void XR_SetupInputs(void)
|
static const struct
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
const char *script;
|
||||||
|
} xr_knownprofiles[] =
|
||||||
{
|
{
|
||||||
unsigned int h;
|
|
||||||
XrResult res;
|
|
||||||
|
|
||||||
//begin instance-level init
|
|
||||||
{
|
|
||||||
XrActionSetCreateInfo info = {XR_TYPE_ACTION_SET_CREATE_INFO};
|
|
||||||
Q_strlcpy(info.actionSetName, "actions", sizeof(info.actionSetName));
|
|
||||||
Q_strlcpy(info.localizedActionSetName, FULLENGINENAME" Actions", sizeof(info.localizedActionSetName));
|
|
||||||
info.priority = 0;
|
|
||||||
|
|
||||||
xr.actionset.subactionPath = XR_NULL_PATH;
|
|
||||||
res = xrCreateActionSet(xr.instance, &info, &xr.actionset.actionSet);
|
|
||||||
if (XR_FAILED(res))
|
|
||||||
Con_Printf("openxr: Unable to create actionset - %s\n", XR_StringForResult(res));
|
|
||||||
}
|
|
||||||
|
|
||||||
h = 0;
|
|
||||||
if (fsfuncs)
|
|
||||||
fsfuncs->EnumerateFiles("oxr_*.binds", XR_BindProfileFile, &h);
|
|
||||||
if (!h) //no user bindings defined, use fallbacks. probably this needs to be per-mod.
|
|
||||||
{
|
|
||||||
//FIXME: set up some proper bindings!
|
//FIXME: set up some proper bindings!
|
||||||
XR_BindProfileStr("khr_simple",
|
{"khr_simple", "/interaction_profiles/khr/simple_controller /user/hand/left/ /user/hand/right/\n"
|
||||||
"/interaction_profiles/khr/simple_controller /user/hand/left/ /user/hand/right/\n"
|
|
||||||
"+attack_left \"Left Attack\" button input/select/click /user/hand/left\n"
|
"+attack_left \"Left Attack\" button input/select/click /user/hand/left\n"
|
||||||
"+attack_right \"Right Attack\" button input/select/click /user/hand/right\n"
|
"+attack_right \"Right Attack\" button input/select/click /user/hand/right\n"
|
||||||
"+menu_left \"Left Menu\" button input/menu/click /user/hand/left\n"
|
"+menu_left \"Left Menu\" button input/menu/click /user/hand/left\n"
|
||||||
|
@ -1072,10 +968,9 @@ static void XR_SetupInputs(void)
|
||||||
// "grip_pose \"Grip Pose\" pose input/grip/pose\n"
|
// "grip_pose \"Grip Pose\" pose input/grip/pose\n"
|
||||||
// "aim_pose \"Aim Pose\" pose input/aim/pose\n"
|
// "aim_pose \"Aim Pose\" pose input/aim/pose\n"
|
||||||
"vibrate \"A Vibrator\" vibration output/haptic\n"
|
"vibrate \"A Vibrator\" vibration output/haptic\n"
|
||||||
);
|
},
|
||||||
|
|
||||||
/* XR_BindProfileStr("valve_index",
|
/* {"valve_index", "/interaction_profiles/valve/index_controller /user/hand/left/ /user/hand/right/\n"
|
||||||
"/interaction_profiles/valve/index_controller /user/hand/left/ /user/hand/right/\n"
|
|
||||||
//"unbound \"Unused Button\" button input/system/click\n"
|
//"unbound \"Unused Button\" button input/system/click\n"
|
||||||
//"unbound \"Unused Button\" button input/system/touch\n"
|
//"unbound \"Unused Button\" button input/system/touch\n"
|
||||||
//"unbound \"Unused Button\" button input/a/click\n"
|
//"unbound \"Unused Button\" button input/a/click\n"
|
||||||
|
@ -1096,10 +991,9 @@ static void XR_SetupInputs(void)
|
||||||
//"unbound \"Unused Button\" pose input/grip/pose\n"
|
//"unbound \"Unused Button\" pose input/grip/pose\n"
|
||||||
//"unbound \"Unused Button\" pose input/aim/pose\n"
|
//"unbound \"Unused Button\" pose input/aim/pose\n"
|
||||||
//"unbound \"Unused Button\" vibration output/haptic\n"
|
//"unbound \"Unused Button\" vibration output/haptic\n"
|
||||||
);
|
},
|
||||||
*/
|
*/
|
||||||
/* XR_BindProfileStr("htc_vive",
|
/* {"htc_vive", "/interaction_profiles/htc/vive_controller /user/hand/left/ /user/hand/right/\n"
|
||||||
"/interaction_profiles/htc/vive_controller /user/hand/left/ /user/hand/right/\n"
|
|
||||||
//"unbound \"Unused Button\" button input/system/click\n"
|
//"unbound \"Unused Button\" button input/system/click\n"
|
||||||
//"unbound \"Unused Button\" button input/squeeze/click\n"
|
//"unbound \"Unused Button\" button input/squeeze/click\n"
|
||||||
//"unbound \"Unused Button\" button input/menu/click\n"
|
//"unbound \"Unused Button\" button input/menu/click\n"
|
||||||
|
@ -1113,8 +1007,7 @@ static void XR_SetupInputs(void)
|
||||||
//"unbound \"Unused Button\" vibration output/haptic\n"
|
//"unbound \"Unused Button\" vibration output/haptic\n"
|
||||||
);
|
);
|
||||||
*/
|
*/
|
||||||
/* XR_BindProfileStr("htc_vive_pro",
|
/* {"htc_vive_pro", "/interaction_profiles/htc/vive_pro /user/head/\n"
|
||||||
"/interaction_profiles/htc/vive_pro /user/head/\n"
|
|
||||||
//"unbound \"Unused Button\" button input/system/click\n"
|
//"unbound \"Unused Button\" button input/system/click\n"
|
||||||
//"unbound \"Unused Button\" button input/volume_up/click\n"
|
//"unbound \"Unused Button\" button input/volume_up/click\n"
|
||||||
//"unbound \"Unused Button\" button input/volume_down/click\n"
|
//"unbound \"Unused Button\" button input/volume_down/click\n"
|
||||||
|
@ -1123,7 +1016,7 @@ static void XR_SetupInputs(void)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//FIXME: map to quake's keys.
|
//FIXME: map to quake's keys.
|
||||||
XR_BindProfileStr("gamepad", "/interaction_profiles/microsoft/xbox_controller /user/gamepad/\n"
|
{"gamepad", "/interaction_profiles/microsoft/xbox_controller /user/gamepad/\n"
|
||||||
"togglemenu Menu button input/menu/click\n"
|
"togglemenu Menu button input/menu/click\n"
|
||||||
//"unbound \"Unused Button\" button input/view/click\n"
|
//"unbound \"Unused Button\" button input/view/click\n"
|
||||||
//"unbound \"Unused Button\" button input/a/click\n"
|
//"unbound \"Unused Button\" button input/a/click\n"
|
||||||
|
@ -1148,7 +1041,34 @@ static void XR_SetupInputs(void)
|
||||||
//"unbound \"Unused Vibrator\" vibration output/haptic_left_trigger\n"
|
//"unbound \"Unused Vibrator\" vibration output/haptic_left_trigger\n"
|
||||||
//"unbound \"Unused Vibrator\" vibration output/haptic_right\n"
|
//"unbound \"Unused Vibrator\" vibration output/haptic_right\n"
|
||||||
//"unbound \"Unused Vibrator\" vibration output/haptic_right_trigger\n"
|
//"unbound \"Unused Vibrator\" vibration output/haptic_right_trigger\n"
|
||||||
);
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static void XR_SetupInputs(void)
|
||||||
|
{
|
||||||
|
unsigned int h;
|
||||||
|
XrResult res;
|
||||||
|
|
||||||
|
//begin instance-level init
|
||||||
|
{
|
||||||
|
XrActionSetCreateInfo info = {XR_TYPE_ACTION_SET_CREATE_INFO};
|
||||||
|
Q_strlcpy(info.actionSetName, "actions", sizeof(info.actionSetName));
|
||||||
|
Q_strlcpy(info.localizedActionSetName, FULLENGINENAME" Actions", sizeof(info.localizedActionSetName));
|
||||||
|
info.priority = 0;
|
||||||
|
|
||||||
|
xr.actionset.subactionPath = XR_NULL_PATH;
|
||||||
|
res = xrCreateActionSet(xr.instance, &info, &xr.actionset.actionSet);
|
||||||
|
if (XR_FAILED(res))
|
||||||
|
Con_Printf("openxr: Unable to create actionset - %s\n", XR_StringForResult(res));
|
||||||
|
}
|
||||||
|
|
||||||
|
h = 0;
|
||||||
|
if (fsfuncs)
|
||||||
|
fsfuncs->EnumerateFiles("oxr_*.binds", XR_BindProfileFile, &h);
|
||||||
|
if (!h) //no user bindings defined, use fallbacks. probably this needs to be per-mod.
|
||||||
|
{
|
||||||
|
for (h = 0; h < countof(xr_knownprofiles); h++)
|
||||||
|
XR_BindProfileStr(xr_knownprofiles[h].name, xr_knownprofiles[h].script);
|
||||||
}
|
}
|
||||||
|
|
||||||
//begin session specific. stuff
|
//begin session specific. stuff
|
||||||
|
@ -1295,8 +1215,7 @@ static void XR_UpdateInputs(XrTime time)
|
||||||
(loc.locationFlags&XR_SPACE_LOCATION_ORIENTATION_VALID_BIT)?angles:NULL,
|
(loc.locationFlags&XR_SPACE_LOCATION_ORIENTATION_VALID_BIT)?angles:NULL,
|
||||||
(vel.velocityFlags&XR_SPACE_VELOCITY_LINEAR_VALID_BIT)?lvel:NULL,
|
(vel.velocityFlags&XR_SPACE_VELOCITY_LINEAR_VALID_BIT)?lvel:NULL,
|
||||||
(vel.velocityFlags&XR_SPACE_VELOCITY_ANGULAR_VALID_BIT)?avel:NULL))
|
(vel.velocityFlags&XR_SPACE_VELOCITY_ANGULAR_VALID_BIT)?avel:NULL))
|
||||||
if (transform[3][0] || transform[3][1] || transform[3][2])
|
{ //custom poses that mods might want to handle themselves...
|
||||||
{
|
|
||||||
vec3_t angles;
|
vec3_t angles;
|
||||||
char cmd[256];
|
char cmd[256];
|
||||||
VectorAngles(transform[0], transform[2], angles, false);
|
VectorAngles(transform[0], transform[2], angles, false);
|
||||||
|
@ -1695,7 +1614,7 @@ static qboolean XR_SyncFrame(double *frametime)
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
static qboolean XR_Render(void(*rendereye)(texid_t tex, vec4_t fovoverride, matrix3x4 axisorg))
|
static qboolean XR_Render(void(*rendereye)(texid_t tex, vec4_t fovoverride, vec3_t angorg[2]))
|
||||||
{
|
{
|
||||||
XrFrameEndInfo endframeinfo = {XR_TYPE_FRAME_END_INFO};
|
XrFrameEndInfo endframeinfo = {XR_TYPE_FRAME_END_INFO};
|
||||||
unsigned int u;
|
unsigned int u;
|
||||||
|
@ -1762,7 +1681,6 @@ static qboolean XR_Render(void(*rendereye)(texid_t tex, vec4_t fovoverride, matr
|
||||||
XrViewState viewstate = {XR_TYPE_VIEW_STATE};
|
XrViewState viewstate = {XR_TYPE_VIEW_STATE};
|
||||||
XrViewLocateInfo locateinfo = {XR_TYPE_VIEW_LOCATE_INFO};
|
XrViewLocateInfo locateinfo = {XR_TYPE_VIEW_LOCATE_INFO};
|
||||||
XrView eyeview[MAX_VIEW_COUNT]={};
|
XrView eyeview[MAX_VIEW_COUNT]={};
|
||||||
matrix3x4 transform, eyetransform, inv;
|
|
||||||
for (u = 0; u < MAX_VIEW_COUNT; u++)
|
for (u = 0; u < MAX_VIEW_COUNT; u++)
|
||||||
eyeview[u].type = XR_TYPE_VIEW;
|
eyeview[u].type = XR_TYPE_VIEW;
|
||||||
|
|
||||||
|
@ -1802,8 +1720,6 @@ static qboolean XR_Render(void(*rendereye)(texid_t tex, vec4_t fovoverride, matr
|
||||||
apose.position.y /= xr.viewcount;
|
apose.position.y /= xr.viewcount;
|
||||||
apose.position.z /= xr.viewcount;
|
apose.position.z /= xr.viewcount;
|
||||||
XR_PoseToAngOrg(&apose, ang, org);
|
XR_PoseToAngOrg(&apose, ang, org);
|
||||||
Matrix3x4_FromAngles(ang, org, transform[0]);
|
|
||||||
Matrix3x4_Invert_XR(transform[0], inv[0]);
|
|
||||||
inputfuncs->SetHandPosition("head", org, ang, NULL, NULL);
|
inputfuncs->SetHandPosition("head", org, ang, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1812,6 +1728,7 @@ static qboolean XR_Render(void(*rendereye)(texid_t tex, vec4_t fovoverride, matr
|
||||||
vec4_t fovoverride;
|
vec4_t fovoverride;
|
||||||
XrSwapchainImageWaitInfo waitinfo = {XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO};
|
XrSwapchainImageWaitInfo waitinfo = {XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO};
|
||||||
unsigned int imgidx = 0;
|
unsigned int imgidx = 0;
|
||||||
|
vec3_t orientation[2];
|
||||||
res = xrAcquireSwapchainImage(xr.eye[u].swapchain, NULL, &imgidx);
|
res = xrAcquireSwapchainImage(xr.eye[u].swapchain, NULL, &imgidx);
|
||||||
if (XR_FAILED(res))
|
if (XR_FAILED(res))
|
||||||
Con_Printf("xrAcquireSwapchainImage: %s\n", XR_StringForResult(res));
|
Con_Printf("xrAcquireSwapchainImage: %s\n", XR_StringForResult(res));
|
||||||
|
@ -1822,8 +1739,7 @@ static qboolean XR_Render(void(*rendereye)(texid_t tex, vec4_t fovoverride, matr
|
||||||
projviews[u].fov = eyeview[u].fov;
|
projviews[u].fov = eyeview[u].fov;
|
||||||
projviews[u].subImage = xr.eye[u].subimage;
|
projviews[u].subImage = xr.eye[u].subimage;
|
||||||
|
|
||||||
XR_PoseToTransform(&eyeview[u].pose, transform[0]);
|
XR_PoseToAngOrg(&eyeview[u].pose, orientation[0], orientation[1]);
|
||||||
Matrix3x4_Multiply_XR(transform[0], inv[0], eyetransform[0]);
|
|
||||||
|
|
||||||
fovoverride[0] = eyeview[u].fov.angleLeft * (180/M_PI);
|
fovoverride[0] = eyeview[u].fov.angleLeft * (180/M_PI);
|
||||||
fovoverride[1] = eyeview[u].fov.angleRight * (180/M_PI);
|
fovoverride[1] = eyeview[u].fov.angleRight * (180/M_PI);
|
||||||
|
@ -1834,7 +1750,7 @@ static qboolean XR_Render(void(*rendereye)(texid_t tex, vec4_t fovoverride, matr
|
||||||
res = xrWaitSwapchainImage(xr.eye[u].swapchain, &waitinfo);
|
res = xrWaitSwapchainImage(xr.eye[u].swapchain, &waitinfo);
|
||||||
if (XR_FAILED(res))
|
if (XR_FAILED(res))
|
||||||
Con_Printf("xrWaitSwapchainImage: %s\n", XR_StringForResult(res));
|
Con_Printf("xrWaitSwapchainImage: %s\n", XR_StringForResult(res));
|
||||||
rendereye(&xr.eye[u].swapimages[imgidx], fovoverride, eyetransform);
|
rendereye(&xr.eye[u].swapimages[imgidx], fovoverride, orientation);
|
||||||
//GL note: the OpenXR specification says NOTHING about the application having to glFlush or glFinish.
|
//GL note: the OpenXR specification says NOTHING about the application having to glFlush or glFinish.
|
||||||
// I take this to mean that the openxr runtime is responsible for setting up barriers or w/e inside ReleaseSwapchainImage.
|
// I take this to mean that the openxr runtime is responsible for setting up barriers or w/e inside ReleaseSwapchainImage.
|
||||||
//VK note: the OpenXR spec does say that it needs to be color_attachment_optimal+owned by queue. which it is.
|
//VK note: the OpenXR spec does say that it needs to be color_attachment_optimal+owned by queue. which it is.
|
||||||
|
|
Loading…
Reference in a new issue