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 }