Quake II RTX doxygen  1.0 dev
predict.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (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. See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18 
19 #include "client.h"
20 #include "common/x86/fpu.h"
21 
22 /*
23 ===================
24 CL_CheckPredictionError
25 ===================
26 */
28 {
29  int frame;
30  int delta[3];
31  unsigned cmd;
32  int len;
33 
34  if (!cls.netchan) {
35  return;
36  }
37 
38  if (sv_paused->integer) {
39  VectorClear(cl.prediction_error);
40  return;
41  }
42 
43  if (!cl_predict->integer || (cl.frame.ps.pmove.pm_flags & PMF_NO_PREDICTION))
44  return;
45 
46  // calculate the last usercmd_t we sent that the server has processed
47  frame = cls.netchan->incoming_acknowledged & CMD_MASK;
48  cmd = cl.history[frame].cmdNumber;
49 
50  // compare what the server returned with what we had predicted it to be
51  VectorSubtract(cl.frame.ps.pmove.origin, cl.predicted_origins[cmd & CMD_MASK], delta);
52 
53  // save the prediction error for interpolation
54  len = abs(delta[0]) + abs(delta[1]) + abs(delta[2]);
55  if (len < 1 || len > 640) {
56  // > 80 world units is a teleport or something
57  VectorClear(cl.prediction_error);
58  return;
59  }
60 
61  SHOWMISS("prediction miss on %i: %i (%d %d %d)\n",
62  cl.frame.number, len, delta[0], delta[1], delta[2]);
63 
64  // don't predict steps against server returned data
65  if (cl.predicted_step_frame <= cmd)
66  cl.predicted_step_frame = cmd + 1;
67 
68  VectorCopy(cl.frame.ps.pmove.origin, cl.predicted_origins[cmd & CMD_MASK]);
69 
70  // save for error interpolation
71  VectorScale(delta, 0.125f, cl.prediction_error);
72 }
73 
74 /*
75 ====================
76 CL_ClipMoveToEntities
77 
78 ====================
79 */
80 static void CL_ClipMoveToEntities(vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, trace_t *tr)
81 {
82  int i;
83  trace_t trace;
84  mnode_t *headnode;
85  centity_t *ent;
86  mmodel_t *cmodel;
87 
88  for (i = 0; i < cl.numSolidEntities; i++) {
89  ent = cl.solidEntities[i];
90 
91  if (ent->current.solid == PACKED_BSP) {
92  // special value for bmodel
93  cmodel = cl.model_clip[ent->current.modelindex];
94  if (!cmodel)
95  continue;
96  headnode = cmodel->headnode;
97  } else {
98  headnode = CM_HeadnodeForBox(ent->mins, ent->maxs);
99  }
100 
101  if (tr->allsolid)
102  return;
103 
104  CM_TransformedBoxTrace(&trace, start, end,
105  mins, maxs, headnode, MASK_PLAYERSOLID,
106  ent->current.origin, ent->current.angles);
107 
108  CM_ClipEntity(tr, &trace, (struct edict_s *)ent);
109  }
110 }
111 
112 
113 /*
114 ================
115 CL_PMTrace
116 ================
117 */
118 static trace_t q_gameabi CL_Trace(vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end)
119 {
120  trace_t t;
121 
122  // check against world
123  CM_BoxTrace(&t, start, end, mins, maxs, cl.bsp->nodes, MASK_PLAYERSOLID);
124  if (t.fraction < 1.0)
125  t.ent = (struct edict_s *)1;
126 
127  // check all other solid models
128  CL_ClipMoveToEntities(start, mins, maxs, end, &t);
129 
130  return t;
131 }
132 
133 static int CL_PointContents(vec3_t point)
134 {
135  int i;
136  centity_t *ent;
137  mmodel_t *cmodel;
138  int contents;
139 
140  contents = CM_PointContents(point, cl.bsp->nodes);
141 
142  for (i = 0; i < cl.numSolidEntities; i++) {
143  ent = cl.solidEntities[i];
144 
145  if (ent->current.solid != PACKED_BSP) // special value for bmodel
146  continue;
147 
148  cmodel = cl.model_clip[ent->current.modelindex];
149  if (!cmodel)
150  continue;
151 
152  contents |= CM_TransformedPointContents(
153  point, cmodel->headnode,
154  ent->current.origin,
155  ent->current.angles);
156  }
157 
158  return contents;
159 }
160 
161 /*
162 =================
163 CL_PredictMovement
164 
165 Sets cl.predicted_origin and cl.predicted_angles
166 =================
167 */
169 {
170  cl.predicted_angles[0] = cl.viewangles[0] + SHORT2ANGLE(cl.frame.ps.pmove.delta_angles[0]);
171  cl.predicted_angles[1] = cl.viewangles[1] + SHORT2ANGLE(cl.frame.ps.pmove.delta_angles[1]);
172  cl.predicted_angles[2] = cl.viewangles[2] + SHORT2ANGLE(cl.frame.ps.pmove.delta_angles[2]);
173 }
174 
176 {
177  unsigned ack, current, frame;
178  pmove_t pm;
179  int step, oldz;
180 
181  if (cls.state != ca_active) {
182  return;
183  }
184 
185  if (cls.demo.playback) {
186  return;
187  }
188 
189  if (sv_paused->integer) {
190  return;
191  }
192 
193  if (!cl_predict->integer || (cl.frame.ps.pmove.pm_flags & PMF_NO_PREDICTION)) {
194  // just set angles
196  return;
197  }
198 
199  ack = cl.history[cls.netchan->incoming_acknowledged & CMD_MASK].cmdNumber;
200  current = cl.cmdNumber;
201 
202  // if we are too far out of date, just freeze
203  if (current - ack > CMD_BACKUP - 1) {
204  SHOWMISS("%i: exceeded CMD_BACKUP\n", cl.frame.number);
205  return;
206  }
207 
208  if (!cl.cmd.msec && current == ack) {
209  SHOWMISS("%i: not moved\n", cl.frame.number);
210  return;
211  }
212 
213  X86_PUSH_FPCW;
214  X86_SINGLE_FPCW;
215 
216  // copy current state to pmove
217  memset(&pm, 0, sizeof(pm));
218  pm.trace = CL_Trace;
219  pm.pointcontents = CL_PointContents;
220 
221  pm.s = cl.frame.ps.pmove;
222 #if USE_SMOOTH_DELTA_ANGLES
223  VectorCopy(cl.delta_angles, pm.s.delta_angles);
224 #endif
225 
226  // run frames
227  while (++ack <= current) {
228  pm.cmd = cl.cmds[ack & CMD_MASK];
229  Pmove(&pm, &cl.pmp);
230 
231  // save for debug checking
232  VectorCopy(pm.s.origin, cl.predicted_origins[ack & CMD_MASK]);
233  }
234 
235  // run pending cmd
236  if (cl.cmd.msec) {
237  pm.cmd = cl.cmd;
238  pm.cmd.forwardmove = cl.localmove[0];
239  pm.cmd.sidemove = cl.localmove[1];
240  pm.cmd.upmove = cl.localmove[2];
241  Pmove(&pm, &cl.pmp);
242  frame = current;
243 
244  // save for debug checking
245  VectorCopy(pm.s.origin, cl.predicted_origins[(current + 1) & CMD_MASK]);
246  } else {
247  frame = current - 1;
248  }
249 
250  X86_POP_FPCW;
251 
252  if (pm.s.pm_type != PM_SPECTATOR && (pm.s.pm_flags & PMF_ON_GROUND)) {
253  oldz = cl.predicted_origins[cl.predicted_step_frame & CMD_MASK][2];
254  step = pm.s.origin[2] - oldz;
255  if (step > 63 && step < 160) {
256  cl.predicted_step = step * 0.125f;
258  cl.predicted_step_frame = frame + 1; // don't double step
259  }
260  }
261 
262  if (cl.predicted_step_frame < frame) {
263  cl.predicted_step_frame = frame;
264  }
265 
266  // copy results out for rendering
267  VectorScale(pm.s.origin, 0.125f, cl.predicted_origin);
268  VectorScale(pm.s.velocity, 0.125f, cl.predicted_velocity);
269  VectorCopy(pm.viewangles, cl.predicted_angles);
270 }
271 
CL_CheckPredictionError
void CL_CheckPredictionError(void)
Definition: predict.c:27
client_state_s::frame
server_frame_t frame
Definition: client.h:212
client_state_s::bsp
bsp_t * bsp
Definition: client.h:300
CM_BoxTrace
void CM_BoxTrace(trace_t *trace, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, mnode_t *headnode, int brushmask)
Definition: cmodel.c:683
pm
static pmove_t * pm
Definition: pmove.c:44
client_static_s::playback
qhandle_t playback
Definition: client.h:453
client_state_s::cmdNumber
unsigned cmdNumber
Definition: client.h:184
client_static_s::demo
struct client_static_s::@3 demo
client_state_s::solidEntities
centity_t * solidEntities[MAX_PACKET_ENTITIES]
Definition: client.h:199
CL_PredictAngles
void CL_PredictAngles(void)
Definition: predict.c:168
client_state_s::model_clip
mmodel_t * model_clip[MAX_MODELS]
Definition: client.h:303
centity_s::mins
vec3_t mins
Definition: client.h:89
CL_PointContents
static int CL_PointContents(vec3_t point)
Definition: predict.c:133
client_state_s::prediction_error
vec3_t prediction_error
Definition: client.h:196
CL_ClipMoveToEntities
static void CL_ClipMoveToEntities(vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, trace_t *tr)
Definition: predict.c:80
client_state_s::predicted_velocity
vec3_t predicted_velocity
Definition: client.h:195
ca_active
@ ca_active
Definition: client.h:340
client_static_s::state
connstate_t state
Definition: client.h:375
CM_HeadnodeForBox
mnode_t * CM_HeadnodeForBox(vec3_t mins, vec3_t maxs)
Definition: cmodel.c:190
cl_predict
cvar_t * cl_predict
Definition: main.c:28
sv_paused
cvar_t * sv_paused
Definition: common.c:96
CL_PredictMovement
void CL_PredictMovement(void)
Definition: predict.c:175
client_state_s::viewangles
vec3_t viewangles
Definition: client.h:230
edict_s::mins
vec3_t mins
Definition: g_local.h:974
client_state_s::predicted_step
float predicted_step
Definition: client.h:189
edict_s
Definition: g_local.h:953
centity_s::current
entity_state_t current
Definition: client.h:86
client_state_s::localmove
vec3_t localmove
Definition: client.h:234
client_state_s::predicted_origin
vec3_t predicted_origin
Definition: client.h:193
CL_Trace
static trace_t q_gameabi CL_Trace(vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end)
Definition: predict.c:118
client_state_s::predicted_step_frame
unsigned predicted_step_frame
Definition: client.h:191
CM_ClipEntity
void CM_ClipEntity(trace_t *dst, const trace_t *src, struct edict_s *ent)
Definition: cmodel.c:804
Pmove
void Pmove(pmove_t *pmove, pmoveParams_t *params)
Definition: pmove.c:1127
client_state_s::cmds
usercmd_t cmds[CMD_BACKUP]
Definition: client.h:183
CM_TransformedBoxTrace
void CM_TransformedBoxTrace(trace_t *trace, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, mnode_t *headnode, int brushmask, vec3_t origin, vec3_t angles)
Definition: cmodel.c:764
centity_s
Definition: client.h:85
client_history_t::cmdNumber
unsigned cmdNumber
Definition: client.h:125
CM_PointContents
int CM_PointContents(vec3_t p, mnode_t *headnode)
Definition: cmodel.c:289
cl
client_state_t cl
Definition: main.c:99
client_state_s::predicted_step_time
unsigned predicted_step_time
Definition: client.h:190
cls
client_static_t cls
Definition: main.c:98
SHOWMISS
#define SHOWMISS(...)
Definition: client.h:533
client_state_s::cmd
usercmd_t cmd
Definition: client.h:182
client_state_s::predicted_origins
short predicted_origins[CMD_BACKUP][3]
Definition: client.h:185
server_frame_t::ps
player_state_t ps
Definition: client.h:137
client.h
edict_s::maxs
vec3_t maxs
Definition: g_local.h:974
server_frame_t::number
int number
Definition: client.h:131
client_static_s::realtime
unsigned realtime
Definition: client.h:389
client_state_s::history
client_history_t history[CMD_BACKUP]
Definition: client.h:186
centity_s::maxs
vec3_t maxs
Definition: client.h:89
client_static_s::netchan
netchan_t * netchan
Definition: client.h:421
CM_TransformedPointContents
int CM_TransformedPointContents(vec3_t p, mnode_t *headnode, vec3_t origin, vec3_t angles)
Definition: cmodel.c:310
client_state_s::numSolidEntities
int numSolidEntities
Definition: client.h:200
client_state_s::pmp
pmoveParams_t pmp
Definition: client.h:280
client_state_s::predicted_angles
vec3_t predicted_angles
Definition: client.h:194