Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

cl_pred.c (6199B)


      1 /*
      2 Copyright (C) 1997-2001 Id Software, Inc.
      3 
      4 This program is free software; you can redistribute it and/or
      5 modify it under the terms of the GNU General Public License
      6 as published by the Free Software Foundation; either version 2
      7 of the License, or (at your option) any later version.
      8 
      9 This program is distributed in the hope that it will be useful,
     10 but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
     12 
     13 See the GNU General Public License for more details.
     14 
     15 You should have received a copy of the GNU General Public License
     16 along with this program; if not, write to the Free Software
     17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     18 
     19 */
     20 
     21 #include "client.h"
     22 
     23 
     24 /*
     25 ===================
     26 CL_CheckPredictionError
     27 ===================
     28 */
     29 void CL_CheckPredictionError (void)
     30 {
     31 	int		frame;
     32 	int		delta[3];
     33 	int		i;
     34 	int		len;
     35 
     36 	if (!cl_predict->value || (cl.frame.playerstate.pmove.pm_flags & PMF_NO_PREDICTION))
     37 		return;
     38 
     39 	// calculate the last usercmd_t we sent that the server has processed
     40 	frame = cls.netchan.incoming_acknowledged;
     41 	frame &= (CMD_BACKUP-1);
     42 
     43 	// compare what the server returned with what we had predicted it to be
     44 	VectorSubtract (cl.frame.playerstate.pmove.origin, cl.predicted_origins[frame], delta);
     45 
     46 	// save the prediction error for interpolation
     47 	len = abs(delta[0]) + abs(delta[1]) + abs(delta[2]);
     48 	if (len > 640)	// 80 world units
     49 	{	// a teleport or something
     50 		VectorClear (cl.prediction_error);
     51 	}
     52 	else
     53 	{
     54 		if (cl_showmiss->value && (delta[0] || delta[1] || delta[2]) )
     55 			Com_Printf ("prediction miss on %i: %i\n", cl.frame.serverframe, 
     56 			delta[0] + delta[1] + delta[2]);
     57 
     58 		VectorCopy (cl.frame.playerstate.pmove.origin, cl.predicted_origins[frame]);
     59 
     60 		// save for error itnerpolation
     61 		for (i=0 ; i<3 ; i++)
     62 			cl.prediction_error[i] = delta[i]*0.125;
     63 	}
     64 }
     65 
     66 
     67 /*
     68 ====================
     69 CL_ClipMoveToEntities
     70 
     71 ====================
     72 */
     73 void CL_ClipMoveToEntities ( vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, trace_t *tr )
     74 {
     75 	int			i, x, zd, zu;
     76 	trace_t		trace;
     77 	int			headnode;
     78 	float		*angles;
     79 	entity_state_t	*ent;
     80 	int			num;
     81 	cmodel_t		*cmodel;
     82 	vec3_t		bmins, bmaxs;
     83 
     84 	for (i=0 ; i<cl.frame.num_entities ; i++)
     85 	{
     86 		num = (cl.frame.parse_entities + i)&(MAX_PARSE_ENTITIES-1);
     87 		ent = &cl_parse_entities[num];
     88 
     89 		if (!ent->solid)
     90 			continue;
     91 
     92 		if (ent->number == cl.playernum+1)
     93 			continue;
     94 
     95 		if (ent->solid == 31)
     96 		{	// special value for bmodel
     97 			cmodel = cl.model_clip[ent->modelindex];
     98 			if (!cmodel)
     99 				continue;
    100 			headnode = cmodel->headnode;
    101 			angles = ent->angles;
    102 		}
    103 		else
    104 		{	// encoded bbox
    105 			x = 8*(ent->solid & 31);
    106 			zd = 8*((ent->solid>>5) & 31);
    107 			zu = 8*((ent->solid>>10) & 63) - 32;
    108 
    109 			bmins[0] = bmins[1] = -x;
    110 			bmaxs[0] = bmaxs[1] = x;
    111 			bmins[2] = -zd;
    112 			bmaxs[2] = zu;
    113 
    114 			headnode = CM_HeadnodeForBox (bmins, bmaxs);
    115 			angles = vec3_origin;	// boxes don't rotate
    116 		}
    117 
    118 		if (tr->allsolid)
    119 			return;
    120 
    121 		trace = CM_TransformedBoxTrace (start, end,
    122 			mins, maxs, headnode,  MASK_PLAYERSOLID,
    123 			ent->origin, angles);
    124 
    125 		if (trace.allsolid || trace.startsolid ||
    126 		trace.fraction < tr->fraction)
    127 		{
    128 			trace.ent = (struct edict_s *)ent;
    129 		 	if (tr->startsolid)
    130 			{
    131 				*tr = trace;
    132 				tr->startsolid = true;
    133 			}
    134 			else
    135 				*tr = trace;
    136 		}
    137 		else if (trace.startsolid)
    138 			tr->startsolid = true;
    139 	}
    140 }
    141 
    142 
    143 /*
    144 ================
    145 CL_PMTrace
    146 ================
    147 */
    148 trace_t		CL_PMTrace (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end)
    149 {
    150 	trace_t	t;
    151 
    152 	// check against world
    153 	t = CM_BoxTrace (start, end, mins, maxs, 0, MASK_PLAYERSOLID);
    154 	if (t.fraction < 1.0)
    155 		t.ent = (struct edict_s *)1;
    156 
    157 	// check all other solid models
    158 	CL_ClipMoveToEntities (start, mins, maxs, end, &t);
    159 
    160 	return t;
    161 }
    162 
    163 int		CL_PMpointcontents (vec3_t point)
    164 {
    165 	int			i;
    166 	entity_state_t	*ent;
    167 	int			num;
    168 	cmodel_t		*cmodel;
    169 	int			contents;
    170 
    171 	contents = CM_PointContents (point, 0);
    172 
    173 	for (i=0 ; i<cl.frame.num_entities ; i++)
    174 	{
    175 		num = (cl.frame.parse_entities + i)&(MAX_PARSE_ENTITIES-1);
    176 		ent = &cl_parse_entities[num];
    177 
    178 		if (ent->solid != 31) // special value for bmodel
    179 			continue;
    180 
    181 		cmodel = cl.model_clip[ent->modelindex];
    182 		if (!cmodel)
    183 			continue;
    184 
    185 		contents |= CM_TransformedPointContents (point, cmodel->headnode, ent->origin, ent->angles);
    186 	}
    187 
    188 	return contents;
    189 }
    190 
    191 
    192 /*
    193 =================
    194 CL_PredictMovement
    195 
    196 Sets cl.predicted_origin and cl.predicted_angles
    197 =================
    198 */
    199 void CL_PredictMovement (void)
    200 {
    201 	int			ack, current;
    202 	int			frame;
    203 	int			oldframe;
    204 	usercmd_t	*cmd;
    205 	pmove_t		pm;
    206 	int			i;
    207 	int			step;
    208 	int			oldz;
    209 
    210 	if (cls.state != ca_active)
    211 		return;
    212 
    213 	if (cl_paused->value)
    214 		return;
    215 
    216 	if (!cl_predict->value || (cl.frame.playerstate.pmove.pm_flags & PMF_NO_PREDICTION))
    217 	{	// just set angles
    218 		for (i=0 ; i<3 ; i++)
    219 		{
    220 			cl.predicted_angles[i] = cl.viewangles[i] + SHORT2ANGLE(cl.frame.playerstate.pmove.delta_angles[i]);
    221 		}
    222 		return;
    223 	}
    224 
    225 	ack = cls.netchan.incoming_acknowledged;
    226 	current = cls.netchan.outgoing_sequence;
    227 
    228 	// if we are too far out of date, just freeze
    229 	if (current - ack >= CMD_BACKUP)
    230 	{
    231 		if (cl_showmiss->value)
    232 			Com_Printf ("exceeded CMD_BACKUP\n");
    233 		return;	
    234 	}
    235 
    236 	// copy current state to pmove
    237 	memset (&pm, 0, sizeof(pm));
    238 	pm.trace = CL_PMTrace;
    239 	pm.pointcontents = CL_PMpointcontents;
    240 
    241 	pm_airaccelerate = atof(cl.configstrings[CS_AIRACCEL]);
    242 
    243 	pm.s = cl.frame.playerstate.pmove;
    244 
    245 //	SCR_DebugGraph (current - ack - 1, 0);
    246 
    247 	frame = 0;
    248 
    249 	// run frames
    250 	while (++ack < current)
    251 	{
    252 		frame = ack & (CMD_BACKUP-1);
    253 		cmd = &cl.cmds[frame];
    254 
    255 		pm.cmd = *cmd;
    256 		Pmove (&pm);
    257 
    258 		// save for debug checking
    259 		VectorCopy (pm.s.origin, cl.predicted_origins[frame]);
    260 	}
    261 
    262 	oldframe = (ack-2) & (CMD_BACKUP-1);
    263 	oldz = cl.predicted_origins[oldframe][2];
    264 	step = pm.s.origin[2] - oldz;
    265 	if (step > 63 && step < 160 && (pm.s.pm_flags & PMF_ON_GROUND) )
    266 	{
    267 		cl.predicted_step = step * 0.125;
    268 		cl.predicted_step_time = cls.realtime - cls.frametime * 500;
    269 	}
    270 
    271 
    272 	// copy results out for rendering
    273 	cl.predicted_origin[0] = pm.s.origin[0]*0.125;
    274 	cl.predicted_origin[1] = pm.s.origin[1]*0.125;
    275 	cl.predicted_origin[2] = pm.s.origin[2]*0.125;
    276 
    277 	VectorCopy (pm.viewangles, cl.predicted_angles);
    278 }