|
|
1.1.1.3 ! root 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: */ 1.1 root 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: 1.1.1.2 root 241: pm_airaccelerate = atof(cl.configstrings[CS_AIRACCEL]); 242: 1.1 root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.