Apply Seth Galbraith's <sgalbrai@linknet.kitsap.lib.wa.us> chasecam patch

This commit is contained in:
Bill Currie 2001-09-28 07:51:15 +00:00
parent e892131af5
commit c78edb3a36
7 changed files with 567 additions and 27 deletions

View file

@ -37,6 +37,22 @@ static const char rcsid[] =
#include "client.h"
#include "world.h"
#include "QF/keys.h"
#include "QF/input.h"
float CL_KeyState (kbutton_t *key);
vec3_t camera_origin = {0,0,0};
vec3_t camera_angles = {0,0,0};
vec3_t player_origin = {0,0,0};
vec3_t player_angles = {0,0,0};
extern kbutton_t in_mlook, in_klook;
extern kbutton_t in_left, in_right, in_forward, in_back;
extern kbutton_t in_lookup, in_lookdown;
extern kbutton_t in_moveleft, in_moveright;
extern kbutton_t in_strafe, in_speed;
qboolean SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f,
vec3_t p1, vec3_t p2, trace_t *trace);
@ -78,38 +94,167 @@ TraceLine (vec3_t start, vec3_t end, vec3_t impact)
VectorCopy (trace.endpos, impact);
}
/*
==================
Chase_Update
==================
*/
void
Chase_Update (void)
{
int i;
float dist;
vec3_t forward, up, right;
vec3_t dest, stop;
vec3_t forward, up, right, stop, dir;
float pitch, yaw, fwd;
usercmd_t cmd; // movement direction
int i;
// lazy camera, look toward player entity
if (chase_active->int_val == 2 || chase_active->int_val == 3)
{
// control camera angles with key/mouse/joy-look
camera_angles[PITCH] += cl.viewangles[PITCH] - player_angles[PITCH];
camera_angles[YAW] += cl.viewangles[YAW] - player_angles[YAW];
camera_angles[ROLL] += cl.viewangles[ROLL] - player_angles[ROLL];
if (chase_active->int_val == 2)
{
if (camera_angles[PITCH] < -60) camera_angles[PITCH] = -60;
if (camera_angles[PITCH] > 60) camera_angles[PITCH] = 60;
}
// move camera, it's not enough to just change the angles because
// the angles are automatically changed to look toward the player
if (chase_active->int_val == 3)
VectorCopy (r_refdef.vieworg, player_origin);
AngleVectors (camera_angles, forward, right, up);
VectorScale (forward, chase_back->value, forward);
VectorSubtract (player_origin, forward, camera_origin);
if (chase_active->int_val == 2)
{
VectorCopy (r_refdef.vieworg, player_origin);
// don't let camera get too low
if (camera_origin[2] < player_origin[2] + chase_up->value)
camera_origin[2] = player_origin[2] + chase_up->value;
}
// don't let camera get too far from player
VectorSubtract (camera_origin, player_origin, dir);
VectorCopy (dir, forward);
VectorNormalize (forward);
if (Length (dir) > chase_back->value)
{
VectorScale (forward, chase_back->value, dir);
VectorAdd (player_origin, dir, camera_origin);
}
// check for walls between player and camera
VectorScale (forward, 8, forward);
VectorAdd (camera_origin, forward, camera_origin);
TraceLine (player_origin, camera_origin, stop);
if (Length (stop) != 0)
VectorSubtract (stop, forward, camera_origin);
VectorSubtract (camera_origin, r_refdef.vieworg, dir);
VectorCopy (dir, forward);
VectorNormalize (forward);
if (chase_active->int_val == 2)
{
if (dir[1] == 0 && dir[0] == 0)
{
// look straight up or down
// camera_angles[YAW] = r_refdef.viewangles[YAW];
if (dir[2] > 0) camera_angles[PITCH] = 90;
else camera_angles[PITCH] = 270;
}
else
{
yaw = (atan2 (dir[1], dir[0]) * 180 / M_PI);
if (yaw < 0) yaw += 360;
if (yaw < 180) yaw += 180;
else yaw -= 180;
camera_angles[YAW] = yaw;
fwd = sqrt (dir[0] * dir[0] + dir[1] * dir[1]);
pitch = (atan2 (dir[2], fwd) * 180 / M_PI);
if (pitch < 0) pitch += 360;
camera_angles[PITCH] = pitch;
}
}
VectorCopy (camera_angles, r_refdef.viewangles); // rotate camera
VectorCopy (camera_origin, r_refdef.vieworg); // move camera
// get basic movement from keyboard
memset (&cmd, 0, sizeof (cmd));
// VectorCopy (cl.viewangles, cmd.angles);
if (in_strafe.state & 1) {
cmd.sidemove += cl_sidespeed->value * CL_KeyState (&in_right);
cmd.sidemove -= cl_sidespeed->value * CL_KeyState (&in_left);
}
cmd.sidemove += cl_sidespeed->value * CL_KeyState (&in_moveright);
cmd.sidemove -= cl_sidespeed->value * CL_KeyState (&in_moveleft);
if (!(in_klook.state & 1)) {
cmd.forwardmove += cl_forwardspeed->value * CL_KeyState (&in_forward);
cmd.forwardmove -= cl_backspeed->value * CL_KeyState (&in_back);
}
if (in_speed.state & 1) {
cmd.forwardmove *= cl_movespeedkey->value;
cmd.sidemove *= cl_movespeedkey->value;
}
// mouse and joystick controllers add to movement
// IN_Move (&cmd); // problem - mouse strafe movement is weird
dir[1] = camera_angles[1]; dir[0] = 0; dir[2] = 0;
AngleVectors (dir, forward, right, up);
VectorScale (forward, cmd.forwardmove, forward);
VectorScale (right, cmd.sidemove, right);
VectorAdd (forward, right, dir);
if (dir[1] || dir[0])
{
cl.viewangles[YAW] = (atan2 (dir[1], dir[0]) * 180 / M_PI);
if (cl.viewangles[YAW] < 0) cl.viewangles[YAW] += 360;
// if (cl.viewangles[YAW] < 180) cl.viewangles[YAW] += 180;
// else cl.viewangles[YAW] -= 180;
}
cl.viewangles[PITCH] = 0;
// remember the new angle to calculate the difference next frame
VectorCopy (cl.viewangles, player_angles);
return;
}
// regular camera, faces same direction as player
// if can't see player, reset
AngleVectors (cl.viewangles, forward, right, up);
// calc exact destination
for (i = 0; i < 3; i++)
chase_dest[i] = r_refdef.vieworg[i]
camera_origin[i] = r_refdef.vieworg[i]
- forward[i] * chase_back->value - right[i] * chase_right->value;
chase_dest[2] = r_refdef.vieworg[2] + chase_up->value;
camera_origin[2] = r_refdef.vieworg[2] + chase_up->value;
// find the spot the player is looking at
VectorMA (r_refdef.vieworg, 4096, forward, dest);
TraceLine (r_refdef.vieworg, dest, stop);
// calculate pitch to look at the same spot from camera
VectorSubtract (stop, r_refdef.vieworg, stop);
dist = DotProduct (stop, forward);
if (dist < 1)
dist = 1;
r_refdef.viewangles[PITCH] = -atan (stop[2] / dist) / M_PI * 180;
TraceLine (r_refdef.vieworg, chase_dest, stop);
// check for walls between player and camera
TraceLine (r_refdef.vieworg, camera_origin, stop);
if (Length (stop) != 0)
VectorCopy (stop, chase_dest);
for (i = 0; i < 3; i++)
camera_origin[i] = stop[i] + forward[i] * 8;
// move towards destination
VectorCopy (chase_dest, r_refdef.vieworg);
VectorCopy (camera_origin, r_refdef.vieworg);
}

View file

@ -459,6 +459,8 @@ CL_AdjustAngles (void)
}
extern cvar_t *chase_active;
/*
CL_BaseMove
@ -505,6 +507,21 @@ CL_BaseMove (usercmd_t *cmd)
IN_Move ();
// adjust for chase camera angles
if (chase_active->int_val == 2 || chase_active->int_val == 3)
{
vec3_t dir = {0,0,0}, forward, right, up;
dir[1] = r_refdef.viewangles[1] - cl.viewangles[1];
AngleVectors (dir, forward, right, up);
VectorScale (forward, cmd->forwardmove, forward);
VectorScale (right, cmd->sidemove, right);
VectorAdd (forward, right, dir);
cmd->forwardmove = dir[0];
cmd->sidemove = dir[1];
}
cmd->forwardmove += viewdelta.position[2] * m_forward->value;
cmd->sidemove += viewdelta.position[0] * m_side->value;
cmd->upmove += viewdelta.position[1];

View file

@ -52,4 +52,6 @@ void CL_Cam_Init_Cvars(void);
void CL_ParseEntityLump(const char *entdata);
void Chase_Update (void);
#endif // _CL_CAM_H

View file

@ -61,6 +61,33 @@ static const char rcsid[] =
#define BUTTON_ATTACK 1
#define MAX_ANGLE_TURN 10
#include "QF/sys.h"
#include "QF/keys.h"
#include "QF/input.h"
#include "QF/mathlib.h"
#include "world.h"
float CL_KeyState (kbutton_t *key);
vec3_t camera_origin = {0,0,0};
vec3_t camera_angles = {0,0,0};
vec3_t player_origin = {0,0,0};
vec3_t player_angles = {0,0,0};
extern kbutton_t in_mlook, in_klook;
extern kbutton_t in_left, in_right, in_forward, in_back;
extern kbutton_t in_lookup, in_lookdown;
extern kbutton_t in_moveleft, in_moveright;
extern kbutton_t in_strafe, in_speed;
qboolean SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f,
vec3_t p1, vec3_t p2, trace_t *trace);
cvar_t *chase_back;
cvar_t *chase_up;
cvar_t *chase_right;
cvar_t *chase_active;
static vec3_t desired_position; // where the camera wants to be
static qboolean locked = false;
static int oldbuttons;
@ -119,6 +146,10 @@ vlen (vec3_t v)
qboolean
Cam_DrawViewModel (void)
{
if (atoi (Info_ValueForKey (cl.serverinfo, "chase"))
&& chase_active->int_val)
return false;
if (!cl.spectator)
return true;
@ -131,6 +162,10 @@ Cam_DrawViewModel (void)
qboolean
Cam_DrawPlayer (int playernum)
{
if (atoi (Info_ValueForKey (cl.serverinfo, "chase")) == 0
|| chase_active->int_val == 0)
return false;
if (cl.spectator && autocam && locked && cl_chasecam->int_val &&
spec_track == playernum)
return false;
@ -616,4 +651,312 @@ CL_Cam_Init_Cvars (void)
cl_hightrack = Cvar_Get ("cl_hightrack", "0", CVAR_NONE, NULL, "view the "
"player who has the most frags while you are in "
"spectator mode.");
chase_back = Cvar_Get ("chase_back", "100", CVAR_NONE, NULL, "None");
chase_up = Cvar_Get ("chase_up", "16", CVAR_NONE, NULL, "None");
chase_right = Cvar_Get ("chase_right", "0", CVAR_NONE, NULL, "None");
chase_active = Cvar_Get ("chase_active", "0", CVAR_NONE, NULL, "None");
}
// 1/32 epsilon to keep floating point happy
#define DIST_EPSILON (0.03125)
qboolean
SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1,
vec3_t p2, trace_t *trace)
{
dclipnode_t *node;
mplane_t *plane;
float t1, t2;
float frac;
int i;
vec3_t mid;
int side;
float midf;
// check for empty
if (num < 0) {
if (num != CONTENTS_SOLID) {
trace->allsolid = false;
if (num == CONTENTS_EMPTY)
trace->inopen = true;
else
trace->inwater = true;
} else
trace->startsolid = true;
return true; // empty
}
if (num < hull->firstclipnode || num > hull->lastclipnode)
Sys_Error ("SV_RecursiveHullCheck: bad node number");
// find the point distances
node = hull->clipnodes + num;
plane = hull->planes + node->planenum;
if (plane->type < 3) {
t1 = p1[plane->type] - plane->dist;
t2 = p2[plane->type] - plane->dist;
} else {
t1 = DotProduct (plane->normal, p1) - plane->dist;
t2 = DotProduct (plane->normal, p2) - plane->dist;
}
#if 1
if (t1 >= 0 && t2 >= 0)
return SV_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1,
p2, trace);
if (t1 < 0 && t2 < 0)
return SV_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1,
p2, trace);
#else
if ((t1 >= DIST_EPSILON && t2 >= DIST_EPSILON) || (t2 > t1 && t1 >= 0))
return SV_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1,
p2, trace);
if ((t1 <= -DIST_EPSILON && t2 <= -DIST_EPSILON) || (t2 < t1 && t1 <= 0))
return SV_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1,
p2, trace);
#endif
// put the crosspoint DIST_EPSILON pixels on the near side
if (t1 < 0)
frac = (t1 + DIST_EPSILON) / (t1 - t2);
else
frac = (t1 - DIST_EPSILON) / (t1 - t2);
if (frac < 0)
frac = 0;
if (frac > 1)
frac = 1;
midf = p1f + (p2f - p1f) * frac;
for (i = 0; i < 3; i++)
mid[i] = p1[i] + frac * (p2[i] - p1[i]);
side = (t1 < 0);
// move up to the node
if (!SV_RecursiveHullCheck
(hull, node->children[side], p1f, midf, p1, mid, trace)) return false;
#ifdef PARANOID
if (SV_HullPointContents (sv_hullmodel, mid, node->children[side])
== CONTENTS_SOLID) {
Sys_Printf ("mid PointInHullSolid\n");
return false;
}
#endif
if (SV_HullPointContents (hull, node->children[side ^ 1], mid)
!= CONTENTS_SOLID)
// go past the node
return SV_RecursiveHullCheck (hull, node->children[side ^ 1], midf,
p2f, mid, p2, trace);
if (trace->allsolid)
return false; // never got out of the solid area
// the other side of the node is solid, this is the impact point
if (!side) {
VectorCopy (plane->normal, trace->plane.normal);
trace->plane.dist = plane->dist;
} else {
VectorSubtract (vec3_origin, plane->normal, trace->plane.normal);
trace->plane.dist = -plane->dist;
}
while (SV_HullPointContents (hull, hull->firstclipnode, mid)
== CONTENTS_SOLID) { // shouldn't really happen, but does
// occasionally
frac -= 0.1;
if (frac < 0) {
trace->fraction = midf;
VectorCopy (mid, trace->endpos);
Sys_Printf ("backup past 0\n");
return false;
}
midf = p1f + (p2f - p1f) * frac;
for (i = 0; i < 3; i++)
mid[i] = p1[i] + frac * (p2[i] - p1[i]);
}
trace->fraction = midf;
VectorCopy (mid, trace->endpos);
return false;
}
void
TraceLine (vec3_t start, vec3_t end, vec3_t impact)
{
trace_t trace;
memset (&trace, 0, sizeof (trace));
SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, start, end, &trace);
VectorCopy (trace.endpos, impact);
}
/*
==================
Chase_Update
==================
*/
void
Chase_Update (void)
{
vec3_t forward, up, right, stop, dir;
float pitch, yaw, fwd;
usercmd_t cmd; // movement direction
int i;
// lazy camera, look toward player entity
if (chase_active->int_val == 2 || chase_active->int_val == 3)
{
// control camera angles with key/mouse/joy-look
camera_angles[PITCH] += cl.viewangles[PITCH] - player_angles[PITCH];
camera_angles[YAW] += cl.viewangles[YAW] - player_angles[YAW];
camera_angles[ROLL] += cl.viewangles[ROLL] - player_angles[ROLL];
if (chase_active->int_val == 2)
{
if (camera_angles[PITCH] < -60) camera_angles[PITCH] = -60;
if (camera_angles[PITCH] > 60) camera_angles[PITCH] = 60;
}
// move camera, it's not enough to just change the angles because
// the angles are automatically changed to look toward the player
if (chase_active->int_val == 3)
VectorCopy (r_refdef.vieworg, player_origin);
AngleVectors (camera_angles, forward, right, up);
VectorScale (forward, chase_back->value, forward);
VectorSubtract (player_origin, forward, camera_origin);
if (chase_active->int_val == 2)
{
VectorCopy (r_refdef.vieworg, player_origin);
// don't let camera get too low
if (camera_origin[2] < player_origin[2] + chase_up->value)
camera_origin[2] = player_origin[2] + chase_up->value;
}
// don't let camera get too far from player
VectorSubtract (camera_origin, player_origin, dir);
VectorCopy (dir, forward);
VectorNormalize (forward);
if (Length (dir) > chase_back->value)
{
VectorScale (forward, chase_back->value, dir);
VectorAdd (player_origin, dir, camera_origin);
}
// check for walls between player and camera
VectorScale (forward, 8, forward);
VectorAdd (camera_origin, forward, camera_origin);
TraceLine (player_origin, camera_origin, stop);
if (Length (stop) != 0)
VectorSubtract (stop, forward, camera_origin);
VectorSubtract (camera_origin, r_refdef.vieworg, dir);
VectorCopy (dir, forward);
VectorNormalize (forward);
if (chase_active->int_val == 2)
{
if (dir[1] == 0 && dir[0] == 0)
{
// look straight up or down
// camera_angles[YAW] = r_refdef.viewangles[YAW];
if (dir[2] > 0) camera_angles[PITCH] = 90;
else camera_angles[PITCH] = 270;
}
else
{
yaw = (atan2 (dir[1], dir[0]) * 180 / M_PI);
if (yaw < 0) yaw += 360;
if (yaw < 180) yaw += 180;
else yaw -= 180;
camera_angles[YAW] = yaw;
fwd = sqrt (dir[0] * dir[0] + dir[1] * dir[1]);
pitch = (atan2 (dir[2], fwd) * 180 / M_PI);
if (pitch < 0) pitch += 360;
camera_angles[PITCH] = pitch;
}
}
VectorCopy (camera_angles, r_refdef.viewangles); // rotate camera
VectorCopy (camera_origin, r_refdef.vieworg); // move camera
// get basic movement from keyboard
memset (&cmd, 0, sizeof (cmd));
// VectorCopy (cl.viewangles, cmd.angles);
if (in_strafe.state & 1) {
cmd.sidemove += cl_sidespeed->value * CL_KeyState (&in_right);
cmd.sidemove -= cl_sidespeed->value * CL_KeyState (&in_left);
}
cmd.sidemove += cl_sidespeed->value * CL_KeyState (&in_moveright);
cmd.sidemove -= cl_sidespeed->value * CL_KeyState (&in_moveleft);
if (!(in_klook.state & 1)) {
cmd.forwardmove += cl_forwardspeed->value * CL_KeyState (&in_forward);
cmd.forwardmove -= cl_backspeed->value * CL_KeyState (&in_back);
}
if (in_speed.state & 1) {
cmd.forwardmove *= cl_movespeedkey->value;
cmd.sidemove *= cl_movespeedkey->value;
}
// mouse and joystick controllers add to movement
// IN_Move (&cmd); // problem - mouse strafe movement is weird
dir[1] = camera_angles[1]; dir[0] = 0; dir[2] = 0;
AngleVectors (dir, forward, right, up);
VectorScale (forward, cmd.forwardmove, forward);
VectorScale (right, cmd.sidemove, right);
VectorAdd (forward, right, dir);
if (dir[1] || dir[0])
{
cl.viewangles[YAW] = (atan2 (dir[1], dir[0]) * 180 / M_PI);
if (cl.viewangles[YAW] < 0) cl.viewangles[YAW] += 360;
// if (cl.viewangles[YAW] < 180) cl.viewangles[YAW] += 180;
// else cl.viewangles[YAW] -= 180;
}
cl.viewangles[PITCH] = 0;
// remember the new angle to calculate the difference next frame
VectorCopy (cl.viewangles, player_angles);
return;
}
// regular camera, faces same direction as player
AngleVectors (cl.viewangles, forward, right, up);
// calc exact destination
for (i = 0; i < 3; i++)
camera_origin[i] = r_refdef.vieworg[i]
- forward[i] * chase_back->value - right[i] * chase_right->value;
camera_origin[2] = r_refdef.vieworg[2] + chase_up->value;
// check for walls between player and camera
TraceLine (r_refdef.vieworg, camera_origin, stop);
if (Length (stop) != 0)
for (i = 0; i < 3; i++)
camera_origin[i] = stop[i] + forward[i] * 8;
VectorCopy (camera_origin, r_refdef.vieworg);
}

View file

@ -805,7 +805,7 @@ CL_LinkPlayers (void)
// things (due to lack of lights?), so I'm leaving this as is for now.
// the player object never gets added
if (j == cl.playernum) {
if (j == cl.playernum && !Cam_DrawPlayer (j)) {
r_player_entity = &cl_player_ents[state - frame->playerstate];
continue;
}
@ -858,11 +858,18 @@ CL_LinkPlayers (void)
(*ent)->colormod[0] = (*ent)->colormod[1] = (*ent)->colormod[2] = 1;
// angles
(*ent)->angles[PITCH] = -state->viewangles[PITCH] / 3;
(*ent)->angles[YAW] = state->viewangles[YAW];
if (j == cl.playernum)
{
(*ent)->angles[PITCH] = -cl.viewangles[PITCH] / 3;
(*ent)->angles[YAW] = cl.viewangles[YAW];
}
else
{
(*ent)->angles[PITCH] = -state->viewangles[PITCH] / 3;
(*ent)->angles[YAW] = state->viewangles[YAW];
}
(*ent)->angles[ROLL] = 0;
(*ent)->angles[ROLL] =
V_CalcRoll ((*ent)->angles, state->velocity) * 4;
(*ent)->angles[ROLL] = V_CalcRoll ((*ent)->angles, state->velocity) * 4;
// only predict half the move to minimize overruns
msec = 500 * (playertime - state->state_time);

View file

@ -475,6 +475,8 @@ CL_AdjustAngles (void)
}
extern cvar_t *chase_active;
/*
CL_BaseMove
@ -519,6 +521,22 @@ CL_BaseMove (usercmd_t *cmd)
IN_Move ();
// adjust for chase camera angles
if (atoi (Info_ValueForKey (cl.serverinfo, "chase"))
&& (chase_active->int_val == 2 || chase_active->int_val == 3))
{
vec3_t dir = {0,0,0}, forward, right, up;
dir[1] = r_refdef.viewangles[1] - cl.viewangles[1];
AngleVectors (dir, forward, right, up);
VectorScale (forward, cmd->forwardmove, forward);
VectorScale (right, cmd->sidemove, right);
VectorAdd (forward, right, dir);
cmd->forwardmove = dir[0];
cmd->sidemove = dir[1];
}
cmd->forwardmove += viewdelta.position[2] * m_forward->value;
cmd->sidemove += viewdelta.position[0] * m_side->value;
cmd->upmove += viewdelta.position[1];

View file

@ -619,6 +619,10 @@ V_CalcIntermissionRefdef (void)
Cvar_SetValue (v_idlescale, old);
}
#include "cl_cam.h"
extern cvar_t *chase_active;
void
V_CalcRefdef (void)
{
@ -724,6 +728,10 @@ V_CalcRefdef (void)
view->origin[2] += oldz - cl.simorg[2];
} else
oldz = cl.simorg[2];
if (atoi (Info_ValueForKey (cl.serverinfo, "chase"))
&& chase_active->int_val)
Chase_Update ();
}
void